@sema-agent/server 7.51.0 → 7.52.1
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/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/USAGE.md +103 -24
- package/dist/adoption/plan.d.ts +4 -4
- package/dist/adoption/plan.js +11 -0
- package/dist/approval-card.d.ts +26 -2
- package/dist/approval-card.js +9 -0
- package/dist/approval-hmac.d.ts +1 -1
- package/dist/approval-reconciler.d.ts +2 -2
- package/dist/approval-reconciler.js +1 -1
- package/dist/bench/l8/artifact.d.ts +1 -1
- package/dist/bench/s1/arms.d.ts +1 -1
- package/dist/bench/s1/live-deps.d.ts +1 -1
- package/dist/bench/s1/oracle.d.ts +1 -1
- package/dist/bench/s1/row.d.ts +1 -1
- package/dist/boot/budget-tracing.d.ts +1 -1
- package/dist/boot/budget-tracing.js +2 -5
- package/dist/boot/coordinators.js +3 -1
- package/dist/boot/deferred-sandbox-path-env.d.ts +1 -1
- package/dist/boot/device-lane.js +2 -0
- package/dist/boot/engine-lease.d.ts +1 -1
- package/dist/boot/execution-env.d.ts +1 -1
- package/dist/boot/governance-seams.d.ts +2 -2
- package/dist/boot/leader.d.ts +1 -1
- package/dist/boot/memory-boundary.d.ts +2 -2
- package/dist/boot/memory-consolidation.d.ts +6 -6
- package/dist/boot/org-memory.d.ts +1 -1
- package/dist/boot/parked-revive-gate.d.ts +3 -3
- package/dist/boot/reapers.d.ts +2 -2
- package/dist/boot/reapers.js +17 -4
- package/dist/boot/resolve-spec.d.ts +12 -0
- package/dist/boot/resolve-spec.js +29 -7
- package/dist/boot/retention-lane.d.ts +2 -2
- package/dist/boot/runner-deps.d.ts +17 -7
- package/dist/boot/runner-deps.js +4 -2
- package/dist/boot/runtime-caps.d.ts +23 -0
- package/dist/boot/runtime-caps.js +24 -2
- package/dist/boot/session-faces.d.ts +1 -1
- package/dist/boot/session-faces.js +14 -3
- package/dist/boot/stores.js +31 -1
- package/dist/boot/task-list-lane.d.ts +2 -2
- package/dist/brain.js +51 -31
- package/dist/budget.d.ts +2 -2
- package/dist/capabilities/center-plugins.d.ts +1 -1
- package/dist/capabilities/collab-workflows.d.ts +1 -1
- package/dist/capabilities/hands-lane.d.ts +3 -3
- package/dist/capabilities/scenarios.d.ts +3 -3
- package/dist/capabilities/skills.d.ts +1 -1
- package/dist/config-center/hot-keys-registry.js +5 -0
- package/dist/config-center/http-client.d.ts +2 -2
- package/dist/config-center/read-face.d.ts +1 -1
- package/dist/config-center/restart-signal.d.ts +1 -1
- package/dist/config-types.d.ts +100 -25
- package/dist/config.d.ts +11 -3
- package/dist/config.js +91 -15
- package/dist/deployment-governance.d.ts +1 -1
- package/dist/device-enrollment.d.ts +2 -2
- package/dist/device-store.d.ts +3 -3
- package/dist/device-ws-hub.d.ts +4 -2
- package/dist/device-ws-hub.js +9 -3
- package/dist/device-ws-protocol.d.ts +2 -2
- package/dist/env-facts.d.ts +1 -1
- package/dist/execution-lane-caps.d.ts +1 -1
- package/dist/fleet/fleet-bus.d.ts +5 -2
- package/dist/fleet/fleet-reconciler.d.ts +1 -1
- package/dist/fleet/fleet-terminal-window.d.ts +1 -1
- package/dist/hooks/hook-runner.d.ts +8 -1
- package/dist/http/active-run-conflict.d.ts +2 -2
- package/dist/http/principal-gate.d.ts +1 -1
- package/dist/http/route-ctx.d.ts +27 -5
- package/dist/http/routes/admin-memory-optout.d.ts +48 -0
- package/dist/http/routes/admin-memory-optout.js +75 -0
- package/dist/http/routes/agents-roster.d.ts +1 -1
- package/dist/http/routes/approvals-assistant.js +21 -21
- package/dist/http/routes/capabilities.js +20 -9
- package/dist/http/routes/diagnostics.d.ts +1 -1
- package/dist/http/routes/leader.d.ts +1 -1
- package/dist/http/routes/memory-bundle.d.ts +1 -1
- package/dist/http/routes/memory-bundle.js +2 -1
- package/dist/http/routes/memory-compliance.d.ts +4 -4
- package/dist/http/routes/memory-origin.d.ts +4 -4
- package/dist/http/routes/memory-origin.js +3 -1
- package/dist/http/routes/memory-policy.js +6 -2
- package/dist/http/routes/retention-ops.d.ts +1 -1
- package/dist/http/routes/rules.d.ts +5 -2
- package/dist/http/routes/rules.js +84 -5
- package/dist/http/routes/run-memory-capture.d.ts +34 -0
- package/dist/http/routes/run-memory-capture.js +97 -0
- package/dist/http/routes/runs.d.ts +1 -0
- package/dist/http/routes/runs.js +212 -6
- package/dist/http/routes/session-sync.d.ts +4 -6
- package/dist/http/routes/session-sync.js +60 -47
- package/dist/http/routes/sessions.js +61 -188
- package/dist/http/routes/shared-memory.d.ts +1 -1
- package/dist/http/routes/tasks.js +1 -1
- package/dist/http/routes/workflows.js +19 -0
- package/dist/http/server.d.ts +35 -13
- package/dist/http/server.js +110 -14
- package/dist/http/verify-rounds.d.ts +1 -1
- package/dist/http/wire-types.d.ts +41 -8
- package/dist/leader/endpoint.d.ts +1 -1
- package/dist/leader/leader.d.ts +1 -1
- package/dist/leader/repair-oracle.d.ts +2 -2
- package/dist/leader/repair-oracle.js +1 -1
- package/dist/main.js +14 -6
- package/dist/memory-bundle-engine.d.ts +1 -1
- package/dist/memory-operator-faces.d.ts +5 -5
- package/dist/memory-origin-fence.d.ts +35 -0
- package/dist/memory-origin-fence.js +66 -0
- package/dist/memory-posture.d.ts +13 -1
- package/dist/memory-posture.js +1 -0
- package/dist/memory-scope.d.ts +6 -1
- package/dist/memory-scope.js +3 -2
- package/dist/model-select.d.ts +2 -2
- package/dist/observability/fail-open.d.ts +17 -5
- package/dist/observability/fail-open.js +17 -5
- package/dist/orchestration/hardened-vm-runner.d.ts +2 -2
- package/dist/orchestration/workflow-completion-inbox.d.ts +2 -2
- package/dist/plugins/background-shell-support.d.ts +2 -2
- package/dist/plugins/blob-backend.d.ts +7 -2
- package/dist/plugins/blob-backend.js +22 -18
- package/dist/plugins/caching-session-store.d.ts +7 -3
- package/dist/plugins/checkpoint-store-sql.d.ts +2 -2
- package/dist/plugins/file-history-store-sql.d.ts +170 -0
- package/dist/plugins/file-history-store-sql.js +827 -0
- package/dist/plugins/file-run-store.d.ts +44 -5
- package/dist/plugins/file-run-store.js +85 -13
- package/dist/plugins/fork-routing-session-store.d.ts +1 -1
- package/dist/plugins/fork-routing-session-store.js +2 -2
- package/dist/plugins/leader-run-store-sql.d.ts +1 -1
- package/dist/plugins/local-session-store.d.ts +9 -1
- package/dist/plugins/memory-embedder-fingerprint.d.ts +1 -1
- package/dist/plugins/memory-optout-grant-store-sql.d.ts +139 -0
- package/dist/plugins/memory-optout-grant-store-sql.js +157 -0
- package/dist/plugins/memory-origin-law.d.ts +2 -2
- package/dist/plugins/memory-run-store.d.ts +4 -3
- package/dist/plugins/memory-run-store.js +2 -1
- package/dist/plugins/permission-rule-store-file.d.ts +16 -6
- package/dist/plugins/permission-rule-store-file.js +77 -13
- package/dist/plugins/permission-rule-store-sql.d.ts +156 -8
- package/dist/plugins/permission-rule-store-sql.js +123 -21
- package/dist/plugins/pg-pool.js +59 -0
- package/dist/plugins/pg-safe-json.d.ts +1 -1
- package/dist/plugins/remote-env-device.d.ts +1 -1
- package/dist/plugins/remote-env-k8s.d.ts +1 -1
- package/dist/plugins/retention-lane-store-sql.d.ts +3 -3
- package/dist/plugins/retention-store-sql.d.ts +7 -7
- package/dist/plugins/retention-store-sql.js +6 -0
- package/dist/plugins/run-store-sql.d.ts +9 -3
- package/dist/plugins/run-store-sql.js +2 -2
- package/dist/plugins/send-user-file.d.ts +1 -1
- package/dist/plugins/session-placement.d.ts +1 -1
- package/dist/plugins/sql-errors.d.ts +1 -1
- package/dist/plugins/store-backend.d.ts +59 -29
- package/dist/plugins/store-backend.js +75 -15
- package/dist/plugins/store-contracts.d.ts +5 -3
- package/dist/plugins/task-list-store-sql.d.ts +1 -1
- package/dist/plugins/tidb-pool.js +59 -0
- package/dist/plugins/web-search.d.ts +1 -1
- package/dist/prompts-domain-validate.js +1 -1
- package/dist/resource-suspend.d.ts +1 -1
- package/dist/resource-window.d.ts +3 -3
- package/dist/rules-consent.d.ts +231 -9
- package/dist/rules-consent.js +411 -13
- package/dist/run-local.js +29 -4
- package/dist/runs.d.ts +15 -1
- package/dist/runs.js +19 -0
- package/dist/runtime-caps-resolver.d.ts +36 -1
- package/dist/runtime-caps-resolver.js +25 -0
- package/dist/runtime-governance.d.ts +1 -1
- package/dist/security.d.ts +5 -5
- package/dist/security.js +1 -1
- package/dist/session-sync.d.ts +52 -37
- package/dist/session-sync.js +19 -16
- package/dist/shared-memory-scope-authorizer.d.ts +1 -1
- package/dist/sighup-idle.d.ts +1 -1
- package/dist/spec-fields.d.ts +22 -1
- package/dist/spec-fields.js +11 -0
- package/dist/store-live-probe.d.ts +2 -2
- package/dist/task-a2a.d.ts +1 -1
- package/dist/task-cwd.d.ts +1 -1
- package/dist/task-mcp.d.ts +3 -3
- package/dist/task-settings.d.ts +3 -3
- package/dist/task-workflow.d.ts +1 -1
- package/dist/text-bidi.d.ts +2 -2
- package/dist/tool-approval.d.ts +191 -9
- package/dist/tool-approval.js +248 -29
- package/dist/trace/core-keyset-guard.d.ts +3 -3
- package/dist/trace/engine-notice-wire.d.ts +6 -4
- package/dist/trace/engine-notice-wire.js +2 -0
- package/dist/trace/ledger-events.d.ts +1 -1
- package/dist/trace/ledger-sink.d.ts +2 -2
- package/dist/trace/project.d.ts +8 -2
- package/dist/trace/project.js +10 -0
- package/dist/turn-activity.d.ts +1 -1
- package/dist/wall-clock-jump-guard.d.ts +3 -3
- package/package.json +3 -3
- package/dist/http/tar.d.ts +0 -17
- package/dist/http/tar.js +0 -53
- package/dist/http/workspace-content.d.ts +0 -11
- package/dist/http/workspace-content.js +0 -20
- package/dist/plugins/file-snapshot-store-sql.d.ts +0 -170
- package/dist/plugins/file-snapshot-store-sql.js +0 -213
|
@@ -6,7 +6,7 @@ import { setLeafAdvanceListener } from "../session-leaf-bus.js";
|
|
|
6
6
|
import { SessionWatchRegistry, posIntEnv } from "../session-watch.js";
|
|
7
7
|
import { defaultTaskRegistry } from "@sema-agent/core";
|
|
8
8
|
export function createSessionFaces(ctx) {
|
|
9
|
-
const { config, logger, metrics, localRoot, backend, sessionStore, runStore, checkpointStore, toolResultStore, resumeAnchorStore, approvalExemptionStore, sessionPolicyStore, taskAttachmentStore,
|
|
9
|
+
const { config, logger, metrics, localRoot, backend, sessionStore, runStore, checkpointStore, toolResultStore, resumeAnchorStore, approvalExemptionStore, sessionPolicyStore, taskAttachmentStore, fileHistoryStore, workflowCompletionInbox, taskListLane, deviceStore, dropSessionScoped, } = ctx;
|
|
10
10
|
const mysqlPool = backend?.mysqlPool();
|
|
11
11
|
const auditPgPool = backend?.pgPool();
|
|
12
12
|
const auditLocalRoot = backend?.kind === "local" ? (config.localDataRoot ?? localRoot) : undefined;
|
|
@@ -66,8 +66,19 @@ export function createSessionFaces(ctx) {
|
|
|
66
66
|
if (deviceStore)
|
|
67
67
|
await deviceStore.deleteByRootSession(sessionId);
|
|
68
68
|
dropSessionScoped?.(sessionId);
|
|
69
|
-
if (
|
|
70
|
-
|
|
69
|
+
if (fileHistoryStore) {
|
|
70
|
+
if (typeof fileHistoryStore.deleteBySession === "function")
|
|
71
|
+
await fileHistoryStore.deleteBySession(sessionId);
|
|
72
|
+
else {
|
|
73
|
+
await fileHistoryStore.reap(sessionId, []);
|
|
74
|
+
logger.warn("session_file_history_baselines_retained", {
|
|
75
|
+
sessionId,
|
|
76
|
+
note: "the local file-history store has no whole-scope purge verb; boundaries were reaped but v1 baselines (original file bytes) remain under the data root until the upstream purge seam lands — recorded as an open deletion-rights gap, not silent",
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (backend?.legacySnapshotPurge)
|
|
81
|
+
await backend.legacySnapshotPurge(sessionId);
|
|
71
82
|
if (workflowCompletionInbox)
|
|
72
83
|
await workflowCompletionInbox.purge(sessionId, owner ?? null).catch((err) => logger.warn("workflow_completion_inbox_purge_failed", { sessionId, err: String(err) }));
|
|
73
84
|
await purgeScratchpadDir(config.localDataRoot ?? localRoot, sessionId);
|
package/dist/boot/stores.js
CHANGED
|
@@ -21,8 +21,9 @@ import { ensurePgDeviceSchema, ensureTiDBDeviceSchema } from "../plugins/device-
|
|
|
21
21
|
import { assertCloudSnapshotBlobPosture, openStoreBackendWithFallback } from "../plugins/store-backend.js";
|
|
22
22
|
import { buildMemoryRemoteLaneWarn, memoryEngineBackendFor, memoryEngineRemoteLanePosture } from "../memory-scope.js";
|
|
23
23
|
import { assertToolResultProvenanceSchema } from "../plugins/tool-result-store-sql.js";
|
|
24
|
-
import { assertPermissionRuleApprovalSchema } from "../plugins/permission-rule-store-sql.js";
|
|
24
|
+
import { assertPermissionRuleApprovalSchema, assertPermissionRuleTicketSchema } from "../plugins/permission-rule-store-sql.js";
|
|
25
25
|
import { assertApprovalAskRuleMaterialSchema } from "../plugins/approval-ask-store-sql.js";
|
|
26
|
+
import { assertFileHistorySchema } from "../plugins/file-history-store-sql.js";
|
|
26
27
|
import { resolveStreamApprovalGate } from "../tool-approval.js";
|
|
27
28
|
import { buildMemoryWriteBoundaryAudit, effectiveMemoryPersistenceCapable } from "./memory-boundary.js";
|
|
28
29
|
import { buildMemoryPosture } from "../memory-posture.js";
|
|
@@ -56,6 +57,10 @@ export async function openStores(ctx) {
|
|
|
56
57
|
await assertPermissionRuleApprovalSchema(async (sql) => ({ rows: (await pgPool.query(sql)).rows }), "pg");
|
|
57
58
|
else if (mysqlPool)
|
|
58
59
|
await assertPermissionRuleApprovalSchema(async (sql) => ({ rows: (await mysqlPool.query(sql))[0] }), "tidb");
|
|
60
|
+
if (pgPool)
|
|
61
|
+
await assertPermissionRuleTicketSchema(async (sql) => ({ rows: (await pgPool.query(sql)).rows }), "pg");
|
|
62
|
+
else if (mysqlPool)
|
|
63
|
+
await assertPermissionRuleTicketSchema(async (sql) => ({ rows: (await mysqlPool.query(sql))[0] }), "tidb");
|
|
59
64
|
}
|
|
60
65
|
if (resolveStreamApprovalGate({
|
|
61
66
|
toolApprovalEnabled: config.toolApprovalEnabled === true,
|
|
@@ -68,6 +73,31 @@ export async function openStores(ctx) {
|
|
|
68
73
|
else if (mysqlPool)
|
|
69
74
|
await assertApprovalAskRuleMaterialSchema(async (sql) => ({ rows: (await mysqlPool.query(sql))[0] }), "tidb");
|
|
70
75
|
}
|
|
76
|
+
if (pgPool)
|
|
77
|
+
await assertFileHistorySchema(async (sql) => ({ rows: (await pgPool.query(sql)).rows }), "pg");
|
|
78
|
+
else if (mysqlPool)
|
|
79
|
+
await assertFileHistorySchema(async (sql) => ({ rows: (await mysqlPool.query(sql))[0] }), "tidb");
|
|
80
|
+
{
|
|
81
|
+
const legacyProbeSql = "SELECT 1 FROM snapshot_manifest LIMIT 1";
|
|
82
|
+
const hasLegacyRows = await (pgPool
|
|
83
|
+
? pgPool.query(legacyProbeSql).then((r) => r.rows.length > 0)
|
|
84
|
+
: mysqlPool
|
|
85
|
+
? mysqlPool.query(legacyProbeSql).then(([rows]) => rows.length > 0)
|
|
86
|
+
: Promise.resolve(false)).catch(() => false);
|
|
87
|
+
if (hasLegacyRows) {
|
|
88
|
+
logger.warn("legacy_snapshot_epoch_rows_present", {
|
|
89
|
+
note: "rows from the RETIRED whole-tree snapshot epoch (snapshot_manifest/snapshot_blob) exist. They are NOT " +
|
|
90
|
+
"migrated (whole-tree manifests and per-file history are structurally different); rewind refusals for " +
|
|
91
|
+
"legacy-era boundaries name the retired epoch via the boundary probe; the retention lane keeps sweeping " +
|
|
92
|
+
"these rows by session, and the maintenance tick GCs their orphaned blob bytes.",
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if ((process.env.REWIND_SNAPSHOT_MAX_MB ?? "") !== "") {
|
|
98
|
+
logger.warn("rewind_snapshot_max_mb_retired", {
|
|
99
|
+
note: "REWIND_SNAPSHOT_MAX_MB no longer has an effect: the whole-tree snapshot epoch is retired (S-15); per-edited-file history captures only files the agent touches, with no tree walk and no size gate. Remove the env var. Per-blob SQL sizing is governed by SNAPSHOT_BLOB_SQL_MAX_BYTES / object storage as before.",
|
|
100
|
+
});
|
|
71
101
|
}
|
|
72
102
|
{
|
|
73
103
|
const minioReq = ["MINIO_ENDPOINT", "MINIO_ACCESS_KEY", "MINIO_SECRET_KEY"];
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* 高水位(next_id)与插入序(next_sort)都由 meta 行的事务计数器持有,`mutate` 是真后端事务。
|
|
22
22
|
* - `memory`:无 SQL 后端(local/file 形、纯内存 dev)⇒ **进程级** per-session 内存店。跨 turn
|
|
23
23
|
* 存活(这就是 F2 的修点),但**跨进程重启丢失**,且 LRU 溢出(> `maxSessions`)时最老的会话
|
|
24
|
-
* 会被逐出=那条会话的待办清空。诚实登记在 USAGE(「local 形重启丢待办」)
|
|
24
|
+
* 会被逐出=那条会话的待办清空。诚实登记在 USAGE(「local 形重启丢待办」),不自造持久性:
|
|
25
25
|
* 这与 local 形其余会话态设施(perSessionCwd / TtlSessionStore)是同一姿势。
|
|
26
26
|
*
|
|
27
27
|
* ## 为什么 SQL 形也进同一只缓存
|
|
@@ -50,7 +50,7 @@ export interface TaskListLane {
|
|
|
50
50
|
* 🔴 为什么必须有:会话 id 由调用方自选、会话删除后可被**别人** `register` 重新登记(security.ts
|
|
51
51
|
* 的 claim-create),而本车道的 listKey 是 `sessionId` 的确定性派生 ⇒ 不级联的话,新化身第一次
|
|
52
52
|
* 打开清单就读到上一位主人的任务标题/描述,`TaskCreate` 还会从上一位的高水位续号(「这里以前
|
|
53
|
-
* 建过 47
|
|
53
|
+
* 建过 47 条」本身也是外泄)。同族腿(anchors / approval-exemption / session-policy / attachment /
|
|
54
54
|
* snapshot / scratchpad)全部走同一条级联,本条与它们同 scoping 理由:路由已在 DELETE 门证过会话
|
|
55
55
|
* 所有权,故按 sessionId 单键删。
|
|
56
56
|
*
|
package/dist/brain.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import { createAnthropicBrain, createCircuitBreakerBrain, createDegradingBrain, createFailoverBrain, createOpenAIBrain, createRoutingBrain, } from "@sema-agent/core";
|
|
1
|
+
import { adjudicateModelRoute, createAnthropicBrain, createCircuitBreakerBrain, createDegradingBrain, createFailoverBrain, createOpenAIBrain, createRoutingBrain, hasAuthCarrier, resolveRouteCredential, routeRefusalText, } from "@sema-agent/core";
|
|
2
2
|
import { normalizeBaseUrl } from "@sema-agent/core";
|
|
3
3
|
import { resolveModelApiKey } from "./key-resolver.js";
|
|
4
|
-
import { isSealedKeyPoison } from "./sealed-key.js";
|
|
5
|
-
import { recordFailOpen } from "./observability/fail-open.js";
|
|
6
4
|
function isOffDeploymentRoot(baseUrl, config) {
|
|
7
5
|
if (!baseUrl)
|
|
8
6
|
return false;
|
|
@@ -11,6 +9,10 @@ function isOffDeploymentRoot(baseUrl, config) {
|
|
|
11
9
|
return false;
|
|
12
10
|
return ![config.gatewayBaseUrl, ...config.gatewayFallbackUrls].some((u) => normalizeBaseUrl(u) === entry);
|
|
13
11
|
}
|
|
12
|
+
function degradeDeclaredRoot(fallbackBaseUrl, config) {
|
|
13
|
+
const armed = Boolean(config.gatewayApiKey) && isOffDeploymentRoot(fallbackBaseUrl, config);
|
|
14
|
+
return armed ? config.gatewayBaseUrl : (fallbackBaseUrl || config.gatewayBaseUrl);
|
|
15
|
+
}
|
|
14
16
|
export const FAST_FAIL_MAX_RETRIES = 2;
|
|
15
17
|
const DEFAULT_RESILIENCE = {
|
|
16
18
|
connectTimeoutMs: 30_000,
|
|
@@ -61,7 +63,7 @@ export function createBrain(config, deps = {}) {
|
|
|
61
63
|
...(config.anthropic.authToken
|
|
62
64
|
? { headers: { Authorization: `Bearer ${config.anthropic.authToken}` } }
|
|
63
65
|
: { apiKey: config.anthropic.apiKey }),
|
|
64
|
-
baseUrl: config.anthropic.baseUrl,
|
|
66
|
+
baseUrl: config.anthropic.baseUrl ?? "https://api.anthropic.com",
|
|
65
67
|
version: config.anthropic.version,
|
|
66
68
|
cacheBreakpoints: config.anthropic.cacheBreakpoints,
|
|
67
69
|
...(config.anthropic.maxRetries !== undefined ? { maxRetries: config.anthropic.maxRetries } : {}),
|
|
@@ -76,44 +78,42 @@ export function createBrain(config, deps = {}) {
|
|
|
76
78
|
const degradeTo = config.degrade.to;
|
|
77
79
|
const fallbackModel = config.models[degradeTo];
|
|
78
80
|
if (fallbackModel) {
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
resolveModelApiKey(degradeTo, config.modelApiKeyEnv ?? {}, process.env, config.modelApiKeys ?? {});
|
|
82
|
-
return own ?? config.gatewayApiKey;
|
|
83
|
-
};
|
|
84
|
-
const hopBorrowsGatewayKey = () => {
|
|
85
|
-
const keys = config.modelApiKeys ?? {};
|
|
86
|
-
if (isSealedKeyPoison(keys[fallbackModel.name]) || isSealedKeyPoison(keys[degradeTo]))
|
|
87
|
-
return false;
|
|
88
|
-
const own = resolveModelApiKey(fallbackModel.name, config.modelApiKeyEnv ?? {}, process.env, keys) ??
|
|
89
|
-
resolveModelApiKey(degradeTo, config.modelApiKeyEnv ?? {}, process.env, keys);
|
|
90
|
-
return own === undefined && config.gatewayApiKey !== undefined && isOffDeploymentRoot(fallbackModel.baseUrl, config);
|
|
91
|
-
};
|
|
81
|
+
const fbOwnApiKey = () => resolveModelApiKey(fallbackModel.name, config.modelApiKeyEnv ?? {}, process.env, config.modelApiKeys ?? {}) ??
|
|
82
|
+
resolveModelApiKey(degradeTo, config.modelApiKeyEnv ?? {}, process.env, config.modelApiKeys ?? {});
|
|
92
83
|
const anthropicLaneHop = fallbackModel.provider === "anthropic" && anthropicBrain !== undefined;
|
|
93
84
|
const fallback = fallbackModel.provider === "anthropic" && anthropicBrain
|
|
94
85
|
?
|
|
95
86
|
anthropicBrain
|
|
96
87
|
: createOpenAIBrain({
|
|
97
|
-
|
|
88
|
+
get baseUrl() {
|
|
89
|
+
return degradeDeclaredRoot(fallbackModel.baseUrl, config);
|
|
90
|
+
},
|
|
98
91
|
get apiKey() {
|
|
99
|
-
return
|
|
92
|
+
return config.gatewayApiKey || undefined;
|
|
100
93
|
},
|
|
101
94
|
...(config.gatewayMaxRetries !== undefined ? { maxRetries: config.gatewayMaxRetries } : {}),
|
|
102
95
|
fetchImpl,
|
|
103
96
|
...timeouts,
|
|
104
97
|
});
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
98
|
+
const degradeEntryModel = {
|
|
99
|
+
...fallbackModel,
|
|
100
|
+
get headers() {
|
|
101
|
+
const own = fbOwnApiKey();
|
|
102
|
+
if (own === undefined)
|
|
103
|
+
return fallbackModel.headers;
|
|
104
|
+
const kept = {};
|
|
105
|
+
for (const [k, v] of Object.entries(fallbackModel.headers ?? {})) {
|
|
106
|
+
if (!hasAuthCarrier({ [k]: v }))
|
|
107
|
+
kept[k] = v;
|
|
108
|
+
}
|
|
109
|
+
return { ...kept, authorization: `Bearer ${own}` };
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
brain = createDegradingBrain({
|
|
113
|
+
primary: brain,
|
|
114
|
+
fallbacks: [{ brain: fallback, model: anthropicLaneHop ? fallbackModel : degradeEntryModel }],
|
|
115
|
+
downgradeOn: config.degrade.downgradeOn,
|
|
116
|
+
});
|
|
117
117
|
}
|
|
118
118
|
}
|
|
119
119
|
return brain;
|
|
@@ -143,6 +143,26 @@ export function brainSummary(config) {
|
|
|
143
143
|
reactiveDegradeBaseUrl: config.degrade?.reactive && config.models?.[config.degrade.to]
|
|
144
144
|
? config.models[config.degrade.to].baseUrl || config.gatewayBaseUrl
|
|
145
145
|
: null,
|
|
146
|
+
...((() => {
|
|
147
|
+
const target = config.degrade?.reactive ? config.models?.[config.degrade.to] : undefined;
|
|
148
|
+
if (!target)
|
|
149
|
+
return { reactiveDegradeRoutePairing: null, reactiveDegradeRouteRefusal: null };
|
|
150
|
+
if (target.provider === "anthropic" && config.anthropic) {
|
|
151
|
+
return { reactiveDegradeRoutePairing: "anthropic-lane", reactiveDegradeRouteRefusal: null };
|
|
152
|
+
}
|
|
153
|
+
const declaresOwnCredential = config.modelApiKeyEnv?.[target.name] !== undefined ||
|
|
154
|
+
config.modelApiKeyEnv?.[config.degrade.to] !== undefined ||
|
|
155
|
+
config.modelApiKeys?.[target.name] !== undefined ||
|
|
156
|
+
config.modelApiKeys?.[config.degrade.to] !== undefined ||
|
|
157
|
+
hasAuthCarrier(target.headers);
|
|
158
|
+
if (declaresOwnCredential) {
|
|
159
|
+
return { reactiveDegradeRoutePairing: "per-model-declared", reactiveDegradeRouteRefusal: null };
|
|
160
|
+
}
|
|
161
|
+
const verdict = adjudicateModelRoute({ id: target.id, baseUrl: target.baseUrl }, resolveRouteCredential({ ...(config.gatewayApiKey ? { configApiKey: config.gatewayApiKey } : {}) }), { baseUrl: degradeDeclaredRoot(target.baseUrl, config) });
|
|
162
|
+
return verdict.ok
|
|
163
|
+
? { reactiveDegradeRoutePairing: `ok:${verdict.posture}`, reactiveDegradeRouteRefusal: null }
|
|
164
|
+
: { reactiveDegradeRoutePairing: `broken:${verdict.code}`, reactiveDegradeRouteRefusal: routeRefusalText(verdict) };
|
|
165
|
+
})()),
|
|
146
166
|
};
|
|
147
167
|
}
|
|
148
168
|
//# sourceMappingURL=brain.js.map
|
package/dist/budget.d.ts
CHANGED
|
@@ -27,7 +27,7 @@ export declare function buildPricing(models: Record<string, Model>): Record<stri
|
|
|
27
27
|
export declare function isPricingConfigured(pricing: Record<string, ModelPricing>): boolean;
|
|
28
28
|
/**
|
|
29
29
|
* Bound the cardinality of a free-form metric label value (BL-11/BL-21). A label fed by untrusted/unbounded
|
|
30
|
-
* input — MCP tool names (a misconfigured/
|
|
30
|
+
* input — MCP tool names (a misconfigured/untrusted server can emit thousands of dynamic names) or center
|
|
31
31
|
* model ids (a malformed roster) — would otherwise mint an unbounded number of metric series: a slow memory
|
|
32
32
|
* leak in the registry + a /metrics scrape blow-up. We track the DISTINCT values seen; once the cap is hit,
|
|
33
33
|
* further NEW values collapse into one `__other__` bucket (already-seen values still report exactly). The
|
|
@@ -66,7 +66,7 @@ export declare class ModelUsageTracker {
|
|
|
66
66
|
private readonly active;
|
|
67
67
|
/** Mark a TOP-LEVEL run active so its `brain.call` usage is tracked. **Required** — `record` ignores any taskId
|
|
68
68
|
* that isn't registered. This is the leak fence: delegated SUB-TASKS (team members,
|
|
69
|
-
*
|
|
69
|
+
* independent verifiers) run on throwaway core-minted sessionIds that the run lifecycle never registers/drains,
|
|
70
70
|
* so without this gate their usage would accumulate under ids nothing ever clears → an unbounded process-lifetime
|
|
71
71
|
* leak. Sub-task spend is intentionally NOT in the per-run `modelUsage` echo (it lands in `TaskStats.nested`);
|
|
72
72
|
* `modelUsage` is the TOP-LEVEL run's own per-model usage. Call at run start; {@link clear} unregisters. */
|
|
@@ -29,7 +29,7 @@ export type PluginValidation = {
|
|
|
29
29
|
};
|
|
30
30
|
/** 条款 1/2/4:https-only、host 全等白名单、sha 40hex。纯函数,worker 侧纵深复验(不信任 wire 已验过)。 */
|
|
31
31
|
export declare function validatePluginDecl(decl: PluginDeclWire, allowHosts: readonly string[]): PluginValidation;
|
|
32
|
-
/** 条款 3/5:clone 计划(argv 序列 + 隔离 env)。纯数据,让"姿势"
|
|
32
|
+
/** 条款 3/5:clone 计划(argv 序列 + 隔离 env)。纯数据,让"姿势"可被锚定。 */
|
|
33
33
|
export declare function gitClonePlan(o: {
|
|
34
34
|
url: string;
|
|
35
35
|
dest: string;
|
|
@@ -37,7 +37,7 @@ export declare function registerCollabWorkflows(workflows: Record<string, Collab
|
|
|
37
37
|
/** composite WorkflowScriptStore 的 resolveName 前段:collab 命中 ⇒ 内置 team-discussion 脚本+本模板
|
|
38
38
|
* defaultArgs(同名 SHADOW core 内置,design/140 §6 1c)。🔴 Object.hasOwn — `name` 是模型供给的
|
|
39
39
|
* (run-workflow-tool 原样传 rawName):裸索引会让 Object.prototype 成员名("constructor"/"toString"/
|
|
40
|
-
* "__proto__"…)假命中 ⇒ 零模板注册也能烧真讨论、且同名文件 store 条目被遮蔽(
|
|
40
|
+
* "__proto__"…)假命中 ⇒ 零模板注册也能烧真讨论、且同名文件 store 条目被遮蔽(交叉评审 2026-07-11 MED)。 */
|
|
41
41
|
export declare function resolveCollabWorkflow(name: string): {
|
|
42
42
|
script: string;
|
|
43
43
|
defaultArgs: unknown;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* #196 场景 hands lane —— 「要手的场景」与「无手的场景」在装配层分家。
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* 根本问题(设计小票 §1,案源 [3208]/[3209]/[3212]):core 的手带工具面是 **per-Runner 表态**
|
|
5
5
|
* (`prepare-task`:`handsEnabled = ownedEnv || deps.executionEnv`,ownedEnv 只要挂了
|
|
6
6
|
* `executionEnvFactory` 就每任务必铸)。server 此前全场景共享一只 runner + 一只 subRunner,
|
|
7
7
|
* 于是任何 REMOTE_EXEC 部署里,声明 clone-free 的 `scan`、只有 `run_council` 的评审团、
|
|
@@ -37,7 +37,7 @@ export declare function pickHandsRunner(hands: ScenarioHands, pair: HandsRunnerP
|
|
|
37
37
|
*
|
|
38
38
|
* 两段来源,都不是拍脑袋:
|
|
39
39
|
* · `HAND_TOOL_EFFECTS`(core 导出面,`tools/fs`)—— band 的 effect 表,11 名。
|
|
40
|
-
* ·
|
|
40
|
+
* · 下方锚定补集 —— `createHandsToolkit` / 手带块还会铸但**不在** effect 表里的 5 名(实测差集,见
|
|
41
41
|
* test/scenario-hands-lane.test.ts 的对表格:它用真 Runner 跑「有手 roster ∖ 无手 roster」,与本常量逐名对账,
|
|
42
42
|
* core 加/改 band 成员时红,防漂移)。
|
|
43
43
|
*
|
|
@@ -50,7 +50,7 @@ export declare function pickHandsRunner(hands: ScenarioHands, pair: HandsRunnerP
|
|
|
50
50
|
* `hands: none` 三场景(scan/code-review/team)在**所有部署**上零 turn 全灭。core 5.21.1 已删
|
|
51
51
|
* 那条死条目([3249]),这道 filter 是结构性防御:将来 core 再退役任何 band 名都不会重演
|
|
52
52
|
* (test/scenario-hands-lane.test.ts 格7/格8 双钉:真 Runner 过审计 + 零交集门)。
|
|
53
|
-
* filter 打在**整表**(effect 表 +
|
|
53
|
+
* filter 打在**整表**(effect 表 + 锚定补集)之后 —— caret floor 下装置会解析到更新的 core,
|
|
54
54
|
* 补集名哪天被退役,只滤前半就是同一次故障换个名字(codex 复审 finding,2026-08-09)。
|
|
55
55
|
*/
|
|
56
56
|
export declare const HANDS_BAND_TOOL_NAMES: readonly string[];
|
|
@@ -65,7 +65,7 @@ export interface ScenarioDeps {
|
|
|
65
65
|
skills: LoadedSkill[];
|
|
66
66
|
repoClient?: RepoReadClient;
|
|
67
67
|
/** Multi-tenant deployment (REQUIRE_PRINCIPAL). Gates the full-body `WebFetch` tool out of the
|
|
68
|
-
* default roster — core says a multi-tenant deployment MUST allowlist hosts (an injected/
|
|
68
|
+
* default roster — core says a multi-tenant deployment MUST allowlist hosts (an injected/untrusted tenant model
|
|
69
69
|
* could exfil via an arbitrary public URL; the SSRF floor only blocks internal). Single-user TOC keeps WebFetch. */
|
|
70
70
|
requirePrincipal?: boolean;
|
|
71
71
|
/** Deployment-injected WebSearch backend (Brave/Tavily/SearXNG via `WEB_SEARCH_PROVIDER`). When set,
|
|
@@ -164,7 +164,7 @@ export declare function semaIdentityProvider(): PromptProvider;
|
|
|
164
164
|
* `code` 场景的提示词提供者([849] 造,[891] clay 裁定改名 autonomous→code):role 基底 = core
|
|
165
165
|
* {@link CODE_SYSTEM_PROMPT}(core 1.298 [891] 改名批正名,旧名 FULL_BODY_SYSTEM_PROMPT=恒等
|
|
166
166
|
* 别名过渡窗;CODE_AGENT persona + AUTONOMY_SELF_AUDIT + ANTI_VERBOSITY +
|
|
167
|
-
* TOOL_PARAM_JSON;[891]
|
|
167
|
+
* TOOL_PARAM_JSON;[891] 谱系定论 = CC 生产编码提示词的蒸馏去牌版,底本随 CC 版本对表 cc-anchors,
|
|
168
168
|
* 非自研)——与 bench 的请求组装完全同源,引用 core 常量随版本走,绝不复制字符串(tb bench 实测:
|
|
169
169
|
* 产品默认请求与同引擎 bench 态的差距根因就在这三件 persona/自检/终验)。品牌层与
|
|
170
170
|
* {@link semaIdentityProvider} 同构:brandIdentity 开时 SEMA_IDENTITY 叠在 role 基底之上;任务自带
|
|
@@ -252,7 +252,7 @@ export declare function centerScenarios(deps: ScenarioDeps, specs: CenterScenari
|
|
|
252
252
|
* by the HTTP layer (validateUserSkills); this stays pure merge policy.
|
|
253
253
|
*/
|
|
254
254
|
export declare function mergeUserSkills(scenarioSkills: SkillSpec[] | undefined, userSkills: SkillSpec[] | undefined, logger?: Logger): SkillSpec[] | undefined;
|
|
255
|
-
/** center caps view 的解析结果两键(
|
|
255
|
+
/** center caps view 的解析结果两键(形状锚定)。`scenario` null = 三层皆未配。 */
|
|
256
256
|
export interface ScenarioRuling {
|
|
257
257
|
scenario: string | null;
|
|
258
258
|
/** 纯场景名集合(principal/组名不上 wire);空 = 该 principal 无任何指派 = 无治理。 */
|
|
@@ -35,7 +35,7 @@ export interface LoadedSkill {
|
|
|
35
35
|
* ——那个便利是有意的(`foo.md -> 共享文件`)。`confineTo` 在场(**不可信 lane**:第三方 git checkout,
|
|
36
36
|
* 见 center-plugins 的 plugin 装载)= 每个被读条目 realpath 后必须仍在该根之内,逃逸即抛。
|
|
37
37
|
* 🔴 为什么信任级必须是**参数**而不是注释里的假设:本函数的头注原写着「skills dir 全受控」,而
|
|
38
|
-
* center-plugins 把它原样复用在
|
|
38
|
+
* center-plugins 把它原样复用在 不可信来源的 git checkout 上——git 原样保留仓里的 symlink,
|
|
39
39
|
* 于是 checkout 里某个 skill 条目(`任意 .md -> /宿主/任意文件`)会被读进 spec.files 进入提示词。resolvePluginSkillsRoot
|
|
40
40
|
* 只 realpath 守了 skills **根**,根下逐条目没守。 */
|
|
41
41
|
export interface LoadSkillsOptions {
|
|
@@ -17,6 +17,11 @@ export const BATCH1_LIMIT_KEYS = [
|
|
|
17
17
|
];
|
|
18
18
|
const B_SETTER_KEYS = ["rateLimitPerMin", "maxPrincipalCostUsd"];
|
|
19
19
|
export const DEFERRED_LIMIT_KEYS = [
|
|
20
|
+
{
|
|
21
|
+
key: "workspaceFileMaxBytes",
|
|
22
|
+
restartReason: "workspace-face-retired",
|
|
23
|
+
why: "the workspace browse face was retired with the whole-tree snapshot epoch (S-15) — this knob has no consumer left; the value is still validated and recorded for center-push compatibility, but applies to nothing (restart does not change that). Removal follows the settings-schema deprecation lane",
|
|
24
|
+
},
|
|
20
25
|
{
|
|
21
26
|
key: "costQuotaWindowSec",
|
|
22
27
|
restartReason: "cost-quota-window",
|
|
@@ -68,7 +68,7 @@ export declare class ConfigCenterHttpError extends Error {
|
|
|
68
68
|
}
|
|
69
69
|
/**
|
|
70
70
|
* Fetch one skill's body by content hash (`GET /api/config/skills/content/<hash>`, Bearer) and VERIFY its
|
|
71
|
-
* sha256 matches the manifest hash (integrity +
|
|
71
|
+
* sha256 matches the manifest hash (integrity + rewrite check). The content is immutable per hash, so the
|
|
72
72
|
* caller caches by hash and never re-fetches an unchanged skill. Throws a {@link ConfigCenterHttpError}
|
|
73
73
|
* (carrying `.status`) on an HTTP error — INCLUDING 404 — or a plain Error on hash mismatch. Callers that
|
|
74
74
|
* want "unknown hash → undefined" parity with the local backend inspect `.status === 404` and swallow it;
|
|
@@ -77,7 +77,7 @@ export declare class ConfigCenterHttpError extends Error {
|
|
|
77
77
|
export declare function fetchSkillContent(baseUrl: string, token: string, contentHash: string, fetchImpl?: typeof fetch): Promise<string>;
|
|
78
78
|
/** [985]b / [1285]① — §9.4 by-digest 补拉二函(fetchSkillContent 同姿势:HTTP+Bearer+8s 超时+
|
|
79
79
|
* 消费侧自证)。artifact=envelope JSON(验真=调用方过 core verifyPromptArtifact,canonical 重算——
|
|
80
|
-
*
|
|
80
|
+
* 本函数只做传输与形读,不超范围解释);blob=段文本 raw-byte(sha256 逐位自证,fetchSkillContent 同款)。
|
|
81
81
|
* digest 参数收带前缀/裸 hex 两形([1285] 参数口径)。 */
|
|
82
82
|
export declare function fetchPromptArtifact(baseUrl: string, token: string, artifactDigest: string, fetchImpl?: typeof fetch): Promise<unknown>;
|
|
83
83
|
export declare function fetchPromptBlob(baseUrl: string, token: string, contentDigest: string, fetchImpl?: typeof fetch): Promise<string>;
|
|
@@ -8,7 +8,7 @@ import type { CenterReadFace, EffectiveConfig } from "./types.js";
|
|
|
8
8
|
* 返回值 = **本机 env 显式占住的 center 键名**(与本次发布内容无关的部署事实)。调用方把它喂给
|
|
9
9
|
* `RestartSliceCtx.readFaceEnvHeld`,`read-face` restart 片于是只指纹「真会 boot-bake 的那部分」——
|
|
10
10
|
* 否则 center 改一个本机永远用不上的键,整片 fleet 会为一次对自己毫无影响的发布滚动重启一遍
|
|
11
|
-
* (codex
|
|
11
|
+
* (codex 交叉复审 finding 2,验真后采纳的那一半)。
|
|
12
12
|
*/
|
|
13
13
|
export declare function applyCenterReadFace(config: ServiceConfig, eff: EffectiveConfig, logger?: Logger): readonly (keyof CenterReadFace)[];
|
|
14
14
|
//# sourceMappingURL=read-face.d.ts.map
|
|
@@ -7,7 +7,7 @@ export interface RestartSliceCtx {
|
|
|
7
7
|
/** `config.degrade.to` when REACTIVE degrade is on (env `MODEL_DEGRADE_TO` + `MODEL_DEGRADE_REACTIVE`);
|
|
8
8
|
* undefined = the lane is off ⇒ no degrading brain was composed ⇒ nothing is boot-frozen. */
|
|
9
9
|
reactiveDegradeTo?: string;
|
|
10
|
-
/** #A4(codex
|
|
10
|
+
/** #A4(codex 交叉复审 finding 2,验真后采纳):本机 env **显式占住**的 readFace 键
|
|
11
11
|
* (`applyCenterReadFace` 的返回值,由 boot 存下)。这些键的 center 值在本机**永不 boot-bake**,
|
|
12
12
|
* 所以它们的变化不该产生 restart 理由 —— 否则 center 改一个本机用不上的键,整片 fleet 会为一次
|
|
13
13
|
* 对自己毫无影响的发布滚动重启一遍。缺席 = 没有 env 覆盖 ⇒ 整域都算数(与旧行为一致)。 */
|