akm-cli 0.9.4 → 0.9.6
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 +265 -0
- package/dist/commands/env/env-cli.js +1 -2
- package/dist/commands/env/secret-cli.js +1 -5
- package/dist/commands/feedback-cli.js +0 -4
- package/dist/commands/health/checks.js +0 -32
- package/dist/commands/health/surfaces.js +2 -2
- package/dist/commands/health.js +6 -15
- package/dist/commands/improve/anti-collapse.js +4 -91
- package/dist/commands/improve/autonomy-gate.js +1 -1
- package/dist/commands/improve/consolidate.js +25 -26
- package/dist/commands/improve/distill.js +2 -2
- package/dist/commands/improve/extract.js +8 -1
- package/dist/commands/improve/improve.js +3 -5
- package/dist/commands/improve/locks.js +13 -5
- package/dist/commands/improve/loop-stages.js +8 -9
- package/dist/commands/improve/memory/memory-contradiction-detect.js +1 -19
- package/dist/commands/improve/outcome-loop.js +0 -6
- package/dist/commands/improve/reflect.js +20 -9
- package/dist/commands/lint/index.js +4 -6
- package/dist/commands/proposal/validators/proposal-quality-validators.js +0 -7
- package/dist/commands/proposal/validators/proposal-validators.js +12 -0
- package/dist/commands/read/search.js +14 -24
- package/dist/commands/sources/bundle-config-ops.js +9 -4
- package/dist/commands/sources/info.js +14 -10
- package/dist/commands/tasks/tasks-cli.js +56 -3
- package/dist/commands/tasks/tasks.js +101 -18
- package/dist/commands/workflow-cli.js +2 -2
- package/dist/core/adapter/adapters/akm-adapter.js +2 -0
- package/dist/core/common.js +61 -24
- package/dist/core/config/config-io.js +2 -2
- package/dist/core/config/config-sources.js +32 -2
- package/dist/core/config/config-version-shim.js +101 -0
- package/dist/core/config/config.js +7 -7
- package/dist/core/config/schema/engines.js +9 -7
- package/dist/core/config/schema/primitives.js +0 -5
- package/dist/core/config/schema/search.js +2 -1
- package/dist/core/file-lock.js +2 -1
- package/dist/core/improve-result.js +35 -14
- package/dist/core/maintenance-barrier.js +2 -14
- package/dist/core/paths.js +0 -3
- package/dist/core/redaction.js +2 -2
- package/dist/core/spawn-env.js +8 -12
- package/dist/core/state/migrations.js +1 -12
- package/dist/core/state-db.js +9 -27
- package/dist/core/write-source.js +12 -19
- package/dist/execution/directory-identity.js +36 -10
- package/dist/execution/guarded-source.js +0 -10
- package/dist/indexer/graph/graph-boost.js +0 -4
- package/dist/indexer/index-writer-lock.js +43 -24
- package/dist/indexer/index-written-assets.js +5 -6
- package/dist/indexer/indexer.js +2 -39
- package/dist/indexer/materialize-embeddings.js +85 -41
- package/dist/indexer/passes/metadata.js +12 -4
- package/dist/indexer/scan/doc-to-entry.js +2 -0
- package/dist/indexer/search/db-search.js +15 -48
- package/dist/indexer/search/ranking-contributors.js +0 -25
- package/dist/indexer/search/ranking.js +3 -13
- package/dist/indexer/search/search-fields.js +16 -1
- package/dist/integrations/agent/builder-shared.js +0 -25
- package/dist/integrations/agent/model-map.js +2 -60
- package/dist/integrations/harnesses/aider/agent-builder.js +1 -3
- package/dist/integrations/harnesses/amazonq/agent-builder.js +2 -7
- package/dist/integrations/harnesses/claude/agent-builder.js +1 -4
- package/dist/integrations/harnesses/codex/agent-builder.js +1 -4
- package/dist/integrations/harnesses/copilot/agent-builder.js +2 -6
- package/dist/integrations/harnesses/gemini/agent-builder.js +2 -7
- package/dist/integrations/harnesses/opencode/agent-builder.js +1 -4
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +2 -16
- package/dist/integrations/harnesses/openhands/agent-builder.js +1 -3
- package/dist/integrations/harnesses/pi/agent-builder.js +2 -4
- package/dist/integrations/session-logs/index.js +0 -9
- package/dist/llm/client.js +75 -42
- package/dist/llm/embedder.js +7 -3
- package/dist/llm/embedders/remote.js +141 -42
- package/dist/output/shapes/passthrough.js +17 -5
- package/dist/registry/network.js +5 -37
- package/dist/runtime.js +2 -10
- package/dist/scripts/akm-migrate-node.js +180 -238
- package/dist/scripts/akm-migrate.js +180 -238
- package/dist/setup/engine-config.js +2 -5
- package/dist/setup/registry-stash-loader.js +0 -8
- package/dist/setup/setup.js +9 -46
- package/dist/setup/steps/connection-shared.js +10 -13
- package/dist/sources/providers/git-install.js +1 -1
- package/dist/storage/engines/sqlite-migrations.js +20 -1
- package/dist/storage/repositories/index-entries-repository.js +0 -15
- package/dist/storage/repositories/proposals-repository.js +32 -6
- package/dist/tasks/backends/launchd.js +15 -20
- package/dist/tasks/backends/schtasks.js +18 -8
- package/dist/tasks/run/run-native-task.js +8 -6
- package/dist/tasks/scheduler-binding.js +15 -5
- package/dist/tasks/scheduler-sync-preview.js +4 -2
- package/dist/tasks/scheduler-sync.js +77 -42
- package/dist/tasks/source/bounded-document.js +2 -4
- package/dist/tasks/source/task-source-v3-frozen.js +5 -7
- package/dist/tasks/source/task-source-v4.js +5 -10
- package/dist/tasks/source/task-to-v3.js +29 -22
- package/dist/tasks/source/task-to-v4.js +1 -14
- package/dist/tasks/source-v3.js +6 -6
- package/dist/workflows/exec/native-executor.js +21 -31
- package/dist/workflows/exec/run-workflow.js +5 -6
- package/dist/workflows/exec/scheduler.js +3 -19
- package/dist/workflows/exec/step-work.js +1 -4
- package/dist/workflows/exec/unit-dispatch.js +2 -2
- package/dist/workflows/exec/worktree.js +1 -13
- package/dist/workflows/freeze/targets/child-workflow.js +2 -10
- package/dist/workflows/ir/plan-hash.js +4 -6
- package/dist/workflows/ir/schema-v4.js +0 -12
- package/dist/workflows/ir/schema.js +20 -31
- package/dist/workflows/parser.js +11 -52
- package/dist/workflows/renderer.js +2 -3
- package/dist/workflows/resource-limits.js +11 -41
- package/dist/workflows/runtime/runs.js +3 -4
- package/dist/workflows/source-ir/schema.js +14 -30
- package/dist/workflows/validator.js +1 -7
- package/docs/reference/cli.md +25 -3
- package/docs/reference/configuration.md +28 -7
- package/docs/reference/tasks.md +10 -0
- package/package.json +1 -1
- package/schemas/akm-config.json +4 -23
- package/schemas/akm-task.json +1 -2
- package/schemas/akm-workflow.json +1 -13
- package/dist/indexer/search/semantic-status.js +0 -142
|
@@ -490,31 +490,6 @@ export const salienceRankingContributor = {
|
|
|
490
490
|
// comment. Do not add it back here without a config gate + a measured
|
|
491
491
|
// curate-golden-bench delta justifying it.
|
|
492
492
|
export const defaultUtilityRankingContributors = [utilityRankingContributor];
|
|
493
|
-
/**
|
|
494
|
-
* EVAL/DEBUG ONLY — remove named ranking contributors from a list.
|
|
495
|
-
*
|
|
496
|
-
* Driven by the `AKM_ABLATE_CONTRIBUTORS` env var (comma-separated contributor
|
|
497
|
-
* `name`s). A no-op — returns the input list unchanged (same reference) — when
|
|
498
|
-
* the env value is unset/empty, so production ranking is never affected unless
|
|
499
|
-
* the operator opts in. Its sole purpose is per-contributor ablation for the
|
|
500
|
-
* curate ablation harness (`scripts/akm-eval/`): run the same fixture with and without a contributor
|
|
501
|
-
* and diff the ranked results to measure whether that contributor is load-bearing.
|
|
502
|
-
*
|
|
503
|
-
* NOTE (from the 2026-06 ablation analysis): a contributor's ablation delta is only observable
|
|
504
|
-
* in the UNSATURATED score regime — once entries saturate at the `displayScore`
|
|
505
|
-
* ceiling their contributor deltas are absorbed and ablation reads Δ=0.
|
|
506
|
-
*/
|
|
507
|
-
export function applyContributorAblation(contributors, ablateEnv) {
|
|
508
|
-
if (!ablateEnv)
|
|
509
|
-
return contributors;
|
|
510
|
-
const ablated = new Set(ablateEnv
|
|
511
|
-
.split(",")
|
|
512
|
-
.map((s) => s.trim())
|
|
513
|
-
.filter(Boolean));
|
|
514
|
-
if (ablated.size === 0)
|
|
515
|
-
return contributors;
|
|
516
|
-
return contributors.filter((c) => !ablated.has(c.name));
|
|
517
|
-
}
|
|
518
493
|
export function applyScoreContributors(item, ctx, contributors = defaultRankingContributors) {
|
|
519
494
|
let boostSum = 0;
|
|
520
495
|
for (const contributor of contributors) {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
4
|
import { getUtilityScoresByIds } from "../../storage/repositories/index-utility-repository.js";
|
|
5
5
|
import { buildLexicalQueryPlan } from "./fts-query.js";
|
|
6
|
-
import { applyBeliefStateScoreCeiling,
|
|
6
|
+
import { applyBeliefStateScoreCeiling, applyScoreContributors, applyUtilityContributors, defaultRankingContributors, defaultUtilityRankingContributors, } from "./ranking-contributors.js";
|
|
7
7
|
export function normalizeFtsScores(results) {
|
|
8
8
|
const ftsScoreMap = new Map();
|
|
9
9
|
if (results.length === 0)
|
|
@@ -75,18 +75,8 @@ export function applyRankingRules(options) {
|
|
|
75
75
|
graphContext: options.graphContext,
|
|
76
76
|
projectContext: options.projectContext,
|
|
77
77
|
};
|
|
78
|
-
// Eval/debug only: lets the ablation harness drop named contributors to
|
|
79
|
-
// measure their effect. Resolved once per query; a no-op (full lists) when
|
|
80
|
-
// unset — see applyContributorAblation. C9: DI via
|
|
81
|
-
// `options.ablateContributors` is now the primary path (see the field's
|
|
82
|
-
// doc comment on RankEntriesOptions); AKM_ABLATE_CONTRIBUTORS is a
|
|
83
|
-
// temporary fallback for the one caller that cannot yet thread the option
|
|
84
|
-
// through (see that doc comment for why).
|
|
85
|
-
const ablateEnv = options.ablateContributors ?? process.env.AKM_ABLATE_CONTRIBUTORS;
|
|
86
|
-
const activeScoreContributors = applyContributorAblation(defaultRankingContributors, ablateEnv);
|
|
87
|
-
const activeUtilityContributors = applyContributorAblation(defaultUtilityRankingContributors, ablateEnv);
|
|
88
78
|
for (const item of options.items) {
|
|
89
|
-
applyScoreContributors(item, rankingContext,
|
|
79
|
+
applyScoreContributors(item, rankingContext, defaultRankingContributors);
|
|
90
80
|
}
|
|
91
81
|
const { global: utilScoresMap, scoped: scopedUtilScoresMap } = getUtilityScoresByIds(options.db, options.items.map((item) => item.id), options.scopeKey);
|
|
92
82
|
// R2 / #692 — salience-ranking is not in defaultUtilityRankingContributors
|
|
@@ -104,7 +94,7 @@ export function applyRankingRules(options) {
|
|
|
104
94
|
salienceRankScores,
|
|
105
95
|
};
|
|
106
96
|
for (const item of options.items) {
|
|
107
|
-
applyUtilityContributors(item, utilityContext,
|
|
97
|
+
applyUtilityContributors(item, utilityContext, defaultUtilityRankingContributors);
|
|
108
98
|
applyRelaxedLexicalScoreCeiling(item, queryTokens);
|
|
109
99
|
// SPEC-5: demoting belief states (superseded/contradicted/archived/
|
|
110
100
|
// deprecated) cap the FINAL score. The additive belief penalty inside the
|
|
@@ -1,6 +1,16 @@
|
|
|
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
|
+
/**
|
|
5
|
+
* Per-field search text extraction for FTS5 indexing.
|
|
6
|
+
*
|
|
7
|
+
* Extracted from indexer.ts to break the circular dependency:
|
|
8
|
+
* db.ts -> indexer.ts -> db.ts
|
|
9
|
+
*
|
|
10
|
+
* This module imports only from metadata.ts (for the IndexDocument type),
|
|
11
|
+
* so it can be safely imported by both db.ts and indexer.ts.
|
|
12
|
+
*/
|
|
13
|
+
import { warnVerbose } from "../../core/warn.js";
|
|
4
14
|
/** Structured metadata plus bounded body text supplied to embedding providers. */
|
|
5
15
|
export const SEARCH_TEXT_MAX_CHARS = 8_192;
|
|
6
16
|
/**
|
|
@@ -80,12 +90,17 @@ export function buildSearchText(entry) {
|
|
|
80
90
|
const structured = [fields.name, fields.description, fields.tags, fields.hints]
|
|
81
91
|
.filter((field) => field.length > 0)
|
|
82
92
|
.join(" ");
|
|
83
|
-
if (structured.length >= SEARCH_TEXT_MAX_CHARS)
|
|
93
|
+
if (structured.length >= SEARCH_TEXT_MAX_CHARS) {
|
|
94
|
+
warnVerbose(`${entry.ref ?? entry.name}: search text truncated to ${SEARCH_TEXT_MAX_CHARS} chars (content dropped entirely)`);
|
|
84
95
|
return truncateUnicodeSafe(structured, SEARCH_TEXT_MAX_CHARS);
|
|
96
|
+
}
|
|
85
97
|
if (!fields.content)
|
|
86
98
|
return structured;
|
|
87
99
|
const separator = structured ? " " : "";
|
|
88
100
|
const remaining = SEARCH_TEXT_MAX_CHARS - structured.length - separator.length;
|
|
101
|
+
if (fields.content.length > remaining) {
|
|
102
|
+
warnVerbose(`${entry.ref ?? entry.name}: search text truncated to ${SEARCH_TEXT_MAX_CHARS} chars`);
|
|
103
|
+
}
|
|
89
104
|
return `${structured}${separator}${truncateUnicodeSafe(fields.content, remaining)}`;
|
|
90
105
|
}
|
|
91
106
|
function truncateUnicodeSafe(text, maxChars) {
|
|
@@ -1,35 +1,10 @@
|
|
|
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
|
-
/**
|
|
5
|
-
* Shared agent-command-builder types and helpers (#563).
|
|
6
|
-
*
|
|
7
|
-
* Extracted from `agent/builders.ts` so per-harness builders (e.g.
|
|
8
|
-
* `harnesses/claude/agent-builder.ts`) can depend on the common
|
|
9
|
-
* types/validation WITHOUT creating an import cycle back through
|
|
10
|
-
* `builders.ts` (which imports the per-harness builders into its registry).
|
|
11
|
-
* This module is a dependency-graph LEAF for the builder subsystem.
|
|
12
|
-
*
|
|
13
|
-
* Behaviour-preserving: the type shapes and helper bodies are unchanged from
|
|
14
|
-
* their previous home in `builders.ts`.
|
|
15
|
-
*/
|
|
16
|
-
import { UsageError } from "../../core/errors.js";
|
|
17
4
|
/** Models reaching a harness have already crossed the single model-map boundary. */
|
|
18
5
|
export function resolveDispatchModel(request, _profile, _platform) {
|
|
19
6
|
return request.model;
|
|
20
7
|
}
|
|
21
|
-
/**
|
|
22
|
-
* Guard against values that start with `--`, which would be mis-interpreted as
|
|
23
|
-
* CLI flags by the spawned process when used as flag values (model, systemPrompt).
|
|
24
|
-
* Bun.spawn uses array argv so there is no shell injection, but a `--`-prefixed
|
|
25
|
-
* value passed as the argument to `--model` or `--system-prompt` can still
|
|
26
|
-
* confuse the CLI parser of the target process.
|
|
27
|
-
*/
|
|
28
|
-
export function assertNotFlag(value, field) {
|
|
29
|
-
if (value?.trimStart().startsWith("--")) {
|
|
30
|
-
throw new UsageError(`${field} must not start with "--": ${JSON.stringify(value.slice(0, 60))}`, "INVALID_FLAG_VALUE");
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
8
|
/**
|
|
34
9
|
* Normalize a toolPolicy value to a comma-separated string suitable for a
|
|
35
10
|
* CLI flag. Structured policy objects are JSON-serialized.
|
|
@@ -5,7 +5,7 @@ import { randomBytes } from "node:crypto";
|
|
|
5
5
|
import fs from "node:fs";
|
|
6
6
|
import path from "node:path";
|
|
7
7
|
import { fileURLToPath } from "node:url";
|
|
8
|
-
import {
|
|
8
|
+
import { writeFileAtomic } from "../../core/common.js";
|
|
9
9
|
import { ENGINE_NAME_PATTERN_SOURCE } from "../../core/config/engine-semantics.js";
|
|
10
10
|
import { ConfigError, UsageError } from "../../core/errors.js";
|
|
11
11
|
import { getConfigDir } from "../../core/paths.js";
|
|
@@ -21,9 +21,6 @@ import { cloneExecutionJsonObject } from "../../execution/json.js";
|
|
|
21
21
|
* provider mappings.
|
|
22
22
|
*/
|
|
23
23
|
export const MODEL_MAP_VERSION = 1;
|
|
24
|
-
export const MODEL_MAP_MAX_BYTES = MAX_CONFIG_FILE_BYTES;
|
|
25
|
-
export const MODEL_MAP_MAX_DEPTH = 64;
|
|
26
|
-
export const MODEL_MAP_MAX_NODES = 100_000;
|
|
27
24
|
let standaloneInstalledModelMapText;
|
|
28
25
|
const ENGINE_KEY_PATTERN = new RegExp(ENGINE_NAME_PATTERN_SOURCE);
|
|
29
26
|
const ALIAS_KEY_PATTERN = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
|
|
@@ -92,62 +89,8 @@ function parseProfileLayer(value, source, jsonPath) {
|
|
|
92
89
|
}
|
|
93
90
|
return Object.freeze(out);
|
|
94
91
|
}
|
|
95
|
-
/**
|
|
96
|
-
* Bound nesting before JSON.parse or any recursive durable-JSON clone runs.
|
|
97
|
-
* Brackets inside strings are ignored, including escaped quote sequences.
|
|
98
|
-
*/
|
|
99
|
-
function assertJsonDepthBudget(text, source) {
|
|
100
|
-
let depth = 0;
|
|
101
|
-
let inString = false;
|
|
102
|
-
let escaped = false;
|
|
103
|
-
for (const character of text) {
|
|
104
|
-
if (inString) {
|
|
105
|
-
if (escaped)
|
|
106
|
-
escaped = false;
|
|
107
|
-
else if (character === "\\")
|
|
108
|
-
escaped = true;
|
|
109
|
-
else if (character === '"')
|
|
110
|
-
inString = false;
|
|
111
|
-
continue;
|
|
112
|
-
}
|
|
113
|
-
if (character === '"') {
|
|
114
|
-
inString = true;
|
|
115
|
-
continue;
|
|
116
|
-
}
|
|
117
|
-
if (character === "{" || character === "[") {
|
|
118
|
-
depth += 1;
|
|
119
|
-
if (depth > MODEL_MAP_MAX_DEPTH) {
|
|
120
|
-
invalid(source, "$", `JSON nesting exceeds the ${MODEL_MAP_MAX_DEPTH}-level limit`);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
else if (character === "}" || character === "]") {
|
|
124
|
-
depth -= 1;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
/** Iterative node budget, deliberately completed before recursive inference cloning. */
|
|
129
|
-
function assertJsonNodeBudget(value, source) {
|
|
130
|
-
const pending = [value];
|
|
131
|
-
let count = 0;
|
|
132
|
-
while (pending.length > 0) {
|
|
133
|
-
const current = pending.pop();
|
|
134
|
-
count += 1;
|
|
135
|
-
if (count > MODEL_MAP_MAX_NODES) {
|
|
136
|
-
invalid(source, "$", `JSON value exceeds the ${MODEL_MAP_MAX_NODES}-node limit`);
|
|
137
|
-
}
|
|
138
|
-
if (current !== null && typeof current === "object") {
|
|
139
|
-
const children = Array.isArray(current) ? current : Object.values(current);
|
|
140
|
-
for (const child of children)
|
|
141
|
-
pending.push(child);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
92
|
/** Parse one installed or user layer. Partial structured profiles are valid at this stage. */
|
|
146
93
|
export function parseModelMapLayer(text, source) {
|
|
147
|
-
if (Buffer.byteLength(text, "utf8") > MODEL_MAP_MAX_BYTES) {
|
|
148
|
-
invalid(source, "$", `document exceeds the ${MODEL_MAP_MAX_BYTES}-byte limit`);
|
|
149
|
-
}
|
|
150
|
-
assertJsonDepthBudget(text, source);
|
|
151
94
|
let parsed;
|
|
152
95
|
try {
|
|
153
96
|
parsed = JSON.parse(text);
|
|
@@ -155,7 +98,6 @@ export function parseModelMapLayer(text, source) {
|
|
|
155
98
|
catch {
|
|
156
99
|
invalid(source, "$", "invalid JSON syntax");
|
|
157
100
|
}
|
|
158
|
-
assertJsonNodeBudget(parsed, source);
|
|
159
101
|
const root = requireRecord(parsed, source, "$");
|
|
160
102
|
assertOnlyKeys(root, ["version", "aliases"], source, "$");
|
|
161
103
|
if (root.version !== MODEL_MAP_VERSION) {
|
|
@@ -314,7 +256,7 @@ function readModelMapFile(filePath, label, optional) {
|
|
|
314
256
|
if (!sameFileIdentity(linkStat, openedStat)) {
|
|
315
257
|
throw new ConfigError(`${label} changed while it was being opened: ${filePath}.`, "INVALID_CONFIG_FILE", "Retry after ensuring no other process is replacing models.json.");
|
|
316
258
|
}
|
|
317
|
-
const text =
|
|
259
|
+
const text = fs.readFileSync(fd, "utf8");
|
|
318
260
|
fs.closeSync(fd);
|
|
319
261
|
fd = undefined;
|
|
320
262
|
return text;
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
* name without any further wiring. The registry entry also declares
|
|
68
68
|
* `structuredOutput: "none"` alongside it (`./index.ts`).
|
|
69
69
|
*/
|
|
70
|
-
import {
|
|
70
|
+
import { resolveDispatchModel } from "../../agent/builder-shared.js";
|
|
71
71
|
import { createAgentRequestLowerer } from "../../agent/request-lowering.js";
|
|
72
72
|
/** Canonical harness/platform id used for model-alias resolution. */
|
|
73
73
|
export const AIDER_PLATFORM = "aider";
|
|
@@ -103,8 +103,6 @@ export const aiderBuilder = {
|
|
|
103
103
|
outputSchema: true,
|
|
104
104
|
}),
|
|
105
105
|
build(profile, req) {
|
|
106
|
-
assertNotFlag(req.systemPrompt, "systemPrompt");
|
|
107
|
-
assertNotFlag(req.model, "model");
|
|
108
106
|
const args = [...profile.args];
|
|
109
107
|
if (req.model) {
|
|
110
108
|
const resolved = resolveDispatchModel(req, profile, AIDER_PLATFORM);
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
* - **systemPrompt** — `q chat` has no system-prompt flag (persona/context
|
|
33
33
|
* comes from Q's own agent config files), so the system prompt is folded
|
|
34
34
|
* into the positional payload ahead of the task prompt, separated by a
|
|
35
|
-
* blank line.
|
|
35
|
+
* blank line.
|
|
36
36
|
* - **schema** — the matrix places Q in the NO-structured-output tier
|
|
37
37
|
* ("via prompt+validate": *(none documented)* — there is no `--json` or
|
|
38
38
|
* `--output-format` to ask for). The JSON Schema is therefore passed
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
* pattern `local-runner`, structuredOutput `none` — is declared alongside it
|
|
63
63
|
* (`./index.ts`).
|
|
64
64
|
*/
|
|
65
|
-
import {
|
|
65
|
+
import { resolveDispatchModel } from "../../agent/builder-shared.js";
|
|
66
66
|
import { createAgentRequestLowerer } from "../../agent/request-lowering.js";
|
|
67
67
|
/** Canonical harness/platform id used for model-alias resolution. */
|
|
68
68
|
export const AMAZONQ_PLATFORM = "amazonq";
|
|
@@ -116,8 +116,6 @@ export const amazonqBuilder = {
|
|
|
116
116
|
outputSchema: true,
|
|
117
117
|
}),
|
|
118
118
|
build(profile, req) {
|
|
119
|
-
assertNotFlag(req.systemPrompt, "systemPrompt");
|
|
120
|
-
assertNotFlag(req.model, "model");
|
|
121
119
|
// Built-in q profiles would ship `args: []`; headless dispatch is the
|
|
122
120
|
// `chat` subcommand. Don't double it when a user profile already pins it.
|
|
123
121
|
const extra = profile.args[0] === "chat" ? profile.args.slice(1) : [...profile.args];
|
|
@@ -129,9 +127,6 @@ export const amazonqBuilder = {
|
|
|
129
127
|
// flags: dropping a restriction must never widen to --trust-all-tools.
|
|
130
128
|
const entries = toolPolicyEntries(req.tools);
|
|
131
129
|
if (entries !== undefined) {
|
|
132
|
-
for (const tool of entries) {
|
|
133
|
-
assertNotFlag(tool, "tools entry");
|
|
134
|
-
}
|
|
135
130
|
// Q's documented allowlist form is equals-joined and comma-separated
|
|
136
131
|
// (`--trust-tools=fs_read,fs_write`); an empty list trusts no tools.
|
|
137
132
|
args.push(`--trust-tools=${entries.join(",")}`);
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
*
|
|
35
35
|
* The builder's `platform` stays `'claude'` (the canonical harness id).
|
|
36
36
|
*/
|
|
37
|
-
import {
|
|
37
|
+
import { normalizeTools, resolveDispatchModel, } from "../../agent/builder-shared.js";
|
|
38
38
|
import { createAgentRequestLowerer } from "../../agent/request-lowering.js";
|
|
39
39
|
/**
|
|
40
40
|
* Assemble the positional prompt: the task prompt and — when a schema is
|
|
@@ -68,9 +68,6 @@ export const claudeBuilder = {
|
|
|
68
68
|
outputSchema: true,
|
|
69
69
|
}),
|
|
70
70
|
build(profile, req) {
|
|
71
|
-
assertNotFlag(req.systemPrompt, "systemPrompt");
|
|
72
|
-
assertNotFlag(req.model, "model");
|
|
73
|
-
assertNotFlag(req.agent, "agent");
|
|
74
71
|
const args = [...profile.args];
|
|
75
72
|
if (req.agent) {
|
|
76
73
|
args.push("--agent", req.agent);
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
import { mkdtempSync, writeFileSync } from "node:fs";
|
|
56
56
|
import { tmpdir } from "node:os";
|
|
57
57
|
import { join } from "node:path";
|
|
58
|
-
import {
|
|
58
|
+
import { resolveDispatchModel } from "../../agent/builder-shared.js";
|
|
59
59
|
import { createAgentRequestLowerer } from "../../agent/request-lowering.js";
|
|
60
60
|
/**
|
|
61
61
|
* Write a node's JSON Schema to a fresh temp file for `--output-schema`.
|
|
@@ -77,7 +77,6 @@ export function writeCodexOutputSchemaFile(schema) {
|
|
|
77
77
|
* extractor); akm never depends on it (plan §"Session, MCP, and identity").
|
|
78
78
|
*/
|
|
79
79
|
export function codexResumeArgs(sessionId) {
|
|
80
|
-
assertNotFlag(sessionId, "sessionId");
|
|
81
80
|
return ["exec", "resume", sessionId];
|
|
82
81
|
}
|
|
83
82
|
/**
|
|
@@ -114,8 +113,6 @@ export const codexBuilder = {
|
|
|
114
113
|
outputSchema: true,
|
|
115
114
|
}),
|
|
116
115
|
build(profile, req) {
|
|
117
|
-
assertNotFlag(req.systemPrompt, "systemPrompt");
|
|
118
|
-
assertNotFlag(req.model, "model");
|
|
119
116
|
// Built-in codex profiles ship `args: []`; headless dispatch is the `exec`
|
|
120
117
|
// subcommand. Don't double it when a user profile already pins it.
|
|
121
118
|
const extra = profile.args[0] === "exec" ? profile.args.slice(1) : [...profile.args];
|
|
@@ -21,8 +21,7 @@
|
|
|
21
21
|
* - **systemPrompt** — Copilot CLI has no system-prompt flag (it reads
|
|
22
22
|
* repo/user custom-instructions files instead), so the system prompt is
|
|
23
23
|
* folded into the `-p` payload ahead of the task prompt, separated by a
|
|
24
|
-
* blank line.
|
|
25
|
-
* prompt cannot turn the front of the `-p` value into a flag.
|
|
24
|
+
* blank line.
|
|
26
25
|
* - **schema** — the matrix places Copilot in the "via prompt+validate" tier
|
|
27
26
|
* (no native `--output-schema` equivalent, unlike Codex), so the JSON
|
|
28
27
|
* Schema is passed through the prompt: a directive matching the engine's
|
|
@@ -45,7 +44,7 @@
|
|
|
45
44
|
* that registry, so this builder is reachable under the `"copilot"` platform
|
|
46
45
|
* name without any further wiring.
|
|
47
46
|
*/
|
|
48
|
-
import {
|
|
47
|
+
import { resolveDispatchModel } from "../../agent/builder-shared.js";
|
|
49
48
|
import { createAgentRequestLowerer } from "../../agent/request-lowering.js";
|
|
50
49
|
/** Canonical harness/platform id used for model-alias resolution. */
|
|
51
50
|
export const COPILOT_PLATFORM = "copilot";
|
|
@@ -98,8 +97,6 @@ export const copilotBuilder = {
|
|
|
98
97
|
outputSchema: true,
|
|
99
98
|
}),
|
|
100
99
|
build(profile, req) {
|
|
101
|
-
assertNotFlag(req.systemPrompt, "systemPrompt");
|
|
102
|
-
assertNotFlag(req.model, "model");
|
|
103
100
|
const args = [...profile.args];
|
|
104
101
|
if (req.model) {
|
|
105
102
|
const resolved = resolveDispatchModel(req, profile, COPILOT_PLATFORM);
|
|
@@ -110,7 +107,6 @@ export const copilotBuilder = {
|
|
|
110
107
|
// Structured policy objects (entries === undefined) emit NO allow flags:
|
|
111
108
|
// dropping a restriction must never widen to --allow-all-tools.
|
|
112
109
|
for (const tool of entries ?? []) {
|
|
113
|
-
assertNotFlag(tool, "tools entry");
|
|
114
110
|
args.push("--allow-tool", tool);
|
|
115
111
|
}
|
|
116
112
|
}
|
|
@@ -23,9 +23,7 @@
|
|
|
23
23
|
* - **systemPrompt** — Gemini CLI has no system-prompt flag in headless mode
|
|
24
24
|
* (system text comes from `GEMINI.md` context files / `GEMINI_SYSTEM_MD`),
|
|
25
25
|
* so the system prompt is folded into the `-p` payload ahead of the task
|
|
26
|
-
* prompt, separated by a blank line.
|
|
27
|
-
* `--`-prefixed system prompt cannot turn the front of the `-p` value into
|
|
28
|
-
* a flag.
|
|
26
|
+
* prompt, separated by a blank line.
|
|
29
27
|
* - **schema** — the matrix places Gemini in the "via prompt+validate" tier
|
|
30
28
|
* (no native `--output-schema` equivalent, unlike Codex — so no temp-file
|
|
31
29
|
* plumbing here), so the JSON Schema is passed through the prompt: a
|
|
@@ -49,7 +47,7 @@
|
|
|
49
47
|
* that registry, so this builder is reachable under the `"gemini"` platform
|
|
50
48
|
* name without any further wiring.
|
|
51
49
|
*/
|
|
52
|
-
import {
|
|
50
|
+
import { resolveDispatchModel } from "../../agent/builder-shared.js";
|
|
53
51
|
import { createAgentRequestLowerer } from "../../agent/request-lowering.js";
|
|
54
52
|
/** Canonical harness/platform id used for model-alias resolution. */
|
|
55
53
|
export const GEMINI_PLATFORM = "gemini";
|
|
@@ -102,8 +100,6 @@ export const geminiBuilder = {
|
|
|
102
100
|
outputSchema: true,
|
|
103
101
|
}),
|
|
104
102
|
build(profile, req) {
|
|
105
|
-
assertNotFlag(req.systemPrompt, "systemPrompt");
|
|
106
|
-
assertNotFlag(req.model, "model");
|
|
107
103
|
const args = [...profile.args];
|
|
108
104
|
if (req.model) {
|
|
109
105
|
const resolved = resolveDispatchModel(req, profile, GEMINI_PLATFORM);
|
|
@@ -113,7 +109,6 @@ export const geminiBuilder = {
|
|
|
113
109
|
// Structured policy objects (entries === undefined) emit NO flags:
|
|
114
110
|
// dropping a restriction must never widen to auto-approval.
|
|
115
111
|
for (const tool of toolPolicyEntries(req.tools) ?? []) {
|
|
116
|
-
assertNotFlag(tool, "tools entry");
|
|
117
112
|
args.push("--allowed-tools", tool);
|
|
118
113
|
}
|
|
119
114
|
}
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* pre-migration `opencodeBuilder`. The builder's `platform` stays `'opencode'`
|
|
15
15
|
* (the canonical harness id).
|
|
16
16
|
*/
|
|
17
|
-
import {
|
|
17
|
+
import { resolveDispatchModel } from "../../agent/builder-shared.js";
|
|
18
18
|
import { createAgentRequestLowerer } from "../../agent/request-lowering.js";
|
|
19
19
|
/**
|
|
20
20
|
* OpenCode builder.
|
|
@@ -34,9 +34,6 @@ export const opencodeBuilder = {
|
|
|
34
34
|
outputSchema: false,
|
|
35
35
|
}),
|
|
36
36
|
build(profile, req) {
|
|
37
|
-
assertNotFlag(req.systemPrompt, "systemPrompt");
|
|
38
|
-
assertNotFlag(req.model, "model");
|
|
39
|
-
assertNotFlag(req.agent, "agent");
|
|
40
37
|
const args = req.model ? [] : [...profile.args];
|
|
41
38
|
if (req.model) {
|
|
42
39
|
for (let index = 0; index < profile.args.length; index += 1) {
|
|
@@ -92,6 +92,7 @@
|
|
|
92
92
|
*/
|
|
93
93
|
import { spawn } from "node:child_process";
|
|
94
94
|
import { createHash } from "node:crypto";
|
|
95
|
+
import { COMMON_SPAWN_ENV_PASSTHROUGH, spawnEnvNamesFor } from "../../../core/spawn-env.js";
|
|
95
96
|
import { DEFAULT_AGENT_TIMEOUT_MS } from "../../agent/config.js";
|
|
96
97
|
// Server registry — one server per complete server-material signature. Caller
|
|
97
98
|
// deadlines race the shared promise independently; they never become startup
|
|
@@ -269,24 +270,9 @@ function serverRegistryKey(profile, env) {
|
|
|
269
270
|
.update(JSON.stringify(canonicalize(material)))
|
|
270
271
|
.digest("hex");
|
|
271
272
|
}
|
|
272
|
-
const OPENCODE_SDK_SERVER_ENV_NAMES = [
|
|
273
|
-
"HOME",
|
|
274
|
-
"PATH",
|
|
275
|
-
"USER",
|
|
276
|
-
"LANG",
|
|
277
|
-
"LC_ALL",
|
|
278
|
-
"TERM",
|
|
279
|
-
"TMPDIR",
|
|
280
|
-
"SYSTEMROOT",
|
|
281
|
-
"COMSPEC",
|
|
282
|
-
"PATHEXT",
|
|
283
|
-
"WINDIR",
|
|
284
|
-
"TEMP",
|
|
285
|
-
"TMP",
|
|
286
|
-
];
|
|
287
273
|
/** @internal Exact environment allowlist used to start the OpenCode SDK server. */
|
|
288
274
|
export function opencodeSdkServerEnvironmentNames(profile) {
|
|
289
|
-
return [...new Set([...
|
|
275
|
+
return [...new Set([...spawnEnvNamesFor(COMMON_SPAWN_ENV_PASSTHROUGH), ...(profile.envPassthrough ?? [])])];
|
|
290
276
|
}
|
|
291
277
|
function buildServerEnv(profile, config, bindings, envSource) {
|
|
292
278
|
const env = {};
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
* `pattern: "local-runner"`, `structuredOutput: "native-json"` alongside it
|
|
72
72
|
* (`./index.ts`).
|
|
73
73
|
*/
|
|
74
|
-
import {
|
|
74
|
+
import { resolveDispatchModel } from "../../agent/builder-shared.js";
|
|
75
75
|
import { createAgentRequestLowerer } from "../../agent/request-lowering.js";
|
|
76
76
|
/** Canonical harness/platform id used for model-alias resolution. */
|
|
77
77
|
export const OPENHANDS_PLATFORM = "openhands";
|
|
@@ -115,8 +115,6 @@ export const openhandsBuilder = {
|
|
|
115
115
|
outputSchema: true,
|
|
116
116
|
}),
|
|
117
117
|
build(profile, req) {
|
|
118
|
-
assertNotFlag(req.systemPrompt, "systemPrompt");
|
|
119
|
-
assertNotFlag(req.model, "model");
|
|
120
118
|
const args = [...profile.args];
|
|
121
119
|
// Headless essentials (matrix shape): non-interactive run, JSONL stdout
|
|
122
120
|
// for the extractor.
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
* builders, so a prompt whose text begins with `-`/`--` can never be parsed
|
|
26
26
|
* as flags.
|
|
27
27
|
* - **systemPrompt** — passed via `--system-prompt` (Pi follows the Claude
|
|
28
|
-
* Code flag conventions)
|
|
28
|
+
* Code flag conventions).
|
|
29
29
|
* - **schema** — the matrix places Pi in the "via prompt+validate" tier (no
|
|
30
30
|
* native `--output-schema` equivalent, unlike Codex), so the JSON Schema is
|
|
31
31
|
* passed through the prompt: a directive matching the engine's wording
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
* wiring. The `PI_SESSION_ID` identity-env marker is declared alongside it
|
|
51
51
|
* (`./index.ts`).
|
|
52
52
|
*/
|
|
53
|
-
import {
|
|
53
|
+
import { resolveDispatchModel } from "../../agent/builder-shared.js";
|
|
54
54
|
import { createAgentRequestLowerer } from "../../agent/request-lowering.js";
|
|
55
55
|
/** Canonical harness/platform id used for model-alias resolution. */
|
|
56
56
|
export const PI_PLATFORM = "pi";
|
|
@@ -81,8 +81,6 @@ export const piBuilder = {
|
|
|
81
81
|
outputSchema: true,
|
|
82
82
|
}),
|
|
83
83
|
build(profile, req) {
|
|
84
|
-
assertNotFlag(req.systemPrompt, "systemPrompt");
|
|
85
|
-
assertNotFlag(req.model, "model");
|
|
86
84
|
const args = [...profile.args];
|
|
87
85
|
if (req.systemPrompt) {
|
|
88
86
|
args.push("--system-prompt", req.systemPrompt);
|
|
@@ -133,12 +133,3 @@ export function collectSessionEvents(harnesses, sinceMs, maxSessionsPerHarness =
|
|
|
133
133
|
}
|
|
134
134
|
return events;
|
|
135
135
|
}
|
|
136
|
-
/**
|
|
137
|
-
* Scan recent session logs from all available harnesses and return
|
|
138
|
-
* repeated failure patterns that might warrant new AKM assets.
|
|
139
|
-
*/
|
|
140
|
-
export function getExecutionLogCandidates(sinceDays = 7) {
|
|
141
|
-
const sinceMs = Date.now() - sinceDays * 24 * 60 * 60 * 1000;
|
|
142
|
-
const events = collectSessionEvents(getAvailableHarnesses(), sinceMs);
|
|
143
|
-
return aggregateSessionEvents(events);
|
|
144
|
-
}
|