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
@@ -2,535 +2,132 @@
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
- * Setup wizard connection steps: embedding (Ollama) detection, LLM provider
6
- * selection, and the two-step small-model + agent connection configuration.
5
+ * Setup step 3: the connection. An endpoint, a key, and one model per alias
6
+ * picked from the models the endpoint itself lists.
7
7
  */
8
- import * as p from "../../cli/clack.js";
9
- import { detectAgentCliProfiles, pickDefaultAgentProfile } from "../../integrations/agent/index.js";
10
- import { detectLMStudio, detectOllama } from "../detect.js";
11
- import { verifyOpenAiCompatibleEndpoint } from "../detected-engines.js";
12
- import { cloneLlmConnection, readAgentEngineSelection, readCurrentLlmEngine, } from "../engine-config.js";
13
- import { prompt } from "../prompt.js";
14
- import { keepCurrentOption, llmConnection, lmStudioOptionHint, probeLlmConnection, promptApiKeyEnvVarName, promptEndpointUrl, promptLmStudioModel, promptModelName, } from "./connection-shared.js";
15
- export async function stepOllama(current) {
16
- const spin = p.spinner();
17
- spin.start("Checking for Ollama...");
18
- const ollama = await detectOllama();
19
- if (!ollama.available) {
20
- spin.stop("Ollama not detected");
21
- p.log.info("Ollama is not running. Embeddings will use the built-in local model.\n" +
22
- "To use Ollama later, install it from https://ollama.com and re-run `akm setup`.");
23
- // Preserve existing embedding config when Ollama is not available
24
- return { embedding: current.embedding };
25
- }
26
- spin.stop(`Ollama detected at ${ollama.endpoint}`);
27
- if (ollama.models.length > 0) {
28
- p.log.info(`Available models: ${ollama.models.join(", ")}`);
29
- }
30
- // Embedding model selection
31
- const embeddingModels = ollama.models.filter((m) => m.includes("embed") || m.includes("nomic") || m.includes("minilm") || m.includes("bge"));
32
- const hasEmbeddingModels = embeddingModels.length > 0;
33
- let embedding;
34
- const embeddingOptions = [];
35
- for (const m of embeddingModels) {
36
- embeddingOptions.push({ value: m, label: m, hint: "Ollama" });
37
- }
38
- embeddingOptions.push({
39
- value: "local",
40
- label: "Built-in local embeddings",
41
- hint: "no server needed",
42
- });
43
- if (current.embedding) {
44
- embeddingOptions.push({
45
- value: "keep",
46
- label: `Keep current: ${current.embedding.provider ?? current.embedding.endpoint}`,
47
- hint: current.embedding.model,
48
- });
49
- }
50
- const embChoice = await prompt(() => p.select({
51
- message: "Which embedding provider should akm use?",
52
- options: embeddingOptions,
53
- initialValue: hasEmbeddingModels ? embeddingModels[0] : "local",
54
- }));
55
- if (embChoice === "keep") {
56
- embedding = current.embedding;
57
- }
58
- else if (embChoice !== "local") {
59
- // Ask for dimension — different models produce different sizes.
60
- // Common dimensions: nomic-embed-text=768, mxbai-embed-large=1024,
61
- // all-minilm/bge-small=384. Default based on selected model.
62
- const knownDims = {
63
- nomic: 768,
64
- mxbai: 1024,
65
- minilm: 384,
66
- bge: 384,
67
- qwen3: 1024,
68
- };
69
- const guessedDim = Object.entries(knownDims).find(([k]) => embChoice.includes(k))?.[1] ?? 384;
70
- p.note("Embedding dimension must match the model. Common values: 384 (BGE small), 768 (BGE base), 1024 (BGE large). Press Enter to accept the detected default.", "Embedding dimension");
71
- const dimChoice = await prompt(() => p.text({
72
- message: `Embedding dimension for ${embChoice}:`,
73
- placeholder: String(guessedDim),
74
- defaultValue: String(guessedDim),
75
- validate: (v) => {
76
- const n = Number(v);
77
- if (!Number.isInteger(n) || n <= 0)
78
- return "Must be a positive integer";
79
- },
80
- }));
81
- embedding = {
82
- provider: "ollama",
83
- endpoint: `${ollama.endpoint}/v1/embeddings`,
84
- model: embChoice,
85
- dimension: Number(dimChoice),
86
- };
87
- p.note([
88
- "Recommended Qwen embedding models (modern, high context support):",
89
- " • qwen3-embedding-0.6b — fast and lightweight (ollama pull qwen3-embedding-0.6b)",
90
- " • qwen3-embedding-4b — higher quality (ollama pull qwen3-embedding-4b)",
91
- "",
92
- "For long documents (wiki pages, large files), set context length to avoid 400 errors:",
93
- " akm config set embedding.contextLength 8192",
94
- ].join("\n"), "Embedding tips");
95
- }
96
- // else: undefined → use built-in local
97
- // Surface Ollama details to the LLM step so it can offer Ollama as a preset.
98
- const ollamaChatModels = ollama.models.filter((m) => !embeddingModels.includes(m));
99
- return { embedding, ollamaEndpoint: ollama.endpoint, ollamaChatModels };
8
+ import { defaultConnection } from "../../core/config/config.js";
9
+ import { apiKeyReference, resolveApiKey, storedCredential } from "../../core/config/credentials.js";
10
+ import { entryModel, STANDARD_ALIASES } from "../../core/config/model-aliases.js";
11
+ import { sameEndpoint } from "../../core/endpoint-url.js";
12
+ import { UsageError } from "../../core/errors.js";
13
+ import { redactUrlCredentials } from "../../core/redaction.js";
14
+ import { warn } from "../../core/warn.js";
15
+ import { isEmbeddingModel } from "../../llm/model-list.js";
16
+ import { listModels, pickModel, promptApiKey, promptEndpoint, promptModelName, warnUser } from "./connection-shared.js";
17
+ const NOTHING = { listed: [], addedDefault: false };
18
+ /** The key to list models with now: the one just supplied, else the connection's own when the endpoint is its own. */
19
+ function listingKey(key, existing, name, endpoint) {
20
+ if (key && "pasted" in key)
21
+ return key.pasted;
22
+ if (key) {
23
+ const value = process.env[key.env]?.trim();
24
+ if (!value)
25
+ warn(`[akm setup] ${key.env} is not set; listing models without a key.`);
26
+ return value || undefined;
27
+ }
28
+ return existing && sameEndpoint(existing.endpoint, endpoint)
29
+ ? resolveApiKey(existing.apiKey, { connection: name }, existing.endpoint, process.env, true)
30
+ : undefined;
100
31
  }
101
- const LLM_PRESETS = [
102
- {
103
- value: "anthropic",
104
- label: "Anthropic Claude (OpenAI SDK compat beta)",
105
- endpoint: "https://api.anthropic.com/v1/chat/completions",
106
- defaultModel: "claude-sonnet-4-5",
107
- hint: "beta OpenAI-compat layer; set AKM_LLM_API_KEY; override the model if the default is unavailable",
108
- },
109
- {
110
- value: "openai",
111
- label: "OpenAI",
112
- endpoint: "https://api.openai.com/v1/chat/completions",
113
- defaultModel: "gpt-4o-mini",
114
- hint: "AKM_LLM_API_KEY required",
115
- },
116
- {
117
- value: "google",
118
- label: "Google Gemini (OpenAI-compat)",
119
- endpoint: "https://generativelanguage.googleapis.com/v1beta/openai/chat/completions",
120
- defaultModel: "gemini-2.0-flash",
121
- hint: "OpenAI-compat endpoint, AKM_LLM_API_KEY required",
122
- },
123
- ];
124
- /**
125
- * Step 3a: pick an LLM provider. Used for LLM-gated background features
126
- * (e.g. memory inference).
127
- *
128
- * @internal Exported for testing only.
129
- */
130
- export async function stepLlm(current, ollamaEndpoint, ollamaChatModels, lmStudio, harnessConfigs) {
131
- // Build "Import from <Harness>" options and prepend them before LLM_PRESETS
132
- const harnessOptions = (harnessConfigs ?? []).map((h) => ({
133
- value: `harness:${h.harnessName}`,
134
- label: `Import from ${h.harnessName}`,
135
- hint: [h.provider, h.model].filter(Boolean).join(" / ") || "detected",
136
- }));
137
- const options = [
138
- ...harnessOptions,
139
- ...LLM_PRESETS.map((preset) => ({
140
- value: preset.value,
141
- label: preset.label,
142
- hint: preset.hint,
143
- })),
144
- ];
145
- const ollamaAvailable = Boolean(ollamaEndpoint && ollamaChatModels && ollamaChatModels.length > 0);
146
- if (ollamaAvailable) {
147
- options.push({
148
- value: "ollama",
149
- label: "Ollama (local)",
150
- hint: ollamaChatModels?.[0] ?? "local",
151
- });
152
- }
153
- options.push({ value: "lmstudio", label: "LM Studio / local server", hint: lmStudioOptionHint(lmStudio) });
154
- options.push({ value: "custom", label: "Custom OpenAI-compatible endpoint" });
155
- options.push({ value: "none", label: "Skip LLM", hint: "LLM-gated background features stay disabled" });
156
- const currentLlm = readCurrentLlmEngine(current);
157
- if (currentLlm) {
158
- options.push(keepCurrentOption(currentLlm));
159
- }
160
- const initialValue = currentLlm ? "keep" : ollamaAvailable ? "ollama" : (LLM_PRESETS[0]?.value ?? "none");
161
- const choice = await prompt(() => p.select({
162
- message: "Configure an LLM for background features:",
163
- options,
164
- initialValue,
165
- }));
166
- if (choice === "keep")
167
- return cloneLlmConnection(currentLlm);
168
- if (choice === "none")
169
- return undefined;
170
- // Handle "Import from <Harness>" choices
171
- if (typeof choice === "string" && choice.startsWith("harness:")) {
172
- const harness = (harnessConfigs ?? []).find((h) => `harness:${h.harnessName}` === choice);
173
- if (!harness)
174
- return undefined;
175
- // Show a summary before accepting
176
- p.log.info(`Importing LLM config from ${harness.harnessName}: ` +
177
- [harness.provider, harness.model, harness.baseUrl].filter(Boolean).join(", "));
178
- if (!harness.baseUrl || !harness.model) {
179
- p.log.warn(`Skipping ${harness.harnessName}: no complete endpoint/model was detected.`);
180
- return undefined;
181
- }
182
- const verified = await verifyOpenAiCompatibleEndpoint({
183
- endpoint: harness.baseUrl,
184
- model: harness.model,
185
- apiKeyEnvVar: harness.apiKeyEnvVar,
186
- });
187
- if (!verified.ok) {
188
- p.log.warn(`Skipping ${harness.harnessName}: ${verified.reason}. Fix its endpoint/credential and retry setup.`);
189
- return undefined;
190
- }
191
- const llmConfig = {
192
- endpoint: verified.endpoint,
193
- model: harness.model ?? "",
194
- temperature: 0.3,
195
- ...(harness.apiKeyEnvVar ? { apiKey: `\${${harness.apiKeyEnvVar}}` } : {}),
196
- };
197
- if (harness.provider)
198
- llmConfig.provider = harness.provider;
199
- return llmConfig;
200
- }
201
- let llm;
202
- if (choice === "ollama") {
203
- const modelChoice = await prompt(() => p.select({
204
- message: "Which Ollama model?",
205
- options: (ollamaChatModels ?? []).map((m) => ({ value: m, label: m })),
206
- initialValue: ollamaChatModels?.[0],
207
- }));
208
- llm = llmConnection("ollama", `${ollamaEndpoint}/v1/chat/completions`, modelChoice);
209
- }
210
- else if (choice === "lmstudio") {
211
- const currentLmsLlm = currentLlm?.provider === "lmstudio" ? currentLlm : undefined;
212
- const defaultEndpoint = currentLmsLlm?.endpoint ??
213
- (lmStudio?.endpoint ? `${lmStudio.endpoint}/v1/chat/completions` : "http://localhost:1234/v1/chat/completions");
214
- const endpoint = await promptEndpointUrl({ placeholder: defaultEndpoint, defaultValue: defaultEndpoint });
215
- const model = await promptLmStudioModel(lmStudio, currentLmsLlm?.model);
216
- llm = llmConnection("lmstudio", endpoint.trim(), model.trim());
217
- }
218
- else if (choice === "custom") {
219
- const currentCustomLlm = currentLlm?.provider === "custom" ? currentLlm : undefined;
220
- const endpoint = await promptEndpointUrl({
221
- message: "OpenAI-compatible chat completions endpoint:",
222
- placeholder: currentCustomLlm?.endpoint ?? "https://your-host/v1/chat/completions",
223
- defaultValue: currentCustomLlm?.endpoint,
224
- schemeMessage: "Endpoint must start with http:// or https://",
225
- });
226
- const model = await promptModelName({
227
- placeholder: currentCustomLlm?.model ?? "gpt-4o-mini",
228
- defaultValue: currentCustomLlm?.model,
229
- });
230
- llm = llmConnection("custom", endpoint.trim(), model.trim());
231
- }
232
- else {
233
- const preset = LLM_PRESETS.find((p) => p.value === choice);
234
- if (!preset)
235
- return undefined;
236
- const model = await promptModelName({
237
- message: `Model for ${preset.label}:`,
238
- placeholder: preset.defaultModel,
239
- defaultValue: preset.defaultModel,
240
- });
241
- llm = llmConnection(preset.value, preset.endpoint, model.trim() || preset.defaultModel);
242
- }
243
- // Remind the user about API key placement. We do not offer a "store in config"
244
- // option because saveConfig() strips apiKey fields before writing — persisting
245
- // secrets would need an encrypted/secure store that we don't ship.
246
- const needsKey = llm.provider !== "ollama" && !llm.endpoint.includes("localhost");
247
- if (needsKey && !process.env.AKM_LLM_API_KEY) {
248
- p.log.info("This provider requires an API key. Set AKM_LLM_API_KEY in your shell (e.g. `export AKM_LLM_API_KEY=...`) before running `akm index`.");
249
- }
250
- // Capability probe — best-effort, never blocks setup.
251
- await probeLlmConnection(llm);
252
- return llm;
32
+ /** Whether the connection has a key of its own: a `$VAR` it references, or one stored for it, at whatever endpoint. */
33
+ function holdsKey(existing, name) {
34
+ return apiKeyReference(existing.apiKey) !== undefined || storedCredential({ connection: name }) !== undefined;
253
35
  }
254
- /**
255
- * Step 1/2: Configure the small model connection used for bounded LLM features.
256
- *
257
- * Detects Ollama automatically and pre-selects it. The user may also choose
258
- * OpenAI, LM Studio, a custom endpoint, or skip the step entirely.
259
- */
260
- export async function stepSmallModelConnection(current) {
261
- p.log.step("Step 1/2: Configure your small model connection");
262
- p.note([
263
- "This connection is used for background processing:",
264
- " • akm improve (lesson distillation)",
265
- " • akm remember --enrich (memory compression)",
266
- ].join("\n"));
267
- // Probe for Ollama and LM Studio in the background while showing the note.
268
- const spin = p.spinner();
269
- spin.start("Detecting local services...");
270
- const [ollama, lmStudio] = await Promise.all([detectOllama(), detectLMStudio()]);
271
- const detectedServices = [
272
- ollama.available ? `Ollama at ${ollama.endpoint}` : null,
273
- lmStudio.available ? `LM Studio at ${lmStudio.endpoint}` : null,
274
- ]
275
- .filter(Boolean)
276
- .join(", ");
277
- spin.stop(detectedServices ? `Detected: ${detectedServices}` : "No local services detected");
278
- const ollamaEndpoint = ollama.available ? ollama.endpoint : undefined;
279
- const providerOptions = [];
280
- if (ollama.available) {
281
- providerOptions.push({
282
- value: "ollama",
283
- label: "Ollama (local)",
284
- hint: `detected at ${ollama.endpoint}`,
285
- });
286
- }
287
- providerOptions.push({ value: "openai", label: "OpenAI", hint: "requires AKM_LLM_API_KEY" }, { value: "lmstudio", label: "LM Studio / local server", hint: lmStudioOptionHint(lmStudio) }, { value: "custom", label: "Custom OpenAI-compatible endpoint" }, { value: "skip", label: "Skip — disable enrichment features" });
288
- const currentLlmSmall = readCurrentLlmEngine(current);
289
- if (currentLlmSmall) {
290
- providerOptions.push(keepCurrentOption(currentLlmSmall));
291
- }
292
- const initialValue = currentLlmSmall ? "keep" : ollama.available ? "ollama" : "openai";
293
- const providerChoice = await prompt(() => p.select({
294
- message: "Provider:",
295
- options: providerOptions,
296
- initialValue,
297
- }));
298
- if (providerChoice === "keep") {
299
- return { llm: cloneLlmConnection(currentLlmSmall), skipped: false, ollamaEndpoint };
300
- }
301
- if (providerChoice === "skip") {
302
- p.note([
303
- "Enrichment features disabled:",
304
- " • akm improve — lesson generation",
305
- " • akm remember --enrich",
306
- "",
307
- "You can configure this later with `akm setup`.",
308
- ].join("\n"), "Warning");
309
- return { llm: undefined, skipped: true, ollamaEndpoint };
310
- }
311
- let llm;
312
- if (providerChoice === "ollama") {
313
- const ollamaChatModels = ollama.models.filter((m) => !m.includes("embed") && !m.includes("nomic") && !m.includes("minilm") && !m.includes("bge"));
314
- let model;
315
- if (ollamaChatModels.length > 0) {
316
- model = await prompt(() => p.select({
317
- message: "Model name:",
318
- options: [
319
- ...ollamaChatModels.map((m) => ({ value: m, label: m })),
320
- { value: "__custom__", label: "Enter a model name manually..." },
321
- ],
322
- initialValue: ollamaChatModels[0],
323
- }));
324
- if (model === "__custom__") {
325
- model = await promptModelName({ placeholder: "llama3.2" });
36
+ /** One model per alias: the connection's current pick is kept; the others are chosen from the endpoint's list, or typed. */
37
+ async function pickAliases(existing, listed, interactive) {
38
+ const current = (alias) => {
39
+ const entry = existing?.models?.[alias];
40
+ return entry === undefined ? undefined : entryModel(entry);
41
+ };
42
+ const chat = listed.filter((model) => !isEmbeddingModel(model));
43
+ const pool = chat.length > 0 ? chat : [...listed];
44
+ const picks = {};
45
+ if (pool.length > 0) {
46
+ for (const alias of STANDARD_ALIASES) {
47
+ const held = current(alias);
48
+ if (!interactive) {
49
+ picks[alias] = held ?? pool[0];
50
+ continue;
326
51
  }
52
+ const options = held !== undefined && !pool.includes(held) ? [held, ...pool] : pool;
53
+ picks[alias] = await pickModel(`Model for "${alias}":`, options, held ?? pool[0]);
327
54
  }
328
- else {
329
- const currentOllamaModel = currentLlmSmall?.provider === "ollama" ? (currentLlmSmall.model ?? "llama3.2") : "llama3.2";
330
- model = await promptModelName({
331
- message: "Model name (e.g. llama3.2):",
332
- placeholder: currentOllamaModel,
333
- defaultValue: currentOllamaModel,
334
- });
335
- }
336
- llm = llmConnection("ollama", `${ollama.endpoint}/v1/chat/completions`, model.trim());
337
- }
338
- else if (providerChoice === "openai") {
339
- const currentOpenAiModel = currentLlmSmall?.provider === "openai" ? (currentLlmSmall.model ?? "gpt-4o-mini") : "gpt-4o-mini";
340
- const model = await promptModelName({ placeholder: currentOpenAiModel, defaultValue: currentOpenAiModel });
341
- if (!process.env.AKM_LLM_API_KEY) {
342
- p.log.info("Set AKM_LLM_API_KEY in your shell before running `akm index`.");
343
- }
344
- llm = llmConnection("openai", "https://api.openai.com/v1/chat/completions", model.trim() || currentOpenAiModel);
345
- }
346
- else if (providerChoice === "lmstudio") {
347
- const currentLmsEndpoint = currentLlmSmall?.provider === "lmstudio"
348
- ? (currentLlmSmall.endpoint ?? `${lmStudio.endpoint}/v1/chat/completions`)
349
- : `${lmStudio.endpoint}/v1/chat/completions`;
350
- const currentLmsModel = currentLlmSmall?.provider === "lmstudio" ? currentLlmSmall.model : undefined;
351
- const endpoint = await promptEndpointUrl({ placeholder: currentLmsEndpoint, defaultValue: currentLmsEndpoint });
352
- const model = await promptLmStudioModel(lmStudio, currentLmsModel);
353
- llm = llmConnection("lmstudio", endpoint.trim(), model.trim());
354
- }
355
- else {
356
- // custom
357
- const currentCustomEndpoint = currentLlmSmall?.provider === "custom" ? currentLlmSmall.endpoint : undefined;
358
- const currentCustomModel = currentLlmSmall?.provider === "custom" ? currentLlmSmall.model : undefined;
359
- const endpoint = await promptEndpointUrl({
360
- message: "OpenAI-compatible chat completions endpoint:",
361
- placeholder: currentCustomEndpoint ?? "https://your-host/v1/chat/completions",
362
- defaultValue: currentCustomEndpoint,
363
- });
364
- const model = await promptModelName({
365
- placeholder: currentCustomModel ?? "gpt-4o-mini",
366
- defaultValue: currentCustomModel,
367
- });
368
- const apiKeyInput = await promptApiKeyEnvVarName();
369
- llm = llmConnection("custom", endpoint.trim(), model.trim(), apiKeyInput?.trim() ? { apiKey: `\${${apiKeyInput.trim()}}` } : {});
370
- }
371
- // Best-effort probe — never blocks setup.
372
- await probeLlmConnection(llm);
373
- return { llm, skipped: false, ollamaEndpoint };
55
+ return picks;
56
+ }
57
+ // The endpoint listed nothing: a model typed by hand answers every alias that has none yet.
58
+ const missing = STANDARD_ALIASES.filter((alias) => current(alias) === undefined);
59
+ if (!interactive || missing.length === 0)
60
+ return picks;
61
+ const typed = await promptModelName({
62
+ message: "Model name (the endpoint could not list its models; change it later with `akm models set`):",
63
+ initialValue: STANDARD_ALIASES.map(current).find((model) => model !== undefined),
64
+ });
65
+ for (const alias of missing)
66
+ picks[alias] = typed;
67
+ return picks;
374
68
  }
375
- /**
376
- * Step 2/2: Configure the agent connection used for agentic features.
377
- *
378
- * Options depend on whether Step 1 was completed or skipped.
379
- */
380
- export async function stepAgentConnection(current, smallModel) {
381
- p.log.step("Step 2/2: Configure your agent connection");
382
- p.note([
383
- "This connection is used for agentic commands:",
384
- " • akm proposal new (generate improvement proposals)",
385
- " • akm improve (run the reflect/distill/consolidate self-improvement pipeline)",
386
- " • akm task run (run automated task prompts)",
387
- ].join("\n"));
388
- // Detect available CLI agents.
389
- const detections = detectAgentCliProfiles(current);
390
- const currentAgentBlock = readAgentEngineSelection(current);
391
- const availableClis = detections.filter((d) => d.available);
392
- const agentOptions = [];
393
- if (!smallModel.skipped && smallModel.llm) {
394
- agentOptions.push({
395
- value: "same-connection",
396
- label: "Same connection, select model",
397
- hint: `uses ${smallModel.llm.endpoint.replace("/v1/chat/completions", "")}`,
398
- });
399
- }
400
- agentOptions.push({ value: "new-connection", label: "New connection (different endpoint)" });
401
- if (availableClis.length > 0) {
402
- agentOptions.push({
403
- value: "cli-agent",
404
- label: "Installed CLI agent",
405
- hint: `${availableClis.map((d) => d.name).join(", ")} detected`,
406
- });
407
- }
408
- agentOptions.push({ value: "none", label: "None — disable agentic features" });
409
- if (currentAgentBlock) {
410
- const currentDesc = currentAgentBlock.default
411
- ? `CLI: ${currentAgentBlock.default}`
412
- : currentAgentBlock.engines?.default?.model
413
- ? `SDK: ${currentAgentBlock.engines.default.model}`
414
- : "configured";
415
- agentOptions.push({ value: "keep", label: `Keep current: ${currentDesc}` });
416
- }
417
- const initialAgentValue = currentAgentBlock
418
- ? "keep"
419
- : availableClis.length > 0 && smallModel.skipped
420
- ? "cli-agent"
421
- : !smallModel.skipped && smallModel.llm
422
- ? "same-connection"
423
- : availableClis.length > 0
424
- ? "cli-agent"
425
- : "none";
426
- const agentChoice = await prompt(() => p.select({
427
- message: "How do you want to run agent commands?",
428
- options: agentOptions,
429
- initialValue: initialAgentValue,
430
- }));
431
- if (agentChoice === "keep") {
432
- return currentAgentBlock;
433
- }
434
- if (agentChoice === "none") {
435
- p.note([
436
- "Agentic features disabled:",
437
- ' • akm proposal new — will show "no agent configured" error',
438
- ' • akm improve — will show "no agent configured" error',
439
- ' • akm task run — will show "no agent configured" error',
440
- "",
441
- "You can configure this later with `akm setup`.",
442
- ].join("\n"), "Warning");
443
- return { disabled: true };
444
- }
445
- if (agentChoice === "same-connection") {
446
- if (smallModel.skipped || !smallModel.llm) {
447
- p.log.warn("You skipped the small model connection. Configure one to use the same connection. Falling back to 'new connection'.");
448
- // Fall through to new-connection flow
449
- }
450
- else {
451
- const baseEndpoint = smallModel.llm.endpoint.replace("/v1/chat/completions", "");
452
- p.log.info(`Endpoint: ${baseEndpoint} (from Step 1)`);
453
- const profileName = `${smallModel.llm.provider ?? "default"}-agent`;
454
- // Pre-populate from existing agent profile for this provider, if any.
455
- const existingAgentModel = currentAgentBlock?.engines?.[profileName]?.model ?? smallModel.llm.model ?? undefined;
456
- const agentModel = await promptModelName({
457
- message: "Model to use for agent tasks (same model is fine, larger models work better):",
458
- placeholder: existingAgentModel ?? "qwen2.5-coder:32b",
459
- defaultValue: existingAgentModel,
460
- });
461
- return {
462
- ...(currentAgentBlock ?? {}),
463
- engines: {
464
- ...(currentAgentBlock?.engines ?? {}),
465
- [profileName]: {
466
- ...(currentAgentBlock?.engines?.[profileName] ?? {}),
467
- kind: "agent",
468
- platform: "opencode-sdk",
469
- model: agentModel.trim(),
470
- ...(current.defaults?.llmEngine ? { llmEngine: current.defaults.llmEngine } : {}),
471
- },
472
- },
473
- default: profileName,
474
- };
475
- }
476
- }
477
- if (agentChoice === "cli-agent") {
478
- if (availableClis.length === 0) {
479
- p.log.warn("No agent CLIs detected on PATH.");
480
- return currentAgentBlock;
69
+ /** One warning for the picks setup keeps that the endpoint, which did list its models, does not serve. */
70
+ function warnOfUnlistedPicks(existing, picks, listed, endpoint, interactive) {
71
+ if (listed.length === 0)
72
+ return;
73
+ const kept = new Set();
74
+ for (const [alias, pick] of Object.entries(picks)) {
75
+ const held = existing?.models?.[alias];
76
+ if (held !== undefined && entryModel(held) === pick && !listed.includes(pick))
77
+ kept.add(pick);
78
+ }
79
+ if (kept.size === 0)
80
+ return;
81
+ const names = [...kept].map((model) => `"${model}"`).join(", ");
82
+ warnUser(`Keeping ${names}: ${redactUrlCredentials(endpoint)} does not list ${kept.size === 1 ? "it" : "them"}. Change a pick with \`akm models set\`.`, interactive);
83
+ }
84
+ export async function stepConnection(input) {
85
+ const { current, flags, interactive } = input;
86
+ const name = flags.name ?? defaultConnection(current)?.name ?? "default";
87
+ const existing = current.connections?.[name];
88
+ const flagged = flags.endpoint !== undefined || flags.apiKeyEnv !== undefined || flags.name !== undefined;
89
+ const local = input.localServers.find((server) => server.available);
90
+ const detected = local ? `${local.baseUrl}/v1` : undefined;
91
+ const needed = flagged ||
92
+ (interactive
93
+ ? existing !== undefined || !input.modelCallsOnHarness
94
+ : existing === undefined && !input.modelCallsOnHarness && detected !== undefined);
95
+ if (!needed)
96
+ return NOTHING;
97
+ let endpoint = flags.endpoint;
98
+ if (endpoint === undefined) {
99
+ const start = existing?.endpoint ?? detected;
100
+ endpoint = interactive
101
+ ? await promptEndpoint({
102
+ message: "Endpoint URL of an OpenAI-compatible server (blank for none):",
103
+ ...(start ? { initialValue: start } : {}),
104
+ })
105
+ : start;
106
+ }
107
+ if (endpoint === undefined) {
108
+ if (flagged) {
109
+ throw new UsageError(`There is no connection "${name}" to update. Pass --endpoint to add one.`, "MISSING_REQUIRED_ARGUMENT");
481
110
  }
482
- const initialCli = pickDefaultAgentProfile(detections, currentAgentBlock?.default) ?? availableClis[0]?.name;
483
- const selectedCli = await prompt(() => p.select({
484
- message: "Which CLI agent?",
485
- options: availableClis.map((d) => ({
486
- value: d.name,
487
- label: d.name,
488
- hint: d.resolvedPath ?? d.bin,
489
- })),
490
- initialValue: initialCli,
491
- }));
492
- return {
493
- ...(currentAgentBlock ?? {}),
494
- default: selectedCli,
495
- };
496
- }
497
- // "new-connection" (also fall-through from "same-provider" when Step 1 was skipped)
498
- // Pre-populate from current "custom" agent profile if available.
499
- const currentCustomAgentProfile = currentAgentBlock?.engines?.["custom-agent"];
500
- const currentNewEndpoint = undefined;
501
- const currentNewModel = currentCustomAgentProfile?.model ?? undefined;
502
- const newEndpoint = await promptEndpointUrl({
503
- message: "OpenAI-compatible chat completions endpoint:",
504
- placeholder: currentNewEndpoint ?? "https://your-host/v1/chat/completions",
505
- defaultValue: currentNewEndpoint,
506
- });
507
- const newApiKeyInput = await promptApiKeyEnvVarName();
508
- const newModel = await promptModelName({
509
- message: "Model name (larger is better, e.g. gpt-4o):",
510
- placeholder: currentNewModel ?? "gpt-4o",
511
- defaultValue: currentNewModel,
512
- });
513
- const llmEngineName = "custom-llm";
514
- const agentEngineName = "custom-agent";
515
- const customProfile = {
516
- kind: "agent",
517
- platform: "opencode-sdk",
518
- llmEngine: llmEngineName,
519
- model: newModel.trim(),
520
- };
521
- return {
522
- ...(currentAgentBlock ?? {}),
523
- engines: {
524
- ...(currentAgentBlock?.engines ?? {}),
525
- [llmEngineName]: {
526
- kind: "llm",
527
- provider: "custom",
528
- endpoint: newEndpoint.trim(),
529
- model: newModel.trim(),
530
- ...(newApiKeyInput?.trim() ? { apiKey: `\${${newApiKeyInput.trim()}}` } : {}),
531
- },
532
- [agentEngineName]: customProfile,
533
- },
534
- default: agentEngineName,
535
- };
111
+ return NOTHING;
112
+ }
113
+ // A key belongs to the endpoint it was given for, so the current one is offered for that endpoint alone.
114
+ const sameServer = existing !== undefined && sameEndpoint(existing.endpoint, endpoint);
115
+ let key;
116
+ if (flags.apiKeyEnv !== undefined) {
117
+ key = { env: flags.apiKeyEnv };
118
+ }
119
+ else if (interactive) {
120
+ const hasKey = sameServer && resolveApiKey(existing?.apiKey, { connection: name }, endpoint, process.env, true) !== undefined;
121
+ const typed = await promptApiKey(hasKey ? "API key (blank keeps the current one)" : "API key (blank for none)");
122
+ if (typed)
123
+ key = { pasted: typed };
124
+ }
125
+ if (key === undefined && existing && !sameServer && holdsKey(existing, name)) {
126
+ warnUser(`The endpoint of "${name}" changed, so its current key is not used with ${redactUrlCredentials(endpoint)}. Give the new endpoint's key with --api-key-env (or at the prompt).`, interactive);
127
+ }
128
+ const listed = input.probe ? await listModels(endpoint, listingKey(key, existing, name, endpoint), interactive) : [];
129
+ const picks = await pickAliases(existing, listed, interactive);
130
+ warnOfUnlistedPicks(existing, picks, listed, endpoint, interactive);
131
+ const addedDefault = existing === undefined && (name === "default" || Object.keys(current.connections ?? {}).length === 0);
132
+ return { answer: { name, endpoint, ...(key ? { key } : {}), picks }, listed, addedDefault };
536
133
  }