akm-cli 0.10.261012-beta → 0.10.261014-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 (518) hide show
  1. package/CHANGELOG.md +710 -3
  2. package/README.md +15 -0
  3. package/SECURITY.md +11 -10
  4. package/STABILITY.md +47 -51
  5. package/dist/assets/hints/cli-hints-full.md +21 -19
  6. package/dist/assets/hints/cli-hints-short.md +3 -4
  7. package/dist/assets/opencode/akm-plugin.js +177 -0
  8. package/dist/assets/stash-skeleton/README.md +1 -1
  9. package/dist/assets/tasks/core/improve.yml +1 -1
  10. package/dist/assets/tasks/improve/akm-improve-consolidate.yml +1 -1
  11. package/dist/assets/ui/config.js +27 -10
  12. package/dist/assets/workflows/workflow-template.md +2 -2
  13. package/dist/cli/clack.js +3 -1
  14. package/dist/cli/selection.js +33 -0
  15. package/dist/cli/shared.js +14 -1
  16. package/dist/cli/unknown-flags.js +6 -37
  17. package/dist/cli.js +69 -48
  18. package/dist/commands/agent/agent-dispatch.js +17 -25
  19. package/dist/commands/agent/contribute-cli.js +9 -8
  20. package/dist/commands/command/command-cli.js +4 -8
  21. package/dist/commands/command/command-execution.js +25 -39
  22. package/dist/commands/command/execution-source-loader.js +10 -14
  23. package/dist/commands/completions.js +1 -1
  24. package/dist/commands/config-cli.js +14 -5
  25. package/dist/commands/env/child-env.js +12 -14
  26. package/dist/commands/env/env-binding.js +47 -58
  27. package/dist/commands/env/env-cli.js +22 -24
  28. package/dist/commands/env/env.js +10 -58
  29. package/dist/commands/env/secret-cli.js +11 -29
  30. package/dist/commands/env/secret.js +3 -10
  31. package/dist/commands/health/checks.js +10 -849
  32. package/dist/commands/health/connections-and-harnesses-check.js +109 -0
  33. package/dist/commands/health/egress.js +3 -3
  34. package/dist/commands/health/html-report.js +9 -10
  35. package/dist/commands/health/plugin-staleness.js +18 -11
  36. package/dist/commands/health/report-view-model.js +16 -12
  37. package/dist/commands/health/scheduler-binary.js +1 -1
  38. package/dist/commands/health/semantic-search-check.js +85 -0
  39. package/dist/commands/health/type-directory-check.js +0 -3
  40. package/dist/commands/health.js +30 -42
  41. package/dist/commands/improve/consolidate/pair-pass.js +10 -25
  42. package/dist/commands/improve/consolidate.js +10 -15
  43. package/dist/commands/improve/distill.js +5 -17
  44. package/dist/commands/improve/eligibility.js +1 -3
  45. package/dist/commands/improve/execution.js +37 -40
  46. package/dist/commands/improve/extract-cli.js +6 -11
  47. package/dist/commands/improve/extract-prompt.js +2 -2
  48. package/dist/commands/improve/extract.js +67 -97
  49. package/dist/commands/improve/improve-cli.js +22 -128
  50. package/dist/commands/improve/improve-report.js +1 -1
  51. package/dist/commands/improve/improve-strategies.js +25 -108
  52. package/dist/commands/improve/improve.js +10 -14
  53. package/dist/commands/improve/loop-stages.js +3 -0
  54. package/dist/commands/improve/memory/memory-improve.js +1 -1
  55. package/dist/commands/improve/preparation.js +8 -13
  56. package/dist/commands/improve/reflect.js +203 -332
  57. package/dist/commands/improve/retrieval-scope.js +1 -1
  58. package/dist/commands/improve/session-asset.js +3 -2
  59. package/dist/commands/improve/stage.js +87 -115
  60. package/dist/commands/lint/base-linter.js +3 -3
  61. package/dist/commands/lint/env-key-rules.js +7 -6
  62. package/dist/commands/lint/index.js +3 -3
  63. package/dist/commands/models-cli.js +103 -63
  64. package/dist/commands/proposal/drain.js +26 -39
  65. package/dist/commands/proposal/proposal-cli.js +14 -18
  66. package/dist/commands/proposal/propose-cli.js +4 -2
  67. package/dist/commands/proposal/propose.js +37 -64
  68. package/dist/commands/proposal/repository.js +17 -17
  69. package/dist/commands/proposal/validators/proposal-validators.js +3 -6
  70. package/dist/commands/read/curate.js +10 -6
  71. package/dist/commands/read/registry-search.js +2 -48
  72. package/dist/commands/read/search-cli.js +1 -8
  73. package/dist/commands/read/search.js +5 -6
  74. package/dist/commands/read/show.js +6 -29
  75. package/dist/commands/remember.js +25 -40
  76. package/dist/commands/sources/add-cli.js +8 -63
  77. package/dist/commands/sources/bundle-cli.js +8 -9
  78. package/dist/commands/sources/bundle-config-ops.js +2 -2
  79. package/dist/commands/sources/info.js +12 -1
  80. package/dist/commands/sources/init.js +1 -1
  81. package/dist/commands/sources/installed-stashes.js +119 -63
  82. package/dist/commands/sources/migration-help.js +1 -1
  83. package/dist/commands/sources/plugin-upgrade.js +8 -15
  84. package/dist/commands/sources/schema-repair.js +4 -10
  85. package/dist/commands/sources/source-add.js +2 -2
  86. package/dist/commands/sources/source-clone.js +31 -7
  87. package/dist/commands/sources/source-manage.js +4 -4
  88. package/dist/commands/targets.js +175 -0
  89. package/dist/commands/tasks/explain.js +104 -69
  90. package/dist/commands/tasks/tasks-cli.js +9 -11
  91. package/dist/commands/tasks/tasks.js +75 -97
  92. package/dist/commands/ui/api.js +11 -3
  93. package/dist/commands/ui/redact.js +5 -31
  94. package/dist/commands/ui/workspace-actions.js +1 -1
  95. package/dist/commands/workflow/plan.js +48 -9
  96. package/dist/commands/workflow-cli.js +40 -45
  97. package/dist/core/adapter/adapters/agent-skills-adapter.js +10 -11
  98. package/dist/core/adapter/adapters/akm-adapter.js +36 -41
  99. package/dist/core/adapter/adapters/akm-lint.js +10 -12
  100. package/dist/core/adapter/adapters/akm-metadata.js +2 -2
  101. package/dist/core/adapter/adapters/akm-task-adapter.js +8 -9
  102. package/dist/core/adapter/adapters/akm-workflow-adapter.js +5 -5
  103. package/dist/core/adapter/adapters/claude-adapter.js +1 -1
  104. package/dist/core/adapter/adapters/dotenv-adapter.js +7 -6
  105. package/dist/core/adapter/adapters/generic-files-adapter.js +5 -5
  106. package/dist/core/adapter/adapters/index.js +3 -4
  107. package/dist/core/adapter/adapters/llm-wiki-adapter.js +12 -14
  108. package/dist/core/adapter/adapters/okf-adapter.js +8 -10
  109. package/dist/core/adapter/adapters/opencode-adapter.js +1 -1
  110. package/dist/core/adapter/adapters/shared.js +3 -3
  111. package/dist/core/adapter/adapters/tool-dir-shared.js +7 -25
  112. package/dist/core/adapter/adapters/website-snapshot-adapter.js +3 -3
  113. package/dist/core/adapter/detect-adapter.js +1 -1
  114. package/dist/core/adapter/execution-source.js +13 -35
  115. package/dist/core/adapter/registry.js +1 -1
  116. package/dist/core/adapter/validate-context.js +2 -4
  117. package/dist/core/asset/asset-placement.js +1 -1
  118. package/dist/core/asset/asset-ref.js +3 -3
  119. package/dist/core/asset/resolve-ref.js +5 -0
  120. package/dist/core/bundle-rename.js +12 -4
  121. package/dist/core/closest-match.js +37 -0
  122. package/dist/core/common.js +37 -57
  123. package/dist/core/config/config-io.js +26 -18
  124. package/dist/core/config/config-schema.js +19 -106
  125. package/dist/core/config/config-sources.js +3 -3
  126. package/dist/core/config/config-types.js +4 -4
  127. package/dist/core/config/config-walker.js +50 -77
  128. package/dist/core/config/config.js +438 -109
  129. package/dist/core/config/convert-engine-references.js +114 -0
  130. package/dist/core/config/convert-engines-shared.js +40 -0
  131. package/dist/core/config/convert-engines.js +300 -0
  132. package/dist/core/config/convert-models-overlay.js +137 -0
  133. package/dist/core/config/credentials.js +304 -0
  134. package/dist/core/config/engine-semantics.js +3 -3
  135. package/dist/core/config/migrate-keys.js +222 -0
  136. package/dist/core/config/model-aliases.js +37 -0
  137. package/dist/core/config/models-file.js +34 -0
  138. package/dist/core/config/retired-engines.js +53 -0
  139. package/dist/core/config/schema/connections.js +41 -0
  140. package/dist/core/config/schema/embedding.js +2 -2
  141. package/dist/core/config/schema/harnesses.js +41 -0
  142. package/dist/core/config/schema/improve-processes.js +9 -28
  143. package/dist/core/config/schema/improve.js +36 -1
  144. package/dist/core/config/schema/index-config.js +18 -20
  145. package/dist/core/config/schema/primitives.js +42 -17
  146. package/dist/core/config/schema/search.js +6 -11
  147. package/dist/core/config/schema/sources-bundles.js +9 -9
  148. package/dist/core/config/schema/workflow.js +2 -6
  149. package/dist/core/config/unusable-entries.js +66 -0
  150. package/dist/core/content-safety.js +3 -6
  151. package/dist/core/endpoint-url.js +47 -0
  152. package/dist/core/env-secret-ref.js +84 -73
  153. package/dist/core/errors.js +10 -16
  154. package/dist/core/extra-params.js +3 -3
  155. package/dist/core/improve-result.js +8 -9
  156. package/dist/core/json-schema.js +1 -1
  157. package/dist/core/lesson-lint.js +1 -1
  158. package/dist/core/llm-inference.js +80 -0
  159. package/dist/core/parse.js +2 -2
  160. package/dist/core/paths.js +33 -10
  161. package/dist/core/recognition-util.js +8 -10
  162. package/dist/core/redaction.js +94 -55
  163. package/dist/core/ref-token.js +82 -0
  164. package/dist/core/secret-value.js +14 -0
  165. package/dist/core/state/migrations.js +17 -22
  166. package/dist/core/structured.js +2 -68
  167. package/dist/core/subprocess.js +63 -22
  168. package/dist/core/type-presentation.js +10 -14
  169. package/dist/core/write-source.js +20 -4
  170. package/dist/execution/input-contract.js +3 -6
  171. package/dist/execution/notices.js +49 -0
  172. package/dist/execution/resolved-request.js +24 -40
  173. package/dist/execution/source.js +21 -45
  174. package/dist/execution/target-ref.js +2 -2
  175. package/dist/indexer/bundle-identity-guard.js +6 -5
  176. package/dist/indexer/ensure-index.js +1 -1
  177. package/dist/indexer/index-writer-lock.js +1 -1
  178. package/dist/indexer/indexer.js +46 -42
  179. package/dist/indexer/installations.js +12 -22
  180. package/dist/indexer/lookup/adapter-concept-owner.js +40 -14
  181. package/dist/indexer/materialize-embeddings.js +20 -16
  182. package/dist/indexer/passes/memory-inference.js +21 -50
  183. package/dist/indexer/passes/metadata.js +5 -5
  184. package/dist/indexer/scan/doc-to-entry.js +1 -1
  185. package/dist/indexer/scan/drain-dir.js +9 -11
  186. package/dist/indexer/search/db-search.js +9 -7
  187. package/dist/indexer/search/search-source.js +42 -22
  188. package/dist/indexer/usage/usage-events.js +2 -3
  189. package/dist/indexer/walk/index-context.js +2 -1
  190. package/dist/indexer/walk/matchers.js +3 -11
  191. package/dist/indexer/walk/path-resolver.js +13 -68
  192. package/dist/indexer/walk/walker.js +32 -26
  193. package/dist/integrations/agent/akm-read-tools.js +81 -0
  194. package/dist/integrations/agent/config.js +1 -1
  195. package/dist/integrations/agent/detect.js +32 -36
  196. package/dist/integrations/agent/execution.js +130 -428
  197. package/dist/integrations/agent/index.js +1 -1
  198. package/dist/integrations/agent/profiles.js +24 -28
  199. package/dist/integrations/agent/prompts.js +17 -30
  200. package/dist/integrations/agent/request-lowering.js +67 -101
  201. package/dist/integrations/agent/resolution.js +332 -0
  202. package/dist/integrations/agent/runner-dispatch.js +156 -181
  203. package/dist/integrations/agent/runner.js +20 -70
  204. package/dist/integrations/agent/runtime-port.js +4 -0
  205. package/dist/integrations/agent/runtime.js +10 -0
  206. package/dist/integrations/agent/spawn.js +65 -190
  207. package/dist/integrations/harnesses/aider/index.js +19 -39
  208. package/dist/integrations/harnesses/amazonq/index.js +17 -32
  209. package/dist/integrations/harnesses/claude/index.js +59 -28
  210. package/dist/integrations/harnesses/claude/session-log.js +7 -5
  211. package/dist/integrations/harnesses/codex/index.js +19 -31
  212. package/dist/integrations/harnesses/copilot/index.js +17 -35
  213. package/dist/integrations/harnesses/gemini/index.js +18 -34
  214. package/dist/integrations/harnesses/harness.js +36 -0
  215. package/dist/integrations/harnesses/index.js +20 -51
  216. package/dist/integrations/harnesses/opencode/agent-builder.js +132 -100
  217. package/dist/integrations/harnesses/opencode/index.js +11 -33
  218. package/dist/integrations/harnesses/opencode/roots.js +50 -0
  219. package/dist/integrations/harnesses/opencode/runtime/binary.js +206 -0
  220. package/dist/integrations/harnesses/opencode/runtime/command.js +152 -0
  221. package/dist/integrations/harnesses/opencode/runtime/index.js +177 -0
  222. package/dist/integrations/harnesses/opencode/runtime/tar.js +107 -0
  223. package/dist/integrations/harnesses/opencode/session-log-v1.js +15 -7
  224. package/dist/integrations/harnesses/opencode/session-log-v2.js +72 -48
  225. package/dist/integrations/harnesses/opencode/session-log.js +58 -137
  226. package/dist/integrations/harnesses/opencode/version.js +34 -53
  227. package/dist/integrations/harnesses/openhands/index.js +13 -37
  228. package/dist/integrations/harnesses/pi/index.js +21 -32
  229. package/dist/integrations/lockfile.js +1 -1
  230. package/dist/integrations/session-logs/index.js +11 -31
  231. package/dist/llm/client.js +93 -111
  232. package/dist/llm/embedder.js +19 -34
  233. package/dist/llm/embedders/connection.js +31 -0
  234. package/dist/llm/embedders/local-model-files.js +56 -0
  235. package/dist/llm/embedders/local.js +146 -115
  236. package/dist/llm/embedders/remote.js +26 -23
  237. package/dist/llm/embedders/types.js +1 -1
  238. package/dist/llm/index-passes.js +33 -39
  239. package/dist/llm/memory-infer.js +67 -77
  240. package/dist/llm/model-list.js +35 -0
  241. package/dist/llm/rerank-client.js +8 -14
  242. package/dist/llm/structured-call.js +45 -99
  243. package/dist/llm/structured.js +60 -0
  244. package/dist/output/renderers.js +2 -8
  245. package/dist/output/shapes/helpers.js +18 -44
  246. package/dist/output/shapes/passthrough.js +1 -0
  247. package/dist/output/shapes.js +1 -7
  248. package/dist/output/text/command-format.js +41 -39
  249. package/dist/output/text/health-format.js +8 -2
  250. package/dist/output/text/helpers.js +1 -1
  251. package/dist/output/text/migrate.js +12 -0
  252. package/dist/output/text/models.js +3 -2
  253. package/dist/output/text/registry-commands.js +1 -2
  254. package/dist/output/text/show-directives.js +16 -28
  255. package/dist/output/text/show-format.js +0 -2
  256. package/dist/output/text/targets-table.js +70 -0
  257. package/dist/output/text/workflow-format.js +44 -15
  258. package/dist/output/text.js +1 -1
  259. package/dist/registry/providers/skills-sh.js +1 -28
  260. package/dist/registry/providers/static-index.js +1 -71
  261. package/dist/runtime.js +6 -2
  262. package/dist/scripts/akm-migrate-node.js +47095 -44905
  263. package/dist/scripts/akm-migrate.js +46946 -44755
  264. package/dist/setup/detect.js +28 -273
  265. package/dist/setup/endpoint.js +36 -0
  266. package/dist/setup/semantic-assets.js +13 -19
  267. package/dist/setup/setup-flags.js +77 -0
  268. package/dist/setup/setup-plan.js +144 -0
  269. package/dist/setup/setup.js +134 -358
  270. package/dist/setup/steps/connection-shared.js +49 -101
  271. package/dist/setup/steps/connection.js +121 -524
  272. package/dist/setup/steps/embeddings.js +151 -0
  273. package/dist/setup/steps/harnesses.js +118 -0
  274. package/dist/setup/steps/platforms.js +2 -81
  275. package/dist/setup/steps/tasks.js +1 -2
  276. package/dist/setup/steps.js +10 -0
  277. package/dist/setup/summary.js +67 -0
  278. package/dist/sources/freshness.js +16 -21
  279. package/dist/sources/providers/git-provider.js +2 -9
  280. package/dist/sources/providers/provider-utils.js +13 -5
  281. package/dist/sources/resolve.js +12 -16
  282. package/dist/sources/snapshot-fetchers/robots.js +11 -12
  283. package/dist/sources/snapshot-fetchers/secret-seam.js +2 -4
  284. package/dist/sources/snapshot-fetchers/website-ingest.js +8 -15
  285. package/dist/sources/snapshot-fetchers/x.js +1 -1
  286. package/dist/standalone/onnxruntime-library.js +52 -0
  287. package/dist/storage/repositories/improve-ledger-repository.js +1 -1
  288. package/dist/storage/repositories/improve-runs-repository.js +0 -13
  289. package/dist/storage/repositories/index-entries-repository.js +2 -2
  290. package/dist/storage/repositories/proposals-repository.js +2 -2
  291. package/dist/storage/repositories/task-history-repository.js +2 -2
  292. package/dist/storage/repositories/workflow-runs-repository.js +44 -129
  293. package/dist/storage/sqlite-read-snapshot.js +33 -29
  294. package/dist/tasks/embedded.js +1 -1
  295. package/dist/tasks/log-redaction.js +7 -119
  296. package/dist/tasks/prepare/prepare-support.js +8 -7
  297. package/dist/tasks/prepare/prepare.js +8 -9
  298. package/dist/tasks/prepare/script-capture.js +9 -25
  299. package/dist/tasks/run/attempt-lifecycle.js +17 -35
  300. package/dist/tasks/run/load-task.js +54 -27
  301. package/dist/tasks/run/run-command-task.js +15 -10
  302. package/dist/tasks/run/run-native-task.js +8 -21
  303. package/dist/tasks/run/run-task.js +5 -8
  304. package/dist/tasks/run/run-workflow-task.js +14 -21
  305. package/dist/tasks/run/task-history.js +9 -17
  306. package/dist/tasks/run/task-log.js +1 -5
  307. package/dist/tasks/scheduler-invocation.js +13 -18
  308. package/dist/tasks/scheduler-sync.js +0 -1
  309. package/dist/tasks/source/bounded-document.js +31 -117
  310. package/dist/tasks/source/parse-task-source.js +0 -1
  311. package/dist/tasks/source/project-v4.js +5 -3
  312. package/dist/tasks/source/task-input-diagnostics.js +3 -4
  313. package/dist/tasks/source/task-source-v4.js +48 -72
  314. package/dist/tasks/source-v3.js +2 -5
  315. package/dist/tasks/task-run-reserved-flags.js +1 -2
  316. package/dist/workflows/authoring/authoring.js +2 -7
  317. package/dist/workflows/compile.js +1 -15
  318. package/dist/workflows/concurrency-policy.js +4 -4
  319. package/dist/workflows/exec/child-workflow.js +1 -4
  320. package/dist/workflows/exec/dispatch-redaction.js +35 -86
  321. package/dist/workflows/exec/environment.js +13 -77
  322. package/dist/workflows/exec/exec-unit.js +14 -55
  323. package/dist/workflows/exec/frozen-judge.js +26 -28
  324. package/dist/workflows/exec/native-executor.js +126 -71
  325. package/dist/workflows/exec/run-workflow.js +38 -42
  326. package/dist/workflows/exec/step-work.js +13 -17
  327. package/dist/workflows/exec/unit-dispatch.js +7 -21
  328. package/dist/workflows/freeze/environment.js +14 -119
  329. package/dist/workflows/freeze/freeze.js +14 -33
  330. package/dist/workflows/freeze/step-values.js +6 -13
  331. package/dist/workflows/freeze/targets/child-workflow.js +3 -5
  332. package/dist/workflows/freeze/targets/command.js +9 -15
  333. package/dist/workflows/freeze/targets/shell.js +0 -3
  334. package/dist/workflows/freeze/task-bindings.js +0 -1
  335. package/dist/workflows/parser.js +50 -59
  336. package/dist/workflows/plan.js +8 -2
  337. package/dist/workflows/renderer.js +83 -9
  338. package/dist/workflows/resource-limits.js +2 -2
  339. package/dist/workflows/runtime/run-plan.js +38 -23
  340. package/dist/workflows/runtime/runs.js +55 -93
  341. package/dist/workflows/runtime/workflow-asset-loader.js +55 -86
  342. package/dist/workflows/source-files.js +7 -19
  343. package/docs/README.md +10 -16
  344. package/docs/architecture/README.md +2 -37
  345. package/docs/architecture/adapters.md +2 -2
  346. package/docs/architecture/akm-core-principles.md +256 -118
  347. package/docs/architecture/architecture.md +283 -99
  348. package/docs/architecture/improvement.md +8 -2
  349. package/docs/architecture/internals/classification.md +1 -3
  350. package/docs/architecture/internals/fresh-host-rebuild-runbook.md +7 -6
  351. package/docs/architecture/internals/health-advisories.md +35 -74
  352. package/docs/architecture/internals/improve-workflow.md +27 -26
  353. package/docs/architecture/internals/indexing.md +3 -3
  354. package/docs/architecture/internals/storage-locations.md +48 -15
  355. package/docs/architecture/persisted-data-compat.md +10 -6
  356. package/docs/architecture/specs/okf-support.md +9 -11
  357. package/docs/architecture/specs/ref.md +7 -9
  358. package/docs/architecture/testing/testing-workflow.md +172 -52
  359. package/docs/architecture/workflow-engine.md +51 -34
  360. package/docs/guides/README.md +0 -1
  361. package/docs/guides/author-bundles.md +15 -20
  362. package/docs/guides/author-workflows.md +93 -71
  363. package/docs/guides/bundles.md +20 -16
  364. package/docs/guides/discover-and-load.md +1 -1
  365. package/docs/guides/getting-started.md +49 -3
  366. package/docs/guides/improve-the-library.md +10 -4
  367. package/docs/guides/recipes/headless-install.md +11 -16
  368. package/docs/guides/run-workflows.md +29 -20
  369. package/docs/guides/scheduling.md +2 -2
  370. package/docs/guides/use-with-any-agent.md +20 -22
  371. package/docs/integration/bundling-akm.md +19 -9
  372. package/docs/maintainers/README.md +2 -6
  373. package/docs/maintainers/release-checklist.md +73 -126
  374. package/docs/migration/README.md +10 -3
  375. package/docs/migration/release-notes/0.10.0.md +81 -16
  376. package/docs/migration/release-notes/0.6.0.md +1 -1
  377. package/docs/migration/release-notes/0.7.0.md +1 -1
  378. package/docs/migration/release-notes/0.9.0.md +1 -1
  379. package/docs/migration/release-notes/README.md +1 -1
  380. package/docs/migration/v0.9-to-v0.10.md +300 -60
  381. package/docs/migration/v0.9.1-to-v0.9.2.md +6 -5
  382. package/docs/posts/config-v2-lessons-16.md +1 -1
  383. package/docs/posts/llm-mode-reflect-13.md +1 -1
  384. package/docs/posts/release-0.6.0.md +11 -11
  385. package/docs/posts/release-0.8.0.md +4 -4
  386. package/docs/posts/workflows-vaults-09.md +1 -1
  387. package/docs/reference/README.md +1 -1
  388. package/docs/reference/asset-types.md +2 -2
  389. package/docs/reference/cli.md +477 -388
  390. package/docs/reference/configuration.md +569 -550
  391. package/docs/reference/data-and-telemetry.md +9 -6
  392. package/docs/reference/env-and-secrets.md +72 -15
  393. package/docs/reference/refs.md +3 -20
  394. package/docs/reference/registry.md +12 -38
  395. package/docs/reference/supported-formats.md +1 -1
  396. package/docs/reference/tasks.md +22 -11
  397. package/docs/reference/ui-api.md +14 -9
  398. package/docs/reference/workflow-schema.md +199 -154
  399. package/docs/reference/workflows.md +4 -6
  400. package/package.json +9 -11
  401. package/schemas/akm-config.json +1696 -2922
  402. package/schemas/akm-task.json +4 -4
  403. package/schemas/akm-workflow.json +36 -9
  404. package/ROADMAP.md +0 -112
  405. package/dist/assets/models.json +0 -35
  406. package/dist/commands/health/engine-usage.js +0 -45
  407. package/dist/commands/sources/dangerous-env-audit.js +0 -134
  408. package/dist/core/activation-policy.js +0 -67
  409. package/dist/core/config/schema/engines.js +0 -160
  410. package/dist/core/config/schema/execution.js +0 -23
  411. package/dist/core/spawn-env.js +0 -268
  412. package/dist/execution/directory-identity.js +0 -78
  413. package/dist/integrations/agent/builder-shared.js +0 -33
  414. package/dist/integrations/agent/builders.js +0 -43
  415. package/dist/integrations/agent/engine-fallback.js +0 -59
  416. package/dist/integrations/agent/engine-resolution.js +0 -333
  417. package/dist/integrations/agent/model-map.js +0 -475
  418. package/dist/integrations/harnesses/aider/agent-builder.js +0 -107
  419. package/dist/integrations/harnesses/aider/result-extractor.js +0 -53
  420. package/dist/integrations/harnesses/amazonq/agent-builder.js +0 -138
  421. package/dist/integrations/harnesses/amazonq/result-extractor.js +0 -48
  422. package/dist/integrations/harnesses/claude/agent-builder.js +0 -106
  423. package/dist/integrations/harnesses/claude/config-import.js +0 -67
  424. package/dist/integrations/harnesses/claude/result-extractor.js +0 -67
  425. package/dist/integrations/harnesses/codex/agent-builder.js +0 -150
  426. package/dist/integrations/harnesses/codex/result-extractor.js +0 -110
  427. package/dist/integrations/harnesses/copilot/agent-builder.js +0 -117
  428. package/dist/integrations/harnesses/copilot/result-extractor.js +0 -178
  429. package/dist/integrations/harnesses/gemini/agent-builder.js +0 -114
  430. package/dist/integrations/harnesses/gemini/result-extractor.js +0 -149
  431. package/dist/integrations/harnesses/opencode/config-import.js +0 -149
  432. package/dist/integrations/harnesses/opencode/model-config.js +0 -33
  433. package/dist/integrations/harnesses/opencode/model-work-agent.js +0 -115
  434. package/dist/integrations/harnesses/opencode/session-log-types.js +0 -12
  435. package/dist/integrations/harnesses/opencode-sdk/index.js +0 -44
  436. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +0 -1052
  437. package/dist/integrations/harnesses/opencode-sdk/v1-adapter.js +0 -199
  438. package/dist/integrations/harnesses/opencode-sdk/v2-adapter.js +0 -254
  439. package/dist/integrations/harnesses/opencode-sdk/wire.js +0 -66
  440. package/dist/integrations/harnesses/openhands/agent-builder.js +0 -120
  441. package/dist/integrations/harnesses/openhands/result-extractor.js +0 -135
  442. package/dist/integrations/harnesses/pi/agent-builder.js +0 -89
  443. package/dist/integrations/harnesses/pi/result-extractor.js +0 -168
  444. package/dist/integrations/harnesses/shared.js +0 -18
  445. package/dist/integrations/harnesses/types.js +0 -55
  446. package/dist/llm/feature-gate.js +0 -115
  447. package/dist/output/shapes/models-list.js +0 -16
  448. package/dist/output/shapes/registry-search.js +0 -10
  449. package/dist/setup/detected-engines.js +0 -136
  450. package/dist/setup/engine-config.js +0 -97
  451. package/dist/setup/harness-config-import.js +0 -47
  452. package/dist/setup/providers.js +0 -14
  453. package/dist/setup/steps/semantic.js +0 -39
  454. package/dist/workflows/authoring/scope-key.js +0 -79
  455. package/dist/workflows/exec/lowering-notices.js +0 -23
  456. package/dist/workflows/source-semantics.js +0 -110
  457. package/docs/architecture/0.10-process-rules.md +0 -832
  458. package/docs/architecture/akm-architecture-decision-history.md +0 -2055
  459. package/docs/architecture/comparisons/claude-code-vs-akm-workflows-full.md +0 -550
  460. package/docs/architecture/decisions/0001-no-interpolation-attached-structured-context.md +0 -72
  461. package/docs/architecture/decisions/0002-unit-reuse-and-input-hash-scope.md +0 -142
  462. package/docs/architecture/decisions/0003-child-env-allowlist-and-provenance.md +0 -189
  463. package/docs/architecture/decisions/0004-task-input-contract-and-flag-coercion.md +0 -97
  464. package/docs/architecture/decisions/0005-task-result-vocabulary-and-legacy-read-mapping.md +0 -108
  465. package/docs/architecture/decisions/0006-task-source-version-routing.md +0 -124
  466. package/docs/architecture/decisions/0007-workflow-composition-bounds.md +0 -83
  467. package/docs/architecture/decisions/0008-task-binding-normalization.md +0 -88
  468. package/docs/architecture/decisions/0009-child-run-publication-column-parity.md +0 -80
  469. package/docs/architecture/decisions/0010-driver-protocol-cut.md +0 -36
  470. package/docs/architecture/decisions/0011-engine-run-loop-invariants.md +0 -125
  471. package/docs/architecture/decisions/README.md +0 -62
  472. package/docs/architecture/internals/functional-contract-patterns.md +0 -340
  473. package/docs/architecture/internals/registry-network-boundary.md +0 -57
  474. package/docs/architecture/internals/search.md +0 -248
  475. package/docs/architecture/reviews/env-secret-access.md +0 -319
  476. package/docs/architecture/runtime-boundary-design.md +0 -153
  477. package/docs/architecture/specs/0.9.0-close-out-plan.md +0 -361
  478. package/docs/architecture/specs/0.9.0-decisions.md +0 -532
  479. package/docs/architecture/specs/0.9.0-docs-code-drift-register.md +0 -745
  480. package/docs/architecture/specs/0.9.0-open-items-register.md +0 -135
  481. package/docs/architecture/specs/0.9.0-public-api-issue-backlog.md +0 -740
  482. package/docs/architecture/specs/0.9.0-release-surface-review.md +0 -636
  483. package/docs/architecture/specs/agent-command-engine-model-design.md +0 -513
  484. package/docs/architecture/specs/akm-0.9.0-bundle-adapter-spec.md +0 -501
  485. package/docs/architecture/specs/akm-0.9.0-ref-grammar-decision.md +0 -291
  486. package/docs/architecture/specs/akm-format-neutral-bundle-workspace-spec.md +0 -2059
  487. package/docs/architecture/specs/di-seams-plan.md +0 -539
  488. package/docs/architecture/specs/driver-protocol-keep-or-cut.md +0 -275
  489. package/docs/architecture/specs/fact-asset-type.md +0 -142
  490. package/docs/architecture/specs/improve-collapse-churn-detector-design.md +0 -634
  491. package/docs/architecture/specs/reviews/task-workflow-unification/README.md +0 -72
  492. package/docs/architecture/specs/reviews/task-workflow-unification/findings-consolidated.md +0 -152
  493. package/docs/architecture/specs/reviews/task-workflow-unification/library-eval-alternatives.md +0 -352
  494. package/docs/architecture/specs/reviews/task-workflow-unification/library-eval-bunqueue.md +0 -300
  495. package/docs/architecture/specs/reviews/task-workflow-unification/library-eval-openworkflow.md +0 -402
  496. package/docs/architecture/specs/reviews/task-workflow-unification/opus-review-1.md +0 -758
  497. package/docs/architecture/specs/reviews/task-workflow-unification/opus-review-2.md +0 -645
  498. package/docs/architecture/specs/reviews/task-workflow-unification/opus-review-3.md +0 -602
  499. package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-adversarial.md +0 -27
  500. package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-architecture.md +0 -27
  501. package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-coverage.md +0 -74
  502. package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-security.md +0 -15
  503. package/docs/architecture/specs/reviews/task-workflow-unification/panel-r2-adversarial.md +0 -132
  504. package/docs/architecture/specs/reviews/task-workflow-unification/panel-r2-verification.md +0 -147
  505. package/docs/architecture/specs/stash-conventions-code-spec.md +0 -275
  506. package/docs/architecture/specs/stash-organization-conventions.md +0 -377
  507. package/docs/architecture/specs/task-workflow-format-unification.md +0 -721
  508. package/docs/architecture/specs/workflow-engine-buy-vs-build.md +0 -231
  509. package/docs/architecture/specs/workflow-format-unification.md +0 -432
  510. package/docs/architecture/testing/manual-testing-checklist.md +0 -3411
  511. package/docs/architecture/testing/okf-v0.2-conformance-runbook.md +0 -924
  512. package/docs/architecture/testing/task-workflow-manual-tests.md +0 -1720
  513. package/docs/guides/claude-code-vs-akm-workflows.md +0 -29
  514. package/docs/guides/knowledge-management.md +0 -18
  515. package/docs/maintainers/curate-workmap.md +0 -335
  516. package/docs/migration/v0.5-to-v0.6.md +0 -759
  517. package/docs/migration/v0.7-to-v0.8.md +0 -1378
  518. package/docs/plans/0.9.2-agent-command-workflow-plan.md +0 -423
