Files
openchamber/packages/web/server/lib/opencode/feature-routes-runtime.js
T
Bohdan Triapitsyn c9ac8676e7 feat: file-backed goal objectives + compaction accounting fixes
Compaction fixes (observed in a real long run):
- the summary message's zeroed tokens froze the goal counter at its
  pre-compaction value; segments now close with the previously displayed
  total as a continuity floor
- audits and continuations after a summary tail now take execution params
  (provider/model/agent/variant) from the newest non-summary assistant
  turn instead of inheriting agent 'compaction' and the summarize model

File-backed objectives:
- the objective text lives in <data-dir>/goals/<sessionId>.md, keyed by
  session id (one goal per session, a new goal overwrites the file);
  metadata carries only an objectiveFile flag so session.updated fanout
  stays light, and never a path — ids are pattern-validated before any
  filesystem access
- limit raised to 5000 chars, no snapshot field: the UI fetches content
  via PUT/GET/DELETE /api/goals/objective/:sessionId (behind the blanket
  /api auth gate), writes the file before stamping metadata, and falls
  back to an inline objective when the write fails
- the loop reads the file fresh on every tick, so objectives are
  live-editable mid-goal; a missing file falls back to the inline text
- scheduled goal tasks write the objective file server-side; VS Code
  degrades to the audit note (route unavailable there by design)
2026-07-12 02:49:56 +03:00

271 lines
7.9 KiB
JavaScript

