akm-cli 0.10.261013-beta → 0.10.261014-beta

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