@sema-agent/server 7.131.0 → 7.132.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/MIGRATION.md +309 -0
- package/README.md +5 -1
- package/README.zh-CN.md +3 -1
- package/USAGE.md +163 -54
- package/dist/approval-card.d.ts +3 -1
- package/dist/approval-card.js +2 -3
- package/dist/audit.d.ts +7 -10
- package/dist/auth-bridge.d.ts +4 -0
- package/dist/auth-bridge.js +10 -11
- package/dist/boot/deployment-mods.d.ts +31 -0
- package/dist/boot/deployment-mods.js +26 -0
- package/dist/boot/execution-env.d.ts +1 -1
- package/dist/boot/execution-env.js +19 -6
- package/dist/boot/memory-boundary.d.ts +2 -2
- package/dist/boot/read-deny-anchor-audit.d.ts +17 -0
- package/dist/boot/read-deny-anchor-audit.js +36 -0
- package/dist/boot/resolve-spec.d.ts +1 -5
- package/dist/boot/resolve-spec.js +19 -47
- package/dist/boot/runner-deps.d.ts +19 -8
- package/dist/boot/runner-deps.js +14 -2
- package/dist/boot/session-faces.d.ts +1 -7
- package/dist/boot/stage-03-store-backend.d.ts +1 -1
- package/dist/boot/stage-03-store-backend.js +2 -2
- package/dist/boot/stage-04-stores.d.ts +1 -1
- package/dist/boot/stage-05-execution-env.d.ts +4 -4
- package/dist/boot/stage-05-execution-env.js +7 -10
- package/dist/boot/stage-06-runners.d.ts +2 -2
- package/dist/boot/stage-06-runners.js +5 -4
- package/dist/boot/stage-07-capability-layer.d.ts +2 -2
- package/dist/boot/stage-07-capability-layer.js +3 -3
- package/dist/boot/stage-08-reapers.d.ts +2 -2
- package/dist/boot/stage-09-leader.d.ts +3 -9
- package/dist/boot/stage-10-http-server.d.ts +3 -9
- package/dist/boot/stage-10-http-server.js +6 -7
- package/dist/boot/stores.d.ts +1 -1
- package/dist/boot/stores.js +5 -6
- package/dist/boot/web-admin.d.ts +0 -3
- package/dist/boot/web-admin.js +35 -35
- package/dist/brain.js +17 -22
- package/dist/budget.js +5 -4
- package/dist/caller-text-echo.d.ts +20 -0
- package/dist/caller-text-echo.js +24 -0
- package/dist/capabilities/brand-identity.d.ts +26 -0
- package/dist/capabilities/brand-identity.js +27 -0
- package/dist/capabilities/center-plugins.js +1 -1
- package/dist/capabilities/center-prompts.d.ts +32 -59
- package/dist/capabilities/center-prompts.js +18 -32
- package/dist/capabilities/engine-capabilities.js +2 -1
- package/dist/capabilities/hands-lane.d.ts +9 -6
- package/dist/capabilities/hands-lane.js +1 -1
- package/dist/capabilities/mcp-probe.d.ts +14 -1
- package/dist/capabilities/mcp-probe.js +22 -133
- package/dist/capabilities/scenarios.d.ts +34 -40
- package/dist/capabilities/scenarios.js +16 -33
- package/dist/capabilities/skills.d.ts +19 -4
- package/dist/capabilities/skills.js +30 -10
- package/dist/config-catalog.js +6 -6
- package/dist/config-lkg.d.ts +9 -9
- package/dist/config-lkg.js +20 -4
- package/dist/config-provider.d.ts +3 -1
- package/dist/config-provider.js +12 -4
- package/dist/config-types.d.ts +7 -9
- package/dist/config.js +17 -4
- package/dist/device-ws-protocol.d.ts +1 -1
- package/dist/device-ws-protocol.js +1 -0
- package/dist/env-name-allowlist-knobs.d.ts +12 -2
- package/dist/env-name-allowlist-knobs.js +5 -4
- package/dist/exec-bounds.d.ts +15 -3
- package/dist/exec-bounds.js +4 -0
- package/dist/execution-lane-caps.d.ts +9 -2
- package/dist/execution-lane-caps.js +11 -0
- package/dist/hooks/classic-stations.d.ts +86 -0
- package/dist/hooks/classic-stations.js +27 -0
- package/dist/hooks/hook-llm.d.ts +8 -5
- package/dist/hooks/hook-llm.js +78 -35
- package/dist/hooks/hook-runner.d.ts +232 -80
- package/dist/hooks/hook-runner.js +218 -312
- package/dist/http/admission.d.ts +8 -2
- package/dist/http/admission.js +101 -57
- package/dist/http/approval-sweeps.js +57 -16
- package/dist/http/checkpoint-ctx.d.ts +25 -8
- package/dist/http/checkpoint-ctx.js +11 -7
- package/dist/http/claimed-run.d.ts +13 -0
- package/dist/http/claimed-run.js +15 -0
- package/dist/http/device-placement.js +5 -10
- package/dist/http/dispatch.d.ts +0 -4
- package/dist/http/dispatch.js +5 -9
- package/dist/http/durable-run-leg.d.ts +2 -1
- package/dist/http/durable-run-leg.js +5 -3
- package/dist/http/health-self-report.d.ts +7 -5
- package/dist/http/health-self-report.js +4 -18
- package/dist/http/principal-gate.d.ts +23 -6
- package/dist/http/principal-gate.js +24 -5
- package/dist/http/refusal-body.d.ts +21 -0
- package/dist/http/refusal-body.js +4 -0
- package/dist/http/request-guards.d.ts +27 -0
- package/dist/http/request-guards.js +24 -3
- package/dist/http/resume-legs.d.ts +25 -0
- package/dist/http/resume-legs.js +43 -22
- package/dist/http/routes/capabilities.js +1 -1
- package/dist/http/routes/diagnostics.js +1 -1
- package/dist/http/routes/rules.js +2 -2
- package/dist/http/routes/runs.js +7 -7
- package/dist/http/routes/session-sync.js +4 -2
- package/dist/http/routes/sessions.js +1 -1
- package/dist/http/routes/shared-memory.js +2 -13
- package/dist/http/routes/side-query.js +2 -3
- package/dist/http/routes/tasks.js +19 -9
- package/dist/http/send.d.ts +9 -7
- package/dist/http/send.js +7 -2
- package/dist/http/server.d.ts +21 -11
- package/dist/http/server.js +28 -2
- package/dist/http/submit-ctx.d.ts +25 -0
- package/dist/http/submit-ctx.js +39 -0
- package/dist/http/wire-types.d.ts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/lane-home-probe.d.ts +43 -0
- package/dist/lane-home-probe.js +35 -0
- package/dist/limit-refusal.d.ts +47 -0
- package/dist/limit-refusal.js +12 -0
- package/dist/main.js +1 -1
- package/dist/mcp-assertion-header.d.ts +1 -9
- package/dist/mcp-assertion-header.js +0 -6
- package/dist/mcp-tool-faces.d.ts +5 -0
- package/dist/mcp-tool-faces.js +5 -1
- package/dist/memory-scope.d.ts +1 -1
- package/dist/model-provider.d.ts +39 -12
- package/dist/model-provider.js +19 -2
- package/dist/model-route-endpoint.d.ts +1 -1
- package/dist/model-route-endpoint.js +5 -5
- package/dist/observability/cost-taxonomy.d.ts +7 -7
- package/dist/observability/fail-open.d.ts +42 -6
- package/dist/observability/fail-open.js +42 -6
- package/dist/observability/metrics.js +3 -1
- package/dist/observability/prompt-manifest.d.ts +47 -82
- package/dist/observability/prompt-manifest.js +119 -17
- package/dist/observability/run-terminal.js +14 -6
- package/dist/observability/secret-env-scrub.d.ts +13 -1
- package/dist/observability/secret-env-scrub.js +13 -1
- package/dist/observability/tool-trace.d.ts +16 -21
- package/dist/observability/tool-trace.js +51 -42
- package/dist/per-task-image.d.ts +7 -1
- package/dist/per-task-image.js +3 -3
- package/dist/plain-string-record.d.ts +25 -0
- package/dist/plain-string-record.js +32 -0
- package/dist/plugins/blob-backend.d.ts +68 -13
- package/dist/plugins/blob-backend.js +53 -10
- package/dist/plugins/checkpoint-store-sql.d.ts +14 -4
- package/dist/plugins/checkpoint-store-sql.js +39 -26
- package/dist/plugins/k8s-bg-scripts.d.ts +11 -0
- package/dist/plugins/k8s-bg-scripts.js +22 -0
- package/dist/plugins/local-checkpoint-store.js +5 -2
- package/dist/plugins/local-session-store.js +1 -1
- package/dist/plugins/one-time-migrations.d.ts +137 -90
- package/dist/plugins/one-time-migrations.js +356 -207
- package/dist/plugins/permission-rule-store-sql.d.ts +13 -7
- package/dist/plugins/permission-rule-store-sql.js +4 -18
- package/dist/plugins/pg-session-storage.d.ts +4 -5
- package/dist/plugins/pg-session-storage.js +7 -17
- package/dist/plugins/remote-env-adb.d.ts +6 -0
- package/dist/plugins/remote-env-adb.js +9 -4
- package/dist/plugins/remote-env-device.js +3 -0
- package/dist/plugins/remote-env-e2b.d.ts +1 -1
- package/dist/plugins/remote-env-e2b.js +21 -9
- package/dist/plugins/remote-env-host.d.ts +9 -9
- package/dist/plugins/remote-env-host.js +10 -32
- package/dist/plugins/remote-env-k8s.d.ts +95 -26
- package/dist/plugins/remote-env-k8s.js +265 -90
- package/dist/plugins/remote-env-local-docker.d.ts +20 -1
- package/dist/plugins/remote-env-local-docker.js +77 -9
- package/dist/plugins/remote-env-ssh.d.ts +15 -0
- package/dist/plugins/remote-env-ssh.js +109 -3
- package/dist/plugins/remote-shell.d.ts +0 -1
- package/dist/plugins/remote-shell.js +1 -2
- package/dist/plugins/retention-store-sql.js +6 -2
- package/dist/plugins/schema-consistency.d.ts +54 -0
- package/dist/plugins/schema-consistency.js +52 -0
- package/dist/plugins/session-epoch-anchor.d.ts +13 -0
- package/dist/plugins/session-epoch-anchor.js +23 -0
- package/dist/plugins/shared-memory-store-sql.d.ts +9 -3
- package/dist/plugins/shared-memory-store-sql.js +5 -16
- package/dist/plugins/sql-driver.d.ts +141 -0
- package/dist/plugins/sql-driver.js +115 -1
- package/dist/plugins/sql-errors.d.ts +41 -0
- package/dist/plugins/sql-errors.js +36 -0
- package/dist/plugins/store-backend.js +2 -1
- package/dist/plugins/tidb-session-storage.d.ts +7 -11
- package/dist/plugins/tidb-session-storage.js +6 -16
- package/dist/plugins/tidb-session-store.js +1 -1
- package/dist/prompts-domain-validate.d.ts +17 -61
- package/dist/prompts-domain-validate.js +9 -119
- package/dist/request-key-closure.d.ts +2 -2
- package/dist/request-key-closure.js +2 -4
- package/dist/rule-entry-list.d.ts +12 -9
- package/dist/rule-entry-list.js +37 -21
- package/dist/run-local.js +19 -19
- package/dist/runs.d.ts +6 -0
- package/dist/runs.js +16 -0
- package/dist/server-secret-env.d.ts +44 -18
- package/dist/server-secret-env.js +49 -8
- package/dist/session-incarnation.d.ts +15 -5
- package/dist/session-incarnation.js +16 -9
- package/dist/session-titler.js +12 -2
- package/dist/spec-fields.d.ts +28 -16
- package/dist/spec-fields.js +46 -53
- package/dist/sql-engine-posture.d.ts +29 -4
- package/dist/sql-engine-posture.js +36 -1
- package/dist/stored-request-tool-axes-m19.d.ts +19 -4
- package/dist/stored-request-tool-axes-m19.js +30 -2
- package/dist/task-a2a.d.ts +9 -1
- package/dist/task-a2a.js +73 -47
- package/dist/task-mcp.d.ts +46 -58
- package/dist/task-mcp.js +99 -65
- package/dist/task-settings.d.ts +7 -21
- package/dist/task-settings.js +7 -36
- package/dist/text-bidi.d.ts +3 -46
- package/dist/text-bidi.js +3 -3
- package/dist/tool-approval.d.ts +1 -1
- package/dist/trace/core-keyset-guard.d.ts +24 -4
- package/dist/trace/engine-notice-wire.d.ts +11 -3
- package/dist/trace/engine-notice-wire.js +8 -1
- package/dist/trace/ledger-events.d.ts +3 -1
- package/dist/trace/ledger-sink.js +4 -1
- package/dist/trace/model-segment.js +1 -1
- package/dist/trace/project.d.ts +19 -6
- package/dist/trace/project.js +57 -22
- package/dist/trace/wire-projection-faces.d.ts +79 -1
- package/dist/trace/wire-projection-faces.js +22 -0
- package/dist/web-admin-client/candidate-gate.d.ts +6 -6
- package/dist/web-admin-client/candidate-gate.js +3 -3
- package/dist/web-admin-client/http-client.js +0 -6
- package/dist/web-admin-client/read-warnings.d.ts +13 -0
- package/dist/web-admin-client/read-warnings.js +10 -0
- package/dist/web-admin-client/skills-mcp.d.ts +3 -0
- package/dist/web-admin-client/skills-mcp.js +9 -6
- package/dist/web-admin-client/types.d.ts +2 -3
- package/dist/workspace-cache.d.ts +35 -0
- package/dist/workspace-cache.js +36 -0
- package/dist/workspace-space.d.ts +3 -2
- package/dist/workspace-space.js +2 -0
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +8 -1
- package/package.json +4 -4
- package/scripts/drain-check-local.mjs +34 -1
- package/scripts/drain-check.mysql.sql +30 -2
- package/scripts/drain-check.pg.sql +29 -2
- package/dist/capabilities/memory-notice.d.ts +0 -138
- package/dist/capabilities/memory-notice.js +0 -64
- package/dist/capabilities/prompt.d.ts +0 -17
- package/dist/capabilities/prompt.js +0 -6
- package/dist/mcp-content-origin.d.ts +0 -34
- package/dist/mcp-content-origin.js +0 -10
- package/dist/tool-axis-words.d.ts +0 -27
- package/dist/tool-axis-words.js +0 -9
- package/dist/wire-name-bound.d.ts +0 -14
- package/dist/wire-name-bound.js +0 -13
|
@@ -1,122 +1,12 @@
|
|
|
1
|
-
import { createHash } from "node:crypto";
|
|
2
|
-
import { createRequire } from "node:module";
|
|
3
|
-
import { readFileSync } from "node:fs";
|
|
4
|
-
import { dirname, join } from "node:path";
|
|
5
1
|
import { verifyPromptArtifact } from "@sema-agent/core";
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
return `${where}: bad id`;
|
|
16
|
-
if (o.id.startsWith("core/"))
|
|
17
|
-
return `${where}: id in the reserved core/ namespace`;
|
|
18
|
-
if (typeof o.slot !== "string" || !SLOTS.includes(o.slot))
|
|
19
|
-
return `${where}: bad slot`;
|
|
20
|
-
if (typeof o.text !== "string" || o.text.length === 0)
|
|
21
|
-
return `${where}: text must be a non-empty string`;
|
|
22
|
-
if (typeof o.contentHash !== "string" || !SHA256_DIGEST_RE.test(o.contentHash))
|
|
23
|
-
return `${where}: contentHash is required (sha256:<64hex> — the epoch declaration axis needs it for byte-level change detection)`;
|
|
24
|
-
const expected = `sha256:${createHash("sha256").update(o.text).digest("hex")}`;
|
|
25
|
-
if (o.contentHash !== expected)
|
|
26
|
-
return `${where}: contentHash does not match sha256(text) — stale or altered declaration`;
|
|
27
|
-
return undefined;
|
|
28
|
-
}
|
|
29
|
-
export function validateCenterPrompts(raw) {
|
|
30
|
-
if (raw === null || typeof raw !== "object")
|
|
31
|
-
return { ok: false, error: "prompts is not an object" };
|
|
32
|
-
const p = raw;
|
|
33
|
-
if (typeof p.packId !== "string" || !/^center:[0-9a-f]{12}$/.test(p.packId))
|
|
34
|
-
return { ok: false, error: "bad packId form (center:<digest12>)" };
|
|
35
|
-
if (typeof p.contentDigest !== "string" || !SHA256_DIGEST_RE.test(p.contentDigest))
|
|
36
|
-
return { ok: false, error: "bad contentDigest form" };
|
|
37
|
-
const arrayIssue = (decls, where) => {
|
|
38
|
-
if (!Array.isArray(decls))
|
|
39
|
-
return `${where} is not an array`;
|
|
40
|
-
if (decls.length === 0)
|
|
41
|
-
return `${where} is empty (an empty replacement set is not a v1 semantic — omit the key instead)`;
|
|
42
|
-
const seen = new Set();
|
|
43
|
-
for (let i = 0; i < decls.length; i++) {
|
|
44
|
-
const issue = declarationIssue(decls[i], `${where}[${i}]`);
|
|
45
|
-
if (issue)
|
|
46
|
-
return issue;
|
|
47
|
-
const id = decls[i].id;
|
|
48
|
-
if (seen.has(id))
|
|
49
|
-
return `${where}[${i}]: duplicate id "${id}" (core composer throws on duplicates)`;
|
|
50
|
-
seen.add(id);
|
|
51
|
-
}
|
|
52
|
-
return undefined;
|
|
53
|
-
};
|
|
54
|
-
const sectionsIssue = arrayIssue(p.sections, "sections");
|
|
55
|
-
if (sectionsIssue)
|
|
56
|
-
return { ok: false, error: sectionsIssue };
|
|
57
|
-
if (p.scenarioOverrides !== undefined) {
|
|
58
|
-
if (p.scenarioOverrides === null || typeof p.scenarioOverrides !== "object" || Array.isArray(p.scenarioOverrides)) {
|
|
59
|
-
return { ok: false, error: "scenarioOverrides is not an object" };
|
|
60
|
-
}
|
|
61
|
-
for (const [name, decls] of Object.entries(p.scenarioOverrides)) {
|
|
62
|
-
const issue = arrayIssue(decls, `scenarioOverrides[${name}]`);
|
|
63
|
-
if (issue)
|
|
64
|
-
return { ok: false, error: issue };
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
return { ok: true, value: raw };
|
|
68
|
-
}
|
|
69
|
-
export const CORE_ENGINE_VERSION = (() => {
|
|
70
|
-
try {
|
|
71
|
-
const entry = createRequire(import.meta.url).resolve("@sema-agent/core");
|
|
72
|
-
return JSON.parse(readFileSync(join(dirname(entry), "..", "package.json"), "utf8")).version ?? "0.0.0";
|
|
73
|
-
}
|
|
74
|
-
catch {
|
|
75
|
-
return "0.0.0";
|
|
76
|
-
}
|
|
77
|
-
})();
|
|
78
|
-
export function validatePromptsDomain(raw) {
|
|
79
|
-
if (raw === null || typeof raw !== "object")
|
|
80
|
-
return { ok: false, error: "prompts is not an object" };
|
|
81
|
-
const w = raw;
|
|
82
|
-
if (w.schemaVersion === undefined) {
|
|
83
|
-
return { ok: false, error: "prompts payload has no schemaVersion — the legacy flat shape was retired in 5.0.0; wrap as {schemaVersion:1, declarations:{...}} (registry-core EffectivePromptsWire)" };
|
|
84
|
-
}
|
|
85
|
-
if (w.schemaVersion !== 1)
|
|
86
|
-
return { ok: false, error: `unsupported prompts schemaVersion ${String(w.schemaVersion)}` };
|
|
87
|
-
if (w.declarations === undefined && w.catalog === undefined)
|
|
88
|
-
return { ok: false, error: "dual-axis prompts carries neither axis (at least one of declarations|catalog required)" };
|
|
89
|
-
const value = { identity: "", axes: [] };
|
|
90
|
-
if (w.declarations !== undefined) {
|
|
91
|
-
const d = validateCenterPrompts(w.declarations);
|
|
92
|
-
if (!d.ok)
|
|
93
|
-
return { ok: false, error: `declarations axis: ${d.error}` };
|
|
94
|
-
value.declarations = d.value;
|
|
95
|
-
value.axes.push("declarations");
|
|
96
|
-
}
|
|
97
|
-
if (w.catalog !== undefined) {
|
|
98
|
-
const c = verifyPromptArtifact(w.catalog, { engineVersion: CORE_ENGINE_VERSION });
|
|
99
|
-
if (!c.ok)
|
|
100
|
-
return { ok: false, error: `catalog axis: ${c.code}: ${c.reason}` };
|
|
101
|
-
value.catalog = w.catalog;
|
|
102
|
-
value.axes.push("catalog");
|
|
103
|
-
}
|
|
104
|
-
value.identity = `${value.declarations?.contentDigest ?? "-"}+${value.catalog?.artifact.artifactDigest ?? "-"}`;
|
|
105
|
-
return { ok: true, value };
|
|
106
|
-
}
|
|
107
|
-
export function centerPromptsFromEffective(eff) {
|
|
108
|
-
const prompts = eff?.prompts;
|
|
109
|
-
if (prompts === undefined || prompts === null)
|
|
110
|
-
return undefined;
|
|
111
|
-
if (typeof prompts !== "object" || Array.isArray(prompts))
|
|
112
|
-
return prompts;
|
|
113
|
-
const o = prompts;
|
|
114
|
-
if ("schemaVersion" in o)
|
|
115
|
-
return prompts;
|
|
116
|
-
if ("packId" in o && "contentDigest" in o && "sections" in o)
|
|
117
|
-
return prompts;
|
|
118
|
-
if (o.catalog !== undefined)
|
|
119
|
-
return { schemaVersion: 1, catalog: o.catalog };
|
|
120
|
-
return undefined;
|
|
2
|
+
import { EffectivePromptsWire, formatConfigPath, sanitizeZodError } from "@sema-agent/settings-schema";
|
|
3
|
+
export function judgePromptsWire(raw) {
|
|
4
|
+
const wire = EffectivePromptsWire.safeParse(raw);
|
|
5
|
+
if (!wire.success) {
|
|
6
|
+
const issues = sanitizeZodError(wire.error).issues.map((i) => `${i.path.length === 0 ? "prompts" : `prompts.${formatConfigPath(i.path.map((s) => (typeof s === "number" ? s : String(s))))}`}: ${i.message}`);
|
|
7
|
+
return { ok: false, error: issues.join("; ") };
|
|
8
|
+
}
|
|
9
|
+
const verified = verifyPromptArtifact(wire.data.artifact);
|
|
10
|
+
return verified.ok ? { ok: true, artifact: verified.artifact } : { ok: false, error: `prompts.artifact refused by the engine (${verified.code}): ${verified.reason}` };
|
|
121
11
|
}
|
|
122
12
|
//# sourceMappingURL=prompts-domain-validate.js.map
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/** 拒体里逐字回显的键名条数上限。键名原样回显(不猜语义),但**条数有界** —— 一个塞满键的体不许把 400 响应
|
|
2
2
|
* 放大成流量面。超出部分只报数。 */
|
|
3
3
|
export declare const MAX_KEY_ECHO = 20;
|
|
4
|
-
/**
|
|
5
|
-
*
|
|
4
|
+
/** 键名回显 = 前缀 + 调用方串的唯一回显口径(`caller-text-echo.ts`:剥控制 / 双向字符、截到 64 字 + …;键名进的是 JSON 错误体与运维日志,
|
|
5
|
+
* 一个 RLO 能把两行字读反)。清洗之外**逐字**,不做大小写/近似猜测。 */
|
|
6
6
|
export declare function echoKeyName(prefix: string, key: string): string;
|
|
7
7
|
/** 一次键闭集裁决的产物:一句 wire 文案 + 两张分类键名表(消费端可机读,不必解析文案)。 */
|
|
8
8
|
export interface KeyClosureIssue {
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { echoCallerText } from "./caller-text-echo.js";
|
|
2
2
|
export const MAX_KEY_ECHO = 20;
|
|
3
|
-
const MAX_KEY_ECHO_CHARS = 64;
|
|
4
3
|
export function echoKeyName(prefix, key) {
|
|
5
|
-
|
|
6
|
-
return `${prefix}${clean.length > MAX_KEY_ECHO_CHARS ? `${clean.slice(0, MAX_KEY_ECHO_CHARS)}…` : clean}`;
|
|
4
|
+
return `${prefix}${echoCallerText(key)}`;
|
|
7
5
|
}
|
|
8
6
|
export function scanKeyClosure(bag, prefix, accepted, tolerated, into) {
|
|
9
7
|
for (const k of Object.keys(bag)) {
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* 运维 / 中心的审批名单读同一份,没有「这一处空名册、那一处带名册」的两种读法。
|
|
18
18
|
* **读成空的哪些原因词是拒面,按方向定**:**限制侧**(读成空 = 静默放行:技能 `disallowedTools`、`excludeTools` / 子代 `denyTools`、`settings.permissions.deny` / `ask`、运维 / 中心的审批名单)四类全拒 ——
|
|
19
19
|
* 近似名 · 退役名 · 文法读不出 · 不带内容形的工具带内容;**放行侧**(读成空 = 想放的什么也没放:`settings.permissions.allow`、根 / 子代 `allowTools`、技能 `allowedTools`)**只拒近似名**
|
|
20
|
-
* ({@link allowSideReadsAsNothing}):近似名现名唯一、确定是笔误;退役名 / 内容形 / 文法读不出 / 协议名对端段通配照 7.130.0 受理、交引擎既有通告(
|
|
20
|
+
* ({@link allowSideReadsAsNothing}):近似名现名唯一、确定是笔误;退役名 / 内容形 / 文法读不出 / 协议名对端段通配照 7.130.0 受理、交引擎既有通告(其中选择器清单 `allowTools` 里**有后继**的退役名〔`Task` ⇒ `Agent`、`bash` ⇒ `Bash`〕core 7.52.0 起由引擎开跑前拒,不在本仓拒面;规则表上的退役名引擎照旧告运维 ——
|
|
21
21
|
* 壳转投的 CC 用户 settings 里这些极常见,尤其内容形里的 `$VAR`(`Bash(echo $HOME)`)读成 `grammar`,拒了 = 每次提交 400)。运维的 `APPROVAL_GRANT` 是运维自己的配置:任何读成空都拒启(写错了当场改)。
|
|
22
22
|
* 技能拒侧那一拒与引擎 #1372(core 7.43.0:那只技能不激活)是同一件事的两处 —— 7.118.0 重估过、本版**不退**:本仓的续跑腿把引擎的
|
|
23
23
|
* `checkpoint.config_refused`(`config.skill_deny_unreadable`)答得不一(资源停车续跑腿 500、`/decide` 先结了卡、`/wake` 先铸了 run 行),先统一那一层再退
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
* `*` 在放行侧是「本层不设名单」、在限制侧读成空;限制侧 `mcp__*` / `a2a__*`(整个协议的拒)合法。
|
|
30
30
|
*/
|
|
31
31
|
import { compileAllowList } from "@sema-agent/core";
|
|
32
|
+
import { type LimitRefusal } from "./limit-refusal.js";
|
|
32
33
|
/** ① 形:字符串数组(空串也是字符串 —— 引擎把它读成 `grammar` 并通告 / 拒,见 ③)。 */
|
|
33
34
|
export declare const ruleEntryListShapeOk: (v: unknown) => v is readonly string[];
|
|
34
35
|
/**
|
|
@@ -42,14 +43,10 @@ export declare const ruleEntryListShapeOk: (v: unknown) => v is readonly string[
|
|
|
42
43
|
* 没有真实用法需要上千条」。抬不抬这个数是产品判断,不随提货改。
|
|
43
44
|
*/
|
|
44
45
|
export declare const MAX_ALLOW_LAYER_ENTRIES = 1000;
|
|
45
|
-
/** 超帽的拒句(
|
|
46
|
+
/** 超帽的拒句({@link allowLayerOverCap} 的句子;请求 allow 桶的拒句按字段重铸时读它)。 */
|
|
46
47
|
export declare function describeAllowLayerOverCap(field: string, count: number): string;
|
|
47
|
-
/** 一张条目表超了 {@link MAX_ALLOW_LAYER_ENTRIES} ⇒
|
|
48
|
-
export declare function allowLayerEntryCountIssue(field: string, list: readonly unknown[]):
|
|
49
|
-
readonly message: string;
|
|
50
|
-
readonly count: number;
|
|
51
|
-
readonly cap: number;
|
|
52
|
-
} | undefined;
|
|
48
|
+
/** 一张条目表超了 {@link MAX_ALLOW_LAYER_ENTRIES} ⇒ 拒(句子 + 机读位 `field` / `reason: "over_cap"` / `count` / `cap`);没超 ⇒ `undefined`。四张表同调这一只。 */
|
|
49
|
+
export declare function allowLayerEntryCountIssue(field: string, list: readonly unknown[]): LimitRefusal | undefined;
|
|
53
50
|
/** 一条引擎读成空的条目(引擎的形:原因词,名字层另带判词 / 1:1 现名;包根不导出这只具名型 ⇒ 从 `compileAllowList` 的返回型取,不手抄)。 */
|
|
54
51
|
export type InertRuleEntry = ReturnType<typeof compileAllowList>["inert"][number];
|
|
55
52
|
/**
|
|
@@ -150,6 +147,12 @@ export declare function replayInertEntry(layer: ToolListLayer | RulePolicyLayer,
|
|
|
150
147
|
export interface SkillDenyInertEntry extends InertToolListEntry {
|
|
151
148
|
readonly layer: SkillListLayer;
|
|
152
149
|
}
|
|
150
|
+
/**
|
|
151
|
+
* 一条技能(顶层 `skills[k]` / 子代 `agents[i].skills[j]`,`at` = 它的体内坐标)两只清单的**条数帽**:先 `allowedTools` 后 `disallowedTools`(与 7.131.0 的判序同)。
|
|
152
|
+
* 判与句子就是 {@link overCapOfList} 那一只(拒点 `resolveSpec` 两腿同经的 {@link inertToolListEntryOf} 先过的也是它):受理口在技能的两道形门处调它
|
|
153
|
+
* (`http/admission.ts` 的 `validateUserSkills` 与 `spec-fields.ts` 的 `validateTaskAgents`:两道门都逐条先形、后帽 —— 与 7.131.0 的拒点与判序同,码与先后不变),句子与机读位点体内坐标。
|
|
154
|
+
*/
|
|
155
|
+
export declare function skillToolListsOverCap(skill: unknown, at: string, scope: "top" | "agent"): InertToolListEntry | undefined;
|
|
153
156
|
/**
|
|
154
157
|
* ③ 的拒侧在**提交体**上的判,技能那两层(顶层 `skills[]` 与子代 `agents[].skills[]`;第一处命中即答)。全部工具名清单的判是 {@link inertToolListEntryOf}(调用点两处都调它);
|
|
155
158
|
* 本函数单独导出是给随包排空脚本:那条判据(`skill-deny-inert`)只数技能这两层,SQL 车道的孪生也只看技能的清单。
|
|
@@ -167,7 +170,7 @@ export declare function skillDenyInertEntryOf(body: unknown): SkillDenyInertEntr
|
|
|
167
170
|
* 本函数只是「在体的哪几处取清单」;句子只有一个有界的组句器({@link describeInertRuleEntries}),清单先过条数帽({@link allowLayerEntryCountIssue})。
|
|
168
171
|
*
|
|
169
172
|
* 为什么限制侧四类全拒、放行侧只拒近似名:引擎 7.51.x 把「没有任何工具答应的名字」改成条目原样保留 + 运维行告知一次。限制侧读成空 = **静默放行**(`denyTools:["BASH"]` 以为禁了 `Bash`,子代照用);
|
|
170
|
-
* 放行侧读成空 = 想放的什么也没放 —— 其中**近似名**(现名唯一)
|
|
173
|
+
* 放行侧读成空 = 想放的什么也没放 —— 其中**近似名**(现名唯一)是确定的笔误,拒并点名现名;**退役名**(选择器清单里有后继的由引擎开跑前拒)、**内容形**与**文法读不出**在放行侧照 7.130.0 受理、交引擎既有通告(见头注 ③)。
|
|
171
174
|
* **真未知名**(没有近似也没有退役对应)不在读成空之列,原样保留、告运维一次(之后挂上同名工具即生效)。请求的 `settings.permissions.deny` / `ask`
|
|
172
175
|
* 与运维 / 中心的审批名单读同一张名册,走另一只入口({@link unmatchableToolNamesRefusal},`config.ts`),不在本函数(存体预判调同一只判据、home 同源于部署配置,见 `http/stored-body-replay.ts`)。
|
|
173
176
|
*
|
package/dist/rule-entry-list.js
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import { PROTOCOL_TABLE, compileAllowList, parsePermissionRule } from "@sema-agent/core";
|
|
2
2
|
import { displayListEntry } from "./list-entry-display.js";
|
|
3
|
+
import { limitRefusal } from "./limit-refusal.js";
|
|
3
4
|
import { TOOL_NAME_ROSTER } from "./namespaced-rule-name.js";
|
|
4
5
|
export const ruleEntryListShapeOk = (v) => Array.isArray(v) && v.every((x) => typeof x === "string");
|
|
5
6
|
export const MAX_ALLOW_LAYER_ENTRIES = 1_000;
|
|
7
|
+
const ALLOW_LAYER_OVER_CAP_TAIL = "Refused rather than truncated: a truncated list silently drops the entries past the cap. Merge entries into broader ones (mcp__<server>__*, Bash(<prefix>:*), Read(//<dir>/**)) or trim the list";
|
|
8
|
+
function allowLayerOverCap(field, count) {
|
|
9
|
+
return limitRefusal(field, "entries", count, MAX_ALLOW_LAYER_ENTRIES, { tail: ALLOW_LAYER_OVER_CAP_TAIL });
|
|
10
|
+
}
|
|
6
11
|
export function describeAllowLayerOverCap(field, count) {
|
|
7
|
-
return (
|
|
8
|
-
`Merge entries into broader ones (mcp__<server>__*, Bash(<prefix>:*), Read(//<dir>/**)) or trim the list`);
|
|
12
|
+
return allowLayerOverCap(field, count).message;
|
|
9
13
|
}
|
|
10
14
|
export function allowLayerEntryCountIssue(field, list) {
|
|
11
|
-
|
|
12
|
-
return undefined;
|
|
13
|
-
return { message: describeAllowLayerOverCap(field, list.length), count: list.length, cap: MAX_ALLOW_LAYER_ENTRIES };
|
|
15
|
+
return list.length <= MAX_ALLOW_LAYER_ENTRIES ? undefined : allowLayerOverCap(field, list.length);
|
|
14
16
|
}
|
|
15
17
|
export function inertRuleEntriesOf(list, behavior) {
|
|
16
18
|
return compileAllowList(list, behavior, TOOL_NAME_ROSTER).inert;
|
|
@@ -114,14 +116,16 @@ function inertEntriesOfList(list, layer) {
|
|
|
114
116
|
function* toolListsOf(body) {
|
|
115
117
|
const skills = body["skills"];
|
|
116
118
|
if (Array.isArray(skills)) {
|
|
117
|
-
for (
|
|
119
|
+
for (let k = 0; k < skills.length; k++) {
|
|
120
|
+
const skill = skills[k];
|
|
118
121
|
if (!isPlainRecord(skill))
|
|
119
122
|
continue;
|
|
120
|
-
yield { layer: "skills", field: "skill.disallowedTools", prefix: "", list: skill["disallowedTools"] };
|
|
123
|
+
yield { layer: "skills", field: "skill.disallowedTools", prefix: "", at: `skills[${k}].disallowedTools`, list: skill["disallowedTools"] };
|
|
121
124
|
}
|
|
122
|
-
for (
|
|
125
|
+
for (let k = 0; k < skills.length; k++) {
|
|
126
|
+
const skill = skills[k];
|
|
123
127
|
if (isPlainRecord(skill))
|
|
124
|
-
yield { layer: "skills.allowedTools", field: "skill.allowedTools", prefix: "", list: skill["allowedTools"] };
|
|
128
|
+
yield { layer: "skills.allowedTools", field: "skill.allowedTools", prefix: "", at: `skills[${k}].allowedTools`, list: skill["allowedTools"] };
|
|
125
129
|
}
|
|
126
130
|
}
|
|
127
131
|
const agents = body["agents"];
|
|
@@ -134,7 +138,7 @@ function* toolListsOf(body) {
|
|
|
134
138
|
for (let j = 0; j < agentSkills.length; j++) {
|
|
135
139
|
const skill = agentSkills[j];
|
|
136
140
|
if (isPlainRecord(skill))
|
|
137
|
-
yield { layer: "agents.skills", field: "skill.disallowedTools", prefix: `agents[${i}]: skills[${j}]: `, list: skill["disallowedTools"] };
|
|
141
|
+
yield { layer: "agents.skills", field: "skill.disallowedTools", prefix: `agents[${i}]: skills[${j}]: `, at: `agents[${i}].skills[${j}].disallowedTools`, list: skill["disallowedTools"] };
|
|
138
142
|
}
|
|
139
143
|
}
|
|
140
144
|
for (let i = 0; i < agents.length; i++) {
|
|
@@ -145,31 +149,29 @@ function* toolListsOf(body) {
|
|
|
145
149
|
for (let j = 0; j < agentSkills.length; j++) {
|
|
146
150
|
const skill = agentSkills[j];
|
|
147
151
|
if (isPlainRecord(skill))
|
|
148
|
-
yield { layer: "agents.skills.allowedTools", field: "skill.allowedTools", prefix: `agents[${i}]: skills[${j}]: `, list: skill["allowedTools"] };
|
|
152
|
+
yield { layer: "agents.skills.allowedTools", field: "skill.allowedTools", prefix: `agents[${i}]: skills[${j}]: `, at: `agents[${i}].skills[${j}].allowedTools`, list: skill["allowedTools"] };
|
|
149
153
|
}
|
|
150
154
|
}
|
|
151
155
|
for (let i = 0; i < agents.length; i++) {
|
|
152
156
|
const agent = agents[i];
|
|
153
157
|
if (!isPlainRecord(agent))
|
|
154
158
|
continue;
|
|
155
|
-
yield { layer: "agents.denyTools", field: `agents[${i}].denyTools`, prefix: "", list: agent["denyTools"] };
|
|
156
|
-
yield { layer: "agents.allowTools", field: `agents[${i}].allowTools`, prefix: "", list: agent["allowTools"] };
|
|
159
|
+
yield { layer: "agents.denyTools", field: `agents[${i}].denyTools`, prefix: "", at: `agents[${i}].denyTools`, list: agent["denyTools"] };
|
|
160
|
+
yield { layer: "agents.allowTools", field: `agents[${i}].allowTools`, prefix: "", at: `agents[${i}].allowTools`, list: agent["allowTools"] };
|
|
157
161
|
}
|
|
158
162
|
}
|
|
159
|
-
yield { layer: "excludeTools", field: "excludeTools", prefix: "", list: body["excludeTools"] };
|
|
160
|
-
yield { layer: "allowTools", field: "allowTools", prefix: "", list: body["allowTools"] };
|
|
163
|
+
yield { layer: "excludeTools", field: "excludeTools", prefix: "", at: "excludeTools", list: body["excludeTools"] };
|
|
164
|
+
yield { layer: "allowTools", field: "allowTools", prefix: "", at: "allowTools", list: body["allowTools"] };
|
|
161
165
|
const settings = body["settings"];
|
|
162
166
|
const permissions = isPlainRecord(settings) ? settings["permissions"] : undefined;
|
|
163
167
|
if (isPlainRecord(permissions))
|
|
164
|
-
yield { layer: "settings.permissions.allow", field: "settings.permissions.allow", prefix: "", list: permissions["allow"] };
|
|
168
|
+
yield { layer: "settings.permissions.allow", field: "settings.permissions.allow", prefix: "", at: "settings.permissions.allow", list: permissions["allow"] };
|
|
165
169
|
}
|
|
166
170
|
function entryOfList(l) {
|
|
167
171
|
const face = TOOL_LIST_FACES[l.layer];
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
return { layer: l.layer, side: face.side, code: LIST_OVER_CAP_CODE, message: `${l.prefix}${over.message}`, extra: { field: l.field, reason: "over_cap", count: over.count, cap: over.cap } };
|
|
172
|
-
}
|
|
172
|
+
const over = overCapOfList(l);
|
|
173
|
+
if (over !== undefined)
|
|
174
|
+
return over;
|
|
173
175
|
if (!ruleEntryListShapeOk(l.list))
|
|
174
176
|
return undefined;
|
|
175
177
|
const inert = inertEntriesOfList(l.list, l.layer);
|
|
@@ -177,6 +179,20 @@ function entryOfList(l) {
|
|
|
177
179
|
return undefined;
|
|
178
180
|
return { layer: l.layer, side: face.side, code: face.code, message: `${l.prefix}${describeInertRuleEntries(l.field, inert)} — ${REFUSAL_TAIL[face.side]}` };
|
|
179
181
|
}
|
|
182
|
+
function overCapOfList(l) {
|
|
183
|
+
if (!Array.isArray(l.list))
|
|
184
|
+
return undefined;
|
|
185
|
+
const over = allowLayerEntryCountIssue(l.at, l.list);
|
|
186
|
+
return over === undefined ? undefined : { layer: l.layer, side: TOOL_LIST_FACES[l.layer].side, code: LIST_OVER_CAP_CODE, message: over.message, extra: over.facts };
|
|
187
|
+
}
|
|
188
|
+
export function skillToolListsOverCap(skill, at, scope) {
|
|
189
|
+
if (!isPlainRecord(skill))
|
|
190
|
+
return undefined;
|
|
191
|
+
const allowLayer = scope === "top" ? "skills.allowedTools" : "agents.skills.allowedTools";
|
|
192
|
+
const denyLayer = scope === "top" ? "skills" : "agents.skills";
|
|
193
|
+
return (overCapOfList({ layer: allowLayer, field: "skill.allowedTools", prefix: "", at: `${at}.allowedTools`, list: skill["allowedTools"] }) ??
|
|
194
|
+
overCapOfList({ layer: denyLayer, field: "skill.disallowedTools", prefix: "", at: `${at}.disallowedTools`, list: skill["disallowedTools"] }));
|
|
195
|
+
}
|
|
180
196
|
function firstInertEntry(body, acceptLayer, acceptSide) {
|
|
181
197
|
if (!isPlainRecord(body))
|
|
182
198
|
return undefined;
|
package/dist/run-local.js
CHANGED
|
@@ -8,7 +8,7 @@ import { join } from "node:path";
|
|
|
8
8
|
import { realpathSync } from "node:fs";
|
|
9
9
|
import { createInterface } from "node:readline/promises";
|
|
10
10
|
import { fileURLToPath } from "node:url";
|
|
11
|
-
import { Runner, uuidv7, FileStorageBackend, NodeExecutionEnv, TtlSessionStore, CenterPromptSource, FilePromptArtifactStore, FilePromptSourceStateStore, MemoryPromptArtifactStore, MemoryPromptSourceStateStore, defaultTaskRegistry } from "@sema-agent/core";
|
|
11
|
+
import { BIDI_CONTROL_CHARS, Runner, uuidv7, FileStorageBackend, NodeExecutionEnv, TtlSessionStore, CenterPromptSource, FilePromptArtifactStore, FilePromptSourceStateStore, MemoryPromptArtifactStore, MemoryPromptSourceStateStore, defaultTaskRegistry } from "@sema-agent/core";
|
|
12
12
|
import { readAskClassPair } from "./approval-card.js";
|
|
13
13
|
import { singleUserAutoAcceptBaselineApplies } from "./approval.js";
|
|
14
14
|
import { withUnattendedLeg } from "./unattended-permission-mode.js";
|
|
@@ -18,14 +18,13 @@ import { assertGuardPatternsUsable, buildOnlySensitiveBaselineWarning, buildAppr
|
|
|
18
18
|
import { applyRuntimeGovernance, autonomyModeFloor, entryPermissionMode } from "./runtime-governance.js";
|
|
19
19
|
import { ForkRoutingSessionStore } from "./plugins/fork-routing-session-store.js";
|
|
20
20
|
import { taskWallClockSec } from "./task-workflow.js";
|
|
21
|
-
import {
|
|
22
|
-
import { CORE_ENGINE_VERSION } from "./prompts-domain-validate.js";
|
|
21
|
+
import { applyCenterArtifact, centerSourceOnError } from "./capabilities/center-prompts.js";
|
|
23
22
|
import { buildUnpricedCeilingNotice, loadConfig, logConfigDiagnostics, parseNumOrFailNonNegative } from "./config.js";
|
|
24
23
|
import { buildStoreOpenRefusalTail } from "./plugins/store-open-refusal.js";
|
|
25
24
|
import { acquireLocalBackendWithWait } from "./plugins/store-lock-wait.js";
|
|
26
25
|
import { configLocalRoot, configProviderKind, createConfigProvider } from "./config-provider.js";
|
|
27
26
|
import { CONFIG_DOMAIN_INVALID_NOTE, buildCandidateRejectedFields, judgeConfigCandidate } from "./web-admin-client/candidate-gate.js";
|
|
28
|
-
import { buildUnreadConfigFileFields } from "./web-admin-client/read-warnings.js";
|
|
27
|
+
import { buildUnreadConfigFileFields, buildUnreadConfigKeyFields } from "./web-admin-client/read-warnings.js";
|
|
29
28
|
import { composeExecutionLane, settleHostLaneShell } from "./boot/execution-lane.js";
|
|
30
29
|
import { judgeConsolidationValve } from "./boot/memory-consolidation.js";
|
|
31
30
|
import { logConfigDirMigration, migrateLocalConfigDirectory } from "./config-d-migration.js";
|
|
@@ -37,7 +36,7 @@ import { createInstructionSourceSeat } from "./instruction-source-notice.js";
|
|
|
37
36
|
import { loadDeploymentSkills } from "./capabilities/skills.js";
|
|
38
37
|
import { createRepoClient } from "./capabilities/repo-tools.js";
|
|
39
38
|
import { webSearchConfigFromEnv, createWebSearchBackend } from "./plugins/web-search.js";
|
|
40
|
-
import { buildScenarios, createScenarioGate, selectScenario, centerScenarios } from "./capabilities/scenarios.js";
|
|
39
|
+
import { buildPromptSeats, buildScenarios, createScenarioGate, selectScenario, centerScenarios } from "./capabilities/scenarios.js";
|
|
41
40
|
import { createTaskListLane } from "./boot/task-list-lane.js";
|
|
42
41
|
import { pickHandsRunner, withoutHands } from "./capabilities/hands-lane.js";
|
|
43
42
|
import { HttpError, sessionIdShapeIssue } from "./security.js";
|
|
@@ -50,7 +49,7 @@ import { createSharedRunnerDeps } from "./boot/runner-deps.js";
|
|
|
50
49
|
import { createGovernanceSeams } from "./boot/governance-seams.js";
|
|
51
50
|
import { assertRetentionLaneWirable } from "./boot/retention-lane.js";
|
|
52
51
|
import { createOrgMemoryAdmissionWiring } from "./boot/org-memory.js";
|
|
53
|
-
import {
|
|
52
|
+
import { assertDeploymentModsAdmitted, createDeploymentMods } from "./boot/deployment-mods.js";
|
|
54
53
|
import { createKeyResolver } from "./key-resolver.js";
|
|
55
54
|
import { createLogger } from "./observability/logger.js";
|
|
56
55
|
import { fatalExit } from "./boot/fatal-exit.js";
|
|
@@ -254,8 +253,9 @@ function argsDisplayOf(args) {
|
|
|
254
253
|
function buildLocalAskPrompt(req, argsShown) {
|
|
255
254
|
return `approve "${terminalSafeText(req.toolName)}"? ${terminalSafeText(req.message)}\n ${argsShown}\n[y/N] `;
|
|
256
255
|
}
|
|
256
|
+
const TERMINAL_UNSAFE_RE = new RegExp(`[\\u0000-\\u001f\\u007f-\\u009f${BIDI_CONTROL_CHARS}\\u200b-\\u200d\\u2028\\u2029\\u2060-\\u2065\\ufeff]`, "g");
|
|
257
257
|
function terminalSafeText(text) {
|
|
258
|
-
return text.replace(
|
|
258
|
+
return text.replace(TERMINAL_UNSAFE_RE, (c) => `\\u${c.charCodeAt(0).toString(16).padStart(4, "0")}`);
|
|
259
259
|
}
|
|
260
260
|
function inputAlreadyEnded(input) {
|
|
261
261
|
const state = input;
|
|
@@ -366,6 +366,8 @@ export async function runLocal(argv, deps = {}) {
|
|
|
366
366
|
else {
|
|
367
367
|
for (const f of r.unreadFiles ?? [])
|
|
368
368
|
logger.warn("config_unread_file", buildUnreadConfigFileFields(f, configProvider.kind === "local" ? root : undefined));
|
|
369
|
+
for (const k of r.unreadKeys ?? [])
|
|
370
|
+
logger.warn("config_unread_key", buildUnreadConfigKeyFields(k, configProvider.kind === "local" ? root : undefined));
|
|
369
371
|
for (const d of r.droppedEntries ?? [])
|
|
370
372
|
logger.warn("config_entry_dropped", { domain: d.domain, entry: d.entry, reasonCode: d.reasonCode, error: d.error, version: r.effective.version, phase: "boot", note: "this one entry failed its domain schema and was dropped on its own — the rest of the candidate applies (per-entry tolerance); fix the named entry to bring it back" });
|
|
371
373
|
applying = true;
|
|
@@ -488,25 +490,25 @@ export async function runLocal(argv, deps = {}) {
|
|
|
488
490
|
return new CenterPromptSource({
|
|
489
491
|
store: new FilePromptArtifactStore(promptEpochDir),
|
|
490
492
|
stateStore: new FilePromptSourceStateStore(promptEpochDir),
|
|
491
|
-
|
|
493
|
+
onError: centerSourceOnError(logger),
|
|
492
494
|
});
|
|
493
495
|
}
|
|
494
496
|
catch (e) {
|
|
495
497
|
logger.warn("center_prompts_store_unwritable", { dir: promptEpochDir, err: String(e), note: "file-backed prompt-epoch store unavailable — memory fallback; built-ins unaffected" });
|
|
496
|
-
return new CenterPromptSource({ store: new MemoryPromptArtifactStore(), stateStore: new MemoryPromptSourceStateStore(),
|
|
498
|
+
return new CenterPromptSource({ store: new MemoryPromptArtifactStore(), stateStore: new MemoryPromptSourceStateStore(), onError: centerSourceOnError(logger) });
|
|
497
499
|
}
|
|
498
500
|
})();
|
|
499
501
|
try {
|
|
500
502
|
await promptSource.restore();
|
|
501
503
|
if (candidatePrompts !== undefined) {
|
|
502
|
-
await
|
|
504
|
+
await applyCenterArtifact(promptSource, candidatePrompts, undefined, logger, "run-local");
|
|
503
505
|
}
|
|
504
506
|
else {
|
|
505
|
-
await
|
|
507
|
+
await applyCenterArtifact(promptSource, undefined, undefined, logger, "run-local");
|
|
506
508
|
}
|
|
507
509
|
}
|
|
508
510
|
catch (e) {
|
|
509
|
-
logger.warn("center_prompts_catalog_restore_failed", { err: String(e), note: "
|
|
511
|
+
logger.warn("center_prompts_catalog_restore_failed", { err: String(e), note: "center candidate absent — built-ins serve" });
|
|
510
512
|
}
|
|
511
513
|
let refusedWithoutPerson = 0;
|
|
512
514
|
const onAsk = createLocalApprover({
|
|
@@ -559,6 +561,8 @@ export async function runLocal(argv, deps = {}) {
|
|
|
559
561
|
{ name: "toolResultStore", store: fileBackend.toolResultStore },
|
|
560
562
|
],
|
|
561
563
|
});
|
|
564
|
+
const deploymentMods = createDeploymentMods({ metrics, brandIdentity: true });
|
|
565
|
+
await assertDeploymentModsAdmitted(deploymentMods);
|
|
562
566
|
const sharedRunnerDeps = createSharedRunnerDeps({
|
|
563
567
|
metrics,
|
|
564
568
|
config,
|
|
@@ -575,10 +579,7 @@ export async function runLocal(argv, deps = {}) {
|
|
|
575
579
|
backgroundAgentStore: fileBackend.backgroundAgentStore,
|
|
576
580
|
mailboxStore: fileBackend.mailboxStore,
|
|
577
581
|
rosterStore: fileBackend.rosterStore,
|
|
578
|
-
|
|
579
|
-
...createPermissionDeniedMeter(metrics),
|
|
580
|
-
...(config.hooksTimeoutMs !== undefined ? { timeoutMs: config.hooksTimeoutMs } : {}),
|
|
581
|
-
},
|
|
582
|
+
deploymentMods,
|
|
582
583
|
toolResultStore: fileBackend.toolResultStore,
|
|
583
584
|
checkpointStore: undefined,
|
|
584
585
|
sessionPolicyStore: fileBackend.sessionPolicyStore,
|
|
@@ -604,7 +605,7 @@ export async function runLocal(argv, deps = {}) {
|
|
|
604
605
|
const subRunnerDeps = { ...sharedRunnerDeps, sessionStore: new ForkRoutingSessionStore(sessionStore, new TtlSessionStore({ defaultTtlDays: 1 / 24 })), onError: engineOnError, onAsk };
|
|
605
606
|
const subRunner = new Runner(subRunnerDeps);
|
|
606
607
|
const handslessRunner = new Runner(withoutHands(runnerDeps));
|
|
607
|
-
const deploymentSkills = loadDeploymentSkills(config);
|
|
608
|
+
const deploymentSkills = loadDeploymentSkills(config, logger);
|
|
608
609
|
const skills = effective?.skills ? await applySkillsManifest(deploymentSkills, effective.skills, configProvider, logger) : deploymentSkills;
|
|
609
610
|
const repoClient = config.gitApiBaseUrl ? createRepoClient(config.gitApiKind, config.gitApiBaseUrl, config.gitApiToken) : undefined;
|
|
610
611
|
const webSearchCfg = webSearchConfigFromEnv();
|
|
@@ -615,7 +616,6 @@ export async function runLocal(argv, deps = {}) {
|
|
|
615
616
|
...(webSearch ? { webSearch } : {}),
|
|
616
617
|
backgroundAgentStore: fileBackend.backgroundAgentStore,
|
|
617
618
|
taskListStoreFor: taskListLane.storeFor,
|
|
618
|
-
brandIdentity: true,
|
|
619
619
|
};
|
|
620
620
|
const scenarios = buildScenarios(scenarioDeps);
|
|
621
621
|
if (effective?.scenarios) {
|
|
@@ -673,7 +673,7 @@ export async function runLocal(argv, deps = {}) {
|
|
|
673
673
|
getApiKeyAndHeaders: keyResolver,
|
|
674
674
|
tools: cap.tools,
|
|
675
675
|
skills: cap.skills,
|
|
676
|
-
...(
|
|
676
|
+
...buildPromptSeats(scenarioName, cap.prompt, undefined),
|
|
677
677
|
...(cap.finalVerification === true ? { finalVerification: true } : {}),
|
|
678
678
|
...(mcp ? { mcp } : {}),
|
|
679
679
|
...(a2a ? { a2a } : {}),
|
package/dist/runs.d.ts
CHANGED
|
@@ -109,6 +109,12 @@ export declare function resumeAtHttpStatus(result: {
|
|
|
109
109
|
* `resumeAtHttpStatus` 自己(单元测试直接喂码)。
|
|
110
110
|
*/
|
|
111
111
|
export declare function syncRefusalHttpStatus(result: Pick<TaskResult, "terminal" | "stats">): number | undefined;
|
|
112
|
+
/**
|
|
113
|
+
* 同步腿零工作拒体的机读事实(交 `refusalBody` 的 `facts`)—— 唯一一处。入参是**出口封口 + 脱敏后**的终局(调用方递 `redactTerminalResult(sealResultForExit(result)).terminal`,
|
|
114
|
+
* 与 run 记录读面 / 流式 `done.result` 上的 `terminal` 同一只来源),本函数只按码取它的 `detail.detail`,不另读、不另脱。码不在登记表里、终局不是 `failed`、
|
|
115
|
+
* 引擎没给 `coded` 因由 ⇒ `{}`(缺席不造键)。
|
|
116
|
+
*/
|
|
117
|
+
export declare function zeroWorkRefusalFacts(terminal: unknown): Readonly<Record<string, unknown>>;
|
|
112
118
|
/**
|
|
113
119
|
* 一条提交腿把引擎终局落行之后的**唯一**收尾:**零工作的拒不占提交幂等键**。判据就是上面这只 {@link syncRefusalHttpStatus}
|
|
114
120
|
* (零 turn、零 token 且是 prepare 期的拒码)—— 三条提交腿(同步 / 流式 / durable)同调这一只,不另开判据。
|
package/dist/runs.js
CHANGED
|
@@ -78,7 +78,10 @@ const PREPARE_REFUSAL_HTTP_STATUS = {
|
|
|
78
78
|
"config.image_invalid": 400,
|
|
79
79
|
"config.user_attachment_invalid": 400,
|
|
80
80
|
"config.tool_face_control": 400,
|
|
81
|
+
"config.agent.unknown_tool": 400,
|
|
82
|
+
"config.legacy_tool_name": 400,
|
|
81
83
|
"config.memory_capture_unsupported": 409,
|
|
84
|
+
"prompt.assembled_role_refused": 400,
|
|
82
85
|
};
|
|
83
86
|
export function resumeAtHttpStatus(result) {
|
|
84
87
|
const code = failureCodeOf(result.terminal);
|
|
@@ -106,6 +109,19 @@ export function syncRefusalHttpStatus(result) {
|
|
|
106
109
|
return undefined;
|
|
107
110
|
return resumeAtHttpStatus(result);
|
|
108
111
|
}
|
|
112
|
+
const ZERO_WORK_REFUSAL_DETAIL_CODES = new Set(["config.user_attachment_invalid"]);
|
|
113
|
+
export function zeroWorkRefusalFacts(terminal) {
|
|
114
|
+
if (terminal === null || typeof terminal !== "object")
|
|
115
|
+
return {};
|
|
116
|
+
const t = terminal;
|
|
117
|
+
if (t.kind !== "failed" || typeof t.code !== "string" || !ZERO_WORK_REFUSAL_DETAIL_CODES.has(t.code))
|
|
118
|
+
return {};
|
|
119
|
+
const cause = t.detail;
|
|
120
|
+
if (cause === null || typeof cause !== "object")
|
|
121
|
+
return {};
|
|
122
|
+
const c = cause;
|
|
123
|
+
return c.kind === "coded" && c.detail !== undefined ? { detail: c.detail } : {};
|
|
124
|
+
}
|
|
109
125
|
export async function releaseKeyIfZeroWorkRefusal(runStore, taskId, result) {
|
|
110
126
|
if (syncRefusalHttpStatus(result) !== undefined)
|
|
111
127
|
await runStore.releaseIdemKey(taskId);
|