@@ -0,0 +1,50 @@
1
+ // This Source Code Form is subject to the terms of the Mozilla Public
2
+ // License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
+ /**
5
+ * Where the user's OpenCode keeps its files: the XDG base directories on every
6
+ * platform (OpenCode's own `global-roots` does not special-case macOS or
7
+ * Windows), each with an `opencode` folder. The one place akm computes them.
8
+ */
9
+ import os from "node:os";
10
+ import path from "node:path";
11
+ import { getDataDir } from "../../../core/paths.js";
12
+ function xdgRoot(name, fallback, env) {
13
+ const set = env[name]?.trim();
14
+ if (set)
15
+ return path.join(set, "opencode");
16
+ const home = env.HOME?.trim() || env.USERPROFILE?.trim() || os.homedir();
17
+ return path.join(home, ...fallback, "opencode");
18
+ }
19
+ /** `$XDG_DATA_HOME/opencode`: the user's `opencode.db`. */
20
+ function opencodeDataDir(env = process.env) {
21
+ return xdgRoot("XDG_DATA_HOME", [".local", "share"], env);
22
+ }
23
+ /** `$XDG_CACHE_HOME/opencode`: the plugin packages it installed. */
24
+ export function opencodeCacheDir(env = process.env) {
25
+ return xdgRoot("XDG_CACHE_HOME", [".cache"], env);
26
+ }
27
+ /** `$OPENCODE_CONFIG_DIR`, else `$XDG_CONFIG_HOME/opencode`: `opencode.json`, agents and plugins. */
28
+ export function opencodeConfigDir(env = process.env) {
29
+ return env.OPENCODE_CONFIG_DIR?.trim() || xdgRoot("XDG_CONFIG_HOME", [".config"], env);
30
+ }
31
+ /** OpenCode's SQLite session store, in OpenCode's data directory and in akm's. */
32
+ export function databaseIn(directory) {
33
+ return path.join(directory, "opencode.db");
34
+ }
35
+ /**
36
+ * Everything akm's own OpenCode runtime keeps, under akm's data directory: the
37
+ * four XDG roots it is started with (`config`, `data`, `cache`, `state`) and its
38
+ * `tmp`. Nothing of the user's OpenCode is in it.
39
+ */
40
+ export function akmRuntimeDir() {
41
+ return path.join(getDataDir(), "opencode-runtime");
42
+ }
43
+ /** The user's OpenCode database. */
44
+ export function opencodeDatabasePath(env = process.env) {
45
+ return databaseIn(opencodeDataDir(env));
46
+ }
47
+ /** Where akm's own runtime keeps its sessions: the `opencode/opencode.db` OpenCode makes under the runtime's `XDG_DATA_HOME`. */
48
+ export function akmOpencodeDatabasePath() {
49
+ return databaseIn(path.join(akmRuntimeDir(), "data", "opencode"));
50
+ }
@@ -0,0 +1,206 @@
1
+ // This Source Code Form is subject to the terms of the Mozilla Public
2
+ // License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
+ /**
5
+ * The OpenCode binary akm's own agent runtime runs, fetched on first use.
6
+ *
7
+ * OpenCode 2 is published as a prebuilt binary on npm: `@opencode/cli`, whose
8
+ * platform packages each hold one executable. akm does not depend on that
9
+ * package: the package manager would install every platform package that matches
10
+ * the OS and CPU (four, for Linux x64, about 900 MB), because none of them
11
+ * declares its libc or CPU features. akm fetches the one that matches this
12
+ * machine from the npm registry the first time its runtime is used, checks it
13
+ * against the registry's integrity hash, and keeps the executable under
14
+ * `<akm cache dir>/opencode/<version>/`. Package selection mirrors the
15
+ * `postinstall.mjs` of `@opencode/cli`.
16
+ */
17
+ import { spawnSync } from "node:child_process";
18
+ import { createHash } from "node:crypto";
19
+ import fs from "node:fs";
20
+ import path from "node:path";
21
+ import { fetchWithRetry, isRecord, toErrorMessage } from "../../../../core/common.js";
22
+ import { getCacheDir } from "../../../../core/paths.js";
23
+ import { info } from "../../../../core/warn.js";
24
+ import { writeResponseToFileCapped } from "../../../../runtime.js";
25
+ import { extractTarGzMember } from "./tar.js";
26
+ /**
27
+ * The OpenCode release akm's own runtime runs. It is pinned because the runtime depends on things no OpenCode release
28
+ * promises: the inline config's shape, the `--standalone` flag, the plugin API, the text `run` prints, and the
29
+ * `opencode.db` tables that `../session-log-v2.ts` reads. To move it, change this version and `PACKAGES` if the release
30
+ * adds or drops a platform package, then run `tests/integration/opencode-runtime-sessions.test.ts` against the new
31
+ * binary (it fetches it) and read `docs/reference/configuration.md` ("Without a harness") for what the version changes.
32
+ */
33
+ export const OPENCODE_RUNTIME_VERSION = "2.1.4";
34
+ const REGISTRY = "https://registry.npmjs.org";
35
+ /** The platform packages of `@opencode/cli` at {@link OPENCODE_RUNTIME_VERSION}. */
36
+ const PACKAGES = new Set([
37
+ "@opencode/cli-linux-x64",
38
+ "@opencode/cli-linux-x64-baseline",
39
+ "@opencode/cli-linux-x64-musl",
40
+ "@opencode/cli-linux-x64-baseline-musl",
41
+ "@opencode/cli-linux-arm64",
42
+ "@opencode/cli-linux-arm64-musl",
43
+ "@opencode/cli-darwin-x64",
44
+ "@opencode/cli-darwin-x64-baseline",
45
+ "@opencode/cli-darwin-arm64",
46
+ "@opencode/cli-windows-x64",
47
+ "@opencode/cli-windows-x64-baseline",
48
+ "@opencode/cli-windows-arm64",
49
+ ]);
50
+ /** The package for a machine: `@opencode/cli-<platform>-<arch>`, with `-baseline` for an x64 CPU without AVX2 and `-musl` for musl. */
51
+ export function opencodePackage({ platform, arch, musl, avx2 }) {
52
+ const name = [
53
+ `@opencode/cli-${platform}-${arch}`,
54
+ ...(arch === "x64" && !avx2 ? ["baseline"] : []),
55
+ ...(platform === "linux" && musl ? ["musl"] : []),
56
+ ].join("-");
57
+ if (!PACKAGES.has(name)) {
58
+ throw new Error(`OpenCode ${OPENCODE_RUNTIME_VERSION} publishes no binary for ${platform} ${arch} (${name}).`);
59
+ }
60
+ return name;
61
+ }
62
+ function run(command, args, timeout) {
63
+ return spawnSync(command, args, { encoding: "utf8", timeout, windowsHide: true });
64
+ }
65
+ const AVX2_WINDOWS_PROBE = '(Add-Type -MemberDefinition "[DllImport(""kernel32.dll"")] public static extern bool IsProcessorFeaturePresent(int ProcessorFeature);" -Name Kernel32 -Namespace Win32 -PassThru)::IsProcessorFeaturePresent(40)';
66
+ /** Whether an x64 CPU has AVX2, asked the way OpenCode's own installer asks it. */
67
+ function hasAvx2(platform) {
68
+ try {
69
+ if (platform === "linux")
70
+ return /(^|\s)avx2(\s|$)/i.test(fs.readFileSync("/proc/cpuinfo", "utf8"));
71
+ if (platform === "darwin") {
72
+ const probe = run("sysctl", ["-n", "hw.optional.avx2_0"], 1500);
73
+ return probe.status === 0 && probe.stdout.trim() === "1";
74
+ }
75
+ for (const shell of ["powershell.exe", "pwsh.exe", "pwsh", "powershell"]) {
76
+ const probe = run(shell, ["-NoProfile", "-NonInteractive", "-Command", AVX2_WINDOWS_PROBE], 3000);
77
+ if (probe.status !== 0)
78
+ continue;
79
+ const answer = probe.stdout.trim().toLowerCase();
80
+ if (answer === "true" || answer === "1")
81
+ return true;
82
+ if (answer === "false" || answer === "0")
83
+ return false;
84
+ }
85
+ }
86
+ catch {
87
+ // Not knowing is the baseline build, which runs everywhere.
88
+ }
89
+ return false;
90
+ }
91
+ /** Whether this Linux uses musl libc. */
92
+ function isMusl() {
93
+ if (fs.existsSync("/etc/alpine-release"))
94
+ return true;
95
+ const probe = run("ldd", ["--version"], 5000);
96
+ return `${probe.stdout ?? ""}${probe.stderr ?? ""}`.toLowerCase().includes("musl");
97
+ }
98
+ /** This machine, as the package choice sees it. */
99
+ export function detectHost(env = process.env, operatingSystem = process.platform, processArch = process.arch) {
100
+ const platform = { darwin: "darwin", linux: "linux", win32: "windows" }[operatingSystem];
101
+ const nodeArch = { x64: "x64", arm64: "arm64" }[processArch];
102
+ if (!platform || !nodeArch)
103
+ throw new Error(`OpenCode publishes no binary for ${operatingSystem} ${processArch}.`);
104
+ // An x64 process on Windows for ARM still names the host CPU in PROCESSOR_IDENTIFIER, and the arm64 build is the one to run.
105
+ const arch = platform === "windows" && nodeArch === "x64" && env.PROCESSOR_IDENTIFIER?.startsWith("ARM") ? "arm64" : nodeArch;
106
+ return { platform, arch, musl: platform === "linux" && isMusl(), avx2: arch === "x64" && hasAvx2(platform) };
107
+ }
108
+ /** Where the OpenCode binary is kept once fetched. */
109
+ export function runtimeBinaryPath(platform = process.platform) {
110
+ return path.join(getCacheDir(), "opencode", OPENCODE_RUNTIME_VERSION, platform === "win32" ? "opencode.exe" : "opencode");
111
+ }
112
+ /** The `sha512-<base64>` integrity npm records for a tarball. */
113
+ function sha512Integrity(file) {
114
+ return new Promise((resolve, reject) => {
115
+ const hash = createHash("sha512");
116
+ fs.createReadStream(file)
117
+ .on("data", (chunk) => hash.update(chunk))
118
+ .on("error", reject)
119
+ .on("end", () => resolve(`sha512-${hash.digest("base64")}`));
120
+ });
121
+ }
122
+ /** Throws unless the tarball at `file` has the integrity the registry lists for it. */
123
+ export async function verifyIntegrity(file, expected) {
124
+ const listed = expected.split(/\s+/).filter((integrity) => integrity.startsWith("sha512-"));
125
+ if (listed.length === 0)
126
+ throw new Error(`the registry lists no sha512 integrity for it (${expected || "none"})`);
127
+ const actual = await sha512Integrity(file);
128
+ if (!listed.includes(actual))
129
+ throw new Error(`its sha512 integrity is ${actual}, not the ${listed.join(" or ")} the registry lists`);
130
+ }
131
+ async function registryDocument(url) {
132
+ const response = await fetchWithRetry(url, { headers: { accept: "application/json" } }, { timeout: 30_000 });
133
+ if (!response.ok) {
134
+ await response.body?.cancel().catch(() => undefined);
135
+ throw new Error(`the registry answered HTTP ${response.status}`);
136
+ }
137
+ const dist = (await response.json()).dist;
138
+ if (!isRecord(dist) || typeof dist.tarball !== "string" || typeof dist.integrity !== "string") {
139
+ throw new Error("the registry document has no dist.tarball and dist.integrity");
140
+ }
141
+ return { tarball: dist.tarball, integrity: dist.integrity };
142
+ }
143
+ /**
144
+ * Fetch the binary of the package `name` into `binary`: the registry document of that one package, its tarball, the
145
+ * integrity check before anything is extracted, then the executable by temp file and rename. Two akm processes fetching
146
+ * at once both finish: a rename that loses to the other leaves the file the other made.
147
+ */
148
+ async function fetchBinary(name, binary) {
149
+ const directory = path.dirname(binary);
150
+ fs.mkdirSync(directory, { recursive: true });
151
+ const download = path.join(directory, `.download-${process.pid}.tgz`);
152
+ const partial = path.join(directory, `.opencode-${process.pid}.tmp`);
153
+ try {
154
+ const { tarball, integrity } = await registryDocument(`${REGISTRY}/${name}/${OPENCODE_RUNTIME_VERSION}`);
155
+ info(`Fetching OpenCode ${OPENCODE_RUNTIME_VERSION} for akm's own agent runtime (about 114 MB, once) into ${directory}.`);
156
+ const response = await fetchWithRetry(tarball, undefined, { timeout: 60_000 });
157
+ if (!response.ok) {
158
+ await response.body?.cancel().catch(() => undefined);
159
+ throw new Error(`${tarball} answered HTTP ${response.status}`);
160
+ }
161
+ // No overall deadline for a 114 MB file on a slow link: only 60 s without bytes fails it.
162
+ await writeResponseToFileCapped(download, response, { stallTimeoutMs: 60_000 });
163
+ await verifyIntegrity(download, integrity);
164
+ const size = await extractTarGzMember(download, `package/bin/${path.basename(binary)}`, partial);
165
+ fs.chmodSync(partial, 0o755);
166
+ try {
167
+ fs.renameSync(partial, binary);
168
+ }
169
+ catch (error) {
170
+ // Where an open executable cannot be replaced, the other process's file stands.
171
+ if (!fs.existsSync(binary) || fs.statSync(binary).size !== size)
172
+ throw error;
173
+ }
174
+ }
175
+ finally {
176
+ fs.rmSync(download, { force: true });
177
+ fs.rmSync(partial, { force: true });
178
+ }
179
+ }
180
+ /** Fetch the binary for this machine, naming the package, its URL and the cache path when it cannot. */
181
+ async function fetchForThisMachine(binary) {
182
+ let name = "an @opencode/cli platform package";
183
+ try {
184
+ name = opencodePackage(detectHost());
185
+ await fetchBinary(name, binary);
186
+ return binary;
187
+ }
188
+ catch (error) {
189
+ throw new Error(`Could not fetch OpenCode ${OPENCODE_RUNTIME_VERSION}, which akm's own agent runtime runs: package ${name} from ${REGISTRY}/${name}/${OPENCODE_RUNTIME_VERSION} into ${path.dirname(binary)}: ${toErrorMessage(error)}. ` +
190
+ "Without network access for this step, enable the opencode harness with an installed OpenCode 2 instead (see docs/reference/configuration.md).");
191
+ }
192
+ }
193
+ let fetching;
194
+ /**
195
+ * The path of the OpenCode binary akm's runtime runs, fetched first if it is not in the cache. A process fetches once,
196
+ * however many runs ask meanwhile.
197
+ */
198
+ export function ensureRuntimeBinary() {
199
+ const binary = runtimeBinaryPath();
200
+ if (fs.existsSync(binary))
201
+ return Promise.resolve(binary);
202
+ fetching ??= fetchForThisMachine(binary).finally(() => {
203
+ fetching = undefined;
204
+ });
205
+ return fetching;
206
+ }
@@ -0,0 +1,152 @@
1
+ // This Source Code Form is subject to the terms of the Mozilla Public
2
+ // License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
+ /**
5
+ * The OpenCode 2 process akm's own runtime starts for one run, built the way the
6
+ * opencode harness builds model work on the user's OpenCode 2
7
+ * (`../agent-builder.ts`): `run --standalone --title akm`, the prompt on stdin,
8
+ * the inline config in `OPENCODE_CONFIG_CONTENT`. What differs is that the
9
+ * process is akm's own, so akm sets what a user's OpenCode keeps for itself:
10
+ *
11
+ * - **The connection is the only provider.** `@ai-sdk/openai-compatible` (which
12
+ * the binary bundles) at the connection's endpoint, with its key, and the one
13
+ * model the run was dispatched with, with the context window and output cap the
14
+ * connection states. The key is not in the config: the config names a 0600
15
+ * file under akm's runtime directory that holds it (`{file:…}`), so no process
16
+ * environment holds the key.
17
+ * - **akm's roots.** OpenCode's config, data, cache and state directories and its
18
+ * temp directory are akm's (`../roots.ts`), so nothing of the user's OpenCode
19
+ * is read or written and the sessions land where akm's reader looks. The
20
+ * inherited `OPENCODE_*` variables are dropped for the same reason.
21
+ * - **Nothing from outside.** No hosted free models and no model catalog fetch
22
+ * (a run with no usable provider fails instead of sending its prompt to
23
+ * OpenCode's service), no project config (`AGENTS.md`, `opencode.json`) and no
24
+ * Claude Code files (`~/.claude/skills`).
25
+ * - **The resume sweep is off** because `--standalone` keeps the run to one
26
+ * process that ends with it and replays nobody's killed sessions.
27
+ * - **The agent's commands do not see any of this.** The plugin puts the
28
+ * variables this module sets back to what akm runs in, or removes them, in the
29
+ * environment of the commands the agent runs: they get the user's directories,
30
+ * not the runtime's, and no OpenCode setting of akm's (an `opencode` they run
31
+ * would otherwise load akm's provider and its key file).
32
+ *
33
+ * The run is OpenCode's default agent (or the native agent the request names) with
34
+ * its normal tools, akm's three read tools and the connection's request fields
35
+ * from the plugin (`../../../../assets/opencode/akm-plugin.js`).
36
+ */
37
+ import path from "node:path";
38
+ import { openAiBaseUrl } from "../../../../core/endpoint-url.js";
39
+ import { effectiveRequestFields } from "../../../../core/llm-inference.js";
40
+ /** The provider the connection is declared as; a process runs one connection, so the name is fixed. */
41
+ const PROVIDER = "akm";
42
+ const positiveInteger = (value) => typeof value === "number" && Number.isInteger(value) && value > 0 ? value : undefined;
43
+ /**
44
+ * A path as a `{file:…}` reference. OpenCode replaces the reference in the config's text before it parses it, so the
45
+ * path is read with the text's JSON escapes in it (measured on 2.1.4: a path holding a backslash or a quote is not
46
+ * found, and the request goes out with no key). Windows takes forward slashes, so its paths are written with them.
47
+ */
48
+ function fileReference(file) {
49
+ return process.platform === "win32" ? file.replaceAll("\\", "/") : file;
50
+ }
51
+ /** What OpenCode assumes of a model that states no limit. It refuses a model whose limit states only one of the two. */
52
+ const DEFAULT_LIMIT = { context: 200_000, output: 32_000 };
53
+ /**
54
+ * The inline OpenCode config of a run. `keyFile` is where the connection's key is written for the run, when it has
55
+ * one. `ambient` is the environment the process is started over: the plugin gives the commands the agent runs these
56
+ * values back for the variables the run sets, and removes them where there is none.
57
+ */
58
+ export function runtimeConfig(connection, pluginDirectory, keyFile, ambient = {}) {
59
+ const requestFields = effectiveRequestFields(connection.request, connection.inference);
60
+ const context = positiveInteger(connection.contextLength);
61
+ const output = positiveInteger(requestFields.max_tokens);
62
+ const limit = context === undefined && output === undefined
63
+ ? undefined
64
+ : { context: context ?? DEFAULT_LIMIT.context, output: output ?? DEFAULT_LIMIT.output };
65
+ return {
66
+ plugins: [
67
+ {
68
+ package: pluginDirectory,
69
+ options: {
70
+ requestFields,
71
+ shellEnv: Object.fromEntries(RUNTIME_VARIABLES.map((name) => [name, ambient[name] ?? null])),
72
+ },
73
+ },
74
+ ],
75
+ provider: {
76
+ [PROVIDER]: {
77
+ npm: "@ai-sdk/openai-compatible",
78
+ name: PROVIDER,
79
+ options: {
80
+ baseURL: openAiBaseUrl(connection.endpoint),
81
+ ...(connection.apiKey ? { apiKey: `{file:${fileReference(keyFile)}}` } : {}),
82
+ },
83
+ models: {
84
+ [connection.model]: {
85
+ name: connection.model,
86
+ ...(limit ? { limit } : {}),
87
+ },
88
+ },
89
+ },
90
+ },
91
+ };
92
+ }
93
+ /**
94
+ * The variables {@link runtimeEnv} sets that the commands the agent runs must not see as set: the runtime's roots (a
95
+ * command would read and write akm's directories instead of the user's) and akm's OpenCode settings (an `opencode` a
96
+ * command runs would load akm's provider and its key file). `AKM_OPENCODE_CLI`, between akm and its plugin, is
97
+ * harmless to a command and is left.
98
+ */
99
+ const RUNTIME_VARIABLES = [
100
+ "XDG_CONFIG_HOME",
101
+ "XDG_DATA_HOME",
102
+ "XDG_CACHE_HOME",
103
+ "XDG_STATE_HOME",
104
+ "TMPDIR",
105
+ "OPENCODE_DISABLE_FREE_MODELS",
106
+ "OPENCODE_DISABLE_MODELS_FETCH",
107
+ "OPENCODE_DISABLE_PROJECT_CONFIG",
108
+ "OPENCODE_DISABLE_CLAUDE_CODE",
109
+ "OPENCODE_CONFIG_CONTENT",
110
+ ];
111
+ /** What a run sets in the process's environment, over the one akm and the caller give every child. */
112
+ export function runtimeEnv(config, where) {
113
+ const at = (...parts) => path.join(where.directory, ...parts);
114
+ return {
115
+ XDG_CONFIG_HOME: at("config"),
116
+ XDG_DATA_HOME: at("data"),
117
+ XDG_CACHE_HOME: at("cache"),
118
+ XDG_STATE_HOME: at("state"),
119
+ TMPDIR: at("tmp"),
120
+ OPENCODE_DISABLE_FREE_MODELS: "1",
121
+ OPENCODE_DISABLE_MODELS_FETCH: "1",
122
+ OPENCODE_DISABLE_PROJECT_CONFIG: "1",
123
+ OPENCODE_DISABLE_CLAUDE_CODE: "1",
124
+ OPENCODE_CONFIG_CONTENT: JSON.stringify(config),
125
+ AKM_OPENCODE_CLI: JSON.stringify(where.akm),
126
+ };
127
+ }
128
+ /**
129
+ * A command that makes and migrates OpenCode's database and does nothing else (it lists the sessions, with no model and
130
+ * no background service), for the first start of a database.
131
+ */
132
+ export function runtimePrepareArgv(binary) {
133
+ return [binary, "session", "list", "--standalone"];
134
+ }
135
+ /**
136
+ * The command line of a run; the prompt is not on it, it goes on stdin. `session` is the id the run's session is made
137
+ * with (`--session` makes a session of that id when none has it), so akm finds the session the run left.
138
+ */
139
+ export function runtimeArgv(connection, dispatch, binary, session) {
140
+ return [
141
+ binary,
142
+ "run",
143
+ "--standalone",
144
+ "--title",
145
+ "akm",
146
+ "--session",
147
+ session,
148
+ ...(dispatch.agent ? ["--agent", dispatch.agent] : []),
149
+ "--model",
150
+ `${PROVIDER}/${connection.model}`,
151
+ ];
152
+ }
@@ -0,0 +1,177 @@
1
+ // This Source Code Form is subject to the terms of the Mozilla Public
2
+ // License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
+ /**
5
+ * akm's own agent runtime: a pinned OpenCode 2 binary run as a process over a
6
+ * connection (`./command.ts`), for agent work when no harness is enabled. It is
7
+ * what the application's port (`integrations/agent/runtime-port.ts`) asks for.
8
+ *
9
+ * The binary is fetched on first use (`./binary.ts`). Each run is its own process,
10
+ * run through the same spawn path as a harness's, so the deadline, the caller's
11
+ * signal and the capture of its output are the ones every agent run has. The
12
+ * process keeps nothing between runs but akm's runtime directory, where its
13
+ * sessions are (`../roots.ts`); nothing here reads config.
14
+ */
15
+ import { randomUUID } from "node:crypto";
16
+ import fs from "node:fs";
17
+ import path from "node:path";
18
+ import akmPlugin from "../../../../assets/opencode/akm-plugin.js" with { type: "text" };
19
+ import { toErrorMessage, writeFileAtomic } from "../../../../core/common.js";
20
+ import { createLockPayload, probeLock, reclaimStaleLock, releaseLock, tryAcquireLockSync, } from "../../../../core/file-lock.js";
21
+ import { PORTABLE_INFERENCE_KEYS } from "../../../../core/llm-inference.js";
22
+ import { openDatabase } from "../../../../storage/database.js";
23
+ import { resolveAkmInvocation } from "../../../../tasks/resolve-akm-bin.js";
24
+ import { buildChildEnv, runBuiltCommand, } from "../../../agent/spawn.js";
25
+ import { akmOpencodeDatabasePath, akmRuntimeDir } from "../roots.js";
26
+ import { v2SessionTokens } from "../session-log-v2.js";
27
+ import { ensureRuntimeBinary, OPENCODE_RUNTIME_VERSION } from "./binary.js";
28
+ import { runtimeArgv, runtimeConfig, runtimeEnv, runtimePrepareArgv } from "./command.js";
29
+ /**
30
+ * What a request is lowered for when it runs here. The persona goes in the prompt, as for the opencode harness
31
+ * (`opencode run` has no system prompt flag); every portable setting is carried, as request fields the plugin lays over
32
+ * the model requests.
33
+ */
34
+ const runtimeLowerer = {
35
+ id: "akm-runtime",
36
+ systemPrompt: false,
37
+ nativeAgent: true,
38
+ // Model work on a connection is a chat call (`buildExecution`), so no run here is confined; if one were lowered here, say so.
39
+ confinable: false,
40
+ inference: PORTABLE_INFERENCE_KEYS,
41
+ };
42
+ /** How long preparing the database may take: it is a few milliseconds of work and a process start. */
43
+ const PREPARE_TIMEOUT_MS = 60_000;
44
+ /** The connection's key, for the one run that reads it, kept as `credentials.json` is: 0600, in a 0700 directory. */
45
+ function writeKeyFile(file, key) {
46
+ fs.mkdirSync(path.dirname(file), { recursive: true, mode: 0o700 });
47
+ writeFileAtomic(file, key, 0o600);
48
+ }
49
+ /** Write the plugin where OpenCode loads it from (a directory, whose `index.mjs` is the module), when it is not already there. */
50
+ function installPlugin(directory) {
51
+ const pluginDirectory = path.join(directory, "config", "akm-plugin");
52
+ const file = path.join(pluginDirectory, "index.mjs");
53
+ if (!fs.existsSync(file) || fs.readFileSync(file, "utf8") !== akmPlugin) {
54
+ fs.mkdirSync(pluginDirectory, { recursive: true });
55
+ const partial = `${file}.${process.pid}.tmp`;
56
+ fs.writeFileSync(partial, akmPlugin);
57
+ fs.renameSync(partial, file);
58
+ }
59
+ return pluginDirectory;
60
+ }
61
+ /**
62
+ * OpenCode makes and migrates its database when a process starts, and two processes doing that to one database break
63
+ * each other (one fails with "Standalone server exited before reporting readiness"; on 2.1.4 two runs started together
64
+ * on a fresh directory lose one of them every time). So the first start of this OpenCode version is a preparing run of
65
+ * its own, under a lock file in the runtime directory that every run, of this akm process or another, waits on, and it
66
+ * leaves a marker naming the version; a run that finds the marker and the database starts at once. A dead holder's
67
+ * lock is reclaimed. The run itself reports anything the preparation does not.
68
+ */
69
+ async function prepareDatabase(directory, command, opts) {
70
+ const marker = path.join(directory, `prepared-${OPENCODE_RUNTIME_VERSION}`);
71
+ const lock = path.join(directory, "prepare.lock");
72
+ const prepared = () => fs.existsSync(marker) && fs.existsSync(akmOpencodeDatabasePath());
73
+ const deadline = Date.now() + PREPARE_TIMEOUT_MS;
74
+ while (!prepared() && !opts.signal?.aborted) {
75
+ const ownership = tryAcquireLockSync(lock, createLockPayload());
76
+ if (ownership) {
77
+ try {
78
+ if (prepared())
79
+ return;
80
+ const result = await runBuiltCommand("akm's runtime preparing its database", command, {
81
+ ...(opts.cwd ? { cwd: opts.cwd } : {}),
82
+ ...(opts.signal ? { signal: opts.signal } : {}),
83
+ timeoutMs: PREPARE_TIMEOUT_MS,
84
+ });
85
+ if (result.ok)
86
+ fs.writeFileSync(marker, "");
87
+ return;
88
+ }
89
+ finally {
90
+ releaseLock(ownership);
91
+ }
92
+ }
93
+ const probe = probeLock(lock);
94
+ if (probe.state === "stale" && reclaimStaleLock(lock, probe))
95
+ continue;
96
+ if (Date.now() >= deadline) {
97
+ throw new Error(`Another akm process is still preparing the database of akm's runtime (lock ${lock}).`);
98
+ }
99
+ await new Promise((resolve) => setTimeout(resolve, 100));
100
+ }
101
+ }
102
+ /**
103
+ * The run's session as OpenCode recorded it, read once the process has ended: its id and the tokens its turn used,
104
+ * which a workflow's `budget.max_tokens` and the unit journal count. Nothing when the run made no session. Accounting
105
+ * is best-effort: a database that cannot be read leaves the run's result as it is.
106
+ */
107
+ function sessionRecord(sessionId) {
108
+ try {
109
+ const db = openDatabase(akmOpencodeDatabasePath(), { readonly: true, create: false });
110
+ try {
111
+ const tokens = v2SessionTokens(db, sessionId);
112
+ if (!tokens)
113
+ return {};
114
+ return {
115
+ sessionId,
116
+ usage: { inputTokens: tokens.input, outputTokens: tokens.output, reasoningTokens: tokens.reasoning },
117
+ };
118
+ }
119
+ finally {
120
+ db.close();
121
+ }
122
+ }
123
+ catch {
124
+ return {};
125
+ }
126
+ }
127
+ export const opencodeRuntime = {
128
+ lowering: runtimeLowerer,
129
+ async run(profile, opts, connection) {
130
+ const label = `akm's runtime on connection "${profile.name}"`;
131
+ const dispatch = opts.dispatch;
132
+ if (dispatch?.prompt === undefined)
133
+ throw new TypeError("A run on akm's runtime is given a prompt.");
134
+ const start = Date.now();
135
+ try {
136
+ const binary = await ensureRuntimeBinary();
137
+ const directory = akmRuntimeDir();
138
+ for (const name of ["config", "data", "cache", "state", "tmp"]) {
139
+ fs.mkdirSync(path.join(directory, name), { recursive: true });
140
+ }
141
+ const where = {
142
+ binary,
143
+ directory,
144
+ pluginDirectory: installPlugin(directory),
145
+ akm: resolveAkmInvocation().argv,
146
+ };
147
+ // The user's own OPENCODE_* variables configure their OpenCode, not this one.
148
+ const ambient = Object.fromEntries(Object.entries(buildChildEnv(opts)).filter(([name]) => !name.startsWith("OPENCODE_")));
149
+ // OpenCode's own ids start with `ses_`, which it requires of one it is given.
150
+ const session = `ses_akm${randomUUID().replaceAll("-", "")}`;
151
+ const keyFile = path.join(directory, "keys", session);
152
+ const config = runtimeConfig(connection, where.pluginDirectory, keyFile, ambient);
153
+ const env = { ...ambient, ...runtimeEnv(config, where) };
154
+ try {
155
+ if (connection.apiKey)
156
+ writeKeyFile(keyFile, connection.apiKey);
157
+ await prepareDatabase(directory, { argv: runtimePrepareArgv(binary), env }, opts);
158
+ const result = await runBuiltCommand(label, { argv: runtimeArgv(connection, dispatch, binary, session), env, stdin: dispatch.prompt }, opts, "captured");
159
+ return { ...result, ...sessionRecord(session) };
160
+ }
161
+ finally {
162
+ fs.rmSync(keyFile, { force: true });
163
+ }
164
+ }
165
+ catch (error) {
166
+ return {
167
+ ok: false,
168
+ exitCode: null,
169
+ stdout: "",
170
+ stderr: toErrorMessage(error),
171
+ durationMs: Date.now() - start,
172
+ reason: "spawn_failed",
173
+ error: toErrorMessage(error),
174
+ };
175
+ }
176
+ },
177
+ };