@moretea-labs/forge 1.8.1 → 1.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (328) hide show
  1. package/AGENTS.md +5 -2
  2. package/CHANGELOG.md +20 -0
  3. package/README.en.md +24 -3
  4. package/README.md +10 -6
  5. package/README.zh-CN.md +5 -3
  6. package/THIRD_PARTY_NOTICES.md +1 -2
  7. package/adapters/chatgpt/browser-delivery-runtime.ts +5 -3
  8. package/adapters/chatgpt/provider-delivery.ts +1 -1
  9. package/adapters/chatgpt/work-conversation-binding-store.ts +20 -1
  10. package/adapters/computer/chatgpt-extension-target.ts +295 -50
  11. package/adapters/computer/chrome-extension/background.js +227 -71
  12. package/adapters/computer/chrome-extension/content.js +181 -157
  13. package/adapters/computer/chrome-extension/manifest.json +3 -1
  14. package/adapters/computer/desktop-operator-provider.ts +18 -6
  15. package/adapters/computer/interaction-target-authority.ts +39 -9
  16. package/adapters/mcp/access-mode.ts +18 -39
  17. package/adapters/mcp/auth.ts +2 -6
  18. package/adapters/mcp/instructions.ts +2 -2
  19. package/adapters/mcp/multi-repository.ts +7 -28
  20. package/adapters/mcp/runtime-gateway/context-adapter.ts +79 -40
  21. package/adapters/mcp/runtime-gateway/context-pack-sidecar.ts +7 -15
  22. package/adapters/mcp/runtime-gateway/execution-tools.ts +7 -13
  23. package/adapters/mcp/runtime-gateway/plugin-adapter.ts +16 -3
  24. package/adapters/mcp/runtime-gateway/process-tools.ts +3 -21
  25. package/adapters/mcp/runtime-gateway/router.ts +3 -5
  26. package/adapters/mcp/runtime-gateway/routing-policy.ts +17 -10
  27. package/adapters/mcp/runtime-gateway/runtime-observation-adapter.ts +1 -1
  28. package/adapters/mcp/runtime-gateway/runtime-tool-definitions.ts +14 -9
  29. package/adapters/mcp/runtime-gateway/runtime-tools.ts +1 -5
  30. package/adapters/mcp/runtime-gateway/scheduler-adapter.ts +36 -1
  31. package/adapters/mcp/runtime-gateway/status-inbox-adapter.ts +58 -4
  32. package/adapters/mcp/runtime-gateway/typescript-navigation-sidecar.ts +7 -3
  33. package/adapters/mcp/runtime-gateway/work-adapter.ts +16 -16
  34. package/adapters/mcp/runtime-gateway/work-input-wire-migration.ts +0 -17
  35. package/adapters/mcp/runtime-gateway/work-semantic-operations.ts +69 -12
  36. package/adapters/mcp/runtime-gateway/workflow-supervisor-adapter.ts +26 -2
  37. package/adapters/mcp/server.ts +24 -3
  38. package/adapters/mcp/setup.ts +4 -10
  39. package/adapters/mcp/tool-mapping/access-tools.ts +0 -6
  40. package/adapters/mcp/tool-mapping/legacy-tool-service.ts +672 -2935
  41. package/adapters/mcp/tool-mapping/post-finalize-work-attribution.ts +1 -1
  42. package/adapters/mcp/tool-mapping/repository-tools.ts +52 -86
  43. package/adapters/mcp/toolset-names.ts +11 -42
  44. package/adapters/mcp/toolset.ts +16 -90
  45. package/{src/cli → adapters}/mcp/transports/AGENTS.md +5 -5
  46. package/{src/cli → adapters}/mcp/transports/CLAUDE.md +5 -5
  47. package/adapters/mcp/transports/http-observation.ts +18 -6
  48. package/adapters/mcp/transports/http-post-lifecycle.ts +19 -0
  49. package/adapters/mcp/transports/http.ts +54 -14
  50. package/adapters/mcp/types.ts +0 -6
  51. package/assets/hooks/lib/session-state.sh +0 -38
  52. package/assets/hooks/post-bash.sh +1 -1
  53. package/assets/hooks/post-tool-observer.sh +0 -5
  54. package/assets/hooks/prompt-guard.sh +0 -55
  55. package/assets/partials/04-project-structure.partial.md +1 -1
  56. package/assets/partials/07-footer.partial.md +1 -1
  57. package/assets/partials-agents/02-operating-mode.partial.md +1 -1
  58. package/assets/partials-agents/08-deep-docs.partial.md +1 -1
  59. package/assets/reference-configs/agentic-development-flow.md +1 -1
  60. package/assets/reference-configs/external-tooling.md +0 -76
  61. package/assets/reference-configs/release-deploy.md +1 -1
  62. package/assets/templates/helpers/architecture-queue.sh +1 -1
  63. package/assets/templates/helpers/check-agent-tooling.sh +1 -327
  64. package/assets/templates/helpers/check-task-workflow.sh +1 -1
  65. package/assets/templates/helpers/ensure-task-workflow.sh +0 -14
  66. package/assets/templates/helpers/migrate-project-template.sh +2 -2
  67. package/assets/workflow-contract.v1.json +0 -2
  68. package/docs/README.md +5 -2
  69. package/docs/architecture/CURRENT.md +114 -30
  70. package/docs/architecture/decisions/20260904-ios-device-migration-baseline.md +42 -0
  71. package/docs/architecture/decisions/20260918-stable-candidate-release-lifecycle.md +15 -2
  72. package/docs/architecture/decisions/20260924-thin-semantic-working-context.md +4 -2
  73. package/docs/architecture/decisions/20261001-supervisor-turn-authority.md +109 -4
  74. package/docs/architecture/decisions/20261009-exact-code-context-discovery.md +19 -0
  75. package/docs/architecture/decisions/20261009-generated-xcode-cache-retention.md +37 -0
  76. package/docs/architecture/decisions/20261011-autonomous-continuation-convergence.md +597 -0
  77. package/docs/architecture/decisions/20261017-edit-session-finalization-reconciliation.md +17 -0
  78. package/docs/architecture/decisions/20261019-retire-host-skills.md +16 -0
  79. package/docs/architecture/diagrams/agentic-dev-plugin-architecture.html +1 -1
  80. package/docs/architecture/domains/public-surface.md +3 -5
  81. package/docs/architecture/domains/verification.md +5 -5
  82. package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +2 -2
  83. package/docs/architecture/requests/2026-09-04-computer-plugin-workflow-taxonomy.md +4 -4
  84. package/docs/architecture/reviews/20261015-code-search-runtime-acceptance.md +75 -0
  85. package/docs/forge-plugin-management.md +14 -2
  86. package/docs/operations/controller-browser-plugin.md +23 -0
  87. package/docs/operations/features.md +6 -7
  88. package/docs/operations/features.zh-CN.md +1 -1
  89. package/docs/operations/github-repository.md +4 -4
  90. package/docs/operations/github-semantic-release-projection.md +20 -0
  91. package/docs/operations/homebrew.md +2 -2
  92. package/docs/operations/mcp-tool-exposure.md +13 -54
  93. package/docs/operations/runtime-performance-diagnostics.md +8 -0
  94. package/docs/operations/standalone-disaster-recovery.md +1 -1
  95. package/docs/tutorials/01-install-and-start.zh-CN.md +1 -1
  96. package/docs/tutorials/03-first-repository-task.md +2 -0
  97. package/docs/wiki/Computer-and-Plugins.md +78 -0
  98. package/docs/wiki/Computer-and-Plugins.zh-CN.md +88 -0
  99. package/docs/wiki/Home.md +16 -2
  100. package/docs/wiki/Implementation.md +24 -12
  101. package/docs/wiki/Installation.md +28 -32
  102. package/docs/wiki/Integrations.md +4 -0
  103. package/docs/wiki/Quick-Start.md +35 -22
  104. package/docs/wiki/Releases-and-Upgrades.md +15 -25
  105. package/docs/wiki/_Sidebar.md +5 -1
  106. package/package.json +1 -12
  107. package/packages/kernel/controller/infrastructure/controller-session-store.ts +63 -38
  108. package/packages/kernel/identity/infrastructure/activity-projection-store.ts +10 -0
  109. package/packages/kernel/scheduler/application/eligibility.ts +4 -1
  110. package/packages/kernel/scheduler/infrastructure/schedule-store.ts +13 -10
  111. package/packages/kernel/work/application/work-service.ts +1 -0
  112. package/packages/kernel/work/domain/repository-completion-receipt.ts +1 -1
  113. package/packages/kernel/work/domain/state-machine.ts +9 -2
  114. package/packages/kernel/work/infrastructure/work-contract-store.ts +28 -1
  115. package/packages/plugin-runtime/browser/provider-registry.ts +12 -36
  116. package/packages/plugin-runtime/computer/conversation-target.ts +17 -7
  117. package/scripts/assemble-template.ts +11 -72
  118. package/scripts/check-mcp-compatibility.ts +55 -74
  119. package/scripts/check-package-identity.mjs +0 -5
  120. package/scripts/check-runtime-architecture.mjs +305 -28
  121. package/scripts/init-project.sh +0 -46
  122. package/scripts/install-ios-hid-toolchain.sh +60 -0
  123. package/scripts/install-standalone-recovery.ts +1 -1
  124. package/scripts/lib/project-init-lib.sh +3 -3
  125. package/scripts/migrate-windows-wsl-controller-home.ts +2 -0
  126. package/scripts/open-source-audit-allowlist.txt +0 -1
  127. package/scripts/run-governed-gate.ts +2 -0
  128. package/scripts/smoke-ios-physical-device.ts +38 -10
  129. package/scripts/smoke-mcp-http-runtime.ts +7 -8
  130. package/scripts/smoke-mcp-tool-surface.ts +27 -41
  131. package/scripts/smoke-workflow-supervisor-chrome-adapter.ts +6 -3
  132. package/scripts/sync-generated-authority.mjs +0 -1
  133. package/src/cli/agent-jobs/executor-health.ts +1 -1
  134. package/src/cli/agent-jobs/integration.ts +2 -2
  135. package/src/cli/chatgpt-browser/file-policy.ts +2 -2
  136. package/src/cli/commands/doctor.ts +1 -143
  137. package/src/cli/commands/global-runtime.ts +3 -196
  138. package/src/cli/commands/init-hook.ts +6 -23
  139. package/src/cli/commands/init.ts +3 -252
  140. package/src/cli/commands/mcp.ts +0 -5
  141. package/src/cli/commands/prompt-guard-decision.ts +0 -2
  142. package/src/cli/commands/recovery.ts +2 -14
  143. package/src/cli/commands/repository.ts +17 -1
  144. package/src/cli/commands/setup-execution.ts +41 -0
  145. package/src/cli/controller/completion-orchestrator.ts +1 -1
  146. package/src/cli/controller/composite-operations.ts +1 -1
  147. package/src/cli/controller/context/instruction-context.ts +1 -1
  148. package/src/cli/controller/context/known-paths.ts +2 -2
  149. package/src/cli/controller/context/query-planning.ts +11 -4
  150. package/src/cli/controller/context/rule-resolution.ts +2 -2
  151. package/src/cli/controller/context/source-materializer.ts +2 -2
  152. package/src/cli/controller/context/structural-provider.ts +84 -0
  153. package/src/cli/controller/context/structural.ts +6 -6
  154. package/src/cli/controller/context/types.ts +8 -9
  155. package/src/cli/controller/context-pack.ts +97 -76
  156. package/src/cli/controller/operational-plan.ts +1 -1
  157. package/src/cli/controller/systemd-user.ts +4 -10
  158. package/src/cli/editing/edit-session.ts +17 -5
  159. package/src/cli/github/github.ts +4 -4
  160. package/src/cli/github/semantic-projection.ts +174 -0
  161. package/src/cli/hook/prompt-intents.ts +0 -9
  162. package/src/cli/index.ts +1 -43
  163. package/src/cli/local-bridge/connector-freshness.ts +1 -12
  164. package/src/cli/local-bridge/console-automations.ts +1 -1
  165. package/src/cli/local-bridge/console-view-models.ts +1 -1
  166. package/src/cli/local-bridge/facade-api.ts +0 -2
  167. package/src/cli/repositories/command-classifier.ts +0 -9
  168. package/src/cli/repositories/command-scope.ts +2 -2
  169. package/src/cli/repositories/locks.ts +20 -0
  170. package/src/cli/repositories/registry.ts +2 -1
  171. package/src/cli/repositories/safe-patch.ts +2 -12
  172. package/src/cli/repositories/structured-git.ts +39 -3
  173. package/src/cli/repository/inspector.ts +185 -343
  174. package/src/effects/process-runner.ts +17 -1
  175. package/src/runtime/context/generic-lsp-provider.ts +1 -1
  176. package/src/runtime/context/semantic-navigation-contract.ts +7 -0
  177. package/src/runtime/context/semantic-navigation.ts +1 -1
  178. package/src/runtime/control-plane/cleanup-artifact-retention.ts +4 -4
  179. package/src/runtime/control-plane/execution/work-delivery-service.ts +150 -31
  180. package/src/runtime/control-plane/execution/work-handle-authority.ts +12 -4
  181. package/src/runtime/control-plane/execution/work-handle-store.ts +53 -1
  182. package/src/runtime/control-plane/execution/work-operation-service.ts +20 -10
  183. package/src/runtime/control-plane/execution/work-preparation-service.ts +108 -4
  184. package/src/runtime/control-plane/execution/work-process-evidence.ts +2 -2
  185. package/src/runtime/control-plane/execution/work-terminal-cleanup.ts +28 -13
  186. package/src/runtime/control-plane/execution/work-validation-reconciler.ts +5 -1
  187. package/src/runtime/control-plane/execution/work-verification-snapshot.ts +1 -1
  188. package/src/runtime/control-plane/facade/capability-registry.ts +2 -0
  189. package/src/runtime/control-plane/facade/work-continuation.ts +1 -1
  190. package/src/runtime/control-plane/generated-cache-retention.ts +114 -63
  191. package/src/runtime/control-plane/global-scheduler/maintenance.ts +20 -8
  192. package/src/runtime/control-plane/global-scheduler/reconciliation.ts +1 -11
  193. package/src/runtime/control-plane/governance/external-effects.ts +1 -1
  194. package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +1 -0
  195. package/src/runtime/control-plane/runtime-cleanup.ts +12 -93
  196. package/src/runtime/evidence/sensitive-output.ts +22 -2
  197. package/src/runtime/execution/jobs/child-reference.ts +11 -0
  198. package/src/runtime/execution/jobs/receipt-recovery.ts +1 -11
  199. package/src/runtime/execution/process-runtime/command-facade.ts +3 -3
  200. package/src/runtime/execution/process-runtime/runtime.ts +20 -16
  201. package/src/runtime/execution/thin-harness/execution-router.ts +16 -16
  202. package/src/runtime/execution/thin-harness/fast-executor.ts +2 -2
  203. package/src/runtime/execution/thin-harness/search-worker.ts +2 -2
  204. package/src/runtime/execution/workers/executor.ts +1 -2
  205. package/src/runtime/maintenance/cleanup.ts +41 -5
  206. package/src/runtime/plugins/action-application.ts +12 -1
  207. package/src/runtime/plugins/app-store-connect-adapter.ts +252 -4
  208. package/src/runtime/plugins/browser-adapter.ts +381 -313
  209. package/src/runtime/plugins/browser-macos-bridge.ts +114 -112
  210. package/src/runtime/plugins/browser-manifest-surface.ts +2 -1
  211. package/src/runtime/plugins/browser-registration.ts +2 -0
  212. package/src/runtime/plugins/browser-runtime.ts +26 -35
  213. package/src/runtime/plugins/computer-chatgpt-browser-adapter-installer.ts +11 -2
  214. package/src/runtime/plugins/computer-registration.ts +76 -9
  215. package/src/runtime/plugins/github-adapter.ts +30 -3
  216. package/src/runtime/plugins/gmail-adapter.ts +166 -1
  217. package/src/runtime/plugins/google-shared.ts +10 -5
  218. package/src/runtime/plugins/ios/remote-xpc-hid.ts +70 -30
  219. package/src/runtime/plugins/ios-adapter.ts +45 -40
  220. package/src/runtime/plugins/ios-agent-device.ts +54 -4
  221. package/src/runtime/plugins/ios-device-ownership.ts +103 -0
  222. package/src/runtime/plugins/ios-physical-device.ts +497 -79
  223. package/src/runtime/plugins/local-system-adapter.ts +1 -99
  224. package/src/runtime/plugins/store.ts +80 -7
  225. package/src/runtime/plugins/types.ts +4 -0
  226. package/src/runtime/projections/git-status-sampler.ts +2 -19
  227. package/src/runtime/recovery/actions.ts +1 -1
  228. package/src/runtime/recovery/lifecycle-inventory.ts +1 -11
  229. package/src/runtime/recovery/probe.ts +2 -2
  230. package/src/runtime/release/release-coordinator.ts +20 -4
  231. package/src/runtime/root/controller-progression-composition.ts +67 -5
  232. package/src/runtime/root/package-connector-service.ts +123 -11
  233. package/src/runtime/root/package-runtime-release.ts +6 -18
  234. package/src/runtime/root/package-runtime-service.ts +7 -13
  235. package/src/runtime/root/release-execution-canary.ts +18 -5
  236. package/src/runtime/root/release-manifest.ts +0 -34
  237. package/src/runtime/root/release-materialize.ts +0 -78
  238. package/src/runtime/root/runtime.ts +1 -2
  239. package/src/runtime/root/scheduled-controller-composition.ts +2 -1
  240. package/src/runtime/root/service.ts +90 -11
  241. package/src/runtime/root/types.ts +0 -6
  242. package/src/runtime/root/workflow-supervisor-composition.ts +207 -19
  243. package/src/runtime/root/workflow-supervisor-runtime.ts +365 -10
  244. package/src/runtime/safe-tooling/google-credential-store.ts +1 -11
  245. package/src/runtime/safe-tooling/ios-development.ts +22 -8
  246. package/src/runtime/safe-tooling/job-summary.ts +1 -1
  247. package/src/runtime/safe-tooling/workspace-auth.ts +4 -1
  248. package/src/runtime/shared/atomic-text-file.ts +21 -0
  249. package/src/runtime/shared/json-files.ts +8 -3
  250. package/src/runtime/standalone-recovery/core.ts +189 -174
  251. package/src/runtime/standalone-recovery/entry.ts +62 -30
  252. package/src/runtime/standalone-recovery/operation-lock.ts +11 -1
  253. package/src/runtime/workflow/schedules/chatgpt-automation-migration.ts +1 -0
  254. package/src/runtime/workflow/schedules/engine.ts +36 -14
  255. package/src/runtime/workflow/schedules/pending-activation.ts +11 -4
  256. package/src/runtime/workflow/schedules/work-continuation.ts +51 -6
  257. package/supervisor/client.ts +31 -14
  258. package/supervisor/control-plane.ts +210 -115
  259. package/supervisor/forge-validators.ts +88 -21
  260. package/supervisor/native-browser-adapter.ts +393 -28
  261. package/supervisor/native-messaging/host.ts +21 -2
  262. package/supervisor/protocol.ts +74 -26
  263. package/supervisor/server.ts +16 -8
  264. package/supervisor/store.ts +476 -57
  265. package/supervisor/types.ts +19 -13
  266. package/SKILL.md +0 -427
  267. package/adapters/computer/chatgpt-target-router.ts +0 -103
  268. package/adapters/mcp/runtime-gateway/automation-receipt-adapter.ts +0 -87
  269. package/adapters/mcp/runtime-gateway/work-validation-reconciler.ts +0 -1
  270. package/adapters/mcp/toolset-selection.ts +0 -41
  271. package/agents/openai.yaml +0 -4
  272. package/assets/skill-hooks.json +0 -41
  273. package/assets/skill-version.json +0 -189
  274. package/assets/skills/claude-review/SKILL.md +0 -231
  275. package/assets/skills/codex-review/SKILL.md +0 -103
  276. package/assets/templates/helpers/check-skill-version.ts +0 -193
  277. package/scripts/check-skill-version.ts +0 -5
  278. package/scripts/ensure-codegraph.sh +0 -16
  279. package/scripts/run-skill-hook.ts +0 -244
  280. package/scripts/sync-codex-installed-copies.sh +0 -182
  281. package/src/cli/commands/tools.ts +0 -167
  282. package/src/cli/mcp/access-mode.ts +0 -2
  283. package/src/cli/mcp/access-tools.ts +0 -2
  284. package/src/cli/mcp/audit.ts +0 -2
  285. package/src/cli/mcp/auth.ts +0 -2
  286. package/src/cli/mcp/instructions.ts +0 -2
  287. package/src/cli/mcp/legacy-context.ts +0 -2
  288. package/src/cli/mcp/legacy-tool-service.ts +0 -2
  289. package/src/cli/mcp/multi-repository.ts +0 -2
  290. package/src/cli/mcp/oauth.ts +0 -2
  291. package/src/cli/mcp/openai-secure-tunnel.ts +0 -2
  292. package/src/cli/mcp/paths.ts +0 -2
  293. package/src/cli/mcp/policy.ts +0 -2
  294. package/src/cli/mcp/post-finalize-work-attribution.ts +0 -2
  295. package/src/cli/mcp/proxy-env.ts +0 -2
  296. package/src/cli/mcp/readiness-projection.ts +0 -2
  297. package/src/cli/mcp/redaction.ts +0 -2
  298. package/src/cli/mcp/repo.ts +0 -2
  299. package/src/cli/mcp/repository-tools.ts +0 -2
  300. package/src/cli/mcp/server.ts +0 -2
  301. package/src/cli/mcp/setup.ts +0 -2
  302. package/src/cli/mcp/tool-capability-cache.ts +0 -2
  303. package/src/cli/mcp/tool-contract.ts +0 -2
  304. package/src/cli/mcp/tools.ts +0 -2
  305. package/src/cli/mcp/toolset-names.ts +0 -2
  306. package/src/cli/mcp/toolset-selection.ts +0 -2
  307. package/src/cli/mcp/toolset.ts +0 -2
  308. package/src/cli/mcp/transports/http.ts +0 -2
  309. package/src/cli/mcp/transports/session-registry.ts +0 -2
  310. package/src/cli/mcp/transports/stdio.ts +0 -2
  311. package/src/cli/mcp/types.ts +0 -2
  312. package/src/cli/mcp/umbrella-tools.ts +0 -2
  313. package/src/cli/tools/codegraph.ts +0 -695
  314. package/src/core/adoption/helper-wrapper-plan.ts +0 -159
  315. package/src/runtime/context/codegraph-cache-boundary.ts +0 -255
  316. package/src/runtime/context/codegraph-read-provider.ts +0 -611
  317. package/src/runtime/context/codegraph-sidecar.cjs +0 -248
  318. package/src/runtime/control-plane/codegraph-cache-retention.ts +0 -164
  319. package/src/runtime/gateway/mcp/execution-tools.ts +0 -2
  320. package/src/runtime/gateway/mcp/legacy-ios-tool-adapter.ts +0 -2
  321. package/src/runtime/gateway/mcp/persisted-check-process.ts +0 -2
  322. package/src/runtime/gateway/mcp/process-tools.ts +0 -2
  323. package/src/runtime/gateway/mcp/router.ts +0 -2
  324. package/src/runtime/gateway/mcp/runtime-tool-definitions.ts +0 -2
  325. package/src/runtime/gateway/mcp/runtime-tools.ts +0 -2
  326. package/src/runtime/gateway/mcp/work-validation-reconciler.ts +0 -2
  327. package/src/runtime/plugins/browser-provider-registry.ts +0 -2
  328. package/src/runtime/plugins/computer-chatgpt-macos-target.ts +0 -891
