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,107 @@
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
+ * One member of a gzip-compressed tar archive, streamed to a file. This is all
6
+ * akm needs of tar: the OpenCode binary is a single regular file of about 240 MB
7
+ * inside its package tarball, so it is never held in memory and no tar library
8
+ * is a dependency.
9
+ */
10
+ import fs from "node:fs";
11
+ import { pipeline } from "node:stream";
12
+ import zlib from "node:zlib";
13
+ const BLOCK_BYTES = 512;
14
+ /** Exact reads from a stream of chunks. */
15
+ class ByteReader {
16
+ #chunks;
17
+ #pending = Buffer.alloc(0);
18
+ constructor(source) {
19
+ this.#chunks = source[Symbol.asyncIterator]();
20
+ }
21
+ /** Up to `max` bytes, at least one unless the stream has ended (`undefined`). */
22
+ async read(max) {
23
+ if (this.#pending.length === 0) {
24
+ const next = await this.#chunks.next();
25
+ if (next.done)
26
+ return undefined;
27
+ this.#pending = next.value;
28
+ }
29
+ const taken = this.#pending.subarray(0, max);
30
+ this.#pending = this.#pending.subarray(taken.length);
31
+ return taken;
32
+ }
33
+ async exact(count) {
34
+ const parts = [];
35
+ for (let left = count; left > 0;) {
36
+ const part = await this.read(left);
37
+ if (!part)
38
+ throw new Error("the archive ends inside an entry");
39
+ parts.push(part);
40
+ left -= part.length;
41
+ }
42
+ return Buffer.concat(parts);
43
+ }
44
+ async skip(count) {
45
+ for (let left = count; left > 0;) {
46
+ const part = await this.read(left);
47
+ if (!part)
48
+ throw new Error("the archive ends inside an entry");
49
+ left -= part.length;
50
+ }
51
+ }
52
+ }
53
+ /** A header field of NUL-terminated text. */
54
+ const field = (header, start, end) => {
55
+ const bytes = header.subarray(start, end);
56
+ const stop = bytes.indexOf(0);
57
+ return bytes.subarray(0, stop < 0 ? bytes.length : stop).toString("utf8");
58
+ };
59
+ /**
60
+ * Write the regular file `member` of the `.tgz` at `archive` to `destination` (mode 0755) and return its size. Entries
61
+ * are matched by the header's name field alone, which holds up to 100 bytes; a longer name, which tar keeps in the
62
+ * ustar prefix field or a PAX `path` record, is not read, so such a member is never found. The one member akm reads,
63
+ * `package/bin/opencode`, is short. Extended headers are skipped like any other entry that is not the member.
64
+ */
65
+ export async function extractTarGzMember(archive, member, destination) {
66
+ const gunzip = zlib.createGunzip();
67
+ pipeline(fs.createReadStream(archive), gunzip, () => { });
68
+ const reader = new ByteReader(gunzip);
69
+ try {
70
+ return await extractFrom(reader, archive, member, destination);
71
+ }
72
+ finally {
73
+ // The rest of the archive is not read: close it now rather than when the stream is collected.
74
+ gunzip.destroy();
75
+ }
76
+ }
77
+ async function extractFrom(reader, archive, member, destination) {
78
+ for (;;) {
79
+ const header = await reader.exact(BLOCK_BYTES);
80
+ if (header.every((byte) => byte === 0))
81
+ throw new Error(`${archive} has no ${member}`);
82
+ const name = field(header, 0, 100).replace(/^\.\//, "");
83
+ const typeflag = String.fromCharCode(header[156] ?? 0);
84
+ const size = Number.parseInt(field(header, 124, 136).trim() || "0", 8);
85
+ if (!Number.isSafeInteger(size))
86
+ throw new Error(`${archive} is not a tar archive this reader understands`);
87
+ const padding = (BLOCK_BYTES - (size % BLOCK_BYTES)) % BLOCK_BYTES;
88
+ if (name !== member || (typeflag !== "0" && typeflag !== "\0")) {
89
+ await reader.skip(size + padding);
90
+ continue;
91
+ }
92
+ const out = await fs.promises.open(destination, "w", 0o755);
93
+ try {
94
+ for (let left = size; left > 0;) {
95
+ const part = await reader.read(left);
96
+ if (!part)
97
+ throw new Error(`${archive} ends inside ${member}`);
98
+ await out.writeFile(part);
99
+ left -= part.length;
100
+ }
101
+ }
102
+ finally {
103
+ await out.close();
104
+ }
105
+ return size;
106
+ }
107
+ }
@@ -2,7 +2,16 @@
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
4
  import { extractInlineRefMentions } from "../../session-logs/inline-refs.js";
5
- import { toMeta } from "./session-log-types.js";
5
+ /** The metadata of a row, with a column that is absent or empty left out. */
6
+ export function toMeta(r, sessionId) {
7
+ return {
8
+ sessionId,
9
+ startedAt: typeof r.time_created === "number" ? r.time_created : undefined,
10
+ endedAt: typeof r.time_updated === "number" ? r.time_updated : undefined,
11
+ projectHint: typeof r.directory === "string" && r.directory.length > 0 ? r.directory : undefined,
12
+ title: typeof r.title === "string" && r.title.length > 0 ? r.title : undefined,
13
+ };
14
+ }
6
15
  /** Listing needs only `session`; reading a session needs `message` and `part`, and fails loudly without them. */
7
16
  export const V1_TABLES = ["session"];
8
17
  /** Every V1 session updated at or after `sinceMs`, newest first. Throws on an incompatible schema. */
@@ -12,18 +21,17 @@ export function listV1Sessions(db, sinceMs) {
12
21
  .all(sinceMs);
13
22
  return rows.map((r) => toMeta(r, r.id));
14
23
  }
15
- /** Whether a V1 `session` row exists for `sessionId`. */
16
- export function hasV1Session(db, sessionId) {
17
- return db.prepare("SELECT id FROM session WHERE id = ?").get(sessionId) !== undefined;
18
- }
19
24
  /**
20
25
  * One event per message, text-parts concatenated in time order. Throws on an
21
- * incompatible schema; individual unparsable rows are skipped.
26
+ * incompatible schema or a session that is not in the file; individual unparsable
27
+ * rows are skipped.
22
28
  */
23
29
  export function readV1Session(db, harness, sessionId, filePath) {
24
30
  const meta = db
25
31
  .prepare("SELECT title, directory, time_created, time_updated FROM session WHERE id = ?")
26
32
  .get(sessionId);
33
+ if (!meta)
34
+ throw new Error(`session ${sessionId} is not in the file`);
27
35
  const messages = db
28
36
  .prepare("SELECT id, data, time_created FROM message WHERE session_id = ? ORDER BY time_created ASC, id ASC")
29
37
  .all(sessionId);
@@ -68,5 +76,5 @@ export function readV1Session(db, harness, sessionId, filePath) {
68
76
  inlineRefs.push(...extractInlineRefMentions(text, ts));
69
77
  }
70
78
  events.sort((a, b) => (a.ts ?? 0) - (b.ts ?? 0));
71
- return { meta: meta ? toMeta(meta, sessionId) : { sessionId }, events, inlineRefs };
79
+ return { meta: toMeta(meta, sessionId), events, inlineRefs };
72
80
  }
@@ -2,37 +2,25 @@
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
4
  /**
5
- * OpenCode 2 session-store adapter. V2 keeps one `session_v2` row per session
6
- * and the ordered conversation as `session_message` rows (`type` + JSON `data`
7
- * minus `id`/`type`, shapes from `@opencode/client` `SessionMessageInfo`).
8
- * Read-only: the database is never migrated; V1 rows a native upgrade copied
9
- * here arrive as the same shapes under the same session id.
5
+ * OpenCode 2 session store: the `session_v2` and `session_message` tables, read
6
+ * with SQLite only. Nothing here starts OpenCode (which would migrate the file
7
+ * and resume its suspended sessions); it reads the rows as they are.
10
8
  *
11
- * Mapping into the session-log contract follows the Codex reader: user and
12
- * assistant text become events of that role, a tool call becomes
13
- * `[tool:<name>] <input>` and its outcome a `tool` event
14
- * `[tool_result] <output>`, so the inline-ref scanner sees shell commands.
15
- * Reasoning, compaction, synthetic/system and bookkeeping messages are skipped.
9
+ * A message row is `(id, type, data)`; OpenCode decodes it as `{ ...data, id, type }`,
10
+ * which is rebuilt here. Only top-level sessions are read, and akm's own
11
+ * model-work sessions are left out: OpenCode 2 stores the agent a session ran as,
12
+ * and akm runs model work as one agent (`./agent-builder.ts`).
13
+ *
14
+ * Mapping to events follows the Codex reader: user and assistant text become events of
15
+ * that role, a tool call becomes `[tool:<name>] <input>` and its outcome a
16
+ * `tool` event `[tool_result] <output>`, so the inline-ref scanner sees shell
17
+ * commands. Reasoning, compaction, synthetic/system and bookkeeping messages
18
+ * are skipped.
16
19
  */
17
20
  import { asRecord, tryParseJson } from "../../../core/common.js";
18
- import { warnOnce } from "../../../core/warn.js";
19
21
  import { extractInlineRefMentions } from "../../session-logs/inline-refs.js";
20
- import { toMeta } from "./session-log-types.js";
21
- export const V2_TABLES = ["session_v2", "session_message"];
22
- /** Every V2 session updated at or after `sinceMs`, newest first. Throws on an incompatible schema. */
23
- export function listV2Sessions(db, sinceMs) {
24
- const rows = db
25
- .prepare("SELECT id, title, directory, time_created, time_updated FROM session_v2 WHERE time_updated >= ? ORDER BY time_updated DESC")
26
- .all(sinceMs);
27
- return rows.map((r) => toMeta(r, r.id));
28
- }
29
- /** Whether `sessionId` has a `session_v2` row, and how many `session_message` rows it owns. */
30
- export function v2SessionState(db, sessionId) {
31
- const row = db
32
- .prepare("SELECT (SELECT COUNT(*) FROM session_message WHERE session_id = s.id) AS n FROM session_v2 s WHERE s.id = ?")
33
- .get(sessionId);
34
- return row ? { exists: true, messages: row.n } : { exists: false, messages: 0 };
35
- }
22
+ import { MODEL_WORK_AGENT } from "./agent-builder.js";
23
+ import { toMeta } from "./session-log-v1.js";
36
24
  const asObject = asRecord;
37
25
  function asNumber(v) {
38
26
  return typeof v === "number" ? v : undefined;
@@ -69,17 +57,8 @@ function structuredErrorText(err) {
69
57
  return e.message;
70
58
  return typeof e?.type === "string" ? e.type : "error";
71
59
  }
72
- /**
73
- * Rebuild one session's events in `seq` order. Throws on an incompatible
74
- * schema; a message whose JSON cannot be read is skipped with one warning.
75
- */
76
- export function readV2Session(db, harness, sessionId, filePath) {
77
- const meta = db
78
- .prepare("SELECT title, directory, time_created, time_updated FROM session_v2 WHERE id = ?")
79
- .get(sessionId);
80
- const rows = db
81
- .prepare("SELECT id, type, data, time_created FROM session_message WHERE session_id = ? ORDER BY seq ASC, time_created ASC, id ASC")
82
- .all(sessionId);
60
+ /** One session's events and inline refs, from its messages oldest first. A message that is not an object is skipped. */
61
+ export function opencodeMessageEvents(messages, harness, sessionId, filePath) {
83
62
  const events = [];
84
63
  const inlineRefs = [];
85
64
  const push = (role, text, ts) => {
@@ -89,18 +68,16 @@ export function readV2Session(db, harness, sessionId, filePath) {
89
68
  events.push({ harness, text: trimmed, ts, sessionId, role, filePath });
90
69
  inlineRefs.push(...extractInlineRefMentions(trimmed, ts));
91
70
  };
92
- for (const row of rows) {
93
- const data = asObject(tryParseJson(row.data));
94
- if (!data) {
95
- warnOnce(`opencode-v2-message:${filePath}:${row.id}`, `OpenCode 2 history: skipped unreadable message ${row.id} in session ${sessionId} (${filePath}).`);
71
+ for (const message of messages) {
72
+ const data = asObject(message);
73
+ if (!data)
96
74
  continue;
97
- }
98
- const ts = asNumber(asObject(data.time)?.created) ?? asNumber(row.time_created);
99
- if (row.type === "user") {
75
+ const ts = asNumber(asObject(data.time)?.created);
76
+ if (data.type === "user") {
100
77
  if (typeof data.text === "string")
101
78
  push("user", data.text, ts);
102
79
  }
103
- else if (row.type === "assistant") {
80
+ else if (data.type === "assistant") {
104
81
  const content = Array.isArray(data.content) ? data.content : [];
105
82
  const text = content
106
83
  .map((c) => asObject(c))
@@ -128,7 +105,7 @@ export function readV2Session(db, harness, sessionId, filePath) {
128
105
  }
129
106
  }
130
107
  }
131
- else if (row.type === "shell") {
108
+ else if (data.type === "shell") {
132
109
  if (typeof data.command === "string")
133
110
  push("assistant", `[tool:shell] ${data.command}`, ts);
134
111
  const out = asObject(data.output)?.output;
@@ -136,5 +113,52 @@ export function readV2Session(db, harness, sessionId, filePath) {
136
113
  push("tool", `[tool_result] ${out}`, ts);
137
114
  }
138
115
  }
139
- return { meta: meta ? toMeta(meta, sessionId) : { sessionId }, events, inlineRefs };
116
+ return { events, inlineRefs };
117
+ }
118
+ /** The columns of each table akm reads; a file lacking one is a schema akm does not support. */
119
+ const V2_COLUMNS = {
120
+ session_v2: ["id", "parent_id", "title", "directory", "agent", "time_created", "time_updated"],
121
+ session_message: ["id", "session_id", "type", "seq", "data"],
122
+ };
123
+ /** Whether `db` has the OpenCode 2 session tables with the columns akm reads. */
124
+ export function hasV2Tables(db) {
125
+ return Object.entries(V2_COLUMNS).every(([table, columns]) => {
126
+ const present = new Set(db
127
+ .prepare(`PRAGMA table_info(${table})`)
128
+ .all()
129
+ .map((c) => c.name));
130
+ return columns.every((column) => present.has(column));
131
+ });
132
+ }
133
+ /** Top-level sessions that are not akm's model work. */
134
+ const AKM_USER_SESSIONS = `parent_id IS NULL AND (agent IS NULL OR agent != '${MODEL_WORK_AGENT}')`;
135
+ /** Every top-level OpenCode 2 session updated at or after `sinceMs`, newest first. Throws on an incompatible schema. */
136
+ export function listV2Sessions(db, sinceMs) {
137
+ return db
138
+ .prepare(`SELECT id, title, directory, time_created, time_updated FROM session_v2 WHERE ${AKM_USER_SESSIONS} AND time_updated >= ? ORDER BY time_updated DESC`)
139
+ .all(sinceMs)
140
+ .map((row) => toMeta(row, row.id));
141
+ }
142
+ /**
143
+ * The tokens one session's turns used: OpenCode records them on each assistant message and keeps their sums on the
144
+ * session row (equal, measured on 2.1.4). Undefined when the session is not in the file.
145
+ */
146
+ export function v2SessionTokens(db, sessionId) {
147
+ const row = db
148
+ .prepare("SELECT tokens_input, tokens_output, tokens_reasoning FROM session_v2 WHERE id = ?")
149
+ .get(sessionId);
150
+ return row ? { input: row.tokens_input, output: row.tokens_output, reasoning: row.tokens_reasoning } : undefined;
151
+ }
152
+ /** One session's events, from its messages in order. Throws when the session is not in the file. */
153
+ export function readV2Session(db, harness, sessionId, filePath) {
154
+ const row = db
155
+ .prepare("SELECT title, directory, time_created, time_updated FROM session_v2 WHERE id = ?")
156
+ .get(sessionId);
157
+ if (!row)
158
+ throw new Error(`session ${sessionId} is not in the file`);
159
+ const messages = db
160
+ .prepare("SELECT id, type, data FROM session_message WHERE session_id = ? ORDER BY seq ASC")
161
+ .all(sessionId)
162
+ .map((message) => ({ ...asRecord(tryParseJson(message.data)), id: message.id, type: message.type }));
163
+ return { meta: toMeta(row, sessionId), ...opencodeMessageEvents(messages, harness, sessionId, filePath) };
140
164
  }
@@ -2,167 +2,88 @@
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
4
  import fs from "node:fs";
5
- import os from "node:os";
6
- import path from "node:path";
7
5
  import { toErrorMessage } from "../../../core/common.js";
8
6
  import { warnOnce } from "../../../core/warn.js";
9
7
  import { openDatabase } from "../../../storage/database.js";
10
8
  import { openSqliteReadSnapshot } from "../../../storage/sqlite-read-snapshot.js";
11
9
  import { AbstractSessionLogProvider } from "../../session-logs/provider-base.js";
12
- import { hasV1Session, listV1Sessions, readV1Session, V1_TABLES } from "./session-log-v1.js";
13
- import { listV2Sessions, readV2Session, V2_TABLES, v2SessionState } from "./session-log-v2.js";
14
- function getOpenCodeBaseDir() {
15
- if (process.platform === "darwin") {
16
- return path.join(os.homedir(), "Library", "Application Support", "opencode");
17
- }
18
- return path.join(os.homedir(), ".local", "share", "opencode");
19
- }
20
- /**
21
- * OpenCode session storage: one SQLite file, `<base>/opencode.db`, whose
22
- * layout decides the reader, never the installed binary or its version:
23
- *
24
- * - V1: `session` table, with `message` / `part` for content (`session-log-v1.ts`).
25
- * - V2: `session_v2` / `session_message` tables (`session-log-v2.ts`).
26
- * - Both: a natively upgraded V1 file keeps its V1 tables and gains the V2
27
- * ones. Sessions are merged by id, V2 winning, V1-only ones kept.
28
- * - Neither: an unsupported layout, reported, never presented as empty.
29
- *
30
- * The file is opened read-only and never migrated or written.
31
- */
32
- /** Filename of opencode's SQLite session store, relative to its base dir. */
33
- const OPENCODE_DB_FILENAME = "opencode.db";
34
- function tableNames(db) {
10
+ import { akmOpencodeDatabasePath, databaseIn, opencodeDatabasePath } from "./roots.js";
11
+ import { listV1Sessions, readV1Session, V1_TABLES } from "./session-log-v1.js";
12
+ import { hasV2Tables, listV2Sessions, readV2Session } from "./session-log-v2.js";
13
+ function layoutOf(db) {
35
14
  const rows = db.prepare("SELECT name FROM sqlite_master WHERE type = 'table'").all();
36
- return new Set(rows.map((r) => r.name));
37
- }
38
- function classify(tables) {
39
- const v1 = V1_TABLES.every((t) => tables.has(t));
40
- const v2 = V2_TABLES.every((t) => tables.has(t));
41
- return v1 || v2 ? { kind: "ok", v1, v2 } : { kind: "unsupported", tables: [...tables].sort() };
15
+ const tables = new Set(rows.map((r) => r.name));
16
+ if (tables.has("session_v2") && hasV2Tables(db))
17
+ return "v2";
18
+ return V1_TABLES.every((t) => tables.has(t)) && !tables.has("session_v2") ? "v1" : "unsupported";
42
19
  }
43
20
  export class OpenCodeProvider extends AbstractSessionLogProvider {
44
21
  name = "opencode";
45
- #baseDir = getOpenCodeBaseDir();
22
+ #userDatabase = opencodeDatabasePath();
46
23
  availabilityRoot() {
47
- return this.#dbPath(this.#baseDir);
24
+ return this.#userDatabase;
48
25
  }
49
- /** Absolute path to opencode's SQLite store under `base`. */
50
- #dbPath(base) {
51
- return path.join(base, OPENCODE_DB_FILENAME);
26
+ /** The user's OpenCode history, or akm's own. */
27
+ isAvailable() {
28
+ return super.isAvailable() || fs.existsSync(akmOpencodeDatabasePath());
52
29
  }
53
- /** Classify the store under `location` (default: opencode's data dir) without listing anything. */
54
- inspectStore(location) {
55
- const dbPath = this.#dbPath(location ?? this.#baseDir);
56
- if (!fs.existsSync(dbPath))
57
- return { kind: "missing" };
58
- let db;
59
- try {
60
- db = openDatabase(dbPath, { readonly: true, create: false });
61
- }
62
- catch (error) {
63
- return { kind: "unreadable", reason: toErrorMessage(error) };
64
- }
65
- try {
66
- return classify(tableNames(db));
67
- }
68
- catch (error) {
69
- return { kind: "unreadable", reason: toErrorMessage(error) };
70
- }
71
- finally {
72
- db.close();
73
- }
30
+ /** The stores to read: the one under `location`, else the user's and akm's. */
31
+ #stores(location) {
32
+ if (location)
33
+ return [databaseIn(location)];
34
+ return [this.#userDatabase, akmOpencodeDatabasePath()];
74
35
  }
75
- listSessions(input = {}) {
76
- const dbPath = this.#dbPath(input.location ?? this.#baseDir);
77
- if (!fs.existsSync(dbPath))
78
- return [];
79
- let db;
80
- try {
81
- db = input.isolatedSnapshot
82
- ? openSqliteReadSnapshot(dbPath)
83
- : openDatabase(dbPath, { readonly: true, create: false });
84
- }
85
- catch (error) {
86
- this.#warnUnavailable(dbPath, `cannot open it (${toErrorMessage(error)})`);
87
- return [];
88
- }
89
- if (!db)
90
- return [];
91
- try {
92
- const status = classify(tableNames(db));
93
- if (status.kind !== "ok") {
94
- this.#warnUnavailable(dbPath, `it has neither the OpenCode 1 (${V1_TABLES.join("/")}) nor the OpenCode 2 (${V2_TABLES.join("/")}) tables`);
95
- return [];
36
+ async listSessions(input = {}) {
37
+ const sinceMs = input.sinceMs ?? 0;
38
+ const listed = [];
39
+ for (const dbPath of this.#stores(input.location)) {
40
+ if (!fs.existsSync(dbPath))
41
+ continue;
42
+ try {
43
+ listed.push(...this.#listStore(dbPath, sinceMs, input.isolatedSnapshot === true));
44
+ }
45
+ catch (error) {
46
+ this.#warnUnavailable(dbPath, `cannot list it (${toErrorMessage(error)})`);
96
47
  }
97
- return this.#listFromDb(db, dbPath, input.sinceMs ?? 0, status.v1, status.v2);
98
- }
99
- catch (error) {
100
- this.#warnUnavailable(dbPath, `cannot query it (${toErrorMessage(error)})`);
101
- return [];
102
- }
103
- finally {
104
- db.close();
105
48
  }
49
+ return listed.sort((a, b) => (b.endedAt ?? 0) - (a.endedAt ?? 0));
106
50
  }
107
- readSession(ref) {
108
- const emptyRef = this.sessionRef({ sessionId: ref.sessionId, filePath: ref.filePath });
109
- const empty = { ref: emptyRef, events: [], inlineRefs: [] };
110
- let db;
111
- try {
112
- db = openDatabase(ref.filePath, { readonly: true, create: false });
51
+ /** One session's events. A file or session that cannot be read throws, so the caller records the failure. */
52
+ async readSession(ref) {
53
+ const layout = this.#withDb(ref.filePath, false, layoutOf);
54
+ if (layout === "unsupported") {
55
+ throw new Error(`${ref.filePath} has no supported OpenCode 1 or OpenCode 2 session tables`);
113
56
  }
114
- catch (error) {
115
- this.#warnUnavailable(ref.filePath, `cannot open it (${toErrorMessage(error)})`);
116
- return empty;
57
+ const read = this.#withDb(ref.filePath, false, (db) => layout === "v2"
58
+ ? readV2Session(db, this.name, ref.sessionId, ref.filePath)
59
+ : readV1Session(db, this.name, ref.sessionId, ref.filePath));
60
+ return {
61
+ ref: this.sessionRef({ ...read.meta, filePath: ref.filePath }),
62
+ events: read.events,
63
+ inlineRefs: read.inlineRefs,
64
+ };
65
+ }
66
+ #listStore(dbPath, sinceMs, isolated) {
67
+ const layout = this.#withDb(dbPath, isolated, layoutOf);
68
+ if (layout === "unsupported") {
69
+ this.#warnUnavailable(dbPath, `it has neither the OpenCode 1 (${V1_TABLES.join("/")}) nor the OpenCode 2 tables`);
70
+ return [];
117
71
  }
72
+ const metas = this.#withDb(dbPath, isolated, (db) => layout === "v2" ? listV2Sessions(db, sinceMs) : listV1Sessions(db, sinceMs));
73
+ return metas.map((meta) => this.sessionRef({ ...meta, filePath: dbPath }));
74
+ }
75
+ /** Run `use` on the SQLite file at `dbPath`, read-only (a private copy when `isolated`). */
76
+ #withDb(dbPath, isolated, use) {
77
+ const db = isolated ? openSqliteReadSnapshot(dbPath) : openDatabase(dbPath, { readonly: true, create: false });
78
+ if (!db)
79
+ throw new Error("the file disappeared");
118
80
  try {
119
- const status = classify(tableNames(db));
120
- if (status.kind !== "ok") {
121
- this.#warnUnavailable(ref.filePath, "it has no supported OpenCode 1 or OpenCode 2 session tables");
122
- return empty;
123
- }
124
- // V2 owns a session that has messages there; otherwise a retained V1 copy (a
125
- // session the upgrade has not copied, or copied without messages) is the history.
126
- const v2 = status.v2 ? v2SessionState(db, ref.sessionId) : { exists: false, messages: 0 };
127
- const useV2 = v2.exists && (v2.messages > 0 || !status.v1 || !hasV1Session(db, ref.sessionId));
128
- const read = useV2
129
- ? readV2Session(db, this.name, ref.sessionId, ref.filePath)
130
- : readV1Session(db, this.name, ref.sessionId, ref.filePath);
131
- return {
132
- ref: this.sessionRef({ ...read.meta, filePath: ref.filePath }),
133
- events: read.events,
134
- inlineRefs: read.inlineRefs,
135
- };
136
- }
137
- catch (error) {
138
- this.#warnUnavailable(ref.filePath, `cannot read session ${ref.sessionId} (${toErrorMessage(error)})`);
139
- return empty;
81
+ return use(db);
140
82
  }
141
83
  finally {
142
84
  db.close();
143
85
  }
144
86
  }
145
- /** List each present layout; one failing layout is reported and the other still listed. */
146
- #listFromDb(db, dbPath, sinceMs, v1, v2) {
147
- const merged = new Map();
148
- const attempt = (label, list) => {
149
- try {
150
- for (const meta of list())
151
- if (!merged.has(meta.sessionId))
152
- merged.set(meta.sessionId, meta);
153
- }
154
- catch (error) {
155
- this.#warnUnavailable(dbPath, `its ${label} session tables cannot be queried (${toErrorMessage(error)})`);
156
- }
157
- };
158
- if (v2)
159
- attempt("OpenCode 2", () => listV2Sessions(db, sinceMs));
160
- if (v1)
161
- attempt("OpenCode 1", () => listV1Sessions(db, sinceMs));
162
- return [...merged.values()]
163
- .sort((a, b) => (b.endedAt ?? 0) - (a.endedAt ?? 0))
164
- .map((meta) => this.sessionRef({ ...meta, filePath: dbPath }));
165
- }
166
87
  #warnUnavailable(dbPath, why) {
167
88
  warnOnce(`opencode-history:${dbPath}:${why}`, `OpenCode session history at ${dbPath} was not read: ${why}. This is an unsupported or damaged store, not an empty history.`);
168
89
  }