akm-cli 0.9.0-rc.0 → 0.9.0-rc.2
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.
- package/CHANGELOG.md +339 -2
- package/SECURITY.md +23 -24
- package/dist/assets/help/help-improve.md +10 -10
- package/dist/assets/hints/cli-hints-full.md +44 -10
- package/dist/assets/hints/cli-hints-short.md +6 -2
- package/dist/assets/{profiles → improve-strategies}/default.json +1 -0
- package/dist/assets/{profiles → improve-strategies}/graph-refresh.json +1 -1
- package/dist/assets/{profiles → improve-strategies}/proactive-maintenance.json +2 -3
- package/dist/assets/{profiles → improve-strategies}/reflect-distill.json +3 -4
- package/dist/assets/prompts/workflow-unit-preamble.md +26 -0
- package/dist/assets/stash-skeleton/README.md +28 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +6 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +6 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +12 -1
- package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +11 -1
- package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +6 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +9 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +7 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +7 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +6 -0
- package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +98 -0
- package/dist/assets/stash-skeleton/facts/conventions/domains.md +63 -0
- package/dist/assets/stash-skeleton/facts/conventions/organization.md +127 -0
- package/dist/assets/tasks/core/backup.yml +1 -0
- package/dist/assets/tasks/core/extract.yml +1 -0
- package/dist/assets/tasks/core/improve.yml +1 -0
- package/dist/assets/tasks/core/index-refresh.yml +1 -0
- package/dist/assets/tasks/core/sync.yml +1 -0
- package/dist/assets/tasks/core/version-check.yml +1 -0
- package/dist/assets/tasks/graph-refresh-weekly.yml +4 -4
- package/dist/assets/templates/html/health.html +5 -1
- package/dist/cli/config-migrate.js +31 -138
- package/dist/cli/config-validate.js +10 -8
- package/dist/cli.js +48 -14
- package/dist/commands/agent/agent-dispatch.js +17 -16
- package/dist/commands/agent/agent-support.js +0 -24
- package/dist/commands/agent/contribute-cli.js +5 -15
- package/dist/commands/backup-cli.js +54 -0
- package/dist/commands/config-cli.js +45 -159
- package/dist/commands/env/env-binding.js +95 -0
- package/dist/commands/env/env-cli.js +8 -65
- package/dist/commands/env/secret.js +8 -5
- package/dist/commands/health/checks.js +130 -83
- package/dist/commands/health/html-report.js +4 -0
- package/dist/commands/health/improve-metrics.js +30 -32
- package/dist/commands/health/llm-usage.js +19 -19
- package/dist/commands/health/md-report.js +4 -0
- package/dist/commands/health/metrics.js +2 -1
- package/dist/commands/health/surfaces.js +5 -4
- package/dist/commands/health.js +1 -1
- package/dist/commands/improve/consolidate/chunking.js +2 -2
- package/dist/commands/improve/consolidate.js +28 -25
- package/dist/commands/improve/distill/promote-memory.js +5 -12
- package/dist/commands/improve/distill/quality-gate.js +5 -7
- package/dist/commands/improve/distill.js +16 -5
- package/dist/commands/improve/eligibility.js +22 -12
- package/dist/commands/improve/extract-cli.js +47 -19
- package/dist/commands/improve/extract.js +110 -62
- package/dist/commands/improve/improve-cli.js +38 -16
- package/dist/commands/improve/improve-result-file.js +30 -24
- package/dist/commands/improve/improve-strategies.js +137 -0
- package/dist/commands/improve/improve.js +60 -30
- package/dist/commands/improve/locks.js +66 -45
- package/dist/commands/improve/loop-stages.js +75 -33
- package/dist/commands/improve/memory/memory-belief.js +79 -7
- package/dist/commands/improve/memory/memory-contradiction-detect.js +12 -4
- package/dist/commands/improve/preparation.js +71 -73
- package/dist/commands/improve/procedural.js +3 -2
- package/dist/commands/improve/recombine.js +2 -1
- package/dist/commands/improve/reflect.js +119 -214
- package/dist/commands/improve/shared.js +11 -5
- package/dist/commands/lint/base-linter.js +152 -42
- package/dist/commands/mv-cli.js +809 -0
- package/dist/commands/proposal/proposal-cli.js +18 -8
- package/dist/commands/proposal/propose.js +64 -69
- package/dist/commands/read/knowledge.js +436 -4
- package/dist/commands/read/remember-cli.js +39 -2
- package/dist/commands/read/search-cli.js +6 -1
- package/dist/commands/registry-cli.js +29 -14
- package/dist/commands/remember.js +2 -0
- package/dist/commands/sources/init.js +13 -14
- package/dist/commands/sources/migration-help.js +7 -4
- package/dist/commands/sources/schema-repair.js +2 -4
- package/dist/commands/sources/source-add.js +62 -73
- package/dist/commands/sources/source-manage.js +50 -46
- package/dist/commands/sources/stash-cli.js +41 -4
- package/dist/commands/tasks/default-tasks.js +12 -12
- package/dist/commands/tasks/tasks-cli.js +7 -3
- package/dist/commands/tasks/tasks.js +113 -18
- package/dist/commands/wiki-cli.js +9 -10
- package/dist/commands/workflow-cli.js +276 -12
- package/dist/core/asset/asset-spec.js +58 -1
- package/dist/core/asset/frontmatter.js +12 -2
- package/dist/core/common.js +5 -3
- package/dist/core/config/config-io.js +28 -17
- package/dist/core/config/config-schema.js +379 -66
- package/dist/core/config/config-types.js +3 -3
- package/dist/core/config/config-version.js +29 -0
- package/dist/core/config/config-walker.js +98 -27
- package/dist/core/config/config.js +132 -266
- package/dist/core/config/deep-merge.js +41 -0
- package/dist/core/config/engine-semantics.js +32 -0
- package/dist/core/errors.js +2 -2
- package/dist/core/extra-params.js +61 -0
- package/dist/core/file-lock.js +201 -56
- package/dist/core/improve-result.js +178 -0
- package/dist/core/json-schema.js +142 -0
- package/dist/core/maintenance-barrier.js +119 -0
- package/dist/core/migration-backup.js +416 -0
- package/dist/core/paths.js +3 -0
- package/dist/core/redaction.js +358 -0
- package/dist/core/state/migrations.js +17 -2
- package/dist/core/state-db.js +44 -1
- package/dist/indexer/db/db.js +118 -2
- package/dist/indexer/graph/graph-extraction.js +28 -16
- package/dist/indexer/index-writer-lock.js +31 -24
- package/dist/indexer/index-written-assets.js +15 -6
- package/dist/indexer/indexer.js +47 -2
- package/dist/indexer/passes/memory-inference.js +10 -6
- package/dist/indexer/passes/metadata.js +250 -0
- package/dist/indexer/search/db-search.js +111 -44
- package/dist/indexer/search/fts-query.js +41 -0
- package/dist/indexer/search/ranking-contributors.js +48 -0
- package/dist/indexer/search/ranking.js +36 -23
- package/dist/indexer/search/search-fields.js +11 -1
- package/dist/indexer/walk/matchers.js +39 -0
- package/dist/integrations/agent/builder-shared.js +7 -0
- package/dist/integrations/agent/builders.js +5 -50
- package/dist/integrations/agent/config.js +3 -143
- package/dist/integrations/agent/detect.js +17 -2
- package/dist/integrations/agent/engine-resolution.js +202 -0
- package/dist/integrations/agent/index.js +1 -2
- package/dist/integrations/agent/model-aliases.js +16 -2
- package/dist/integrations/agent/profiles.js +36 -62
- package/dist/integrations/agent/runner-dispatch.js +91 -4
- package/dist/integrations/agent/runner.js +76 -207
- package/dist/integrations/agent/spawn.js +141 -20
- package/dist/integrations/harnesses/aider/agent-builder.js +112 -0
- package/dist/integrations/harnesses/aider/index.js +57 -0
- package/dist/integrations/harnesses/aider/result-extractor.js +53 -0
- package/dist/integrations/harnesses/amazonq/agent-builder.js +152 -0
- package/dist/integrations/harnesses/amazonq/index.js +58 -0
- package/dist/integrations/harnesses/amazonq/result-extractor.js +48 -0
- package/dist/integrations/harnesses/claude/agent-builder.js +46 -8
- package/dist/integrations/harnesses/claude/index.js +25 -25
- package/dist/integrations/harnesses/claude/result-extractor.js +52 -0
- package/dist/integrations/harnesses/codex/agent-builder.js +136 -0
- package/dist/integrations/harnesses/codex/index.js +62 -0
- package/dist/integrations/harnesses/codex/result-extractor.js +73 -0
- package/dist/integrations/harnesses/copilot/agent-builder.js +121 -0
- package/dist/integrations/harnesses/copilot/index.js +59 -0
- package/dist/integrations/harnesses/copilot/result-extractor.js +151 -0
- package/dist/integrations/harnesses/gemini/agent-builder.js +120 -0
- package/dist/integrations/harnesses/gemini/index.js +59 -0
- package/dist/integrations/harnesses/gemini/result-extractor.js +121 -0
- package/dist/integrations/harnesses/index.js +27 -28
- package/dist/integrations/harnesses/opencode/agent-builder.js +2 -3
- package/dist/integrations/harnesses/opencode/index.js +15 -22
- package/dist/integrations/harnesses/opencode-sdk/harness.js +60 -0
- package/dist/integrations/harnesses/opencode-sdk/index.js +8 -32
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +681 -108
- package/dist/integrations/harnesses/openhands/agent-builder.js +125 -0
- package/dist/integrations/harnesses/openhands/index.js +57 -0
- package/dist/integrations/harnesses/openhands/result-extractor.js +103 -0
- package/dist/integrations/harnesses/pi/agent-builder.js +103 -0
- package/dist/integrations/harnesses/pi/index.js +57 -0
- package/dist/integrations/harnesses/pi/result-extractor.js +135 -0
- package/dist/integrations/harnesses/types.js +8 -32
- package/dist/integrations/lockfile.js +32 -21
- package/dist/integrations/session-logs/index.js +24 -11
- package/dist/llm/client.js +48 -14
- package/dist/llm/feature-gate.js +15 -47
- package/dist/llm/graph-extract.js +1 -1
- package/dist/llm/index-passes.js +8 -42
- package/dist/llm/memory-infer-impl.js +1 -1
- package/dist/llm/usage-persist.js +4 -0
- package/dist/llm/usage-telemetry.js +35 -5
- package/dist/output/renderers.js +3 -2
- package/dist/output/shapes/helpers.js +2 -1
- package/dist/output/shapes/passthrough.js +6 -0
- package/dist/output/text/helpers.js +215 -2
- package/dist/output/text/workflow.js +3 -1
- package/dist/schemas/akm-config.json +16638 -0
- package/dist/schemas/akm-task.json +87 -0
- package/dist/schemas/akm-workflow.json +372 -0
- package/dist/scripts/migrate-storage.js +10944 -8801
- package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +9247 -350
- package/dist/setup/detected-engines.js +142 -0
- package/dist/setup/engine-config.js +89 -0
- package/dist/setup/setup.js +236 -132
- package/dist/setup/steps/connection.js +61 -32
- package/dist/setup/steps/platforms.js +4 -4
- package/dist/setup/steps.js +3 -2
- package/dist/storage/database.js +13 -1
- package/dist/storage/engines/sqlite-migrations.js +1 -0
- package/dist/storage/repositories/improve-runs-repository.js +5 -5
- package/dist/storage/repositories/task-history-repository.js +78 -0
- package/dist/storage/repositories/workflow-runs-repository.js +190 -1
- package/dist/tasks/parser.js +138 -52
- package/dist/tasks/runner.js +71 -75
- package/dist/tasks/schema.js +1 -1
- package/dist/tasks/validator.js +11 -6
- package/dist/text-import-hook.mjs +1 -1
- package/dist/wiki/wiki.js +9 -8
- package/dist/workflows/authoring/authoring.js +123 -10
- package/dist/workflows/authoring/workflow-program-template.yaml +31 -0
- package/dist/workflows/cli.js +4 -0
- package/dist/workflows/concurrency-policy.js +15 -0
- package/dist/workflows/db.js +200 -13
- package/dist/workflows/exec/brief.js +478 -0
- package/dist/workflows/exec/frozen-judge.js +47 -0
- package/dist/workflows/exec/native-executor.js +1034 -0
- package/dist/workflows/exec/param-secrets.js +115 -0
- package/dist/workflows/exec/report.js +1355 -0
- package/dist/workflows/exec/run-workflow.js +609 -0
- package/dist/workflows/exec/scheduler.js +71 -0
- package/dist/workflows/exec/step-work.js +1212 -0
- package/dist/workflows/exec/unit-writer.js +23 -0
- package/dist/workflows/exec/watch.js +116 -0
- package/dist/workflows/exec/worktree.js +171 -0
- package/dist/workflows/ir/compile.js +375 -0
- package/dist/workflows/ir/freeze.js +243 -0
- package/dist/workflows/ir/params.js +54 -0
- package/dist/workflows/ir/plan-hash.js +68 -0
- package/dist/workflows/ir/schema.js +545 -0
- package/dist/workflows/parser.js +10 -1
- package/dist/workflows/program/expressions.js +369 -0
- package/dist/workflows/program/parser.js +869 -0
- package/dist/workflows/program/project.js +104 -0
- package/dist/workflows/program/schema.js +54 -0
- package/dist/workflows/renderer.js +82 -5
- package/dist/workflows/resource-limits.js +20 -0
- package/dist/workflows/runtime/agent-identity.js +59 -14
- package/dist/workflows/runtime/plan-classifier.js +187 -0
- package/dist/workflows/runtime/runs.js +246 -69
- package/dist/workflows/runtime/unit-checkin.js +45 -0
- package/dist/workflows/runtime/workflow-asset-loader.js +42 -1
- package/dist/workflows/validate-summary.js +24 -3
- package/dist/workflows/validator.js +26 -1
- package/docs/data-and-telemetry.md +4 -3
- package/docs/migration/release-notes/0.6.0.md +1 -1
- package/docs/migration/release-notes/0.7.0.md +5 -4
- package/docs/migration/release-notes/0.9.0-beta.60.md +19 -0
- package/docs/migration/v0.8-to-v0.9.md +401 -0
- package/package.json +4 -2
- package/schemas/akm-config.json +16638 -0
- package/schemas/akm-task.json +87 -0
- package/schemas/akm-workflow.json +372 -0
- package/dist/commands/improve/improve-profiles.js +0 -168
- package/dist/core/config/config-migration.js +0 -602
- package/dist/core/deep-merge.js +0 -38
- package/dist/llm/call-ai.js +0 -62
- package/dist/setup/legacy-config.js +0 -106
- package/docs/README.md +0 -104
- /package/dist/assets/{profiles → improve-strategies}/catchup.json +0 -0
- /package/dist/assets/{profiles → improve-strategies}/consolidate.json +0 -0
- /package/dist/assets/{profiles → improve-strategies}/frequent.json +0 -0
- /package/dist/assets/{profiles → improve-strategies}/memory-focus.json +0 -0
- /package/dist/assets/{profiles → improve-strategies}/quick.json +0 -0
- /package/dist/assets/{profiles → improve-strategies}/recombine-only.json +0 -0
- /package/dist/assets/{profiles → improve-strategies}/synthesize.json +0 -0
- /package/dist/assets/{profiles → improve-strategies}/thorough.json +0 -0
|
@@ -2,9 +2,8 @@
|
|
|
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
|
export { getCommandBuilder } from "./builders.js";
|
|
5
|
-
export { DEFAULT_AGENT_TIMEOUT_MS
|
|
5
|
+
export { DEFAULT_AGENT_TIMEOUT_MS } from "./config.js";
|
|
6
6
|
export { _setAgentDetectForTests, defaultWhich, detectAgentCliProfiles, pickDefaultAgentProfile } from "./detect.js";
|
|
7
7
|
export { listBuiltinModelAliases, resolveModel } from "./model-aliases.js";
|
|
8
8
|
export { BUILTIN_AGENT_PROFILE_NAMES, getBuiltinAgentProfile, listBuiltinAgentProfiles, } from "./profiles.js";
|
|
9
9
|
export { buildProposePrompt, buildReflectPrompt, buildSchemaRepairPrompt, extractDraftConfidence, parseAgentProposalPayload, } from "./prompts.js";
|
|
10
|
-
export { runAgent } from "./spawn.js";
|
|
@@ -11,6 +11,15 @@
|
|
|
11
11
|
* always resolve to the full name for determinism)
|
|
12
12
|
*/
|
|
13
13
|
const BUILTIN_ALIASES = [
|
|
14
|
+
{
|
|
15
|
+
// Anthropic's Mythos-class tier above Opus — the recommended resolution
|
|
16
|
+
// target for the `deep` workflow tier (see docs/features/workflows.md).
|
|
17
|
+
alias: "fable",
|
|
18
|
+
platforms: {
|
|
19
|
+
claude: "claude-fable-5",
|
|
20
|
+
opencode: "opencode/claude-fable-5",
|
|
21
|
+
},
|
|
22
|
+
},
|
|
14
23
|
{
|
|
15
24
|
alias: "opus",
|
|
16
25
|
platforms: {
|
|
@@ -41,19 +50,24 @@ const BUILTIN_ALIASES = [
|
|
|
41
50
|
* @param platform Builder platform name ("claude", "opencode", ...).
|
|
42
51
|
* @param custom Profile-level aliases from config.json — take priority over globals and builtins.
|
|
43
52
|
* @param global Config-root `modelAliases` tier table (alias → platform → model, `"*"` fallback).
|
|
53
|
+
* @param fallbackPlatforms Additional global tier columns checked after `platform` and before `"*"`.
|
|
44
54
|
* @returns Resolved model string, or `model` verbatim when no alias matches.
|
|
45
55
|
*/
|
|
46
|
-
export function resolveModel(model, platform, custom, global) {
|
|
56
|
+
export function resolveModel(model, platform, custom, global, fallbackPlatforms = []) {
|
|
47
57
|
const key = model.toLowerCase();
|
|
48
58
|
if (custom?.[key])
|
|
49
59
|
return custom[key];
|
|
50
60
|
const tier = global?.[key];
|
|
51
|
-
const fromGlobal = tier?.[platform] ?? tier?.["*"];
|
|
61
|
+
const fromGlobal = tier?.[platform] ?? fallbackPlatforms.map((fallback) => tier?.[fallback]).find(Boolean) ?? tier?.["*"];
|
|
52
62
|
if (fromGlobal)
|
|
53
63
|
return fromGlobal;
|
|
54
64
|
const entry = BUILTIN_ALIASES.find((a) => a.alias === key);
|
|
55
65
|
return entry?.platforms[platform] ?? model;
|
|
56
66
|
}
|
|
67
|
+
/** Resolve a direct/fallback LLM model through engine-specific, `llm`, then `*` tiers. */
|
|
68
|
+
export function resolveLlmModel(model, engine, global) {
|
|
69
|
+
return resolveModel(model, engine, undefined, global, ["llm"]);
|
|
70
|
+
}
|
|
57
71
|
/** Return all built-in alias entries (for tests and documentation). */
|
|
58
72
|
export function listBuiltinModelAliases() {
|
|
59
73
|
return BUILTIN_ALIASES;
|
|
@@ -9,11 +9,12 @@
|
|
|
9
9
|
// every lane's read-back (GRR). It is a provenance tag, never a secret.
|
|
10
10
|
const COMMON_PASSTHROUGH = ["HOME", "PATH", "USER", "LANG", "LC_ALL", "TERM", "TMPDIR", "AKM_EVENT_SOURCE"];
|
|
11
11
|
/**
|
|
12
|
-
* Built-in profiles for the
|
|
13
|
-
*
|
|
14
|
-
*
|
|
12
|
+
* Built-in profiles for the agent CLIs akm knows out of the box: the five the
|
|
13
|
+
* v1 spec calls out explicitly, plus the P2 harness adapters (copilot, pi,
|
|
14
|
+
* amazonq, openhands — plan §"Capability matrix"). The fields here are
|
|
15
|
+
* conservative defaults — every value is overridable from user config.
|
|
15
16
|
*
|
|
16
|
-
*
|
|
17
|
+
* Engine lowering selects captured stdio for unattended dispatch.
|
|
17
18
|
*/
|
|
18
19
|
const BUILTINS = {
|
|
19
20
|
opencode: {
|
|
@@ -56,76 +57,49 @@ const BUILTINS = {
|
|
|
56
57
|
envPassthrough: [...COMMON_PASSTHROUGH, "OPENAI_API_KEY", "ANTHROPIC_API_KEY"],
|
|
57
58
|
parseOutput: "text",
|
|
58
59
|
},
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
* These profiles use `stdio: "captured"` and `parseOutput: "json"` so the
|
|
64
|
-
* agent's response can be read from stdout. They share the same `bin` and
|
|
65
|
-
* `envPassthrough` as the corresponding base profile but are intentionally
|
|
66
|
-
* kept out of `BUILTIN_AGENT_PROFILE_NAMES` (and therefore out of CLI
|
|
67
|
-
* detection/enumeration) to avoid showing up as separate installable profiles.
|
|
68
|
-
*
|
|
69
|
-
* Users may reference them by name via `--profile opencode-headless` or by
|
|
70
|
-
* setting `agent.default: "opencode-headless"` in config.json.
|
|
71
|
-
*/
|
|
72
|
-
const HEADLESS_BUILTINS = {
|
|
73
|
-
"opencode-headless": {
|
|
74
|
-
name: "opencode-headless",
|
|
75
|
-
bin: "opencode",
|
|
76
|
-
args: ["run"],
|
|
77
|
-
stdio: "captured",
|
|
78
|
-
envPassthrough: [...COMMON_PASSTHROUGH, "OPENCODE_API_KEY", "OPENCODE_CONFIG"],
|
|
79
|
-
parseOutput: "json",
|
|
80
|
-
},
|
|
81
|
-
"claude-headless": {
|
|
82
|
-
name: "claude-headless",
|
|
83
|
-
bin: "claude",
|
|
60
|
+
// ── P2 harness-adapter profiles (plan §"Capability matrix") ────────────────
|
|
61
|
+
copilot: {
|
|
62
|
+
name: "copilot",
|
|
63
|
+
bin: "copilot",
|
|
84
64
|
args: [],
|
|
85
|
-
stdio: "
|
|
86
|
-
envPassthrough: [...COMMON_PASSTHROUGH, "
|
|
87
|
-
parseOutput: "
|
|
65
|
+
stdio: "interactive",
|
|
66
|
+
envPassthrough: [...COMMON_PASSTHROUGH, "GH_TOKEN", "GITHUB_TOKEN"],
|
|
67
|
+
parseOutput: "text",
|
|
88
68
|
},
|
|
89
|
-
|
|
90
|
-
name: "
|
|
91
|
-
bin: "
|
|
69
|
+
pi: {
|
|
70
|
+
name: "pi",
|
|
71
|
+
bin: "pi",
|
|
92
72
|
args: [],
|
|
93
|
-
stdio: "
|
|
94
|
-
envPassthrough: [...COMMON_PASSTHROUGH, "
|
|
95
|
-
parseOutput: "
|
|
73
|
+
stdio: "interactive",
|
|
74
|
+
envPassthrough: [...COMMON_PASSTHROUGH, "PI_API_KEY", "ANTHROPIC_API_KEY", "OPENAI_API_KEY"],
|
|
75
|
+
parseOutput: "text",
|
|
96
76
|
},
|
|
97
|
-
|
|
98
|
-
name: "
|
|
99
|
-
bin: "
|
|
77
|
+
amazonq: {
|
|
78
|
+
name: "amazonq",
|
|
79
|
+
bin: "q",
|
|
100
80
|
args: [],
|
|
101
|
-
stdio: "
|
|
102
|
-
envPassthrough: [...COMMON_PASSTHROUGH, "
|
|
103
|
-
parseOutput: "
|
|
81
|
+
stdio: "interactive",
|
|
82
|
+
envPassthrough: [...COMMON_PASSTHROUGH, "AWS_PROFILE", "AWS_REGION"],
|
|
83
|
+
parseOutput: "text",
|
|
104
84
|
},
|
|
105
|
-
|
|
106
|
-
name: "
|
|
107
|
-
bin: "
|
|
108
|
-
args: [
|
|
109
|
-
stdio: "
|
|
110
|
-
envPassthrough: [...COMMON_PASSTHROUGH, "
|
|
111
|
-
parseOutput: "
|
|
85
|
+
openhands: {
|
|
86
|
+
name: "openhands",
|
|
87
|
+
bin: "openhands",
|
|
88
|
+
args: [],
|
|
89
|
+
stdio: "interactive",
|
|
90
|
+
envPassthrough: [...COMMON_PASSTHROUGH, "LLM_MODEL", "LLM_API_KEY", "LLM_BASE_URL"],
|
|
91
|
+
parseOutput: "text",
|
|
112
92
|
},
|
|
113
93
|
};
|
|
114
|
-
/**
|
|
115
|
-
* Names of the five primary built-in profiles. Stable, sorted. Does NOT
|
|
116
|
-
* include the `-headless` variants (those are resolvable by name but are
|
|
117
|
-
* excluded from detection/enumeration flows).
|
|
118
|
-
*/
|
|
94
|
+
/** Names of the canonical built-in harness descriptors. Stable, sorted. */
|
|
119
95
|
export const BUILTIN_AGENT_PROFILE_NAMES = Object.freeze(Object.keys(BUILTINS).sort());
|
|
120
|
-
/** Returns the built-in
|
|
96
|
+
/** Returns the built-in descriptor for a canonical harness id. */
|
|
121
97
|
export function getBuiltinAgentProfile(name) {
|
|
122
|
-
return BUILTINS[name]
|
|
98
|
+
return BUILTINS[name];
|
|
123
99
|
}
|
|
124
100
|
/**
|
|
125
|
-
* Return a
|
|
126
|
-
*
|
|
127
|
-
* to look them up by name. Callers should not assume reference equality with
|
|
128
|
-
* subsequent calls.
|
|
101
|
+
* Return a copy of every canonical built-in descriptor keyed by harness id.
|
|
102
|
+
* Callers should not assume reference equality with subsequent calls.
|
|
129
103
|
*/
|
|
130
104
|
export function listBuiltinAgentProfiles() {
|
|
131
105
|
const out = {};
|
|
@@ -28,8 +28,67 @@
|
|
|
28
28
|
* (X2) can wrap `executeRunner` without changing this contract.
|
|
29
29
|
*/
|
|
30
30
|
import { assertNever } from "../../core/assert.js";
|
|
31
|
-
import {
|
|
31
|
+
import { collectSensitiveValues, isEnvPassthroughValueSafeToExpose, redactSensitiveText, redactSensitiveValue, } from "../../core/redaction.js";
|
|
32
|
+
import { closeServer as disposeOpencodeSdkServers, runOpencodeSdk } from "../harnesses/opencode-sdk/sdk-runner.js";
|
|
33
|
+
import { materializeLlmConnection } from "./engine-resolution.js";
|
|
34
|
+
import { materializeLlmRunnerConnection } from "./runner.js";
|
|
32
35
|
import { runAgent } from "./spawn.js";
|
|
36
|
+
/**
|
|
37
|
+
* Release every long-lived resource the dispatch runners CACHE for reuse, so a
|
|
38
|
+
* one-shot process (the CLI) can exit cleanly once dispatching is done.
|
|
39
|
+
*
|
|
40
|
+
* The `sdk` runner keeps a per-material registry of `opencode serve` CHILD
|
|
41
|
+
* PROCESSES (see `opencode-sdk/sdk-runner.ts`), started lazily and reused
|
|
42
|
+
* across units within a process. Each live child is an OS handle that keeps
|
|
43
|
+
* Bun's event loop open — and the registry's own teardown is wired ONLY to
|
|
44
|
+
* `process.once('exit')`, which never fires while such a child holds the loop
|
|
45
|
+
* open. That is a deadlock: a successful `akm workflow run` that dispatched via
|
|
46
|
+
* the SDK path would hang the CLI (owner finding 4) because the process is
|
|
47
|
+
* never idle enough for the exit hook to run and close the children it is
|
|
48
|
+
* waiting on.
|
|
49
|
+
*
|
|
50
|
+
* The CLI composition root and workflow engine call this in `finally` blocks to
|
|
51
|
+
* drain the registry deterministically before relying on the event loop. Started
|
|
52
|
+
* servers close synchronously; in-flight starts are awaited and closed on
|
|
53
|
+
* arrival. When no SDK server was started this is an idempotent no-op.
|
|
54
|
+
*/
|
|
55
|
+
export async function disposeDispatchResources() {
|
|
56
|
+
await disposeOpencodeSdkServers();
|
|
57
|
+
}
|
|
58
|
+
/** Collect every materialized value that can reach one runner dispatch. */
|
|
59
|
+
export function collectDispatchSensitiveValues(spec, opts, envSource = opts.envSource ?? process.env) {
|
|
60
|
+
const values = new Set();
|
|
61
|
+
const add = (value) => {
|
|
62
|
+
if (value !== undefined && value.length > 0)
|
|
63
|
+
values.add(value);
|
|
64
|
+
};
|
|
65
|
+
const addConnection = (connection) => add(connection?.apiKey);
|
|
66
|
+
if (spec.kind === "llm")
|
|
67
|
+
addConnection(spec.connection);
|
|
68
|
+
if (spec.kind === "sdk")
|
|
69
|
+
addConnection(spec.fallbackConnection);
|
|
70
|
+
if (spec.kind !== "llm") {
|
|
71
|
+
for (const value of Object.values(spec.profile.env ?? {}))
|
|
72
|
+
add(value);
|
|
73
|
+
for (const name of spec.profile.envPassthrough) {
|
|
74
|
+
const value = envSource[name];
|
|
75
|
+
if (!isEnvPassthroughValueSafeToExpose(name, value))
|
|
76
|
+
add(value);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
for (const value of Object.values(opts.env ?? {}))
|
|
80
|
+
add(value);
|
|
81
|
+
return collectSensitiveValues(values);
|
|
82
|
+
}
|
|
83
|
+
function redactResult(result, sensitiveValues) {
|
|
84
|
+
return {
|
|
85
|
+
...result,
|
|
86
|
+
stdout: redactSensitiveText(result.stdout, sensitiveValues),
|
|
87
|
+
stderr: redactSensitiveText(result.stderr, sensitiveValues),
|
|
88
|
+
...(result.error !== undefined ? { error: redactSensitiveText(result.error, sensitiveValues) } : {}),
|
|
89
|
+
...(result.parsed !== undefined ? { parsed: redactSensitiveValue(result.parsed, sensitiveValues) } : {}),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
33
92
|
/**
|
|
34
93
|
* Dispatch a {@link RunnerSpec} to its runner and return the raw
|
|
35
94
|
* {@link AgentRunResult}. `opts` is the {@link RunAgentOptions} for the profile
|
|
@@ -37,23 +96,51 @@ import { runAgent } from "./spawn.js";
|
|
|
37
96
|
* its exact option set (incl. any `timeoutMs` the caller chose to apply).
|
|
38
97
|
*/
|
|
39
98
|
export async function executeRunner(spec, prompt, opts, seams = {}) {
|
|
99
|
+
const withSpecOptions = (timeoutMs, workspace) => ({
|
|
100
|
+
...opts,
|
|
101
|
+
...(Object.hasOwn(opts, "timeoutMs") ? {} : timeoutMs !== undefined ? { timeoutMs } : {}),
|
|
102
|
+
...(opts.cwd === undefined && workspace ? { cwd: workspace } : {}),
|
|
103
|
+
});
|
|
104
|
+
let result;
|
|
105
|
+
const dispatchSensitiveValues = [];
|
|
40
106
|
switch (spec.kind) {
|
|
41
107
|
case "llm": {
|
|
42
108
|
if (!seams.llm) {
|
|
43
109
|
throw new Error("executeRunner: an `llm` runner requires a `seams.llm` handler (no default LLM dispatch).");
|
|
44
110
|
}
|
|
45
|
-
|
|
111
|
+
const connection = materializeLlmRunnerConnection(spec);
|
|
112
|
+
if (connection.apiKey)
|
|
113
|
+
dispatchSensitiveValues.push(connection.apiKey);
|
|
114
|
+
result = await seams.llm({ ...spec, connection }, prompt, withSpecOptions(spec.timeoutMs));
|
|
115
|
+
break;
|
|
46
116
|
}
|
|
47
117
|
case "agent": {
|
|
48
118
|
const run = seams.runAgent ?? runAgent;
|
|
49
|
-
|
|
119
|
+
result = await run(spec.profile, prompt, withSpecOptions(spec.timeoutMs, spec.profile.workspace));
|
|
120
|
+
break;
|
|
50
121
|
}
|
|
51
122
|
case "sdk": {
|
|
52
123
|
const run = seams.runSdk ?? runOpencodeSdk;
|
|
53
|
-
|
|
124
|
+
const fallbackConnection = spec.fallbackConnection
|
|
125
|
+
? materializeLlmConnection({
|
|
126
|
+
engine: spec.engine ?? "unnamed-sdk-fallback",
|
|
127
|
+
connection: spec.fallbackConnection,
|
|
128
|
+
...(spec.fallbackCredential ? { credential: spec.fallbackCredential } : {}),
|
|
129
|
+
timeoutMs: spec.fallbackTimeoutMs !== undefined
|
|
130
|
+
? spec.fallbackTimeoutMs
|
|
131
|
+
: Object.hasOwn(spec.fallbackConnection, "timeoutMs")
|
|
132
|
+
? (spec.fallbackConnection.timeoutMs ?? null)
|
|
133
|
+
: null,
|
|
134
|
+
})
|
|
135
|
+
: undefined;
|
|
136
|
+
if (fallbackConnection?.apiKey)
|
|
137
|
+
dispatchSensitiveValues.push(fallbackConnection.apiKey);
|
|
138
|
+
result = await run(spec.profile, prompt, withSpecOptions(spec.timeoutMs, spec.profile.workspace), fallbackConnection);
|
|
139
|
+
break;
|
|
54
140
|
}
|
|
55
141
|
default:
|
|
56
142
|
// Exhaustiveness arm: a 4th RunnerSpec kind becomes a compile error here.
|
|
57
143
|
return assertNever(spec);
|
|
58
144
|
}
|
|
145
|
+
return redactResult(result, [...collectDispatchSensitiveValues(spec, opts), ...dispatchSensitiveValues]);
|
|
59
146
|
}
|
|
@@ -2,230 +2,99 @@
|
|
|
2
2
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
4
|
import { ConfigError } from "../../core/errors.js";
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
5
|
+
import { materializeLlmConnection, resolveEngine, resolveLlmEngineUse, } from "./engine-resolution.js";
|
|
6
|
+
import { resolveModel } from "./model-aliases.js";
|
|
7
|
+
/** Resolve the current credential value for one frozen LLM runner at dispatch. */
|
|
8
|
+
export function materializeLlmRunnerConnection(runner) {
|
|
9
|
+
const connectionWithLegacyTimeout = runner.connection;
|
|
10
|
+
const timeoutMs = runner.timeoutMs !== undefined
|
|
11
|
+
? runner.timeoutMs
|
|
12
|
+
: Object.hasOwn(connectionWithLegacyTimeout, "timeoutMs")
|
|
13
|
+
? (connectionWithLegacyTimeout.timeoutMs ?? null)
|
|
14
|
+
: null;
|
|
15
|
+
return materializeLlmConnection({
|
|
16
|
+
engine: runner.engine ?? "unnamed",
|
|
17
|
+
connection: runner.connection,
|
|
18
|
+
...(runner.credential ? { credential: runner.credential } : {}),
|
|
19
|
+
timeoutMs,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
13
22
|
export function runnerIsLlm(runner) {
|
|
14
23
|
return runner.kind === "llm";
|
|
15
24
|
}
|
|
16
|
-
/**
|
|
17
|
-
* Whether this runner can honour the file-write contract. Agent CLI + OpenCode
|
|
18
|
-
* SDK runners both have filesystem access; the direct LLM HTTP runner does NOT
|
|
19
|
-
* (see `src/llm/call-ai.ts`). Equivalent to `!runnerIsLlm(runner)` but names
|
|
20
|
-
* the capability the callers actually care about.
|
|
21
|
-
*/
|
|
22
25
|
export function runnerSupportsFileWrite(runner) {
|
|
23
26
|
return runner.kind !== "llm";
|
|
24
27
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
if (config.profiles?.llm?.[profileName])
|
|
31
|
-
return "llm";
|
|
32
|
-
const agentProfile = config.profiles?.agent?.[profileName];
|
|
33
|
-
if (agentProfile) {
|
|
34
|
-
return agentProfile.platform === "opencode-sdk" ? "sdk" : "agent";
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
// Fall back to defaults
|
|
38
|
-
if (config.defaults?.llm)
|
|
39
|
-
return "llm";
|
|
40
|
-
if (config.defaults?.agent)
|
|
41
|
-
return "agent";
|
|
42
|
-
return "llm";
|
|
43
|
-
}
|
|
44
|
-
function resolveProfileName(entry, mode, config) {
|
|
45
|
-
if (entry.profile)
|
|
46
|
-
return entry.profile;
|
|
47
|
-
if (mode === "llm") {
|
|
48
|
-
const defaultName = config.defaults?.llm;
|
|
49
|
-
if (defaultName)
|
|
50
|
-
return defaultName;
|
|
51
|
-
throw new ConfigError(`No LLM profile configured. Set defaults.llm in config or specify profile in the process entry.`, "LLM_NOT_CONFIGURED", "Run `akm setup` or define a profile under `profiles.llm` and set `defaults.llm`.");
|
|
52
|
-
}
|
|
53
|
-
const defaultName = config.defaults?.agent;
|
|
54
|
-
if (defaultName)
|
|
55
|
-
return defaultName;
|
|
56
|
-
throw new ConfigError(`No agent profile configured. Set defaults.agent in config or specify profile in the process entry.`, "INVALID_CONFIG_FILE", "Run `akm setup` to configure an agent profile, or add one under `profiles.agent`.");
|
|
57
|
-
}
|
|
58
|
-
function buildLlmRunnerSpec(profileName, timeoutMs, config) {
|
|
59
|
-
const profile = config.profiles?.llm?.[profileName];
|
|
60
|
-
if (!profile) {
|
|
61
|
-
throw new ConfigError(`LLM profile "${profileName}" not found in profiles.llm.`, "LLM_NOT_CONFIGURED", `Available profiles: ${Object.keys(config.profiles?.llm ?? {}).join(", ") || "none"}. Run \`akm setup\` to configure.`);
|
|
62
|
-
}
|
|
28
|
+
/** Resolve the configured LLM default without ever consulting retired profiles. */
|
|
29
|
+
export function resolveDefaultLlmRunner(config, timeoutMs) {
|
|
30
|
+
const resolved = resolveLlmEngineUse(config, [], { optional: true });
|
|
31
|
+
if (!resolved)
|
|
32
|
+
return null;
|
|
63
33
|
return {
|
|
64
34
|
kind: "llm",
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
function buildAgentRunnerSpec(kind, profileName, timeoutMs, config) {
|
|
70
|
-
const profileConfig = config.profiles?.agent?.[profileName];
|
|
71
|
-
if (!profileConfig) {
|
|
72
|
-
throw new ConfigError(`Agent profile "${profileName}" not found in profiles.agent.`, "INVALID_CONFIG_FILE", `Available profiles: ${Object.keys(config.profiles?.agent ?? {}).join(", ") || "none"}. Run \`akm setup\` to configure.`);
|
|
73
|
-
}
|
|
74
|
-
// Validate mode/platform consistency
|
|
75
|
-
if (kind === "sdk" && profileConfig.platform !== "opencode-sdk") {
|
|
76
|
-
throw new ConfigError(`Mode "sdk" requires platform "opencode-sdk", but profiles.agent["${profileName}"].platform is "${profileConfig.platform}".`, "INVALID_CONFIG_FILE");
|
|
77
|
-
}
|
|
78
|
-
if (kind === "agent" && profileConfig.platform === "opencode-sdk") {
|
|
79
|
-
throw new ConfigError(`Mode "agent" requires platform "opencode" or "claude", but profiles.agent["${profileName}"].platform is "opencode-sdk".`, "INVALID_CONFIG_FILE");
|
|
80
|
-
}
|
|
81
|
-
const agentProfile = {
|
|
82
|
-
name: profileName,
|
|
83
|
-
bin: profileConfig.bin ?? profileName,
|
|
84
|
-
args: profileConfig.args ?? [],
|
|
85
|
-
stdio: "captured",
|
|
86
|
-
envPassthrough: [],
|
|
87
|
-
parseOutput: "text",
|
|
88
|
-
...(profileConfig.model ? { model: profileConfig.model } : {}),
|
|
89
|
-
...(profileConfig.workspace ? { workspace: profileConfig.workspace } : {}),
|
|
90
|
-
};
|
|
91
|
-
return {
|
|
92
|
-
kind,
|
|
93
|
-
profile: agentProfile,
|
|
94
|
-
...(typeof timeoutMs === "number" ? { timeoutMs } : {}),
|
|
35
|
+
engine: resolved.engine,
|
|
36
|
+
connection: resolved.connection,
|
|
37
|
+
...(resolved.credential ? { credential: resolved.credential } : {}),
|
|
38
|
+
...(timeoutMs !== undefined ? { timeoutMs } : { timeoutMs: resolved.timeoutMs }),
|
|
95
39
|
};
|
|
96
40
|
}
|
|
97
|
-
/**
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
* Shared resolution path for the `validation` and `triage judgment` tiers,
|
|
113
|
-
* both of which take a `{ mode?, profile?, timeoutMs? }`-shaped block, attempt
|
|
114
|
-
* to resolve it via {@link resolveImproveProcessRunnerFromProfile}, and
|
|
115
|
-
* otherwise fall back to an `llm` runner built from `defaults.llm`.
|
|
116
|
-
*
|
|
117
|
-
* @param block the `{ mode?, profile?, timeoutMs? }` subset to resolve.
|
|
118
|
-
* @param config the active AKM config.
|
|
119
|
-
* @param opts.fallbackTimeoutMs timeout applied to the `defaults.llm` fallback
|
|
120
|
-
* runner (validation passes `undefined`; triage forwards `block.timeoutMs`).
|
|
121
|
-
* @param opts.suppressLlmFallbackForExplicitMode when `true` and the block
|
|
122
|
-
* explicitly sets `mode: "agent"` or `"sdk"`, do NOT silently fall back
|
|
123
|
-
* to `defaults.llm` if the profile resolver returns `null` or throws —
|
|
124
|
-
* return `null` instead and emit a `warn(...)` (see FIX 8). Validation
|
|
125
|
-
* passes `false` to preserve its always-fallback behavior.
|
|
126
|
-
*/
|
|
127
|
-
function resolveProcessRunnerWithLlmFallback(block, config, opts) {
|
|
128
|
-
const explicitNonLlmMode = block?.mode === "agent" || block?.mode === "sdk";
|
|
129
|
-
if (block && (block.mode || block.profile)) {
|
|
130
|
-
try {
|
|
131
|
-
const spec = resolveImproveProcessRunnerFromProfile(block, config);
|
|
132
|
-
if (spec)
|
|
133
|
-
return spec;
|
|
41
|
+
/** Resolve a triage judgment using judgment -> triage -> strategy -> defaults.llmEngine precedence. */
|
|
42
|
+
export function resolveTriageJudgmentRunner(judgment, config, triage, strategy) {
|
|
43
|
+
const layers = [strategy ?? {}, triage ?? {}, judgment ?? {}];
|
|
44
|
+
const selectedEngine = judgment?.engine ?? triage?.engine ?? strategy?.engine ?? config.defaults?.llmEngine;
|
|
45
|
+
if (selectedEngine) {
|
|
46
|
+
const runner = resolveEngine(selectedEngine, config);
|
|
47
|
+
if (runner.kind === "llm") {
|
|
48
|
+
const resolved = resolveLlmEngineUse(config, layers);
|
|
49
|
+
return {
|
|
50
|
+
kind: "llm",
|
|
51
|
+
engine: resolved.engine,
|
|
52
|
+
connection: resolved.connection,
|
|
53
|
+
...(resolved.credential ? { credential: resolved.credential } : {}),
|
|
54
|
+
timeoutMs: resolved.timeoutMs,
|
|
55
|
+
};
|
|
134
56
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
// FIX 8: an EXPLICIT agent/sdk request must not be silently downgraded to
|
|
139
|
-
// llm. When the profile resolver could not produce a runner, surface the
|
|
140
|
-
// misconfiguration and let callers skip this tier rather than substituting
|
|
141
|
-
// an llm judge.
|
|
142
|
-
if (opts.suppressLlmFallbackForExplicitMode && explicitNonLlmMode) {
|
|
143
|
-
warn(`[akm] Could not resolve the "${block?.mode}" judgment profile; ` +
|
|
144
|
-
`skipping the judgment tier instead of falling back to an llm judge. ` +
|
|
145
|
-
`Check profiles.agent and the judgment profile/mode configuration.`);
|
|
146
|
-
return null;
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
const defaultLlm = config.defaults?.llm;
|
|
150
|
-
if (defaultLlm) {
|
|
151
|
-
try {
|
|
152
|
-
return buildLlmRunnerSpec(defaultLlm, opts.fallbackTimeoutMs, config);
|
|
153
|
-
}
|
|
154
|
-
catch {
|
|
155
|
-
return null;
|
|
57
|
+
const effectiveLlmOverrides = [...layers].reverse().find((layer) => layer.llm !== undefined)?.llm;
|
|
58
|
+
if (effectiveLlmOverrides) {
|
|
59
|
+
throw new ConfigError(`Triage judgment engine "${selectedEngine}" is an agent engine and cannot receive llm overrides.`, "INVALID_CONFIG_FILE");
|
|
156
60
|
}
|
|
61
|
+
const model = [...layers].reverse().find((layer) => layer.model !== undefined)?.model;
|
|
62
|
+
const profile = model
|
|
63
|
+
? {
|
|
64
|
+
...runner.profile,
|
|
65
|
+
model: resolveModel(model, runner.profile.platform ?? runner.profile.name, runner.profile.modelAliases, runner.profile.globalModelAliases),
|
|
66
|
+
modelIsExact: true,
|
|
67
|
+
}
|
|
68
|
+
: runner.profile;
|
|
69
|
+
const timeoutLayer = [...layers].reverse().find((layer) => Object.hasOwn(layer, "timeoutMs"));
|
|
70
|
+
return {
|
|
71
|
+
...runner,
|
|
72
|
+
profile,
|
|
73
|
+
...(timeoutLayer ? { timeoutMs: timeoutLayer.timeoutMs ?? null } : {}),
|
|
74
|
+
};
|
|
157
75
|
}
|
|
158
76
|
return null;
|
|
159
77
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
*/
|
|
167
|
-
export function resolveDefaultLlmRunner(config, timeoutMs) {
|
|
168
|
-
const name = config.defaults?.llm;
|
|
169
|
-
if (!name)
|
|
170
|
-
return null;
|
|
171
|
-
return buildLlmRunnerSpec(name, timeoutMs, config);
|
|
172
|
-
}
|
|
173
|
-
export function resolveValidationRunner(config) {
|
|
174
|
-
const validation = config.profiles?.improve?.default?.processes?.validation;
|
|
175
|
-
const block = validation && validation.enabled !== false ? validation : undefined;
|
|
176
|
-
return resolveProcessRunnerWithLlmFallback(block, config, {
|
|
177
|
-
fallbackTimeoutMs: undefined,
|
|
178
|
-
suppressLlmFallbackForExplicitMode: false,
|
|
179
|
-
});
|
|
78
|
+
export function resolveImproveProcessLlmUse(config, strategy, processName, options = {}) {
|
|
79
|
+
const process = strategy?.processes?.[processName];
|
|
80
|
+
const layers = strategy ? [strategy, process ?? {}] : [];
|
|
81
|
+
return options.optional
|
|
82
|
+
? resolveLlmEngineUse(config, layers, { optional: true })
|
|
83
|
+
: resolveLlmEngineUse(config, layers);
|
|
180
84
|
}
|
|
181
|
-
/**
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
* compatible with {@link ImproveProcessConfig}, so it resolves through the same
|
|
185
|
-
* {@link resolveImproveProcessRunnerFromProfile} path.
|
|
186
|
-
*
|
|
187
|
-
* Mirrors {@link resolveValidationRunner}'s `defaults.llm` fallback only for
|
|
188
|
-
* the unset/`llm` case: when the block sets neither `mode` nor `profile` (so
|
|
189
|
-
* the profile resolver returns `null`) or `mode: "llm"`, fall back to an `llm`
|
|
190
|
-
* runner built from `defaults.llm` so `judgment.mode: llm` defaults are honored
|
|
191
|
-
* (§14). However (FIX 8) when the caller EXPLICITLY sets `mode: "agent"` or
|
|
192
|
-
* `"sdk"` and the profile resolver returns `null` or throws, do NOT downgrade
|
|
193
|
-
* to an llm judge — return `null` (callers skip the judgment tier and emit
|
|
194
|
-
* `triage_deferred`) and emit a `warn(...)`. Returns `null` when nothing is
|
|
195
|
-
* configured.
|
|
196
|
-
*/
|
|
197
|
-
export function resolveTriageJudgmentRunner(judgment, config) {
|
|
198
|
-
return resolveProcessRunnerWithLlmFallback(judgment, config, {
|
|
199
|
-
fallbackTimeoutMs: judgment?.timeoutMs,
|
|
200
|
-
suppressLlmFallbackForExplicitMode: true,
|
|
201
|
-
});
|
|
202
|
-
}
|
|
203
|
-
export function resolveRunner(mode, profileName, config) {
|
|
204
|
-
if (mode === "llm")
|
|
205
|
-
return buildLlmRunnerSpec(profileName, undefined, config);
|
|
206
|
-
return buildAgentRunnerSpec(mode, profileName, undefined, config);
|
|
207
|
-
}
|
|
208
|
-
/**
|
|
209
|
-
* Resolve a RunnerSpec from an improve-profile process entry. Returns `null`
|
|
210
|
-
* when the entry is absent or provides no overrides — callers should fall
|
|
211
|
-
* back to the default per-process runner resolution path.
|
|
212
|
-
*/
|
|
213
|
-
export function resolveImproveProcessRunnerFromProfile(processConfig, config) {
|
|
214
|
-
if (!processConfig)
|
|
85
|
+
/** Resolve the LLM runner selected by an improve strategy and process without reading credentials. */
|
|
86
|
+
export function resolveImproveProcessRunner(strategy, processName, config) {
|
|
87
|
+
if (!strategy)
|
|
215
88
|
return null;
|
|
216
|
-
const
|
|
217
|
-
if (!
|
|
89
|
+
const resolved = resolveImproveProcessLlmUse(config, strategy, processName, { optional: true });
|
|
90
|
+
if (!resolved)
|
|
218
91
|
return null;
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
}
|
|
227
|
-
return null;
|
|
92
|
+
return {
|
|
93
|
+
kind: "llm",
|
|
94
|
+
engine: resolved.engine,
|
|
95
|
+
connection: resolved.connection,
|
|
96
|
+
...(resolved.credential ? { credential: resolved.credential } : {}),
|
|
97
|
+
timeoutMs: resolved.timeoutMs,
|
|
98
|
+
};
|
|
228
99
|
}
|
|
229
|
-
// Re-export `isProcessEnabled` from feature-gate.ts so callers that previously
|
|
230
|
-
// imported it from runner.ts continue to work.
|
|
231
100
|
export { isProcessEnabled } from "../../llm/feature-gate.js";
|