@@ -1,611 +0,0 @@
1
- import { spawn, spawnSync, type ChildProcessWithoutNullStreams } from 'child_process';
2
- import { accessSync, constants, existsSync } from 'fs';
3
- import { createRequire } from 'module';
4
- import { dirname, join, resolve } from 'path';
5
- import { createInterface, type Interface as ReadlineInterface } from 'readline';
6
- import { fileURLToPath } from 'url';
7
- import { resolveControllerHome } from '../../cli/repositories/controller-home';
8
- import { createCodegraphCacheLocator, codegraphRepositoryCacheRoot, type CodegraphCacheLocator } from './codegraph-cache-boundary';
9
-
10
- const require = createRequire(import.meta.url);
11
- const SCHEMA_VERSION = 1;
12
- const MAX_REQUEST_BYTES = 64 * 1024;
13
- const MAX_RESPONSE_BYTES = 1024 * 1024;
14
- const MAX_STDERR_CHARS = 8_000;
15
- const DEFAULT_TIMEOUT_MS = 15_000;
16
- const PERSISTENT_SIDECAR_IDLE_MS = 30_000;
17
- const ALLOWED_OPERATIONS = new Set<CodeGraphReadOperation>(['status', 'search', 'context', 'impact', 'file_dependencies']);
18
-
19
- export type CodeGraphReadOperation = 'status' | 'search' | 'context' | 'impact' | 'file_dependencies';
20
- export type CodeGraphProviderStatus = 'ready' | 'stale' | 'unavailable' | 'degraded';
21
-
22
- export interface CodeGraphNodeSummary {
23
- id: string;
24
- kind: string;
25
- name: string;
26
- qualifiedName: string;
27
- filePath: string;
28
- language: string;
29
- startLine: number;
30
- endLine: number;
31
- signature?: string;
32
- }
33
-
34
- export interface CodeGraphEdgeSummary {
35
- source: string;
36
- target: string;
37
- kind: string;
38
- line?: number;
39
- provenance?: string;
40
- }
41
-
42
- export interface CodeGraphIndexMetadata {
43
- initialized: boolean;
44
- lastIndexedAt: number | null;
45
- buildVersion: string | null;
46
- extractionVersion: number | null;
47
- staleEngine: boolean;
48
- changedFiles: {
49
- added: string[];
50
- modified: string[];
51
- removed: string[];
52
- };
53
- /** CodeGraph SDK drift entries excluded by the repository's Git ignore authority. */
54
- ignoredChangedFileCount?: number;
55
- stats?: {
56
- nodeCount: number;
57
- edgeCount: number;
58
- fileCount: number;
59
- dbSizeBytes: number;
60
- lastUpdated: number;
61
- };
62
- backend?: string;
63
- journalMode?: string;
64
- }
65
-
66
- export interface CodeGraphReadRequest {
67
- operation: CodeGraphReadOperation;
68
- query?: string;
69
- nodeId?: string;
70
- filePath?: string;
71
- limit?: number;
72
- maxNodes?: number;
73
- maxDepth?: number;
74
- /** Refresh only the derived CodeGraph index before a required structural read. */
75
- refresh?: 'if_stale';
76
- }
77
-
78
- export interface CodeGraphReadProviderResponse {
79
- schemaVersion: 1;
80
- provider: 'codegraph';
81
- operation: CodeGraphReadOperation;
82
- ok: boolean;
83
- status: CodeGraphProviderStatus;
84
- metadata?: CodeGraphIndexMetadata;
85
- result?: Record<string, unknown>;
86
- error?: {
87
- code: string;
88
- message: string;
89
- };
90
- timingsMs: {
91
- total: number;
92
- process?: number;
93
- open?: number;
94
- query?: number;
95
- };
96
- }
97
-
98
- interface SidecarSuccess {
99
- schemaVersion: 1;
100
- ok: true;
101
- operation: CodeGraphReadOperation;
102
- metadata: CodeGraphIndexMetadata;
103
- result: Record<string, unknown>;
104
- timingsMs?: { open?: number; query?: number };
105
- }
106
-
107
- interface SidecarFailure {
108
- schemaVersion: 1;
109
- ok: false;
110
- operation?: CodeGraphReadOperation;
111
- error: { code: string; message: string };
112
- timingsMs?: { open?: number; query?: number };
113
- }
114
-
115
- type SidecarResponse = SidecarSuccess | SidecarFailure;
116
-
117
- function isExecutable(path: string): boolean {
118
- try {
119
- if (!existsSync(path)) return false;
120
- accessSync(path, process.platform === 'win32' ? constants.F_OK : constants.X_OK);
121
- return true;
122
- } catch {
123
- return false;
124
- }
125
- }
126
-
127
- function boundedInteger(value: number | undefined, fallback: number, min: number, max: number): number {
128
- if (typeof value !== 'number' || !Number.isFinite(value)) return fallback;
129
- return Math.min(Math.max(Math.trunc(value), min), max);
130
- }
131
-
132
- export function resolveCodeGraphBundledRuntime(options: { runtimeRoot?: string } = {}): {
133
- nodeExecutable: string;
134
- sidecarPath: string;
135
- libraryPath: string;
136
- platformPackage: string;
137
- source: 'release' | 'dependency';
138
- } {
139
- const target = `${process.platform}-${process.arch}`;
140
- const platformPackage = `@colbymchenry/codegraph-${target}`;
141
- const configuredReleaseRoot = process.env.FORGE_RELEASE_PATH?.trim();
142
- const runtimeRoot = options.runtimeRoot ?? (configuredReleaseRoot ? resolve(configuredReleaseRoot) : dirname(process.execPath));
143
- const releaseNode = join(runtimeRoot, 'codegraph-node');
144
- const releaseSidecar = join(runtimeRoot, 'codegraph-sidecar.cjs');
145
- const releaseLibrary = join(runtimeRoot, 'codegraph-lib', 'dist', 'index.js');
146
- if (isExecutable(releaseNode) && existsSync(releaseSidecar) && existsSync(releaseLibrary)) {
147
- return {
148
- nodeExecutable: releaseNode,
149
- sidecarPath: releaseSidecar,
150
- libraryPath: releaseLibrary,
151
- platformPackage,
152
- source: 'release',
153
- };
154
- }
155
- let packageJson: string;
156
- try {
157
- packageJson = require.resolve(`${platformPackage}/package.json`);
158
- } catch {
159
- throw new Error(`CODEGRAPH_PLATFORM_BUNDLE_MISSING: ${platformPackage} is not installed`);
160
- }
161
- const nodeExecutable = join(dirname(packageJson), process.platform === 'win32' ? 'node.exe' : 'node');
162
- if (!isExecutable(nodeExecutable)) {
163
- throw new Error(`CODEGRAPH_BUNDLED_NODE_UNAVAILABLE: bundled Node runtime is missing for ${platformPackage}`);
164
- }
165
- const sidecarPath = fileURLToPath(new URL('./codegraph-sidecar.cjs', import.meta.url));
166
- if (!existsSync(sidecarPath)) {
167
- throw new Error('CODEGRAPH_SIDECAR_MISSING: packaged read-only sidecar could not be resolved');
168
- }
169
- const libraryPath = join(dirname(packageJson), 'lib', 'dist', 'index.js');
170
- if (!existsSync(libraryPath)) {
171
- throw new Error(`CODEGRAPH_LIBRARY_UNAVAILABLE: compiled library is missing for ${platformPackage}`);
172
- }
173
- return { nodeExecutable, sidecarPath, libraryPath, platformPackage, source: 'dependency' };
174
- }
175
-
176
- function minimalEnvironment(runtime: ReturnType<typeof resolveCodeGraphBundledRuntime>, codegraphDir?: string): NodeJS.ProcessEnv {
177
- return Object.fromEntries(Object.entries({
178
- PATH: dirname(runtime.nodeExecutable),
179
- HOME: process.env.HOME,
180
- TMPDIR: process.env.TMPDIR,
181
- TEMP: process.env.TEMP,
182
- TMP: process.env.TMP,
183
- LANG: process.env.LANG,
184
- LC_ALL: process.env.LC_ALL,
185
- CODEGRAPH_TELEMETRY: '0',
186
- DO_NOT_TRACK: '1',
187
- CODEGRAPH_NO_DAEMON: '1',
188
- CODEGRAPH_DIR: codegraphDir,
189
- FORGE_CODEGRAPH_LIBRARY_PATH: runtime.libraryPath,
190
- }).filter((entry): entry is [string, string] => typeof entry[1] === 'string'));
191
- }
192
-
193
- function parseSidecarResponse(raw: string): SidecarResponse {
194
- let parsed: unknown;
195
- try {
196
- parsed = JSON.parse(raw);
197
- } catch {
198
- throw new Error('CODEGRAPH_PROTOCOL_ERROR: sidecar returned invalid JSON');
199
- }
200
- if (!parsed || typeof parsed !== 'object' || (parsed as { schemaVersion?: unknown }).schemaVersion !== SCHEMA_VERSION) {
201
- throw new Error('CODEGRAPH_PROTOCOL_ERROR: sidecar returned an unsupported response');
202
- }
203
- return parsed as SidecarResponse;
204
- }
205
-
206
- function providerStatus(metadata: CodeGraphIndexMetadata): CodeGraphProviderStatus {
207
- if (!metadata.initialized) return 'unavailable';
208
- if (metadata.staleEngine) return 'stale';
209
- if (metadata.changedFiles.added.length > 0 || metadata.changedFiles.modified.length > 0 || metadata.changedFiles.removed.length > 0) return 'stale';
210
- return 'ready';
211
- }
212
-
213
- /**
214
- * CodeGraph 1.0.1 deliberately discovers nested repositories below ignored
215
- * directories. Its read-only change scan can then report those same paths as
216
- * permanently added/removed relative to the owning repository. Ignore only
217
- * paths that Git itself classifies as excluded; tracked changes still make the
218
- * structural index stale and any Git probe failure keeps the SDK result.
219
- */
220
- export function filterGitIgnoredCodeGraphChanges(
221
- repoRoot: string,
222
- metadata: CodeGraphIndexMetadata,
223
- ): CodeGraphIndexMetadata {
224
- const changed = [
225
- ...metadata.changedFiles.added,
226
- ...metadata.changedFiles.modified,
227
- ...metadata.changedFiles.removed,
228
- ];
229
- if (changed.length === 0) return metadata;
230
- const git = spawnSync('git', ['-C', resolve(repoRoot), 'check-ignore', '--stdin', '-z'], {
231
- input: `${changed.join('\0')}\0`,
232
- encoding: 'utf8',
233
- env: {
234
- PATH: process.env.PATH,
235
- HOME: process.env.HOME,
236
- GIT_TERMINAL_PROMPT: '0',
237
- GIT_CONFIG_NOSYSTEM: '1',
238
- CI: '1',
239
- },
240
- timeout: 5_000,
241
- maxBuffer: 512 * 1024,
242
- windowsHide: true,
243
- });
244
- if (git.error || (git.status !== 0 && git.status !== 1)) return metadata;
245
- const ignored = new Set(String(git.stdout ?? '').split('\0').filter(Boolean));
246
- if (ignored.size === 0) return metadata;
247
- return {
248
- ...metadata,
249
- changedFiles: {
250
- added: metadata.changedFiles.added.filter((path) => !ignored.has(path)),
251
- modified: metadata.changedFiles.modified.filter((path) => !ignored.has(path)),
252
- removed: metadata.changedFiles.removed.filter((path) => !ignored.has(path)),
253
- },
254
- ignoredChangedFileCount: ignored.size,
255
- };
256
- }
257
-
258
- function errorResponse(operation: CodeGraphReadOperation, code: string, message: string, total: number): CodeGraphReadProviderResponse {
259
- const unavailable = code.includes('MISSING') || code.includes('UNAVAILABLE') || code.includes('NOT_INITIALIZED');
260
- return {
261
- schemaVersion: 1,
262
- provider: 'codegraph',
263
- operation,
264
- ok: false,
265
- status: unavailable ? 'unavailable' : 'degraded',
266
- error: { code, message: message.slice(0, 1_000) },
267
- timingsMs: { total },
268
- };
269
- }
270
-
271
- export function queryCodeGraphReadProvider(
272
- repoRoot: string,
273
- request: CodeGraphReadRequest,
274
- options: { timeoutMs?: number } = {},
275
- ): CodeGraphReadProviderResponse {
276
- const startedAt = performance.now();
277
- if (!ALLOWED_OPERATIONS.has(request.operation)) {
278
- return errorResponse(request.operation, 'CODEGRAPH_OPERATION_NOT_ALLOWED', `Unsupported read operation: ${String(request.operation)}`, performance.now() - startedAt);
279
- }
280
-
281
- let runtime: ReturnType<typeof resolveCodeGraphBundledRuntime>;
282
- try {
283
- runtime = resolveCodeGraphBundledRuntime();
284
- } catch (error) {
285
- const message = error instanceof Error ? error.message : String(error);
286
- const [code] = message.split(':', 1);
287
- return errorResponse(request.operation, code || 'CODEGRAPH_RUNTIME_UNAVAILABLE', message, performance.now() - startedAt);
288
- }
289
-
290
- const normalizedRequest = {
291
- schemaVersion: SCHEMA_VERSION,
292
- operation: request.operation,
293
- projectRoot: resolve(repoRoot),
294
- ...(typeof request.query === 'string' ? { query: request.query.slice(0, 2_000) } : {}),
295
- ...(typeof request.nodeId === 'string' ? { nodeId: request.nodeId.slice(0, 1_000) } : {}),
296
- ...(typeof request.filePath === 'string' ? { filePath: request.filePath.slice(0, 2_000) } : {}),
297
- ...(request.refresh === 'if_stale' ? { refresh: 'if_stale' as const } : {}),
298
- limit: boundedInteger(request.limit, 12, 1, 40),
299
- maxNodes: boundedInteger(request.maxNodes, 40, 1, 80),
300
- maxDepth: boundedInteger(request.maxDepth, 2, 1, 5),
301
- };
302
- const input = JSON.stringify(normalizedRequest);
303
- if (Buffer.byteLength(input) > MAX_REQUEST_BYTES) {
304
- return errorResponse(request.operation, 'CODEGRAPH_REQUEST_TOO_LARGE', 'CodeGraph request exceeded the bounded input limit.', performance.now() - startedAt);
305
- }
306
-
307
- const processStartedAt = performance.now();
308
- const resolvedRepoRoot = resolve(repoRoot);
309
- const locator = createCodegraphCacheLocator(resolvedRepoRoot, resolveControllerHome(), { createTarget: false });
310
- let execution: ReturnType<typeof spawnSync>;
311
- try {
312
- execution = spawnSync(runtime.nodeExecutable, [runtime.sidecarPath], {
313
- cwd: resolvedRepoRoot,
314
- input,
315
- encoding: 'utf8',
316
- env: minimalEnvironment(runtime, locator?.name),
317
- timeout: boundedInteger(options.timeoutMs, DEFAULT_TIMEOUT_MS, 1_000, 60_000),
318
- maxBuffer: MAX_RESPONSE_BYTES,
319
- windowsHide: true,
320
- shell: false,
321
- });
322
- } finally {
323
- locator?.release();
324
- }
325
- const processMs = performance.now() - processStartedAt;
326
- if (execution.error) {
327
- const code = (execution.error as NodeJS.ErrnoException).code === 'ETIMEDOUT' ? 'CODEGRAPH_TIMEOUT' : 'CODEGRAPH_START_FAILED';
328
- return errorResponse(request.operation, code, execution.error.message, performance.now() - startedAt);
329
- }
330
- if (Buffer.byteLength(execution.stdout ?? '') > MAX_RESPONSE_BYTES) {
331
- return errorResponse(request.operation, 'CODEGRAPH_RESPONSE_TOO_LARGE', 'CodeGraph response exceeded the bounded output limit.', performance.now() - startedAt);
332
- }
333
- if (execution.status !== 0) {
334
- const stderr = String(execution.stderr ?? '').slice(-MAX_STDERR_CHARS);
335
- return errorResponse(request.operation, 'CODEGRAPH_SIDECAR_FAILED', stderr || `CodeGraph sidecar exited with status ${String(execution.status)}`, performance.now() - startedAt);
336
- }
337
-
338
- let parsed: SidecarResponse;
339
- try {
340
- parsed = parseSidecarResponse(String(execution.stdout ?? ''));
341
- } catch (error) {
342
- return errorResponse(request.operation, 'CODEGRAPH_PROTOCOL_ERROR', error instanceof Error ? error.message : String(error), performance.now() - startedAt);
343
- }
344
- if (!parsed.ok) {
345
- return errorResponse(request.operation, parsed.error.code, parsed.error.message, performance.now() - startedAt);
346
- }
347
- const metadata = filterGitIgnoredCodeGraphChanges(repoRoot, parsed.metadata);
348
- return {
349
- schemaVersion: 1,
350
- provider: 'codegraph',
351
- operation: request.operation,
352
- ok: metadata.initialized,
353
- status: providerStatus(metadata),
354
- metadata,
355
- result: parsed.result,
356
- timingsMs: {
357
- total: Math.round((performance.now() - startedAt) * 100) / 100,
358
- process: Math.round(processMs * 100) / 100,
359
- ...(typeof parsed.timingsMs?.open === 'number' ? { open: parsed.timingsMs.open } : {}),
360
- ...(typeof parsed.timingsMs?.query === 'number' ? { query: parsed.timingsMs.query } : {}),
361
- },
362
- };
363
- }
364
-
365
- interface PersistentCodeGraphSession {
366
- repoRoot: string;
367
- runtimeKey: string;
368
- child: ChildProcessWithoutNullStreams;
369
- reader: ReadlineInterface;
370
- lines: AsyncIterator<string>;
371
- stderr: string;
372
- closed: boolean;
373
- idleTimer?: NodeJS.Timeout;
374
- queue: Promise<void>;
375
- locator?: CodegraphCacheLocator;
376
- }
377
-
378
- const persistentSessions = new Map<string, PersistentCodeGraphSession>();
379
- let persistentSessionSpawns = 0;
380
- let persistentSessionReuses = 0;
381
- let persistentSessionRequests = 0;
382
-
383
- function persistentRuntimeKey(runtime: ReturnType<typeof resolveCodeGraphBundledRuntime>, cacheMode: 'controller' | 'legacy'): string {
384
- return `${runtime.nodeExecutable}\u0000${runtime.sidecarPath}\u0000${runtime.libraryPath}\u0000${cacheMode}`;
385
- }
386
-
387
- function closePersistentSessionNow(session: PersistentCodeGraphSession): void {
388
- if (session.closed) return;
389
- session.closed = true;
390
- if (session.idleTimer) clearTimeout(session.idleTimer);
391
- if (persistentSessions.get(session.repoRoot) === session) persistentSessions.delete(session.repoRoot);
392
- try { session.reader.close(); } catch {}
393
- try { session.child.stdin.end(); } catch {}
394
- try { session.child.kill(); } catch {}
395
- session.locator?.release();
396
- session.locator = undefined;
397
- }
398
-
399
- function schedulePersistentSessionIdle(session: PersistentCodeGraphSession): void {
400
- if (session.idleTimer) clearTimeout(session.idleTimer);
401
- const timer = setTimeout(() => closePersistentSessionNow(session), PERSISTENT_SIDECAR_IDLE_MS);
402
- timer.unref();
403
- session.idleTimer = timer;
404
- }
405
-
406
- function createPersistentSession(
407
- repoRoot: string,
408
- runtime: ReturnType<typeof resolveCodeGraphBundledRuntime>,
409
- ): PersistentCodeGraphSession {
410
- const controllerHome = resolveControllerHome();
411
- const cacheMode: 'controller' | 'legacy' = existsSync(codegraphRepositoryCacheRoot(controllerHome, repoRoot)) ? 'controller' : 'legacy';
412
- const locator = cacheMode === 'controller'
413
- ? createCodegraphCacheLocator(repoRoot, controllerHome, { createTarget: false }) ?? undefined
414
- : undefined;
415
- let child: ChildProcessWithoutNullStreams;
416
- try {
417
- child = spawn(runtime.nodeExecutable, [runtime.sidecarPath], {
418
- cwd: repoRoot,
419
- env: { ...minimalEnvironment(runtime, locator?.name), FORGE_CODEGRAPH_PERSISTENT: '1' },
420
- stdio: ['pipe', 'pipe', 'pipe'],
421
- windowsHide: true,
422
- shell: false,
423
- });
424
- } catch (error) {
425
- locator?.release();
426
- throw error;
427
- }
428
- child.unref();
429
- const reader = createInterface({ input: child.stdout, crlfDelay: Infinity });
430
- const session: PersistentCodeGraphSession = {
431
- repoRoot,
432
- runtimeKey: persistentRuntimeKey(runtime, cacheMode),
433
- child,
434
- reader,
435
- lines: reader[Symbol.asyncIterator](),
436
- stderr: '',
437
- closed: false,
438
- queue: Promise.resolve(),
439
- locator,
440
- };
441
- child.stderr.on('data', (chunk: Buffer) => {
442
- if (session.stderr.length >= MAX_STDERR_CHARS) return;
443
- session.stderr += chunk.toString('utf8').slice(0, MAX_STDERR_CHARS - session.stderr.length);
444
- });
445
- child.on('error', () => closePersistentSessionNow(session));
446
- child.on('close', () => {
447
- session.closed = true;
448
- if (session.idleTimer) clearTimeout(session.idleTimer);
449
- if (persistentSessions.get(repoRoot) === session) persistentSessions.delete(repoRoot);
450
- session.locator?.release();
451
- session.locator = undefined;
452
- });
453
- persistentSessions.set(repoRoot, session);
454
- persistentSessionSpawns += 1;
455
- return session;
456
- }
457
-
458
- function getPersistentSession(
459
- repoRoot: string,
460
- runtime: ReturnType<typeof resolveCodeGraphBundledRuntime>,
461
- ): PersistentCodeGraphSession {
462
- const controllerHome = resolveControllerHome();
463
- const cacheMode: 'controller' | 'legacy' = existsSync(codegraphRepositoryCacheRoot(controllerHome, repoRoot)) ? 'controller' : 'legacy';
464
- const key = persistentRuntimeKey(runtime, cacheMode);
465
- const current = persistentSessions.get(repoRoot);
466
- if (current && !current.closed && current.runtimeKey === key) {
467
- if (current.idleTimer) clearTimeout(current.idleTimer);
468
- current.idleTimer = undefined;
469
- persistentSessionReuses += 1;
470
- return current;
471
- }
472
- if (current) closePersistentSessionNow(current);
473
- return createPersistentSession(repoRoot, runtime);
474
- }
475
-
476
- async function serializedPersistentRequest<T>(session: PersistentCodeGraphSession, operation: () => Promise<T>): Promise<T> {
477
- const previous = session.queue;
478
- let release!: () => void;
479
- session.queue = new Promise<void>((resolveQueue) => { release = resolveQueue; });
480
- await previous.catch(() => undefined);
481
- try {
482
- return await operation();
483
- } finally {
484
- release();
485
- }
486
- }
487
-
488
- async function nextPersistentLine(session: PersistentCodeGraphSession, timeoutMs: number): Promise<string> {
489
- let timer: NodeJS.Timeout | undefined;
490
- try {
491
- const timeout = new Promise<never>((_, reject) => {
492
- timer = setTimeout(() => reject(new Error('CODEGRAPH_TIMEOUT')), timeoutMs);
493
- timer.unref();
494
- });
495
- const next = await Promise.race([session.lines.next(), timeout]);
496
- if (next.done || typeof next.value !== 'string') {
497
- throw new Error(session.stderr || 'CODEGRAPH_SIDECAR_CLOSED');
498
- }
499
- return next.value;
500
- } finally {
501
- if (timer) clearTimeout(timer);
502
- }
503
- }
504
-
505
- export async function closeCodeGraphReadProviderSessions(): Promise<void> {
506
- const sessions = [...persistentSessions.values()];
507
- persistentSessions.clear();
508
- for (const session of sessions) closePersistentSessionNow(session);
509
- }
510
-
511
- export async function clearCodeGraphReadProviderSessionsForTest(): Promise<void> {
512
- await closeCodeGraphReadProviderSessions();
513
- persistentSessionSpawns = 0;
514
- persistentSessionReuses = 0;
515
- persistentSessionRequests = 0;
516
- }
517
-
518
- export function codeGraphReadProviderSessionSnapshotForTest(): {
519
- active: number;
520
- spawns: number;
521
- reuses: number;
522
- requests: number;
523
- } {
524
- return {
525
- active: persistentSessions.size,
526
- spawns: persistentSessionSpawns,
527
- reuses: persistentSessionReuses,
528
- requests: persistentSessionRequests,
529
- };
530
- }
531
-
532
- /** Async sidecar path used by the first broad Context Plane fan-in. */
533
- export async function queryCodeGraphReadProviderAsync(
534
- repoRoot: string,
535
- request: CodeGraphReadRequest,
536
- options: { timeoutMs?: number } = {},
537
- ): Promise<CodeGraphReadProviderResponse> {
538
- const startedAt = performance.now();
539
- if (!ALLOWED_OPERATIONS.has(request.operation)) {
540
- return errorResponse(request.operation, 'CODEGRAPH_OPERATION_NOT_ALLOWED', `Unsupported read operation: ${String(request.operation)}`, performance.now() - startedAt);
541
- }
542
- let runtime: ReturnType<typeof resolveCodeGraphBundledRuntime>;
543
- try { runtime = resolveCodeGraphBundledRuntime(); }
544
- catch (error) {
545
- const message = error instanceof Error ? error.message : String(error);
546
- return errorResponse(request.operation, message.split(':', 1)[0] || 'CODEGRAPH_RUNTIME_UNAVAILABLE', message, performance.now() - startedAt);
547
- }
548
- const resolvedRepoRoot = resolve(repoRoot);
549
- const input = JSON.stringify({
550
- schemaVersion: SCHEMA_VERSION,
551
- operation: request.operation,
552
- projectRoot: resolvedRepoRoot,
553
- ...(typeof request.query === 'string' ? { query: request.query.slice(0, 2_000) } : {}),
554
- ...(typeof request.nodeId === 'string' ? { nodeId: request.nodeId.slice(0, 1_000) } : {}),
555
- ...(typeof request.filePath === 'string' ? { filePath: request.filePath.slice(0, 2_000) } : {}),
556
- ...(request.refresh === 'if_stale' ? { refresh: 'if_stale' as const } : {}),
557
- limit: boundedInteger(request.limit, 12, 1, 40),
558
- maxNodes: boundedInteger(request.maxNodes, 40, 1, 80),
559
- maxDepth: boundedInteger(request.maxDepth, 2, 1, 5),
560
- });
561
- if (Buffer.byteLength(input) > MAX_REQUEST_BYTES) {
562
- return errorResponse(request.operation, 'CODEGRAPH_REQUEST_TOO_LARGE', 'CodeGraph request exceeded the bounded input limit.', performance.now() - startedAt);
563
- }
564
-
565
- let session = getPersistentSession(resolvedRepoRoot, runtime);
566
- return await serializedPersistentRequest(session, async () => {
567
- if (session.closed) session = getPersistentSession(resolvedRepoRoot, runtime);
568
- const processStartedAt = performance.now();
569
- persistentSessionRequests += 1;
570
- try {
571
- await new Promise<void>((resolveWrite, rejectWrite) => {
572
- session.child.stdin.write(`${input}\n`, (error) => error ? rejectWrite(error) : resolveWrite());
573
- });
574
- const raw = await nextPersistentLine(
575
- session,
576
- boundedInteger(options.timeoutMs, DEFAULT_TIMEOUT_MS, 1_000, 60_000),
577
- );
578
- if (Buffer.byteLength(raw) > MAX_RESPONSE_BYTES) {
579
- closePersistentSessionNow(session);
580
- return errorResponse(request.operation, 'CODEGRAPH_RESPONSE_TOO_LARGE', 'CodeGraph response exceeded the bounded output limit.', performance.now() - startedAt);
581
- }
582
- const parsed = parseSidecarResponse(raw);
583
- if (!parsed.ok) {
584
- schedulePersistentSessionIdle(session);
585
- return errorResponse(request.operation, parsed.error.code, parsed.error.message, performance.now() - startedAt);
586
- }
587
- const metadata = filterGitIgnoredCodeGraphChanges(resolvedRepoRoot, parsed.metadata);
588
- schedulePersistentSessionIdle(session);
589
- return {
590
- schemaVersion: 1,
591
- provider: 'codegraph',
592
- operation: request.operation,
593
- ok: metadata.initialized,
594
- status: providerStatus(metadata),
595
- metadata,
596
- result: parsed.result,
597
- timingsMs: {
598
- total: Math.round((performance.now() - startedAt) * 100) / 100,
599
- process: Math.round((performance.now() - processStartedAt) * 100) / 100,
600
- ...(typeof parsed.timingsMs?.open === 'number' ? { open: parsed.timingsMs.open } : {}),
601
- ...(typeof parsed.timingsMs?.query === 'number' ? { query: parsed.timingsMs.query } : {}),
602
- },
603
- };
604
- } catch (error) {
605
- closePersistentSessionNow(session);
606
- const message = error instanceof Error ? error.message : String(error);
607
- const code = message === 'CODEGRAPH_TIMEOUT' ? 'CODEGRAPH_TIMEOUT' : 'CODEGRAPH_SIDECAR_FAILED';
608
- return errorResponse(request.operation, code, message, performance.now() - startedAt);
609
- }
610
- });
611
- }