akm-cli 0.9.0-beta.9 → 0.9.0-rc.0

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 (325) hide show
  1. package/CHANGELOG.md +592 -0
  2. package/README.md +12 -4
  3. package/dist/akm +38 -0
  4. package/dist/akm-migrate-storage +38 -0
  5. package/dist/assets/help/help-improve.md +9 -6
  6. package/dist/assets/hints/cli-hints-full.md +6 -5
  7. package/dist/assets/profiles/default.json +9 -4
  8. package/dist/assets/profiles/frequent.json +1 -1
  9. package/dist/assets/profiles/memory-focus.json +1 -1
  10. package/dist/assets/profiles/proactive-maintenance.json +25 -0
  11. package/dist/assets/profiles/quick.json +1 -1
  12. package/dist/assets/profiles/recombine-only.json +21 -0
  13. package/dist/assets/profiles/reflect-distill.json +30 -0
  14. package/dist/assets/profiles/synthesize.json +15 -0
  15. package/dist/assets/profiles/thorough.json +1 -1
  16. package/dist/assets/prompts/consolidate-system.md +23 -0
  17. package/dist/assets/prompts/contradiction-judge.md +33 -0
  18. package/dist/assets/prompts/distill-knowledge-system.md +22 -0
  19. package/dist/assets/prompts/distill-lesson-system.md +36 -0
  20. package/dist/assets/prompts/extract-session.md +11 -3
  21. package/dist/assets/prompts/graph-extract-system.md +1 -0
  22. package/dist/assets/prompts/graph-extract-user-prompt.md +1 -1
  23. package/dist/assets/prompts/memory-infer-system.md +1 -0
  24. package/dist/assets/prompts/memory-infer-user.md +5 -0
  25. package/dist/assets/prompts/metadata-enhance-system.md +1 -0
  26. package/dist/assets/prompts/procedural-system.md +44 -0
  27. package/dist/assets/prompts/recombine-system.md +40 -0
  28. package/dist/assets/prompts/staleness-detect-system.md +6 -0
  29. package/dist/assets/prompts/validate-summary-judge.md +1 -0
  30. package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +38 -0
  31. package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +38 -0
  32. package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +39 -0
  33. package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +40 -0
  34. package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +43 -0
  35. package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +38 -0
  36. package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +43 -0
  37. package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +40 -0
  38. package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +43 -0
  39. package/dist/assets/templates/html/health.html +281 -111
  40. package/dist/assets/wiki/ingest-workflow-template.md +45 -16
  41. package/dist/assets/wiki/schema-template.md +4 -4
  42. package/dist/cli/clack.js +56 -0
  43. package/dist/cli/config-migrate.js +7 -1
  44. package/dist/cli/confirm.js +1 -1
  45. package/dist/cli/parse-args.js +46 -1
  46. package/dist/cli/shared.js +28 -0
  47. package/dist/cli.js +25 -21
  48. package/dist/commands/agent/agent-dispatch.js +3 -2
  49. package/dist/commands/agent/agent-support.js +0 -7
  50. package/dist/commands/agent/contribute-cli.js +26 -7
  51. package/dist/commands/config-cli.js +26 -13
  52. package/dist/commands/env/child-env.js +47 -0
  53. package/dist/commands/env/env-cli.js +220 -227
  54. package/dist/commands/env/env.js +14 -67
  55. package/dist/commands/env/secret-cli.js +140 -138
  56. package/dist/commands/feedback-cli.js +156 -155
  57. package/dist/commands/graph/graph-cli.js +5 -13
  58. package/dist/commands/graph/graph.js +3 -3
  59. package/dist/commands/health/advisories.js +151 -0
  60. package/dist/commands/health/checks.js +103 -16
  61. package/dist/commands/health/html-report.js +447 -81
  62. package/dist/commands/health/improve-metrics.js +771 -0
  63. package/dist/commands/health/llm-usage.js +65 -0
  64. package/dist/commands/health/md-report.js +103 -0
  65. package/dist/commands/health/metrics.js +278 -0
  66. package/dist/commands/health/stash-exposure.js +46 -0
  67. package/dist/commands/health/surfaces.js +216 -0
  68. package/dist/commands/health/task-runs.js +135 -0
  69. package/dist/commands/health/types.js +26 -0
  70. package/dist/commands/health/windows.js +195 -0
  71. package/dist/commands/health.js +91 -1091
  72. package/dist/commands/improve/anti-collapse.js +170 -0
  73. package/dist/commands/improve/calibration.js +161 -0
  74. package/dist/commands/improve/collapse-detector.js +421 -0
  75. package/dist/commands/improve/consolidate/chunking.js +141 -0
  76. package/dist/commands/improve/consolidate/eligibility.js +64 -0
  77. package/dist/commands/improve/consolidate/merge.js +145 -0
  78. package/dist/commands/improve/consolidate/sanitize.js +231 -0
  79. package/dist/commands/{lint.js → improve/consolidate/types.js} +1 -1
  80. package/dist/commands/improve/consolidate.js +1295 -1277
  81. package/dist/commands/improve/dedup.js +482 -0
  82. package/dist/commands/improve/distill/content-repair.js +202 -0
  83. package/dist/commands/improve/distill/promote-memory.js +229 -0
  84. package/dist/commands/improve/distill/quality-gate.js +236 -0
  85. package/dist/commands/improve/distill-guards.js +127 -0
  86. package/dist/commands/improve/distill-promotion-policy.js +826 -167
  87. package/dist/commands/improve/distill.js +228 -605
  88. package/dist/commands/improve/eligibility.js +434 -0
  89. package/dist/commands/improve/encoding-salience.js +205 -0
  90. package/dist/commands/improve/extract-cli.js +179 -59
  91. package/dist/commands/improve/extract-prompt.js +54 -3
  92. package/dist/commands/improve/extract-watch.js +140 -0
  93. package/dist/commands/improve/extract.js +409 -43
  94. package/dist/commands/improve/feedback-valence.js +54 -0
  95. package/dist/commands/improve/hot-probation.js +45 -0
  96. package/dist/commands/improve/improve-auto-accept.js +157 -10
  97. package/dist/commands/improve/improve-cli.js +115 -73
  98. package/dist/commands/improve/improve-profiles.js +28 -8
  99. package/dist/commands/improve/improve-result-file.js +15 -25
  100. package/dist/commands/improve/improve-session.js +58 -0
  101. package/dist/commands/improve/improve.js +485 -2764
  102. package/dist/commands/improve/locks.js +154 -0
  103. package/dist/commands/improve/loop-stages.js +1100 -0
  104. package/dist/commands/improve/memory/memory-belief.js +14 -15
  105. package/dist/commands/improve/memory/memory-contradiction-detect.js +83 -60
  106. package/dist/commands/improve/memory/memory-improve.js +27 -27
  107. package/dist/commands/improve/outcome-loop.js +270 -0
  108. package/dist/commands/improve/preparation.js +2002 -0
  109. package/dist/commands/improve/proactive-maintenance.js +37 -35
  110. package/dist/commands/improve/procedural.js +398 -0
  111. package/dist/commands/improve/recombine.js +818 -0
  112. package/dist/commands/improve/reflect-noise.js +0 -0
  113. package/dist/commands/improve/reflect.js +206 -45
  114. package/dist/commands/improve/salience.js +455 -0
  115. package/dist/commands/improve/schema-similarity-gate.js +168 -0
  116. package/dist/commands/improve/shared.js +51 -0
  117. package/dist/commands/improve/triage.js +93 -0
  118. package/dist/commands/lint/agent-linter.js +19 -24
  119. package/dist/commands/lint/base-linter.js +173 -60
  120. package/dist/commands/lint/command-linter.js +19 -24
  121. package/dist/commands/lint/env-key-rules.js +38 -1
  122. package/dist/commands/lint/fact-linter.js +39 -0
  123. package/dist/commands/lint/index.js +31 -13
  124. package/dist/commands/lint/memory-linter.js +1 -1
  125. package/dist/commands/lint/registry.js +7 -2
  126. package/dist/commands/lint/task-linter.js +3 -3
  127. package/dist/commands/lint/workflow-linter.js +26 -1
  128. package/dist/commands/observability-cli.js +4 -4
  129. package/dist/commands/proposal/drain-policies.js +13 -4
  130. package/dist/commands/proposal/drain.js +45 -51
  131. package/dist/commands/proposal/legacy-import.js +115 -0
  132. package/dist/commands/proposal/proposal-cli.js +24 -34
  133. package/dist/commands/proposal/proposal.js +2 -1
  134. package/dist/commands/proposal/propose.js +8 -3
  135. package/dist/commands/proposal/repository.js +829 -0
  136. package/dist/commands/proposal/validators/proposal-quality-validators.js +9 -8
  137. package/dist/commands/proposal/validators/proposals.js +93 -895
  138. package/dist/commands/read/curate.js +410 -111
  139. package/dist/commands/read/knowledge.js +10 -3
  140. package/dist/commands/read/remember-cli.js +133 -138
  141. package/dist/commands/read/search-cli.js +15 -8
  142. package/dist/commands/read/search.js +22 -11
  143. package/dist/commands/read/show.js +106 -14
  144. package/dist/commands/registry-cli.js +76 -87
  145. package/dist/commands/remember.js +11 -12
  146. package/dist/commands/sources/add-cli.js +91 -95
  147. package/dist/commands/sources/history.js +1 -1
  148. package/dist/commands/sources/init.js +66 -18
  149. package/dist/commands/sources/installed-stashes.js +11 -3
  150. package/dist/commands/sources/schema-repair.js +44 -46
  151. package/dist/commands/sources/self-update.js +2 -2
  152. package/dist/commands/sources/source-add.js +7 -3
  153. package/dist/commands/sources/sources-cli.js +3 -3
  154. package/dist/commands/sources/stash-cli.js +19 -39
  155. package/dist/commands/sources/stash-skeleton.js +57 -8
  156. package/dist/commands/tasks/default-tasks.js +15 -2
  157. package/dist/commands/tasks/tasks-cli.js +20 -29
  158. package/dist/commands/tasks/tasks.js +39 -11
  159. package/dist/commands/wiki-cli.js +23 -38
  160. package/dist/commands/workflow-cli.js +15 -1
  161. package/dist/core/asset/asset-registry.js +3 -1
  162. package/dist/core/asset/asset-spec.js +21 -4
  163. package/dist/core/asset/frontmatter.js +188 -167
  164. package/dist/core/asset/markdown.js +8 -0
  165. package/dist/core/authoring-rules.js +92 -0
  166. package/dist/core/common.js +4 -23
  167. package/dist/core/concurrent.js +10 -1
  168. package/dist/core/config/config-io.js +10 -1
  169. package/dist/core/config/config-migration.js +18 -40
  170. package/dist/core/config/config-schema.js +382 -62
  171. package/dist/core/config/config-types.js +3 -3
  172. package/dist/core/config/config.js +67 -22
  173. package/dist/core/deep-merge.js +38 -0
  174. package/dist/core/errors.js +1 -0
  175. package/dist/core/eval/rank-metrics.js +113 -0
  176. package/dist/core/events.js +4 -7
  177. package/dist/core/improve-types.js +47 -8
  178. package/dist/core/logs-db.js +14 -75
  179. package/dist/core/parse.js +36 -16
  180. package/dist/core/paths.js +18 -18
  181. package/dist/core/standards/resolve-standards-context.js +87 -0
  182. package/dist/core/standards/resolve-stash-standards.js +99 -0
  183. package/dist/core/standards/resolve-type-conventions.js +66 -0
  184. package/dist/core/state/migrations.js +770 -0
  185. package/dist/core/state-db.js +132 -1126
  186. package/dist/core/structured.js +69 -0
  187. package/dist/core/time.js +53 -0
  188. package/dist/core/warn.js +21 -0
  189. package/dist/core/write-source.js +37 -0
  190. package/dist/indexer/db/db.js +259 -769
  191. package/dist/indexer/db/entry-mapper.js +41 -0
  192. package/dist/indexer/db/graph-db.js +129 -86
  193. package/dist/indexer/db/llm-cache.js +2 -2
  194. package/dist/indexer/db/schema.js +516 -0
  195. package/dist/indexer/ensure-index.js +36 -92
  196. package/dist/indexer/feedback/utility-policy.js +75 -0
  197. package/dist/indexer/graph/graph-boost.js +51 -41
  198. package/dist/indexer/graph/graph-extraction.js +207 -4
  199. package/dist/indexer/index-writer-lock.js +18 -11
  200. package/dist/indexer/index-written-assets.js +105 -0
  201. package/dist/indexer/indexer.js +182 -204
  202. package/dist/indexer/passes/dir-staleness.js +114 -0
  203. package/dist/indexer/passes/memory-inference.js +13 -5
  204. package/dist/indexer/passes/metadata.js +20 -0
  205. package/dist/indexer/read-preflight.js +23 -0
  206. package/dist/indexer/search/db-search.js +89 -13
  207. package/dist/indexer/search/fts-query.js +51 -0
  208. package/dist/indexer/search/ranking-contributors.js +95 -9
  209. package/dist/indexer/search/ranking.js +79 -3
  210. package/dist/indexer/search/search-fields.js +6 -0
  211. package/dist/indexer/search/search-source.js +32 -21
  212. package/dist/indexer/search/semantic-status.js +4 -0
  213. package/dist/indexer/walk/matchers.js +9 -0
  214. package/dist/indexer/walk/walker.js +21 -13
  215. package/dist/integrations/agent/builders.js +39 -13
  216. package/dist/integrations/agent/config.js +20 -59
  217. package/dist/integrations/agent/detect.js +9 -0
  218. package/dist/integrations/agent/index.js +3 -19
  219. package/dist/integrations/agent/model-aliases.js +7 -2
  220. package/dist/integrations/agent/profiles.js +7 -1
  221. package/dist/integrations/agent/prompts.js +75 -9
  222. package/dist/integrations/agent/runner-dispatch.js +59 -0
  223. package/dist/integrations/agent/runner.js +13 -9
  224. package/dist/integrations/agent/spawn.js +69 -67
  225. package/dist/integrations/harnesses/claude/agent-builder.js +1 -1
  226. package/dist/integrations/harnesses/claude/index.js +2 -0
  227. package/dist/integrations/harnesses/claude/session-log.js +10 -0
  228. package/dist/integrations/harnesses/index.js +2 -3
  229. package/dist/integrations/harnesses/opencode/agent-builder.js +1 -1
  230. package/dist/integrations/harnesses/opencode/index.js +2 -0
  231. package/dist/integrations/harnesses/opencode/session-log.js +173 -3
  232. package/dist/integrations/harnesses/opencode-sdk/index.js +2 -2
  233. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +98 -17
  234. package/dist/integrations/harnesses/types.js +1 -0
  235. package/dist/integrations/session-logs/index.js +16 -0
  236. package/dist/llm/call-ai.js +2 -2
  237. package/dist/llm/client.js +34 -11
  238. package/dist/llm/embedder.js +67 -4
  239. package/dist/llm/embedders/cache.js +3 -1
  240. package/dist/llm/embedders/deterministic.js +66 -0
  241. package/dist/llm/embedders/local.js +73 -3
  242. package/dist/llm/feature-gate.js +16 -15
  243. package/dist/llm/graph-extract.js +67 -44
  244. package/dist/llm/memory-infer-impl.js +138 -0
  245. package/dist/llm/memory-infer.js +1 -127
  246. package/dist/llm/metadata-enhance.js +44 -31
  247. package/dist/llm/structured-call.js +49 -0
  248. package/dist/migrate-storage-node.mjs +8 -0
  249. package/dist/output/context.js +5 -5
  250. package/dist/output/renderers.js +85 -14
  251. package/dist/output/shapes/curate.js +14 -2
  252. package/dist/output/shapes/helpers.js +0 -3
  253. package/dist/output/shapes/passthrough.js +2 -1
  254. package/dist/output/text/helpers.js +29 -1
  255. package/dist/output/text/workflow.js +1 -0
  256. package/dist/registry/providers/skills-sh.js +21 -147
  257. package/dist/registry/providers/static-index.js +15 -157
  258. package/dist/registry/resolve.js +27 -9
  259. package/dist/runtime.js +25 -1
  260. package/dist/scripts/migrate-storage.js +2661 -2369
  261. package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +883 -596
  262. package/dist/setup/detect.js +9 -0
  263. package/dist/setup/legacy-config.js +106 -0
  264. package/dist/setup/prompt.js +57 -0
  265. package/dist/setup/providers.js +14 -0
  266. package/dist/setup/registry-stash-loader.js +12 -0
  267. package/dist/setup/semantic-assets.js +124 -0
  268. package/dist/setup/setup.js +52 -1614
  269. package/dist/setup/steps/connection.js +734 -0
  270. package/dist/setup/steps/output.js +31 -0
  271. package/dist/setup/steps/platforms.js +124 -0
  272. package/dist/setup/steps/semantic.js +27 -0
  273. package/dist/setup/steps/sources.js +222 -0
  274. package/dist/setup/steps/stashdir.js +42 -0
  275. package/dist/setup/steps/tasks.js +152 -0
  276. package/dist/sources/include.js +6 -2
  277. package/dist/sources/providers/filesystem.js +0 -1
  278. package/dist/sources/providers/git-install.js +210 -0
  279. package/dist/sources/providers/git-provider.js +234 -0
  280. package/dist/sources/providers/git-stash.js +248 -0
  281. package/dist/sources/providers/git.js +10 -661
  282. package/dist/sources/providers/npm.js +2 -6
  283. package/dist/sources/providers/provider-utils.js +13 -7
  284. package/dist/sources/providers/sync-from-ref.js +9 -1
  285. package/dist/sources/providers/website.js +9 -5
  286. package/dist/sources/website-ingest.js +187 -29
  287. package/dist/sources/wiki-fetchers/registry.js +53 -0
  288. package/dist/sources/wiki-fetchers/youtube.js +239 -0
  289. package/dist/storage/database.js +45 -10
  290. package/dist/storage/managed-db.js +82 -0
  291. package/dist/storage/repositories/canaries-repository.js +107 -0
  292. package/dist/storage/repositories/consolidation-repository.js +38 -0
  293. package/dist/storage/repositories/embeddings-repository.js +72 -0
  294. package/dist/storage/repositories/events-repository.js +187 -0
  295. package/dist/storage/repositories/extract-sessions-repository.js +96 -0
  296. package/dist/storage/repositories/improve-runs-repository.js +146 -0
  297. package/dist/storage/repositories/index-db.js +14 -8
  298. package/dist/storage/repositories/proposals-repository.js +220 -0
  299. package/dist/storage/repositories/recombine-repository.js +213 -0
  300. package/dist/storage/repositories/registry-cache.js +93 -0
  301. package/dist/storage/repositories/registry-index-cache-repository.js +46 -0
  302. package/dist/storage/repositories/task-history-repository.js +93 -0
  303. package/dist/storage/sqlite-pragmas.js +146 -0
  304. package/dist/tasks/backends/cron.js +1 -1
  305. package/dist/tasks/backends/index.js +9 -0
  306. package/dist/tasks/backends/launchd.js +1 -1
  307. package/dist/tasks/backends/schtasks.js +1 -1
  308. package/dist/tasks/{resolveAkmBin.js → resolve-akm-bin.js} +2 -2
  309. package/dist/tasks/runner.js +15 -13
  310. package/dist/text-import-hook.mjs +0 -0
  311. package/dist/wiki/wiki.js +52 -11
  312. package/dist/workflows/cli.js +1 -0
  313. package/dist/workflows/db.js +3 -4
  314. package/dist/workflows/runtime/runs.js +43 -118
  315. package/dist/workflows/runtime/workflow-asset-loader.js +125 -0
  316. package/dist/workflows/validate-summary.js +2 -7
  317. package/docs/README.md +69 -18
  318. package/docs/data-and-telemetry.md +5 -4
  319. package/docs/migration/release-notes/0.7.0.md +1 -1
  320. package/docs/migration/release-notes/0.9.0.md +39 -0
  321. package/package.json +10 -10
  322. package/dist/assets/tasks/core/update-stashes.yml +0 -4
  323. package/dist/commands/db-cli.js +0 -23
  324. package/dist/indexer/db/db-backup.js +0 -376
  325. package/dist/indexer/passes/staleness-detect.js +0 -488
