@sema-agent/server 7.120.0 → 7.122.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 +173 -0
- package/README.md +1 -1
- package/README.zh-CN.md +3 -1
- package/USAGE.md +97 -29
- package/deploy/sema-up/chart/templates/server-v4pro.yaml +2 -2
- package/deploy/sema-up/chart/templates/server.yaml +2 -2
- package/deploy/sema-up/stack/sema-stack-cluster.yaml +1 -1
- package/dist/approval-reconciler.d.ts +8 -0
- package/dist/approval-reconciler.js +72 -52
- package/dist/auto-mode-face.d.ts +9 -2
- package/dist/auto-mode-face.js +5 -3
- package/dist/bench/s1/live-deps.js +1 -0
- package/dist/boot/config-center.d.ts +5 -7
- package/dist/boot/config-center.js +33 -9
- package/dist/boot/engine-lease.d.ts +1 -1
- package/dist/boot/leader.js +1 -0
- package/dist/boot/reapers.d.ts +3 -0
- package/dist/boot/reapers.js +2 -1
- package/dist/boot/resolve-spec.js +2 -4
- package/dist/boot/shutdown.d.ts +9 -10
- package/dist/boot/shutdown.js +59 -16
- package/dist/boot/stage-08-reapers.js +2 -2
- package/dist/boot/stage-09-leader.d.ts +2 -9
- package/dist/boot/stage-10-http-server.d.ts +1 -9
- package/dist/boot/stage-10-http-server.js +31 -8
- package/dist/capabilities/composite-members.d.ts +1 -1
- package/dist/capabilities/composite-members.js +1 -1
- package/dist/capabilities/memory-notice.d.ts +1 -1
- package/dist/config-catalog.js +12 -6
- package/dist/config-center/center-request.d.ts +13 -1
- package/dist/config-center/center-request.js +25 -10
- package/dist/config-types.d.ts +44 -5
- package/dist/config-types.js +6 -0
- package/dist/config.d.ts +35 -6
- package/dist/config.js +113 -33
- package/dist/fleet/drain-entry.d.ts +112 -0
- package/dist/fleet/drain-entry.js +38 -0
- package/dist/fleet/engine-signal.d.ts +144 -0
- package/dist/fleet/engine-signal.js +60 -0
- package/dist/fleet/serving-lease.d.ts +47 -0
- package/dist/fleet/serving-lease.js +233 -0
- package/dist/fleet-client.d.ts +35 -19
- package/dist/fleet-client.js +49 -25
- package/dist/governance-overrides.d.ts +7 -2
- package/dist/http/admission.js +7 -5
- package/dist/http/approval-sweeps.js +5 -7
- package/dist/http/checkpoint-ctx.d.ts +60 -11
- package/dist/http/checkpoint-ctx.js +23 -9
- package/dist/http/dispatch.js +33 -16
- package/dist/http/health-self-report.d.ts +60 -0
- package/dist/http/health-self-report.js +53 -0
- package/dist/http/principal-gate.d.ts +8 -1
- package/dist/http/principal-gate.js +1 -0
- package/dist/http/readiness.d.ts +25 -5
- package/dist/http/readiness.js +31 -6
- package/dist/http/resume-legs.js +9 -9
- package/dist/http/route-ctx.d.ts +25 -7
- package/dist/http/route-table.d.ts +6 -0
- package/dist/http/route-table.js +8 -1
- package/dist/http/routes/a2a-serve.d.ts +1 -1
- package/dist/http/routes/a2a-serve.js +5 -5
- package/dist/http/routes/admin-drain.d.ts +15 -31
- package/dist/http/routes/admin-drain.js +28 -10
- package/dist/http/routes/approvals-assistant.d.ts +4 -3
- package/dist/http/routes/approvals-assistant.js +9 -9
- package/dist/http/routes/capabilities.js +7 -5
- package/dist/http/routes/devices.js +3 -2
- package/dist/http/routes/fleet.d.ts +1 -0
- package/dist/http/routes/fleet.js +1 -1
- package/dist/http/routes/images.d.ts +1 -0
- package/dist/http/routes/images.js +1 -1
- package/dist/http/routes/leader.d.ts +1 -1
- package/dist/http/routes/leader.js +7 -1
- package/dist/http/routes/memory-consolidation.d.ts +1 -1
- package/dist/http/routes/memory-consolidation.js +1 -1
- package/dist/http/routes/notify-wake.d.ts +1 -1
- package/dist/http/routes/notify-wake.js +1 -1
- package/dist/http/routes/rules.js +4 -3
- package/dist/http/routes/runs.d.ts +4 -2
- package/dist/http/routes/runs.js +7 -6
- package/dist/http/routes/sessions.d.ts +1 -0
- package/dist/http/routes/sessions.js +1 -1
- package/dist/http/routes/side-query.d.ts +1 -1
- package/dist/http/routes/side-query.js +1 -1
- package/dist/http/routes/tasks.d.ts +2 -2
- package/dist/http/routes/tasks.js +3 -3
- package/dist/http/routes/trace-usage.d.ts +1 -0
- package/dist/http/routes/trace-usage.js +1 -1
- package/dist/http/routes/workflows.d.ts +1 -0
- package/dist/http/routes/workflows.js +1 -1
- package/dist/http/send.d.ts +13 -0
- package/dist/http/send.js +9 -0
- package/dist/http/server.d.ts +10 -21
- package/dist/http/server.js +20 -1
- package/dist/http/stored-body-replay.d.ts +27 -0
- package/dist/http/stored-body-replay.js +23 -0
- package/dist/http/wire-types.d.ts +7 -1
- package/dist/leader/leader.d.ts +22 -1
- package/dist/leader/leader.js +4 -1
- package/dist/leader/repair-wire.d.ts +1 -1
- package/dist/leader/repair-wire.js +2 -2
- package/dist/leader/run-entry.d.ts +27 -0
- package/dist/leader/run-entry.js +29 -0
- package/dist/leader/wire.d.ts +10 -0
- package/dist/leader/wire.js +15 -10
- package/dist/model-reach-scope.d.ts +15 -3
- package/dist/model-reach-scope.js +3 -2
- package/dist/model-route-url.d.ts +13 -20
- package/dist/model-route-url.js +28 -24
- package/dist/model-unreachable-notice.d.ts +2 -1
- package/dist/model-unreachable-notice.js +1 -0
- package/dist/observability/fail-open.d.ts +35 -2
- package/dist/observability/fail-open.js +20 -0
- package/dist/plugins/approval-ask-store-file.d.ts +1 -0
- package/dist/plugins/approval-ask-store-file.js +3 -0
- package/dist/plugins/approval-ask-store-memory.d.ts +1 -0
- package/dist/plugins/approval-ask-store-memory.js +6 -0
- package/dist/plugins/approval-ask-store-sql.d.ts +12 -0
- package/dist/plugins/approval-ask-store-sql.js +4 -0
- package/dist/plugins/one-time-migrations.js +14 -1
- package/dist/plugins/park-commit-watch.d.ts +19 -5
- package/dist/plugins/park-commit-watch.js +24 -17
- package/dist/plugins/permission-rule-store-sql.d.ts +2 -1
- package/dist/plugins/remote-env-device.js +0 -1
- package/dist/request-key-closure.js +1 -1
- package/dist/router/route-orchestration.d.ts +4 -2
- package/dist/router/route-orchestration.js +2 -1
- package/dist/rules-consent.d.ts +6 -2
- package/dist/rules-consent.js +3 -0
- package/dist/run-local.js +3 -1
- package/dist/runs.js +1 -1
- package/dist/runtime-governance.d.ts +44 -32
- package/dist/runtime-governance.js +23 -9
- package/dist/sighup-idle.d.ts +7 -1
- package/dist/sighup-idle.js +4 -4
- package/dist/task-settings.d.ts +37 -14
- package/dist/task-settings.js +20 -20
- package/dist/tool-approval.d.ts +13 -0
- package/dist/tool-approval.js +17 -2
- package/dist/trace/core-keyset-guard.d.ts +2 -2
- package/dist/trace/redact.d.ts +3 -3
- package/dist/trace/self-minted-wire.d.ts +64 -0
- package/dist/trace/self-minted-wire.js +30 -0
- package/dist/unattended-permission-mode.d.ts +17 -13
- package/dist/unattended-permission-mode.js +3 -1
- package/dist/url-shape.d.ts +31 -0
- package/dist/url-shape.js +41 -0
- package/package.json +3 -3
- package/scripts/drain-check-local.mjs +1 -1
|
@@ -7,7 +7,7 @@ import { isParkedRunStatus } from "../../plugins/store-contracts.js";
|
|
|
7
7
|
import { principalFrom, decodeCheckpointScope, PRINCIPAL_TOKEN_HEADER, APPROVAL_MAC_HEADER, APPROVAL_MAC_KID_HEADER } from "../../security.js";
|
|
8
8
|
import { editedPlanBinding, isWellFormedUnicode, verifyDirectDoorProof } from "../../principal-jwt.js";
|
|
9
9
|
import { MAX_APPROVAL_REASON_CHARS, projectQuestionAnswer, questionAnswerFromProjection } from "../../approval-hmac.js";
|
|
10
|
-
import { PLAN_APPROVE_PERMISSION_MODES_AFTER, isPlanApprovePermissionModeAfter, storedBodyPermissionMode } from "../../task-settings.js";
|
|
10
|
+
import { PLAN_APPROVE_PERMISSION_MODES_AFTER, isPlanApprovePermissionModeAfter, planReviewDecisionExitsPlan, storedBodyPermissionMode } from "../../task-settings.js";
|
|
11
11
|
import { MAX_APPROVAL_NONCE_CHARS } from "../../plugins/approval-nonce-store.js";
|
|
12
12
|
import { redactedPreview, redactSecrets } from "../../trace/redact.js";
|
|
13
13
|
import { redactRiskDescriptor } from "../../observability/run-terminal.js";
|
|
@@ -59,7 +59,7 @@ const DECISION_DOOR_FAMILY = {
|
|
|
59
59
|
"assistant-task-plan-review": {
|
|
60
60
|
accepted: PLAN_REVIEW_BODY_DECLARED_KEYS,
|
|
61
61
|
requestNoun: "plan-review-request",
|
|
62
|
-
costliestTypo: "a misspelled `permissionModeAfter` silently leaves this task
|
|
62
|
+
costliestTypo: "a misspelled `permissionModeAfter` silently leaves this task asking before every write after you approved its plan",
|
|
63
63
|
},
|
|
64
64
|
};
|
|
65
65
|
const SUBMIT_BODY_NEAR_MISS_KEYS = ["permissionMode"];
|
|
@@ -534,8 +534,8 @@ export async function handleApprovalsAssistant(req, res, match, ctx) {
|
|
|
534
534
|
sendError(res, 400, "request.field_invalid", `permissionModeAfter must be one of ${PLAN_APPROVE_PERMISSION_MODES_AFTER.map((m) => JSON.stringify(m)).join(" | ")} when present (the permission mode this task continues in once the plan is approved; absent = "default", which keeps asking before each write)`);
|
|
535
535
|
return;
|
|
536
536
|
}
|
|
537
|
-
if (decision
|
|
538
|
-
sendError(res, 400, "request.field_conflict", `permissionModeAfter is only valid with decision 'approve'
|
|
537
|
+
if (!planReviewDecisionExitsPlan(decision) && body.permissionModeAfter !== undefined) {
|
|
538
|
+
sendError(res, 400, "request.field_conflict", `permissionModeAfter is only valid with a decision that carries the plan out ('approve' or 'edit'; got '${decision}')`);
|
|
539
539
|
return;
|
|
540
540
|
}
|
|
541
541
|
if (body.reason !== undefined && typeof body.reason !== "string") {
|
|
@@ -610,7 +610,7 @@ export async function handleApprovalsAssistant(req, res, match, ctx) {
|
|
|
610
610
|
if (body.permissionModeAfter !== undefined) {
|
|
611
611
|
const storedCtx = plan.prepared.ctx;
|
|
612
612
|
if (storedCtx.body !== undefined && storedBodyPermissionMode(storedCtx.body) !== "plan") {
|
|
613
|
-
sendError(res, 400, "request.field_conflict", "permissionModeAfter does not apply to this task: it was not
|
|
613
|
+
sendError(res, 400, "request.field_conflict", "permissionModeAfter does not apply to this task: it was not started in plan mode (its stored permission mode is not \"plan\"), so approving the plan returns it to the mode it was in before planning");
|
|
614
614
|
return;
|
|
615
615
|
}
|
|
616
616
|
}
|
|
@@ -910,16 +910,16 @@ export async function streamApprovals(req, res, cs, live, scope, governance, pol
|
|
|
910
910
|
}
|
|
911
911
|
export const APPROVALS_ASSISTANT_ROUTES = [
|
|
912
912
|
{ id: "approvals-list", path: "/v1/approvals", methods: ["GET"] },
|
|
913
|
-
{ id: "approvals-stream", path: "/v1/approvals/stream", methods: ["GET"] },
|
|
913
|
+
{ id: "approvals-stream", path: "/v1/approvals/stream", methods: ["GET"], subscription: true },
|
|
914
914
|
{ id: "assistant-inbox", path: "/v1/assistant/inbox", methods: ["GET"] },
|
|
915
915
|
{ id: "assistant-tasks", path: "/v1/assistant/tasks", methods: ["GET"] },
|
|
916
916
|
{ id: "approval-decide", pattern: /^\/v1\/approvals\/(?<sessionId>[^/]+)\/decide$/, label: "/v1/approvals/:id/decide", methods: ["POST"] },
|
|
917
917
|
{ id: "approval-exemptions-list", pattern: /^\/v1\/approvals\/(?<sessionId>[^/]+)\/exemptions(?:\/(?<tool>[^/]+))?$/, label: "/v1/approvals/:id/exemptions", methods: ["GET"] },
|
|
918
918
|
{ id: "approval-exemption-delete", pattern: /^\/v1\/approvals\/(?<sessionId>[^/]+)\/exemptions(?:\/(?<tool>[^/]+))?$/, label: "/v1/approvals/:id/exemptions", methods: ["DELETE"] },
|
|
919
919
|
{ id: "assistant-task-preempt", pattern: /^\/v1\/assistant\/tasks\/(?<taskId>[^/]+)\/preempt$/, label: "/v1/assistant/tasks/:id/preempt", methods: ["POST"] },
|
|
920
|
-
{ id: "assistant-task-resume", pattern: /^\/v1\/assistant\/tasks\/(?<taskId>[^/]+)\/resume$/, label: "/v1/assistant/tasks/:id/resume", billable:
|
|
921
|
-
{ id: "assistant-task-plan-review", pattern: /^\/v1\/assistant\/tasks\/(?<taskId>[^/]+)\/plan_review$/, label: "/v1/assistant/tasks/:id/plan_review", billable:
|
|
922
|
-
{ prefix: "/v1/approvals", billable:
|
|
920
|
+
{ id: "assistant-task-resume", pattern: /^\/v1\/assistant\/tasks\/(?<taskId>[^/]+)\/resume$/, label: "/v1/assistant/tasks/:id/resume", billable: "resume", methods: ["POST"] },
|
|
921
|
+
{ id: "assistant-task-plan-review", pattern: /^\/v1\/assistant\/tasks\/(?<taskId>[^/]+)\/plan_review$/, label: "/v1/assistant/tasks/:id/plan_review", billable: "hitl-answer", methods: ["POST"] },
|
|
922
|
+
{ prefix: "/v1/approvals", billable: "hitl-answer" },
|
|
923
923
|
];
|
|
924
924
|
const DECISION_DOOR_KEY_TABLE = deriveDecisionDoorKeyTable(DECISION_DOOR_FAMILY, APPROVALS_ASSISTANT_ROUTES);
|
|
925
925
|
//# sourceMappingURL=approvals-assistant.js.map
|
|
@@ -4,7 +4,8 @@ import { modelKeyPoisonOf, resolveModelApiKey } from "../../key-resolver.js";
|
|
|
4
4
|
import { projectSealedKeyCapability } from "../../sealed-key.js";
|
|
5
5
|
import { cwdHonored, deviceCwdHonored } from "../../task-cwd.js";
|
|
6
6
|
import { taskWriteFaceRefusal } from "../../hosted-posture.js";
|
|
7
|
-
import {
|
|
7
|
+
import { leaderEntryRefusal, leaderRunEntry } from "../../leader/run-entry.js";
|
|
8
|
+
import { autonomyKeepsOpenWriteFace, autonomyModeFloor } from "../../runtime-governance.js";
|
|
8
9
|
import { DEVICE_PROTOCOL_VERSION, DEVICE_WS_PATH } from "../../device-ws-protocol.js";
|
|
9
10
|
import { a2aInjectionHonored } from "../../task-a2a.js";
|
|
10
11
|
import { buildEmptyMcpProbeFace, buildMcpInjectionRefusal, buildMcpProbeCacheKey, buildMcpProbeInflightRefusal, buildMcpProbeRateKey, buildMcpProbeRateRefusal, createMcpProbeLocal, buildMcpProbeDeclarationRefusal, buildMcpProbeIncompleteRefusal, McpProbeIncomplete, MCP_PROBE_HTTP_STATUS, MCP_PROBE_MAX_INFLIGHT, MCP_PROBE_VERDICT_TIMEOUT_MS, createMcpProbeWalk, readMcpProbeBody, } from "../../capabilities/mcp-probe.js";
|
|
@@ -64,7 +65,7 @@ export async function handleCapabilities(req, res, match, ctx) {
|
|
|
64
65
|
return;
|
|
65
66
|
}
|
|
66
67
|
const entitlementSource = centerEntitlementSourceWired(deps.config);
|
|
67
|
-
const { fault: autoModeFault, ...autoMode } = await judgeAutoModeArming(deps.autoModeFace, { requestedMode, principal: gatedPrincipal(req, deps.config), localDeny: deps.config.permissionsDisableAutoMode });
|
|
68
|
+
const { fault: autoModeFault, ...autoMode } = await judgeAutoModeArming(deps.autoModeFace, { requestedMode, floor: autonomyModeFloor(deps.config.autonomy), principal: gatedPrincipal(req, deps.config), localDeny: deps.config.permissionsDisableAutoMode });
|
|
68
69
|
if (autoModeFault !== undefined)
|
|
69
70
|
deps.logger?.warn("auto_mode_face_resolver_fault", { fault: autoModeFault });
|
|
70
71
|
const rulesLaneForCaller = facts.ruleLaneForCaller(deps, gatedPrincipal(req, deps.config)).available;
|
|
@@ -79,10 +80,10 @@ export async function handleCapabilities(req, res, match, ctx) {
|
|
|
79
80
|
: false,
|
|
80
81
|
sessionEvents: facts.sessionEventStream(deps).available,
|
|
81
82
|
fleet: facts.fleetStream(deps).available
|
|
82
|
-
? { stream: true, sessionScope: true, observe: true, resume: "snapshot", bgNotifyFailClosed: true, steerPriority: "engine", hookFailureNotice: true }
|
|
83
|
+
? { stream: true, sessionScope: true, observe: true, resume: "snapshot", bgNotifyFailClosed: true, steerPriority: "engine", hookFailureNotice: true, leaseClient: true, generationEcho: true }
|
|
83
84
|
: false,
|
|
84
85
|
workspace: facts.workspaceBrowse().available,
|
|
85
|
-
leader: facts.leaderLane(deps).available,
|
|
86
|
+
leader: facts.leaderLane(deps).available && leaderEntryRefusal(leaderRunEntry(deps.config.autonomy)) === undefined,
|
|
86
87
|
images: facts.imagePool(deps).available,
|
|
87
88
|
memory: false,
|
|
88
89
|
memoryWrite: false,
|
|
@@ -130,6 +131,7 @@ export async function handleCapabilities(req, res, match, ctx) {
|
|
|
130
131
|
readFace: deps.config.readFace ?? null,
|
|
131
132
|
writeProtection: projectWriteProtectionCapability(deps.writeProtection),
|
|
132
133
|
appendSystemPrompt: true,
|
|
134
|
+
outputStyle: true,
|
|
133
135
|
compactionModel: true,
|
|
134
136
|
subagentOutput: facts.subagentOutput(deps).available,
|
|
135
137
|
subagentStream: facts.subagentOutput(deps).available,
|
|
@@ -143,7 +145,7 @@ export async function handleCapabilities(req, res, match, ctx) {
|
|
|
143
145
|
skillToolLists: true,
|
|
144
146
|
projectContext: cwdHonored(deps.config),
|
|
145
147
|
callerCwd: cwdHonored(deps.config) || deviceCwdHonored(deps.config),
|
|
146
|
-
taskWriteFaceOpen: taskWriteFaceRefusal(deps.config) === undefined &&
|
|
148
|
+
taskWriteFaceOpen: taskWriteFaceRefusal(deps.config) === undefined && autonomyKeepsOpenWriteFace(deps.config.autonomy),
|
|
147
149
|
executionLane: projectExecutionLaneCapability(deps.config),
|
|
148
150
|
mcpInjection: facts.mcpInjection(deps).available,
|
|
149
151
|
a2a: true,
|
|
@@ -8,6 +8,7 @@ import { deviceOwnerDomainOf } from "../device-placement.js";
|
|
|
8
8
|
import { echoKeyName } from "../../request-key-closure.js";
|
|
9
9
|
const DEVICE_NOT_FOUND_MESSAGE = "device not found";
|
|
10
10
|
const NO_DEVICE_DOMAIN_MESSAGE = "device management needs a caller domain: this credential carries no verified tenant scope claim (registry auth-bridge JWT `scope`) and is not an explicit operator — connect through the registry auth bridge, or configure OPERATOR_PRINCIPALS";
|
|
11
|
+
const NO_ENROLL_DOMAIN_MESSAGE = "device enrollment needs a registry login that carries a tenant scope: this credential carries no verified tenant scope claim (registry auth-bridge JWT `scope`), and an operator principal carries no scope, so it cannot enroll a device or issue an enroll token — connect through the registry auth bridge with a tenant-scoped login";
|
|
11
12
|
const DEVICE_LANE_REQUIRED_MESSAGE = "device management requires the device execution lane (REMOTE_EXEC=device with a SQL store backend) — this deployment has no device lane wired";
|
|
12
13
|
const _deviceRouteCodesPinned = ["not_found.device", "device.rebind_rev_conflict", "device.rebind_active_run"];
|
|
13
14
|
void _deviceRouteCodesPinned;
|
|
@@ -164,7 +165,7 @@ export async function handleDevices(req, res, match, ctx) {
|
|
|
164
165
|
}
|
|
165
166
|
if (match.decl.id === "device-enroll-tokens") {
|
|
166
167
|
if (domain === undefined) {
|
|
167
|
-
sendError(res, 403, "auth.forbidden",
|
|
168
|
+
sendError(res, 403, "auth.forbidden", NO_ENROLL_DOMAIN_MESSAGE);
|
|
168
169
|
return;
|
|
169
170
|
}
|
|
170
171
|
if ((await readClosedBody(req, res, readJson, [])) === null)
|
|
@@ -180,7 +181,7 @@ export async function handleDevices(req, res, match, ctx) {
|
|
|
180
181
|
}
|
|
181
182
|
if (match.decl.id === "device-enroll") {
|
|
182
183
|
if (domain === undefined) {
|
|
183
|
-
sendError(res, 403, "auth.forbidden",
|
|
184
|
+
sendError(res, 403, "auth.forbidden", NO_ENROLL_DOMAIN_MESSAGE);
|
|
184
185
|
return;
|
|
185
186
|
}
|
|
186
187
|
const raw = await readClosedBody(req, res, readJson, ENROLL_BODY_KEYS);
|
|
@@ -14,6 +14,7 @@ export declare const FLEET_ROUTES: readonly [{
|
|
|
14
14
|
readonly id: "fleet-stream";
|
|
15
15
|
readonly path: "/v1/fleet/stream";
|
|
16
16
|
readonly methods: readonly ["GET"];
|
|
17
|
+
readonly subscription: true;
|
|
17
18
|
}];
|
|
18
19
|
/** 本域可分派行的 `id` 闭集 —— handler 的 `switch` 按它判穷尽(漏一口 = 编译红)。 */
|
|
19
20
|
export type FleetRouteId = RouteIdsOf<typeof FLEET_ROUTES>;
|
|
@@ -239,6 +239,6 @@ function streamFleet(req, res, bus, callerScope, callerSession = null, completio
|
|
|
239
239
|
});
|
|
240
240
|
}
|
|
241
241
|
export const FLEET_ROUTES = [
|
|
242
|
-
{ id: "fleet-stream", path: "/v1/fleet/stream", methods: ["GET"] },
|
|
242
|
+
{ id: "fleet-stream", path: "/v1/fleet/stream", methods: ["GET"], subscription: true },
|
|
243
243
|
];
|
|
244
244
|
//# sourceMappingURL=fleet.js.map
|
|
@@ -55,6 +55,7 @@ export declare const IMAGES_ROUTES: readonly [{
|
|
|
55
55
|
readonly pattern: RegExp;
|
|
56
56
|
readonly label: "/v1/images/bakes/:id/events";
|
|
57
57
|
readonly methods: readonly ["GET"];
|
|
58
|
+
readonly subscription: true;
|
|
58
59
|
}, {
|
|
59
60
|
readonly id: "image-bake-cancel";
|
|
60
61
|
readonly pattern: RegExp;
|
|
@@ -643,7 +643,7 @@ export const IMAGES_ROUTES = [
|
|
|
643
643
|
{ id: "image-bake-claim-next", path: "/v1/images/bakes/claim", methods: ["POST"] },
|
|
644
644
|
{ id: "image-select", path: "/v1/images/select", methods: ["POST"] },
|
|
645
645
|
{ id: "image-register", path: "/v1/images/register", methods: ["POST"] },
|
|
646
|
-
{ id: "image-bake-events", pattern: /^\/v1\/images\/bakes\/(?<bakeId>[^/]+)\/events$/, label: "/v1/images/bakes/:id/events", methods: ["GET"] },
|
|
646
|
+
{ id: "image-bake-events", pattern: /^\/v1\/images\/bakes\/(?<bakeId>[^/]+)\/events$/, label: "/v1/images/bakes/:id/events", methods: ["GET"], subscription: true },
|
|
647
647
|
{ id: "image-bake-cancel", pattern: /^\/v1\/images\/bakes\/(?<bakeId>[^/]+)\/cancel$/, label: "/v1/images/bakes/:id/cancel", methods: ["POST"] },
|
|
648
648
|
{ id: "image-bake-claim", pattern: /^\/v1\/images\/bakes\/(?<bakeId>[^/]+)\/claim$/, label: "/v1/images/bakes/:id/claim", methods: ["POST"] },
|
|
649
649
|
{ id: "image-bake-ingest", pattern: /^\/v1\/images\/bakes\/(?<bakeId>[^/]+)\/ingest$/, label: "/v1/images/bakes/:id/ingest", methods: ["POST"] },
|
|
@@ -16,7 +16,7 @@ export declare function handleLeader(req: IncomingMessage, res: ServerResponse,
|
|
|
16
16
|
export declare const LEADER_ROUTES: readonly [{
|
|
17
17
|
readonly id: "leader-submit";
|
|
18
18
|
readonly path: "/v1/leader";
|
|
19
|
-
readonly billable:
|
|
19
|
+
readonly billable: "submit";
|
|
20
20
|
readonly methods: readonly ["POST"];
|
|
21
21
|
}, {
|
|
22
22
|
readonly id: "leader-detail";
|
|
@@ -2,6 +2,7 @@ import { sendJson, sendError } from "../send.js";
|
|
|
2
2
|
import { gatedPrincipal, headerStr, sendPrincipalRefusal } from "../principal-gate.js";
|
|
3
3
|
import { assertNever } from "../route-ctx.js";
|
|
4
4
|
import * as facts from "../../capability-facts.js";
|
|
5
|
+
import { leaderEntryRefusal, leaderRunEntry } from "../../leader/run-entry.js";
|
|
5
6
|
export const LEADER_SUBMIT_PATH = "/v1/leader";
|
|
6
7
|
export async function handleLeader(req, res, match, ctx) {
|
|
7
8
|
switch (match.decl.id) {
|
|
@@ -35,6 +36,11 @@ export async function handleLeader(req, res, match, ctx) {
|
|
|
35
36
|
sendError(res, 400, "request.invalid_json", "invalid JSON body");
|
|
36
37
|
return;
|
|
37
38
|
}
|
|
39
|
+
const laneRefusal = leaderEntryRefusal(leaderRunEntry(deps.config.autonomy));
|
|
40
|
+
if (laneRefusal !== undefined) {
|
|
41
|
+
sendError(res, 422, "request.autonomy_lane_refused", laneRefusal);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
38
44
|
const r = await endpoint.handle("POST", LEADER_SUBMIT_PATH, body, requester, headerStr(req.headers["idempotency-key"]) ?? null);
|
|
39
45
|
if (r) {
|
|
40
46
|
sendJson(res, r.status, r.body);
|
|
@@ -51,7 +57,7 @@ export async function handleLeader(req, res, match, ctx) {
|
|
|
51
57
|
throw new Error(`leader endpoint did not claim its own declared route: ${match.decl.id}`);
|
|
52
58
|
}
|
|
53
59
|
export const LEADER_ROUTES = [
|
|
54
|
-
{ id: "leader-submit", path: LEADER_SUBMIT_PATH, billable:
|
|
60
|
+
{ id: "leader-submit", path: LEADER_SUBMIT_PATH, billable: "submit", methods: ["POST"] },
|
|
55
61
|
{ id: "leader-detail", pattern: /^\/v1\/leader\/(?<id>[^/]+)$/, label: "/v1/leader/:id", methods: ["GET"] },
|
|
56
62
|
];
|
|
57
63
|
//# sourceMappingURL=leader.js.map
|
|
@@ -58,7 +58,7 @@ export declare function handleMemoryConsolidation(req: IncomingMessage, res: Ser
|
|
|
58
58
|
export declare const MEMORY_CONSOLIDATION_ROUTES: readonly [{
|
|
59
59
|
readonly id: "memory-consolidation-run";
|
|
60
60
|
readonly path: "/v1/admin/memory/consolidation/run";
|
|
61
|
-
readonly billable:
|
|
61
|
+
readonly billable: "submit";
|
|
62
62
|
readonly methods: readonly ["POST"];
|
|
63
63
|
}, {
|
|
64
64
|
readonly id: "memory-consolidation-status";
|
|
@@ -163,7 +163,7 @@ export async function handleMemoryConsolidation(req, res, match, ctx) {
|
|
|
163
163
|
}
|
|
164
164
|
}
|
|
165
165
|
export const MEMORY_CONSOLIDATION_ROUTES = [
|
|
166
|
-
{ id: "memory-consolidation-run", path: MEMORY_CONSOLIDATION_RUN_PATH, billable:
|
|
166
|
+
{ id: "memory-consolidation-run", path: MEMORY_CONSOLIDATION_RUN_PATH, billable: "submit", methods: ["POST"] },
|
|
167
167
|
{ id: "memory-consolidation-status", path: MEMORY_CONSOLIDATION_STATUS_PATH, methods: ["GET"] },
|
|
168
168
|
];
|
|
169
169
|
//# sourceMappingURL=memory-consolidation.js.map
|
|
@@ -22,7 +22,7 @@ export declare const NOTIFY_WAKE_ROUTES: readonly [{
|
|
|
22
22
|
readonly id: "session-wake";
|
|
23
23
|
readonly pattern: RegExp;
|
|
24
24
|
readonly label: "/v1/sessions/:id/$verb";
|
|
25
|
-
readonly billable:
|
|
25
|
+
readonly billable: "submit";
|
|
26
26
|
readonly methods: readonly ["POST"];
|
|
27
27
|
}, {
|
|
28
28
|
readonly id: "session-notify";
|
|
@@ -143,7 +143,7 @@ export async function handleNotifyWake(req, res, match, ctx) {
|
|
|
143
143
|
}
|
|
144
144
|
}
|
|
145
145
|
export const NOTIFY_WAKE_ROUTES = [
|
|
146
|
-
{ id: "session-wake", pattern: /^\/v1\/sessions\/(?<sessionId>[^/]+)\/wake$/, label: "/v1/sessions/:id/$verb", billable:
|
|
146
|
+
{ id: "session-wake", pattern: /^\/v1\/sessions\/(?<sessionId>[^/]+)\/wake$/, label: "/v1/sessions/:id/$verb", billable: "submit", methods: ["POST"] },
|
|
147
147
|
{ id: "session-notify", pattern: /^\/v1\/sessions\/(?<sessionId>[^/]+)\/notify$/, label: "/v1/sessions/:id/$verb", methods: ["POST"] },
|
|
148
148
|
];
|
|
149
149
|
//# sourceMappingURL=notify-wake.js.map
|
|
@@ -4,7 +4,7 @@ import { gatedPrincipal, explicitOperatorOk, sendOperatorPrincipalsRequired, sen
|
|
|
4
4
|
import { assertNever } from "../route-ctx.js";
|
|
5
5
|
import * as facts from "../../capability-facts.js";
|
|
6
6
|
import { createLogger } from "../../observability/logger.js";
|
|
7
|
-
import { RULE_IMPORT_RETRY_AFTER_SEC, RULE_SCOPE_REFUSAL_SENTENCE, MAX_RULE_SCOPE_CHARS, parseRuleScope, serializeRuleScope } from "../../rules-consent.js";
|
|
7
|
+
import { RULE_IMPORT_RETRY_AFTER_SEC, RULE_SCOPE_REFUSAL_SENTENCE, MAX_RULE_SCOPE_CHARS, buildCcImportLayerRootRefusal, parseRuleScope, serializeRuleScope } from "../../rules-consent.js";
|
|
8
8
|
import { CONTROL_AND_BIDI_CHARS } from "../../text-bidi.js";
|
|
9
9
|
import { HttpError } from "../../security.js";
|
|
10
10
|
import { MAX_RULE_TEXT_CHARS, RULE_BEHAVIORS, isValidDurableScope } from "@sema-agent/core";
|
|
@@ -173,8 +173,9 @@ export async function handleRules(req, res, match, ctx) {
|
|
|
173
173
|
sendError(res, 400, "request.body_shape", "body must be {layers:[{layer,path,root,content}]}");
|
|
174
174
|
return;
|
|
175
175
|
}
|
|
176
|
-
|
|
177
|
-
|
|
176
|
+
const refusedLayer = parsed.data.layers.findIndex(ccImportRootRefused);
|
|
177
|
+
if (refusedLayer >= 0) {
|
|
178
|
+
sendError(res, 400, "request.body_shape", buildCcImportLayerRootRefusal(refusedLayer));
|
|
178
179
|
return;
|
|
179
180
|
}
|
|
180
181
|
const prepared = await lane.prepareImport(principal, parsed.data.layers);
|
|
@@ -40,7 +40,7 @@ idemKey: string | undefined): Promise<{
|
|
|
40
40
|
export declare const RUNS_ROUTES: readonly [{
|
|
41
41
|
readonly id: "runs-submit";
|
|
42
42
|
readonly path: "/v1/runs";
|
|
43
|
-
readonly billable:
|
|
43
|
+
readonly billable: "submit";
|
|
44
44
|
readonly methods: readonly ["POST"];
|
|
45
45
|
}, {
|
|
46
46
|
readonly id: "run-steer";
|
|
@@ -72,6 +72,7 @@ export declare const RUNS_ROUTES: readonly [{
|
|
|
72
72
|
readonly pattern: RegExp;
|
|
73
73
|
readonly label: "/v1/runs/:id/events";
|
|
74
74
|
readonly methods: readonly ["GET"];
|
|
75
|
+
readonly subscription: true;
|
|
75
76
|
}, {
|
|
76
77
|
readonly id: "run-detail";
|
|
77
78
|
readonly pattern: RegExp;
|
|
@@ -90,6 +91,7 @@ export declare const RUN_VERBS_ROUTES: readonly [{
|
|
|
90
91
|
readonly pattern: RegExp;
|
|
91
92
|
readonly label: "/v1/runs/:id/subagents/:sub/*";
|
|
92
93
|
readonly methods: readonly ["GET"];
|
|
94
|
+
readonly subscription: true;
|
|
93
95
|
}, {
|
|
94
96
|
readonly id: "run-subagent-steer";
|
|
95
97
|
readonly pattern: RegExp;
|
|
@@ -99,7 +101,7 @@ export declare const RUN_VERBS_ROUTES: readonly [{
|
|
|
99
101
|
readonly id: "run-subagent-resume";
|
|
100
102
|
readonly pattern: RegExp;
|
|
101
103
|
readonly label: "/v1/runs/:id/subagents/:sub/*";
|
|
102
|
-
readonly billable:
|
|
104
|
+
readonly billable: "resume";
|
|
103
105
|
readonly methods: readonly ["POST"];
|
|
104
106
|
}, {
|
|
105
107
|
readonly id: "run-task-output";
|
package/dist/http/routes/runs.js
CHANGED
|
@@ -33,7 +33,8 @@ import { mintAndDriveDurableRun } from "../durable-run-leg.js";
|
|
|
33
33
|
import { RUN_NOT_FOUND_MESSAGE, runNotFoundMessage } from "../route-ctx.js";
|
|
34
34
|
import { withPrincipal } from "../../observability/principal-context.js";
|
|
35
35
|
import { readResumeCtx } from "../resume-ctx-read.js";
|
|
36
|
-
import { storedBodyReplayAnswer, storedBodyReplayLogFields
|
|
36
|
+
import { storedBodyReplayAnswer, storedBodyReplayLogFields } from "../checkpoint-ctx.js";
|
|
37
|
+
import { storedBodyReplayRefusal } from "../stored-body-replay.js";
|
|
37
38
|
const STEER_PRIORITY_WORDS = INJECTION_TIERS.map((tier) => `'${tier}'`);
|
|
38
39
|
const STEER_PRIORITY_UNION = STEER_PRIORITY_WORDS.join(" | ");
|
|
39
40
|
const STEER_PRIORITY_CHOICES = STEER_PRIORITY_WORDS.length <= 2 ? STEER_PRIORITY_WORDS.join(" or ") : `${STEER_PRIORITY_WORDS.slice(0, -1).join(", ")}, or ${STEER_PRIORITY_WORDS[STEER_PRIORITY_WORDS.length - 1]}`;
|
|
@@ -647,7 +648,7 @@ export async function handleRuns(req, res, match, ctx) {
|
|
|
647
648
|
mintResult.noResumeCtx = true;
|
|
648
649
|
return;
|
|
649
650
|
}
|
|
650
|
-
const unservable = storedBodyReplayRefusal(resumeRead.ctx);
|
|
651
|
+
const unservable = storedBodyReplayRefusal(resumeRead.ctx, deps.config.autonomy);
|
|
651
652
|
if (unservable !== undefined) {
|
|
652
653
|
mintResult.unservable = unservable;
|
|
653
654
|
return;
|
|
@@ -1656,20 +1657,20 @@ export async function createDurableRun(req, res, ctx, prepared, idemKey) {
|
|
|
1656
1657
|
return resp;
|
|
1657
1658
|
}
|
|
1658
1659
|
export const RUNS_ROUTES = [
|
|
1659
|
-
{ id: "runs-submit", path: "/v1/runs", billable:
|
|
1660
|
+
{ id: "runs-submit", path: "/v1/runs", billable: "submit", methods: ["POST"] },
|
|
1660
1661
|
{ id: "run-steer", pattern: /^\/v1\/runs\/(?<taskId>[^/]+)\/steer$/, label: "/v1/runs/:id/steer", methods: ["POST"] },
|
|
1661
1662
|
{ id: "run-interrupt", pattern: /^\/v1\/runs\/(?<taskId>[^/]+)\/interrupt$/, label: "/v1/runs/:id/interrupt", methods: ["POST"] },
|
|
1662
1663
|
{ id: "run-detach", pattern: /^\/v1\/runs\/(?<taskId>[^/]+)\/detach$/, label: "/v1/runs/:id/detach", methods: ["POST"] },
|
|
1663
1664
|
{ id: "run-cancel", pattern: /^\/v1\/runs\/(?<taskId>[^/]+)\/cancel$/, label: "/v1/runs/:id/cancel", methods: ["POST"] },
|
|
1664
1665
|
{ id: "run-compact", pattern: /^\/v1\/runs\/(?<taskId>[^/]+)\/compact$/, label: "/v1/runs/:id/compact", methods: ["POST"] },
|
|
1665
|
-
{ id: "run-events", pattern: /^\/v1\/runs\/(?<taskId>[^/]+)\/events$/, label: "/v1/runs/:id/events", methods: ["GET"] },
|
|
1666
|
+
{ id: "run-events", pattern: /^\/v1\/runs\/(?<taskId>[^/]+)\/events$/, label: "/v1/runs/:id/events", methods: ["GET"], subscription: true },
|
|
1666
1667
|
{ id: "run-detail", pattern: /^\/v1\/runs\/(?<taskId>[^/]+)$/, label: "/v1/runs/:id", methods: ["GET"] },
|
|
1667
1668
|
];
|
|
1668
1669
|
export const RUN_VERBS_ROUTES = [
|
|
1669
1670
|
{ id: "run-subagent-output", pattern: /^\/v1\/runs\/(?<runId>[^/]+)\/subagents\/(?<sub>[^/]+)\/output$/, label: "/v1/runs/:id/subagents/:sub/*", methods: ["GET"] },
|
|
1670
|
-
{ id: "run-subagent-stream", pattern: /^\/v1\/runs\/(?<runId>[^/]+)\/subagents\/(?<sub>[^/]+)\/stream$/, label: "/v1/runs/:id/subagents/:sub/*", methods: ["GET"] },
|
|
1671
|
+
{ id: "run-subagent-stream", pattern: /^\/v1\/runs\/(?<runId>[^/]+)\/subagents\/(?<sub>[^/]+)\/stream$/, label: "/v1/runs/:id/subagents/:sub/*", methods: ["GET"], subscription: true },
|
|
1671
1672
|
{ id: "run-subagent-steer", pattern: /^\/v1\/runs\/(?<runId>[^/]+)\/subagents\/(?<sub>[^/]+)\/steer$/, label: "/v1/runs/:id/subagents/:sub/*", methods: ["POST"] },
|
|
1672
|
-
{ id: "run-subagent-resume", pattern: /^\/v1\/runs\/(?<runId>[^/]+)\/subagents\/(?<sub>[^/]+)\/resume$/, label: "/v1/runs/:id/subagents/:sub/*", billable:
|
|
1673
|
+
{ id: "run-subagent-resume", pattern: /^\/v1\/runs\/(?<runId>[^/]+)\/subagents\/(?<sub>[^/]+)\/resume$/, label: "/v1/runs/:id/subagents/:sub/*", billable: "resume", methods: ["POST"] },
|
|
1673
1674
|
{ id: "run-task-output", pattern: /^\/v1\/runs\/(?<runId>[^/]+)\/tasks\/(?<tid>[^/]+)\/output$/, label: "/v1/runs/:id/tasks/:tid/*", methods: ["GET"] },
|
|
1674
1675
|
{ id: "run-task-stop", pattern: /^\/v1\/runs\/(?<runId>[^/]+)\/tasks\/(?<tid>[^/]+)\/stop$/, label: "/v1/runs/:id/tasks/:tid/*", methods: ["POST"] },
|
|
1675
1676
|
{ id: "elicitation-respond", pattern: /^\/v1\/elicitations\/(?<id>[^/]+)\/respond$/, label: "/v1/elicitations/:id/respond", methods: ["POST"] },
|
|
@@ -79,6 +79,7 @@ export declare const SESSIONS_ROUTES: readonly [{
|
|
|
79
79
|
readonly pattern: RegExp;
|
|
80
80
|
readonly label: "/v1/sessions/:id/$verb";
|
|
81
81
|
readonly methods: readonly ["GET"];
|
|
82
|
+
readonly subscription: true;
|
|
82
83
|
}, {
|
|
83
84
|
readonly id: "session-fork";
|
|
84
85
|
readonly pattern: RegExp;
|
|
@@ -844,7 +844,7 @@ export const SESSIONS_ROUTES = [
|
|
|
844
844
|
{ id: "session-mcp", pattern: /^\/v1\/sessions\/(?<sessionId>[^/]+)\/mcp$/, label: "/v1/sessions/:id/$verb", methods: ["GET"] },
|
|
845
845
|
{ id: "session-a2a", pattern: /^\/v1\/sessions\/(?<sessionId>[^/]+)\/a2a$/, label: "/v1/sessions/:id/$verb", methods: ["GET"] },
|
|
846
846
|
{ id: "session-head", pattern: /^\/v1\/sessions\/(?<sessionId>[^/]+)\/head$/, label: "/v1/sessions/:id/$verb", methods: ["GET"] },
|
|
847
|
-
{ id: "session-events", pattern: /^\/v1\/sessions\/(?<sessionId>[^/]+)\/events$/, label: "/v1/sessions/:id/$verb", methods: ["GET"] },
|
|
847
|
+
{ id: "session-events", pattern: /^\/v1\/sessions\/(?<sessionId>[^/]+)\/events$/, label: "/v1/sessions/:id/$verb", methods: ["GET"], subscription: true },
|
|
848
848
|
{ id: "session-fork", pattern: /^\/v1\/sessions\/(?<sessionId>[^/]+)\/fork$/, label: "/v1/sessions/:id/$verb", methods: ["POST"] },
|
|
849
849
|
{ id: "session-policy-get", pattern: /^\/v1\/sessions\/(?<sessionId>[^/]+)\/policy$/, label: "/v1/sessions/:id/$verb", methods: ["GET"] },
|
|
850
850
|
{ id: "session-policy-put", pattern: /^\/v1\/sessions\/(?<sessionId>[^/]+)\/policy$/, label: "/v1/sessions/:id/$verb", methods: ["PUT"] },
|
|
@@ -17,7 +17,7 @@ export declare function handleSideQuery(req: IncomingMessage, res: ServerRespons
|
|
|
17
17
|
export declare const SIDE_QUERY_ROUTES: readonly [{
|
|
18
18
|
readonly id: "side-query";
|
|
19
19
|
readonly path: "/v1/side-query";
|
|
20
|
-
readonly billable:
|
|
20
|
+
readonly billable: "submit";
|
|
21
21
|
readonly methods: readonly ["POST"];
|
|
22
22
|
}];
|
|
23
23
|
/** 本域可分派行的 `id` 闭集 —— handler 的 `switch` 按它判穷尽(漏一口 = 编译红)。 */
|
|
@@ -133,6 +133,6 @@ export async function handleSideQuery(req, res, match, ctx) {
|
|
|
133
133
|
}
|
|
134
134
|
}
|
|
135
135
|
export const SIDE_QUERY_ROUTES = [
|
|
136
|
-
{ id: "side-query", path: "/v1/side-query", billable:
|
|
136
|
+
{ id: "side-query", path: "/v1/side-query", billable: "submit", methods: ["POST"] },
|
|
137
137
|
];
|
|
138
138
|
//# sourceMappingURL=side-query.js.map
|
|
@@ -25,12 +25,12 @@ export declare function handleTasks(req: IncomingMessage, res: ServerResponse, m
|
|
|
25
25
|
export declare const TASKS_ROUTES: readonly [{
|
|
26
26
|
readonly id: "tasks-submit";
|
|
27
27
|
readonly path: "/v1/tasks";
|
|
28
|
-
readonly billable:
|
|
28
|
+
readonly billable: "submit";
|
|
29
29
|
readonly methods: readonly ["POST"];
|
|
30
30
|
}, {
|
|
31
31
|
readonly id: "tasks-submit-stream";
|
|
32
32
|
readonly path: "/v1/tasks/stream";
|
|
33
|
-
readonly billable:
|
|
33
|
+
readonly billable: "submit";
|
|
34
34
|
readonly methods: readonly ["POST"];
|
|
35
35
|
}];
|
|
36
36
|
/** 本域可分派行的 `id` 闭集 —— handler 的 `switch` 按它判穷尽(漏一口 = 编译红)。 */
|
|
@@ -639,7 +639,7 @@ export async function handleTasks(req, res, match, ctx) {
|
|
|
639
639
|
});
|
|
640
640
|
}
|
|
641
641
|
const withApproval = () => approvalCtx && deps.toolApproval ? deps.toolApproval.runWithContext(approvalCtx, withQuestion) : withQuestion();
|
|
642
|
-
await instructionLeg.run(prepared.spec.sessionId, () => withModelReachScope(prepared.spec.sessionId, () => deps.sendUserFile
|
|
642
|
+
await instructionLeg.run(prepared.spec.sessionId, () => withModelReachScope({ sessionId: prepared.spec.sessionId, taskId: durableTaskId }, () => deps.sendUserFile
|
|
643
643
|
? deps.sendUserFile.runWithContext({
|
|
644
644
|
taskId: askTaskId,
|
|
645
645
|
emit: async (f) => {
|
|
@@ -901,7 +901,7 @@ export async function handleTasks(req, res, match, ctx) {
|
|
|
901
901
|
}
|
|
902
902
|
}
|
|
903
903
|
export const TASKS_ROUTES = [
|
|
904
|
-
{ id: "tasks-submit", path: "/v1/tasks", billable:
|
|
905
|
-
{ id: "tasks-submit-stream", path: "/v1/tasks/stream", billable:
|
|
904
|
+
{ id: "tasks-submit", path: "/v1/tasks", billable: "submit", methods: ["POST"] },
|
|
905
|
+
{ id: "tasks-submit-stream", path: "/v1/tasks/stream", billable: "submit", methods: ["POST"] },
|
|
906
906
|
];
|
|
907
907
|
//# sourceMappingURL=tasks.js.map
|
|
@@ -38,6 +38,7 @@ export declare const TRACE_USAGE_ROUTES: readonly [{
|
|
|
38
38
|
readonly pattern: RegExp;
|
|
39
39
|
readonly label: "/v1/tasks/:id/$sub";
|
|
40
40
|
readonly methods: readonly ["GET"];
|
|
41
|
+
readonly subscription: true;
|
|
41
42
|
}, {
|
|
42
43
|
readonly id: "task-trace-artifacts";
|
|
43
44
|
readonly pattern: RegExp;
|
|
@@ -302,7 +302,7 @@ export const TRACE_USAGE_ROUTES = [
|
|
|
302
302
|
{ id: "task-trace-list", path: "/v1/tasks", methods: ["GET"] },
|
|
303
303
|
{ id: "task-tool-result", pattern: /^\/v1\/tasks\/(?<taskId>[^/]+)\/tool-results\/(?<ref>[^/]+)$/, label: "/v1/tasks/:id/tool-results/:ref", methods: ["GET"] },
|
|
304
304
|
{ id: "task-trace-turns", pattern: /^\/v1\/tasks\/(?<taskId>[^/]+)\/turns$/, label: "/v1/tasks/:id/$sub", methods: ["GET"] },
|
|
305
|
-
{ id: "task-trace-stream", pattern: /^\/v1\/tasks\/(?<taskId>[^/]+)\/stream$/, label: "/v1/tasks/:id/$sub", methods: ["GET"] },
|
|
305
|
+
{ id: "task-trace-stream", pattern: /^\/v1\/tasks\/(?<taskId>[^/]+)\/stream$/, label: "/v1/tasks/:id/$sub", methods: ["GET"], subscription: true },
|
|
306
306
|
{ id: "task-trace-artifacts", pattern: /^\/v1\/tasks\/(?<taskId>[^/]+)\/artifacts$/, label: "/v1/tasks/:id/$sub", methods: ["GET"] },
|
|
307
307
|
{ id: "usage-analytics", pattern: /^\/v1\/usage\/(?<sub>summary|series|breakdown)$/, label: "/v1/usage/$sub", methods: ["GET"] },
|
|
308
308
|
];
|
|
@@ -15,6 +15,7 @@ export declare const WORKFLOWS_ROUTES: readonly [{
|
|
|
15
15
|
readonly pattern: RegExp;
|
|
16
16
|
readonly label: "/v1/workflows/:id/$sub";
|
|
17
17
|
readonly methods: readonly ["GET"];
|
|
18
|
+
readonly subscription: true;
|
|
18
19
|
}, {
|
|
19
20
|
readonly id: "workflow-journal";
|
|
20
21
|
readonly pattern: RegExp;
|
|
@@ -416,7 +416,7 @@ function sendWorkflowsUnavailable(res, why) {
|
|
|
416
416
|
}
|
|
417
417
|
export const WORKFLOWS_ROUTES = [
|
|
418
418
|
{ id: "workflows-list", path: "/v1/workflows", methods: ["GET"] },
|
|
419
|
-
{ id: "workflow-stream", pattern: /^\/v1\/workflows\/(?<runId>[^/]+)\/stream$/, label: "/v1/workflows/:id/$sub", methods: ["GET"] },
|
|
419
|
+
{ id: "workflow-stream", pattern: /^\/v1\/workflows\/(?<runId>[^/]+)\/stream$/, label: "/v1/workflows/:id/$sub", methods: ["GET"], subscription: true },
|
|
420
420
|
{ id: "workflow-journal", pattern: /^\/v1\/workflows\/(?<runId>[^/]+)\/journal$/, label: "/v1/workflows/:id/$sub", methods: ["GET"] },
|
|
421
421
|
{ id: "workflow-detail", pattern: /^\/v1\/workflows\/(?<runId>[^/]+)$/, label: "/v1/workflows/:id", methods: ["GET"] },
|
|
422
422
|
];
|
package/dist/http/send.d.ts
CHANGED
|
@@ -47,6 +47,19 @@ export declare const SSE_MAX_STREAM_MS: number;
|
|
|
47
47
|
* 要么给 approvals 减 type=消费端破坏),属候裁,不在本批的零行为码范围内。
|
|
48
48
|
*/
|
|
49
49
|
export declare const SSE_HEARTBEAT_IDLE_MS = 15000;
|
|
50
|
+
/**
|
|
51
|
+
* S-1281 —— 服务端**主动**收一条已开的 SSE 流:一帧 `event: error`(帧形与流帽那一帧同一套 `{type:"error", errorCode, message}`,
|
|
52
|
+
* 消费端按既有「服务端收流 ⇒ 重连」协议处置,SDK 的流读口把它当一帧事件交出再重连)后 `end()`。
|
|
53
|
+
*
|
|
54
|
+
* 收流的是分派器,不是流自己的泵:泵此刻可能正停在一次 await 上,醒来还会写一帧。Node 上 `end()` 之后、`close` 之前的那一写会发一个
|
|
55
|
+
* `error` 事件(实测 v24.2.0:无监听 ⇒ 进程级未捕获;`close` 之后的写只回 `false`,不再发)。⇒ 先挂一只**只吸收这一种**
|
|
56
|
+
* (`ERR_STREAM_WRITE_AFTER_END`)的监听再 `end()`:那一帧本来就无处可去(连接是我们关的),别的错照旧抛(不改既有失败形)。
|
|
57
|
+
* 已收尾的流不碰(幂等;排空入口与硬停起点各调一次)。
|
|
58
|
+
*/
|
|
59
|
+
export declare function endSseWithError(res: ServerResponse, frame: {
|
|
60
|
+
readonly errorCode: string;
|
|
61
|
+
readonly message: string;
|
|
62
|
+
}): void;
|
|
50
63
|
export declare function sendJson(res: ServerResponse, status: number, body: unknown): void;
|
|
51
64
|
/** A6([ref] lens1 §C3/lens3 §C3a): canonical error-response sender for sites that already carry a
|
|
52
65
|
* machine `errorCode` — `errorCode` is a required positional arg (not optional-bag) so a call site
|
package/dist/http/send.js
CHANGED
|
@@ -17,6 +17,15 @@ export function sseHeaders(res, extra) {
|
|
|
17
17
|
}
|
|
18
18
|
export const SSE_MAX_STREAM_MS = 15 * 60 * 1000;
|
|
19
19
|
export const SSE_HEARTBEAT_IDLE_MS = 15_000;
|
|
20
|
+
export function endSseWithError(res, frame) {
|
|
21
|
+
if (res.writableEnded || res.destroyed)
|
|
22
|
+
return;
|
|
23
|
+
res.on("error", (err) => {
|
|
24
|
+
if (err.code !== "ERR_STREAM_WRITE_AFTER_END")
|
|
25
|
+
throw err;
|
|
26
|
+
});
|
|
27
|
+
res.end(`event: error\ndata: ${JSON.stringify({ type: "error", errorCode: frame.errorCode, message: frame.message })}\n\n`);
|
|
28
|
+
}
|
|
20
29
|
export function sendJson(res, status, body) {
|
|
21
30
|
res.writeHead(status, { "content-type": "application/json" });
|
|
22
31
|
res.end(JSON.stringify(body));
|
package/dist/http/server.d.ts
CHANGED
|
@@ -649,8 +649,6 @@ export interface ServiceGovernanceDeps {
|
|
|
649
649
|
* 「诊断说亮、位说暗」。缺席(桩/一次性 CLI)⇒ 读面如实答 `deployment_incapable`。 */
|
|
650
650
|
autoModeFace?: import("../auto-mode-face.js").AutoModeFaceDeps;
|
|
651
651
|
}
|
|
652
|
-
/** **部署自述面**:只被 /health、/v1/capabilities 与提交前置门读的部署事实(多为 live getter,
|
|
653
|
-
* 不是快照——/health 必须回答「此刻」)。 */
|
|
654
652
|
export interface ServiceDeploymentDeps {
|
|
655
653
|
/** Stable per-process id recorded on runs (audit / stale recovery). */
|
|
656
654
|
instanceId?: string;
|
|
@@ -686,16 +684,14 @@ export interface ServiceDeploymentDeps {
|
|
|
686
684
|
* • [ref]:`attachedStreams` 同样 ASSIGNED BY createServer —— 本副本当前打开着的 SSE 流条数
|
|
687
685
|
* (= 引擎附着租约集的大小)。消费方是 `boot/engine-lease.ts` 的自退判据;与 `inflight` 同族,
|
|
688
686
|
* 同一个共享盒子,不另开第二条 main↔server 的通道。
|
|
687
|
+
* • S-1281:`inflight` 只数**工作** —— 只读订阅流(路由表 `subscription` 列的八条 GET SSE 读面)不进 admission 计数,只进
|
|
688
|
+
* `attachedStreams`;`endSubscriptions`(同样 ASSIGNED BY createServer)发 `draining` 终帧后关掉它们,收尾链在排空进入那一拍与
|
|
689
|
+
* 硬停起点各调一次。
|
|
689
690
|
*/
|
|
690
|
-
drainState?:
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
inflight?: () => number;
|
|
695
|
-
lastActivityAt?: () => number;
|
|
696
|
-
attachedStreams?: () => number;
|
|
697
|
-
lastAttachEndedAt?: () => number;
|
|
698
|
-
};
|
|
691
|
+
drainState?: import("../fleet/drain-entry.js").DrainState;
|
|
692
|
+
/** 编排器片 2 件 3:服务租约此刻的读数(`fleet/serving-lease.ts` 的客户端交出;引擎信号铸点与计费准入判同读)。缺席 = 没装租约客户端
|
|
693
|
+
* (非 fleet 成员 / 没接中心 / 测试夹具)⇒ `none`(与没有租约的引擎逐字同)。 */
|
|
694
|
+
servingLease?: () => import("../fleet/engine-signal.js").ServingLeaseView;
|
|
699
695
|
/** boot ready 门(b):false = 布防(`CONFIG_REQUIRE_ROSTER=true`)且首次 effective pull 尚未落 roster
|
|
700
696
|
* (worker 只有占位模型)。就绪原因 `model_roster_pending`(`http/readiness.ts`):计费提交 503 + `/readyz` 503 +
|
|
701
697
|
* /health 加性 `ready:false`。absent = 恒 ready(未布防 / 非 registry 部署),现有部署零影响。config-center 的
|
|
@@ -722,6 +718,9 @@ export interface ServiceDeploymentDeps {
|
|
|
722
718
|
* (`boot/stage-10-http-server.ts` → `modelRefusals: () => deployment.modelRefusalsState?.()`)—— 一处铸、两出口。缺席 / 返回 undefined =
|
|
723
719
|
* 没有可报的拒或没有配置管道 ⇒ `/health` 形状逐字不变(additive)。 */
|
|
724
720
|
modelRefusalsState?: () => import("@sema-agent/settings-schema").ModelRefusalsSignal | undefined;
|
|
721
|
+
/** `/health.configHandoff`(只上 `/health`):在场 ⇔ 部署声明了耐久接力 ∧ 应用着的那一代没被确认(config-center 接力账的 `configHandoffState()`;合成律
|
|
722
|
+
* `fleet/engine-signal.ts` 的 `buildConfigHandoff`)。缺席 / 返回 undefined = 有接力、没有中心或本地腿 ⇒ 键缺席。 */
|
|
723
|
+
configHandoffState?: () => import("../fleet/engine-signal.js").ConfigHandoff | undefined;
|
|
725
724
|
/** [ref] 追加件:`POST /v1/admin/config/refresh` 的实现面 —— 触发**一次既有**的 refresh 拍(在飞则 join)。
|
|
726
725
|
* 缺席 / 回 `"not-wired"` = 本部署没有配置管道 ⇒ 该口诚实 4xx(绝不吞成 200)。 */
|
|
727
726
|
configRefreshNow?: () => Promise<"triggered" | "not-wired" | "failed">;
|
|
@@ -739,16 +738,6 @@ export interface ServiceDeploymentDeps {
|
|
|
739
738
|
mcpRevocationState?: () => {
|
|
740
739
|
revoked: string[];
|
|
741
740
|
} | undefined;
|
|
742
|
-
/** codex R18: the persistent "retained WITHOUT a next-boot handoff" state — a candidate whose restart signal is
|
|
743
|
-
* withheld because no restart-surviving handoff exists yet (durable-declared LKG publication incomplete, or a
|
|
744
|
-
* boot skills debt not yet proven repairable). Surfaced on /health (`modelPlaneDeferred` — the key keeps its birth
|
|
745
|
-
* name: it was born for the model-plane deferral, which retired with the `models-tiers` slice in S-668 波 0) so
|
|
746
|
-
* the stuck state outlives the one-shot warn (the etag advances → later ticks 304). */
|
|
747
|
-
planeDeferredState?: () => {
|
|
748
|
-
version: number;
|
|
749
|
-
since: number;
|
|
750
|
-
blocked?: string[];
|
|
751
|
-
} | undefined;
|
|
752
741
|
/** B1(鲁棒性批3 设计件):后台**缓存**探针的读座——/health 绝不逐请求打 DB(center/k8s 高频面),
|
|
753
742
|
* main.ts 只在 SQL 后端(backend.kind !== "local")挂环(createStoreLiveProbe,STORE_PROBE_INTERVAL_MS)。
|
|
754
743
|
* 缺席(local/memory/探针关)= /health 形状不变;接线 = `storeProbe{live,ageMs,error?}` 恒在
|