akm-cli 0.8.0-rc2 → 0.8.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 (295) hide show
  1. package/{.github/CHANGELOG.md → CHANGELOG.md} +191 -3
  2. package/README.md +22 -6
  3. package/SECURITY.md +93 -0
  4. package/dist/cli/config-migrate.js +144 -0
  5. package/dist/cli/config-validate.js +39 -0
  6. package/dist/cli/confirm.js +73 -0
  7. package/dist/cli/parse-args.js +93 -3
  8. package/dist/cli/shared.js +129 -0
  9. package/dist/cli.js +2141 -1268
  10. package/dist/commands/add-cli.js +279 -0
  11. package/dist/commands/agent-dispatch.js +20 -12
  12. package/dist/commands/agent-support.js +11 -5
  13. package/dist/commands/completions.js +3 -0
  14. package/dist/commands/config-cli.js +129 -517
  15. package/dist/commands/consolidate.js +1533 -144
  16. package/dist/commands/curate.js +44 -3
  17. package/dist/commands/db-cli.js +23 -0
  18. package/dist/commands/distill-promotion-policy.js +5 -3
  19. package/dist/commands/distill.js +906 -100
  20. package/dist/commands/env.js +213 -0
  21. package/dist/commands/eval-cases.js +3 -0
  22. package/dist/commands/events.js +3 -0
  23. package/dist/commands/extract-cli.js +127 -0
  24. package/dist/commands/extract-prompt.js +204 -0
  25. package/dist/commands/extract.js +477 -0
  26. package/dist/commands/feedback-cli.js +331 -0
  27. package/dist/commands/graph.js +260 -5
  28. package/dist/commands/health.js +977 -51
  29. package/dist/commands/help/help-accept.md +6 -3
  30. package/dist/commands/help/help-improve.md +36 -8
  31. package/dist/commands/help/help-proposals.md +7 -4
  32. package/dist/commands/help/help-reject.md +5 -2
  33. package/dist/commands/history.js +51 -16
  34. package/dist/commands/improve-auto-accept.js +97 -0
  35. package/dist/commands/improve-cli.js +236 -0
  36. package/dist/commands/improve-profiles.js +184 -0
  37. package/dist/commands/improve-result-file.js +167 -0
  38. package/dist/commands/improve.js +1725 -332
  39. package/dist/commands/info.js +3 -0
  40. package/dist/commands/init.js +49 -1
  41. package/dist/commands/installed-stashes.js +6 -23
  42. package/dist/commands/knowledge.js +3 -0
  43. package/dist/commands/lint/agent-linter.js +3 -0
  44. package/dist/commands/lint/base-linter.js +199 -5
  45. package/dist/commands/lint/command-linter.js +3 -0
  46. package/dist/commands/lint/default-linter.js +3 -0
  47. package/dist/commands/lint/env-key-rules.js +154 -0
  48. package/dist/commands/lint/index.js +92 -3
  49. package/dist/commands/lint/knowledge-linter.js +3 -0
  50. package/dist/commands/lint/markdown-insertion.js +343 -0
  51. package/dist/commands/lint/memory-linter.js +3 -0
  52. package/dist/commands/lint/registry.js +3 -0
  53. package/dist/commands/lint/skill-linter.js +3 -0
  54. package/dist/commands/lint/task-linter.js +15 -12
  55. package/dist/commands/lint/types.js +3 -0
  56. package/dist/commands/lint/workflow-linter.js +3 -0
  57. package/dist/commands/lint.js +3 -0
  58. package/dist/commands/migration-help.js +5 -2
  59. package/dist/commands/proposal-drain-policies.js +128 -0
  60. package/dist/commands/proposal-drain.js +477 -0
  61. package/dist/commands/proposal.js +60 -6
  62. package/dist/commands/propose.js +24 -19
  63. package/dist/commands/reflect.js +1004 -94
  64. package/dist/commands/registry-cli.js +150 -0
  65. package/dist/commands/registry-search.js +3 -0
  66. package/dist/commands/remember-cli.js +257 -0
  67. package/dist/commands/remember.js +15 -6
  68. package/dist/commands/schema-repair.js +88 -15
  69. package/dist/commands/search.js +99 -14
  70. package/dist/commands/secret.js +173 -0
  71. package/dist/commands/self-update.js +3 -0
  72. package/dist/commands/show.js +32 -13
  73. package/dist/commands/source-add.js +7 -35
  74. package/dist/commands/source-clone.js +3 -0
  75. package/dist/commands/source-manage.js +3 -0
  76. package/dist/commands/tasks.js +161 -95
  77. package/dist/commands/url-checker.js +3 -0
  78. package/dist/core/action-contributors.js +3 -0
  79. package/dist/core/asset-ref.js +13 -2
  80. package/dist/core/asset-registry.js +9 -2
  81. package/dist/core/asset-serialize.js +88 -0
  82. package/dist/core/asset-spec.js +61 -5
  83. package/dist/core/common.js +93 -5
  84. package/dist/core/concurrent.js +3 -0
  85. package/dist/core/config-io.js +347 -0
  86. package/dist/core/config-migration.js +622 -0
  87. package/dist/core/config-schema.js +558 -0
  88. package/dist/core/config-sources.js +108 -0
  89. package/dist/core/config-types.js +4 -0
  90. package/dist/core/config-walker.js +337 -0
  91. package/dist/core/config.js +366 -1077
  92. package/dist/core/errors.js +42 -20
  93. package/dist/core/events.js +31 -25
  94. package/dist/core/file-lock.js +104 -0
  95. package/dist/core/frontmatter.js +75 -10
  96. package/dist/core/lesson-lint.js +3 -0
  97. package/dist/core/markdown.js +3 -0
  98. package/dist/core/memory-belief.js +62 -0
  99. package/dist/core/memory-contradiction-detect.js +274 -0
  100. package/dist/core/memory-improve.js +142 -14
  101. package/dist/core/parse.js +3 -0
  102. package/dist/core/paths.js +218 -50
  103. package/dist/core/proposal-quality-validators.js +380 -0
  104. package/dist/core/proposal-validators.js +11 -3
  105. package/dist/core/proposals.js +464 -5
  106. package/dist/core/state-db.js +349 -56
  107. package/dist/core/text-truncation.js +107 -0
  108. package/dist/core/time.js +3 -0
  109. package/dist/core/tty.js +59 -0
  110. package/dist/core/warn.js +7 -2
  111. package/dist/core/write-source.js +12 -0
  112. package/dist/indexer/db-backup.js +391 -0
  113. package/dist/indexer/db-search.js +136 -28
  114. package/dist/indexer/db.js +661 -166
  115. package/dist/indexer/ensure-index.js +3 -0
  116. package/dist/indexer/file-context.js +3 -0
  117. package/dist/indexer/graph-boost.js +162 -40
  118. package/dist/indexer/graph-db.js +241 -51
  119. package/dist/indexer/graph-dedup.js +3 -7
  120. package/dist/indexer/graph-extraction.js +242 -149
  121. package/dist/indexer/index-context.js +3 -9
  122. package/dist/indexer/indexer.js +84 -14
  123. package/dist/indexer/llm-cache.js +24 -19
  124. package/dist/indexer/manifest.js +3 -0
  125. package/dist/indexer/matchers.js +184 -11
  126. package/dist/indexer/memory-inference.js +94 -50
  127. package/dist/indexer/metadata-contributors.js +3 -0
  128. package/dist/indexer/metadata.js +110 -50
  129. package/dist/indexer/path-resolver.js +3 -0
  130. package/dist/indexer/project-context.js +192 -0
  131. package/dist/indexer/ranking-contributors.js +134 -7
  132. package/dist/indexer/ranking.js +8 -1
  133. package/dist/indexer/search-fields.js +5 -9
  134. package/dist/indexer/search-hit-enrichers.js +91 -2
  135. package/dist/indexer/search-source.js +20 -1
  136. package/dist/indexer/semantic-status.js +4 -1
  137. package/dist/indexer/staleness-detect.js +447 -0
  138. package/dist/indexer/usage-events.js +12 -9
  139. package/dist/indexer/walker.js +3 -0
  140. package/dist/integrations/agent/builders.js +135 -0
  141. package/dist/integrations/agent/config.js +121 -401
  142. package/dist/integrations/agent/detect.js +3 -0
  143. package/dist/integrations/agent/index.js +6 -14
  144. package/dist/integrations/agent/model-aliases.js +55 -0
  145. package/dist/integrations/agent/profiles.js +3 -0
  146. package/dist/integrations/agent/prompts.js +137 -8
  147. package/dist/integrations/agent/runner.js +208 -0
  148. package/dist/integrations/agent/sdk-runner.js +8 -2
  149. package/dist/integrations/agent/spawn.js +54 -14
  150. package/dist/integrations/github.js +3 -0
  151. package/dist/integrations/lockfile.js +22 -51
  152. package/dist/integrations/session-logs/index.js +4 -0
  153. package/dist/integrations/session-logs/inline-refs.js +35 -0
  154. package/dist/integrations/session-logs/pre-filter.js +152 -0
  155. package/dist/integrations/session-logs/providers/claude-code.js +226 -0
  156. package/dist/integrations/session-logs/providers/opencode.js +231 -25
  157. package/dist/integrations/session-logs/types.js +3 -0
  158. package/dist/llm/call-ai.js +14 -26
  159. package/dist/llm/client.js +16 -2
  160. package/dist/llm/embedder.js +20 -29
  161. package/dist/llm/embedders/cache.js +3 -7
  162. package/dist/llm/embedders/local.js +42 -1
  163. package/dist/llm/embedders/remote.js +20 -8
  164. package/dist/llm/embedders/types.js +3 -7
  165. package/dist/llm/feature-gate.js +92 -56
  166. package/dist/llm/graph-extract.js +401 -30
  167. package/dist/llm/index-passes.js +44 -29
  168. package/dist/llm/memory-infer.js +30 -2
  169. package/dist/llm/metadata-enhance.js +3 -7
  170. package/dist/llm/prompts/extract-session.md +80 -0
  171. package/dist/llm/prompts/graph-extract-user-prompt.md +24 -1
  172. package/dist/output/cli-hints-full.md +60 -32
  173. package/dist/output/cli-hints-short.md +10 -7
  174. package/dist/output/cli-hints.js +5 -2
  175. package/dist/output/context.js +60 -8
  176. package/dist/output/renderers.js +170 -194
  177. package/dist/output/shapes/curate.js +56 -0
  178. package/dist/output/shapes/distill.js +10 -0
  179. package/dist/output/shapes/env-list.js +19 -0
  180. package/dist/output/shapes/events.js +11 -0
  181. package/dist/output/shapes/helpers.js +424 -0
  182. package/dist/output/shapes/history.js +7 -0
  183. package/dist/output/shapes/passthrough.js +105 -0
  184. package/dist/output/shapes/proposal-accept.js +7 -0
  185. package/dist/output/shapes/proposal-diff.js +7 -0
  186. package/dist/output/shapes/proposal-list.js +7 -0
  187. package/dist/output/shapes/proposal-producer.js +11 -0
  188. package/dist/output/shapes/proposal-reject.js +7 -0
  189. package/dist/output/shapes/proposal-show.js +7 -0
  190. package/dist/output/shapes/registry-search.js +6 -0
  191. package/dist/output/shapes/registry.js +30 -0
  192. package/dist/output/shapes/search.js +6 -0
  193. package/dist/output/shapes/secret-list.js +19 -0
  194. package/dist/output/shapes/show.js +6 -0
  195. package/dist/output/shapes/vault-list.js +19 -0
  196. package/dist/output/shapes.js +51 -549
  197. package/dist/output/text/add.js +6 -0
  198. package/dist/output/text/clone.js +6 -0
  199. package/dist/output/text/config.js +6 -0
  200. package/dist/output/text/curate.js +6 -0
  201. package/dist/output/text/distill.js +7 -0
  202. package/dist/output/text/enable-disable.js +7 -0
  203. package/dist/output/text/events.js +10 -0
  204. package/dist/output/text/feedback.js +6 -0
  205. package/dist/output/text/helpers.js +1059 -0
  206. package/dist/output/text/history.js +7 -0
  207. package/dist/output/text/import.js +6 -0
  208. package/dist/output/text/index.js +6 -0
  209. package/dist/output/text/info.js +6 -0
  210. package/dist/output/text/init.js +6 -0
  211. package/dist/output/text/list.js +6 -0
  212. package/dist/output/text/proposal-producer.js +8 -0
  213. package/dist/output/text/proposal.js +12 -0
  214. package/dist/output/text/registry-commands.js +11 -0
  215. package/dist/output/text/registry.js +30 -0
  216. package/dist/output/text/remember.js +6 -0
  217. package/dist/output/text/remove.js +6 -0
  218. package/dist/output/text/save.js +6 -0
  219. package/dist/output/text/search.js +6 -0
  220. package/dist/output/text/show.js +6 -0
  221. package/dist/output/text/update.js +6 -0
  222. package/dist/output/text/upgrade.js +6 -0
  223. package/dist/output/text/vault.js +16 -0
  224. package/dist/output/text/wiki.js +15 -0
  225. package/dist/output/text/workflow.js +14 -0
  226. package/dist/output/text.js +44 -1329
  227. package/dist/registry/build-index.js +3 -0
  228. package/dist/registry/create-provider-registry.js +3 -0
  229. package/dist/registry/factory.js +4 -1
  230. package/dist/registry/origin-resolve.js +3 -0
  231. package/dist/registry/providers/index.js +3 -0
  232. package/dist/registry/providers/skills-sh.js +11 -2
  233. package/dist/registry/providers/static-index.js +10 -1
  234. package/dist/registry/providers/types.js +3 -24
  235. package/dist/registry/resolve.js +11 -16
  236. package/dist/registry/types.js +3 -0
  237. package/dist/scripts/migrate-storage.js +17767 -0
  238. package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +9031 -0
  239. package/dist/scripts/migrations/v16-to-v17.js +141 -0
  240. package/dist/setup/detect.js +3 -0
  241. package/dist/setup/ripgrep-install.js +3 -0
  242. package/dist/setup/ripgrep-resolve.js +3 -0
  243. package/dist/setup/setup.js +306 -67
  244. package/dist/setup/steps.js +3 -15
  245. package/dist/sources/include.js +3 -0
  246. package/dist/sources/provider-factory.js +3 -11
  247. package/dist/sources/provider.js +3 -20
  248. package/dist/sources/providers/filesystem.js +19 -23
  249. package/dist/sources/providers/git.js +171 -21
  250. package/dist/sources/providers/index.js +3 -0
  251. package/dist/sources/providers/install-types.js +3 -13
  252. package/dist/sources/providers/npm.js +3 -4
  253. package/dist/sources/providers/provider-utils.js +3 -0
  254. package/dist/sources/providers/sync-from-ref.js +3 -11
  255. package/dist/sources/providers/tar-utils.js +3 -0
  256. package/dist/sources/providers/website.js +18 -22
  257. package/dist/sources/resolve.js +3 -0
  258. package/dist/sources/types.js +3 -0
  259. package/dist/sources/website-ingest.js +3 -0
  260. package/dist/tasks/backends/cron.js +3 -0
  261. package/dist/tasks/backends/exec-utils.js +3 -0
  262. package/dist/tasks/backends/index.js +3 -11
  263. package/dist/tasks/backends/launchd.js +3 -0
  264. package/dist/tasks/backends/schtasks.js +3 -0
  265. package/dist/tasks/parser.js +51 -38
  266. package/dist/tasks/resolveAkmBin.js +3 -0
  267. package/dist/tasks/runner.js +35 -9
  268. package/dist/tasks/schedule.js +20 -1
  269. package/dist/tasks/schema.js +5 -3
  270. package/dist/tasks/validator.js +6 -3
  271. package/dist/version.js +3 -0
  272. package/dist/wiki/wiki-templates.js +3 -0
  273. package/dist/wiki/wiki.js +3 -0
  274. package/dist/workflows/authoring.js +3 -0
  275. package/dist/workflows/cli.js +3 -0
  276. package/dist/workflows/db.js +140 -10
  277. package/dist/workflows/document-cache.js +3 -10
  278. package/dist/workflows/parser.js +3 -0
  279. package/dist/workflows/renderer.js +3 -0
  280. package/dist/workflows/runs.js +18 -1
  281. package/dist/workflows/schema.js +3 -0
  282. package/dist/workflows/scope-key.js +3 -0
  283. package/dist/workflows/validator.js +5 -9
  284. package/docs/README.md +7 -2
  285. package/docs/data-and-telemetry.md +225 -0
  286. package/docs/migration/release-notes/0.7.5.md +2 -2
  287. package/docs/migration/release-notes/0.8.0.md +57 -5
  288. package/docs/migration/v0.7-to-v0.8.md +1378 -0
  289. package/package.json +28 -11
  290. package/.github/LICENSE +0 -374
  291. package/dist/commands/install-audit.js +0 -385
  292. package/dist/commands/vault.js +0 -310
  293. package/dist/indexer/match-contributors.js +0 -141
  294. package/dist/integrations/agent/pipeline.js +0 -39
  295. package/dist/integrations/agent/runners.js +0 -31