import { registerFsRoutes } from '../fs/routes.js';
import { registerQuotaRoutes } from '../quota/routes.js';
import { registerSmallModelRoutes } from '../small-model/routes.js';
import { registerSessionGoalRoutes } from '../session-goal/routes.js';
import { registerGitHubRoutes } from '../github/routes.js';
import { registerGitRoutes } from '../git/routes.js';
import { registerMagicPromptRoutes } from '../magic-prompts/routes.js';
import { registerSessionFoldersRoutes } from '../session-folders/routes.js';
import { registerConfigEntityRoutes } from './config-entity-routes.js';
import { registerSettingsUtilityRoutes } from './core-routes.js';
import { registerProjectIconRoutes } from './project-icon-routes.js';
import { registerScheduledTaskRoutes } from '../scheduled-tasks/routes.js';
import { registerSkillRoutes } from './skill-routes.js';
import { registerPluginRoutes } from './plugin-routes.js';
import { getNpmInfo, clearCache as clearNpmCache } from './npm-registry.js';
import { parseNpmSpec, parsePathSpec, isExactSemver } from './plugin-spec.js';
import { registerOpenCodeRoutes } from './routes.js';
import { getProviderSources, removeProviderConfig } from './providers.js';
import { getAgentSources, getAgentConfig, createAgent, updateAgent, deleteAgent } from './agents.js';
import { getCommandSources, createCommand, updateCommand, deleteCommand } from './commands.js';
import { listMcpConfigs, getMcpConfig, createMcpConfig, updateMcpConfig, deleteMcpConfig } from './mcp.js';
import { listSnippets, getSnippet, createSnippet, updateSnippet, deleteSnippet, expandSnippets } from './snippets.js';
import {
listPluginEntries,
getPluginEntry,
createPluginEntry,
updatePluginEntry,
deletePluginEntry,
listPluginDirFiles,
readPluginDirFile,
writePluginDirFile,
deletePluginDirFile,
encodePluginId,
decodePluginId,
} from './plugins.js';
import { SKILL_DIR, SKILL_SCOPE, readSkillSupportingFile, writeSkillSupportingFile, deleteSkillSupportingFile } from './shared.js';
import { getSkillSources, discoverSkills, mergeDiscoveredSkills, createSkill, updateSkill, deleteSkill } from './skills.js';
import { getCuratedSkillsSources } from '../skills-catalog/curated-sources.js';
import { getCacheKey, getCachedScan, setCachedScan } from '../skills-catalog/cache.js';
import { isClawdHubSource, parseSkillRepoSource } from '../skills-catalog/source.js';
import { scanSkillsRepository } from '../skills-catalog/scan.js';
import { installSkillsFromRepository } from '../skills-catalog/install.js';
import { scanClawdHubPage } from '../skills-catalog/clawdhub/scan.js';
import { installSkillsFromClawdHub } from '../skills-catalog/clawdhub/install.js';
export const createFeatureRoutesRuntime = (dependencies) => {
const {
clientReloadDelayMs,
} = dependencies;
let quotaProviders = null;
const getQuotaProviders = async () => {
if (!quotaProviders) {
quotaProviders = await import('../quota/index.js');
}
return quotaProviders;
};
let smallModelService = null;
const getSmallModelService = async () => {
if (!smallModelService) {
smallModelService = await import('../small-model/index.js');
}
return smallModelService;
};
const registerRoutes = async (app, routeDependencies) => {
const {
crypto,
fs,
os,
path,
fsPromises,
spawn,
resolveGitBinaryForSpawn,
createFsSearchRuntime,
openchamberDataDir,
openchamberUserConfigRoot,
normalizeDirectoryPath,
resolveProjectDirectory,
resolveOptionalProjectDirectory,
validateDirectoryPath,
readCustomThemesFromDisk,
refreshOpenCodeAfterConfigChange,
getOpenCodeResolutionSnapshot,
formatSettingsResponse,
readSettingsFromDisk,
readSettingsFromDiskMigrated,
persistSettings,
sanitizeProjects,
sanitizeSkillCatalogs,
isUnsafeSkillRelativePath,
buildOpenCodeUrl,
getOpenCodeAuthHeaders,
getOpenCodePort,
buildAugmentedPath,
projectConfigRuntime,
scheduledTasksRuntime,
getOpenChamberEventClients,
writeSseEvent,
} = routeDependencies;
registerSettingsUtilityRoutes(app, {
readCustomThemesFromDisk,
refreshOpenCodeAfterConfigChange,
clientReloadDelayMs,
});
registerOpenCodeRoutes(app, {
crypto,
clientReloadDelayMs,
getOpenCodeResolutionSnapshot,
formatSettingsResponse,
readSettingsFromDisk,
readSettingsFromDiskMigrated,
persistSettings,
sanitizeProjects,
validateDirectoryPath,
resolveProjectDirectory,
getProviderSources,
removeProviderConfig,
refreshOpenCodeAfterConfigChange,
buildOpenCodeUrl,
getOpenCodeAuthHeaders,
});
registerProjectIconRoutes(app, {
fsPromises,
path,
crypto,
openchamberDataDir,
sanitizeProjects,
readSettingsFromDiskMigrated,
persistSettings,
createFsSearchRuntime,
spawn,
resolveGitBinaryForSpawn,
});
registerScheduledTaskRoutes(app, {
readSettingsFromDiskMigrated,
sanitizeProjects,
projectConfigRuntime,
scheduledTasksRuntime,
getOpenChamberEventClients,
writeSseEvent,
});
registerConfigEntityRoutes(app, {
resolveProjectDirectory,
resolveOptionalProjectDirectory,
refreshOpenCodeAfterConfigChange,
clientReloadDelayMs,
getAgentSources,
getAgentConfig,
createAgent,
updateAgent,
deleteAgent,
getCommandSources,
createCommand,
updateCommand,
deleteCommand,
listMcpConfigs,
getMcpConfig,
createMcpConfig,
updateMcpConfig,
deleteMcpConfig,
listSnippets,
getSnippet,
createSnippet,
updateSnippet,
deleteSnippet,
expandSnippets,
});
registerPluginRoutes(app, {
resolveOptionalProjectDirectory,
refreshOpenCodeAfterConfigChange,
clientReloadDelayMs,
listPluginEntries,
getPluginEntry,
createPluginEntry,
updatePluginEntry,
deletePluginEntry,
listPluginDirFiles,
readPluginDirFile,
writePluginDirFile,
deletePluginDirFile,
encodePluginId,
decodePluginId,
getNpmInfo,
parseNpmSpec,
parsePathSpec,
isExactSemver,
});
const { getProfiles, getProfile } = await import('../git/index.js');
registerSkillRoutes(app, {
fs,
path,
os,
resolveProjectDirectory,
resolveOptionalProjectDirectory,
readSettingsFromDisk,
sanitizeSkillCatalogs,
isUnsafeSkillRelativePath,
refreshOpenCodeAfterConfigChange,
clientReloadDelayMs,
buildOpenCodeUrl,
getOpenCodeAuthHeaders,
getOpenCodePort,
getSkillSources,
discoverSkills,
mergeDiscoveredSkills,
createSkill,
updateSkill,
deleteSkill,
readSkillSupportingFile,
writeSkillSupportingFile,
deleteSkillSupportingFile,
SKILL_SCOPE,
SKILL_DIR,
getCuratedSkillsSources,
getCacheKey,
getCachedScan,
setCachedScan,
parseSkillRepoSource,
scanSkillsRepository,
installSkillsFromRepository,
scanClawdHubPage,
installSkillsFromClawdHub,
isClawdHubSource,
getProfiles,
getProfile,
});
registerQuotaRoutes(app, { getQuotaProviders });
registerSmallModelRoutes(app, { getSmallModelService });
registerSessionGoalRoutes(app);
registerGitHubRoutes(app);
registerGitRoutes(app);
registerMagicPromptRoutes(app, {
fsPromises,
path,
openchamberDataDir,
});
registerSessionFoldersRoutes(app, {
fsPromises,
path,
openchamberDataDir,
});
registerFsRoutes(app, {
os,
path,
fsPromises,
spawn,
crypto,
normalizeDirectoryPath,
resolveProjectDirectory,
buildAugmentedPath,
resolveGitBinaryForSpawn,
openchamberUserConfigRoot,
});
};
return {
registerRoutes,
};
};