akm-cli 0.9.30 → 0.10.261001-beta

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 (384) hide show
  1. package/CHANGELOG.md +438 -0
  2. package/README.md +10 -10
  3. package/ROADMAP.md +112 -0
  4. package/STABILITY.md +99 -57
  5. package/dist/api-node.mjs +20 -0
  6. package/dist/api.d.ts +23 -0
  7. package/dist/api.js +45 -0
  8. package/dist/assets/hints/cli-hints-full.md +15 -29
  9. package/dist/assets/hints/cli-hints-short.md +2 -2
  10. package/dist/assets/improve-strategies/default.json +3 -3
  11. package/dist/assets/prompts/consolidate-pair.md +9 -7
  12. package/dist/assets/stash-skeleton/README.md +1 -1
  13. package/dist/assets/tasks/improve/akm-improve-consolidate.yml +1 -1
  14. package/dist/cli/shared.js +31 -48
  15. package/dist/cli/unknown-flags.js +6 -43
  16. package/dist/cli.js +8 -34
  17. package/dist/commands/agent/contribute-cli.js +1 -1
  18. package/dist/commands/completions.js +1 -2
  19. package/dist/commands/config-cli.js +5 -28
  20. package/dist/commands/env/env-cli.js +5 -5
  21. package/dist/commands/env/secret-cli.js +2 -2
  22. package/dist/commands/feedback-cli.js +75 -49
  23. package/dist/commands/health/checks.js +41 -16
  24. package/dist/commands/health/plugin-staleness.js +52 -22
  25. package/dist/commands/improve/autonomy-gate.js +5 -3
  26. package/dist/commands/improve/consolidate/chunking.js +3 -10
  27. package/dist/commands/improve/consolidate/continuity-check.js +4 -4
  28. package/dist/commands/improve/consolidate/pair-pass.js +29 -10
  29. package/dist/commands/improve/consolidate.js +10 -65
  30. package/dist/commands/improve/distill/lesson-update.js +91 -0
  31. package/dist/commands/improve/distill-guards.js +1 -43
  32. package/dist/commands/improve/distill.js +148 -21
  33. package/dist/commands/improve/eligibility.js +14 -1
  34. package/dist/commands/improve/extract-cli.js +1 -1
  35. package/dist/commands/improve/extract-prompt.js +17 -7
  36. package/dist/commands/improve/extract.js +5 -7
  37. package/dist/commands/improve/improve-cli.js +125 -118
  38. package/dist/commands/improve/improve-strategies.js +8 -12
  39. package/dist/commands/improve/improve.js +134 -52
  40. package/dist/commands/improve/loop-stages.js +18 -5
  41. package/dist/commands/improve/planner.js +0 -1
  42. package/dist/commands/improve/preparation.js +40 -99
  43. package/dist/commands/improve/proactive-maintenance.js +2 -2
  44. package/dist/commands/improve/reflect-noise.js +3 -55
  45. package/dist/commands/improve/reflect.js +29 -34
  46. package/dist/commands/improve/retrieval-queries.js +37 -0
  47. package/dist/commands/improve/retrieval-scope.js +2 -2
  48. package/dist/commands/improve/salience.js +2 -9
  49. package/dist/commands/improve/session-asset.js +4 -1
  50. package/dist/commands/improve/stage.js +23 -12
  51. package/dist/commands/lint/index.js +5 -20
  52. package/dist/commands/observability-cli.js +3 -9
  53. package/dist/commands/proposal/drain.js +43 -6
  54. package/dist/commands/proposal/proposal-cli.js +11 -31
  55. package/dist/commands/proposal/repository.js +20 -14
  56. package/dist/commands/proposal/validators/proposal-quality-validators.js +0 -3
  57. package/dist/commands/read/knowledge.js +3 -3
  58. package/dist/commands/read/remember-cli.js +0 -13
  59. package/dist/commands/read/search-cli.js +29 -97
  60. package/dist/commands/read/search.js +0 -11
  61. package/dist/commands/read/show.js +0 -19
  62. package/dist/commands/sources/plugin-upgrade.js +164 -101
  63. package/dist/commands/sources/sources-cli.js +1 -15
  64. package/dist/commands/sources/stash-cli.js +6 -14
  65. package/dist/commands/tasks/tasks-cli.js +4 -115
  66. package/dist/commands/workflow/plan.js +11 -33
  67. package/dist/commands/workflow-cli.js +2 -7
  68. package/dist/core/adapter/adapter-ids.js +1 -2
  69. package/dist/core/adapter/adapters/agent-skills-adapter.js +0 -4
  70. package/dist/core/adapter/adapters/akm-adapter.js +9 -48
  71. package/dist/core/adapter/adapters/akm-lint.js +10 -26
  72. package/dist/core/adapter/adapters/akm-metadata.js +2 -72
  73. package/dist/core/adapter/adapters/akm-task-adapter.js +0 -5
  74. package/dist/core/adapter/adapters/akm-workflow-adapter.js +9 -28
  75. package/dist/core/adapter/adapters/dotenv-adapter.js +1 -20
  76. package/dist/core/adapter/adapters/generic-files-adapter.js +0 -10
  77. package/dist/core/adapter/adapters/llm-wiki-adapter.js +0 -4
  78. package/dist/core/adapter/adapters/tool-dir-shared.js +0 -24
  79. package/dist/core/adapter/adapters/website-snapshot-adapter.js +4 -4
  80. package/dist/core/adapter/recognize-match.js +3 -4
  81. package/dist/core/common.js +18 -2
  82. package/dist/core/config/config-schema.js +12 -15
  83. package/dist/core/config/config-types.js +6 -15
  84. package/dist/core/config/config-walker.js +6 -23
  85. package/dist/core/config/config.js +17 -80
  86. package/dist/core/config/engine-semantics.js +7 -3
  87. package/dist/core/config/schema/engines.js +7 -7
  88. package/dist/core/config/schema/improve-processes.js +10 -63
  89. package/dist/core/config/schema/improve.js +2 -21
  90. package/dist/core/config/schema/index-config.js +6 -39
  91. package/dist/core/env-secret-ref.js +2 -45
  92. package/dist/core/errors.js +1 -2
  93. package/dist/core/extra-params.js +2 -86
  94. package/dist/core/file-lock.js +12 -7
  95. package/dist/core/improve-result.js +13 -1
  96. package/dist/core/mutation-target.js +2 -2
  97. package/dist/core/paths.js +4 -0
  98. package/dist/core/recognition-util.js +4 -5
  99. package/dist/core/run-lock.js +1 -1
  100. package/dist/core/subprocess.js +49 -0
  101. package/dist/core/warn.js +21 -4
  102. package/dist/core/write-source.js +3 -3
  103. package/dist/execution/target-ref.js +1 -2
  104. package/dist/indexer/indexer.js +15 -6
  105. package/dist/indexer/passes/memory-inference.js +15 -6
  106. package/dist/indexer/search/db-search.js +49 -36
  107. package/dist/indexer/search/fts-query.js +0 -19
  108. package/dist/indexer/search/ranking.js +29 -1
  109. package/dist/indexer/usage/usage-events.js +21 -16
  110. package/dist/integrations/agent/engine-resolution.js +5 -2
  111. package/dist/integrations/agent/index.js +1 -1
  112. package/dist/integrations/agent/profiles.js +41 -98
  113. package/dist/integrations/agent/request-lowering.js +3 -3
  114. package/dist/integrations/harnesses/aider/index.js +5 -0
  115. package/dist/integrations/harnesses/amazonq/index.js +1 -0
  116. package/dist/integrations/harnesses/claude/config-import.js +2 -3
  117. package/dist/integrations/harnesses/claude/index.js +5 -0
  118. package/dist/integrations/harnesses/codex/index.js +1 -0
  119. package/dist/integrations/harnesses/copilot/index.js +1 -0
  120. package/dist/integrations/harnesses/gemini/index.js +1 -0
  121. package/dist/integrations/harnesses/index.js +18 -39
  122. package/dist/integrations/harnesses/opencode/agent-builder.js +60 -35
  123. package/dist/integrations/harnesses/opencode/config-import.js +121 -52
  124. package/dist/integrations/harnesses/opencode/index.js +22 -0
  125. package/dist/integrations/harnesses/opencode/plugin-layout.js +68 -0
  126. package/dist/integrations/harnesses/opencode/session-log-types.js +12 -0
  127. package/dist/integrations/harnesses/opencode/session-log-v1.js +72 -0
  128. package/dist/integrations/harnesses/opencode/session-log-v2.js +140 -0
  129. package/dist/integrations/harnesses/opencode/session-log.js +104 -115
  130. package/dist/integrations/harnesses/opencode/version.js +98 -0
  131. package/dist/integrations/harnesses/opencode-sdk/{harness.js → index.js} +5 -17
  132. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +105 -206
  133. package/dist/integrations/harnesses/opencode-sdk/v1-adapter.js +199 -0
  134. package/dist/integrations/harnesses/opencode-sdk/v2-adapter.js +254 -0
  135. package/dist/integrations/harnesses/opencode-sdk/wire.js +66 -0
  136. package/dist/integrations/harnesses/openhands/index.js +1 -0
  137. package/dist/integrations/harnesses/pi/index.js +1 -0
  138. package/dist/integrations/harnesses/shared.js +2 -0
  139. package/dist/integrations/harnesses/types.js +2 -0
  140. package/dist/llm/client.js +74 -14
  141. package/dist/output/cli-hints.js +1 -1
  142. package/dist/output/context.js +10 -19
  143. package/dist/output/format-exempt.js +5 -8
  144. package/dist/output/shapes/helpers.js +1 -22
  145. package/dist/output/shapes/passthrough.js +0 -1
  146. package/dist/output/shapes.js +3 -31
  147. package/dist/output/stdout.js +5 -1
  148. package/dist/output/text/command-format.js +6 -1
  149. package/dist/output/text/workflow-format.js +4 -22
  150. package/dist/scripts/akm-migrate-node.js +15769 -16731
  151. package/dist/scripts/akm-migrate.js +16339 -17297
  152. package/dist/setup/detect.js +10 -4
  153. package/dist/setup/harness-config-import.js +5 -14
  154. package/dist/setup/setup.js +1 -1
  155. package/dist/setup/steps/tasks.js +12 -13
  156. package/dist/sources/providers/git-stash.js +94 -13
  157. package/dist/storage/repositories/index-utility-repository.js +2 -32
  158. package/dist/storage/repositories/index-vec-repository.js +4 -0
  159. package/dist/storage/repositories/task-history-repository.js +0 -5
  160. package/dist/storage/repositories/workflow-runs-repository.js +5 -15
  161. package/dist/tasks/embedded.js +2 -1
  162. package/dist/tasks/run/run-command-task.js +9 -1
  163. package/dist/tasks/run/run-workflow-task.js +4 -3
  164. package/dist/tasks/run/task-history.js +0 -2
  165. package/dist/tasks/run/task-log.js +38 -1
  166. package/dist/tasks/schedule-gates.js +39 -0
  167. package/dist/tasks/scheduler-binding.js +0 -16
  168. package/dist/tasks/scheduler-sync.js +3 -97
  169. package/dist/tasks/source/bounded-document.js +1 -1
  170. package/dist/tasks/source/task-source-v4.js +2 -12
  171. package/dist/tasks/task-run-reserved-flags.js +2 -31
  172. package/dist/workflows/authoring/authoring.js +6 -6
  173. package/dist/workflows/compile.js +8 -65
  174. package/dist/workflows/exec/child-workflow.js +22 -3
  175. package/dist/workflows/exec/native-executor.js +12 -147
  176. package/dist/workflows/exec/run-workflow.js +31 -103
  177. package/dist/workflows/exec/step-work.js +9 -178
  178. package/dist/workflows/exec/unit-dispatch.js +0 -10
  179. package/dist/workflows/freeze/environment.js +3 -44
  180. package/dist/workflows/freeze/freeze.js +8 -41
  181. package/dist/workflows/freeze/targets/child-workflow.js +27 -63
  182. package/dist/workflows/freeze/targets/command.js +2 -16
  183. package/dist/workflows/freeze/targets/shell.js +0 -2
  184. package/dist/workflows/freeze/task-bindings.js +2 -28
  185. package/dist/workflows/ir/params.js +12 -2
  186. package/dist/workflows/parser.js +82 -232
  187. package/dist/workflows/plan.js +1 -1
  188. package/dist/workflows/renderer.js +10 -19
  189. package/dist/workflows/runtime/run-plan.js +11 -53
  190. package/dist/workflows/runtime/runs.js +4 -27
  191. package/dist/workflows/source-files.js +12 -16
  192. package/dist/workflows/source-semantics.js +1 -93
  193. package/docs/README.md +43 -42
  194. package/docs/agents/README.md +15 -0
  195. package/docs/agents/agent-install.md +14 -0
  196. package/docs/architecture/0.10-process-rules.md +827 -0
  197. package/docs/architecture/README.md +67 -0
  198. package/docs/architecture/adapters.md +258 -0
  199. package/docs/architecture/akm-architecture-decision-history.md +2055 -0
  200. package/docs/architecture/akm-core-principles.md +126 -0
  201. package/docs/architecture/architecture.md +578 -0
  202. package/docs/architecture/comparisons/claude-code-vs-akm-workflows-full.md +550 -0
  203. package/docs/architecture/decisions/0001-no-interpolation-attached-structured-context.md +72 -0
  204. package/docs/architecture/decisions/0002-unit-reuse-and-input-hash-scope.md +142 -0
  205. package/docs/architecture/decisions/0003-child-env-allowlist-and-provenance.md +189 -0
  206. package/docs/architecture/decisions/0004-task-input-contract-and-flag-coercion.md +97 -0
  207. package/docs/architecture/decisions/0005-task-result-vocabulary-and-legacy-read-mapping.md +108 -0
  208. package/docs/architecture/decisions/0006-task-source-version-routing.md +124 -0
  209. package/docs/architecture/decisions/0007-workflow-composition-bounds.md +83 -0
  210. package/docs/architecture/decisions/0008-task-binding-normalization.md +88 -0
  211. package/docs/architecture/decisions/0009-child-run-publication-column-parity.md +80 -0
  212. package/docs/architecture/decisions/0010-driver-protocol-cut.md +36 -0
  213. package/docs/architecture/decisions/0011-engine-run-loop-invariants.md +125 -0
  214. package/docs/architecture/decisions/README.md +62 -0
  215. package/docs/architecture/improvement.md +479 -0
  216. package/docs/architecture/internals/classification.md +154 -0
  217. package/docs/architecture/internals/fresh-host-rebuild-runbook.md +40 -0
  218. package/docs/architecture/internals/functional-contract-patterns.md +340 -0
  219. package/docs/architecture/internals/health-advisories.md +110 -0
  220. package/docs/architecture/internals/improve-workflow.md +719 -0
  221. package/docs/architecture/internals/indexing.md +498 -0
  222. package/docs/architecture/internals/registry-network-boundary.md +57 -0
  223. package/docs/architecture/internals/search.md +248 -0
  224. package/docs/architecture/internals/storage-locations.md +943 -0
  225. package/docs/architecture/persisted-data-compat.md +68 -0
  226. package/docs/architecture/reviews/env-secret-access.md +319 -0
  227. package/docs/architecture/runtime-boundary-design.md +153 -0
  228. package/docs/architecture/specs/0.9.0-close-out-plan.md +361 -0
  229. package/docs/architecture/specs/0.9.0-decisions.md +532 -0
  230. package/docs/architecture/specs/0.9.0-docs-code-drift-register.md +745 -0
  231. package/docs/architecture/specs/0.9.0-open-items-register.md +135 -0
  232. package/docs/architecture/specs/0.9.0-public-api-issue-backlog.md +740 -0
  233. package/docs/architecture/specs/0.9.0-release-surface-review.md +636 -0
  234. package/docs/architecture/specs/agent-command-engine-model-design.md +513 -0
  235. package/docs/architecture/specs/akm-0.9.0-bundle-adapter-spec.md +501 -0
  236. package/docs/architecture/specs/akm-0.9.0-ref-grammar-decision.md +291 -0
  237. package/docs/architecture/specs/akm-format-neutral-bundle-workspace-spec.md +2059 -0
  238. package/docs/architecture/specs/di-seams-plan.md +539 -0
  239. package/docs/architecture/specs/driver-protocol-keep-or-cut.md +275 -0
  240. package/docs/architecture/specs/fact-asset-type.md +142 -0
  241. package/docs/architecture/specs/improve-collapse-churn-detector-design.md +634 -0
  242. package/docs/architecture/specs/okf-support.md +148 -0
  243. package/docs/architecture/specs/ref.md +329 -0
  244. package/docs/architecture/specs/reviews/task-workflow-unification/README.md +72 -0
  245. package/docs/architecture/specs/reviews/task-workflow-unification/findings-consolidated.md +152 -0
  246. package/docs/architecture/specs/reviews/task-workflow-unification/library-eval-alternatives.md +352 -0
  247. package/docs/architecture/specs/reviews/task-workflow-unification/library-eval-bunqueue.md +300 -0
  248. package/docs/architecture/specs/reviews/task-workflow-unification/library-eval-openworkflow.md +402 -0
  249. package/docs/architecture/specs/reviews/task-workflow-unification/opus-review-1.md +758 -0
  250. package/docs/architecture/specs/reviews/task-workflow-unification/opus-review-2.md +645 -0
  251. package/docs/architecture/specs/reviews/task-workflow-unification/opus-review-3.md +602 -0
  252. package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-adversarial.md +27 -0
  253. package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-architecture.md +27 -0
  254. package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-coverage.md +74 -0
  255. package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-security.md +15 -0
  256. package/docs/architecture/specs/reviews/task-workflow-unification/panel-r2-adversarial.md +132 -0
  257. package/docs/architecture/specs/reviews/task-workflow-unification/panel-r2-verification.md +147 -0
  258. package/docs/architecture/specs/stash-conventions-code-spec.md +275 -0
  259. package/docs/architecture/specs/stash-organization-conventions.md +377 -0
  260. package/docs/architecture/specs/task-workflow-format-unification.md +721 -0
  261. package/docs/architecture/specs/workflow-engine-buy-vs-build.md +231 -0
  262. package/docs/architecture/specs/workflow-format-unification.md +432 -0
  263. package/docs/architecture/testing/manual-testing-checklist.md +3411 -0
  264. package/docs/architecture/testing/okf-v0.2-conformance-runbook.md +924 -0
  265. package/docs/architecture/testing/task-workflow-manual-tests.md +1720 -0
  266. package/docs/architecture/testing/testing-workflow.md +446 -0
  267. package/docs/architecture/workflow-engine.md +223 -0
  268. package/docs/guides/README.md +33 -0
  269. package/docs/guides/author-bundles.md +310 -0
  270. package/docs/guides/author-workflows.md +490 -0
  271. package/docs/guides/bundles.md +323 -0
  272. package/docs/guides/capture-knowledge.md +136 -0
  273. package/docs/guides/claude-code-vs-akm-workflows.md +29 -0
  274. package/docs/guides/concepts.md +93 -0
  275. package/docs/guides/discover-and-load.md +158 -0
  276. package/docs/guides/getting-started.md +240 -0
  277. package/docs/guides/improve-the-library.md +247 -0
  278. package/docs/guides/knowledge-management.md +18 -0
  279. package/docs/guides/recipes/headless-install.md +97 -0
  280. package/docs/guides/recipes/website-source.md +28 -0
  281. package/docs/guides/run-workflows.md +279 -0
  282. package/docs/guides/scheduling.md +131 -0
  283. package/docs/guides/use-with-any-agent.md +174 -0
  284. package/docs/guides/wikis.md +81 -0
  285. package/docs/integration/bundling-akm.md +7 -6
  286. package/docs/maintainers/README.md +19 -0
  287. package/docs/maintainers/curate-workmap.md +335 -0
  288. package/docs/maintainers/eval.md +3 -0
  289. package/docs/maintainers/local-development.md +108 -0
  290. package/docs/maintainers/release-checklist.md +135 -0
  291. package/docs/migration/README.md +4 -2
  292. package/docs/migration/release-notes/0.0.13.md +1 -1
  293. package/docs/migration/release-notes/0.1.0.md +1 -1
  294. package/docs/migration/release-notes/0.10.0.md +201 -0
  295. package/docs/migration/release-notes/0.2.0.md +1 -1
  296. package/docs/migration/release-notes/0.3.0.md +1 -1
  297. package/docs/migration/release-notes/0.5.0.md +1 -1
  298. package/docs/migration/release-notes/0.6.0.md +1 -1
  299. package/docs/migration/release-notes/0.7.0.md +1 -1
  300. package/docs/migration/release-notes/0.7.3.md +2 -2
  301. package/docs/migration/release-notes/0.7.4.md +1 -1
  302. package/docs/migration/release-notes/0.7.5.md +1 -1
  303. package/docs/migration/release-notes/0.8.0.md +1 -1
  304. package/docs/migration/release-notes/0.9.0.md +1 -1
  305. package/docs/migration/release-notes/0.9.14.md +1 -1
  306. package/docs/migration/release-notes/0.9.15.md +1 -1
  307. package/docs/migration/release-notes/0.9.16.md +1 -1
  308. package/docs/migration/release-notes/0.9.17.md +1 -1
  309. package/docs/migration/release-notes/0.9.19.md +1 -1
  310. package/docs/migration/release-notes/0.9.2.md +1 -1
  311. package/docs/migration/release-notes/README.md +28 -31
  312. package/docs/migration/v0.5-to-v0.6.md +759 -0
  313. package/docs/migration/v0.8-to-v0.9.md +1 -1
  314. package/docs/migration/v0.9-to-v0.10.md +507 -0
  315. package/docs/plans/0.9.2-agent-command-workflow-plan.md +423 -0
  316. package/docs/posts/README.md +30 -0
  317. package/docs/posts/akm-command-tour.md +495 -0
  318. package/docs/posts/akm-logo-sized.webp +0 -0
  319. package/docs/posts/belief-aware-memory-12.md +139 -0
  320. package/docs/posts/config-v2-lessons-16.md +191 -0
  321. package/docs/posts/improve-loop-autonomous-10.md +225 -0
  322. package/docs/posts/improve-pipeline-debugging-0803.md +179 -0
  323. package/docs/posts/intro-part-01.md +76 -0
  324. package/docs/posts/intro-part-02.md +221 -0
  325. package/docs/posts/intro-part-03.md +190 -0
  326. package/docs/posts/intro-part-04.md +221 -0
  327. package/docs/posts/llm-mode-reflect-13.md +166 -0
  328. package/docs/posts/openpalm-built-on-akm.md +86 -0
  329. package/docs/posts/progressive-disclosure-06.md +129 -0
  330. package/docs/posts/proposal-safety-net-15.md +112 -0
  331. package/docs/posts/release-0.5.0.md +247 -0
  332. package/docs/posts/release-0.6.0.md +117 -0
  333. package/docs/posts/release-0.7.0.md +159 -0
  334. package/docs/posts/release-0.8.0.md +332 -0
  335. package/docs/posts/scattered-skills-05.md +100 -0
  336. package/docs/posts/task-assets-persistent-workflows-11.md +222 -0
  337. package/docs/posts/team-skills-07.md +198 -0
  338. package/docs/posts/wiki-agent-knowledge-08.md +223 -0
  339. package/docs/posts/workflows-vaults-09.md +321 -0
  340. package/docs/product-surface.md +54 -0
  341. package/docs/reference/README.md +2 -2
  342. package/docs/reference/api.md +65 -0
  343. package/docs/reference/asset-types.md +166 -0
  344. package/docs/reference/bundle-types.md +2 -4
  345. package/docs/reference/cli.md +163 -192
  346. package/docs/reference/configuration.md +101 -20
  347. package/docs/reference/data-and-telemetry.md +2 -2
  348. package/docs/reference/env-and-secrets.md +126 -0
  349. package/docs/reference/memory.md +124 -0
  350. package/docs/reference/refs.md +156 -0
  351. package/docs/reference/registry.md +489 -0
  352. package/docs/reference/supported-formats.md +3 -4
  353. package/docs/reference/tasks.md +12 -19
  354. package/docs/reference/website-sources.md +141 -0
  355. package/docs/reference/workflow-schema.md +89 -317
  356. package/docs/reference/workflows.md +20 -48
  357. package/package.json +23 -16
  358. package/schemas/akm-config.json +2 -243
  359. package/schemas/akm-task.json +2 -3
  360. package/schemas/akm-workflow.json +47 -84
  361. package/dist/assets/improve-strategies/catchup.json +0 -41
  362. package/dist/assets/improve-strategies/proactive-maintenance.json +0 -24
  363. package/dist/assets/improve-strategies/quick.json +0 -17
  364. package/dist/assets/improve-strategies/reflect-distill.json +0 -29
  365. package/dist/assets/improve-strategies/thorough.json +0 -49
  366. package/dist/assets/prompts/retrieval-relevance-judge.md +0 -6
  367. package/dist/assets/tasks/improve/akm-improve-catchup.yml +0 -6
  368. package/dist/assets/tasks/improve/akm-improve-frequent.yml +0 -4
  369. package/dist/assets/tasks/improve/akm-improve-nightly.yml +0 -4
  370. package/dist/cli/retired-commands.js +0 -118
  371. package/dist/commands/improve/retrieval-gate.js +0 -132
  372. package/dist/commands/tasks/validate.js +0 -176
  373. package/dist/core/config/legacy-source-shape-shim.js +0 -117
  374. package/dist/indexer/feedback/utility-policy.js +0 -75
  375. package/dist/integrations/harnesses/ids.js +0 -28
  376. package/dist/tasks/source/task-source-v3-frozen.js +0 -424
  377. package/dist/tasks/source/task-to-v4.js +0 -863
  378. package/dist/workflows/exec/worktree.js +0 -372
  379. package/dist/workflows/freeze/child-output-references.js +0 -83
  380. package/dist/workflows/freeze/identity.js +0 -22
  381. package/dist/workflows/freeze/targets/script.js +0 -50
  382. package/dist/workflows/freeze/targets/task.js +0 -124
  383. package/dist/workflows/github-yaml.js +0 -506
  384. package/dist/workflows/runtime/run-outputs.js +0 -80