@@ -14,6 +14,11 @@ import { defaultWhich } from "../integrations/agent/detect.js";
14
14
  import { SESSION_LOG_HARNESSES } from "../integrations/harnesses/index.js";
15
15
  import { spawn } from "../runtime.js";
16
16
  import { detectHarnessConfigs } from "./harness-config-import.js";
17
+ let detectOverrides;
18
+ /** TEST-ONLY. Swap the network/host probes; pass undefined to restore. */
19
+ export function _setDetectForTests(fakes) {
20
+ detectOverrides = fakes;
21
+ }
17
22
  // ── Ollama Detection ────────────────────────────────────────────────────────
18
23
  const OLLAMA_BASE = "http://localhost:11434";
19
24
  /**
@@ -23,6 +28,8 @@ const OLLAMA_BASE = "http://localhost:11434";
23
28
  * via subprocess. Returns available models sorted alphabetically.
24
29
  */
25
30
  export async function detectOllama() {
31
+ if (detectOverrides?.detectOllama)
32
+ return detectOverrides.detectOllama();
26
33
  const result = { available: false, models: [], endpoint: OLLAMA_BASE };
27
34
  // Try HTTP API first
28
35
  try {
@@ -120,6 +127,8 @@ const AGENT_PLATFORMS = SESSION_LOG_HARNESSES.filter((h) => h.setupDetectionDir)
120
127
  * Supports both HOME (Unix) and USERPROFILE (Windows).
121
128
  */
122
129
  export function detectAgentPlatforms() {
130
+ if (detectOverrides?.detectAgentPlatforms)
131
+ return detectOverrides.detectAgentPlatforms();
123
132
  const home = process.env.HOME?.trim() || process.env.USERPROFILE?.trim();
124
133
  if (!home)
125
134
  return [];
@@ -0,0 +1,106 @@
1
+ // This Source Code Form is subject to the terms of the Mozilla Public
2
+ // License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
+ import { getDefaultLlmConfig } from "../core/config/config.js";
5
+ import { warn } from "../core/warn.js";
6
+ import { v1ProfilePlatform } from "../integrations/harnesses/index.js";
7
+ /** Read the currently-configured LLM connection from a loaded config. */
8
+ export function getCurrentLlm(config) {
9
+ return getDefaultLlmConfig(config);
10
+ }
11
+ /** Read a synthesised legacy-shape agent block from the new-shape AkmConfig. */
12
+ export function getCurrentAgentBlock(config) {
13
+ if (!config.profiles?.agent && !config.defaults?.agent)
14
+ return undefined;
15
+ const block = {};
16
+ if (config.defaults?.agent)
17
+ block.default = config.defaults.agent;
18
+ if (config.profiles?.agent) {
19
+ const profiles = {};
20
+ for (const [name, raw] of Object.entries(config.profiles.agent)) {
21
+ profiles[name] = {
22
+ ...(raw.platform === "opencode-sdk" ? { sdkMode: true } : {}),
23
+ ...(raw.model ? { model: raw.model } : {}),
24
+ ...(raw.bin ? { bin: raw.bin } : {}),
25
+ ...(raw.args ? { args: raw.args } : {}),
26
+ };
27
+ }
28
+ block.profiles = profiles;
29
+ }
30
+ return block;
31
+ }
32
+ /** Apply an LLM connection patch onto the new-shape config. */
33
+ export function applyLegacyLlm(config, llm) {
34
+ if (!llm) {
35
+ // Clear the default LLM profile.
36
+ const name = config.defaults?.llm ?? "default";
37
+ const remaining = { ...(config.profiles?.llm ?? {}) };
38
+ delete remaining[name];
39
+ return {
40
+ profiles: { ...(config.profiles ?? {}), llm: remaining },
41
+ defaults: { ...(config.defaults ?? {}), llm: undefined },
42
+ };
43
+ }
44
+ const name = config.defaults?.llm ?? "default";
45
+ return {
46
+ profiles: {
47
+ ...(config.profiles ?? {}),
48
+ llm: { ...(config.profiles?.llm ?? {}), [name]: llm },
49
+ },
50
+ defaults: { ...(config.defaults ?? {}), llm: name },
51
+ };
52
+ }
53
+ /** Apply a legacy-shape agent block onto the new-shape config. */
54
+ export function applyLegacyAgent(config, agent) {
55
+ if (!agent) {
56
+ return {
57
+ profiles: { ...(config.profiles ?? {}), agent: undefined },
58
+ defaults: { ...(config.defaults ?? {}), agent: undefined },
59
+ };
60
+ }
61
+ const v2Profiles = { ...(config.profiles?.agent ?? {}) };
62
+ for (const [name, profile] of Object.entries(agent.profiles ?? {})) {
63
+ // #566: resolve the platform via the harness registry instead of the old
64
+ // `name.includes("claude") ? "claude" : "opencode"` heuristic, which
65
+ // silently mapped Cursor/Copilot/any new harness to "opencode". An explicit
66
+ // sdkMode flag still wins; otherwise we ask the registry. A name the
67
+ // registry does not recognize is surfaced (warn) rather than silently
68
+ // misclassified, then kept as a best-effort "opencode" profile so the user
69
+ // does not lose a profile they explicitly configured.
70
+ let platform;
71
+ if (profile.sdkMode) {
72
+ platform = "opencode-sdk";
73
+ }
74
+ else {
75
+ const resolved = v1ProfilePlatform(name);
76
+ if (resolved) {
77
+ platform = resolved;
78
+ }
79
+ else {
80
+ warn(`[akm setup] Agent profile "${name}" did not match any known harness; ` +
81
+ `defaulting its platform to "opencode". Set its platform explicitly in config if this is wrong.`);
82
+ platform = "opencode";
83
+ }
84
+ }
85
+ v2Profiles[name] = {
86
+ platform,
87
+ ...(profile.bin ? { bin: profile.bin } : {}),
88
+ ...(profile.args ? { args: profile.args } : {}),
89
+ ...(profile.model ? { model: profile.model } : {}),
90
+ };
91
+ }
92
+ return {
93
+ profiles: { ...(config.profiles ?? {}), agent: v2Profiles },
94
+ defaults: { ...(config.defaults ?? {}), agent: agent.default },
95
+ };
96
+ }
97
+ /** Deep-ish clone of an LLM connection config (capabilities + extraParams). */
98
+ export function cloneLlmConfig(llm) {
99
+ if (!llm)
100
+ return undefined;
101
+ return {
102
+ ...llm,
103
+ ...(llm.capabilities ? { capabilities: { ...llm.capabilities } } : {}),
104
+ ...(llm.extraParams ? { extraParams: { ...llm.extraParams } } : {}),
105
+ };
106
+ }
@@ -0,0 +1,57 @@
1
+ // This Source Code Form is subject to the terms of the Mozilla Public
2
+ // License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
+ /**
5
+ * Clack prompt shims for the setup wizard: cancel-aware prompting so pressing
6
+ * Escape offers a confirm-to-quit rather than crashing the wizard.
7
+ */
8
+ import * as p from "../cli/clack.js";
9
+ export function bail() {
10
+ p.cancel("Setup cancelled. No changes were saved.");
11
+ process.exit(0);
12
+ }
13
+ /**
14
+ * Check if a prompt result was cancelled (Escape). If so, ask the user
15
+ * whether they really want to quit. Returns true if the user chose to
16
+ * stay (i.e. the caller should re-prompt), or calls bail() to exit.
17
+ *
18
+ * @internal Exported for testing only.
19
+ */
20
+ export async function onCancel(value) {
21
+ if (!p.isCancel(value))
22
+ return false;
23
+ const confirmExit = await p.confirm({
24
+ message: "Exit the wizard? No changes will be saved.",
25
+ initialValue: false,
26
+ });
27
+ // Only exit when the user explicitly confirms "Yes".
28
+ // Pressing Escape on the confirmation (isCancel) or choosing "No"
29
+ // both mean "stay in the wizard".
30
+ if (confirmExit === true) {
31
+ bail();
32
+ }
33
+ // User chose to stay
34
+ return true;
35
+ }
36
+ /**
37
+ * Run a prompt function in a loop, retrying if the user presses Escape
38
+ * but decides to stay. Returns the non-cancelled result.
39
+ */
40
+ export async function prompt(fn) {
41
+ for (;;) {
42
+ const result = await fn();
43
+ if (await onCancel(result))
44
+ continue;
45
+ return result;
46
+ }
47
+ }
48
+ /**
49
+ * Like `prompt`, but pressing Escape returns `null` instead of re-prompting.
50
+ * Use inside sub-actions so the user can back out to the parent menu.
51
+ */
52
+ export async function promptOrBack(fn) {
53
+ const result = await fn();
54
+ if (p.isCancel(result))
55
+ return null;
56
+ return result;
57
+ }
@@ -0,0 +1,14 @@
1
+ // This Source Code Form is subject to the terms of the Mozilla Public
2
+ // License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
+ /**
5
+ * Endpoint + default model for each cloud provider akm can recommend from a
6
+ * detected API key. A provider absent from this table yields no recommendation
7
+ * (the previous paired `switch`es both returned `undefined`).
8
+ */
9
+ export const PROVIDER_DEFAULTS = {
10
+ anthropic: { endpoint: "https://api.anthropic.com/v1", model: "claude-sonnet-4-5" },
11
+ openai: { endpoint: "https://api.openai.com/v1", model: "gpt-4o-mini" },
12
+ gemini: { endpoint: "https://generativelanguage.googleapis.com/v1beta/openai", model: "gemini-1.5-flash" },
13
+ groq: { endpoint: "https://api.groq.com/openai/v1", model: "llama-3.3-70b-versatile" },
14
+ };
@@ -44,6 +44,13 @@ const FALLBACK_STASHES = [
44
44
  defaultSelected: false,
45
45
  },
46
46
  ];
47
+ // ── Test seam ────────────────────────────────────────────────────────────────
48
+ // Swap-and-restore override. Inert in production; only tests call the setter.
49
+ let loadSetupStashesOverride;
50
+ /** TEST-ONLY. Swap the implementation of `loadSetupStashes`; pass undefined to restore. */
51
+ export function _setLoadSetupStashesForTests(fake) {
52
+ loadSetupStashesOverride = fake;
53
+ }
47
54
  // ── Loader ──────────────────────────────────────────────────────────────────
48
55
  /**
49
56
  * Fetch available stashes from the registry and map to SetupStashEntry[].
@@ -55,6 +62,11 @@ const FALLBACK_STASHES = [
55
62
  * @param timeoutMs Fetch timeout in ms (default: 4000).
56
63
  */
57
64
  export async function loadSetupStashes(registryUrl, timeoutMs = 4000) {
65
+ if (loadSetupStashesOverride)
66
+ return loadSetupStashesOverride(registryUrl, timeoutMs);
67
+ return loadSetupStashesReal(registryUrl, timeoutMs);
68
+ }
69
+ async function loadSetupStashesReal(registryUrl, timeoutMs = 4000) {
58
70
  try {
59
71
  const response = await fetch(registryUrl, {
60
72
  signal: AbortSignal.timeout(timeoutMs),
@@ -0,0 +1,124 @@
1
+ // This Source Code Form is subject to the terms of the Mozilla Public
2
+ // License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
+ /**
5
+ * Semantic-search asset preparation for the setup wizard. Isolates the one
6
+ * `bun add @huggingface/transformers` subprocess and the sqlite-vec probe so
7
+ * the rest of setup stays free of subprocess/DB I/O.
8
+ */
9
+ import fs from "node:fs";
10
+ import os from "node:os";
11
+ import path from "node:path";
12
+ import * as p from "../cli/clack.js";
13
+ import { isHttpUrl } from "../core/common.js";
14
+ import { closeDatabase, isVecAvailable, openIndexDatabase } from "../indexer/db/db.js";
15
+ import { checkEmbeddingAvailability, DEFAULT_LOCAL_MODEL, isTransformersAvailable } from "../llm/embedder.js";
16
+ import { getDirname, spawn } from "../runtime.js";
17
+ // Approximate first-download sizes used in the setup note.
18
+ // LOCAL_MODEL_APPROX_SIZE_MB tracks the default local model (DEFAULT_LOCAL_MODEL).
19
+ const LOCAL_MODEL_APPROX_SIZE_MB = 130;
20
+ // SQLITE_VEC_APPROX_SIZE_MB reflects the optional sqlite-vec install footprint.
21
+ const SQLITE_VEC_APPROX_SIZE_MB = 5;
22
+ export function isRemoteEmbeddingConfig(embedding) {
23
+ return isHttpUrl(embedding?.endpoint);
24
+ }
25
+ /**
26
+ * @internal Exported for testing only.
27
+ */
28
+ export function describeSemanticSearchAssets(embedding) {
29
+ if (isRemoteEmbeddingConfig(embedding)) {
30
+ return [
31
+ `• Embedding endpoint: ${embedding?.provider ?? "custom"} / ${embedding?.model} (no local model download)`,
32
+ `• sqlite-vec acceleration: optional native extension (~${SQLITE_VEC_APPROX_SIZE_MB} MB when installed separately)`,
33
+ ];
34
+ }
35
+ return [
36
+ `• Local embedding model: ${embedding?.localModel ?? DEFAULT_LOCAL_MODEL} (~${LOCAL_MODEL_APPROX_SIZE_MB} MB download on first use)`,
37
+ `• sqlite-vec acceleration: optional native extension (~${SQLITE_VEC_APPROX_SIZE_MB} MB when installed separately)`,
38
+ ];
39
+ }
40
+ export async function prepareSemanticSearchAssets(config) {
41
+ const remote = isRemoteEmbeddingConfig(config.embedding);
42
+ // For local embeddings, ensure the required package is installed first.
43
+ if (!remote) {
44
+ if (!isTransformersAvailable()) {
45
+ const spin = p.spinner();
46
+ spin.start("Installing @huggingface/transformers...");
47
+ try {
48
+ const pkgRoot = path.resolve(getDirname(import.meta.url), "../..");
49
+ const proc = spawn(["bun", "add", "@huggingface/transformers"], {
50
+ cwd: pkgRoot,
51
+ stdout: "pipe",
52
+ stderr: "pipe",
53
+ });
54
+ await proc.exited;
55
+ if (proc.exitCode !== 0) {
56
+ const stderr = await new Response(proc.stderr).text();
57
+ throw new Error(stderr || `exit code ${proc.exitCode}`);
58
+ }
59
+ spin.stop("@huggingface/transformers installed.");
60
+ }
61
+ catch (err) {
62
+ const msg = err instanceof Error ? err.message : String(err);
63
+ spin.stop("Could not install @huggingface/transformers.");
64
+ p.log.warn(`Automatic install failed: ${msg}\n` +
65
+ "Install it manually with: bun add @huggingface/transformers\n" +
66
+ "Then re-run `akm setup` or `akm index --full --verbose`.");
67
+ return { ok: false, reason: "missing-package", message: `Automatic install failed: ${msg}` };
68
+ }
69
+ }
70
+ }
71
+ const spin = p.spinner();
72
+ spin.start(remote
73
+ ? "Checking remote embedding endpoint..."
74
+ : `Downloading local embedding model (${config.embedding?.localModel ?? DEFAULT_LOCAL_MODEL})...`);
75
+ const result = await checkEmbeddingAvailability(config.embedding);
76
+ if (!result.available) {
77
+ spin.stop("Semantic-search assets could not be prepared.");
78
+ if (result.reason === "remote-unreachable") {
79
+ p.log.warn("The remote embedding endpoint is not reachable. Check your endpoint and credentials, then retry `akm index --full --verbose`.");
80
+ return { ok: false, reason: "remote-network", message: "The remote embedding endpoint is not reachable." };
81
+ }
82
+ else if (result.reason === "missing-package") {
83
+ p.log.warn("@huggingface/transformers is not installed. Install it with: bun add @huggingface/transformers\n" +
84
+ "Then re-run `akm setup` or `akm index --full --verbose`.");
85
+ return { ok: false, reason: "missing-package", message: "@huggingface/transformers is not installed." };
86
+ }
87
+ else {
88
+ p.log.warn(`The local embedding model could not be downloaded: ${result.message}\n` +
89
+ "Retry `akm index --full --verbose` after confirming local model downloads are permitted.");
90
+ return { ok: false, reason: "local-model-download", message: result.message };
91
+ }
92
+ }
93
+ spin.stop(remote ? "Remote embedding endpoint is ready." : "Local embedding model downloaded and ready.");
94
+ let db;
95
+ let probeDir;
96
+ try {
97
+ probeDir = fs.mkdtempSync(path.join(os.tmpdir(), "akm-setup-vec-probe-"));
98
+ db = openIndexDatabase(path.join(probeDir, "probe.db"), config.embedding?.dimension ? { embeddingDim: config.embedding.dimension } : undefined);
99
+ if (isVecAvailable(db)) {
100
+ p.log.info("sqlite-vec is available for fast vector search.");
101
+ }
102
+ else {
103
+ p.log.info("sqlite-vec is not available. Semantic search will use the JS fallback until the optional extension is installed.");
104
+ }
105
+ }
106
+ catch (error) {
107
+ const message = error instanceof Error ? error.message : String(error);
108
+ p.log.warn(`Could not open the local database or check for sqlite-vec. Semantic search will use the JS fallback. (${message})\n` +
109
+ "Check file permissions and available disk space in the cache directory, or run `akm index --full --verbose` to diagnose.");
110
+ }
111
+ finally {
112
+ if (db)
113
+ closeDatabase(db);
114
+ if (probeDir) {
115
+ try {
116
+ fs.rmSync(probeDir, { recursive: true, force: true });
117
+ }
118
+ catch {
119
+ /* ignore cleanup failure */
120
+ }
121
+ }
122
+ }
123
+ return { ok: true };
124
+ }