@@ -1,351 +1,25 @@
1
- /**
2
- * Parser + resolver for the optional `agent` config block (v1 spec §12).
3
- *
4
- * The on-disk shape is:
5
- *
6
- * ```jsonc
7
- * {
8
- * "agent": {
9
- * "default": "opencode",
10
- * "timeoutMs": 60000,
11
- * "profiles": {
12
- * "opencode": { "bin": "opencode", "args": ["--non-interactive"], ... }
13
- * }
14
- * }
15
- * }
16
- * ```
17
- *
18
- * Unknown keys at any level under `agent` are warn-and-ignored — this is the
19
- * v1 §9.2 contract. Missing `agent` block disables agent commands; callers
20
- * should reach for {@link requireAgentConfig} to surface a stable
21
- * `ConfigError` with a hint pointing at setup.
22
- *
23
- * No LLM SDK is imported here. The runtime path is shell-out only (see
24
- * `./spawn.ts`).
25
- */
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/.
26
4
  import { ConfigError } from "../../core/errors";
27
5
  import { warn } from "../../core/warn";
28
6
  import { BUILTIN_AGENT_PROFILE_NAMES, getBuiltinAgentProfile, listBuiltinAgentProfiles, } from "./profiles";
29
- /** Keys recognised at the top level of an `agent` config block. */
30
- const KNOWN_AGENT_KEYS = new Set(["default", "timeoutMs", "profiles", "processes"]);
31
- /** Keys recognised on a profile entry. */
32
- const KNOWN_PROFILE_KEYS = new Set([
33
- "bin",
34
- "args",
35
- "stdio",
36
- "env",
37
- "envPassthrough",
38
- "timeoutMs",
39
- "parseOutput",
40
- "sdkMode",
41
- "model",
42
- "endpoint",
43
- "apiKey",
44
- ]);
45
7
  /**
46
- * Default hard timeout for an agent CLI. Spec §12.2 calls for a hard
47
- * timeout; 60s matches the example value in `docs/configuration.md`.
8
+ * Default hard timeout for an agent CLI (60s matches the value used in
9
+ * `docs/configuration.md`).
48
10
  */
