@sema-agent/server 7.79.2 → 7.80.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/dist/boot/late-binds.d.ts +35 -0
- package/dist/boot/late-binds.js +20 -0
- package/dist/boot/stage-01-config.d.ts +7 -0
- package/dist/boot/stage-01-config.js +60 -0
- package/dist/boot/stage-02-registry-pull.d.ts +10 -0
- package/dist/boot/stage-02-registry-pull.js +11 -0
- package/dist/boot/stage-03-store-backend.d.ts +32 -0
- package/dist/boot/stage-03-store-backend.js +11 -0
- package/dist/boot/stage-04-stores.d.ts +69 -0
- package/dist/boot/stage-04-stores.js +49 -0
- package/dist/boot/stage-05-execution-env.d.ts +82 -0
- package/dist/boot/stage-05-execution-env.js +20 -0
- package/dist/boot/stage-06-runners.d.ts +143 -0
- package/dist/boot/stage-06-runners.js +207 -0
- package/dist/boot/stage-07-capability-layer.d.ts +157 -0
- package/dist/boot/stage-07-capability-layer.js +162 -0
- package/dist/boot/stage-08-reapers.d.ts +172 -0
- package/dist/boot/stage-08-reapers.js +78 -0
- package/dist/boot/stage-09-leader.d.ts +204 -0
- package/dist/boot/stage-09-leader.js +47 -0
- package/dist/boot/stage-10-http-server.d.ts +204 -0
- package/dist/boot/stage-10-http-server.js +289 -0
- package/dist/config-invariants.d.ts +9 -0
- package/dist/config-invariants.js +7 -1
- package/dist/config-types.d.ts +1 -1
- package/dist/http/dispatch.js +28 -8
- package/dist/http/route-ctx.d.ts +101 -4
- package/dist/http/route-ctx.js +4 -0
- package/dist/http/route-table.d.ts +71 -43
- package/dist/http/route-table.js +111 -187
- package/dist/http/routes/a2a-serve.d.ts +18 -3
- package/dist/http/routes/a2a-serve.js +25 -23
- package/dist/http/routes/admin-config-refresh.d.ts +9 -2
- package/dist/http/routes/admin-config-refresh.js +32 -31
- package/dist/http/routes/admin-drain.d.ts +9 -2
- package/dist/http/routes/admin-drain.js +32 -31
- package/dist/http/routes/admin-memory-optout.d.ts +28 -2
- package/dist/http/routes/admin-memory-optout.js +26 -39
- package/dist/http/routes/adoption.d.ts +15 -2
- package/dist/http/routes/adoption.js +52 -52
- package/dist/http/routes/agents-roster.d.ts +9 -2
- package/dist/http/routes/agents-roster.js +82 -80
- package/dist/http/routes/approvals-assistant.d.ts +58 -5
- package/dist/http/routes/approvals-assistant.js +37 -38
- package/dist/http/routes/attachments.d.ts +22 -2
- package/dist/http/routes/attachments.js +81 -72
- package/dist/http/routes/capabilities.d.ts +21 -2
- package/dist/http/routes/capabilities.js +174 -170
- package/dist/http/routes/config-catalog.d.ts +9 -2
- package/dist/http/routes/config-catalog.js +28 -31
- package/dist/http/routes/devices.d.ts +24 -2
- package/dist/http/routes/devices.js +19 -21
- package/dist/http/routes/diagnostics.d.ts +9 -2
- package/dist/http/routes/diagnostics.js +41 -43
- package/dist/http/routes/fleet.d.ts +11 -2
- package/dist/http/routes/fleet.js +23 -22
- package/dist/http/routes/images.d.ts +63 -9
- package/dist/http/routes/images.js +53 -46
- package/dist/http/routes/leader.d.ts +20 -2
- package/dist/http/routes/leader.js +43 -40
- package/dist/http/routes/memory-bundle.d.ts +15 -2
- package/dist/http/routes/memory-bundle.js +38 -38
- package/dist/http/routes/memory-compliance.d.ts +16 -4
- package/dist/http/routes/memory-compliance.js +44 -45
- package/dist/http/routes/memory-consolidation.d.ts +14 -2
- package/dist/http/routes/memory-consolidation.js +66 -66
- package/dist/http/routes/memory-origin.d.ts +23 -4
- package/dist/http/routes/memory-origin.js +65 -65
- package/dist/http/routes/memory-policy.d.ts +21 -2
- package/dist/http/routes/memory-policy.js +119 -115
- package/dist/http/routes/notify-wake.d.ts +21 -11
- package/dist/http/routes/notify-wake.js +118 -116
- package/dist/http/routes/observability.d.ts +16 -2
- package/dist/http/routes/observability.js +54 -51
- package/dist/http/routes/retention-ops.d.ts +19 -2
- package/dist/http/routes/retention-ops.js +20 -22
- package/dist/http/routes/rules.d.ts +36 -2
- package/dist/http/routes/rules.js +22 -24
- package/dist/http/routes/run-memory-capture.d.ts +10 -3
- package/dist/http/routes/run-memory-capture.js +84 -84
- package/dist/http/routes/runs.d.ts +102 -22
- package/dist/http/routes/runs.js +71 -88
- package/dist/http/routes/session-sync.d.ts +41 -2
- package/dist/http/routes/session-sync.js +25 -23
- package/dist/http/routes/sessions-list.d.ts +16 -2
- package/dist/http/routes/sessions-list.js +78 -75
- package/dist/http/routes/sessions.d.ts +77 -2
- package/dist/http/routes/sessions.js +50 -47
- package/dist/http/routes/shared-memory.d.ts +19 -2
- package/dist/http/routes/shared-memory.js +65 -63
- package/dist/http/routes/side-query.d.ts +11 -2
- package/dist/http/routes/side-query.js +81 -79
- package/dist/http/routes/tasks.d.ts +17 -2
- package/dist/http/routes/tasks.js +18 -11
- package/dist/http/routes/trace-usage.d.ts +40 -2
- package/dist/http/routes/trace-usage.js +46 -35
- package/dist/http/routes/workflows.d.ts +35 -3
- package/dist/http/routes/workflows.js +29 -29
- package/dist/main.js +20 -870
- package/dist/service-version.d.ts +5 -0
- package/dist/service-version.js +12 -0
- package/dist/trace/redact.d.ts +7 -6
- package/dist/trace/redact.js +419 -229
- package/package.json +1 -1
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import type { runStage09 } from "./stage-09-leader.js";
|
|
2
|
+
export declare function runStage10(ctx: Awaited<ReturnType<typeof runStage09>>): Promise<{
|
|
3
|
+
drainState: {
|
|
4
|
+
draining: boolean;
|
|
5
|
+
since?: number;
|
|
6
|
+
reason?: string;
|
|
7
|
+
inflight?: () => number;
|
|
8
|
+
lastActivityAt?: () => number;
|
|
9
|
+
attachedStreams?: () => number;
|
|
10
|
+
lastAttachEndedAt?: () => number;
|
|
11
|
+
};
|
|
12
|
+
hookWakeBus: {
|
|
13
|
+
deliver?: (sessionId: string, text: string) => Promise<boolean>;
|
|
14
|
+
};
|
|
15
|
+
instrumentDegenerate: ((result: import("@sema-agent/core").TaskResult) => void) | undefined;
|
|
16
|
+
leaderEndpoint: import("../leader/endpoint.js").LeaderEndpoint | undefined;
|
|
17
|
+
ownerAware: import("../security.js").OwnerAwareSessionStore;
|
|
18
|
+
planCacheProbe: import("../plan-cache-probe.js").PlanCacheProbe;
|
|
19
|
+
purgeSession: ((sessionId: string, owner: string | null) => Promise<{
|
|
20
|
+
deleted: boolean;
|
|
21
|
+
} | {
|
|
22
|
+
active: string;
|
|
23
|
+
}>) | undefined;
|
|
24
|
+
registryJwtVerifier: import("../auth-bridge.js").RegistryJwtVerifier | undefined;
|
|
25
|
+
sessionAudit: ((sessionId: string) => Promise<{
|
|
26
|
+
owner: string | null;
|
|
27
|
+
sessionId: string;
|
|
28
|
+
createdAt: string;
|
|
29
|
+
floorEntryId: string | null;
|
|
30
|
+
thinkingLevel: string;
|
|
31
|
+
model: {
|
|
32
|
+
provider: string;
|
|
33
|
+
modelId: string;
|
|
34
|
+
} | null;
|
|
35
|
+
messages: unknown[];
|
|
36
|
+
promptEpoch?: {
|
|
37
|
+
epoch: number;
|
|
38
|
+
artifactDigest: string;
|
|
39
|
+
packId: string;
|
|
40
|
+
assemblyApi: number;
|
|
41
|
+
activatedBy: "session_start" | "compaction" | "legacy_migration";
|
|
42
|
+
};
|
|
43
|
+
} | undefined>) | undefined;
|
|
44
|
+
sessionWatchRegistry: import("../session-watch.js").SessionWatchRegistry | undefined;
|
|
45
|
+
staticWiring: import("@sema-agent/core").WiringManifest;
|
|
46
|
+
otelExporter: {
|
|
47
|
+
stop(): void;
|
|
48
|
+
} | undefined;
|
|
49
|
+
reaper: NodeJS.Timeout;
|
|
50
|
+
retentionLaneStarted: import("./retention-lane.js").RetentionLaneController | undefined;
|
|
51
|
+
approvalExemptionStore: import("../plugins/approval-exemption-store.js").ApprovalExemptionStore | undefined;
|
|
52
|
+
approvalNonceStore: import("../plugins/approval-nonce-store.js").ApprovalNonceStore | undefined;
|
|
53
|
+
authorize: (ctx: {
|
|
54
|
+
req: import("http").IncomingMessage;
|
|
55
|
+
body: import("../index.js").TaskRequestBody;
|
|
56
|
+
}) => Promise<import("../security.js").AuthContext>;
|
|
57
|
+
imageBakes: import("../plugins/store-backend.js").ImageBake | undefined;
|
|
58
|
+
imageIndex: import("../plugins/store-backend.js").ImageIndex | undefined;
|
|
59
|
+
parkedReviveInheritedGate: ((row: import("@sema-agent/core").BackgroundAgentRecord, identity: import("./parked-revive-gate.js").ParkedReviveIdentity) => Promise<import("./parked-revive-gate.js").RebuiltInheritedGate>) | undefined;
|
|
60
|
+
parkedReviveTool: import("@sema-agent/core").ToolSpec<import("@sema-agent/core").TSchema> | undefined;
|
|
61
|
+
rateLimiter: import("../index.js").RateLimiter | import("../plugins/pg-rate-limiter.js").PgRateLimiter | import("../plugins/tidb-rate-limiter.js").TiDBRateLimiter;
|
|
62
|
+
resumeAnchorStore: import("../plugins/store-backend.js").ResumeAnchorStore | undefined;
|
|
63
|
+
runStore: import("../plugins/store-backend.js").RunStore | undefined;
|
|
64
|
+
scenarioDetails: Record<string, import("../capabilities/scenarios.js").ScenarioDetail>;
|
|
65
|
+
scenarios: Record<string, import("../index.js").Scenario>;
|
|
66
|
+
selectEnvTool: import("@sema-agent/core").ToolSpec<import("@sema-agent/core").TSchema> | undefined;
|
|
67
|
+
singleUserAutoAcceptBaseline: boolean;
|
|
68
|
+
taskLimitCaps: {
|
|
69
|
+
timeoutSec: number | undefined;
|
|
70
|
+
maxOutputTokens: number | undefined;
|
|
71
|
+
maxTurns: number | undefined;
|
|
72
|
+
};
|
|
73
|
+
taskTimeoutSec: number;
|
|
74
|
+
approvalAskAudit: import("../approval-ask-audit-store.js").FileApprovalAskAuditStore | undefined;
|
|
75
|
+
centerRuntimeCapsResolver: ((principal: string | undefined) => Promise<import("@sema-agent/core").RuntimeCaps | undefined>) | undefined;
|
|
76
|
+
checkpointStore: import("../plugins/store-backend.js").CheckpointStoreFull | undefined;
|
|
77
|
+
durableEnabled: boolean;
|
|
78
|
+
elicitation: import("../elicitation.js").ElicitationCoordinator | undefined;
|
|
79
|
+
fleetBus: import("../fleet/fleet-bus.js").FleetEventBus;
|
|
80
|
+
governanceSeams: import("./governance-seams.js").GovernanceSeams;
|
|
81
|
+
handslessRunner: import("@sema-agent/core").Runner;
|
|
82
|
+
handslessSubRunner: import("@sema-agent/core").Runner;
|
|
83
|
+
hookAgent: import("../hooks/hook-runner.js").HookLlmCall;
|
|
84
|
+
hookAgentRunner: import("@sema-agent/core").Runner;
|
|
85
|
+
hookLlm: import("../hooks/hook-runner.js").HookLlmCall;
|
|
86
|
+
mcpRevocations: import("../config-center/mcp-revocation.js").McpRevocationLedger;
|
|
87
|
+
memoryConsolidationFaces: import("./memory-consolidation.js").MemoryConsolidationFaces | undefined;
|
|
88
|
+
memoryOptOutGrantStore: import("../plugins/memory-optout-grant-store-sql.js").MemoryOptOutGrantStore | undefined;
|
|
89
|
+
orgMemoryAdmission: import("./org-memory.js").OrgMemoryAdmissionWiring;
|
|
90
|
+
outcomeSink: import("../plugins/file-outcome-sink.js").OutcomeSink | undefined;
|
|
91
|
+
principalCaps: import("../runtime-caps-resolver.js").PrincipalEntitlementsClient | undefined;
|
|
92
|
+
question: import("../question.js").QuestionCoordinator | undefined;
|
|
93
|
+
retentionExecutor: import("../plugins/retention-store-sql.js").SqlRetentionStore | undefined;
|
|
94
|
+
retentionLaneStore: import("../plugins/retention-lane-store-sql.js").RetentionLaneStore | undefined;
|
|
95
|
+
runner: import("@sema-agent/core").Runner;
|
|
96
|
+
runnerDeps: import("@sema-agent/core").RunnerDeps;
|
|
97
|
+
runnerTierFrozen: boolean;
|
|
98
|
+
runtimeCapsPeekResolver: import("../runtime-caps-resolver.js").EntitlementsResolverFn | undefined;
|
|
99
|
+
sendFileLedger: import("../plugins/send-file-ledger.js").SendFileLedger | undefined;
|
|
100
|
+
sendUserFileEmitter: import("../capabilities/send-user-file-tool.js").SendUserFileEmitter | undefined;
|
|
101
|
+
sendUserFileToolSpec: import("@sema-agent/core").ToolSpec<import("@sema-agent/core").TSchema> | undefined;
|
|
102
|
+
sessionShellGateRegistry: import("./session-shell-gate-registry.js").SessionShellGateRegistry;
|
|
103
|
+
sessionTitler: import("../session-titler.js").SessionTitler | undefined;
|
|
104
|
+
sharedMemoryStore: import("../plugins/shared-memory-store-sql.js").SqlSharedMemoryStore | undefined;
|
|
105
|
+
sqlWorkflowRunStore: import("@sema-agent/core").WorkflowRunStore | undefined;
|
|
106
|
+
streamApprovalGate: import("../tool-approval.js").StreamApprovalGate;
|
|
107
|
+
subRunner: import("@sema-agent/core").Runner;
|
|
108
|
+
subRunnerSessions: import("../plugins/fork-routing-session-store.js").ForkRoutingSessionStore;
|
|
109
|
+
subagentSteerRegistry: import("../orchestration/subagent-steer.js").SubagentSteerRegistry;
|
|
110
|
+
toolApproval: import("../tool-approval.js").ToolApprovalCoordinator | undefined;
|
|
111
|
+
workflowAgentRegistry: import("../orchestration/workflow-agent-steer.js").WorkflowAgentRegistry | undefined;
|
|
112
|
+
workflowAgentSessionIndex: import("../orchestration/workflow-agent-session-index.js").WorkflowAgentSessionIndex | undefined;
|
|
113
|
+
workflowCompletionInbox: import("../orchestration/workflow-completion-inbox.js").WorkflowCompletionInbox | undefined;
|
|
114
|
+
workflowJournalStore: import("../plugins/store-backend.js").ServiceWorkflowJournalStore | undefined;
|
|
115
|
+
workflowModelAllowlistSnapshot: readonly string[];
|
|
116
|
+
workflowNotifyGate: import("../orchestration/workflow-notify-journal.js").WorkflowNotifyGate | undefined;
|
|
117
|
+
workflowNotifyJournal: import("../orchestration/workflow-notify-journal.js").WorkflowNotifyJournalStore | undefined;
|
|
118
|
+
workflowRecoverOpts: {
|
|
119
|
+
orphanGraceMs?: number;
|
|
120
|
+
finalizeStartedBeforeMs?: number;
|
|
121
|
+
publishTerminalFleetRow?: (id: string, run: import("@sema-agent/core").WorkflowRun) => void;
|
|
122
|
+
};
|
|
123
|
+
workflowRunStore: import("../orchestration/workflow-notify-journal.js").JournalingWorkflowRunStore | undefined;
|
|
124
|
+
workflowsCapable: boolean;
|
|
125
|
+
deploymentHooks: import("@sema-agent/core").Hooks;
|
|
126
|
+
deviceLane: import("./device-lane.js").DeviceLane | undefined;
|
|
127
|
+
dropSessionScoped: (sid: string) => void;
|
|
128
|
+
executionEnvFactory: import("@sema-agent/core").ExecutionEnvFactory | undefined;
|
|
129
|
+
fenceSessionOwner: (sid: string, owner: string | null) => void;
|
|
130
|
+
lspManager: import("../lsp/manager.js").E2bLspManager | import("@sema-agent/core").NodeLspManager | undefined;
|
|
131
|
+
perSessionCwd: Map<string, string>;
|
|
132
|
+
perTaskImage: import("../per-task-image.js").PerTaskImageRegistry;
|
|
133
|
+
sendUserFileTaskEnvs: import("../capabilities/sandbox-file-send.js").TaskEnvRegistry | undefined;
|
|
134
|
+
sessionEnvSelection: import("../capabilities/select-environment-tool.js").SessionEnvironmentSelection;
|
|
135
|
+
setSessionCwd: (sid: string, cwd: string) => void;
|
|
136
|
+
setSessionShellEnv: (sid: string, env: Record<string, string>) => void;
|
|
137
|
+
worktreeReap: (() => Promise<void>) | undefined;
|
|
138
|
+
brain: import("@sema-agent/core").Brain;
|
|
139
|
+
costQuota: import("../observability/cost-quota.js").CostQuota | import("../plugins/pg-cost-quota.js").PgCostQuota | import("../plugins/tidb-cost-quota.js").TiDBCostQuota;
|
|
140
|
+
counterDegradeHook: (info: {
|
|
141
|
+
table: string;
|
|
142
|
+
kind: string;
|
|
143
|
+
streak: number;
|
|
144
|
+
prevStreak: number;
|
|
145
|
+
error?: string;
|
|
146
|
+
}) => void;
|
|
147
|
+
fileHistoryStore: import("../plugins/store-backend.js").ServiceFileHistoryStore | undefined;
|
|
148
|
+
fleetLease: import("../fleet-lease.js").FleetLeaseManager | undefined;
|
|
149
|
+
fleetUsage: import("../fleet-client.js").FleetUsageAccumulator | undefined;
|
|
150
|
+
memoryBundleFaces: import("../memory-bundle-engine.js").MemoryBundleFaces | undefined;
|
|
151
|
+
memoryComplianceFaces: import("../memory-operator-faces.js").MemoryComplianceFaces | undefined;
|
|
152
|
+
memoryOriginFaces: import("../memory-operator-faces.js").MemoryOriginFaces | undefined;
|
|
153
|
+
modelUsageTracker: import("../budget.js").ModelUsageTracker;
|
|
154
|
+
permissionRuleProvider: import("@sema-agent/core").PermissionRuleStoreProvider | undefined;
|
|
155
|
+
permissionRuleStores: import("../rules-consent.js").PermissionRuleStoreBundle | undefined;
|
|
156
|
+
pricing: Record<string, import("@sema-agent/core").ModelPricing>;
|
|
157
|
+
promptManifestTracker: import("../budget.js").PromptManifestTracker;
|
|
158
|
+
ruleConsent: import("../rules-consent.js").RuleConsentLane | undefined;
|
|
159
|
+
sessionMemoryStatusFace: import("../memory-operator-faces.js").SessionMemoryStatusFace | undefined;
|
|
160
|
+
sessionPolicyStore: import("@sema-agent/core").SessionPolicyStore | undefined;
|
|
161
|
+
sideQueryAccounting: (principal: string | undefined, r: {
|
|
162
|
+
model: string;
|
|
163
|
+
usage?: {
|
|
164
|
+
input?: number;
|
|
165
|
+
output?: number;
|
|
166
|
+
cacheRead?: number;
|
|
167
|
+
cacheWrite?: number;
|
|
168
|
+
cost?: {
|
|
169
|
+
total?: number;
|
|
170
|
+
};
|
|
171
|
+
};
|
|
172
|
+
}) => void;
|
|
173
|
+
toolResultStore: import("../plugins/store-backend.js").ToolResultStoreFull | undefined;
|
|
174
|
+
tracer: import("@sema-agent/core").TracerHook;
|
|
175
|
+
backend: import("../plugins/store-backend.js").StoreBackend | undefined;
|
|
176
|
+
backgroundAgentStore: import("@sema-agent/core").BackgroundAgentStore | undefined;
|
|
177
|
+
breakerState: import("../plugins/breaker-state-sql.js").TiDBBreakerState | import("../plugins/breaker-state-sql.js").PgBreakerState | undefined;
|
|
178
|
+
instanceId: string;
|
|
179
|
+
mailboxStore: import("@sema-agent/core").MailboxStore | undefined;
|
|
180
|
+
memoryEngine: {
|
|
181
|
+
backend: import("@sema-agent/core").MemoryBackend;
|
|
182
|
+
root: string;
|
|
183
|
+
} | undefined;
|
|
184
|
+
memoryExportBackend: import("@sema-agent/core").MemoryBackend | undefined;
|
|
185
|
+
memoryPosture: import("../memory-posture.js").MemoryPosture;
|
|
186
|
+
memorySyncCursors: import("../plugins/memory-sync-store-pg.js").MemorySyncStore | undefined;
|
|
187
|
+
memorySyncRunner: import("../memory-sync-client.js").MemorySyncRunner | undefined;
|
|
188
|
+
rosterStore: import("@sema-agent/core").RosterStore | undefined;
|
|
189
|
+
sessionCaptureRecordStore: import("@sema-agent/core").SessionCaptureRecordStore | undefined;
|
|
190
|
+
sessionCaptureRecords: import("../plugins/store-backend.js").SessionCaptureRecordSource | undefined;
|
|
191
|
+
sessionStore: import("@sema-agent/core").SessionStore;
|
|
192
|
+
sqlEngineFacts: (() => import("../plugins/sql-driver.js").SqlEngineFacts | null) | undefined;
|
|
193
|
+
storeBackendDegraded: boolean;
|
|
194
|
+
taskAttachmentStore: import("../plugins/task-attachment-store.js").TaskAttachmentStore | undefined;
|
|
195
|
+
taskListLane: import("./task-list-lane.js").TaskListLane;
|
|
196
|
+
usageWindowStore: import("@sema-agent/core").UsageWindowStore | undefined;
|
|
197
|
+
ceilingVerdict: import("./unpriced-ceiling-verdict.js").UnpricedCeilingVerdict;
|
|
198
|
+
configCenter: import("./config-center.js").ConfigCenterRuntime;
|
|
199
|
+
config: import("../config-types.js").ServiceConfig;
|
|
200
|
+
localRoot: string;
|
|
201
|
+
logger: import("../index.js").Logger;
|
|
202
|
+
metrics: import("../index.js").Metrics;
|
|
203
|
+
}>;
|
|
204
|
+
//# sourceMappingURL=stage-10-http-server.d.ts.map
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
import { defaultTaskRegistry } from "@sema-agent/core";
|
|
2
|
+
import { posIntEnv } from "../session-watch.js";
|
|
3
|
+
import { brainSummary } from "../brain.js";
|
|
4
|
+
import { resolveBindHost } from "../config.js";
|
|
5
|
+
import { buildWriteProtectionPosture } from "../write-protection.js";
|
|
6
|
+
import { isPricingConfigured } from "../budget.js";
|
|
7
|
+
import { createHandsRunnerSelector } from "../capabilities/hands-lane.js";
|
|
8
|
+
import { createHttpServer } from "../http/server.js";
|
|
9
|
+
import { exportMemoryScope } from "../memory-export.js";
|
|
10
|
+
import { performMemorySync } from "../memory-sync.js";
|
|
11
|
+
import { backgroundAgentOutput, taskHandleOutput, taskHandleStop } from "../runs.js";
|
|
12
|
+
import { SQL_BLOB_DEFAULT_MAX_BYTES } from "../plugins/blob-backend.js";
|
|
13
|
+
import { createStoreLiveProbe } from "../store-live-probe.js";
|
|
14
|
+
import { counterStoreLabel } from "../plugins/store-backend.js";
|
|
15
|
+
import { startFleetClientFromEnv } from "../fleet-client.js";
|
|
16
|
+
import { createResolveSpec } from "./resolve-spec.js";
|
|
17
|
+
import { startFleetReconciler } from "../fleet/fleet-reconciler.js";
|
|
18
|
+
import { createSideQueryLane } from "./side-query-lane.js";
|
|
19
|
+
import { classifierRouteFor, coreArmsAutoOnIntent } from "../auto-mode-face.js";
|
|
20
|
+
import { createRunnerDepsOnAsk } from "./runner-deps.js";
|
|
21
|
+
import { installShutdownHandlers } from "./shutdown.js";
|
|
22
|
+
import { bindServerLateSeats } from "./late-binds.js";
|
|
23
|
+
import { serviceVersion } from "../service-version.js";
|
|
24
|
+
export async function runStage10(ctx) {
|
|
25
|
+
const { approvalAskAudit, approvalExemptionStore, approvalNonceStore, authorize, backend, backgroundAgentStore, brain, breakerState, centerRuntimeCapsResolver, checkpointStore, config, configCenter, costQuota, deploymentHooks, deviceLane, drainState, durableEnabled, elicitation, fenceSessionOwner, fileHistoryStore, fleetBus, fleetLease, fleetUsage, governanceSeams, handslessRunner, hookAgent, hookLlm, hookWakeBus, imageBakes, imageIndex, instanceId, instrumentDegenerate, leaderEndpoint, localRoot, logger, lspManager, mcpRevocations, memoryBundleFaces, memoryComplianceFaces, memoryConsolidationFaces, memoryEngine, memoryExportBackend, memoryOptOutGrantStore, memoryOriginFaces, memoryPosture, memorySyncCursors, metrics, modelUsageTracker, orgMemoryAdmission, otelExporter, outcomeSink, ownerAware, parkedReviveInheritedGate, parkedReviveTool, perSessionCwd, perTaskImage, planCacheProbe, pricing, principalCaps, promptManifestTracker, purgeSession, question, rateLimiter, reaper, registryJwtVerifier, resumeAnchorStore, retentionLaneStarted, retentionLaneStore, ruleConsent, runStore, runner, runnerDeps, runtimeCapsPeekResolver, scenarioDetails, scenarios, selectEnvTool, sendFileLedger, sendUserFileEmitter, sendUserFileToolSpec, sessionAudit, sessionEnvSelection, sessionMemoryStatusFace, sessionPolicyStore, sessionShellGateRegistry, sessionTitler, sessionWatchRegistry, setSessionCwd, setSessionShellEnv, sharedMemoryStore, sideQueryAccounting, singleUserAutoAcceptBaseline, sqlEngineFacts, sqlWorkflowRunStore, staticWiring, storeBackendDegraded, subRunner, subagentSteerRegistry, taskAttachmentStore, taskLimitCaps, taskTimeoutSec, toolApproval, toolResultStore, usageWindowStore, workflowAgentRegistry, workflowAgentSessionIndex, workflowCompletionInbox, workflowJournalStore, workflowModelAllowlistSnapshot, workflowNotifyGate, workflowNotifyJournal, workflowRecoverOpts, workflowRunStore, workflowsCapable } = ctx;
|
|
26
|
+
const stores = {
|
|
27
|
+
runStore,
|
|
28
|
+
resumeAnchorStore: resumeAnchorStore ? resumeAnchorStore : undefined,
|
|
29
|
+
approvalExemptionStore: approvalExemptionStore ? approvalExemptionStore : undefined,
|
|
30
|
+
approvalNonceStore: approvalNonceStore ? approvalNonceStore : undefined,
|
|
31
|
+
checkpointStore,
|
|
32
|
+
sessionPolicyStore: sessionPolicyStore ? sessionPolicyStore : undefined,
|
|
33
|
+
ruleConsent,
|
|
34
|
+
fileHistoryStore: fileHistoryStore ? fileHistoryStore : undefined,
|
|
35
|
+
toolResultStore,
|
|
36
|
+
taskAttachmentStore: taskAttachmentStore ? taskAttachmentStore : undefined,
|
|
37
|
+
backgroundAgentStore: backgroundAgentStore ? backgroundAgentStore : undefined,
|
|
38
|
+
sessionStorage: ownerAware,
|
|
39
|
+
workflowRunStore: workflowRunStore ? workflowRunStore : undefined,
|
|
40
|
+
workflowAgentSessionIndex: workflowAgentSessionIndex ? workflowAgentSessionIndex : undefined,
|
|
41
|
+
workflowJournalStore: workflowJournalStore ? workflowJournalStore : undefined,
|
|
42
|
+
imageIndex,
|
|
43
|
+
imageBakes,
|
|
44
|
+
outcomeSink: outcomeSink ? outcomeSink : undefined,
|
|
45
|
+
sendFileLedger: sendFileLedger ? sendFileLedger : undefined,
|
|
46
|
+
backend: backend ? backend : undefined,
|
|
47
|
+
};
|
|
48
|
+
let resolveFleetRecovery;
|
|
49
|
+
const fleetRecoveryDone = new Promise((r) => { resolveFleetRecovery = r; });
|
|
50
|
+
const coordinators = {
|
|
51
|
+
elicitation: elicitation ? elicitation : undefined,
|
|
52
|
+
question: question ? question : undefined,
|
|
53
|
+
toolApproval: toolApproval ? toolApproval : undefined,
|
|
54
|
+
approvalAskAudit: approvalAskAudit ? approvalAskAudit : undefined,
|
|
55
|
+
approvalLateSettle: approvalAskAudit ? approvalAskAudit : undefined,
|
|
56
|
+
workflowAgentRegistry: workflowAgentRegistry ? workflowAgentRegistry : undefined,
|
|
57
|
+
subagentSteerRegistry,
|
|
58
|
+
workflowCompletionInbox: workflowCompletionInbox ? workflowCompletionInbox : undefined,
|
|
59
|
+
fleetBus,
|
|
60
|
+
fleetRecoveryDone,
|
|
61
|
+
sessionWatch: sessionWatchRegistry ? sessionWatchRegistry : undefined,
|
|
62
|
+
hookWakeBus,
|
|
63
|
+
sendUserFile: sendUserFileEmitter ? sendUserFileEmitter : undefined,
|
|
64
|
+
leaderEndpoint,
|
|
65
|
+
sessionTitler: sessionTitler ? sessionTitler : undefined,
|
|
66
|
+
};
|
|
67
|
+
const seams = {
|
|
68
|
+
deviceHub: deviceLane?.hub,
|
|
69
|
+
deviceStore: deviceLane?.store,
|
|
70
|
+
sessionAudit,
|
|
71
|
+
routeJudgeBrain: brain,
|
|
72
|
+
purgeSession: purgeSession ? purgeSession : undefined,
|
|
73
|
+
subagentTaskOutput: (handle, access) => backgroundAgentOutput(defaultTaskRegistry, handle, access, backgroundAgentStore),
|
|
74
|
+
taskHandleOutput: (handle, access) => taskHandleOutput(defaultTaskRegistry, handle, access, backgroundAgentStore),
|
|
75
|
+
taskHandleStop: (handle, access) => taskHandleStop(defaultTaskRegistry, handle, access, backgroundAgentStore),
|
|
76
|
+
memoryExport: memoryExportBackend ? (scope) => exportMemoryScope(memoryExportBackend, scope) : undefined,
|
|
77
|
+
memorySync: memoryExportBackend && memorySyncCursors
|
|
78
|
+
? (scope, syncReq) => performMemorySync(memoryExportBackend, memorySyncCursors, scope, syncReq)
|
|
79
|
+
: undefined,
|
|
80
|
+
memoryBundleExport: memoryBundleFaces ? memoryBundleFaces.exportScopes : undefined,
|
|
81
|
+
memoryBundleImport: memoryBundleFaces ? memoryBundleFaces.importBundle : undefined,
|
|
82
|
+
memoryCompliance: memoryComplianceFaces,
|
|
83
|
+
memoryOriginFace: memoryOriginFaces,
|
|
84
|
+
sessionMemoryStatus: sessionMemoryStatusFace,
|
|
85
|
+
memoryConsolidation: memoryConsolidationFaces,
|
|
86
|
+
memoryOptOutGrant: memoryOptOutGrantStore,
|
|
87
|
+
orgMemoryDirectory: orgMemoryAdmission.directory,
|
|
88
|
+
sharedMemoryStore: sharedMemoryStore ? sharedMemoryStore : undefined,
|
|
89
|
+
sessionMirrorRuling: principalCaps
|
|
90
|
+
? async (p) => (await principalCaps.executionRuling(p))?.sessionMirror
|
|
91
|
+
: undefined,
|
|
92
|
+
instrumentDegenerate,
|
|
93
|
+
sideQueryAccounting,
|
|
94
|
+
parkedReviveTool: parkedReviveTool ? parkedReviveTool : undefined,
|
|
95
|
+
parkedReviveInheritedGate: parkedReviveInheritedGate ? parkedReviveInheritedGate : undefined,
|
|
96
|
+
};
|
|
97
|
+
const observability = {
|
|
98
|
+
logger,
|
|
99
|
+
metrics,
|
|
100
|
+
modelUsage: modelUsageTracker,
|
|
101
|
+
promptManifests: promptManifestTracker,
|
|
102
|
+
planCacheProbe,
|
|
103
|
+
};
|
|
104
|
+
const governance = {
|
|
105
|
+
authorize,
|
|
106
|
+
registryJwtVerifier: registryJwtVerifier ? registryJwtVerifier : undefined,
|
|
107
|
+
rateLimiter,
|
|
108
|
+
costQuota,
|
|
109
|
+
fleetLease: fleetLease ? fleetLease : undefined,
|
|
110
|
+
usageWindowStore: usageWindowStore ? usageWindowStore : undefined,
|
|
111
|
+
autoModeFace: {
|
|
112
|
+
seatMounted: runnerDeps.autoMode !== undefined,
|
|
113
|
+
engineArmsOnIntent: coreArmsAutoOnIntent(),
|
|
114
|
+
resolveCaps: runtimeCapsPeekResolver,
|
|
115
|
+
classifierModel: () => {
|
|
116
|
+
const route = classifierRouteFor(runnerDeps);
|
|
117
|
+
if (route.fault !== undefined)
|
|
118
|
+
logger.debug("auto_mode_classifier_route_unresolved", { fault: route.fault });
|
|
119
|
+
return route.id;
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
const storeLiveProbe = backend && backend.kind !== "local" && backend.dbNowMs && config.storeProbeIntervalMs > 0
|
|
124
|
+
? createStoreLiveProbe({ probe: () => backend.dbNowMs(), intervalMs: config.storeProbeIntervalMs, logger })
|
|
125
|
+
: undefined;
|
|
126
|
+
const deployment = {
|
|
127
|
+
sessionStoreLabel: config.sessionBackend === "tidb" && backend ? `durable(${backend.kind})` : config.sessionBackend,
|
|
128
|
+
modelReady: () => configCenter.modelReady(),
|
|
129
|
+
scenarioDetails,
|
|
130
|
+
workflowsCapable,
|
|
131
|
+
workflowModelAllowlist: workflowModelAllowlistSnapshot,
|
|
132
|
+
staticWiring,
|
|
133
|
+
memoryPosture,
|
|
134
|
+
sqlEngineFacts,
|
|
135
|
+
writeProtection: buildWriteProtectionPosture(config),
|
|
136
|
+
instanceId,
|
|
137
|
+
capabilities: {
|
|
138
|
+
version: serviceVersion(),
|
|
139
|
+
scenarios: Object.keys(scenarios),
|
|
140
|
+
get pricingConfigured() {
|
|
141
|
+
return isPricingConfigured(pricing);
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
restartState: () => configCenter.restartState(),
|
|
145
|
+
planeDeferredState: () => configCenter.planeDeferredState(),
|
|
146
|
+
configApplyState: () => configCenter.configApplyState(),
|
|
147
|
+
mcpRevocations,
|
|
148
|
+
mcpRevocationState: () => configCenter.mcpRevocationState(),
|
|
149
|
+
configRefreshNow: () => configCenter.refreshNow(),
|
|
150
|
+
configCenterManagedKeys: () => configCenter.centerManagedKeys(),
|
|
151
|
+
drainState,
|
|
152
|
+
storeDegraded: storeBackendDegraded,
|
|
153
|
+
storeLiveState: storeLiveProbe ? () => storeLiveProbe.state() : undefined,
|
|
154
|
+
};
|
|
155
|
+
const knobs = {
|
|
156
|
+
snapshotBlobSqlCapBytes: backend && backend.kind !== "local" && !config.snapshotBlobStore
|
|
157
|
+
? (config.snapshotBlobSqlMaxBytes ?? (backend.kind === "mysql" ? SQL_BLOB_DEFAULT_MAX_BYTES : undefined))
|
|
158
|
+
: undefined,
|
|
159
|
+
sessionEventsMaxConnections: sessionWatchRegistry ? posIntEnv(process.env.SESSION_EVENTS_MAX_CONNS, 256, 100_000) : undefined,
|
|
160
|
+
};
|
|
161
|
+
const resolveSpec = createResolveSpec({
|
|
162
|
+
config, logger, metrics, localRoot, scenarios, principalCaps, centerRuntimeCapsResolver,
|
|
163
|
+
getCenterPrompts: () => configCenter.getCenterPrompts(),
|
|
164
|
+
getKeyResolver: () => configCenter.getKeyResolver(),
|
|
165
|
+
taskAttachmentStore, perSessionCwd, setSessionCwd, setSessionShellEnv, fenceSessionOwner,
|
|
166
|
+
hookLlm, hookAgent, fleetBus, hookWakeBus, resumeAnchorStore, ownerAware, taskLimitCaps, taskTimeoutSec,
|
|
167
|
+
noteSessionShellGate: sessionShellGateRegistry.note,
|
|
168
|
+
selectEnvTool, sendUserFileToolSpec, memoryEngine, durableEnabled, approvalExemptionStore,
|
|
169
|
+
singleUserAutoAcceptBaseline, checkpointStore, deploymentHooks, imageIndex, perTaskImage,
|
|
170
|
+
sessionEnvSelection,
|
|
171
|
+
lockedKeys: governanceSeams.lockedKeys,
|
|
172
|
+
liveQuestionFace: question,
|
|
173
|
+
approverSeat: createRunnerDepsOnAsk(toolApproval),
|
|
174
|
+
});
|
|
175
|
+
const runnerFor = createHandsRunnerSelector({ full: runner, handsless: handslessRunner });
|
|
176
|
+
const sideQuery = createSideQueryLane({ brain, config, getKeyResolver: () => configCenter.getKeyResolver() });
|
|
177
|
+
const server = createHttpServer({ runner, runnerFor, sideQuery, config, resolveSpec, stores, coordinators, seams, observability, governance, deployment, knobs });
|
|
178
|
+
bindServerLateSeats({ config, logger, server });
|
|
179
|
+
const fleetReconcile = startFleetReconciler({
|
|
180
|
+
bus: fleetBus,
|
|
181
|
+
isLiveOnThisReplica: server.isRunLiveOnThisReplica,
|
|
182
|
+
...(runStore ? { runs: runStore } : {}),
|
|
183
|
+
...(workflowRunStore ? { workflows: workflowRunStore } : {}),
|
|
184
|
+
instanceId,
|
|
185
|
+
logger,
|
|
186
|
+
metrics,
|
|
187
|
+
});
|
|
188
|
+
const bindHost = resolveBindHost(config);
|
|
189
|
+
if (config.bindHostSource === "HOST" && bindHost !== config.bindHost) {
|
|
190
|
+
logger.warn("bind_host_from_HOST_env_overridden", {
|
|
191
|
+
bindHost,
|
|
192
|
+
ignoredHostEnv: config.bindHost,
|
|
193
|
+
note: "HOST was inherited from the shell (zsh commonly sets it to the machine name) and would have bound the write face to a non-loopback address — but this deployment has ALLOW_UNAUTHED_WRITES with no service token, so the bind address was narrowed to loopback instead. Two ways out if you meant to expose it: set BIND_HOST explicitly, or configure a service token.",
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
else if (config.bindHostSource === "HOST") {
|
|
197
|
+
logger.warn("bind_host_from_HOST_env", {
|
|
198
|
+
bindHost,
|
|
199
|
+
note: "the bind address came from the HOST env var (not BIND_HOST). Shells like zsh commonly set HOST to the machine name — if you did not set it yourself, this may be an inherited shell variable silently configuring the bind face. Set BIND_HOST explicitly to silence this warning.",
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
let onListenError;
|
|
203
|
+
try {
|
|
204
|
+
await new Promise((resolve, reject) => {
|
|
205
|
+
onListenError = reject;
|
|
206
|
+
server.once("error", onListenError);
|
|
207
|
+
bindHost ? server.listen(config.port, bindHost, resolve) : server.listen(config.port, resolve);
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
catch (e) {
|
|
211
|
+
logger.error("listen_failed", {
|
|
212
|
+
port: config.port,
|
|
213
|
+
bindHost: bindHost ?? "0.0.0.0/::(all interfaces)",
|
|
214
|
+
...(config.bindHostSource ? { bindHostSource: config.bindHostSource } : {}),
|
|
215
|
+
...(config.bindHostSource === "HOST" ? { note: "bind failed for a host inherited from the HOST env var — set BIND_HOST explicitly (e.g. BIND_HOST=127.0.0.1)." } : {}),
|
|
216
|
+
error: e instanceof Error ? e.message : String(e),
|
|
217
|
+
});
|
|
218
|
+
throw e;
|
|
219
|
+
}
|
|
220
|
+
finally {
|
|
221
|
+
if (onListenError)
|
|
222
|
+
server.removeListener("error", onListenError);
|
|
223
|
+
}
|
|
224
|
+
server.on("error", (e) => {
|
|
225
|
+
logger.error("server_error", {
|
|
226
|
+
error: e.message,
|
|
227
|
+
...("code" in e ? { code: String(e.code) } : {}),
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
const fleetClient = startFleetClientFromEnv(config, {
|
|
231
|
+
instanceId,
|
|
232
|
+
version: serviceVersion(),
|
|
233
|
+
isDraining: () => drainState.draining,
|
|
234
|
+
...(fleetUsage ? { usage: fleetUsage } : {}),
|
|
235
|
+
logger: { info: (m, d) => logger.info(m, d ?? {}), warn: (m, d) => logger.warn(m, d ?? {}) },
|
|
236
|
+
});
|
|
237
|
+
if (fleetClient)
|
|
238
|
+
logger.info("fleet_client_started", { worker: config.configCenter?.worker, address: process.env.FLEET_ADVERTISE_ADDRESS });
|
|
239
|
+
logger.info("listening", {
|
|
240
|
+
port: config.port,
|
|
241
|
+
bindHost: bindHost ?? "0.0.0.0/::(all interfaces)",
|
|
242
|
+
...(bindHost === "127.0.0.1" && !config.bindHost
|
|
243
|
+
? { bindHostNote: "auto-narrowed to loopback: write face is unauthenticated (ALLOW_UNAUTHED_WRITES with no service token). Set BIND_HOST explicitly to override." }
|
|
244
|
+
: {}),
|
|
245
|
+
model: config.model.id,
|
|
246
|
+
brain: brainSummary(config),
|
|
247
|
+
breakerState: config.resilience.circuitBreaker ? (breakerState ? `shared(${backend.kind})` : "in-process") : "off",
|
|
248
|
+
session: config.sessionBackend === "tidb" && backend ? `durable(${backend.kind})` : config.sessionBackend,
|
|
249
|
+
memory: memoryEngine ? `engine(${memoryEngine.root})` : "off",
|
|
250
|
+
instanceId,
|
|
251
|
+
rateLimitPerMin: config.rateLimitPerMin,
|
|
252
|
+
rateLimit: config.rateLimitPerMin > 0 ? counterStoreLabel(backend?.rateLimiter, backend?.kind) : "off",
|
|
253
|
+
maxPrincipalCostUsd: config.maxPrincipalCostUsd || null,
|
|
254
|
+
costQuota: config.maxPrincipalCostUsd > 0 ? counterStoreLabel(backend?.costQuota, backend?.kind) : "off",
|
|
255
|
+
toolResultStore: toolResultStore ? (backend?.kind === "local" ? "file(local)" : "shared(sql)") : "in-process",
|
|
256
|
+
otel: config.otel ? config.otel.endpoint : null,
|
|
257
|
+
perModelKeys: Object.keys(config.modelApiKeyEnv).length,
|
|
258
|
+
sealedModelKeys: Object.values(config.modelApiKeys).filter((v) => typeof v === "string").length,
|
|
259
|
+
sealedPoisonedModels: Object.values(config.modelApiKeys).filter((v) => typeof v !== "string").length,
|
|
260
|
+
workflowRunStore: config.selfOrchestrationEnabled
|
|
261
|
+
? config.workflowRunStoreBackend === "memory"
|
|
262
|
+
? "in-process"
|
|
263
|
+
: sqlWorkflowRunStore
|
|
264
|
+
? `db(${backend.kind})`
|
|
265
|
+
: "file"
|
|
266
|
+
: "off",
|
|
267
|
+
});
|
|
268
|
+
if (workflowNotifyGate) {
|
|
269
|
+
void workflowNotifyGate
|
|
270
|
+
.recover(workflowRecoverOpts)
|
|
271
|
+
.then((tally) => logger.info("workflow_notify_recovered", tally))
|
|
272
|
+
.catch((err) => logger.warn("workflow_notify_recover_failed", { err: String(err) }))
|
|
273
|
+
.finally(() => resolveFleetRecovery());
|
|
274
|
+
}
|
|
275
|
+
else {
|
|
276
|
+
resolveFleetRecovery();
|
|
277
|
+
}
|
|
278
|
+
void installShutdownHandlers({
|
|
279
|
+
config, logger, server, reaper, fleetReconcile, otelExporter, breakerState, costQuota, rateLimiter,
|
|
280
|
+
version: serviceVersion(),
|
|
281
|
+
runner, subRunner, lspManager, workflowNotifyJournal, fleetClient, backend, drainState,
|
|
282
|
+
storeLiveProbe, configCenter,
|
|
283
|
+
deviceHub: deviceLane?.hub,
|
|
284
|
+
retentionLane: retentionLaneStarted,
|
|
285
|
+
releaseRetentionLease: retentionLaneStore !== undefined ? () => retentionLaneStore.release(instanceId) : undefined,
|
|
286
|
+
});
|
|
287
|
+
return { ...ctx };
|
|
288
|
+
}
|
|
289
|
+
//# sourceMappingURL=stage-10-http-server.js.map
|
|
@@ -52,6 +52,15 @@ export interface CrossInvariant {
|
|
|
52
52
|
check(input: CrossInvariantInput): string | undefined;
|
|
53
53
|
}
|
|
54
54
|
export declare const CONFIG_CROSS_INVARIANTS: readonly CrossInvariant[];
|
|
55
|
+
/**
|
|
56
|
+
* 按 id 取**一条**(S-157②:boot 面的单源化出口)。
|
|
57
|
+
*
|
|
58
|
+
* 为什么不是在 boot 期跑 `checkCrossInvariants` 全表:全表里有若干条的 boot 拒启点在 `config.ts` 的装配尾
|
|
59
|
+
* (各自有自己的锚),在这里再跑一遍全表等于给 boot 加上今天不存在的拒启臂 —— 那是行为改动,不是单源化。
|
|
60
|
+
* 本出口只做一件事:让 boot 与 stage 两面调**同一只** `check`(连拒因文本也来自它),消灭手抄的第二份判据。
|
|
61
|
+
* 闭集越界不可达(`CrossInvariantId` 是编译期闭集),真撞上就响亮抛 —— 不返回 undefined 让调用方静默跳过。
|
|
62
|
+
*/
|
|
63
|
+
export declare function crossInvariant(id: CrossInvariantId): CrossInvariant;
|
|
55
64
|
export type CrossInvariantVerdict = {
|
|
56
65
|
ok: true;
|
|
57
66
|
} | {
|
|
@@ -8,7 +8,7 @@ export const CONFIG_CROSS_INVARIANTS = [
|
|
|
8
8
|
id: "run-stale-heartbeat",
|
|
9
9
|
keys: ["runStaleSec"],
|
|
10
10
|
restartReason: "run-stale-heartbeat",
|
|
11
|
-
bootAnchor: { file: "src/
|
|
11
|
+
bootAnchor: { file: "src/boot/stage-01-config.ts", marker: "CROSS-INVARIANT:run-stale-heartbeat" },
|
|
12
12
|
check: ({ next }) => next.runStaleSec * 1000 <= LIVENESS_HEARTBEAT_MS
|
|
13
13
|
? `runStaleSec (${next.runStaleSec}s) must exceed the ${LIVENESS_HEARTBEAT_MS / 1000}s liveness heartbeat — the reaper would race a run that is still heartbeating normally and reap live work`
|
|
14
14
|
: undefined,
|
|
@@ -130,6 +130,12 @@ export const CONFIG_CROSS_INVARIANTS = [
|
|
|
130
130
|
: undefined,
|
|
131
131
|
},
|
|
132
132
|
];
|
|
133
|
+
export function crossInvariant(id) {
|
|
134
|
+
const inv = CONFIG_CROSS_INVARIANTS.find((i) => i.id === id);
|
|
135
|
+
if (inv === undefined)
|
|
136
|
+
throw new Error(`unknown cross-invariant: ${id}`);
|
|
137
|
+
return inv;
|
|
138
|
+
}
|
|
133
139
|
export function checkCrossInvariants(input) {
|
|
134
140
|
for (const inv of CONFIG_CROSS_INVARIANTS) {
|
|
135
141
|
const reason = inv.check(input);
|
package/dist/config-types.d.ts
CHANGED
|
@@ -1167,7 +1167,7 @@ export interface ServiceConfigFlat {
|
|
|
1167
1167
|
infraCostRates: InfraCostRates;
|
|
1168
1168
|
/** v2 leader endpoint ([ref]): enable POST/GET /v1/leader. Requires an ISOLATED remote-exec backend —
|
|
1169
1169
|
* REMOTE_EXEC=e2b, OR REMOTE_EXEC=k8s (Kata pod-sandbox) WITH an S3/MinIO config for the workspace-durable
|
|
1170
|
-
* snapshot/merge
|
|
1170
|
+
* snapshot/merge(装配点 `boot/leader.ts#assertLeaderDurableStore`) — + (deploy) git on the host + a durable remote with creds. Orthogonal to the
|
|
1171
1171
|
* D-G direct door (auth axis) — a worker can be direct-mode + kata + leader at once. Default OFF. `LEADER_ENABLED=true`. */
|
|
1172
1172
|
leaderEnabled: boolean;
|
|
1173
1173
|
/** [ref] A6 (correctness-first knob): `LEADER_FANOUT_ENABLED=false` pins the leader router to the
|
package/dist/http/dispatch.js
CHANGED
|
@@ -2,9 +2,10 @@ import { createHash } from "node:crypto";
|
|
|
2
2
|
import { setSsoPrincipal, ssoVerifiedPrincipal, setSsoScope, isDestructiveSessionWrite, PRINCIPAL_TOKEN_HEADER, APPROVAL_MAC_HEADER, APPROVAL_MAC_KID_HEADER } from "../security.js";
|
|
3
3
|
import { publicStoreProbeError } from "../store-live-probe.js";
|
|
4
4
|
import { looksLikeJwt } from "@sema-agent/settings-schema/api/auth-bridge";
|
|
5
|
-
import {
|
|
5
|
+
import { ROUTE_METHOD_ORDER } from "./route-ctx.js";
|
|
6
|
+
import { PRE_CREDENTIAL_ROUTES, POST_CREDENTIAL_ROUTES, routeLabel, isBillableSubmitPath, isCredentialGatedRewrite, isMethodDispatchedSubmitPath, lookupRoute } from "./route-table.js";
|
|
6
7
|
import { sendJson, sendError, isSseResponse } from "./send.js";
|
|
7
|
-
import { authorized, systemFor } from "./principal-gate.js";
|
|
8
|
+
import { authorized, systemFor, gatedPrincipal, sendPrincipalRefusal } from "./principal-gate.js";
|
|
8
9
|
const PROCESS_STARTED_AT_MS = Date.now() - Math.round(process.uptime() * 1000);
|
|
9
10
|
export function hasServiceAuth(config) {
|
|
10
11
|
return Boolean(config.authToken) || Object.keys(config.authTokens ?? {}).length > 0;
|
|
@@ -42,19 +43,29 @@ export function createDispatch(ctx) {
|
|
|
42
43
|
};
|
|
43
44
|
deps.drainState.lastAttachEndedAt = () => lastAttachEndedAt;
|
|
44
45
|
}
|
|
45
|
-
async function dispatchSegment(rows, req, res, url, ctx) {
|
|
46
|
+
async function dispatchSegment(rows, req, res, url, search, method, allow, ctx) {
|
|
46
47
|
for (const row of rows) {
|
|
47
48
|
if (row.enabled !== undefined && !row.enabled(deps))
|
|
48
49
|
continue;
|
|
49
|
-
|
|
50
|
-
|
|
50
|
+
const found = lookupRoute(row.decls, url, method);
|
|
51
|
+
for (const m of found.allow)
|
|
52
|
+
if (!allow.includes(m))
|
|
53
|
+
allow.push(m);
|
|
54
|
+
if (found.decl === null)
|
|
55
|
+
continue;
|
|
56
|
+
await row.handler(req, res, { decl: found.decl, params: found.params, search }, ctx);
|
|
57
|
+
return true;
|
|
51
58
|
}
|
|
52
59
|
return false;
|
|
53
60
|
}
|
|
54
61
|
async function handle(req, res) {
|
|
55
62
|
const startedAt = Date.now();
|
|
56
63
|
const method = req.method ?? "GET";
|
|
57
|
-
const
|
|
64
|
+
const rawUrl = req.url ?? "/";
|
|
65
|
+
const qMark = rawUrl.indexOf("?");
|
|
66
|
+
const url = qMark === -1 ? rawUrl : rawUrl.slice(0, qMark);
|
|
67
|
+
const search = qMark === -1 ? "" : rawUrl.slice(qMark);
|
|
68
|
+
const allow = { pre: [], post: [] };
|
|
58
69
|
noteActivity(url);
|
|
59
70
|
const admitted = method !== "OPTIONS" && url !== "/health" && !url.startsWith("/metrics");
|
|
60
71
|
if (admitted)
|
|
@@ -180,7 +191,7 @@ export function createDispatch(ctx) {
|
|
|
180
191
|
}
|
|
181
192
|
}
|
|
182
193
|
}
|
|
183
|
-
if (await dispatchSegment(PRE_CREDENTIAL_ROUTES, req, res, url, ctx))
|
|
194
|
+
if (await dispatchSegment(PRE_CREDENTIAL_ROUTES, req, res, url, search, method, allow.pre, ctx))
|
|
184
195
|
return;
|
|
185
196
|
let source = null;
|
|
186
197
|
const anyServiceAuth = hasServiceAuth(deps.config);
|
|
@@ -221,8 +232,17 @@ export function createDispatch(ctx) {
|
|
|
221
232
|
sendError(res, 503, "auth.service_token_required", "this worker requires a service auth token (set SERVICE_AUTH_TOKEN) before accepting destructive session writes (policy / sync-import / fork / delete)");
|
|
222
233
|
return;
|
|
223
234
|
}
|
|
224
|
-
if (await dispatchSegment(POST_CREDENTIAL_ROUTES, req, res, url, ctx))
|
|
235
|
+
if (await dispatchSegment(POST_CREDENTIAL_ROUTES, req, res, url, search, method, allow.post, ctx))
|
|
225
236
|
return;
|
|
237
|
+
if (allow.pre.length > 0 || allow.post.length > 0) {
|
|
238
|
+
if (allow.post.length > 0 && deps.config.requirePrincipal && gatedPrincipal(req, deps.config) === undefined) {
|
|
239
|
+
sendPrincipalRefusal(res, req, deps.config);
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
res.setHeader("allow", ROUTE_METHOD_ORDER.filter((m) => allow.pre.includes(m) || allow.post.includes(m)).join(", "));
|
|
243
|
+
sendError(res, 405, "method_not_allowed", "this path exists but not for this HTTP method — the `Allow` response header lists the methods it does answer");
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
226
246
|
sendError(res, 404, "not_found.route", "not found");
|
|
227
247
|
}
|
|
228
248
|
return { handle };
|