akm-cli 0.9.1 → 0.9.2-alpha.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 +103 -28
- package/README.md +3 -1
- package/SECURITY.md +1 -1
- package/STABILITY.md +1 -1
- package/dist/akm +2 -2
- package/dist/akm-migrate +2 -2
- package/dist/assets/hints/cli-hints-full.md +14 -9
- package/dist/assets/improve-strategies/proactive-maintenance.json +1 -1
- package/dist/assets/improve-strategies/reflect-distill.json +1 -1
- package/dist/assets/models.json +35 -0
- package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +3 -4
- package/dist/assets/stash-skeleton/facts/conventions/organization.md +1 -3
- package/dist/assets/tasks/core/extract.yml +6 -5
- package/dist/assets/tasks/core/improve.yml +6 -5
- package/dist/assets/tasks/core/index-refresh.yml +6 -5
- package/dist/assets/tasks/core/sync.yml +6 -5
- package/dist/assets/tasks/core/version-check.yml +6 -5
- package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +6 -5
- package/dist/assets/tasks/improve/akm-improve-catchup.yml +6 -5
- package/dist/assets/tasks/improve/akm-improve-consolidate.yml +6 -5
- package/dist/assets/tasks/improve/akm-improve-frequent.yml +6 -5
- package/dist/assets/tasks/improve/akm-improve-nightly.yml +6 -5
- package/dist/cli/confirm.js +2 -2
- package/dist/cli/parse-args.js +3 -24
- package/dist/cli/retired-commands.js +1 -1
- package/dist/cli/shared.js +2 -2
- package/dist/cli.js +11 -9
- package/dist/commands/agent/agent-dispatch.js +55 -89
- package/dist/commands/agent/contribute-cli.js +12 -45
- package/dist/commands/command/builtin-action.js +32 -0
- package/dist/commands/command/command-cli.js +99 -0
- package/dist/commands/command/command-execution.js +308 -0
- package/dist/commands/command/execution-source-loader.js +176 -0
- package/dist/commands/command/portable-template.js +60 -0
- package/dist/commands/config-cli.js +10 -4
- package/dist/commands/env/env.js +4 -2
- package/dist/commands/feedback-cli.js +1 -1
- package/dist/commands/health/checks.js +241 -29
- package/dist/commands/health/html-report.js +0 -14
- package/dist/commands/health/report-view-model.js +0 -1
- package/dist/commands/health/surfaces.js +6 -7
- package/dist/commands/health/types.js +0 -2
- package/dist/commands/health.js +63 -18
- package/dist/commands/improve/collapse-detector.js +5 -6
- package/dist/commands/improve/consolidate.js +251 -214
- package/dist/commands/improve/distill/promote-memory.js +71 -34
- package/dist/commands/improve/distill/quality-gate.js +17 -5
- package/dist/commands/improve/distill.js +232 -155
- package/dist/commands/improve/eligibility.js +112 -79
- package/dist/commands/improve/execution.js +57 -0
- package/dist/commands/improve/extract-cli.js +5 -5
- package/dist/commands/improve/extract-prompt.js +64 -22
- package/dist/commands/improve/extract.js +608 -360
- package/dist/commands/improve/improve-strategies.js +43 -14
- package/dist/commands/improve/improve.js +249 -29
- package/dist/commands/improve/loop-stages.js +11 -17
- package/dist/commands/improve/memory/memory-contradiction-detect.js +90 -66
- package/dist/commands/improve/outcome-loop.js +22 -38
- package/dist/commands/improve/planner.js +134 -0
- package/dist/commands/improve/preparation.js +730 -409
- package/dist/commands/improve/reflect.js +386 -223
- package/dist/commands/improve/run-context.js +3 -4
- package/dist/commands/improve/salience.js +6 -58
- package/dist/commands/improve/session-asset.js +12 -12
- package/dist/commands/lint/index.js +101 -29
- package/dist/commands/migrate-cli.js +11 -69
- package/dist/commands/migration-tool.js +6 -9
- package/dist/commands/models-cli.js +27 -0
- package/dist/commands/proposal/drain.js +258 -186
- package/dist/commands/proposal/proposal-cli.js +32 -10
- package/dist/commands/proposal/proposal.js +2 -5
- package/dist/commands/proposal/propose.js +192 -172
- package/dist/commands/proposal/repository.js +54 -91
- package/dist/commands/proposal/validators/proposal-validators.js +9 -7
- package/dist/commands/read/curate.js +53 -22
- package/dist/commands/read/registry-search.js +25 -9
- package/dist/commands/read/remember-cli.js +14 -2
- package/dist/commands/read/search.js +10 -4
- package/dist/commands/read/show.js +139 -153
- package/dist/commands/registry-cli.js +16 -7
- package/dist/commands/remember.js +33 -18
- package/dist/commands/sources/add-cli.js +19 -178
- package/dist/commands/sources/bundle-cli.js +15 -3
- package/dist/commands/sources/dangerous-env-audit.js +135 -0
- package/dist/commands/sources/info.js +2 -1
- package/dist/commands/sources/installed-stashes.js +901 -177
- package/dist/commands/sources/schema-repair.js +174 -95
- package/dist/commands/sources/self-update.js +30 -74
- package/dist/commands/sources/source-add.js +3 -5
- package/dist/commands/sources/sources-cli.js +2 -15
- package/dist/commands/sources/update-transaction.js +220 -0
- package/dist/commands/tasks/tasks-cli.js +3 -3
- package/dist/commands/tasks/tasks.js +736 -317
- package/dist/commands/workflow-cli.js +2 -2
- package/dist/core/adapter/adapters/agent-skills-adapter.js +3 -0
- package/dist/core/adapter/adapters/akm-adapter.js +85 -35
- package/dist/core/adapter/adapters/akm-lint.js +54 -39
- package/dist/core/adapter/adapters/akm-metadata.js +45 -45
- package/dist/core/adapter/adapters/akm-task-adapter.js +32 -49
- package/dist/core/adapter/adapters/akm-workflow-adapter.js +38 -23
- package/dist/core/adapter/adapters/dotenv-adapter.js +30 -1
- package/dist/core/adapter/adapters/generic-files-adapter.js +11 -0
- package/dist/core/adapter/adapters/index.js +0 -9
- package/dist/core/adapter/adapters/llm-wiki-adapter.js +4 -0
- package/dist/core/adapter/adapters/okf-adapter.js +4 -0
- package/dist/core/adapter/adapters/opencode-adapter.js +5 -8
- package/dist/core/adapter/adapters/tool-dir-shared.js +63 -6
- package/dist/core/adapter/adapters/website-snapshot-adapter.js +4 -0
- package/dist/core/adapter/execution-source.js +308 -0
- package/dist/core/adapter/recognize-match.js +36 -13
- package/dist/core/adapter/registry.js +0 -9
- package/dist/core/asset/stash-meta.js +94 -4
- package/dist/core/common.js +6 -11
- package/dist/core/config/config-io.js +3 -3
- package/dist/core/config/config-schema.js +18 -40
- package/dist/core/config/config-sources.js +11 -21
- package/dist/core/config/config-walker.js +31 -13
- package/dist/core/config/config.js +23 -26
- package/dist/core/config/schema/engines.js +8 -7
- package/dist/core/config/schema/improve-processes.js +29 -5
- package/dist/core/config/schema/index-config.js +0 -27
- package/dist/core/config/schema/primitives.js +1 -23
- package/dist/core/config/schema/sources-bundles.js +13 -16
- package/dist/core/errors.js +2 -0
- package/dist/core/events.js +68 -32
- package/dist/core/extra-params.js +1 -0
- package/dist/core/improve-result.js +315 -0
- package/dist/core/lesson-lint.js +0 -6
- package/dist/core/maintenance-barrier.js +4 -4
- package/dist/core/network-policy.js +152 -0
- package/dist/core/paths.js +1 -1
- package/dist/core/recognition-util.js +4 -4
- package/dist/core/registry-url.js +456 -0
- package/dist/core/state/migrations.js +161 -47
- package/dist/core/state-db.js +453 -80
- package/dist/core/system-error.js +32 -0
- package/dist/core/time.js +2 -12
- package/dist/core/write-source.js +0 -18
- package/dist/execution/directory-identity.js +52 -0
- package/dist/execution/executable-identity.js +107 -0
- package/dist/execution/guarded-source.js +398 -0
- package/dist/execution/json.js +95 -0
- package/dist/{commands/health/types-session-log.js → execution/limits.js} +2 -1
- package/dist/execution/record.js +55 -0
- package/dist/execution/resolved-request.js +730 -0
- package/dist/execution/source.js +320 -0
- package/dist/indexer/bundle-identity-guard.js +5 -4
- package/dist/indexer/db/graph-db.js +33 -0
- package/dist/indexer/graph/graph-boost.js +3 -4
- package/dist/indexer/graph/graph-extraction.js +562 -373
- package/dist/indexer/index-written-assets.js +78 -39
- package/dist/indexer/indexer.js +471 -432
- package/dist/indexer/installations.js +6 -0
- package/dist/indexer/lookup/adapter-concept-owner.js +283 -0
- package/dist/indexer/materialize-embeddings.js +155 -0
- package/dist/indexer/passes/memory-inference.js +227 -174
- package/dist/indexer/passes/metadata.js +263 -118
- package/dist/indexer/scan/doc-to-entry.js +7 -10
- package/dist/indexer/scan/drain-dir.js +51 -23
- package/dist/indexer/search/db-search.js +156 -50
- package/dist/indexer/search/fts-query.js +40 -40
- package/dist/indexer/search/ranking.js +36 -1
- package/dist/indexer/search/search-attribution.js +3 -1
- package/dist/indexer/search/search-fields.js +23 -14
- package/dist/indexer/search/search-hit-enrichers.js +1 -1
- package/dist/indexer/search/search-source.js +7 -16
- package/dist/indexer/search/semantic-status.js +10 -1
- package/dist/indexer/usage/show-usage.js +105 -0
- package/dist/indexer/usage/usage-events.js +7 -2
- package/dist/indexer/walk/matchers.js +40 -10
- package/dist/indexer/walk/path-resolver.js +5 -2
- package/dist/indexer/walk/walker.js +20 -2
- package/dist/integrations/agent/builder-shared.js +3 -6
- package/dist/integrations/agent/conversation-fallback.js +16 -0
- package/dist/integrations/agent/engine-resolution.js +87 -87
- package/dist/integrations/agent/execution-cascade.js +566 -0
- package/dist/integrations/agent/execution-definitions.js +211 -0
- package/dist/integrations/agent/execution-lowering.js +811 -0
- package/dist/integrations/agent/execution-preparation.js +67 -0
- package/dist/integrations/agent/index.js +0 -2
- package/dist/integrations/agent/inline-execution.js +74 -0
- package/dist/integrations/agent/model-map.js +515 -0
- package/dist/integrations/agent/persona-fallback.js +30 -0
- package/dist/integrations/agent/request-lowering.js +186 -0
- package/dist/integrations/agent/runner-dispatch.js +230 -37
- package/dist/integrations/agent/runner.js +12 -83
- package/dist/integrations/harnesses/aider/agent-builder.js +8 -0
- package/dist/integrations/harnesses/aider/index.js +0 -1
- package/dist/integrations/harnesses/amazonq/agent-builder.js +8 -0
- package/dist/integrations/harnesses/amazonq/index.js +0 -1
- package/dist/integrations/harnesses/claude/agent-builder.js +14 -1
- package/dist/integrations/harnesses/claude/index.js +1 -5
- package/dist/integrations/harnesses/claude/session-log.js +3 -33
- package/dist/integrations/harnesses/codex/agent-builder.js +8 -0
- package/dist/integrations/harnesses/codex/index.js +0 -1
- package/dist/integrations/harnesses/copilot/agent-builder.js +8 -0
- package/dist/integrations/harnesses/copilot/index.js +0 -1
- package/dist/integrations/harnesses/gemini/agent-builder.js +8 -0
- package/dist/integrations/harnesses/gemini/index.js +0 -1
- package/dist/integrations/harnesses/index.js +4 -44
- package/dist/integrations/harnesses/opencode/agent-builder.js +16 -9
- package/dist/integrations/harnesses/opencode/index.js +0 -2
- package/dist/integrations/harnesses/opencode/session-log.js +14 -204
- package/dist/integrations/harnesses/opencode-sdk/harness.js +12 -1
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +40 -42
- package/dist/integrations/harnesses/openhands/agent-builder.js +8 -0
- package/dist/integrations/harnesses/openhands/index.js +0 -1
- package/dist/integrations/harnesses/pi/agent-builder.js +8 -0
- package/dist/integrations/harnesses/pi/index.js +0 -1
- package/dist/integrations/harnesses/shared.js +0 -1
- package/dist/integrations/harnesses/types.js +1 -3
- package/dist/integrations/lockfile.js +82 -79
- package/dist/integrations/session-logs/index.js +6 -17
- package/dist/integrations/session-logs/provider-base.js +1 -29
- package/dist/llm/client.js +10 -5
- package/dist/llm/embedder.js +6 -7
- package/dist/llm/embedders/local.js +37 -88
- package/dist/llm/embedders/types.js +1 -1
- package/dist/llm/graph-extract.js +75 -50
- package/dist/llm/index-passes.js +43 -5
- package/dist/llm/memory-infer.js +8 -6
- package/dist/llm/metadata-enhance.js +5 -3
- package/dist/llm/structured-call.js +122 -25
- package/dist/output/format-exempt.js +1 -1
- package/dist/output/render-registry.js +0 -16
- package/dist/output/renderers.js +12 -7
- package/dist/output/shapes/curate.js +1 -0
- package/dist/output/shapes/helpers.js +10 -2
- package/dist/output/shapes/passthrough.js +2 -0
- package/dist/output/text/command-format.js +31 -33
- package/dist/output/text/health-format.js +1 -29
- package/dist/output/text/migrate.js +6 -56
- package/dist/output/text/proposal-format.js +16 -1
- package/dist/output/text/workflow-format.js +16 -0
- package/dist/registry/network.js +279 -0
- package/dist/registry/pinned-request-helper.js +247 -0
- package/dist/registry/pinned-transport.js +717 -0
- package/dist/registry/providers/skills-sh.js +18 -6
- package/dist/registry/providers/static-index.js +20 -7
- package/dist/registry/resolve.js +53 -28
- package/dist/scripts/akm-migrate-node.js +19334 -52269
- package/dist/scripts/akm-migrate.js +19270 -51612
- package/dist/setup/registry-stash-loader.js +64 -20
- package/dist/setup/semantic-assets.js +9 -34
- package/dist/setup/setup.js +12 -30
- package/dist/setup/source-identity.js +17 -0
- package/dist/setup/steps/sources.js +36 -15
- package/dist/setup/steps/tasks.js +39 -11
- package/dist/sources/providers/git-provider.js +3 -3
- package/dist/sources/providers/npm.js +2 -2
- package/dist/sources/providers/provider-utils.js +4 -3
- package/dist/sources/providers/website.js +11 -7
- package/dist/sources/snapshot-fetchers/host-guard.js +9 -136
- package/dist/sources/snapshot-fetchers/website-ingest.js +25 -109
- package/dist/sources/website-url.js +73 -0
- package/dist/storage/engines/sqlite-migrations.js +81 -26
- package/dist/storage/managed-db.js +27 -24
- package/dist/storage/repositories/events-repository.js +3 -0
- package/dist/storage/repositories/index-connection.js +42 -10
- package/dist/storage/repositories/index-entries-repository.js +203 -229
- package/dist/storage/repositories/index-entry-mapper.js +8 -12
- package/dist/storage/repositories/index-entry-schema.js +255 -0
- package/dist/storage/repositories/index-fts-repository.js +64 -71
- package/dist/storage/repositories/index-llm-cache-repository.js +8 -13
- package/dist/storage/repositories/index-meta-repository.js +0 -11
- package/dist/storage/repositories/index-schema.js +74 -350
- package/dist/storage/repositories/index-utility-repository.js +12 -17
- package/dist/storage/repositories/index-vec-repository.js +56 -7
- package/dist/storage/repositories/proposals-repository.js +4 -127
- package/dist/storage/repositories/registry-cache.js +2 -1
- package/dist/storage/repositories/task-history-repository.js +20 -40
- package/dist/storage/repositories/workflow-runs-repository.js +228 -129
- package/dist/storage/sqlite-read-snapshot.js +148 -0
- package/dist/tasks/backends/cron.js +170 -42
- package/dist/tasks/backends/index.js +1 -1
- package/dist/tasks/backends/launchd.js +787 -202
- package/dist/tasks/backends/schtasks.js +282 -83
- package/dist/tasks/embedded.js +7 -7
- package/dist/tasks/frozen-script.js +50 -0
- package/dist/tasks/resolve-akm-bin.js +5 -1
- package/dist/tasks/runner.js +239 -251
- package/dist/tasks/runtime-v3.js +281 -0
- package/dist/tasks/scheduler-binding.js +272 -0
- package/dist/tasks/scheduler-invocation.js +57 -43
- package/dist/tasks/scheduler-sync.js +654 -0
- package/dist/tasks/source-v3.js +752 -0
- package/dist/tasks/standalone-script-entry.js +5 -0
- package/dist/tasks/task-id.js +29 -0
- package/dist/workflows/authoring/authoring.js +15 -32
- package/dist/workflows/exec/dispatch-redaction.js +14 -8
- package/dist/workflows/exec/exec-unit.js +7 -28
- package/dist/workflows/exec/frozen-judge.js +57 -89
- package/dist/workflows/exec/lowering-notices.js +23 -0
- package/dist/workflows/exec/native-executor.js +301 -458
- package/dist/workflows/exec/param-secrets.js +4 -3
- package/dist/workflows/exec/run-workflow.js +26 -32
- package/dist/workflows/exec/step-work.js +105 -109
- package/dist/workflows/exec/unit-dispatch.js +103 -27
- package/dist/workflows/exec/unit-writer.js +3 -3
- package/dist/workflows/exec/worktree.js +2 -2
- package/dist/workflows/ir/compile.js +86 -72
- package/dist/workflows/ir/environment-v4.js +328 -0
- package/dist/workflows/ir/freeze-v4.js +122 -0
- package/dist/workflows/ir/plan-hash.js +13 -7
- package/dist/workflows/ir/schema-v4.js +525 -0
- package/dist/workflows/ir/schema.js +25 -284
- package/dist/workflows/ir/source-freeze-v4.js +506 -0
- package/dist/workflows/parser.js +27 -24
- package/dist/workflows/program/schema.js +1 -2
- package/dist/workflows/renderer.js +42 -29
- package/dist/workflows/resource-limits.js +4 -5
- package/dist/workflows/runtime/agent-identity.js +11 -13
- package/dist/workflows/runtime/plan-classifier.js +8 -8
- package/dist/workflows/runtime/runs.js +27 -43
- package/dist/workflows/runtime/workflow-asset-loader.js +45 -205
- package/dist/workflows/source-files.js +373 -0
- package/dist/workflows/source-ir/compile.js +196 -0
- package/dist/workflows/source-ir/github-yaml.js +577 -0
- package/dist/workflows/source-ir/ordering.js +38 -0
- package/dist/workflows/source-ir/program.js +50 -0
- package/dist/workflows/source-ir/result.js +26 -0
- package/dist/workflows/source-ir/schema.js +772 -0
- package/dist/workflows/source-ir/semantics.js +242 -0
- package/dist/workflows/source-ir/uses.js +14 -0
- package/docs/README.md +2 -0
- package/docs/migration/README.md +3 -1
- package/docs/migration/release-notes/0.9.2.md +55 -0
- package/docs/migration/release-notes/README.md +5 -0
- package/docs/migration/v0.8-to-v0.9.md +76 -1077
- package/docs/migration/v0.9.0-troubleshooting.md +104 -516
- package/docs/migration/v0.9.1-to-v0.9.2.md +150 -0
- package/docs/reference/README.md +1 -0
- package/docs/reference/cli.md +230 -98
- package/docs/reference/configuration.md +159 -36
- package/docs/reference/data-and-telemetry.md +19 -1
- package/docs/reference/supported-formats.md +23 -3
- package/docs/reference/tasks.md +182 -0
- package/docs/reference/workflow-schema.md +91 -40
- package/docs/reference/workflows.md +33 -6
- package/package.json +10 -6
- package/schemas/akm-config.json +372 -224
- package/schemas/akm-task.json +324 -80
- package/schemas/akm-workflow.json +6 -9
- package/dist/core/migration-operation.js +0 -75
- package/dist/integrations/agent/model-aliases.js +0 -74
- package/dist/tasks/parser.js +0 -380
- package/dist/tasks/schema.js +0 -123
- package/dist/tasks/validator.js +0 -80
- package/dist/workflows/ir/freeze.js +0 -320
- package/dist/workflows/runtime/document-cache.js +0 -13
|
@@ -0,0 +1,30 @@
|
|
|
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 const PERSONA_FALLBACK_NOTICE_CODE = "persona-prompt-composed";
|
|
5
|
+
export const PERSONA_FALLBACK_BEGIN = "<AKM_PERSONA>";
|
|
6
|
+
export const PERSONA_FALLBACK_END = "</AKM_PERSONA>";
|
|
7
|
+
function withTrailingNewline(value) {
|
|
8
|
+
return value.endsWith("\n") ? value : `${value}\n`;
|
|
9
|
+
}
|
|
10
|
+
/** Preserve a persona when a target has no native system/persona channel. */
|
|
11
|
+
export function composePersonaFallbackPrompt(persona, command, adapter) {
|
|
12
|
+
if (typeof persona !== "string" || typeof command !== "string") {
|
|
13
|
+
throw new TypeError("persona fallback content must be strings");
|
|
14
|
+
}
|
|
15
|
+
if (typeof adapter !== "string" || adapter.length === 0) {
|
|
16
|
+
throw new TypeError("persona fallback adapter must be a non-empty string");
|
|
17
|
+
}
|
|
18
|
+
const notice = Object.freeze({
|
|
19
|
+
code: PERSONA_FALLBACK_NOTICE_CODE,
|
|
20
|
+
severity: "info",
|
|
21
|
+
adapter,
|
|
22
|
+
field: "persona",
|
|
23
|
+
message: "The selected engine has no native persona channel; AKM composed the persona into the prompt.",
|
|
24
|
+
});
|
|
25
|
+
const notices = Object.freeze([notice]);
|
|
26
|
+
return Object.freeze({
|
|
27
|
+
prompt: `${PERSONA_FALLBACK_BEGIN}\n${withTrailingNewline(persona)}${PERSONA_FALLBACK_END}\n\n${command}`,
|
|
28
|
+
notices,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
@@ -0,0 +1,186 @@
|
|
|
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 { ConfigError } from "../../core/errors.js";
|
|
5
|
+
import { composeConversationFallbackPrompt } from "./conversation-fallback.js";
|
|
6
|
+
import { composePersonaFallbackPrompt } from "./persona-fallback.js";
|
|
7
|
+
function own(value, key) {
|
|
8
|
+
return Object.hasOwn(value, key);
|
|
9
|
+
}
|
|
10
|
+
function hasToolSelection(value) {
|
|
11
|
+
if (value === null)
|
|
12
|
+
return false;
|
|
13
|
+
if (typeof value === "string")
|
|
14
|
+
return value.length > 0;
|
|
15
|
+
if (Array.isArray(value))
|
|
16
|
+
return value.length > 0;
|
|
17
|
+
return Object.keys(value).length > 0;
|
|
18
|
+
}
|
|
19
|
+
function translatesTools(mode, value) {
|
|
20
|
+
if (!hasToolSelection(value))
|
|
21
|
+
return true;
|
|
22
|
+
if (mode === "all")
|
|
23
|
+
return true;
|
|
24
|
+
if (mode === "flat")
|
|
25
|
+
return typeof value === "string" || Array.isArray(value);
|
|
26
|
+
if (mode === "sdk") {
|
|
27
|
+
return (typeof value === "string" ||
|
|
28
|
+
Array.isArray(value) ||
|
|
29
|
+
(value !== null && Object.values(value).every((entry) => typeof entry === "boolean")));
|
|
30
|
+
}
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
function notice(adapter, field) {
|
|
34
|
+
return Object.freeze({
|
|
35
|
+
code: "untranslated-field",
|
|
36
|
+
severity: "warning",
|
|
37
|
+
adapter,
|
|
38
|
+
field,
|
|
39
|
+
message: `The ${adapter} lowerer does not translate resolved field ${field}; dispatch will continue optimistically.`,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
function conversationFallbackNotice(adapter) {
|
|
43
|
+
return Object.freeze({
|
|
44
|
+
code: "conversation-prompt-composed",
|
|
45
|
+
severity: "warning",
|
|
46
|
+
adapter,
|
|
47
|
+
field: "conversation",
|
|
48
|
+
message: `The ${adapter} transport has no native multi-message channel; AKM composed the conversation prefix into one deterministic JSON prompt block.`,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
function selectedExtensionPaths(request) {
|
|
52
|
+
const out = [];
|
|
53
|
+
if (own(request, "extensions"))
|
|
54
|
+
out.push("extensions");
|
|
55
|
+
if (own(request.command, "extensions"))
|
|
56
|
+
out.push("command.extensions");
|
|
57
|
+
const persona = own(request, "persona") ? request.persona : undefined;
|
|
58
|
+
if (persona && own(persona, "extensions"))
|
|
59
|
+
out.push("persona.extensions");
|
|
60
|
+
if (own(request.engine, "extensions"))
|
|
61
|
+
out.push("engine.extensions");
|
|
62
|
+
if (own(request.runtime, "extensions"))
|
|
63
|
+
out.push("runtime.extensions");
|
|
64
|
+
return out;
|
|
65
|
+
}
|
|
66
|
+
function sortedUnique(values) {
|
|
67
|
+
return Object.freeze([...new Set(values)].sort());
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Build one harness-owned structural lowerer. Each harness registers the
|
|
71
|
+
* function it gets back beside its argv builder; no global model/provider
|
|
72
|
+
* capability table participates in dispatch.
|
|
73
|
+
*/
|
|
74
|
+
export function createAgentRequestLowerer(options) {
|
|
75
|
+
const supportedInference = new Set(options.inference ?? []);
|
|
76
|
+
return (_profile, request) => {
|
|
77
|
+
const translated = new Set(["command.content", "engine"]);
|
|
78
|
+
for (const field of ["timeoutMs", "workspace", "environment"]) {
|
|
79
|
+
if (own(request.runtime, field))
|
|
80
|
+
translated.add(`runtime.${field}`);
|
|
81
|
+
}
|
|
82
|
+
const untranslated = new Set();
|
|
83
|
+
const notices = [];
|
|
84
|
+
const reject = (field) => {
|
|
85
|
+
untranslated.add(field);
|
|
86
|
+
notices.push(notice(options.adapter, field));
|
|
87
|
+
};
|
|
88
|
+
let prompt = request.command.content;
|
|
89
|
+
if (own(request, "conversation")) {
|
|
90
|
+
translated.add("conversation");
|
|
91
|
+
if (request.conversation && request.conversation.length > 0) {
|
|
92
|
+
prompt = composeConversationFallbackPrompt(request.conversation, prompt);
|
|
93
|
+
notices.push(conversationFallbackNotice(options.adapter));
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
let systemPrompt;
|
|
97
|
+
const persona = own(request, "persona") ? request.persona : undefined;
|
|
98
|
+
const agent = own(request, "agent") ? request.agent : undefined;
|
|
99
|
+
let nativeAgent;
|
|
100
|
+
if (persona) {
|
|
101
|
+
if (options.personaChannel === "native") {
|
|
102
|
+
systemPrompt = persona.content;
|
|
103
|
+
translated.add("persona");
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
const composed = composePersonaFallbackPrompt(persona.content, prompt, options.adapter);
|
|
107
|
+
prompt = composed.prompt;
|
|
108
|
+
notices.push(...composed.notices);
|
|
109
|
+
translated.add("persona");
|
|
110
|
+
}
|
|
111
|
+
if (typeof agent === "string")
|
|
112
|
+
translated.add("agent");
|
|
113
|
+
}
|
|
114
|
+
else if (typeof agent === "string") {
|
|
115
|
+
if (!options.nativeAgentSelector) {
|
|
116
|
+
throw new ConfigError(`The ${options.adapter} transport cannot consume native agent selector ${JSON.stringify(agent)}.`, "INVALID_CONFIG_FILE");
|
|
117
|
+
}
|
|
118
|
+
nativeAgent = agent;
|
|
119
|
+
translated.add("agent");
|
|
120
|
+
}
|
|
121
|
+
else if (own(request, "agent")) {
|
|
122
|
+
translated.add("agent");
|
|
123
|
+
}
|
|
124
|
+
const dispatch = { prompt };
|
|
125
|
+
if (nativeAgent !== undefined)
|
|
126
|
+
dispatch.agent = nativeAgent;
|
|
127
|
+
if (systemPrompt !== undefined)
|
|
128
|
+
dispatch.systemPrompt = systemPrompt;
|
|
129
|
+
if (own(request, "model")) {
|
|
130
|
+
translated.add("model");
|
|
131
|
+
if (request.model) {
|
|
132
|
+
dispatch.model = request.model.resolved;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
if (own(request, "inference")) {
|
|
136
|
+
dispatch.inference = request.inference;
|
|
137
|
+
const inference = request.inference;
|
|
138
|
+
if (inference && Object.keys(inference).length > 0) {
|
|
139
|
+
for (const key of Object.keys(inference).sort()) {
|
|
140
|
+
const field = `inference.${key}`;
|
|
141
|
+
if (supportedInference.has(key))
|
|
142
|
+
translated.add(field);
|
|
143
|
+
else
|
|
144
|
+
reject(field);
|
|
145
|
+
}
|
|
146
|
+
if (typeof inference.effort === "string")
|
|
147
|
+
dispatch.effort = inference.effort;
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
translated.add("inference");
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
if (own(request, "outputSchema")) {
|
|
154
|
+
if (request.outputSchema === null || options.outputSchema)
|
|
155
|
+
translated.add("outputSchema");
|
|
156
|
+
else
|
|
157
|
+
reject("outputSchema");
|
|
158
|
+
if (request.outputSchema)
|
|
159
|
+
dispatch.schema = request.outputSchema;
|
|
160
|
+
}
|
|
161
|
+
if (own(request, "tools")) {
|
|
162
|
+
const tools = request.tools;
|
|
163
|
+
if (translatesTools(options.tools, tools))
|
|
164
|
+
translated.add("tools");
|
|
165
|
+
else
|
|
166
|
+
reject("tools");
|
|
167
|
+
dispatch.tools = tools;
|
|
168
|
+
}
|
|
169
|
+
if (own(request.runtime, "settings")) {
|
|
170
|
+
const settings = request.runtime.settings;
|
|
171
|
+
if (settings === null || Object.keys(settings).length === 0)
|
|
172
|
+
translated.add("runtime.settings");
|
|
173
|
+
else
|
|
174
|
+
reject("runtime.settings");
|
|
175
|
+
}
|
|
176
|
+
for (const field of selectedExtensionPaths(request))
|
|
177
|
+
reject(field);
|
|
178
|
+
return Object.freeze({
|
|
179
|
+
prompt,
|
|
180
|
+
dispatch: Object.freeze(dispatch),
|
|
181
|
+
translatedFields: sortedUnique(translated),
|
|
182
|
+
untranslatedFields: sortedUnique(untranslated),
|
|
183
|
+
notices: Object.freeze(notices),
|
|
184
|
+
});
|
|
185
|
+
};
|
|
186
|
+
}
|
|
@@ -2,37 +2,183 @@
|
|
|
2
2
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* The low-level exhaustive dispatch seam for the {@link RunnerSpec} transport
|
|
6
|
+
* union (`llm | agent | sdk`). User/model work reaches this function only
|
|
7
|
+
* after `ResolvedExecutionRequestV1` preparation and engine-owned lowering;
|
|
8
|
+
* `dispatchLoweredExecutionRequest` supplies the direct-LLM handler. A
|
|
9
|
+
* prompt-free native launch crosses the explicit payload-free interactive
|
|
10
|
+
* lowerer in that same shared layer.
|
|
6
11
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* Scoping (behavior-preserving):
|
|
14
|
-
* - The `agent` and `sdk` arms are byte-identical across call sites: invoke
|
|
15
|
-
* the profile runner (`runAgent` / `runOpencodeSdk`) with the per-call
|
|
16
|
-
* `RunAgentOptions` the caller passes. Those default runners live here so
|
|
17
|
-
* callers stop importing `runAgent` / `runOpencodeSdk` for dispatch. The
|
|
18
|
-
* `opts` (incl. any `timeoutMs`) is constructed by the caller and passed
|
|
19
|
-
* through unchanged, so each site keeps its exact option set.
|
|
20
|
-
* - The `llm` arm is irreducibly caller-specific (reflect wraps
|
|
21
|
-
* `runReflectViaLlm`, which returns reflect's iteration shape; drain wraps a
|
|
22
|
-
* plain `chatCompletion`). It is therefore a REQUIRED seam — there is no
|
|
23
|
-
* default `llm` handler — so neither caller's bespoke behavior is changed.
|
|
24
|
-
* - The `assertNever` exhaustiveness arm is kept so a 4th `RunnerSpec` kind is
|
|
25
|
-
* a compile error here instead of a silent runtime fall-through.
|
|
26
|
-
*
|
|
27
|
-
* The return type is {@link AgentRunResult} so a later `callStructured` layer
|
|
28
|
-
* (X2) can wrap `executeRunner` without changing this contract.
|
|
12
|
+
* Agent and SDK arms use the shared profile runners. The LLM arm deliberately
|
|
13
|
+
* requires a handler because structured callers own their parse/fallback
|
|
14
|
+
* contract. The `assertNever` arm keeps a fourth transport kind from becoming
|
|
15
|
+
* an implicit fallthrough. Symbolic LLM and SDK-fallback credentials are
|
|
16
|
+
* materialized here, at authorized operation-lease acquisition or the final
|
|
17
|
+
* single-call boundary, then scrubbed from the result.
|
|
29
18
|
*/
|
|
30
19
|
import { assertNever } from "../../core/assert.js";
|
|
31
20
|
import { collectSensitiveValues, isEnvPassthroughValueSafeToExpose, redactSensitiveText, redactSensitiveValue, } from "../../core/redaction.js";
|
|
32
|
-
import {
|
|
33
|
-
import {
|
|
34
|
-
import {
|
|
21
|
+
import { spawnEnvNamesFor } from "../../core/spawn-env.js";
|
|
22
|
+
import { closeServer as disposeOpencodeSdkServers, opencodeSdkServerEnvironmentNames, runOpencodeSdk, } from "../harnesses/opencode-sdk/sdk-runner.js";
|
|
23
|
+
import { lookupCredentialFromEnv, materializeLlmConnection, materializeLlmConnectionWithCredential, resolveCredentialFromEnv, } from "./engine-resolution.js";
|
|
24
|
+
import { materializeLlmRunnerConnection, materializeLlmRunnerConnectionWithCredential, } from "./runner.js";
|
|
35
25
|
import { runAgent } from "./spawn.js";
|
|
26
|
+
const liveRunnerDispatchLeases = new WeakMap();
|
|
27
|
+
const issuedRunnerDispatchLeases = new WeakSet();
|
|
28
|
+
const disposedRunnerDispatchLeases = new WeakSet();
|
|
29
|
+
function credentialBinding(credential) {
|
|
30
|
+
return credential ? { names: [...credential.names], required: credential.required } : null;
|
|
31
|
+
}
|
|
32
|
+
function passthroughBinding(spec) {
|
|
33
|
+
return [...new Set(spec.profile.envPassthrough)].sort();
|
|
34
|
+
}
|
|
35
|
+
function dispatchEnvironmentNames(spec) {
|
|
36
|
+
switch (spec.kind) {
|
|
37
|
+
case "llm":
|
|
38
|
+
return [];
|
|
39
|
+
case "agent":
|
|
40
|
+
return spawnEnvNamesFor(spec.profile.envPassthrough);
|
|
41
|
+
case "sdk":
|
|
42
|
+
return opencodeSdkServerEnvironmentNames(spec.profile);
|
|
43
|
+
default:
|
|
44
|
+
return assertNever(spec);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function snapshotDispatchEnvironment(spec, envSource) {
|
|
48
|
+
const snapshot = new Map();
|
|
49
|
+
const read = (name) => {
|
|
50
|
+
if (!snapshot.has(name))
|
|
51
|
+
snapshot.set(name, envSource[name]);
|
|
52
|
+
return snapshot.get(name);
|
|
53
|
+
};
|
|
54
|
+
const environmentSource = new Proxy(Object.create(null), {
|
|
55
|
+
get(_target, property) {
|
|
56
|
+
return typeof property === "string" ? snapshot.get(property) : undefined;
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
for (const name of dispatchEnvironmentNames(spec))
|
|
60
|
+
read(name);
|
|
61
|
+
const passthroughSensitiveValues = new Set();
|
|
62
|
+
if (spec.kind !== "llm") {
|
|
63
|
+
for (const name of new Set(spec.profile.envPassthrough)) {
|
|
64
|
+
const value = snapshot.get(name);
|
|
65
|
+
if (!isEnvPassthroughValueSafeToExpose(name, value) && value)
|
|
66
|
+
passthroughSensitiveValues.add(value);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return { environmentSnapshot: snapshot, environmentSource, passthroughSensitiveValues, read };
|
|
70
|
+
}
|
|
71
|
+
/** Bind only transport identity; request model/inference/schema/timeout remain per-call. */
|
|
72
|
+
function runnerLeaseBinding(spec) {
|
|
73
|
+
switch (spec.kind) {
|
|
74
|
+
case "llm":
|
|
75
|
+
return JSON.stringify({
|
|
76
|
+
kind: spec.kind,
|
|
77
|
+
engine: spec.engine ?? null,
|
|
78
|
+
endpoint: spec.connection.endpoint,
|
|
79
|
+
provider: spec.connection.provider ?? null,
|
|
80
|
+
credential: credentialBinding(spec.credential),
|
|
81
|
+
});
|
|
82
|
+
case "agent":
|
|
83
|
+
return JSON.stringify({
|
|
84
|
+
kind: spec.kind,
|
|
85
|
+
engine: spec.engine ?? null,
|
|
86
|
+
platform: spec.profile.platform ?? null,
|
|
87
|
+
name: spec.profile.name,
|
|
88
|
+
bin: spec.profile.bin,
|
|
89
|
+
envPassthrough: passthroughBinding(spec),
|
|
90
|
+
});
|
|
91
|
+
case "sdk":
|
|
92
|
+
return JSON.stringify({
|
|
93
|
+
kind: spec.kind,
|
|
94
|
+
engine: spec.engine ?? null,
|
|
95
|
+
platform: spec.profile.platform ?? null,
|
|
96
|
+
name: spec.profile.name,
|
|
97
|
+
bin: spec.profile.bin,
|
|
98
|
+
envPassthrough: passthroughBinding(spec),
|
|
99
|
+
fallbackEndpoint: spec.fallbackConnection?.endpoint ?? null,
|
|
100
|
+
fallbackProvider: spec.fallbackConnection?.provider ?? null,
|
|
101
|
+
fallbackCredential: credentialBinding(spec.fallbackCredential),
|
|
102
|
+
});
|
|
103
|
+
default:
|
|
104
|
+
return assertNever(spec);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function requireRunnerDispatchLease(lease, spec) {
|
|
108
|
+
if (typeof lease !== "object" || lease === null)
|
|
109
|
+
throw new TypeError("invalid dispatch lease");
|
|
110
|
+
const state = liveRunnerDispatchLeases.get(lease);
|
|
111
|
+
if (!state) {
|
|
112
|
+
if (issuedRunnerDispatchLeases.has(lease) && disposedRunnerDispatchLeases.has(lease)) {
|
|
113
|
+
throw new TypeError("dispatch lease is disposed");
|
|
114
|
+
}
|
|
115
|
+
throw new TypeError("invalid dispatch lease");
|
|
116
|
+
}
|
|
117
|
+
if (spec && state.binding !== runnerLeaseBinding(spec)) {
|
|
118
|
+
throw new TypeError("dispatch lease does not match the lowered runner transport");
|
|
119
|
+
}
|
|
120
|
+
return state;
|
|
121
|
+
}
|
|
122
|
+
/** @internal Verify provenance, liveness, and transport binding without exposing state. */
|
|
123
|
+
export function assertRunnerDispatchLease(lease, spec) {
|
|
124
|
+
requireRunnerDispatchLease(lease, spec);
|
|
125
|
+
}
|
|
126
|
+
/** @internal Acquire only through execution-lowering after authorization/provenance validation. */
|
|
127
|
+
export function acquireRunnerDispatchLease(spec, envSource = process.env) {
|
|
128
|
+
const environment = snapshotDispatchEnvironment(spec, envSource);
|
|
129
|
+
const credentialSource = new Proxy(Object.create(null), {
|
|
130
|
+
get(_target, property) {
|
|
131
|
+
return typeof property === "string" ? environment.read(property) : undefined;
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
const primaryCredential = spec.kind === "llm" ? resolveCredentialFromEnv(spec.credential, credentialSource) : undefined;
|
|
135
|
+
const fallbackCredential = spec.kind === "sdk" ? resolveCredentialFromEnv(spec.fallbackCredential, credentialSource) : undefined;
|
|
136
|
+
const handle = Object.create(null);
|
|
137
|
+
Object.defineProperty(handle, "toJSON", {
|
|
138
|
+
configurable: false,
|
|
139
|
+
enumerable: false,
|
|
140
|
+
writable: false,
|
|
141
|
+
value: () => {
|
|
142
|
+
throw new TypeError("dispatch lease is not serializable");
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
Object.freeze(handle);
|
|
146
|
+
const sensitiveValues = collectSensitiveValues([
|
|
147
|
+
primaryCredential,
|
|
148
|
+
fallbackCredential,
|
|
149
|
+
...environment.passthroughSensitiveValues,
|
|
150
|
+
]);
|
|
151
|
+
liveRunnerDispatchLeases.set(handle, {
|
|
152
|
+
binding: runnerLeaseBinding(spec),
|
|
153
|
+
primaryCredential,
|
|
154
|
+
fallbackCredential,
|
|
155
|
+
environmentSnapshot: environment.environmentSnapshot,
|
|
156
|
+
environmentSource: environment.environmentSource,
|
|
157
|
+
sensitiveValues,
|
|
158
|
+
});
|
|
159
|
+
issuedRunnerDispatchLeases.add(handle);
|
|
160
|
+
return handle;
|
|
161
|
+
}
|
|
162
|
+
/** @internal Scrub private material and invalidate one issued handle. */
|
|
163
|
+
export function disposeRunnerDispatchLease(lease) {
|
|
164
|
+
if (typeof lease !== "object" || lease === null || !issuedRunnerDispatchLeases.has(lease)) {
|
|
165
|
+
throw new TypeError("invalid dispatch lease");
|
|
166
|
+
}
|
|
167
|
+
const state = liveRunnerDispatchLeases.get(lease);
|
|
168
|
+
if (!state)
|
|
169
|
+
return;
|
|
170
|
+
state.primaryCredential = undefined;
|
|
171
|
+
state.fallbackCredential = undefined;
|
|
172
|
+
state.environmentSnapshot.clear();
|
|
173
|
+
state.sensitiveValues.fill("");
|
|
174
|
+
state.sensitiveValues = [];
|
|
175
|
+
liveRunnerDispatchLeases.delete(lease);
|
|
176
|
+
disposedRunnerDispatchLeases.add(lease);
|
|
177
|
+
}
|
|
178
|
+
/** @internal Redact with private credential material without exposing its values. */
|
|
179
|
+
export function redactWithRunnerDispatchLease(lease, value) {
|
|
180
|
+
return redactSensitiveText(value, requireRunnerDispatchLease(lease).sensitiveValues);
|
|
181
|
+
}
|
|
36
182
|
/**
|
|
37
183
|
* Release every long-lived resource the dispatch runners CACHE for reuse, so a
|
|
38
184
|
* one-shot process (the CLI) can exit cleanly once dispatching is done.
|
|
@@ -67,6 +213,10 @@ export function collectDispatchSensitiveValues(spec, opts, envSource = opts.envS
|
|
|
67
213
|
addConnection(spec.connection);
|
|
68
214
|
if (spec.kind === "sdk")
|
|
69
215
|
addConnection(spec.fallbackConnection);
|
|
216
|
+
if (spec.kind === "llm")
|
|
217
|
+
add(lookupCredentialFromEnv(spec.credential, envSource));
|
|
218
|
+
if (spec.kind === "sdk")
|
|
219
|
+
add(lookupCredentialFromEnv(spec.fallbackCredential, envSource));
|
|
70
220
|
if (spec.kind !== "llm") {
|
|
71
221
|
for (const value of Object.values(spec.profile.env ?? {}))
|
|
72
222
|
add(value);
|
|
@@ -82,6 +232,33 @@ export function collectDispatchSensitiveValues(spec, opts, envSource = opts.envS
|
|
|
82
232
|
}
|
|
83
233
|
return collectSensitiveValues(values);
|
|
84
234
|
}
|
|
235
|
+
function collectNonCredentialDispatchSensitiveValues(spec, opts, envSource = opts.envSource ?? process.env, includeProfilePassthrough = true) {
|
|
236
|
+
const values = new Set();
|
|
237
|
+
const add = (value) => {
|
|
238
|
+
if (value !== undefined && value.length > 0)
|
|
239
|
+
values.add(value);
|
|
240
|
+
};
|
|
241
|
+
if (spec.kind === "llm")
|
|
242
|
+
add(spec.connection.apiKey);
|
|
243
|
+
if (spec.kind === "sdk")
|
|
244
|
+
add(spec.fallbackConnection?.apiKey);
|
|
245
|
+
if (spec.kind !== "llm") {
|
|
246
|
+
for (const value of Object.values(spec.profile.env ?? {}))
|
|
247
|
+
add(value);
|
|
248
|
+
if (includeProfilePassthrough) {
|
|
249
|
+
for (const name of spec.profile.envPassthrough) {
|
|
250
|
+
const value = envSource[name];
|
|
251
|
+
if (!isEnvPassthroughValueSafeToExpose(name, value))
|
|
252
|
+
add(value);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
for (const [name, value] of Object.entries(opts.env ?? {})) {
|
|
257
|
+
if (!isEnvPassthroughValueSafeToExpose(name, value))
|
|
258
|
+
add(value);
|
|
259
|
+
}
|
|
260
|
+
return collectSensitiveValues(values);
|
|
261
|
+
}
|
|
85
262
|
function redactResult(result, sensitiveValues) {
|
|
86
263
|
return {
|
|
87
264
|
...result,
|
|
@@ -94,23 +271,33 @@ function redactResult(result, sensitiveValues) {
|
|
|
94
271
|
/**
|
|
95
272
|
* Dispatch a {@link RunnerSpec} to its runner and return the raw
|
|
96
273
|
* {@link AgentRunResult}. `opts` is the {@link RunAgentOptions} for the profile
|
|
97
|
-
* (`agent` / `sdk`) arms
|
|
98
|
-
*
|
|
274
|
+
* (`agent` / `sdk`) arms. Callers keep their per-call options; a bound lease
|
|
275
|
+
* replaces only `envSource` with its private immutable environment snapshot.
|
|
99
276
|
*/
|
|
100
|
-
export async function executeRunner(spec, prompt, opts, seams = {}) {
|
|
101
|
-
const withSpecOptions = (timeoutMs, workspace) => ({
|
|
277
|
+
export async function executeRunner(spec, prompt, opts, seams = {}, lease) {
|
|
278
|
+
const withSpecOptions = (timeoutMs, workspace, environmentSource) => ({
|
|
102
279
|
...opts,
|
|
103
280
|
...(Object.hasOwn(opts, "timeoutMs") ? {} : timeoutMs !== undefined ? { timeoutMs } : {}),
|
|
104
281
|
...(opts.cwd === undefined && workspace ? { cwd: workspace } : {}),
|
|
282
|
+
...(environmentSource ? { envSource: environmentSource } : {}),
|
|
105
283
|
});
|
|
106
284
|
let result;
|
|
107
285
|
const dispatchSensitiveValues = [];
|
|
286
|
+
const leaseState = lease ? requireRunnerDispatchLease(lease, spec) : undefined;
|
|
287
|
+
const preDispatchSensitiveValues = leaseState
|
|
288
|
+
? collectSensitiveValues([
|
|
289
|
+
...leaseState.sensitiveValues,
|
|
290
|
+
...collectNonCredentialDispatchSensitiveValues(spec, opts, undefined, false),
|
|
291
|
+
])
|
|
292
|
+
: collectDispatchSensitiveValues(spec, opts);
|
|
108
293
|
switch (spec.kind) {
|
|
109
294
|
case "llm": {
|
|
110
295
|
if (!seams.llm) {
|
|
111
296
|
throw new Error("executeRunner: an `llm` runner requires a `seams.llm` handler (no default LLM dispatch).");
|
|
112
297
|
}
|
|
113
|
-
const connection =
|
|
298
|
+
const connection = leaseState
|
|
299
|
+
? materializeLlmRunnerConnectionWithCredential(spec, leaseState.primaryCredential)
|
|
300
|
+
: materializeLlmRunnerConnection(spec);
|
|
114
301
|
if (connection.apiKey)
|
|
115
302
|
dispatchSensitiveValues.push(connection.apiKey);
|
|
116
303
|
result = await seams.llm({ ...spec, connection }, prompt, withSpecOptions(spec.timeoutMs));
|
|
@@ -118,13 +305,13 @@ export async function executeRunner(spec, prompt, opts, seams = {}) {
|
|
|
118
305
|
}
|
|
119
306
|
case "agent": {
|
|
120
307
|
const run = seams.runAgent ?? runAgent;
|
|
121
|
-
result = await run(spec.profile, prompt, withSpecOptions(spec.timeoutMs, spec.profile.workspace));
|
|
308
|
+
result = await run(spec.profile, prompt, withSpecOptions(spec.timeoutMs, spec.profile.workspace, leaseState?.environmentSource));
|
|
122
309
|
break;
|
|
123
310
|
}
|
|
124
311
|
case "sdk": {
|
|
125
312
|
const run = seams.runSdk ?? runOpencodeSdk;
|
|
126
|
-
const
|
|
127
|
-
?
|
|
313
|
+
const fallbackMaterial = spec.fallbackConnection
|
|
314
|
+
? {
|
|
128
315
|
engine: spec.engine ?? "unnamed-sdk-fallback",
|
|
129
316
|
connection: spec.fallbackConnection,
|
|
130
317
|
...(spec.fallbackCredential ? { credential: spec.fallbackCredential } : {}),
|
|
@@ -133,16 +320,22 @@ export async function executeRunner(spec, prompt, opts, seams = {}) {
|
|
|
133
320
|
: Object.hasOwn(spec.fallbackConnection, "timeoutMs")
|
|
134
321
|
? (spec.fallbackConnection.timeoutMs ?? null)
|
|
135
322
|
: null,
|
|
136
|
-
}
|
|
323
|
+
}
|
|
324
|
+
: undefined;
|
|
325
|
+
const fallbackConnection = fallbackMaterial
|
|
326
|
+
? leaseState
|
|
327
|
+
? materializeLlmConnectionWithCredential(fallbackMaterial, leaseState.fallbackCredential)
|
|
328
|
+
: materializeLlmConnection(fallbackMaterial)
|
|
137
329
|
: undefined;
|
|
138
330
|
if (fallbackConnection?.apiKey)
|
|
139
331
|
dispatchSensitiveValues.push(fallbackConnection.apiKey);
|
|
140
|
-
result = await run(spec.profile, prompt, withSpecOptions(spec.timeoutMs, spec.profile.workspace), fallbackConnection);
|
|
332
|
+
result = await run(spec.profile, prompt, withSpecOptions(spec.timeoutMs, spec.profile.workspace, leaseState?.environmentSource), fallbackConnection);
|
|
141
333
|
break;
|
|
142
334
|
}
|
|
143
335
|
default:
|
|
144
336
|
// Exhaustiveness arm: a 4th RunnerSpec kind becomes a compile error here.
|
|
145
337
|
return assertNever(spec);
|
|
146
338
|
}
|
|
147
|
-
|
|
339
|
+
const sensitiveValues = collectSensitiveValues([...preDispatchSensitiveValues, ...dispatchSensitiveValues]);
|
|
340
|
+
return redactResult(result, sensitiveValues);
|
|
148
341
|
}
|
|
@@ -1,99 +1,28 @@
|
|
|
1
1
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
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
|
-
import {
|
|
5
|
-
import { materializeLlmConnection, resolveEngine, resolveLlmEngineUse, } from "./engine-resolution.js";
|
|
6
|
-
import { resolveModel } from "./model-aliases.js";
|
|
4
|
+
import { materializeLlmConnection, materializeLlmConnectionWithCredential, } from "./engine-resolution.js";
|
|
7
5
|
/** Resolve the current credential value for one frozen LLM runner at dispatch. */
|
|
8
6
|
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
7
|
return materializeLlmConnection({
|
|
16
|
-
engine: runner.engine
|
|
8
|
+
engine: runner.engine,
|
|
17
9
|
connection: runner.connection,
|
|
18
10
|
...(runner.credential ? { credential: runner.credential } : {}),
|
|
19
|
-
timeoutMs,
|
|
11
|
+
timeoutMs: runner.timeoutMs ?? null,
|
|
20
12
|
});
|
|
21
13
|
}
|
|
14
|
+
/** Inject an already-snapshotted credential without consulting live process state. */
|
|
15
|
+
export function materializeLlmRunnerConnectionWithCredential(runner, credentialValue) {
|
|
16
|
+
return materializeLlmConnectionWithCredential({
|
|
17
|
+
engine: runner.engine,
|
|
18
|
+
connection: runner.connection,
|
|
19
|
+
...(runner.credential ? { credential: runner.credential } : {}),
|
|
20
|
+
timeoutMs: runner.timeoutMs ?? null,
|
|
21
|
+
}, credentialValue);
|
|
22
|
+
}
|
|
22
23
|
export function runnerIsLlm(runner) {
|
|
23
24
|
return runner.kind === "llm";
|
|
24
25
|
}
|
|
25
26
|
export function runnerSupportsFileWrite(runner) {
|
|
26
27
|
return runner.kind !== "llm";
|
|
27
28
|
}
|
|
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;
|
|
33
|
-
return {
|
|
34
|
-
kind: "llm",
|
|
35
|
-
engine: resolved.engine,
|
|
36
|
-
connection: resolved.connection,
|
|
37
|
-
...(resolved.credential ? { credential: resolved.credential } : {}),
|
|
38
|
-
...(timeoutMs !== undefined ? { timeoutMs } : { timeoutMs: resolved.timeoutMs }),
|
|
39
|
-
};
|
|
40
|
-
}
|
|
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
|
-
};
|
|
56
|
-
}
|
|
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");
|
|
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
|
-
};
|
|
75
|
-
}
|
|
76
|
-
return null;
|
|
77
|
-
}
|
|
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);
|
|
84
|
-
}
|
|
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)
|
|
88
|
-
return null;
|
|
89
|
-
const resolved = resolveImproveProcessLlmUse(config, strategy, processName, { optional: true });
|
|
90
|
-
if (!resolved)
|
|
91
|
-
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
|
-
};
|
|
99
|
-
}
|