49
11
  export const DEFAULT_AGENT_TIMEOUT_MS = 60_000;
50
- /** Keys recognised on a `processes[<name>]` object entry. */
51
- const KNOWN_PROCESS_ENTRY_KEYS = new Set(["profile", "timeoutMs"]);
52
- /**
53
- * Parse a raw value (typically `rawConfig.agent` from `JSON.parse`) into a
54
- * normalised {@link AgentConfig}. Returns `undefined` when the value is not
55
- * an object (i.e. the block is absent or malformed at the root level — for
56
- * malformed roots we emit a warning).
57
- *
58
- * Unknown keys (top-level and per-profile) are warn-and-ignore. Type errors
59
- * on individual fields are warn-and-ignore so a bad `timeoutMs` does not
60
- * break the rest of the block.
61
- */
62
- export function parseAgentConfig(value) {
63
- if (value === undefined)
64
- return undefined;
65
- if (typeof value !== "object" || value === null || Array.isArray(value)) {
66
- warn('[akm] Ignoring "agent" config: expected an object.');
67
- return undefined;
68
- }
69
- const raw = value;
70
- const out = {};
71
- for (const key of Object.keys(raw)) {
72
- if (!KNOWN_AGENT_KEYS.has(key)) {
73
- warn(`[akm] Ignoring unknown agent config key: "${key}"`);
74
- }
75
- }
76
- if ("default" in raw) {
77
- if (typeof raw.default === "string" && raw.default.trim()) {
78
- out.default = raw.default.trim();
79
- }
80
- else if (raw.default !== undefined) {
81
- warn("[akm] Ignoring agent.default: expected a non-empty string.");
82
- }
83
- }
84
- if ("timeoutMs" in raw) {
85
- if (typeof raw.timeoutMs === "number" &&
86
- Number.isFinite(raw.timeoutMs) &&
87
- Number.isInteger(raw.timeoutMs) &&
88
- raw.timeoutMs > 0) {
89
- out.timeoutMs = raw.timeoutMs;
90
- }
91
- else {
92
- warn("[akm] Ignoring agent.timeoutMs: expected a positive integer (milliseconds).");
93
- }
94
- }
95
- if ("profiles" in raw) {
96
- const profiles = parseAgentProfilesMap(raw.profiles);
97
- if (profiles)
98
- out.profiles = profiles;
99
- }
100
- if ("processes" in raw) {
101
- const processes = parseProcessesMap(raw.processes);
102
- if (processes)
103
- out.processes = processes;
104
- }
105
- return out;
106
- }
107
- function parseAgentProfilesMap(value) {
108
- if (typeof value !== "object" || value === null || Array.isArray(value)) {
109
- warn("[akm] Ignoring agent.profiles: expected an object.");
110
- return undefined;
111
- }
112
- const out = {};
113
- for (const [name, raw] of Object.entries(value)) {
114
- const parsed = parseAgentProfileConfig(name, raw);
115
- if (parsed)
116
- out[name] = parsed;
117
- }
118
- return Object.keys(out).length > 0 ? out : undefined;
119
- }
120
- /**
121
- * Parse one entry in `agent.processes`. Accepts a string (profile name) or an
122
- * object with optional `profile` and `timeoutMs` fields. Returns `undefined`
123
- * and emits a warning for entries that are neither valid strings nor valid
124
- * objects (warn-and-ignore).
125
- */
126
- export function parseProcessEntry(value, name) {
127
- if (typeof value === "string") {
128
- if (!value.trim()) {
129
- warn(`[akm] Ignoring agent.processes."${name}": string value must be non-empty (a profile name).`);
130
- return undefined;
131
- }
132
- return value.trim();
133
- }
134
- if (typeof value !== "object" || value === null || Array.isArray(value)) {
135
- warn(`[akm] Ignoring agent.processes."${name}": expected a string (profile name) or an object with optional "profile" and "timeoutMs".`);
136
- return undefined;
137
- }
138
- const raw = value;
139
- // Warn on unknown keys (warn-and-ignore contract).
140
- for (const key of Object.keys(raw)) {
141
- if (!KNOWN_PROCESS_ENTRY_KEYS.has(key)) {
142
- warn(`[akm] Ignoring unknown agent.processes."${name}" key: "${key}"`);
143
- }
144
- }
145
- const out = {};
146
- if ("profile" in raw) {
147
- if (typeof raw.profile === "string" && raw.profile.trim()) {
148
- out.profile = raw.profile.trim();
149
- }
150
- else if (raw.profile !== undefined) {
151
- warn(`[akm] Ignoring agent.processes."${name}".profile: expected a non-empty string.`);
152
- }
153
- }
154
- if ("timeoutMs" in raw) {
155
- if (raw.timeoutMs === null) {
156
- // null = unlimited — explicit, valid.
157
- out.timeoutMs = null;
158
- }
159
- else if (typeof raw.timeoutMs === "number" &&
160
- Number.isFinite(raw.timeoutMs) &&
161
- Number.isInteger(raw.timeoutMs) &&
162
- raw.timeoutMs > 0) {
163
- out.timeoutMs = raw.timeoutMs;
164
- }
165
- else {
166
- warn(`[akm] Ignoring agent.processes."${name}".timeoutMs: expected a positive integer (milliseconds) or null (unlimited).`);
167
- }
168
- }
169
- return out;
170
- }
171
- /**
172
- * Parse the `agent.processes` map. Returns `undefined` when the value is not
173
- * a valid object; per-entry validation errors are warn-and-ignored (per spec §9.2).
174
- */
175
- export function parseProcessesMap(value) {
176
- if (typeof value !== "object" || value === null || Array.isArray(value)) {
177
- warn("[akm] Ignoring agent.processes: expected an object.");
178
- return undefined;
179
- }
180
- const out = {};
181
- for (const [name, raw] of Object.entries(value)) {
182
- const parsed = parseProcessEntry(raw, name);
183
- if (parsed !== undefined)
184
- out[name] = parsed;
185
- }
186
- return Object.keys(out).length > 0 ? out : undefined;
187
- }
188
- /**
189
- * Resolve the agent profile and effective timeout for a named process.
190
- *
191
- * Resolution order:
192
- * 1. `config.processes[processName]` — if a string, that is the profile name;
193
- * if an object, extract `profile` (and optionally `timeoutMs`).
194
- * 2. Profile name falls back to `config.default` when not specified in the
195
- * process entry.
196
- * 3. `timeoutMs` falls back: `process.timeoutMs` (null = unlimited) →
197
- * profile.timeoutMs → agent.timeoutMs → DEFAULT_AGENT_TIMEOUT_MS.
198
- *
199
- * Returns `{ profile, timeoutMs }` where `timeoutMs` is `undefined` when the
200
- * resolved timeout is `null` (unlimited) or when no timeout is set at any
201
- * layer (callers treat `undefined` as the DEFAULT_AGENT_TIMEOUT_MS default).
202
- *
203
- * Throws {@link ConfigError} (via {@link requireAgentProfile}) when the agent
204
- * block is missing or the resolved profile cannot be used.
205
- */
206
- export function resolveProcessAgentProfile(processName, agentConfig) {
207
- let profileName;
208
- let processTimeoutMs; // null = unlimited from config
209
- const processEntry = agentConfig?.processes?.[processName];
210
- if (processEntry !== undefined) {
211
- if (typeof processEntry === "string") {
212
- profileName = processEntry;
213
- }
214
- else {
215
- profileName = processEntry.profile;
216
- processTimeoutMs = processEntry.timeoutMs;
217
- }
218
- }
219
- // Profile name falls back to agent.default when not set in the process entry.
220
- const resolvedProfile = requireAgentProfile(agentConfig, profileName);
221
- // Timeout resolution: process entry → profile → agent-level → undefined (caller applies DEFAULT).
222
- let resolvedTimeoutMs;
223
- if (processTimeoutMs === null) {
224
- // null = explicit "unlimited" — surface as undefined so callers omit the timer.
225
- resolvedTimeoutMs = undefined;
226
- }
227
- else if (processTimeoutMs !== undefined) {
228
- resolvedTimeoutMs = processTimeoutMs;
229
- }
230
- else if (resolvedProfile.timeoutMs !== undefined) {
231
- resolvedTimeoutMs = resolvedProfile.timeoutMs;
232
- }
233
- else if (agentConfig?.timeoutMs !== undefined) {
234
- resolvedTimeoutMs = agentConfig.timeoutMs;
235
- }
236
- return { profile: resolvedProfile, timeoutMs: resolvedTimeoutMs };
237
- }
238
- function parseAgentProfileConfig(name, value) {
239
- if (typeof value !== "object" || value === null || Array.isArray(value)) {
240
- warn(`[akm] Ignoring agent.profiles."${name}": expected an object.`);
241
- return undefined;
242
- }
243
- const raw = value;
244
- const out = {};
245
- for (const key of Object.keys(raw)) {
246
- if (!KNOWN_PROFILE_KEYS.has(key)) {
247
- warn(`[akm] Ignoring unknown agent.profiles."${name}" key: "${key}"`);
248
- }
249
- }
250
- if (typeof raw.bin === "string" && raw.bin.trim()) {
251
- out.bin = raw.bin.trim();
252
- }
253
- else if (raw.bin !== undefined) {
254
- warn(`[akm] Ignoring agent.profiles."${name}".bin: expected a non-empty string.`);
255
- }
256
- if (Array.isArray(raw.args)) {
257
- const args = raw.args.filter((a) => typeof a === "string");
258
- if (args.length === raw.args.length) {
259
- out.args = args;
260
- }
261
- else {
262
- warn(`[akm] Ignoring non-string entries in agent.profiles."${name}".args.`);
263
- if (args.length > 0)
264
- out.args = args;
265
- }
266
- }
267
- else if (raw.args !== undefined) {
268
- warn(`[akm] Ignoring agent.profiles."${name}".args: expected an array of strings.`);
269
- }
270
- if (raw.stdio === "captured" || raw.stdio === "interactive") {
271
- out.stdio = raw.stdio;
272
- }
273
- else if (raw.stdio !== undefined) {
274
- warn(`[akm] Ignoring agent.profiles."${name}".stdio: expected "captured" or "interactive".`);
275
- }
276
- if (typeof raw.env === "object" && raw.env !== null && !Array.isArray(raw.env)) {
277
- const env = {};
278
- for (const [k, v] of Object.entries(raw.env)) {
279
- if (typeof v === "string")
280
- env[k] = v;
281
- }
282
- if (Object.keys(env).length > 0)
283
- out.env = env;
284
- }
285
- else if (raw.env !== undefined) {
286
- warn(`[akm] Ignoring agent.profiles."${name}".env: expected a string-valued object.`);
287
- }
288
- if (Array.isArray(raw.envPassthrough)) {
289
- const list = raw.envPassthrough.filter((s) => typeof s === "string" && s.length > 0);
290
- if (list.length > 0)
291
- out.envPassthrough = list;
292
- }
293
- else if (raw.envPassthrough !== undefined) {
294
- warn(`[akm] Ignoring agent.profiles."${name}".envPassthrough: expected an array of strings.`);
295
- }
296
- if (typeof raw.timeoutMs === "number" &&
297
- Number.isFinite(raw.timeoutMs) &&
298
- Number.isInteger(raw.timeoutMs) &&
299
- raw.timeoutMs > 0) {
300
- out.timeoutMs = raw.timeoutMs;
301
- }
302
- else if (raw.timeoutMs !== undefined) {
303
- warn(`[akm] Ignoring agent.profiles."${name}".timeoutMs: expected a positive integer.`);
304
- }
305
- if (raw.parseOutput === "text" || raw.parseOutput === "json") {
306
- out.parseOutput = raw.parseOutput;
307
- }
308
- else if (raw.parseOutput !== undefined) {
309
- warn(`[akm] Ignoring agent.profiles."${name}".parseOutput: expected "text" or "json".`);
310
- }
311
- if (raw.sdkMode === true || raw.sdkMode === false) {
312
- out.sdkMode = raw.sdkMode;
313
- }
314
- else if (raw.sdkMode !== undefined) {
315
- warn(`[akm] Ignoring agent.profiles."${name}".sdkMode: expected a boolean.`);
316
- }
317
- if (typeof raw.model === "string" && raw.model.trim()) {
318
- out.model = raw.model.trim();
319
- }
320
- else if (raw.model !== undefined) {
321
- warn(`[akm] Ignoring agent.profiles."${name}".model: expected a non-empty string.`);
322
- }
323
- if (typeof raw.endpoint === "string" && raw.endpoint.trim()) {
324
- out.endpoint = raw.endpoint.trim();
325
- }
326
- else if (raw.endpoint !== undefined) {
327
- warn(`[akm] Ignoring agent.profiles."${name}".endpoint: expected a non-empty string.`);
328
- }
329
- if (typeof raw.apiKey === "string" && raw.apiKey.trim()) {
330
- out.apiKey = raw.apiKey.trim();
331
- }
332
- else if (raw.apiKey !== undefined) {
333
- warn(`[akm] Ignoring agent.profiles."${name}".apiKey: expected a non-empty string.`);
334
- }
335
- return out;
336
- }
337
12
  /**
338
- * Merge a user override (from `agent.profiles[<name>]`) on top of the
339
- * built-in profile (if any) and return the resolved profile. If `name`
340
- * matches no built-in and the user override has no `bin`, returns
341
- * `undefined` — the profile is unusable.
342
- *
343
- * Used at the spawn site, never at config-load time. Keeping merge logic
344
- * here means the parser stays a pure shape-checker.
13
+ * Resolve the effective `AgentProfile` for `name` by merging the optional
14
+ * user override (`profiles.agent[name]`) on top of the built-in profile (if
15
+ * any). Returns `undefined` when neither yields a usable profile.
345
16
  */
