@sema-agent/server 7.123.0 → 7.124.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 +132 -0
- package/README.md +2 -2
- package/README.zh-CN.md +2 -2
- package/USAGE.md +53 -51
- package/dist/approval-ask-audit-store.d.ts +27 -32
- package/dist/approval-ask-audit-store.js +10 -9
- package/dist/approval-crash-convergence.d.ts +2 -2
- package/dist/approval-crash-convergence.js +5 -5
- package/dist/approval-deny-reasons.d.ts +163 -51
- package/dist/approval-deny-reasons.js +79 -8
- package/dist/approval-policy-settlement.d.ts +4 -1
- package/dist/approval-policy-settlement.js +3 -2
- package/dist/approval-reconciler.d.ts +3 -3
- package/dist/approval-reconciler.js +10 -10
- package/dist/approval.d.ts +1 -1
- package/dist/approval.js +1 -1
- package/dist/audit.js +1 -1
- package/dist/auth-bridge.d.ts +8 -8
- package/dist/auth-bridge.js +6 -6
- package/dist/auth-keys.d.ts +2 -2
- package/dist/auto-mode-face.d.ts +1 -1
- package/dist/boot/budget-tracing.js +1 -1
- package/dist/boot/execution-env.js +1 -0
- package/dist/boot/leader.d.ts +1 -1
- package/dist/boot/memory-consolidation.d.ts +4 -4
- package/dist/boot/org-memory.d.ts +3 -3
- package/dist/boot/org-memory.js +5 -5
- package/dist/boot/resolve-spec.js +7 -7
- package/dist/boot/runner-deps.d.ts +1 -1
- package/dist/boot/runtime-caps.d.ts +1 -1
- package/dist/boot/runtime-caps.js +10 -10
- package/dist/boot/shutdown.d.ts +2 -2
- package/dist/boot/shutdown.js +2 -2
- package/dist/boot/side-query-lane.d.ts +3 -3
- package/dist/boot/{stage-02-registry-pull.d.ts → stage-02-web-admin-pull.d.ts} +2 -2
- package/dist/boot/{stage-02-registry-pull.js → stage-02-web-admin-pull.js} +4 -4
- package/dist/boot/stage-03-store-backend.d.ts +2 -2
- package/dist/boot/stage-04-stores.d.ts +1 -1
- package/dist/boot/stage-05-execution-env.d.ts +1 -1
- package/dist/boot/stage-06-runners.d.ts +2 -2
- package/dist/boot/stage-06-runners.js +6 -6
- package/dist/boot/stage-07-capability-layer.d.ts +2 -2
- package/dist/boot/stage-07-capability-layer.js +6 -5
- package/dist/boot/stage-08-reapers.d.ts +3 -3
- package/dist/boot/stage-08-reapers.js +3 -3
- package/dist/boot/stage-09-leader.d.ts +3 -3
- package/dist/boot/stage-09-leader.js +7 -7
- package/dist/boot/stage-10-http-server.d.ts +3 -3
- package/dist/boot/stage-10-http-server.js +19 -19
- package/dist/boot/unpriced-ceiling-verdict.d.ts +1 -1
- package/dist/boot/{config-center.d.ts → web-admin.d.ts} +11 -11
- package/dist/boot/{config-center.js → web-admin.js} +38 -22
- package/dist/boot/webfetch-summarize-lane.d.ts +2 -2
- package/dist/brain.d.ts +1 -1
- package/dist/brain.js +1 -1
- package/dist/budget.d.ts +3 -3
- package/dist/canonical-json.d.ts +2 -2
- package/dist/capabilities/center-plugins.d.ts +1 -1
- package/dist/capabilities/center-wiring.d.ts +12 -5
- package/dist/capabilities/center-wiring.js +11 -2
- package/dist/capabilities/composite-members.d.ts +1 -1
- package/dist/capabilities/composite-members.js +1 -1
- package/dist/capabilities/scenarios.js +2 -2
- package/dist/capabilities/team.d.ts +1 -1
- package/dist/capabilities/tool-defer.d.ts +1 -1
- package/dist/center-credential-renewer.d.ts +1 -1
- package/dist/center-credential-renewer.js +7 -7
- package/dist/center-credential.d.ts +9 -9
- package/dist/center-credential.js +6 -6
- package/dist/config-catalog.d.ts +7 -10
- package/dist/config-catalog.js +15 -15
- package/dist/config-d-migration.d.ts +32 -0
- package/dist/config-d-migration.js +59 -0
- package/dist/config-invariants.d.ts +14 -4
- package/dist/config-invariants.js +31 -2
- package/dist/config-lkg.d.ts +26 -6
- package/dist/config-lkg.js +43 -14
- package/dist/config-provider.d.ts +23 -19
- package/dist/config-provider.js +24 -26
- package/dist/config-types.d.ts +52 -51
- package/dist/config.d.ts +9 -46
- package/dist/config.js +33 -92
- package/dist/execution-lane-caps.d.ts +1 -1
- package/dist/fleet/drain-entry.d.ts +1 -1
- package/dist/fleet/engine-signal.d.ts +8 -8
- package/dist/fleet/fleet-bus.d.ts +12 -3
- package/dist/fleet/fleet-bus.js +13 -9
- package/dist/fleet/serving-lease.d.ts +3 -3
- package/dist/fleet/serving-lease.js +1 -1
- package/dist/fleet-client.d.ts +7 -7
- package/dist/fleet-client.js +5 -4
- package/dist/fleet-lease.d.ts +3 -3
- package/dist/fleet-lease.js +2 -2
- package/dist/host-lsp-manager.d.ts +1 -1
- package/dist/hosted-posture.d.ts +4 -4
- package/dist/http/admission.js +4 -4
- package/dist/http/checkpoint-ctx.d.ts +20 -3
- package/dist/http/checkpoint-ctx.js +13 -5
- package/dist/http/dispatch.js +2 -2
- package/dist/http/durable-run-leg.js +2 -1
- package/dist/http/health-self-report.d.ts +4 -4
- package/dist/http/health-self-report.js +3 -3
- package/dist/http/idempotency.d.ts +1 -1
- package/dist/http/resume-legs.d.ts +4 -3
- package/dist/http/resume-legs.js +31 -18
- package/dist/http/route-ctx.d.ts +8 -0
- package/dist/http/routes/admin-config-refresh.d.ts +1 -1
- package/dist/http/routes/admin-config-refresh.js +1 -1
- package/dist/http/routes/admin-drain.d.ts +1 -1
- package/dist/http/routes/admin-drain.js +5 -4
- package/dist/http/routes/approvals-assistant.js +4 -4
- package/dist/http/routes/capabilities.js +5 -5
- package/dist/http/routes/config-catalog.js +2 -3
- package/dist/http/routes/diagnostics.js +1 -1
- package/dist/http/routes/runs.js +8 -4
- package/dist/http/routes/sessions-list.js +2 -1
- package/dist/http/routes/sessions.js +1 -1
- package/dist/http/routes/side-query.js +3 -3
- package/dist/http/routes/tasks.js +3 -2
- package/dist/http/run-meta.d.ts +1 -1
- package/dist/http/run-meta.js +2 -2
- package/dist/http/server.d.ts +7 -7
- package/dist/http/server.js +1 -1
- package/dist/http/stored-body-replay.js +3 -2
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/key-resolver.d.ts +1 -1
- package/dist/leader/wire.d.ts +2 -2
- package/dist/leader/wire.js +2 -1
- package/dist/main.js +1 -1
- package/dist/mcp-tool-faces.d.ts +2 -2
- package/dist/model-entry-refusal.d.ts +3 -3
- package/dist/model-entry-refusal.js +4 -4
- package/dist/model-provider.d.ts +2 -2
- package/dist/model-route-endpoint.d.ts +1 -1
- package/dist/model-route-url.d.ts +1 -1
- package/dist/model-route-url.js +2 -1
- package/dist/model-select.d.ts +24 -21
- package/dist/model-select.js +22 -17
- package/dist/observability/metrics.d.ts +1 -1
- package/dist/org-memory-admission.d.ts +1 -1
- package/dist/plugins/approval-ask-store-file.d.ts +4 -2
- package/dist/plugins/approval-ask-store-file.js +3 -3
- package/dist/plugins/approval-ask-store-memory.d.ts +4 -3
- package/dist/plugins/approval-ask-store-memory.js +10 -4
- package/dist/plugins/approval-ask-store-sql.d.ts +16 -2
- package/dist/plugins/approval-ask-store-sql.js +20 -13
- package/dist/plugins/caching-session-store.d.ts +0 -10
- package/dist/plugins/caching-session-store.js +0 -3
- package/dist/plugins/file-run-store.js +9 -3
- package/dist/plugins/leader-run-store-sql.d.ts +3 -2
- package/dist/plugins/leader-run-store-sql.js +3 -2
- package/dist/plugins/local-session-store.d.ts +20 -27
- package/dist/plugins/local-session-store.js +19 -17
- package/dist/plugins/memory-run-store.js +9 -3
- package/dist/plugins/one-time-migrations.js +26 -2
- package/dist/plugins/scheduler-support.d.ts +26 -7
- package/dist/plugins/scheduler-support.js +96 -53
- package/dist/plugins/store-backend.js +1 -1
- package/dist/plugins/store-contracts.d.ts +20 -4
- package/dist/plugins/web-search.d.ts +1 -1
- package/dist/plugins/web-search.js +2 -1
- package/dist/posture-source.d.ts +1 -1
- package/dist/read-face-posture.d.ts +3 -3
- package/dist/read-face-posture.js +1 -1
- package/dist/run-local.js +6 -3
- package/dist/runtime-caps-resolver.d.ts +4 -4
- package/dist/runtime-caps-resolver.js +2 -2
- package/dist/runtime-governance.d.ts +5 -5
- package/dist/sealed-key.d.ts +4 -4
- package/dist/sealed-key.js +3 -2
- package/dist/security.d.ts +3 -3
- package/dist/service-version.d.ts +1 -1
- package/dist/service-version.js +5 -0
- package/dist/session-titler.d.ts +0 -11
- package/dist/session-titler.js +3 -5
- package/dist/shared-memory-scope-authorizer.d.ts +4 -4
- package/dist/task-a2a.d.ts +1 -1
- package/dist/tool-approval.d.ts +43 -4
- package/dist/tool-approval.js +147 -98
- package/dist/trace/core-keyset-guard.d.ts +1 -1
- package/dist/trace/project.d.ts +3 -3
- package/dist/trace/redact.d.ts +2 -23
- package/dist/trace/redact.js +1 -6
- package/dist/trace/self-minted-wire.d.ts +147 -3
- package/dist/trace/self-minted-wire.js +50 -9
- package/dist/url-refusal.d.ts +35 -0
- package/dist/url-refusal.js +15 -0
- package/dist/user-authored-text.d.ts +31 -0
- package/dist/user-authored-text.js +18 -0
- package/dist/{config-center → web-admin-client}/apply-effective.d.ts +13 -70
- package/dist/{config-center → web-admin-client}/apply-effective.js +100 -119
- package/dist/{config-center → web-admin-client}/apply-ledger.d.ts +2 -2
- package/dist/{config-center → web-admin-client}/center-request.d.ts +7 -7
- package/dist/{config-center → web-admin-client}/center-request.js +5 -4
- package/dist/{config-center → web-admin-client}/effective-keys.d.ts +1 -3
- package/dist/{config-center → web-admin-client}/effective-keys.js +0 -9
- package/dist/{config-center → web-admin-client}/facade.d.ts +6 -6
- package/dist/{config-center → web-admin-client}/facade.js +2 -2
- package/dist/{config-center → web-admin-client}/http-client.d.ts +6 -10
- package/dist/{config-center → web-admin-client}/http-client.js +12 -12
- package/dist/{config-center → web-admin-client}/pull-state.d.ts +1 -1
- package/dist/{config-center → web-admin-client}/read-face.js +4 -4
- package/dist/{config-center → web-admin-client}/read-warnings.d.ts +23 -16
- package/dist/{config-center → web-admin-client}/read-warnings.js +33 -23
- package/dist/{config-center → web-admin-client}/restart-signal.d.ts +5 -3
- package/dist/{config-center → web-admin-client}/restart-signal.js +3 -4
- package/dist/{config-center → web-admin-client}/skills-mcp.d.ts +1 -1
- package/dist/{config-center → web-admin-client}/skills-mcp.js +13 -13
- package/dist/{config-center → web-admin-client}/stage-limits.d.ts +1 -7
- package/dist/{config-center → web-admin-client}/stage-limits.js +6 -7
- package/dist/{config-center → web-admin-client}/types.d.ts +12 -39
- package/package.json +2 -2
- package/skills/find-skills.md +2 -2
- package/dist/url-shape.d.ts +0 -31
- package/dist/url-shape.js +0 -41
- /package/dist/{config-center → web-admin-client}/apply-ledger.js +0 -0
- /package/dist/{config-center → web-admin-client}/hot-keys-registry.d.ts +0 -0
- /package/dist/{config-center → web-admin-client}/hot-keys-registry.js +0 -0
- /package/dist/{config-center → web-admin-client}/mcp-revocation.d.ts +0 -0
- /package/dist/{config-center → web-admin-client}/mcp-revocation.js +0 -0
- /package/dist/{config-center → web-admin-client}/pull-state.js +0 -0
- /package/dist/{config-center → web-admin-client}/read-face.d.ts +0 -0
- /package/dist/{config-center → web-admin-client}/types.js +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { CANCELLED_CODE } from "./run-cancel-context.js";
|
|
2
2
|
import { settleByPolicy } from "./approval-policy-settlement.js";
|
|
3
3
|
import { isTerminalRunStatus } from "./plugins/store-contracts.js";
|
|
4
|
-
import {
|
|
4
|
+
import { APPROVAL_ENDING_CAUSES } from "./approval-deny-reasons.js";
|
|
5
5
|
import { buildRevokeFrame } from "./approval-card.js";
|
|
6
6
|
import { encodeCheckpointScope } from "./security.js";
|
|
7
7
|
const RECONCILE_STORE_TIMEOUT_MS = 10_000;
|
|
@@ -61,21 +61,21 @@ export function decideReconcileAction(input) {
|
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
if (batchState === "ABORTED")
|
|
64
|
-
return { kind: "void", reason:
|
|
64
|
+
return { kind: "void", reason: APPROVAL_ENDING_CAUSES.BATCH_ABORTED };
|
|
65
65
|
if (batchState === "ROUTING_BOUND" && input.batchBoundAskId != null && input.batchBoundAskId !== ask.askId) {
|
|
66
|
-
return { kind: "void", reason:
|
|
66
|
+
return { kind: "void", reason: APPROVAL_ENDING_CAUSES.BATCH_BOUND_ELSEWHERE };
|
|
67
67
|
}
|
|
68
68
|
if (run !== null && isTerminalRunStatus(run.status)) {
|
|
69
69
|
if (run.status === "failed" && run.errorCode === CANCELLED_CODE) {
|
|
70
|
-
return { kind: "void", reason:
|
|
70
|
+
return { kind: "void", reason: APPROVAL_ENDING_CAUSES.RUN_CANCELLED };
|
|
71
71
|
}
|
|
72
|
-
return { kind: "deny", reason:
|
|
72
|
+
return { kind: "deny", reason: APPROVAL_ENDING_CAUSES.ROUTING_FAILURE };
|
|
73
73
|
}
|
|
74
74
|
if (run === null && ask.sessionId === ask.taskId && nowMs > ask.expiresAtMs + adhocGraceMs) {
|
|
75
|
-
return { kind: "void", reason:
|
|
75
|
+
return { kind: "void", reason: APPROVAL_ENDING_CAUSES.ADHOC_LEG_NO_DURABLE_DOMAIN };
|
|
76
76
|
}
|
|
77
77
|
if (nowMs - ask.createdAtMs >= orphanTtlMs)
|
|
78
|
-
return { kind: "void", reason:
|
|
78
|
+
return { kind: "void", reason: APPROVAL_ENDING_CAUSES.ORPHAN_TTL_EXCEEDED };
|
|
79
79
|
void candidates;
|
|
80
80
|
return { kind: "hold" };
|
|
81
81
|
}
|
|
@@ -157,10 +157,10 @@ export function createApprovalReconciler(deps) {
|
|
|
157
157
|
const won = await withDeadline(askStore.transitionAsk(ask.askId, "PARKING", "VOID", { deniedReason: action.reason, updatedAtMs: nowMs }), "transitionAsk(VOID)");
|
|
158
158
|
if (!won)
|
|
159
159
|
return { outcome: "held", match: gateMatch };
|
|
160
|
-
if (action.reason ===
|
|
160
|
+
if (action.reason === APPROVAL_ENDING_CAUSES.ORPHAN_TTL_EXCEEDED) {
|
|
161
161
|
warn("approval_ask_orphan_voided", { askId: ask.askId, taskId: ask.taskId, ageMs: nowMs - ask.createdAtMs, ttlMs: orphanTtlMs });
|
|
162
162
|
}
|
|
163
|
-
revoke(ask, [ask.askId], action.reason ===
|
|
163
|
+
revoke(ask, [ask.askId], action.reason === APPROVAL_ENDING_CAUSES.BATCH_BOUND_ELSEWHERE ? "superseded_by_park" : "aborted", nowMs);
|
|
164
164
|
return { outcome: "voided", match: gateMatch };
|
|
165
165
|
}
|
|
166
166
|
case "hold": {
|
|
@@ -274,7 +274,7 @@ export function createApprovalReconciler(deps) {
|
|
|
274
274
|
if (row.expiresAtMs + pendingGraceMs >= nowMs)
|
|
275
275
|
continue;
|
|
276
276
|
try {
|
|
277
|
-
const res = await withDeadline(settleByPolicy(askStore, row, unattendedPolicy), "claimTerminal(orphan)");
|
|
277
|
+
const res = await withDeadline(settleByPolicy(askStore, row, unattendedPolicy, APPROVAL_ENDING_CAUSES.TTL_EXPIRED), "claimTerminal(orphan)");
|
|
278
278
|
if (!res.claimed)
|
|
279
279
|
continue;
|
|
280
280
|
stats.orphansExpired += 1;
|
package/dist/approval.d.ts
CHANGED
|
@@ -58,7 +58,7 @@ export declare function singleUserAutoAcceptBaselineApplies(config: GateIntentVi
|
|
|
58
58
|
* HIGH;与 env 墓碑族同谱系)。v4.3.0 的轮询门形(APPROVAL_REQUIRE + DB backend + DURABLE_APPROVAL 未设)在
|
|
59
59
|
* 5.0.0 只剩 core 每任务 warn——**原先拦、现在放**(方向反转)。「留 undefined 让 core warn」对新配置是
|
|
60
60
|
* 曝露误配,对升级存量是门静默消失,后者必须响亮。
|
|
61
|
-
* · **热路径**(S-668 波 2 ④,`
|
|
61
|
+
* · **热路径**(S-668 波 2 ④,`web-admin-client/apply-effective.ts` 的审批组 stage):对**候选视图**
|
|
62
62
|
* (活配置 + 候选名单)判,拒因 ⇒ 审批组**整组拒**、活配置零变化、世代账停旧代。进程在跑,拒启不是选项;
|
|
63
63
|
* 而放行一份「没有 checkpoint 店可停车」的名单 = 单用户 auto-accept 基线仍在、名单静默不生效。
|
|
64
64
|
* · **每个任务的装配**(S-1144,`boot/resolve-spec.ts` 的 `resolveSpec` 头一道):对**活配置**判,拒因 ⇒ 请求 501
|
package/dist/approval.js
CHANGED
|
@@ -58,7 +58,7 @@ export function buildForceDurableGateInertNotice(input) {
|
|
|
58
58
|
event: "center_force_durable_gate_inert",
|
|
59
59
|
fields: {
|
|
60
60
|
durableApproval: input.durableApproval,
|
|
61
|
-
note: "this deployment resolves per-principal entitlements from
|
|
61
|
+
note: "this deployment resolves per-principal entitlements from web-admin, but it has NO checkpoint store " +
|
|
62
62
|
(input.durableApproval
|
|
63
63
|
? "(DURABLE_APPROVAL=true, yet the configured backend exposes no checkpoint face)"
|
|
64
64
|
: "(DURABLE_APPROVAL is off)") +
|
package/dist/audit.js
CHANGED
|
@@ -4,6 +4,7 @@ import { PgSessionStorage } from "./plugins/pg-session-storage.js";
|
|
|
4
4
|
import { createLocalSessionRepo } from "./plugins/local-session-store.js";
|
|
5
5
|
import { redactModelText } from "./observability/run-terminal.js";
|
|
6
6
|
import { redactDeepWith } from "./trace/redact.js";
|
|
7
|
+
import { INJECTED_BLOCK_RE } from "./user-authored-text.js";
|
|
7
8
|
export async function buildSessionAudit(pool, sessionId) {
|
|
8
9
|
return auditFromStorage(await TiDBSessionStorage.wake(pool, sessionId), sessionId);
|
|
9
10
|
}
|
|
@@ -142,7 +143,6 @@ export function windowMessages(messages, opts) {
|
|
|
142
143
|
const offset = Math.max(0, total - tail);
|
|
143
144
|
return { messages: messages.slice(offset), window: { offset, total } };
|
|
144
145
|
}
|
|
145
|
-
const INJECTED_BLOCK_RE = /<(system-reminder|task-notification)(?:\s[^>]*)?>[\s\S]*?<\/\1>\s*/g;
|
|
146
146
|
function capWithInjectionAwareness(s, capBytes) {
|
|
147
147
|
const total = Buffer.byteLength(s, "utf8");
|
|
148
148
|
if (total <= capBytes)
|
package/dist/auth-bridge.d.ts
CHANGED
|
@@ -4,22 +4,22 @@ import type { Metrics } from "./observability/metrics.js";
|
|
|
4
4
|
export type { VerifiedIdentity } from "@sema-agent/settings-schema/api/auth-bridge";
|
|
5
5
|
/**
|
|
6
6
|
* S-866 ② —— 鉴权桥 issuer 的**唯一**取值(装配 `boot/stage-09-leader.ts` 与 caps `centerWiring.issuer` 同读,不各写一份回退):
|
|
7
|
-
* 显式 `AUTH_BRIDGE_ISSUER`(`config.authBridgeIssuer`)恒赢 ⇒ `source:"explicit"`;缺席则回退中心基址 `
|
|
7
|
+
* 显式 `AUTH_BRIDGE_ISSUER`(`config.authBridgeIssuer`)恒赢 ⇒ `source:"explicit"`;缺席则回退中心基址 `webAdmin.baseUrl`
|
|
8
8
|
* (配了中心即默认开桥)⇒ `source:"fallback"`;两者都没有 ⇒ `undefined`(桥不装)。
|
|
9
9
|
*/
|
|
10
10
|
export declare function authBridgeIssuerOf(config: {
|
|
11
11
|
readonly authBridgeIssuer?: string | undefined;
|
|
12
|
-
readonly
|
|
12
|
+
readonly webAdmin?: {
|
|
13
13
|
readonly baseUrl: string;
|
|
14
14
|
} | undefined;
|
|
15
15
|
}): {
|
|
16
16
|
readonly issuer: string;
|
|
17
17
|
readonly source: "explicit" | "fallback";
|
|
18
18
|
} | undefined;
|
|
19
|
-
export interface
|
|
20
|
-
/** R4 — 期望 iss(registry 的 SSO_ISSUER;默认=
|
|
19
|
+
export interface WebAdminJwtVerifierOptions {
|
|
20
|
+
/** R4 — 期望 iss(registry 的 SSO_ISSUER;默认=SEMA_WEB_ADMIN_URL,双侧去尾斜杠比较)。 */
|
|
21
21
|
issuer: string;
|
|
22
|
-
/** R2 — JWKS 绝对 URL(默认=issuer +
|
|
22
|
+
/** R2 — JWKS 绝对 URL(默认=issuer + WEB_ADMIN_JWKS_PATH)。 */
|
|
23
23
|
jwksUrl?: string;
|
|
24
24
|
/** R7 — 设了则 aud 必须包含它;不设=忽略 aud。 */
|
|
25
25
|
audience?: string;
|
|
@@ -41,13 +41,13 @@ export type VerifyOutcome = {
|
|
|
41
41
|
ok: false;
|
|
42
42
|
error: AuthBridgeErrorCode;
|
|
43
43
|
};
|
|
44
|
-
/** The live object `
|
|
45
|
-
export interface
|
|
44
|
+
/** The live object `createWebAdminJwtVerifier` produces — a single `verify` entry point over the process-level JWKS cache. */
|
|
45
|
+
export interface WebAdminJwtVerifier {
|
|
46
46
|
verify: (bearer: string) => Promise<VerifyOutcome>;
|
|
47
47
|
}
|
|
48
48
|
/**
|
|
49
49
|
* registry-JWT verifier(单例,进程级 JWKS 缓存)。`verify(bearer)` 全程不 throw——一切异常折为
|
|
50
50
|
* AUTH_BRIDGE_ERROR_CODES(HTTP 面由调用方恒答 generic 401,码只进日志/metrics,R9)。
|
|
51
51
|
*/
|
|
52
|
-
export declare function
|
|
52
|
+
export declare function createWebAdminJwtVerifier(opts: WebAdminJwtVerifierOptions): WebAdminJwtVerifier;
|
|
53
53
|
//# sourceMappingURL=auth-bridge.d.ts.map
|
package/dist/auth-bridge.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { createPublicKey, verify as cryptoVerify } from "node:crypto";
|
|
2
|
-
import { AUTH_BRIDGE_ALGS, DEFAULT_CLOCK_SKEW_SEC, DEFAULT_JWKS_REFRESH_MIN_INTERVAL_SEC, DEFAULT_OFFLINE_GRACE_SEC,
|
|
2
|
+
import { AUTH_BRIDGE_ALGS, DEFAULT_CLOCK_SKEW_SEC, DEFAULT_JWKS_REFRESH_MIN_INTERVAL_SEC, DEFAULT_OFFLINE_GRACE_SEC, WEB_ADMIN_JWKS_PATH, WebAdminJwks, classifyTimeClaims, jwksWithinOfflineGrace, shouldForceJwksRefresh, toVerifiedIdentity, } from "@sema-agent/settings-schema/api/auth-bridge";
|
|
3
3
|
import { buildDisplaySafeUrl } from "./trace/redact.js";
|
|
4
4
|
export function authBridgeIssuerOf(config) {
|
|
5
5
|
if (config.authBridgeIssuer !== undefined)
|
|
6
6
|
return { issuer: config.authBridgeIssuer, source: "explicit" };
|
|
7
|
-
if (config.
|
|
8
|
-
return { issuer: config.
|
|
7
|
+
if (config.webAdmin !== undefined)
|
|
8
|
+
return { issuer: config.webAdmin.baseUrl, source: "fallback" };
|
|
9
9
|
return undefined;
|
|
10
10
|
}
|
|
11
11
|
const DEFAULT_JWKS_TTL_SEC = 15 * 60;
|
|
@@ -25,10 +25,10 @@ function b64urlJson(seg) {
|
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
const stripSlash = (s) => s.replace(/\/+$/, "");
|
|
28
|
-
export function
|
|
28
|
+
export function createWebAdminJwtVerifier(opts) {
|
|
29
29
|
const issuer = stripSlash(opts.issuer);
|
|
30
30
|
const displayIssuer = buildDisplaySafeUrl(issuer);
|
|
31
|
-
const jwksUrl = opts.jwksUrl ?? `${issuer}${
|
|
31
|
+
const jwksUrl = opts.jwksUrl ?? `${issuer}${WEB_ADMIN_JWKS_PATH}`;
|
|
32
32
|
const clockSkewSec = opts.clockSkewSec ?? DEFAULT_CLOCK_SKEW_SEC;
|
|
33
33
|
const refreshMin = opts.jwksRefreshMinIntervalSec ?? DEFAULT_JWKS_REFRESH_MIN_INTERVAL_SEC;
|
|
34
34
|
const offlineGraceSec = opts.offlineGraceSec ?? DEFAULT_OFFLINE_GRACE_SEC;
|
|
@@ -59,7 +59,7 @@ export function createRegistryJwtVerifier(opts) {
|
|
|
59
59
|
const buf = Buffer.from(await res.arrayBuffer());
|
|
60
60
|
if (buf.byteLength > MAX_JWKS_BYTES)
|
|
61
61
|
throw new Error("jwks body too large");
|
|
62
|
-
const doc =
|
|
62
|
+
const doc = WebAdminJwks.parse(JSON.parse(buf.toString("utf8")));
|
|
63
63
|
const next = new Map();
|
|
64
64
|
for (const k of doc.keys) {
|
|
65
65
|
try {
|
package/dist/auth-keys.d.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* (verifyApprovalHmac / verifyPrincipalJwt) stay in ./approval-hmac.ts and ./principal-jwt.ts; consumers import these four names from HERE ([ref] 兼容面全清).
|
|
9
9
|
*/
|
|
10
10
|
/** One key in the rotating HMAC key-set. `kid` lets the verifier pick the signing key (or fall back to trying the
|
|
11
|
-
* whole set); `status` lets
|
|
11
|
+
* whole set); `status` lets web-admin rotate without breaking in-flight approvals: `active` = sign + verify,
|
|
12
12
|
* `retiring` = verify-only (kept for the overlap window so a MAC signed with the old key still verifies). */
|
|
13
13
|
export interface ApprovalHmacKey {
|
|
14
14
|
kid: string;
|
|
@@ -36,7 +36,7 @@ export interface KeySetRejection {
|
|
|
36
36
|
* 门数的 SHAPE B;这两条钥又都在凭据轴上,所以由**类型**逼每个调用点当场表态,而不是靠人记得去接。
|
|
37
37
|
*/
|
|
38
38
|
export type OnKeySetRejection = (rejection: KeySetRejection) => void;
|
|
39
|
-
/** Parse APPROVAL_HMAC_KEYS — a
|
|
39
|
+
/** Parse APPROVAL_HMAC_KEYS — a web-admin-managed, rotating key-SET, as a JSON array of {kid,key,status}.
|
|
40
40
|
* Empty / unset / unparseable ⇒ `[]` ⇒ HMAC verification is OFF (D-G inactive; back-compat, BFF-only door).
|
|
41
41
|
* fail-closed 语义与改前**逐字相同**;新增的只有 `onReject`([ref]:每一条被丢弃的条目都要说出来)。 */
|
|
42
42
|
export declare function parseApprovalHmacKeys(raw: string | undefined, onReject: OnKeySetRejection): ApprovalHmacKey[];
|
package/dist/auto-mode-face.d.ts
CHANGED
|
@@ -104,7 +104,7 @@ export interface AutoModeFaceDeps {
|
|
|
104
104
|
/** 分类器**配置**的模型路由(server 侧按 core 的 role 回落序 `classifier → summarize → default` 从
|
|
105
105
|
* `config.roles` 读到的 catalog 名)。这是「配置了什么」,不是「这次真用了什么」——core 的
|
|
106
106
|
* `derivedRouteFallsBack` 可能在运行期回落到主模型;真值候 core 状态座。
|
|
107
|
-
* 🔴 codex r3 [medium]:是 **getter** 不是快照——
|
|
107
|
+
* 🔴 codex r3 [medium]:是 **getter** 不是快照——web-admin 会原地热更新 `config.roles`(Runner 每任务从活引用
|
|
108
108
|
* 重解),boot 期铸的字符串会在热切换后永久陈旧;生产装配递的 getter 调 `classifierRouteFor({ models: config.models, roles: config.roles })` 并把 fault 记 debug。 */
|
|
109
109
|
readonly classifierModel?: (() => string | undefined) | undefined;
|
|
110
110
|
}
|
|
@@ -2,7 +2,7 @@ import { createBrainAssembly } from "../brain.js";
|
|
|
2
2
|
import { ModelUsageTracker, PromptManifestTracker, buildPricing, createSideQueryAccountant, createTracer } from "../budget.js";
|
|
3
3
|
import { FleetUsageAccumulator } from "../fleet-client.js";
|
|
4
4
|
import { createFleetLeaseFromEnv } from "../fleet-lease.js";
|
|
5
|
-
import { centerLaneConfigured } from "../
|
|
5
|
+
import { centerLaneConfigured } from "../web-admin-client/center-request.js";
|
|
6
6
|
import { CostQuota } from "../observability/cost-quota.js";
|
|
7
7
|
import { buildQuotaBounds } from "./limit-sync.js";
|
|
8
8
|
import { assembleFileHistory } from "../file-history-capture.js";
|
|
@@ -209,6 +209,7 @@ export function createExecutionEnv(ctx) {
|
|
|
209
209
|
const hostScheduler = facts.hostScheduler(config).available
|
|
210
210
|
? new FileSchedulerBackend({
|
|
211
211
|
storePath: schedulerStorePath,
|
|
212
|
+
log: logger,
|
|
212
213
|
...(config.schedulerSessionWakeup === false || config.schedulerSessionLifetime === false
|
|
213
214
|
? {
|
|
214
215
|
caps: {
|
package/dist/boot/leader.d.ts
CHANGED
|
@@ -37,7 +37,7 @@ export interface LeaderCtx {
|
|
|
37
37
|
/** [ref]([ref],[ref]-T1)—— 治理窗**账本店**(与 `config.usageWindows` 声明成对;声明直接从
|
|
38
38
|
* 本 ctx 的 config 取,leader 不另读)。缺席 = 未配治理窗的部署。必填键,理由同 `tracer`。 */
|
|
39
39
|
usageWindowStore: RunnerDeps["usageWindowStore"];
|
|
40
|
-
/** [ref]([ref])—— center 发布的 prompt catalog(`
|
|
40
|
+
/** [ref]([ref])—— center 发布的 prompt catalog(`webAdmin.promptSource`,与主 runner/subRunner
|
|
41
41
|
* 同一只)。缺席 ⇒ leader 的四类顶层任务跑引擎内置提示词,而同部署其余三条腿跑运维发布的那一份,
|
|
42
42
|
* 且 core 顶层新任务是**静默**落回(无 notice)。必填键,理由同 `tracer`。 */
|
|
43
43
|
promptSource: RunnerDeps["promptSource"];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { RestartSliceCtx } from "../
|
|
1
|
+
import type { RestartSliceCtx } from "../web-admin-client/restart-signal.js";
|
|
2
2
|
import type { MemoryConsolidationDriverConfig, ServiceConfig } from "../config-types.js";
|
|
3
3
|
import { type ConsolidationDriverRunRow, type ConsolidationRunReceipt, type MemoryBackend, type MemoryConsolidationDriverDeps, type RunMemoryConsolidationOptions, type SessionCaptureRecordStore } from "@sema-agent/core";
|
|
4
4
|
/** D3 投影的座标签闭集。`role:<name>` 里的 name 只可能是 core 的 role 链两跳之一。 */
|
|
@@ -178,14 +178,14 @@ export declare function consolidationDriverUnwirable(input: ConsolidationWiringF
|
|
|
178
178
|
* ({@link seatLabel} 注里同一条理由:抄一份就是第二真源,而 `ROLE_TIER_DEFAULTS` 的 flash 缺省会让手抄版答错)。
|
|
179
179
|
*
|
|
180
180
|
* 为什么不按 env `MODEL_CHEAP_ID` 的拼写判:它只是供座的一条路。env 角色表在它缺席时把 summarize 指回
|
|
181
|
-
* `default`(`config.ts` 的 `cheapRef`),而目录(`config.d/models.json` /
|
|
181
|
+
* `default`(`config.ts` 的 `cheapRef`),而目录(`config.d/models.json` / web-admin)的 roles / 档位同样能供
|
|
182
182
|
* consolidate / summarize 两跳 —— 判「装配后的座落不落主模型」才与计费事实同形(整理跑按座的模型计费)。
|
|
183
183
|
*
|
|
184
184
|
* 主模型 = 本仓给每条 task 铸的 `DEFAULT_MODEL_REF` 解到的那只(`boot/resolve-spec.ts` 每条 spec 都盖 `spec.model`),
|
|
185
185
|
* **不是** core 的 `default` 角色链 —— 与 `auto-mode-face.ts` 的 `classifierRouteFor` 同一口径(共用 `model-select.ts`
|
|
186
186
|
* `resolveMainModel`);喂**展开**目录,与引擎构造期 `expandTiers` 之后再解逐字同源。比的是**目录条目身份**(对象引用),
|
|
187
187
|
* **不比 `Model.id` 串**(车PI 修复轮 ⑤ / codex C-2:两条不同名的条目可以共享上游 id 却各带不同的 baseUrl / 凭据 / 价,那是两只
|
|
188
|
-
* 模型;与 `model-select.ts` `
|
|
188
|
+
* 模型;与 `model-select.ts` `isAtMentionable` 同一口径)。env 的「cheap id == 主 id」不会走到这里变成两只:`config.ts` 在铸造处
|
|
189
189
|
* 就不铸那只影子条目(车PI 验修轮 B)。
|
|
190
190
|
* 探针 brain 零请求:座解析只 `brainToRuntime` 它一次,真被调用 = 装配缺陷,响亮抛。
|
|
191
191
|
* ⚠️ **爆炸半径**(车PI 验修轮 F10,如实登记):判决的每一臂 —— 包括未设 + 没配便宜模型的派生关(TOC 最常见的形)—— 都走
|
|
@@ -212,7 +212,7 @@ export declare function consolidationSeatBillingOf(plane: ConsolidationSeatPlane
|
|
|
212
212
|
* 拒因说清「为什么没开」。在 `loadConfig` 判会把「未设 + scope + 便宜模型在场」这台本该派生成开的部署当场拒掉。
|
|
213
213
|
*
|
|
214
214
|
* ⚠️ **起服判一次**(restart-to-apply):判决落在 boot 第 4 段的装配点 {@link createConsolidationValve} —— 目录已应用
|
|
215
|
-
* (`config.d/models.json` /
|
|
215
|
+
* (`config.d/models.json` / web-admin 的 boot 采纳或 LKG)、记忆引擎已接线;座解析在第 6 段读这份判决。之后中心热改了 roles / 档位(或 boot 拉取超窗、目录迟到),**阀门不跟着翻**,
|
|
216
216
|
* 但翻的**需要**由 `memory-consolidation` 重启片报出来({@link createConsolidationValveWatch}):开着的那台盯座位漂移;
|
|
217
217
|
* 派生关的那台盯「此刻重判会不会开」(codex 车内复审 F2:修前派生关没有任何读数,热加一只便宜模型零信号、阀门永远关着)。
|
|
218
218
|
*/
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* 的两个 seam(`RunnerDeps.memoryScopeAdmission` / `RunnerDeps.deploymentMemoryScopes`)。
|
|
4
4
|
*
|
|
5
5
|
* 目录源三态(单选,授权面不做双源合并):
|
|
6
|
-
* · center 在场(
|
|
6
|
+
* · center 在场(webAdmin 且非 dryRun)⇒ 远程腿:per-principal caps 响应的 `orgMemory` 段
|
|
7
7
|
* (走 `fetchPrincipalOrgMemory` —— 与 caps 腿同一条 HTTP 请求形与同一道 principal 回声核,但**只
|
|
8
8
|
* 投影 org 段**读,治理面值漂移不连坐;段键缺席=旧 center 能力握手 ⇒ 目录记 section_absent 瞬时)。
|
|
9
9
|
* **独立 fetch,不复用 caps 缓存条目**(C3:org 授权段自带判别联合缓存,两张表的失败域互不干扰
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
*
|
|
18
18
|
* 能力探测(C12,fail-loud):多租户(requirePrincipal)部署 **且记忆面真点亮**(MEMORY_ENGINE 开 +
|
|
19
19
|
* backend 非 file——见下方 `memoryPlaneLive` 注)的 projects 登记簿里挂了 org 键 ——这些键在多租户下
|
|
20
|
-
* 按 request-origin 盖章(N2 部署形态维)——而目录源缺席(含
|
|
20
|
+
* 按 request-origin 盖章(N2 部署形态维)——而目录源缺席(含 webAdmin dryRun 形)⇒ 启动报错:
|
|
21
21
|
* 该部署的每个 projectId 请求都会在 prepare 期被整拒,「audit 在跑但恒拒」不是可运行状态,响亮拒
|
|
22
22
|
* 启动比静默全拒服务诚实(clay 三裁 [ref]:直接 BREAKING,不留兼容臂)。记忆面 dark 的部署里这些
|
|
23
23
|
* 键根本到不了准入门,不在探测范围(复审 D-1)。
|
|
@@ -46,7 +46,7 @@ export interface OrgMemoryAdmissionWiring {
|
|
|
46
46
|
*
|
|
47
47
|
* 为什么这个消费点必须活取而上面那个可以不:共享记忆读面对 principal-less 请求**直接**把这组 scope
|
|
48
48
|
* 当作全部授权事实交出去(没有第二道盖章腿能纠正它)⇒ 快照在新增方向让新登记的 org 库变成终局式
|
|
49
|
-
* 空集、在撤销方向让已下架的 scope 继续被放行(fail-open),而 `config.projects` 恰恰是
|
|
49
|
+
* 空集、在撤销方向让已下架的 scope 继续被放行(fail-open),而 `config.projects` 恰恰是 web-admin
|
|
50
50
|
* 标注「🟢 热生效」的字段、且 env 腿恒空(只可能由 center 灌)。判据本体与快照同源(同一个
|
|
51
51
|
* `collectDeploymentOrgScopes`),差别只有取值时机。
|
|
52
52
|
*/
|
package/dist/boot/org-memory.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { fetchPrincipalOrgMemory } from "../
|
|
1
|
+
import { fetchPrincipalOrgMemory } from "../web-admin-client/http-client.js";
|
|
2
2
|
import { createIdentityBins } from "../center-credential.js";
|
|
3
3
|
import { createMemoryScopeAdmission, createOrgMemoryDirectory, parseOrgDirectoryStatic } from "../org-memory-admission.js";
|
|
4
4
|
const ORG_PREFIX = "org:";
|
|
@@ -18,11 +18,11 @@ function collectDeploymentOrgScopes(config) {
|
|
|
18
18
|
export function createOrgMemoryAdmissionWiring(opts) {
|
|
19
19
|
const { config, logger, metrics } = opts;
|
|
20
20
|
const deploymentMemoryScopes = collectDeploymentOrgScopes(config);
|
|
21
|
-
const centerLeg = config.
|
|
21
|
+
const centerLeg = config.webAdmin !== undefined && !config.webAdmin.dryRun ? config.webAdmin : undefined;
|
|
22
22
|
const staticJson = config.memoryOrgDirectoryJson;
|
|
23
23
|
if (centerLeg !== undefined && staticJson !== undefined) {
|
|
24
24
|
logger.warn("org_memory_directory_env_ignored", {
|
|
25
|
-
reason: "MEMORY_ORG_DIRECTORY_JSON is set but a
|
|
25
|
+
reason: "MEMORY_ORG_DIRECTORY_JSON is set but a web-admin is wired — the center directory wins; the env table is IGNORED (authorization faces never merge two sources)",
|
|
26
26
|
});
|
|
27
27
|
}
|
|
28
28
|
const directory = centerLeg !== undefined
|
|
@@ -48,8 +48,8 @@ export function createOrgMemoryAdmissionWiring(opts) {
|
|
|
48
48
|
.map(([id]) => id);
|
|
49
49
|
if (orgProjects.length > 0) {
|
|
50
50
|
throw new Error(`multi-tenant deployment has org: keys in projects[${orgProjects.join(", ")}].defaultScopes but NO org-memory directory source ` +
|
|
51
|
-
`(
|
|
52
|
-
`(memory.admission_required, fail-closed). Wire a
|
|
51
|
+
`(web-admin absent/dry-run and MEMORY_ORG_DIRECTORY_JSON unset) — every request selecting these projects would be refused at prepare ` +
|
|
52
|
+
`(memory.admission_required, fail-closed). Wire a web-admin or set MEMORY_ORG_DIRECTORY_JSON, or remove the org keys.`);
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
const memoryScopeAdmission = directory !== undefined
|
|
@@ -17,7 +17,7 @@ import { composeHooks, createTaskHooks } from "../hooks/hook-runner.js";
|
|
|
17
17
|
import { HOST_POSTURE_REFUSED_CODE, taskInheritEnvRefusal, taskWriteFaceRefusal } from "../hosted-posture.js";
|
|
18
18
|
import { headerStr } from "../http/principal-gate.js";
|
|
19
19
|
import { explicitOperatorOk } from "../http/server.js";
|
|
20
|
-
import {
|
|
20
|
+
import { isAtMentionable, matchCatalogModel, modelSupportsImages, refusedCatalogEntry, resolveTaskModel, selectableCatalog, terminalCatalogName } from "../model-select.js";
|
|
21
21
|
import { modelUnavailableMessage } from "../model-entry-refusal.js";
|
|
22
22
|
import { PerTaskImageRegistry, resolveSandboxImageRef } from "../per-task-image.js";
|
|
23
23
|
import { isRemoteScratchpadLane, remoteScratchpadDirFor } from "../plugins/remote-scratchpad.js";
|
|
@@ -30,7 +30,7 @@ import { applyRuntimeGovernance } from "../runtime-governance.js";
|
|
|
30
30
|
import { HttpError, createCodedHttpError, encodeCheckpointScope } from "../security.js";
|
|
31
31
|
import { memoryProjectKeyFor, memorySpecForRequest } from "../memory-scope.js";
|
|
32
32
|
import { inheritEnvFieldIssue, singleMemberOffFieldIssue } from "../request-value-closure.js";
|
|
33
|
-
import { a2aForScenario, mcpForScenario } from "../
|
|
33
|
+
import { a2aForScenario, mcpForScenario } from "../web-admin-client/facade.js";
|
|
34
34
|
import { normalizeAttachments, normalizeResilience, normalizeResumeAtMode, normalizeSuggestNextPrompts, promptProfileFromBody, resolveTaskLimits, retainBackgroundProcessesFromBody, taskAgentsSpecFragment, toolMaterializeStrategyFromBody, toolNameListFromBody } from "../spec-fields.js";
|
|
35
35
|
import { cwdHonored, deviceCwdHonored, effectiveHostWorkspace, inProcessSingleUserLane, isValidCwd, parseAdditionalDirectories, satisfiedByProcessCwd, shellEnvMismatchCount } from "../task-cwd.js";
|
|
36
36
|
import { assertRequestA2aUnlocked, resolveRequestA2a } from "../task-a2a.js";
|
|
@@ -259,7 +259,7 @@ export function createResolveSpec(ctx) {
|
|
|
259
259
|
logger.warn("task_additional_read_directories_ignored", { honored: false, sessionId: auth?.sessionId ?? null });
|
|
260
260
|
}
|
|
261
261
|
const wireCatalog = selectableCatalog(config.models, config.tiers, config.modelRefusals);
|
|
262
|
-
const picked = resolveTaskModel(body.model ?? parsedSettings.settings?.model, objective, wireCatalog, config.
|
|
262
|
+
const picked = resolveTaskModel(body.model ?? parsedSettings.settings?.model, objective, wireCatalog, config.atMention, config.modelRefusals);
|
|
263
263
|
if (picked.unavailable !== undefined) {
|
|
264
264
|
const { requested, name, refusal, source } = picked.unavailable;
|
|
265
265
|
if (opts?.leg === "fresh") {
|
|
@@ -271,7 +271,7 @@ export function createResolveSpec(ctx) {
|
|
|
271
271
|
if (picked.notAllowed !== undefined) {
|
|
272
272
|
const { requested, resolved, source } = picked.notAllowed;
|
|
273
273
|
if (opts?.leg === "fresh") {
|
|
274
|
-
throw new HttpError(400, `model "${requested.slice(0, 120)}" is not
|
|
274
|
+
throw new HttpError(400, `model "${requested.slice(0, 120)}" is not @-mentionable on this deployment (it resolves to catalog model "${resolved}") — which models can be @-mentioned is configured by the operator (models.atMention)`, { code: "request.model_not_allowed" });
|
|
275
275
|
}
|
|
276
276
|
metrics.inc("task_model_not_allowlisted_resume_total");
|
|
277
277
|
logger.warn("task_model_not_allowlisted_resume", { requested: requested.slice(0, 120), resolved, source, sessionId: auth?.sessionId ?? null, note: "resumed leg keeps running the model it was started on — the allowlist gates fresh picks only" });
|
|
@@ -395,10 +395,10 @@ export function createResolveSpec(ctx) {
|
|
|
395
395
|
logger.warn("compaction_model_unknown_fallback", { requested: body.compactionModel.slice(0, 120), sessionId: auth?.sessionId ?? null });
|
|
396
396
|
return {};
|
|
397
397
|
}
|
|
398
|
-
if (!
|
|
398
|
+
if (!isAtMentionable(cm, wireCatalog, config.atMention, config.modelRefusals)) {
|
|
399
399
|
const terminal = terminalCatalogName(cm, wireCatalog, config.modelRefusals) ?? cm;
|
|
400
400
|
if (opts?.leg === "fresh") {
|
|
401
|
-
throw new HttpError(400, `compactionModel "${body.compactionModel.slice(0, 120)}" is not
|
|
401
|
+
throw new HttpError(400, `compactionModel "${body.compactionModel.slice(0, 120)}" is not @-mentionable on this deployment (it resolves to catalog model "${terminal}") — which models can be @-mentioned is configured by the operator (models.atMention)`, { code: "request.model_not_allowed" });
|
|
402
402
|
}
|
|
403
403
|
metrics.inc("task_model_not_allowlisted_resume_total");
|
|
404
404
|
logger.warn("task_model_not_allowlisted_resume", { requested: body.compactionModel.slice(0, 120), resolved: terminal, source: "compaction", sessionId: auth?.sessionId ?? null, note: "resumed leg keeps the compaction model it was started with — the allowlist gates fresh picks only" });
|
|
@@ -622,7 +622,7 @@ export function createResolveSpec(ctx) {
|
|
|
622
622
|
throw new HttpError(400, "sandboxImageProfile is only supported on the k8s sandbox backend");
|
|
623
623
|
}
|
|
624
624
|
if (!imageIndex) {
|
|
625
|
-
throw new HttpError(400, "sandboxImageProfile requires the image index (
|
|
625
|
+
throw new HttpError(400, "sandboxImageProfile requires the image index (web-admin backend not configured)");
|
|
626
626
|
}
|
|
627
627
|
if (!auth?.sessionId) {
|
|
628
628
|
throw new HttpError(400, "sandboxImageProfile requires a resolved session");
|
|
@@ -204,7 +204,7 @@ export interface RunnerDepsCtx {
|
|
|
204
204
|
permissionRuleStore: RunnerDeps["permissionRuleStore"];
|
|
205
205
|
/** [ref](core 5.50 [ref]):mid-turn MCP 撤销台账席 —— core 每次 MCP dispatch 前同步探
|
|
206
206
|
* `isRevoked(serverName)`,被撤服务器的调用结算为 coded 拒绝 `mcp.server_revoked`(known-not-executed)。
|
|
207
|
-
* 来源=
|
|
207
|
+
* 来源=webAdmin.takeMcpRevocations()(取走即声明接线,restart 豁免与承接绑同一动作)。
|
|
208
208
|
* 缺席=undefined=pre-338 语义(纯 env 部署无中心撤销面)。 */
|
|
209
209
|
mcpRevocations: RunnerDeps["mcpRevocations"];
|
|
210
210
|
/**
|
|
@@ -23,7 +23,7 @@ export interface RuntimeCapsCtx {
|
|
|
23
23
|
*
|
|
24
24
|
* governed 的语义是「per-principal verdict **必答**」:core 对 verdict 缺席一律**拒跑**(fail-closed,部署显式
|
|
25
25
|
* 选的方向)。verdict 源**两条**(析取,[ref] 起):①SQL 后端上的 `memory_optout_grant` 表(三层折叠后
|
|
26
|
-
* 恒答显式 boolean),②非 dry-run 的
|
|
26
|
+
* 恒答显式 boolean),②非 dry-run 的 web-admin 发 `EntitlementRuntimeCaps.allowMemoryOptOut`。
|
|
27
27
|
* governed 而两源皆无 ⇒ 每一个 `capture:"off"` 声明都被 core 以
|
|
28
28
|
* `memory.capture_optout_denied` 拒掉,而运维看到的只是一台「启动成功、opt-out 全拒」的机器 —— 正是
|
|
29
29
|
* 「阀门开着而配不出来 ⇒ 悄悄读成别的」那一形。所以在**启动期**点名:接 SQL 后端(表随中央
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { applyGovernedVerdictAbsenceWarning, applyLocalAutoModeDeny, applyMemoryOptOutGrant, applyObserverEnvOptIn, centerEntitlementSourceWired, createPrincipalEntitlementsClient, } from "../runtime-caps-resolver.js";
|
|
2
2
|
import { scopedTokenNeedsWorker } from "../center-credential.js";
|
|
3
|
-
import {
|
|
3
|
+
import { WEB_ADMIN_ENV } from "@sema-agent/settings-schema";
|
|
4
4
|
export function assertMemoryCapturePolicyWirable(input) {
|
|
5
5
|
if (input.policy !== "governed")
|
|
6
6
|
return;
|
|
@@ -13,9 +13,9 @@ export function assertMemoryCapturePolicyWirable(input) {
|
|
|
13
13
|
`own contract), so a governed worker without a source would refuse every \`memory.capture:"off"\` declaration and the ` +
|
|
14
14
|
`refusal would read as an entitlement denial rather than the misconfiguration it is. This version has TWO verdict sources ` +
|
|
15
15
|
`— wire either one: (1) the \`memory_optout_grant\` table on a SQL store backend (DB_BACKEND=mysql|pg; the table is ` +
|
|
16
|
-
`created by the central ensureSchema and administered through /v1/admin/memory-optout), or (2) a
|
|
17
|
-
`EMITS \`allowMemoryOptOut\` in each principal's entitlement caps (
|
|
18
|
-
|
|
16
|
+
`created by the central ensureSchema and administered through /v1/admin/memory-optout), or (2) a web-admin that ` +
|
|
17
|
+
`EMITS \`allowMemoryOptOut\` in each principal's entitlement caps (${WEB_ADMIN_ENV.url} + ${WEB_ADMIN_ENV.token}, ` +
|
|
18
|
+
`${WEB_ADMIN_ENV.dryRun} off — dry-run observes without applying, so it is not a source; and note the key is OPTIONAL in ` +
|
|
19
19
|
`the entitlement schema: a center that never emits it leaves every verdict absent, i.e. every opt-out still refused). ` +
|
|
20
20
|
`Or set MEMORY_CAPTURE_POLICY=open (opt-outs take effect; only an explicit per-principal false denies) or ` +
|
|
21
21
|
`MEMORY_CAPTURE_POLICY=capture-required (every opt-out declaration refused, no source consulted).`);
|
|
@@ -35,18 +35,18 @@ export function createRuntimeCaps(ctx) {
|
|
|
35
35
|
const governedCenterOnlySource = config.memoryCapturePolicy === "governed" && !grantSourceWired && centerEntitlementSourceWired(config);
|
|
36
36
|
if (governedCenterOnlySource) {
|
|
37
37
|
logger.warn("memory_capture_governed_center_only_source", {
|
|
38
|
-
reason: "MEMORY_CAPTURE_POLICY=governed with NO local memory_optout_grant table: the only verdict source is the
|
|
38
|
+
reason: "MEMORY_CAPTURE_POLICY=governed with NO local memory_optout_grant table: the only verdict source is the web-admin, and `allowMemoryOptOut` is an OPTIONAL entitlement key — for any principal whose caps omit it the verdict is ABSENT and core refuses that session's memory.capture:\"off\" (memory.capture_optout_denied, fail-closed). ANONYMOUS/system runs are worse off still: the center source is per-principal and is never consulted without an identity, so on this shape a principal-less run can never obtain a verdict at all. Verify the center emits allowMemoryOptOut for every principal, or wire a SQL backend (DB_BACKEND=mysql|pg) so the grant table answers (its deployment-default row also covers anonymous runs).",
|
|
39
39
|
});
|
|
40
40
|
}
|
|
41
|
-
if (centerEntitlementSourceWired(config) && config.
|
|
41
|
+
if (centerEntitlementSourceWired(config) && config.webAdmin && scopedTokenNeedsWorker(config.webAdmin.credential.read(), config.webAdmin.worker)) {
|
|
42
42
|
logger.warn("runtime_caps_scoped_token_no_worker", {
|
|
43
|
-
reason: `${
|
|
43
|
+
reason: `${WEB_ADMIN_ENV.token} is a worker-scoped wpt_ token but ${WEB_ADMIN_ENV.worker} is unset → web-admin 403s per-principal caps → ALL workflow self-orchestration will be fail-closed denied. Set ${WEB_ADMIN_ENV.worker} (the orchestrator normally injects it) or use the full SERVICE_PULL_TOKEN.`,
|
|
44
44
|
});
|
|
45
45
|
}
|
|
46
|
-
const principalCaps = centerEntitlementSourceWired(config) && config.
|
|
46
|
+
const principalCaps = centerEntitlementSourceWired(config) && config.webAdmin
|
|
47
47
|
? createPrincipalEntitlementsClient({
|
|
48
|
-
center: config.
|
|
49
|
-
...(config.
|
|
48
|
+
center: config.webAdmin,
|
|
49
|
+
...(config.webAdmin.worker ? { worker: config.webAdmin.worker } : {}),
|
|
50
50
|
onError: (err, principal) => logger.warn("runtime_caps_resolve_failed", { principal, err: String(err) }),
|
|
51
51
|
})
|
|
52
52
|
: undefined;
|
package/dist/boot/shutdown.d.ts
CHANGED
|
@@ -79,9 +79,9 @@ export interface ShutdownCtx {
|
|
|
79
79
|
* HTTP 层不能自作主张。所以 `drainState.draining` 翻真的那一刻,这里同步调 `beginDrain()`。
|
|
80
80
|
*/
|
|
81
81
|
deviceHub: import("../device-ws-hub.js").DeviceWsHub | undefined;
|
|
82
|
-
/** [ref]-2:config 60s 刷新环(
|
|
82
|
+
/** [ref]-2:config 60s 刷新环(web-admin startRefreshLoop)——不停的话停机中途还可能热应用
|
|
83
83
|
* 一份新配置。缺席 = 纯 env 部署没起环。 */
|
|
84
|
-
|
|
84
|
+
webAdmin: {
|
|
85
85
|
stopRefreshLoop(): void;
|
|
86
86
|
} | undefined;
|
|
87
87
|
/** S-929:活体审批协调器(`TOOL_APPROVAL_ENABLED` 关 ⇒ 缺席)。hardShutdown 起点调它的 `drainForShutdown`:本进程握着的活卡
|
package/dist/boot/shutdown.js
CHANGED
|
@@ -17,7 +17,7 @@ export function backgroundGraceRemainingMs(a) {
|
|
|
17
17
|
return Math.max(0, Math.min(a.softStoppedAt + a.graceMs, a.deadlineMs) - a.now);
|
|
18
18
|
}
|
|
19
19
|
export function installShutdownHandlers(ctx) {
|
|
20
|
-
const { config, logger, server, reaper, fleetReconcile, retentionLane, releaseRetentionLease, otelExporter, breakerState, costQuota, rateLimiter, runner, subRunner, lspManager, workflowNotifyJournal, fleetClient, backend, drainState, storeLiveProbe,
|
|
20
|
+
const { config, logger, server, reaper, fleetReconcile, retentionLane, releaseRetentionLease, otelExporter, breakerState, costQuota, rateLimiter, runner, subRunner, lspManager, workflowNotifyJournal, fleetClient, backend, drainState, storeLiveProbe, webAdmin, version, deviceHub, toolApproval, parkCommits, servingLease, } = ctx;
|
|
21
21
|
const dataRoot = config.localDataRoot;
|
|
22
22
|
if (dataRoot) {
|
|
23
23
|
const prior = readCrashLast(dataRoot);
|
|
@@ -107,7 +107,7 @@ export function installShutdownHandlers(ctx) {
|
|
|
107
107
|
storeLiveProbe?.stop();
|
|
108
108
|
servingLease?.stop();
|
|
109
109
|
void deviceHub?.close().catch((err) => logger.warn("device_hub_close_failed", { err: String(err) }));
|
|
110
|
-
|
|
110
|
+
webAdmin?.stopRefreshLoop();
|
|
111
111
|
otelExporter?.stop();
|
|
112
112
|
breakerState?.stop();
|
|
113
113
|
runner.sessions.dispose();
|
|
@@ -69,9 +69,9 @@ export type SideQueryLane = (spec: SideQuerySpec) => Promise<SideQueryResult>;
|
|
|
69
69
|
export interface SideQueryLaneCtx {
|
|
70
70
|
/** 与 `RunnerDeps.brain` **同一只**实例([ref] 换装后本席不再包它 —— key 走 spec 座位)。 */
|
|
71
71
|
brain: Brain;
|
|
72
|
-
/** 活配置引用:目录/角色表/网关地址被
|
|
72
|
+
/** 活配置引用:目录/角色表/网关地址被 web-admin 就地热应用(`mutateInPlace`),按调用取值才跟得上。 */
|
|
73
73
|
config: ServiceConfig;
|
|
74
|
-
/** 活引用取值 —— registry 热应用整个换 resolver 引用(`boot/
|
|
74
|
+
/** 活引用取值 —— registry 热应用整个换 resolver 引用(`boot/web-admin.ts` 每次 apply 重铸)。 */
|
|
75
75
|
getKeyResolver: () => KeyResolver;
|
|
76
76
|
}
|
|
77
77
|
/**
|
|
@@ -119,7 +119,7 @@ export declare function createPerModelKeyBrain(brain: Brain, getKeyResolver: ()
|
|
|
119
119
|
* ([ref] codex R1-F2:目录与密钥表零 await 窗成对换代):
|
|
120
120
|
* · `models` = `expandTiers(config.models, config.tiers)` —— 档位词 / CC 别名(`flash`/`opus`/…)在
|
|
121
121
|
* side-query 上照常可选路(core 的 `Runner` 构造时做同一件事),且 `Runner` 那次展开是**构造时快照**,
|
|
122
|
-
* 而本路由的模型白名单门(`routes/side-query.ts` 的 `
|
|
122
|
+
* 而本路由的模型白名单门(`routes/side-query.ts` 的 `isAtMentionable`)按请求现算同一张增广目录 ——
|
|
123
123
|
* 两边取同一份才不会出现「名单放行、选路说不认识」的分歧;
|
|
124
124
|
* · `getKeyResolver()` —— 热应用整个换 resolver 引用,活取才跟得上(装配时快照 = 旧 key 用到重启)。
|
|
125
125
|
* (第三件 `config.gatewayBaseUrl` 曾是 off-route 记债判据的参照系,core 5.57.0 起判据整只上收 core 的
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { runStage01 } from "./stage-01-config.js";
|
|
2
2
|
export declare function runStage02(ctx: Awaited<ReturnType<typeof runStage01>>): Promise<{
|
|
3
3
|
ceilingVerdict: import("./unpriced-ceiling-verdict.js").UnpricedCeilingVerdict;
|
|
4
|
-
|
|
4
|
+
webAdmin: import("./web-admin.js").WebAdminRuntime;
|
|
5
5
|
config: import("../config-types.js").ServiceConfig;
|
|
6
6
|
localRoot: string;
|
|
7
7
|
logger: import("../index.js").Logger;
|
|
8
8
|
metrics: import("../index.js").Metrics;
|
|
9
9
|
}>;
|
|
10
|
-
//# sourceMappingURL=stage-02-
|
|
10
|
+
//# sourceMappingURL=stage-02-web-admin-pull.d.ts.map
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { createUnpricedCeilingVerdict } from "./unpriced-ceiling-verdict.js";
|
|
2
|
-
import {
|
|
2
|
+
import { createWebAdminRuntime } from "./web-admin.js";
|
|
3
3
|
import { composeExecutionLane, FILE_SOURCED_LANES } from "./execution-lane.js";
|
|
4
4
|
import { serviceConfigSourceKind } from "../config-provider.js";
|
|
5
5
|
import { defaultModelRefusal, refusedNameMintedRefusal } from "../model-entry-refusal.js";
|
|
6
6
|
export async function runStage02(ctx) {
|
|
7
7
|
const { config, localRoot, logger, metrics } = ctx;
|
|
8
8
|
await composeExecutionLane(config, { configSource: serviceConfigSourceKind(config), localRoot, logger, drivesFromFile: FILE_SOURCED_LANES });
|
|
9
|
-
const
|
|
9
|
+
const webAdmin = await createWebAdminRuntime({ config, logger, metrics, localRoot });
|
|
10
10
|
const noDefaultModel = defaultModelRefusal(config, "env");
|
|
11
11
|
if (noDefaultModel !== undefined) {
|
|
12
12
|
throw new Error(noDefaultModel);
|
|
@@ -17,6 +17,6 @@ export async function runStage02(ctx) {
|
|
|
17
17
|
}
|
|
18
18
|
const ceilingVerdict = createUnpricedCeilingVerdict({ config, logger });
|
|
19
19
|
ceilingVerdict.judge();
|
|
20
|
-
return { ...ctx, ceilingVerdict,
|
|
20
|
+
return { ...ctx, ceilingVerdict, webAdmin };
|
|
21
21
|
}
|
|
22
|
-
//# sourceMappingURL=stage-02-
|
|
22
|
+
//# sourceMappingURL=stage-02-web-admin-pull.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { runStage02 } from "./stage-02-
|
|
1
|
+
import type { runStage02 } from "./stage-02-web-admin-pull.js";
|
|
2
2
|
export declare function runStage03(ctx: Awaited<ReturnType<typeof runStage02>>): Promise<{
|
|
3
3
|
backend: import("../index.js").StoreBackend | undefined;
|
|
4
4
|
backgroundAgentStore: import("@sema-agent/core").BackgroundAgentStore | undefined;
|
|
@@ -24,7 +24,7 @@ export declare function runStage03(ctx: Awaited<ReturnType<typeof runStage02>>):
|
|
|
24
24
|
taskListLane: import("./task-list-lane.js").TaskListLane;
|
|
25
25
|
usageWindowStore: import("@sema-agent/core").UsageWindowStore | undefined;
|
|
26
26
|
ceilingVerdict: import("./unpriced-ceiling-verdict.js").UnpricedCeilingVerdict;
|
|
27
|
-
|
|
27
|
+
webAdmin: import("./web-admin.js").WebAdminRuntime;
|
|
28
28
|
config: import("../config-types.js").ServiceConfig;
|
|
29
29
|
localRoot: string;
|
|
30
30
|
logger: import("../index.js").Logger;
|
|
@@ -65,7 +65,7 @@ export declare function runStage04(ctx: Awaited<ReturnType<typeof runStage03>>):
|
|
|
65
65
|
taskListLane: import("./task-list-lane.js").TaskListLane;
|
|
66
66
|
usageWindowStore: import("@sema-agent/core").UsageWindowStore | undefined;
|
|
67
67
|
ceilingVerdict: import("./unpriced-ceiling-verdict.js").UnpricedCeilingVerdict;
|
|
68
|
-
|
|
68
|
+
webAdmin: import("./web-admin.js").WebAdminRuntime;
|
|
69
69
|
config: import("../config-types.js").ServiceConfig;
|
|
70
70
|
localRoot: string;
|
|
71
71
|
logger: import("../index.js").Logger;
|
|
@@ -81,7 +81,7 @@ export declare function runStage05(ctx: Awaited<ReturnType<typeof runStage04>>):
|
|
|
81
81
|
taskListLane: import("./task-list-lane.js").TaskListLane;
|
|
82
82
|
usageWindowStore: import("@sema-agent/core").UsageWindowStore | undefined;
|
|
83
83
|
ceilingVerdict: import("./unpriced-ceiling-verdict.js").UnpricedCeilingVerdict;
|
|
84
|
-
|
|
84
|
+
webAdmin: import("./web-admin.js").WebAdminRuntime;
|
|
85
85
|
config: import("../config-types.js").ServiceConfig;
|
|
86
86
|
localRoot: string;
|
|
87
87
|
logger: import("../index.js").Logger;
|