@@ -16,6 +16,17 @@
16
16
  * 'opencode-sdk'`). It is the dispatch path for SDK runner specs; it exposes
17
17
  * no native session logs of its own (`capabilities.sessionLogs = false`).
18
18
  *
19
+ * ## Two OpenCode majors, one runner (#1049)
20
+ *
21
+ * This file owns what both majors share: the managed `opencode serve` child
22
+ * (spawn, port, registry, cleanup, {@link closeServer}), the child environment,
23
+ * per-workspace isolation, deadlines, abort handling and result shaping. The
24
+ * per-major wire protocol is an adapter behind `./wire.ts`, chosen once per
25
+ * dispatch from the major the engine's binary reports
26
+ * (`../opencode/version.ts`); the major is part of the server registry key.
27
+ * Where the sections below name an OpenCode 1 wire shape (`query.directory`,
28
+ * the prompt body), `v2-adapter.ts` has the OpenCode 2 equivalent.
29
+ *
19
30
  * ## Sessions are kept (#1100)
20
31
  *
21
32
  * One session is created per dispatch and is NEVER deleted: it stays in
@@ -84,7 +95,7 @@
84
95
  * until the child ACTUALLY exits — and a real `opencode serve` (a live HTTP
85
96
  * server with provider children) can outlive SIGTERM long enough to hang the
86
97
  * caller indefinitely. {@link createManagedOpencode} therefore owns the spawn
87
- * (the SDK package is used only for `createOpencodeClient`).
98
+ * (the SDK package is used only for its client).
88
99
  *
89
100
  * Owning the spawn changes the LIFECYCLE, not the REQUIREMENT: the SDK's
90
101
  * `createOpencodeServer` is itself a `spawn("opencode", ["serve", ...])`, and
@@ -102,11 +113,14 @@
102
113
  */
103
114
  import { spawn } from "node:child_process";
104
115
  import { createHash } from "node:crypto";
105
- import { isRecord } from "../../../core/common.js";
106
116
  import { COMMON_SPAWN_ENV_PASSTHROUGH, OPENCODE_ENV_PASSTHROUGH, spawnEnvNamesFor } from "../../../core/spawn-env.js";
107
117
  import { DEFAULT_AGENT_TIMEOUT_MS } from "../../agent/config.js";
108
118
  import { opencodeInferenceConfig } from "../opencode/model-config.js";
109
119
  import { MODEL_WORK_OPENCODE_AGENT, modelWorkOpencodeConfig, modelWorkPluginEnv } from "../opencode/model-work-agent.js";
120
+ import { detectOpencodeMajor } from "../opencode/version.js";
121
+ import { V1_ADAPTER } from "./v1-adapter.js";
122
+ import { V2_ADAPTER } from "./v2-adapter.js";
123
+ import { parseReadiness, } from "./wire.js";
110
124
  // Server registry — one server per complete server-material signature. Caller
111
125
  // deadlines race the shared promise independently; they never become startup
112
126
  // configuration inherited by later callers.
@@ -299,9 +313,10 @@ export function buildSdkConfig(profile, llmConfig, modelWork = false, requestInf
299
313
  }
300
314
  return modelWork ? { ...sdkConfig, ...modelWorkOpencodeConfig(agentOptions) } : sdkConfig;
301
315
  }
302
- /** Digest the executable and exact environment received by the child. */
303
- function serverRegistryKey(profile, env) {
304
- const material = { bin: profile.bin, env };
316
+ /** Digest the OpenCode major, the executable and the exact environment received by the child. */
317
+ function serverRegistryKey(adapter, profile, env) {
318
+ // The major is part of the identity: a v1 and a v2 server never share an entry.
319
+ const material = { major: adapter.major, bin: profile.bin, env };
305
320
  return createHash("sha256")
306
321
  .update(JSON.stringify(canonicalize(material)))
307
322
  .digest("hex");
@@ -425,13 +440,13 @@ export function __setServeCommand(argv) {
425
440
  * - handshake failure → the child is killed and unref'ed before rejecting.
426
441
  */
427
442
  async function createManagedOpencode(options) {
428
- const { createOpencodeClient } = (await import("@opencode-ai/sdk").catch(() => {
429
- throw new Error("OpenCode SDK not available. Install @opencode-ai/sdk or configure a CLI agent instead.");
430
- }));
443
+ const { adapter } = options;
431
444
  const port = options.port ?? DEFAULT_SDK_PORT;
432
- const argv = _serveCommand ?? [options.bin ?? "opencode", "serve", "--hostname=127.0.0.1", `--port=${port}`];
445
+ const argv = _serveCommand ?? adapter.serveArgv(options.bin ?? "opencode", port);
446
+ // The adapter may add to the child's environment (V2: the server password akm chose).
447
+ const authorization = adapter.authorize();
433
448
  const proc = spawn(argv[0], argv.slice(1), {
434
- env: options.env,
449
+ env: { ...options.env, ...authorization.env },
435
450
  stdio: ["ignore", "pipe", "pipe"],
436
451
  });
437
452
  let closeStarted = false;
@@ -516,15 +531,14 @@ async function createManagedOpencode(options) {
516
531
  const onStdoutData = (chunk) => {
517
532
  output += chunk.toString();
518
533
  for (const line of output.split("\n")) {
519
- if (line.startsWith("opencode server listening")) {
520
- const match = line.match(/on\s+(https?:\/\/\S+)/);
521
- if (!match?.[1]) {
522
- fail(new Error(`Failed to parse the OpenCode server url from: ${line}`));
523
- return;
524
- }
525
- succeed(match[1]);
526
- return;
527
- }
534
+ const verdict = parseReadiness(line, adapter.major);
535
+ if (!verdict)
536
+ continue;
537
+ if ("error" in verdict)
538
+ fail(new Error(verdict.error));
539
+ else
540
+ succeed(verdict.url);
541
+ return;
528
542
  }
529
543
  };
530
544
  const onStderrData = (chunk) => {
@@ -553,62 +567,18 @@ async function createManagedOpencode(options) {
553
567
  proc.stdout?.destroy();
554
568
  proc.stderr?.destroy();
555
569
  proc.unref();
556
- const client = createOpencodeClient({ baseUrl: url });
557
- client.event = { subscribe: (args) => subscribeEvents(url, args) };
558
- return { client, server: { close: closeManaged } };
559
- }
560
- /**
561
- * Subscribe to the server's event stream. The SDK's own `event.subscribe`
562
- * cannot be closed safely: aborting it leaves an unhandled `AbortError`
563
- * rejection (from its un-awaited `reader.cancel()`), which akm's global
564
- * handler turns into a process exit. This reader ends quietly on abort.
565
- */
566
- async function subscribeEvents(baseUrl, args) {
567
- const eventUrl = new URL("/event", baseUrl);
568
- if (args.query?.directory)
569
- eventUrl.searchParams.set("directory", args.query.directory);
570
- const response = await fetch(eventUrl, { signal: args.signal, headers: { accept: "text/event-stream" } });
571
- if (!response.ok || !response.body)
572
- throw new Error(`OpenCode event stream failed: HTTP ${response.status}`);
573
- const reader = response.body.getReader();
574
- async function* stream() {
575
- const decoder = new TextDecoder();
576
- let buffer = "";
577
- try {
578
- while (true) {
579
- const { done, value } = await reader.read();
580
- if (done)
581
- return;
582
- buffer += decoder.decode(value, { stream: true });
583
- const frames = buffer.split("\n\n");
584
- buffer = frames.pop() ?? "";
585
- for (const frame of frames) {
586
- const data = frame
587
- .split("\n")
588
- .filter((line) => line.startsWith("data:"))
589
- .map((line) => line.replace(/^data:\s*/, ""))
590
- .join("\n");
591
- if (!data)
592
- continue;
593
- try {
594
- yield JSON.parse(data);
595
- }
596
- catch {
597
- /* not JSON: not an event we act on */
598
- }
599
- }
600
- }
601
- }
602
- catch (err) {
603
- if (!args.signal.aborted)
604
- throw err;
605
- }
570
+ try {
571
+ return { client: await adapter.connect(url, authorization.credentials), server: { close: closeManaged } };
572
+ }
573
+ catch (err) {
574
+ closeManaged();
575
+ throw err;
606
576
  }
607
- return { stream: stream() };
608
577
  }
609
- async function startServer(profile, sdkConfig, env, registryKey, startupSignal) {
578
+ async function startServer(adapter, profile, sdkConfig, env, registryKey, startupSignal) {
610
579
  const factory = _serverFactory ?? createManagedOpencode;
611
580
  const options = {
581
+ adapter,
612
582
  bin: profile.bin,
613
583
  ...(Object.keys(sdkConfig).length > 0 ? { config: sdkConfig } : {}),
614
584
  env,
@@ -651,17 +621,17 @@ async function startServer(profile, sdkConfig, env, registryKey, startupSignal)
651
621
  * start (the registry stores the in-flight promise). A failed start is
652
622
  * evicted so the next call can retry instead of caching the error forever.
653
623
  */
654
- function getOrStartServer(profile, llmConfig, env, envSource = process.env, modelWork = false, inference) {
624
+ function getOrStartServer(adapter, profile, llmConfig, env, envSource = process.env, modelWork = false, inference) {
655
625
  if (_testServer)
656
626
  return { promise: Promise.resolve(_testServer), release() { } };
657
627
  const sdkConfig = buildSdkConfig(profile, llmConfig, modelWork, inference);
658
628
  const serverEnv = buildServerEnv(profile, sdkConfig, env, envSource, modelWork);
659
- const key = serverRegistryKey(profile, serverEnv);
629
+ const key = serverRegistryKey(adapter, profile, serverEnv);
660
630
  let entry = _servers.get(key);
661
631
  if (!entry) {
662
632
  const controller = new AbortController();
663
633
  entry = {
664
- promise: startServer(profile, sdkConfig, serverEnv, key, controller.signal),
634
+ promise: startServer(adapter, profile, sdkConfig, serverEnv, key, controller.signal),
665
635
  controller,
666
636
  waiters: 0,
667
637
  };
@@ -699,25 +669,6 @@ function getOrStartServer(profile, llmConfig, env, envSource = process.env, mode
699
669
  },
700
670
  };
701
671
  }
702
- /**
703
- * Extract best-effort token usage from a prompt response. Only numeric
704
- * fields the server actually reported are copied; returns undefined when
705
- * nothing usable is present (older servers, test fakes).
706
- */
707
- function extractUsage(info) {
708
- const tokens = info?.tokens;
709
- if (!tokens)
710
- return undefined;
711
- const usage = {};
712
- if (typeof tokens.input === "number" && Number.isFinite(tokens.input))
713
- usage.inputTokens = tokens.input;
714
- if (typeof tokens.output === "number" && Number.isFinite(tokens.output))
715
- usage.outputTokens = tokens.output;
716
- if (typeof tokens.reasoning === "number" && Number.isFinite(tokens.reasoning)) {
717
- usage.reasoningTokens = tokens.reasoning;
718
- }
719
- return Object.keys(usage).length > 0 ? usage : undefined;
720
- }
721
672
  const SDK_OPERATION_TIMED_OUT = Symbol("opencode-sdk-operation-timeout");
722
673
  const SDK_OPERATION_ABORTED = Symbol("opencode-sdk-operation-aborted");
723
674
  async function raceSdkOperation(operation, opts) {
@@ -753,29 +704,6 @@ async function raceSdkOperation(operation, opts) {
753
704
  function errorText(err) {
754
705
  return err instanceof Error ? err.message : String(err);
755
706
  }
756
- /**
757
- * Map an SDK `{ error }` result or a reply's `info.error` onto a failure
758
- * (#1015). Both are opencode NamedErrors, `{ name, data: { message } }`. An
759
- * aborted message is `aborted`, a reply cut off at the output limit is
760
- * `parse_error`, and every other error (auth, API, unknown, an HTTP error
761
- * body) is `non_zero_exit`.
762
- */
763
- function sdkErrorFailure(error) {
764
- if (!isRecord(error) || typeof error.name !== "string") {
765
- return { reason: "non_zero_exit", message: typeof error === "string" ? error : JSON.stringify(error) };
766
- }
767
- const detail = isRecord(error.data) ? error.data.message : undefined;
768
- const message = typeof detail === "string" ? `${error.name}: ${detail}` : error.name;
769
- if (error.name === "MessageAbortedError")
770
- return { reason: "aborted", message };
771
- if (error.name === "MessageOutputLengthError")
772
- return { reason: "parse_error", message };
773
- return { reason: "non_zero_exit", message };
774
- }
775
- /** Stop a server-side session that the dispatch has given up on, so it stops calling the model. */
776
- function abortSessionBestEffort(client, sessionId, query) {
777
- void client.session.abort?.({ path: { id: sessionId }, ...(query ? { query } : {}) }).catch(() => { });
778
- }
779
707
  /**
780
708
  * Answer every OpenCode permission request of the dispatch's session (and of
781
709
  * the sub-sessions it spawns) with "reject", once each. This is what a
@@ -785,78 +713,52 @@ function abortSessionBestEffort(client, sessionId, query) {
785
713
  * model as a tool error it can work around. Each request and answer is
786
714
  * appended to `notes`. The same stream reports OpenCode's retries (#1108):
787
715
  * each is noted, and one caused by a usage limit, or due after `deadline`,
788
- * ends the run through `stopForRetry` instead of a silent wait. `ready` (absent when the client has no event surface)
716
+ * ends the run through `stopForRetry` instead of a silent wait. `ready`
789
717
  * settles once the subscription is open and never rejects; `stop` closes it.
718
+ * The wire format (event shapes, the reject call) is the adapter's.
790
719
  */
791
- function rejectPermissionRequests(client, sessionId, query, notes, deadline, stopForRetry) {
792
- const subscribe = client.event?.subscribe;
793
- const reply = client.postSessionIdPermissionsPermissionId;
720
+ function rejectPermissionRequests(adapter, client, sessionId, spec, notes, deadline, stopForRetry) {
794
721
  const controller = new AbortController();
795
722
  const stop = () => controller.abort();
796
- if (!subscribe || !reply)
723
+ if (adapter.canWatch?.(client) === false)
797
724
  return { stop };
798
725
  const sessions = new Set([sessionId]);
799
726
  const answered = new Set();
800
727
  const consume = async (stream) => {
801
- for await (const event of stream) {
802
- if (!isRecord(event) || !isRecord(event.properties))
728
+ for await (const raw of stream) {
729
+ const event = adapter.decodeEvent(raw);
730
+ if (!event)
803
731
  continue;
804
- const props = event.properties;
805
- if (event.type === "session.created" && isRecord(props.info)) {
806
- const { id, parentID } = props.info;
807
- if (typeof id === "string" && typeof parentID === "string" && sessions.has(parentID))
808
- sessions.add(id);
732
+ if (event.kind === "session") {
733
+ if (event.parentId !== undefined && sessions.has(event.parentId))
734
+ sessions.add(event.id);
809
735
  continue;
810
736
  }
811
- if (event.type === "session.status") {
812
- const { sessionID, status } = props;
813
- if (typeof sessionID !== "string" || !sessions.has(sessionID) || !isRecord(status) || status.type !== "retry") {
814
- continue;
815
- }
816
- const attempt = typeof status.attempt === "number" ? status.attempt : "unknown";
817
- const message = typeof status.message === "string" ? status.message : "OpenCode is retrying";
818
- const next = typeof status.next === "number" ? status.next : undefined;
819
- const retryAt = next === undefined ? "unknown time" : new Date(next).toISOString();
820
- // `action` is not present in the SDK's retry type yet, but current
821
- // OpenCode servers include it for provider/account limits.
822
- const action = isRecord(status.action) ? status.action : undefined;
823
- const provider = typeof action?.provider === "string" ? action.provider : undefined;
824
- notes.push(`OpenCode retry attempt ${attempt}${provider ? ` (${provider})` : ""}: ${message}; retrying at ${retryAt}`);
825
- if (action?.reason === "account_rate_limit") {
826
- stopForRetry(`OpenCode provider limit stopped this run${provider ? ` (${provider})` : ""}: ${message}; reset at ${retryAt}`);
737
+ if (!sessions.has(event.sessionId))
738
+ continue;
739
+ if (event.kind === "retry") {
740
+ const retryAt = event.next === undefined ? "unknown time" : new Date(event.next).toISOString();
741
+ notes.push(`OpenCode retry attempt ${event.attempt ?? "unknown"}${event.provider ? ` (${event.provider})` : ""}: ${event.message}; retrying at ${retryAt}`);
742
+ if (event.accountLimit) {
743
+ stopForRetry(`OpenCode provider limit stopped this run${event.provider ? ` (${event.provider})` : ""}: ${event.message}; reset at ${retryAt}`);
827
744
  }
828
- else if (next !== undefined && deadline !== null && next > deadline) {
829
- stopForRetry(`OpenCode's next retry (${retryAt}) is after this run's deadline: ${message}`);
745
+ else if (event.next !== undefined && deadline !== null && event.next > deadline) {
746
+ stopForRetry(`OpenCode's next retry (${retryAt}) is after this run's deadline: ${event.message}`);
830
747
  }
831
748
  continue;
832
749
  }
833
- // `permission.asked` (OpenCode >= 1.3) / `permission.updated` (older).
834
- if (event.type !== "permission.asked" && event.type !== "permission.updated")
750
+ if (answered.has(event.requestId))
835
751
  continue;
836
- const { id, sessionID } = props;
837
- if (typeof id !== "string" || typeof sessionID !== "string")
838
- continue;
839
- if (!sessions.has(sessionID) || answered.has(id))
840
- continue;
841
- answered.add(id);
842
- const patterns = Array.isArray(props.patterns) ? props.patterns : props.pattern ? [props.pattern] : [];
843
- notes.push(`permission requested: ${String(props.permission ?? props.type ?? "unknown")} (${patterns.join(", ")}); auto-rejecting`);
844
- reply
845
- .call(client, {
846
- path: { id: sessionID, permissionID: id },
847
- body: { response: "reject" },
848
- ...(query ? { query } : {}),
849
- })
850
- .then((r) => {
851
- if (r.error)
852
- notes.push(`permission reply for ${id} failed: ${JSON.stringify(r.error)}`);
853
- })
854
- .catch((err) => notes.push(`permission reply for ${id} failed: ${errorText(err)}`));
752
+ answered.add(event.requestId);
753
+ notes.push(`permission requested: ${event.description}; auto-rejecting`);
754
+ adapter.rejectPermission(client, event, spec).catch((err) => {
755
+ notes.push(`permission reply for ${event.requestId} failed: ${errorText(err)}`);
756
+ });
855
757
  }
856
758
  };
857
- const ready = subscribe
858
- .call(client.event, { ...(query ? { query } : {}), signal: controller.signal })
859
- .then(({ stream }) => {
759
+ const ready = adapter
760
+ .subscribe(client, spec, controller.signal)
761
+ .then((stream) => {
860
762
  void consume(stream).catch((err) => {
861
763
  if (!controller.signal.aborted)
862
764
  notes.push(`permission event stream ended: ${errorText(err)}`);
@@ -867,6 +769,11 @@ function rejectPermissionRequests(client, sessionId, query, notes, deadline, sto
867
769
  });
868
770
  return { ready, stop };
869
771
  }
772
+ const ADAPTERS = { 1: V1_ADAPTER, 2: V2_ADAPTER };
773
+ /** The wire adapter for the OpenCode major the engine's binary reports. */
774
+ function adapterFor(profile) {
775
+ return ADAPTERS[detectOpencodeMajor(profile.bin).major];
776
+ }
870
777
  function abortedBeforeSdkStart(profile) {
871
778
  return {
872
779
  ok: false,
@@ -888,12 +795,13 @@ export async function runOpencodeSdk(profile, prompt, opts = {}, llmConfig) {
888
795
  if (opts.signal?.aborted)
889
796
  return abortedBeforeSdkStart(profile);
890
797
  const modelWork = opts.dispatch?.modelWork === true;
798
+ const adapter = adapterFor(profile);
891
799
  let client;
892
800
  if (_testServer) {
893
801
  client = _testServer.client;
894
802
  }
895
803
  else {
896
- const startupHandle = getOrStartServer(profile, llmConfig, opts.env, opts.envSource, modelWork, opts.dispatch?.inference);
804
+ const startupHandle = getOrStartServer(adapter, profile, llmConfig, opts.env, opts.envSource, modelWork, opts.dispatch?.inference);
897
805
  try {
898
806
  const startup = await raceSdkOperation(startupHandle.promise, {
899
807
  timeoutMs: remainingTimeoutMs(),
@@ -945,10 +853,23 @@ export async function runOpencodeSdk(profile, prompt, opts = {}, llmConfig) {
945
853
  // local-model endpoint or wedged server could block the caller indefinitely.
946
854
  // The same absolute deadline covers server startup, session creation, and
947
855
  // prompting. null disables every dispatch timer.
948
- // Per-call working directory (module doc): forwarded as the SDK's
949
- // `query.directory` on every session call, so worktree-isolated units run
950
- // in their own checkout without a per-cwd server.
951
- const query = opts.cwd ? { directory: opts.cwd } : undefined;
856
+ // Per-call working directory (module doc): the adapter scopes the session to
857
+ // it, so worktree-isolated units run in their own checkout without a
858
+ // per-cwd server.
859
+ // Forward the exact native agent selector, systemPrompt, and tools from the abstract
860
+ // dispatch request. Both were once accepted on AgentDispatchRequest but silently dropped
861
+ // on the SDK path (#564). Model work runs the confined agent its server config defines;
862
+ // its tools are that agent's.
863
+ const dispatch = opts.dispatch;
864
+ const agent = modelWork ? MODEL_WORK_OPENCODE_AGENT : dispatch?.agent;
865
+ const system = dispatch?.systemPrompt;
866
+ const tools = toolsToSdkAllowlist(dispatch?.tools);
867
+ const spec = {
868
+ ...(opts.cwd ? { directory: opts.cwd } : {}),
869
+ ...(agent ? { agent } : {}),
870
+ ...(system ? { system } : {}),
871
+ ...(tools ? { tools } : {}),
872
+ };
952
873
  // One session per call — do NOT reuse (history accumulates, token costs grow).
953
874
  // Session creation is startup plumbing, so failures map to spawn_failed rather
954
875
  // than bubbling out as a generic workflow dispatch exception.
@@ -962,7 +883,7 @@ export async function runOpencodeSdk(profile, prompt, opts = {}, llmConfig) {
962
883
  const abortSignal = runController.signal;
963
884
  let sessionId;
964
885
  try {
965
- const created = await raceSdkOperation(client.session.create({ body: { title: "akm" }, ...(query ? { query } : {}) }), {
886
+ const created = await raceSdkOperation(adapter.createSession(client, spec), {
966
887
  timeoutMs: remainingTimeoutMs(),
967
888
  setTimeoutFn: setTimeoutImpl,
968
889
  clearTimeoutFn: clearTimeoutImpl,
@@ -990,7 +911,7 @@ export async function runOpencodeSdk(profile, prompt, opts = {}, llmConfig) {
990
911
  error: `opencode-sdk agent "${profile.name}" timed out creating a session after ${timeoutMs}ms`,
991
912
  };
992
913
  }
993
- sessionId = created.data?.id;
914
+ sessionId = created;
994
915
  }
995
916
  catch (err) {
996
917
  return {
@@ -1014,27 +935,11 @@ export async function runOpencodeSdk(profile, prompt, opts = {}, llmConfig) {
1014
935
  error: "Failed to create OpenCode session",
1015
936
  };
1016
937
  }
1017
- // Forward the exact native agent selector, systemPrompt, and tools from the abstract
1018
- // dispatch request. Both were previously accepted on AgentDispatchRequest but
1019
- // silently dropped on the SDK path, so SDK-mode dispatch ignored agent-asset
1020
- // system prompts and tool policies entirely (the CLI path honours both).
1021
- // Model work runs the confined agent its server config defines; its tools are that agent's.
1022
- const dispatch = opts.dispatch;
1023
- const agent = modelWork ? MODEL_WORK_OPENCODE_AGENT : dispatch?.agent;
1024
- const system = dispatch?.systemPrompt;
1025
- const tools = toolsToSdkAllowlist(dispatch?.tools);
1026
- const body = { parts: [{ type: "text", text: prompt }] };
1027
- if (agent)
1028
- body.agent = agent;
1029
- if (system)
1030
- body.system = system;
1031
- if (tools)
1032
- body.tools = tools;
1033
938
  let result;
1034
939
  // Subscribed before the prompt so no request can be missed; closed in `finally`.
1035
940
  const permissionNotes = [];
1036
941
  let retryFailure;
1037
- const permissions = rejectPermissionRequests(client, sessionId, query, permissionNotes, deadline, (failure) => {
942
+ const permissions = rejectPermissionRequests(adapter, client, sessionId, spec, permissionNotes, deadline, (failure) => {
1038
943
  retryFailure ??= failure;
1039
944
  runController.abort();
1040
945
  });
@@ -1048,7 +953,7 @@ export async function runOpencodeSdk(profile, prompt, opts = {}, llmConfig) {
1048
953
  signal: abortSignal,
1049
954
  });
1050
955
  }
1051
- const prompted = await raceSdkOperation(client.session.prompt({ path: { id: sessionId }, body, ...(query ? { query } : {}) }), {
956
+ const prompted = await raceSdkOperation(adapter.prompt(client, sessionId, prompt, spec, abortSignal), {
1052
957
  timeoutMs: remainingTimeoutMs(),
1053
958
  setTimeoutFn: setTimeoutImpl,
1054
959
  clearTimeoutFn: clearTimeoutImpl,
@@ -1056,7 +961,7 @@ export async function runOpencodeSdk(profile, prompt, opts = {}, llmConfig) {
1056
961
  });
1057
962
  // A session the dispatch stops early is aborted on the server too.
1058
963
  if (prompted === SDK_OPERATION_ABORTED || prompted === SDK_OPERATION_TIMED_OUT) {
1059
- abortSessionBestEffort(client, sessionId, query);
964
+ adapter.abort(client, sessionId, spec);
1060
965
  }
1061
966
  if (prompted === SDK_OPERATION_ABORTED && retryFailure) {
1062
967
  result = {
@@ -1095,16 +1000,8 @@ export async function runOpencodeSdk(profile, prompt, opts = {}, llmConfig) {
1095
1000
  };
1096
1001
  }
1097
1002
  else {
1098
- const parts = prompted.data?.parts ?? [];
1099
- // The last text part is the answer; earlier ones narrate the steps before it.
1100
- const stdout = parts.filter((p) => p.type === "text").at(-1)?.text ?? "";
1101
- // Token accounting from the AssistantMessage (previously discarded) —
1102
- // the seam that makes workflow budget.maxTokens meterable on the
1103
- // default sdk runner.
1104
- const usage = extractUsage(prompted.data?.info);
1105
- const sdkError = prompted.error ?? prompted.data?.info?.error;
1106
- if (sdkError) {
1107
- const failure = sdkErrorFailure(sdkError);
1003
+ const { text: stdout, usage, failure } = prompted;
1004
+ if (failure) {
1108
1005
  result = {
1109
1006
  ok: false,
1110
1007
  stdout,
@@ -1145,6 +1042,8 @@ export async function runOpencodeSdk(profile, prompt, opts = {}, llmConfig) {
1145
1042
  finally {
1146
1043
  permissions.stop();
1147
1044
  callerSignal?.removeEventListener("abort", abortForCaller);
1045
+ // The dispatch is over: cancel any request still in flight.
1046
+ runController.abort();
1148
1047
  }
1149
1048
  if (permissionNotes.length > 0) {
1150
1049
  result.stderr = [result.stderr, ...permissionNotes].filter(Boolean).join("\n");