346
17
  export function resolveAgentProfile(name, overrides) {
347
18
  const builtin = getBuiltinAgentProfile(name);
348
- if (!builtin && !overrides?.bin && overrides?.sdkMode !== true)
19
+ const platform = overrides?.platform;
20
+ // For opencode-sdk profiles, allow synthesizing without a built-in.
21
+ const sdkMode = platform === "opencode-sdk";
22
+ if (!builtin && !overrides?.bin && !sdkMode)
349
23
  return undefined;
350
24
  const base = builtin ??
351
25
  {
@@ -355,110 +29,156 @@ export function resolveAgentProfile(name, overrides) {
355
29
  stdio: "captured",
356
30
  envPassthrough: [],
357
31
  parseOutput: "text",
32
+ ...(sdkMode ? { sdkMode: true } : {}),
358
33
  };
359
34
  if (!overrides)
360
35
  return base;
361
- const merged = {
36
+ return {
362
37
  name,
363
38
  bin: overrides.bin ?? base.bin,
364
39
  args: overrides.args ?? base.args,
365
- stdio: overrides.stdio ?? base.stdio,
366
- env: overrides.env ?? base.env,
367
- envPassthrough: overrides.envPassthrough
368
- ? mergePassthrough(base.envPassthrough, overrides.envPassthrough)
369
- : base.envPassthrough,
370
- timeoutMs: overrides.timeoutMs ?? base.timeoutMs,
371
- parseOutput: overrides.parseOutput ?? base.parseOutput,
372
- sdkMode: overrides.sdkMode ?? base.sdkMode,
40
+ stdio: base.stdio,
41
+ env: base.env,
42
+ envPassthrough: base.envPassthrough,
43
+ timeoutMs: base.timeoutMs,
44
+ parseOutput: base.parseOutput,
45
+ ...(sdkMode ? { sdkMode: true } : {}),
373
46
  model: overrides.model ?? base.model,
374
- endpoint: overrides.endpoint ?? base.endpoint,
375
- apiKey: overrides.apiKey ?? base.apiKey,
47
+ endpoint: base.endpoint,
48
+ apiKey: base.apiKey,
49
+ commandBuilder: base.commandBuilder,
50
+ modelAliases: base.modelAliases,
376
51
  };
377
- return merged;
378
- }
379
- function mergePassthrough(base, extra) {
380
- const seen = new Set();
381
- const out = [];
382
- for (const k of [...base, ...extra]) {
383
- if (!seen.has(k)) {
384
- seen.add(k);
385
- out.push(k);
386
- }
387
- }
388
- return out;
389
52
  }
390
53
  /**
391
54
  * Resolve the runnable profile for `name`, or `undefined` if none is
392
- * available (no built-in and no user override with a `bin`).
55
+ * available (no built-in and no user override).
393
56
  */
394
- export function resolveProfileFromConfig(name, agent) {
395
- return resolveAgentProfile(name, agent?.profiles?.[name]);
57
+ export function resolveProfileFromConfig(name, config) {
58
+ return resolveAgentProfile(name, config?.profiles?.agent?.[name]);
396
59
  }
397
60
  /**
398
- * Return the names of every profile available in `agent` config (built-in
399
- * names plus any user-defined ones). Sorted, deduplicated.
61
+ * Return the names of every agent profile available in `config` built-ins
62
+ * plus any user-defined entries under `profiles.agent`. Sorted, deduplicated.
400
63
  */
401
- export function listAgentProfileNames(agent) {
64
+ export function listAgentProfileNames(config) {
402
65
  const seen = new Set(BUILTIN_AGENT_PROFILE_NAMES);
403
- for (const name of Object.keys(agent?.profiles ?? {}))
66
+ for (const name of Object.keys(config?.profiles?.agent ?? {}))
404
67
  seen.add(name);
405
68
  return [...seen].sort();
406
69
  }
407
70
  /**
408
- * Resolve the default profile name. Order: explicit `name` arg → config
409
- * `agent.default` → undefined.
71
+ * Resolve the default agent profile name. Order: explicit `requested` arg →
72
+ * `config.defaults.agent` → undefined.
410
73
  */
411
- export function resolveDefaultProfileName(agent, requested) {
74
+ export function resolveDefaultProfileName(config, requested) {
412
75
  if (requested?.trim())
413
76
  return requested.trim();
414
- if (agent?.default?.trim())
415
- return agent.default.trim();
77
+ const def = config?.defaults?.agent;
78
+ if (typeof def === "string" && def.trim())
79
+ return def.trim();
416
80
  return undefined;
417
81
  }
418
82
  /**
419
- * Throw a {@link ConfigError} with a stable hint when the caller needs
420
- * `agent` config but it is missing or unresolvable.
421
- *
422
- * Covers two cases per acceptance criteria:
423
- *
424
- * 1. The `agent` block is absent — agent commands are disabled.
425
- * 2. The block exists but no usable profile (no `default`, no requested
426
- * name, or the named profile cannot be resolved).
427
- *
428
- * Use as `const profile = requireAgentProfile(config.agent, requestedName)`.
83
+ * Throw a stable `ConfigError` when the caller needs an agent profile but
84
+ * none can be resolved.
429
85
  */
430
- export function requireAgentProfile(agent, requested) {
431
- if (!agent) {
432
- throw new ConfigError("agent commands are disabled: no `agent` block in config.json.", "INVALID_CONFIG_FILE", 'Run `akm setup` to detect and configure an agent CLI, or add an `agent` block manually (see docs/configuration.md "agent.*").');
86
+ export function requireAgentProfile(config, requested) {
87
+ if (!config) {
88
+ throw new ConfigError("agent commands are disabled: no agent configuration in config.json.", "INVALID_CONFIG_FILE", "Run `akm setup` to detect and configure an agent CLI, or add an entry under `profiles.agent` and set `defaults.agent`.");
433
89
  }
434
- const name = resolveDefaultProfileName(agent, requested);
90
+ const name = resolveDefaultProfileName(config, requested);
435
91
  if (!name) {
436
- throw new ConfigError("agent commands require a profile: pass --profile or set `agent.default` in config.json.", "INVALID_CONFIG_FILE", `Available profiles: ${listAgentProfileNames(agent).join(", ")}.`);
92
+ throw new ConfigError("agent commands require a profile: pass --profile or set `defaults.agent` in config.json.", "INVALID_CONFIG_FILE", `Available profiles: ${listAgentProfileNames(config).join(", ")}.`);
437
93
  }
438
- const profile = resolveProfileFromConfig(name, agent);
94
+ const profile = resolveProfileFromConfig(name, config);
439
95
  if (!profile) {
440
- throw new ConfigError(`agent profile "${name}" is not built-in and has no \`bin\` override.`, "INVALID_CONFIG_FILE", `Define agent.profiles."${name}".bin in config.json, or pick one of: ${listAgentProfileNames(agent).join(", ")}.`);
441
- }
442
- // Apply the top-level agent.timeoutMs as the effective default for this
443
- // profile when the profile itself has no timeout override. This makes
444
- // `agent.timeoutMs` the universal fallback without requiring every
445
- // profile definition in config.json to repeat it.
446
- if (profile.timeoutMs === undefined && agent?.timeoutMs !== undefined) {
447
- return { ...profile, timeoutMs: agent.timeoutMs };
96
+ throw new ConfigError(`agent profile "${name}" is not built-in and has no \`bin\` override.`, "INVALID_CONFIG_FILE", `Define profiles.agent."${name}".bin in config.json, or pick one of: ${listAgentProfileNames(config).join(", ")}.`);
448
97
  }
449
98
  return profile;
450
99
  }
100
+ /**
101
+ * Resolve the agent profile bound to a named improve process. Reads from
102
+ * `profiles.improve.default.processes.<processName>` for the profile binding,
103
+ * then falls back to `defaults.agent`.
104
+ */
105
+ export function resolveProcessAgentProfile(processName, config) {
106
+ const processEntry = config?.profiles?.improve?.default?.processes;
107
+ const entry = processEntry?.[processName];
108
+ const profileName = entry?.profile;
109
+ const profile = requireAgentProfile(config, profileName);
110
+ let resolvedTimeoutMs;
111
+ if (entry?.timeoutMs === null) {
112
+ resolvedTimeoutMs = null;
113
+ }
114
+ else if (typeof entry?.timeoutMs === "number") {
115
+ resolvedTimeoutMs = entry.timeoutMs;
116
+ }
117
+ else if (profile.timeoutMs !== undefined) {
118
+ resolvedTimeoutMs = profile.timeoutMs;
119
+ }
120
+ return { profile, timeoutMs: resolvedTimeoutMs };
121
+ }
451
122
  /**
452
123
  * Convenience: list every fully-resolved profile (built-ins merged with
453
- * any user overrides). Used by setup detection to enumerate candidates.
124
+ * user overrides). Used by setup detection to enumerate candidates.
454
125
  */
455
- export function listResolvedAgentProfiles(agent) {
126
+ export function listResolvedAgentProfiles(config) {
456
127
  const resolved = [];
457
128
  const builtins = listBuiltinAgentProfiles();
458
- for (const name of listAgentProfileNames(agent)) {
459
- const profile = resolveProfileFromConfig(name, agent) ?? builtins[name];
129
+ for (const name of listAgentProfileNames(config)) {
130
+ const profile = resolveProfileFromConfig(name, config) ?? builtins[name];
460
131
  if (profile)
461
132
  resolved.push(profile);
462
133
  }
463
134
  return resolved;
464
135
  }
136
+ /**
137
+ * Parse the v2 `profiles.agent` map (AgentProfileConfigV2 shape with required
138
+ * `platform` field). Returns a map of profile name → AgentProfileConfigV2.
139
+ */
140
+ export function parseAgentProfilesMapV2(value) {
141
+ if (typeof value !== "object" || value === null || Array.isArray(value))
142
+ return undefined;
143
+ const out = {};
144
+ const VALID_PLATFORMS = ["opencode", "claude", "opencode-sdk"];
145
+ for (const [name, raw] of Object.entries(value)) {
146
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
147
+ warn(`[akm] Ignoring profiles.agent["${name}"]: expected an object.`);
148
+ continue;
149
+ }
150
+ const obj = raw;
151
+ if (!VALID_PLATFORMS.includes(obj.platform)) {
152
+ warn(`[akm] Ignoring profiles.agent["${name}"]: missing or invalid "platform" (must be one of: ${VALID_PLATFORMS.join(", ")}).`);
153
+ continue;
154
+ }
155
+ const profile = {
156
+ platform: obj.platform,
157
+ };
158
+ if (typeof obj.bin === "string" && obj.bin.trim())
159
+ profile.bin = obj.bin.trim();
160
+ if (Array.isArray(obj.args) && obj.args.every((a) => typeof a === "string")) {
161
+ profile.args = obj.args;
162
+ }
163
+ if (typeof obj.workspace === "string" && obj.workspace.trim())
164
+ profile.workspace = obj.workspace.trim();
165
+ if (typeof obj.model === "string" && obj.model.trim())
166
+ profile.model = obj.model.trim();
167
+ out[name] = profile;
168
+ }
169
+ return Object.keys(out).length > 0 ? out : undefined;
170
+ }
171
+ /**
172
+ * Stub kept for source-compat with callers that previously used the v1 agent
173
+ * config parser. After 0.8.0 there is no separate `agent` block to parse — the
174
+ * loaded `AkmConfig` already carries the agent data on `profiles.agent` and
175
+ * `defaults.agent`. This function is a no-op alias for those callers.
176
+ *
177
+ * @deprecated v0.8.0 — the unified `AkmConfig` IS the agent config. Use the
178
+ * profile/defaults accessors above instead.
179
+ */
180
+ export function parseAgentConfig(_value) {
181
+ // No-op: there is no separate agent block in 0.8.0. Callers should pass
182
+ // their loaded `AkmConfig` directly to `requireAgentProfile` etc.
183
+ return undefined;
184
+ }
@@ -1,3 +1,6 @@
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/.
1
4
  /**
2
5
  * Setup-time agent CLI detection (v1 spec §12.3).
3
6
  *
@@ -1,19 +1,11 @@
1
- /**
2
- * Internal entry point for the `agent` integration. CLI-only project no
3
- * public exports map. Other akm modules import from this barrel for the
4
- * sake of grouping imports.
5
- *
6
- * Surface:
7
- * • Types: AgentProfile, AgentConfig, AgentRunResult, AgentFailureReason.
8
- * • Profiles: getBuiltinAgentProfile, listBuiltinAgentProfiles, BUILTIN_AGENT_PROFILE_NAMES.
9
- * • Config: parseAgentConfig, resolveProfileFromConfig, requireAgentProfile, listResolvedAgentProfiles, listAgentProfileNames.
10
- * • Spawn: runAgent.
11
- * • Detection: detectAgentCliProfiles, pickDefaultAgentProfile, defaultWhich.
12
- */
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
+ export { getCommandBuilder } from "./builders";
13
5
  export { DEFAULT_AGENT_TIMEOUT_MS, listAgentProfileNames, listResolvedAgentProfiles, parseAgentConfig, requireAgentProfile, resolveAgentProfile, resolveDefaultProfileName, resolveProfileFromConfig, } from "./config";
14
6
  export { defaultWhich, detectAgentCliProfiles, pickDefaultAgentProfile } from "./detect";
7
+ export { listBuiltinModelAliases, resolveModel } from "./model-aliases";
15
8
  export { BUILTIN_AGENT_PROFILE_NAMES, getBuiltinAgentProfile, listBuiltinAgentProfiles, } from "./profiles";
16
- export { buildProposePrompt, buildReflectPrompt, buildSchemaRepairPrompt, parseAgentProposalPayload, stripJsonFences, } from "./prompts";
17
- export { runWithAgentRunner, selectAgentRunner } from "./runners";
9
+ export { buildProposePrompt, buildReflectPrompt, buildSchemaRepairPrompt, extractDraftConfidence, parseAgentProposalPayload, stripJsonFences, } from "./prompts";
18
10
  export { runAgentSdk } from "./sdk-runner";
19
11
  export { runAgent } from "./spawn";
@@ -0,0 +1,55 @@
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
+ * Built-in alias table. Alias keys are lowercase.
6
+ *
7
+ * Platform model string conventions:
8
+ * opencode — "<provider>/<model>" e.g. "opencode/claude-opus-4-7"
9
+ * claude — bare model name e.g. "claude-opus-4-7"
10
+ * (Claude Code also accepts its own built-in shorthands, but we
11
+ * always resolve to the full name for determinism)
12
+ */
13
+ const BUILTIN_ALIASES = [
14
+ {
15
+ alias: "opus",
16
+ platforms: {
17
+ claude: "claude-opus-4-7",
18
+ opencode: "opencode/claude-opus-4-7",
19
+ },
20
+ },
21
+ {
22
+ alias: "sonnet",
23
+ platforms: {
24
+ claude: "claude-sonnet-4-6",
25
+ opencode: "opencode/claude-sonnet-4-6",
26
+ },
27
+ },
28
+ {
29
+ alias: "haiku",
30
+ platforms: {
31
+ claude: "claude-haiku-4-5-20251001",
32
+ opencode: "opencode/claude-haiku-4-5",
33
+ },
34
+ },
35
+ ];
36
+ /**
37
+ * Resolve a model alias or exact model ID to the string the target platform
38
+ * CLI expects for its --model flag.
39
+ *
40
+ * @param model Raw alias ("opus") or exact model ID ("claude-opus-4-7").
41
+ * @param platform Builder platform name ("claude", "opencode", ...).
42
+ * @param custom Profile-level aliases from config.json — take priority over builtins.
43
+ * @returns Resolved model string, or `model` verbatim when no alias matches.
44
+ */
45
+ export function resolveModel(model, platform, custom) {
46
+ const key = model.toLowerCase();
47
+ if (custom?.[key])
48
+ return custom[key];
49
+ const entry = BUILTIN_ALIASES.find((a) => a.alias === key);
50
+ return entry?.platforms[platform] ?? model;
51
+ }
52
+ /** Return all built-in alias entries (for tests and documentation). */
53
+ export function listBuiltinModelAliases() {
54
+ return BUILTIN_ALIASES;
55
+ }