akm-cli 0.10.261013-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 (477) hide show
  1. package/CHANGELOG.md +494 -3
  2. package/README.md +15 -0
  3. package/SECURITY.md +9 -8
  4. package/STABILITY.md +45 -49
  5. package/dist/assets/hints/cli-hints-full.md +15 -12
  6. package/dist/assets/opencode/akm-plugin.js +177 -0
  7. package/dist/assets/stash-skeleton/README.md +1 -1
  8. package/dist/assets/tasks/core/improve.yml +1 -1
  9. package/dist/assets/tasks/improve/akm-improve-consolidate.yml +1 -1
  10. package/dist/assets/ui/config.js +27 -10
  11. package/dist/assets/workflows/workflow-template.md +2 -2
  12. package/dist/cli/clack.js +3 -1
  13. package/dist/cli/selection.js +33 -0
  14. package/dist/cli/shared.js +14 -1
  15. package/dist/cli/unknown-flags.js +6 -37
  16. package/dist/cli.js +69 -48
  17. package/dist/commands/agent/agent-dispatch.js +17 -25
  18. package/dist/commands/agent/contribute-cli.js +9 -8
  19. package/dist/commands/command/command-cli.js +4 -8
  20. package/dist/commands/command/command-execution.js +25 -39
  21. package/dist/commands/completions.js +1 -1
  22. package/dist/commands/config-cli.js +14 -5
  23. package/dist/commands/env/child-env.js +12 -14
  24. package/dist/commands/env/env-cli.js +2 -2
  25. package/dist/commands/env/secret-cli.js +2 -2
  26. package/dist/commands/health/checks.js +10 -849
  27. package/dist/commands/health/connections-and-harnesses-check.js +109 -0
  28. package/dist/commands/health/egress.js +3 -3
  29. package/dist/commands/health/html-report.js +9 -10
  30. package/dist/commands/health/plugin-staleness.js +18 -11
  31. package/dist/commands/health/report-view-model.js +16 -12
  32. package/dist/commands/health/semantic-search-check.js +85 -0
  33. package/dist/commands/health/type-directory-check.js +0 -3
  34. package/dist/commands/health.js +30 -42
  35. package/dist/commands/improve/consolidate/pair-pass.js +10 -25
  36. package/dist/commands/improve/consolidate.js +10 -15
  37. package/dist/commands/improve/distill.js +5 -15
  38. package/dist/commands/improve/eligibility.js +1 -1
  39. package/dist/commands/improve/execution.js +37 -40
  40. package/dist/commands/improve/extract-cli.js +6 -11
  41. package/dist/commands/improve/extract-prompt.js +2 -2
  42. package/dist/commands/improve/extract.js +67 -97
  43. package/dist/commands/improve/improve-cli.js +22 -128
  44. package/dist/commands/improve/improve-report.js +1 -1
  45. package/dist/commands/improve/improve-strategies.js +25 -108
  46. package/dist/commands/improve/improve.js +10 -14
  47. package/dist/commands/improve/loop-stages.js +3 -0
  48. package/dist/commands/improve/memory/memory-improve.js +1 -1
  49. package/dist/commands/improve/preparation.js +8 -13
  50. package/dist/commands/improve/reflect.js +203 -332
  51. package/dist/commands/improve/retrieval-scope.js +1 -1
  52. package/dist/commands/improve/session-asset.js +3 -2
  53. package/dist/commands/improve/stage.js +87 -115
  54. package/dist/commands/lint/base-linter.js +3 -3
  55. package/dist/commands/lint/index.js +2 -2
  56. package/dist/commands/models-cli.js +103 -63
  57. package/dist/commands/proposal/drain.js +26 -39
  58. package/dist/commands/proposal/proposal-cli.js +14 -18
  59. package/dist/commands/proposal/propose-cli.js +4 -2
  60. package/dist/commands/proposal/propose.js +37 -64
  61. package/dist/commands/proposal/repository.js +17 -17
  62. package/dist/commands/proposal/validators/proposal-validators.js +2 -2
  63. package/dist/commands/read/curate.js +10 -6
  64. package/dist/commands/read/registry-search.js +2 -48
  65. package/dist/commands/read/search-cli.js +1 -8
  66. package/dist/commands/read/search.js +5 -6
  67. package/dist/commands/read/show.js +2 -4
  68. package/dist/commands/remember.js +25 -40
  69. package/dist/commands/sources/bundle-config-ops.js +2 -2
  70. package/dist/commands/sources/info.js +12 -1
  71. package/dist/commands/sources/init.js +1 -1
  72. package/dist/commands/sources/installed-stashes.js +2 -2
  73. package/dist/commands/sources/migration-help.js +1 -1
  74. package/dist/commands/sources/plugin-upgrade.js +8 -15
  75. package/dist/commands/sources/schema-repair.js +4 -8
  76. package/dist/commands/sources/source-add.js +2 -2
  77. package/dist/commands/sources/source-manage.js +4 -4
  78. package/dist/commands/targets.js +175 -0
  79. package/dist/commands/tasks/explain.js +103 -68
  80. package/dist/commands/tasks/tasks-cli.js +9 -11
  81. package/dist/commands/tasks/tasks.js +37 -41
  82. package/dist/commands/ui/api.js +11 -3
  83. package/dist/commands/ui/redact.js +1 -27
  84. package/dist/commands/ui/workspace-actions.js +1 -1
  85. package/dist/commands/workflow/plan.js +1 -1
  86. package/dist/commands/workflow-cli.js +3 -4
  87. package/dist/core/adapter/adapters/agent-skills-adapter.js +10 -11
  88. package/dist/core/adapter/adapters/akm-adapter.js +33 -38
  89. package/dist/core/adapter/adapters/akm-lint.js +7 -8
  90. package/dist/core/adapter/adapters/akm-task-adapter.js +3 -3
  91. package/dist/core/adapter/adapters/akm-workflow-adapter.js +5 -5
  92. package/dist/core/adapter/adapters/claude-adapter.js +1 -1
  93. package/dist/core/adapter/adapters/dotenv-adapter.js +3 -3
  94. package/dist/core/adapter/adapters/generic-files-adapter.js +5 -5
  95. package/dist/core/adapter/adapters/index.js +3 -4
  96. package/dist/core/adapter/adapters/llm-wiki-adapter.js +12 -14
  97. package/dist/core/adapter/adapters/okf-adapter.js +8 -10
  98. package/dist/core/adapter/adapters/opencode-adapter.js +1 -1
  99. package/dist/core/adapter/adapters/shared.js +3 -3
  100. package/dist/core/adapter/adapters/tool-dir-shared.js +7 -25
  101. package/dist/core/adapter/adapters/website-snapshot-adapter.js +3 -3
  102. package/dist/core/adapter/detect-adapter.js +1 -1
  103. package/dist/core/adapter/execution-source.js +13 -35
  104. package/dist/core/adapter/registry.js +1 -1
  105. package/dist/core/adapter/validate-context.js +2 -4
  106. package/dist/core/asset/asset-placement.js +1 -1
  107. package/dist/core/asset/asset-ref.js +3 -3
  108. package/dist/core/closest-match.js +37 -0
  109. package/dist/core/common.js +33 -5
  110. package/dist/core/config/config-io.js +26 -18
  111. package/dist/core/config/config-schema.js +19 -106
  112. package/dist/core/config/config-sources.js +3 -3
  113. package/dist/core/config/config-types.js +4 -4
  114. package/dist/core/config/config-walker.js +50 -77
  115. package/dist/core/config/config.js +385 -93
  116. package/dist/core/config/convert-engine-references.js +114 -0
  117. package/dist/core/config/convert-engines-shared.js +40 -0
  118. package/dist/core/config/convert-engines.js +300 -0
  119. package/dist/core/config/convert-models-overlay.js +137 -0
  120. package/dist/core/config/credentials.js +304 -0
  121. package/dist/core/config/engine-semantics.js +3 -3
  122. package/dist/core/config/migrate-keys.js +222 -0
  123. package/dist/core/config/model-aliases.js +37 -0
  124. package/dist/core/config/models-file.js +34 -0
  125. package/dist/core/config/retired-engines.js +53 -0
  126. package/dist/core/config/schema/connections.js +41 -0
  127. package/dist/core/config/schema/embedding.js +2 -2
  128. package/dist/core/config/schema/harnesses.js +41 -0
  129. package/dist/core/config/schema/improve-processes.js +9 -28
  130. package/dist/core/config/schema/improve.js +36 -1
  131. package/dist/core/config/schema/index-config.js +18 -20
  132. package/dist/core/config/schema/primitives.js +41 -22
  133. package/dist/core/config/schema/search.js +6 -11
  134. package/dist/core/config/schema/sources-bundles.js +7 -7
  135. package/dist/core/config/schema/workflow.js +2 -6
  136. package/dist/core/config/unusable-entries.js +66 -0
  137. package/dist/core/content-safety.js +3 -6
  138. package/dist/core/endpoint-url.js +47 -0
  139. package/dist/core/errors.js +9 -15
  140. package/dist/core/extra-params.js +3 -3
  141. package/dist/core/improve-result.js +8 -9
  142. package/dist/core/json-schema.js +1 -1
  143. package/dist/core/lesson-lint.js +1 -1
  144. package/dist/core/llm-inference.js +80 -0
  145. package/dist/core/parse.js +2 -2
  146. package/dist/core/paths.js +32 -4
  147. package/dist/core/recognition-util.js +8 -10
  148. package/dist/core/redaction.js +78 -52
  149. package/dist/core/state/migrations.js +17 -22
  150. package/dist/core/structured.js +2 -68
  151. package/dist/core/subprocess.js +63 -22
  152. package/dist/core/type-presentation.js +10 -14
  153. package/dist/execution/input-contract.js +3 -6
  154. package/dist/execution/notices.js +49 -0
  155. package/dist/execution/resolved-request.js +24 -40
  156. package/dist/execution/source.js +21 -45
  157. package/dist/execution/target-ref.js +2 -2
  158. package/dist/indexer/bundle-identity-guard.js +6 -5
  159. package/dist/indexer/ensure-index.js +1 -1
  160. package/dist/indexer/index-writer-lock.js +1 -1
  161. package/dist/indexer/indexer.js +19 -6
  162. package/dist/indexer/installations.js +11 -14
  163. package/dist/indexer/materialize-embeddings.js +20 -16
  164. package/dist/indexer/passes/memory-inference.js +21 -50
  165. package/dist/indexer/passes/metadata.js +5 -5
  166. package/dist/indexer/scan/doc-to-entry.js +1 -1
  167. package/dist/indexer/scan/drain-dir.js +6 -8
  168. package/dist/indexer/search/db-search.js +9 -7
  169. package/dist/indexer/search/search-source.js +40 -22
  170. package/dist/indexer/usage/usage-events.js +2 -3
  171. package/dist/indexer/walk/index-context.js +2 -1
  172. package/dist/indexer/walk/matchers.js +3 -11
  173. package/dist/indexer/walk/walker.js +14 -4
  174. package/dist/integrations/agent/akm-read-tools.js +81 -0
  175. package/dist/integrations/agent/config.js +1 -1
  176. package/dist/integrations/agent/detect.js +32 -36
  177. package/dist/integrations/agent/execution.js +130 -428
  178. package/dist/integrations/agent/index.js +1 -1
  179. package/dist/integrations/agent/profiles.js +24 -28
  180. package/dist/integrations/agent/prompts.js +17 -30
  181. package/dist/integrations/agent/request-lowering.js +67 -101
  182. package/dist/integrations/agent/resolution.js +332 -0
  183. package/dist/integrations/agent/runner-dispatch.js +154 -178
  184. package/dist/integrations/agent/runner.js +20 -72
  185. package/dist/integrations/agent/runtime-port.js +4 -0
  186. package/dist/integrations/agent/runtime.js +10 -0
  187. package/dist/integrations/agent/spawn.js +65 -190
  188. package/dist/integrations/harnesses/aider/index.js +19 -39
  189. package/dist/integrations/harnesses/amazonq/index.js +17 -32
  190. package/dist/integrations/harnesses/claude/index.js +59 -28
  191. package/dist/integrations/harnesses/claude/session-log.js +7 -5
  192. package/dist/integrations/harnesses/codex/index.js +19 -31
  193. package/dist/integrations/harnesses/copilot/index.js +17 -35
  194. package/dist/integrations/harnesses/gemini/index.js +18 -34
  195. package/dist/integrations/harnesses/harness.js +36 -0
  196. package/dist/integrations/harnesses/index.js +20 -51
  197. package/dist/integrations/harnesses/opencode/agent-builder.js +132 -100
  198. package/dist/integrations/harnesses/opencode/index.js +11 -33
  199. package/dist/integrations/harnesses/opencode/roots.js +50 -0
  200. package/dist/integrations/harnesses/opencode/runtime/binary.js +206 -0
  201. package/dist/integrations/harnesses/opencode/runtime/command.js +152 -0
  202. package/dist/integrations/harnesses/opencode/runtime/index.js +177 -0
  203. package/dist/integrations/harnesses/opencode/runtime/tar.js +107 -0
  204. package/dist/integrations/harnesses/opencode/session-log-v1.js +15 -7
  205. package/dist/integrations/harnesses/opencode/session-log-v2.js +72 -48
  206. package/dist/integrations/harnesses/opencode/session-log.js +58 -137
  207. package/dist/integrations/harnesses/opencode/version.js +34 -53
  208. package/dist/integrations/harnesses/openhands/index.js +13 -37
  209. package/dist/integrations/harnesses/pi/index.js +21 -32
  210. package/dist/integrations/lockfile.js +1 -1
  211. package/dist/integrations/session-logs/index.js +11 -31
  212. package/dist/llm/client.js +93 -111
  213. package/dist/llm/embedder.js +19 -34
  214. package/dist/llm/embedders/connection.js +31 -0
  215. package/dist/llm/embedders/local-model-files.js +56 -0
  216. package/dist/llm/embedders/local.js +146 -115
  217. package/dist/llm/embedders/remote.js +26 -24
  218. package/dist/llm/embedders/types.js +1 -1
  219. package/dist/llm/index-passes.js +33 -39
  220. package/dist/llm/memory-infer.js +67 -77
  221. package/dist/llm/model-list.js +35 -0
  222. package/dist/llm/rerank-client.js +8 -14
  223. package/dist/llm/structured-call.js +45 -99
  224. package/dist/llm/structured.js +60 -0
  225. package/dist/output/renderers.js +2 -7
  226. package/dist/output/shapes/helpers.js +18 -42
  227. package/dist/output/shapes/passthrough.js +1 -0
  228. package/dist/output/shapes.js +1 -7
  229. package/dist/output/text/command-format.js +29 -37
  230. package/dist/output/text/health-format.js +8 -2
  231. package/dist/output/text/helpers.js +1 -1
  232. package/dist/output/text/migrate.js +12 -0
  233. package/dist/output/text/models.js +3 -2
  234. package/dist/output/text/registry-commands.js +1 -2
  235. package/dist/output/text/show-format.js +0 -2
  236. package/dist/output/text/targets-table.js +70 -0
  237. package/dist/output/text/workflow-format.js +7 -8
  238. package/dist/output/text.js +1 -1
  239. package/dist/registry/providers/skills-sh.js +1 -28
  240. package/dist/registry/providers/static-index.js +1 -71
  241. package/dist/runtime.js +6 -2
  242. package/dist/scripts/akm-migrate-node.js +5280 -4263
  243. package/dist/scripts/akm-migrate.js +5280 -4263
  244. package/dist/setup/detect.js +28 -273
  245. package/dist/setup/endpoint.js +36 -0
  246. package/dist/setup/semantic-assets.js +13 -19
  247. package/dist/setup/setup-flags.js +77 -0
  248. package/dist/setup/setup-plan.js +144 -0
  249. package/dist/setup/setup.js +134 -358
  250. package/dist/setup/steps/connection-shared.js +49 -101
  251. package/dist/setup/steps/connection.js +121 -524
  252. package/dist/setup/steps/embeddings.js +151 -0
  253. package/dist/setup/steps/harnesses.js +118 -0
  254. package/dist/setup/steps/platforms.js +2 -81
  255. package/dist/setup/steps.js +10 -0
  256. package/dist/setup/summary.js +67 -0
  257. package/dist/sources/freshness.js +16 -21
  258. package/dist/sources/providers/git-provider.js +2 -9
  259. package/dist/sources/providers/provider-utils.js +1 -5
  260. package/dist/sources/snapshot-fetchers/robots.js +11 -12
  261. package/dist/sources/snapshot-fetchers/website-ingest.js +8 -15
  262. package/dist/standalone/onnxruntime-library.js +52 -0
  263. package/dist/storage/repositories/improve-ledger-repository.js +1 -1
  264. package/dist/storage/repositories/improve-runs-repository.js +0 -13
  265. package/dist/storage/repositories/index-entries-repository.js +2 -2
  266. package/dist/storage/repositories/workflow-runs-repository.js +8 -15
  267. package/dist/storage/sqlite-read-snapshot.js +33 -29
  268. package/dist/tasks/log-redaction.js +7 -119
  269. package/dist/tasks/prepare/prepare-support.js +5 -5
  270. package/dist/tasks/prepare/prepare.js +5 -5
  271. package/dist/tasks/prepare/script-capture.js +3 -5
  272. package/dist/tasks/run/attempt-lifecycle.js +17 -35
  273. package/dist/tasks/run/load-task.js +8 -13
  274. package/dist/tasks/run/run-command-task.js +15 -10
  275. package/dist/tasks/run/run-native-task.js +8 -13
  276. package/dist/tasks/run/run-task.js +5 -8
  277. package/dist/tasks/run/run-workflow-task.js +12 -19
  278. package/dist/tasks/run/task-history.js +9 -17
  279. package/dist/tasks/run/task-log.js +1 -5
  280. package/dist/tasks/scheduler-invocation.js +13 -18
  281. package/dist/tasks/source/bounded-document.js +31 -76
  282. package/dist/tasks/source/project-v4.js +5 -3
  283. package/dist/tasks/source/task-input-diagnostics.js +3 -4
  284. package/dist/tasks/source/task-source-v4.js +47 -68
  285. package/dist/tasks/source-v3.js +2 -5
  286. package/dist/tasks/task-run-reserved-flags.js +1 -2
  287. package/dist/workflows/authoring/authoring.js +2 -7
  288. package/dist/workflows/concurrency-policy.js +4 -4
  289. package/dist/workflows/exec/child-workflow.js +0 -2
  290. package/dist/workflows/exec/dispatch-redaction.js +14 -83
  291. package/dist/workflows/exec/environment.js +2 -3
  292. package/dist/workflows/exec/exec-unit.js +10 -59
  293. package/dist/workflows/exec/frozen-judge.js +10 -26
  294. package/dist/workflows/exec/native-executor.js +56 -45
  295. package/dist/workflows/exec/run-workflow.js +7 -24
  296. package/dist/workflows/exec/step-work.js +9 -14
  297. package/dist/workflows/exec/unit-dispatch.js +6 -13
  298. package/dist/workflows/freeze/freeze.js +14 -32
  299. package/dist/workflows/freeze/step-values.js +5 -11
  300. package/dist/workflows/freeze/targets/command.js +3 -6
  301. package/dist/workflows/freeze/task-bindings.js +0 -1
  302. package/dist/workflows/parser.js +44 -34
  303. package/dist/workflows/plan.js +3 -1
  304. package/dist/workflows/renderer.js +6 -5
  305. package/dist/workflows/resource-limits.js +2 -2
  306. package/dist/workflows/runtime/run-plan.js +2 -1
  307. package/dist/workflows/runtime/runs.js +14 -9
  308. package/docs/README.md +10 -16
  309. package/docs/architecture/README.md +2 -37
  310. package/docs/architecture/adapters.md +2 -2
  311. package/docs/architecture/akm-core-principles.md +256 -118
  312. package/docs/architecture/architecture.md +282 -98
  313. package/docs/architecture/improvement.md +8 -2
  314. package/docs/architecture/internals/classification.md +1 -3
  315. package/docs/architecture/internals/fresh-host-rebuild-runbook.md +7 -6
  316. package/docs/architecture/internals/health-advisories.md +35 -74
  317. package/docs/architecture/internals/improve-workflow.md +27 -26
  318. package/docs/architecture/internals/indexing.md +3 -3
  319. package/docs/architecture/internals/storage-locations.md +45 -12
  320. package/docs/architecture/persisted-data-compat.md +9 -6
  321. package/docs/architecture/specs/okf-support.md +9 -11
  322. package/docs/architecture/specs/ref.md +7 -9
  323. package/docs/architecture/testing/testing-workflow.md +164 -42
  324. package/docs/architecture/workflow-engine.md +17 -14
  325. package/docs/guides/README.md +0 -1
  326. package/docs/guides/author-bundles.md +1 -3
  327. package/docs/guides/author-workflows.md +61 -73
  328. package/docs/guides/bundles.md +4 -5
  329. package/docs/guides/discover-and-load.md +1 -1
  330. package/docs/guides/getting-started.md +49 -3
  331. package/docs/guides/improve-the-library.md +10 -4
  332. package/docs/guides/recipes/headless-install.md +11 -16
  333. package/docs/guides/run-workflows.md +6 -9
  334. package/docs/guides/scheduling.md +2 -2
  335. package/docs/guides/use-with-any-agent.md +20 -22
  336. package/docs/integration/bundling-akm.md +19 -9
  337. package/docs/maintainers/README.md +0 -3
  338. package/docs/migration/README.md +10 -3
  339. package/docs/migration/release-notes/0.10.0.md +81 -16
  340. package/docs/migration/release-notes/0.6.0.md +1 -1
  341. package/docs/migration/release-notes/0.7.0.md +1 -1
  342. package/docs/migration/release-notes/0.9.0.md +1 -1
  343. package/docs/migration/release-notes/README.md +1 -1
  344. package/docs/migration/v0.9-to-v0.10.md +295 -59
  345. package/docs/migration/v0.9.1-to-v0.9.2.md +6 -5
  346. package/docs/posts/config-v2-lessons-16.md +1 -1
  347. package/docs/posts/llm-mode-reflect-13.md +1 -1
  348. package/docs/posts/release-0.6.0.md +11 -11
  349. package/docs/posts/release-0.8.0.md +4 -4
  350. package/docs/posts/workflows-vaults-09.md +1 -1
  351. package/docs/reference/README.md +1 -1
  352. package/docs/reference/asset-types.md +2 -2
  353. package/docs/reference/cli.md +356 -279
  354. package/docs/reference/configuration.md +569 -557
  355. package/docs/reference/data-and-telemetry.md +8 -5
  356. package/docs/reference/env-and-secrets.md +11 -5
  357. package/docs/reference/refs.md +3 -20
  358. package/docs/reference/registry.md +6 -27
  359. package/docs/reference/supported-formats.md +1 -1
  360. package/docs/reference/tasks.md +11 -8
  361. package/docs/reference/ui-api.md +11 -6
  362. package/docs/reference/workflow-schema.md +106 -134
  363. package/docs/reference/workflows.md +4 -6
  364. package/package.json +9 -11
  365. package/schemas/akm-config.json +1696 -2922
  366. package/schemas/akm-task.json +2 -0
  367. package/schemas/akm-workflow.json +36 -9
  368. package/ROADMAP.md +0 -112
  369. package/dist/assets/models.json +0 -35
  370. package/dist/commands/health/engine-usage.js +0 -45
  371. package/dist/core/config/schema/engines.js +0 -160
  372. package/dist/core/config/schema/execution.js +0 -23
  373. package/dist/core/spawn-env.js +0 -268
  374. package/dist/integrations/agent/builder-shared.js +0 -33
  375. package/dist/integrations/agent/builders.js +0 -43
  376. package/dist/integrations/agent/engine-fallback.js +0 -59
  377. package/dist/integrations/agent/engine-resolution.js +0 -335
  378. package/dist/integrations/agent/model-map.js +0 -475
  379. package/dist/integrations/harnesses/aider/agent-builder.js +0 -107
  380. package/dist/integrations/harnesses/aider/result-extractor.js +0 -53
  381. package/dist/integrations/harnesses/amazonq/agent-builder.js +0 -138
  382. package/dist/integrations/harnesses/amazonq/result-extractor.js +0 -48
  383. package/dist/integrations/harnesses/claude/agent-builder.js +0 -106
  384. package/dist/integrations/harnesses/claude/config-import.js +0 -67
  385. package/dist/integrations/harnesses/claude/result-extractor.js +0 -67
  386. package/dist/integrations/harnesses/codex/agent-builder.js +0 -150
  387. package/dist/integrations/harnesses/codex/result-extractor.js +0 -110
  388. package/dist/integrations/harnesses/copilot/agent-builder.js +0 -117
  389. package/dist/integrations/harnesses/copilot/result-extractor.js +0 -178
  390. package/dist/integrations/harnesses/gemini/agent-builder.js +0 -114
  391. package/dist/integrations/harnesses/gemini/result-extractor.js +0 -149
  392. package/dist/integrations/harnesses/opencode/config-import.js +0 -149
  393. package/dist/integrations/harnesses/opencode/model-config.js +0 -33
  394. package/dist/integrations/harnesses/opencode/model-work-agent.js +0 -115
  395. package/dist/integrations/harnesses/opencode/session-log-types.js +0 -12
  396. package/dist/integrations/harnesses/opencode-sdk/index.js +0 -44
  397. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +0 -1052
  398. package/dist/integrations/harnesses/opencode-sdk/v1-adapter.js +0 -199
  399. package/dist/integrations/harnesses/opencode-sdk/v2-adapter.js +0 -254
  400. package/dist/integrations/harnesses/opencode-sdk/wire.js +0 -66
  401. package/dist/integrations/harnesses/openhands/agent-builder.js +0 -120
  402. package/dist/integrations/harnesses/openhands/result-extractor.js +0 -135
  403. package/dist/integrations/harnesses/pi/agent-builder.js +0 -89
  404. package/dist/integrations/harnesses/pi/result-extractor.js +0 -168
  405. package/dist/integrations/harnesses/shared.js +0 -18
  406. package/dist/integrations/harnesses/types.js +0 -55
  407. package/dist/llm/feature-gate.js +0 -115
  408. package/dist/output/shapes/models-list.js +0 -16
  409. package/dist/output/shapes/registry-search.js +0 -10
  410. package/dist/setup/detected-engines.js +0 -136
  411. package/dist/setup/engine-config.js +0 -97
  412. package/dist/setup/harness-config-import.js +0 -47
  413. package/dist/setup/providers.js +0 -14
  414. package/dist/setup/steps/semantic.js +0 -39
  415. package/dist/workflows/exec/lowering-notices.js +0 -23
  416. package/docs/architecture/0.10-process-rules.md +0 -832
  417. package/docs/architecture/akm-architecture-decision-history.md +0 -2055
  418. package/docs/architecture/comparisons/claude-code-vs-akm-workflows-full.md +0 -544
  419. package/docs/architecture/decisions/0001-no-interpolation-attached-structured-context.md +0 -72
  420. package/docs/architecture/decisions/0002-unit-reuse-and-input-hash-scope.md +0 -142
  421. package/docs/architecture/decisions/0003-child-env-allowlist-and-provenance.md +0 -187
  422. package/docs/architecture/decisions/0004-task-input-contract-and-flag-coercion.md +0 -97
  423. package/docs/architecture/decisions/0005-task-result-vocabulary-and-legacy-read-mapping.md +0 -108
  424. package/docs/architecture/decisions/0006-task-source-version-routing.md +0 -124
  425. package/docs/architecture/decisions/0007-workflow-composition-bounds.md +0 -83
  426. package/docs/architecture/decisions/0008-task-binding-normalization.md +0 -88
  427. package/docs/architecture/decisions/0009-child-run-publication-column-parity.md +0 -80
  428. package/docs/architecture/decisions/0010-driver-protocol-cut.md +0 -36
  429. package/docs/architecture/decisions/0011-engine-run-loop-invariants.md +0 -125
  430. package/docs/architecture/decisions/README.md +0 -62
  431. package/docs/architecture/internals/functional-contract-patterns.md +0 -340
  432. package/docs/architecture/internals/registry-network-boundary.md +0 -57
  433. package/docs/architecture/internals/search.md +0 -248
  434. package/docs/architecture/reviews/env-secret-access.md +0 -319
  435. package/docs/architecture/runtime-boundary-design.md +0 -153
  436. package/docs/architecture/specs/0.9.0-close-out-plan.md +0 -361
  437. package/docs/architecture/specs/0.9.0-decisions.md +0 -532
  438. package/docs/architecture/specs/0.9.0-docs-code-drift-register.md +0 -745
  439. package/docs/architecture/specs/0.9.0-open-items-register.md +0 -135
  440. package/docs/architecture/specs/0.9.0-public-api-issue-backlog.md +0 -740
  441. package/docs/architecture/specs/0.9.0-release-surface-review.md +0 -636
  442. package/docs/architecture/specs/agent-command-engine-model-design.md +0 -513
  443. package/docs/architecture/specs/akm-0.9.0-bundle-adapter-spec.md +0 -501
  444. package/docs/architecture/specs/akm-0.9.0-ref-grammar-decision.md +0 -291
  445. package/docs/architecture/specs/akm-format-neutral-bundle-workspace-spec.md +0 -2059
  446. package/docs/architecture/specs/di-seams-plan.md +0 -539
  447. package/docs/architecture/specs/driver-protocol-keep-or-cut.md +0 -275
  448. package/docs/architecture/specs/fact-asset-type.md +0 -142
  449. package/docs/architecture/specs/improve-collapse-churn-detector-design.md +0 -634
  450. package/docs/architecture/specs/reviews/task-workflow-unification/README.md +0 -72
  451. package/docs/architecture/specs/reviews/task-workflow-unification/findings-consolidated.md +0 -152
  452. package/docs/architecture/specs/reviews/task-workflow-unification/library-eval-alternatives.md +0 -352
  453. package/docs/architecture/specs/reviews/task-workflow-unification/library-eval-bunqueue.md +0 -300
  454. package/docs/architecture/specs/reviews/task-workflow-unification/library-eval-openworkflow.md +0 -402
  455. package/docs/architecture/specs/reviews/task-workflow-unification/opus-review-1.md +0 -758
  456. package/docs/architecture/specs/reviews/task-workflow-unification/opus-review-2.md +0 -645
  457. package/docs/architecture/specs/reviews/task-workflow-unification/opus-review-3.md +0 -602
  458. package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-adversarial.md +0 -27
  459. package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-architecture.md +0 -27
  460. package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-coverage.md +0 -74
  461. package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-security.md +0 -15
  462. package/docs/architecture/specs/reviews/task-workflow-unification/panel-r2-adversarial.md +0 -132
  463. package/docs/architecture/specs/reviews/task-workflow-unification/panel-r2-verification.md +0 -147
  464. package/docs/architecture/specs/stash-conventions-code-spec.md +0 -275
  465. package/docs/architecture/specs/stash-organization-conventions.md +0 -377
  466. package/docs/architecture/specs/task-workflow-format-unification.md +0 -721
  467. package/docs/architecture/specs/workflow-engine-buy-vs-build.md +0 -231
  468. package/docs/architecture/specs/workflow-format-unification.md +0 -432
  469. package/docs/architecture/testing/manual-testing-checklist.md +0 -3379
  470. package/docs/architecture/testing/okf-v0.2-conformance-runbook.md +0 -924
  471. package/docs/architecture/testing/task-workflow-manual-tests.md +0 -1702
  472. package/docs/guides/claude-code-vs-akm-workflows.md +0 -29
  473. package/docs/guides/knowledge-management.md +0 -18
  474. package/docs/maintainers/curate-workmap.md +0 -335
  475. package/docs/migration/v0.5-to-v0.6.md +0 -759
  476. package/docs/migration/v0.7-to-v0.8.md +0 -1378
  477. 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
+ };