@sema-agent/server 7.79.1 → 7.79.3

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.
Files changed (41) hide show
  1. package/dist/boot/late-binds.d.ts +35 -0
  2. package/dist/boot/late-binds.js +20 -0
  3. package/dist/boot/stage-01-config.d.ts +7 -0
  4. package/dist/boot/stage-01-config.js +60 -0
  5. package/dist/boot/stage-02-registry-pull.d.ts +10 -0
  6. package/dist/boot/stage-02-registry-pull.js +11 -0
  7. package/dist/boot/stage-03-store-backend.d.ts +32 -0
  8. package/dist/boot/stage-03-store-backend.js +11 -0
  9. package/dist/boot/stage-04-stores.d.ts +69 -0
  10. package/dist/boot/stage-04-stores.js +49 -0
  11. package/dist/boot/stage-05-execution-env.d.ts +82 -0
  12. package/dist/boot/stage-05-execution-env.js +20 -0
  13. package/dist/boot/stage-06-runners.d.ts +143 -0
  14. package/dist/boot/stage-06-runners.js +207 -0
  15. package/dist/boot/stage-07-capability-layer.d.ts +157 -0
  16. package/dist/boot/stage-07-capability-layer.js +162 -0
  17. package/dist/boot/stage-08-reapers.d.ts +172 -0
  18. package/dist/boot/stage-08-reapers.js +78 -0
  19. package/dist/boot/stage-09-leader.d.ts +204 -0
  20. package/dist/boot/stage-09-leader.js +47 -0
  21. package/dist/boot/stage-10-http-server.d.ts +204 -0
  22. package/dist/boot/stage-10-http-server.js +289 -0
  23. package/dist/config-invariants.d.ts +9 -0
  24. package/dist/config-invariants.js +7 -1
  25. package/dist/config-types.d.ts +1 -1
  26. package/dist/http/dispatch.d.ts +9 -73
  27. package/dist/http/dispatch.js +12 -281
  28. package/dist/http/route-table.d.ts +113 -0
  29. package/dist/http/route-table.js +235 -0
  30. package/dist/http/routes/admin-memory-optout.d.ts +1 -1
  31. package/dist/http/routes/memory-compliance.d.ts +1 -1
  32. package/dist/http/routes/memory-origin.d.ts +1 -1
  33. package/dist/http/routes/rules.js +4 -4
  34. package/dist/http/server.d.ts +2 -1
  35. package/dist/http/server.js +2 -1
  36. package/dist/main.js +20 -870
  37. package/dist/service-version.d.ts +5 -0
  38. package/dist/service-version.js +12 -0
  39. package/dist/trace/redact.d.ts +16 -6
  40. package/dist/trace/redact.js +568 -246
  41. package/package.json +1 -1
package/dist/main.js CHANGED
@@ -1,875 +1,25 @@
1
- import { readFileSync } from "node:fs";
2
- import { DEFAULT_MODEL_REF } from "./model-select.js";
3
- import { homedir } from "node:os";
4
- import { join } from "node:path";
5
- import { Runner, terminalProjection, createPermissionRuleStoreProvider, InMemoryToolResultStore, TtlSessionStore, uuidv7, defaultTaskRegistry, createAllowDenyPolicy, workflowsCapability, probeSearchBackend, describeStaticWiring, DEFAULT_SUBAGENT_TOOL_NAME } from "@sema-agent/core";
6
- import { createSessionTitler } from "./session-titler.js";
7
- import { posIntEnv } from "./session-watch.js";
8
- import { selectEnvironmentTool } from "./capabilities/select-environment-tool.js";
9
- import { subagentSendUserFileExtraTools } from "./capabilities/send-user-file-tool.js";
10
- import { brainSummary } from "./brain.js";
11
- import { loadConfig, logConfigDiagnostics, resolveBindHost, splitLocalRoots, parseCapEnv, parseNumOrFailNonNegative } from "./config.js";
12
- import { createUnpricedCeilingVerdict } from "./boot/unpriced-ceiling-verdict.js";
13
- import { buildWriteProtectionPosture } from "./write-protection.js";
14
- import { cardRuleScopeRoot } from "./task-cwd.js";
15
- import { isPricingConfigured } from "./budget.js";
16
- import { drainNumEnvWarnings } from "./plugins/remote-shell.js";
17
- import { ensureChildSessionDurableWithPromotion } from "./plugins/session-store.js";
18
- import { ForkRoutingSessionStore } from "./plugins/fork-routing-session-store.js";
19
- import { webSearchConfigFromEnv, createWebSearchBackend, setWebSearchBadPayloadObserver, shouldProbeWebSearchOnBoot } from "./plugins/web-search.js";
20
- import { createAuthorizer, encodeCheckpointScope } from "./security.js";
21
- import { assertGateIntentServiceable, buildForceDurableGateInertNotice, hasOperatorGateIntent } from "./approval.js";
22
- import { loadSkills } from "./capabilities/skills.js";
23
- import { createRepoClient } from "./capabilities/repo-tools.js";
24
- import { buildScenarios, builtinScenarioDetails } from "./capabilities/scenarios.js";
25
- import { createHandsRunnerSelector, withoutExecutionEnv } from "./capabilities/hands-lane.js";
26
1
  import { createLogger } from "./observability/logger.js";
27
- import { createToolTracer, createPermissionDeniedMeter } from "./observability/tool-trace.js";
28
- import { createRegistryJwtVerifier } from "./auth-bridge.js";
29
- import { createMetrics } from "./observability/metrics.js";
30
- import { installFailOpenRecorder } from "./observability/fail-open.js";
31
- import { installFileHistoryFailureRecorder } from "./file-history-disclosure.js";
32
- import { installSecretEnvScrubRecorder } from "./observability/secret-env-scrub.js";
33
- import { setRunTerminalObserver } from "./observability/run-terminal-log.js";
34
- import { setRedactionObserver, redactSecrets } from "./trace/redact.js";
35
- import { RateLimiter } from "./observability/rate-limit.js";
36
- import { createHttpServer, explicitOperatorOk, hasServiceAuth } from "./http/server.js";
37
- import { exportMemoryScope } from "./memory-export.js";
38
- import { workflowModelAllowlistFor, selfOrchestrationDenial } from "./task-workflow.js";
39
- import { centerEntitlementSourceWired } from "./runtime-caps-resolver.js";
40
- import { createMemoryBundleFaces } from "./memory-bundle-engine.js";
41
- import { backendOwnsControlPlane, createMemoryComplianceFaces, createMemoryOriginFaces, createSessionMemoryStatusFace } from "./memory-operator-faces.js";
42
- import { performMemorySync } from "./memory-sync.js";
43
- import { startOtlpExporter } from "./observability/otel-exporter.js";
44
- import { HEARTBEAT_MS, backgroundAgentOutput, taskHandleOutput, taskHandleStop } from "./runs.js";
45
- import { SQL_BLOB_DEFAULT_MAX_BYTES } from "./plugins/blob-backend.js";
46
- import { createStoreLiveProbe } from "./store-live-probe.js";
47
- import { counterStoreLabel } from "./plugins/store-backend.js";
48
- import { composeHooks } from "./hooks/hook-runner.js";
49
- import { createHookLlm } from "./hooks/hook-llm.js";
50
- import { startFleetClientFromEnv } from "./fleet-client.js";
51
- import { reclaimOrphansAtBoot } from "./boot-reclaim.js";
52
- import { createConfigCenterRuntime } from "./boot/config-center.js";
53
- import { createResolveSpec } from "./boot/resolve-spec.js";
54
- import { createParkedReviveInheritedGate } from "./boot/parked-revive-gate.js";
55
- import { startReapers } from "./boot/reapers.js";
56
- import { assertRetentionLaneWirable, startRetentionLane, RETENTION_LEASE_TTL_FACTOR } from "./boot/retention-lane.js";
57
- import { assertConsolidationDriverWirable, buildConsolidationValveAudit, createMemoryConsolidationFaces, resolveConsolidationDriverSeat } from "./boot/memory-consolidation.js";
58
- import { startFleetReconciler } from "./fleet/fleet-reconciler.js";
59
- import { openStores } from "./boot/stores.js";
60
- import { assertDeviceLaneWired, createDeviceLane } from "./boot/device-lane.js";
61
- import { runAdoptionBootScan } from "./boot/adoption.js";
62
- import { auditDormantPermissionRules } from "./boot/permission-rules-audit.js";
63
- import { createBudgetAndTracing } from "./boot/budget-tracing.js";
64
- import { createLimitSync } from "./boot/limit-sync.js";
65
- import { createSideQueryLane, createPerModelAuthSeat } from "./boot/side-query-lane.js";
66
- import { createWebFetchSummarizeLane } from "./boot/webfetch-summarize-lane.js";
67
- import { createRuleConsentLane } from "./rules-consent.js";
68
- import { createExecutionEnv } from "./boot/execution-env.js";
69
- import { createWorkflowOrchestration } from "./boot/workflow-orchestration.js";
70
- import { createLiveCoordinators } from "./boot/coordinators.js";
71
- import { createRuntimeCaps } from "./boot/runtime-caps.js";
72
- import { classifierRouteFor, coreArmsAutoOnIntent } from "./auto-mode-face.js";
73
- import { createSessionShellGateRegistry } from "./boot/session-shell-gate-registry.js";
74
- import { createRunnerDeps, createRunnerDepsOnAsk, createSharedRunnerDeps } from "./boot/runner-deps.js";
75
- import { createOrgMemoryAdmissionWiring } from "./boot/org-memory.js";
76
- import { createGovernanceSeams } from "./boot/governance-seams.js";
77
- import { createSharedMemoryScopeAuthorizer } from "./shared-memory-scope-authorizer.js";
78
- import { createSessionFaces } from "./boot/session-faces.js";
79
- import { createLeaderFace } from "./boot/leader.js";
80
- import { assertStaticWiringConsistent } from "./http/routes/diagnostics.js";
81
- import { installShutdownHandlers } from "./boot/shutdown.js";
82
- function serviceVersion() {
83
- try {
84
- const pkg = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
85
- return pkg.version ?? "unknown";
86
- }
87
- catch {
88
- return "unknown";
89
- }
90
- }
2
+ import { runStage01 } from "./boot/stage-01-config.js";
3
+ import { runStage02 } from "./boot/stage-02-registry-pull.js";
4
+ import { runStage03 } from "./boot/stage-03-store-backend.js";
5
+ import { runStage04 } from "./boot/stage-04-stores.js";
6
+ import { runStage05 } from "./boot/stage-05-execution-env.js";
7
+ import { runStage06 } from "./boot/stage-06-runners.js";
8
+ import { runStage07 } from "./boot/stage-07-capability-layer.js";
9
+ import { runStage08 } from "./boot/stage-08-reapers.js";
10
+ import { runStage09 } from "./boot/stage-09-leader.js";
11
+ import { runStage10 } from "./boot/stage-10-http-server.js";
91
12
  async function main() {
92
- const config = loadConfig();
93
- if (config.runStaleSec * 1000 <= HEARTBEAT_MS) {
94
- throw new Error(`REAP_RUN_STALE_SEC (${config.runStaleSec}s) must exceed the ${HEARTBEAT_MS / 1000}s liveness heartbeat`);
95
- }
96
- const logger = createLogger(config.logLevel);
97
- const metrics = createMetrics();
98
- installFailOpenRecorder({ logger, metrics });
99
- installSecretEnvScrubRecorder({ logger, metrics });
100
- installFileHistoryFailureRecorder({ logger, metrics });
101
- logConfigDiagnostics(logger);
102
- for (const w of drainNumEnvWarnings())
103
- logger.warn("config_env_invalid_using_default", { env: w.env, raw: w.raw });
104
- if ((config.roles?.verifier ?? "default") === "default") {
105
- logger.warn("verify_decorrelation_unavailable", {
106
- hint: "verifier role = default (= implementer) — adversarial verification grades its own work; set MODEL_VERIFIER=<catalog model id> to a heterogeneous model",
107
- ...(process.env.MODEL_VERIFIER ? { rejected: process.env.MODEL_VERIFIER, reason: "not in catalog" } : {}),
108
- });
109
- }
110
- setRedactionObserver((pattern, n, meta) => metrics.inc("redactions_applied_total", { pattern, arm: meta.arm }, n));
111
- setWebSearchBadPayloadObserver((provider) => {
112
- metrics.inc("web_search_bad_payload_total", { provider });
113
- logger.warn("web_search_non_array_payload", { provider });
114
- });
115
- setRunTerminalObserver((level, fields) => {
116
- if (level === "error")
117
- logger.error("run_failed", fields);
118
- else
119
- logger.info("run_failed", fields);
120
- });
121
- const localRoot = config.configLocalDir ?? process.env.AGENT_DATA_DIR ?? join(homedir(), ".ai-agent");
122
- const rootsSplit = splitLocalRoots({
123
- localDataRoot: config.localDataRoot,
124
- configLocalDir: config.configLocalDir,
125
- agentDataDir: process.env.AGENT_DATA_DIR,
126
- home: homedir(),
127
- });
128
- if (rootsSplit) {
129
- logger.warn("local_roots_split", {
130
- ...rootsSplit,
131
- note: "LOCAL_DATA_ROOT moved the local backend's DATA root, but config.d / remote-exec.json are still read from the config root (LOCAL_DATA_ROOT is not consulted there). If you meant to move both, set CONFIG_LOCAL_DIR to the same directory.",
132
- });
133
- }
134
- const configCenter = await createConfigCenterRuntime({ config, logger, metrics, localRoot });
135
- await configCenter.applyLocalRemoteExec();
136
- const ceilingVerdict = createUnpricedCeilingVerdict({ config, logger });
137
- ceilingVerdict.judge();
138
- const { backend, storeBackendDegraded, memoryEngine, memorySyncCursors, rosterStore, backgroundAgentStore, taskAttachmentStore, mailboxStore, memoryExportBackend, memorySyncRunner, sessionStore, breakerState, usageWindowStore, memoryPosture, taskListLane, sqlEngineFacts, } = await openStores({ config, logger, metrics, localRoot });
139
- const instanceId = uuidv7();
140
- const sessionCaptureRecords = backend?.sessionCaptureRecords();
141
- const sessionCaptureRecordStore = sessionCaptureRecords?.();
142
- const memoryBundleFaces = memoryEngine ? createMemoryBundleFaces(memoryEngine, { ...(sessionCaptureRecordStore !== undefined ? { captureRecordStore: sessionCaptureRecordStore } : {}) }) : undefined;
143
- const memoryComplianceFaces = memoryEngine
144
- ? createMemoryComplianceFaces(memoryEngine, {
145
- onIncident: (err) => logger.warn("memory_compliance_incident", { code: err.code ?? null, detail: err.message }),
146
- ...(sessionCaptureRecordStore !== undefined ? { captureRecordStore: sessionCaptureRecordStore } : {}),
147
- })
148
- : undefined;
149
- const memoryOriginFaces = memoryEngine
150
- ? createMemoryOriginFaces(memoryEngine, {
151
- onIncident: (err) => logger.warn("memory_origin_incident", { code: err.code ?? null, detail: err.message }),
152
- ...(sessionCaptureRecordStore !== undefined ? { captureRecordStore: sessionCaptureRecordStore } : {}),
153
- })
154
- : undefined;
155
- const sessionMemoryStatusFace = memoryEngine
156
- ? createSessionMemoryStatusFace(memoryEngine, { ...(sessionCaptureRecordStore !== undefined ? { captureRecordStore: sessionCaptureRecordStore } : {}) })
157
- : undefined;
158
- const adoptionBoot = await runAdoptionBootScan({ backend, logger });
159
- if (adoptionBoot.scanned > 0 || adoptionBoot.error !== undefined) {
160
- logger.info("adoption_boot_scan", { ...adoptionBoot });
161
- }
162
- const { brain, pricing, counterDegradeHook, costQuota, modelUsageTracker, promptManifestTracker, fleetUsage, fleetLease, tracer, sideQueryAccounting, toolResultStore, sessionPolicyStore, fileHistoryStore, } = createBudgetAndTracing({ config, logger, metrics, backend, breakerState });
163
- const permissionRuleStores = config.permissionRulesEnabled && backend ? backend.permissionRule() : undefined;
164
- const permissionRuleProvider = permissionRuleStores
165
- ? createPermissionRuleStoreProvider({ durable: permissionRuleStores.durable })
166
- : undefined;
167
- const ruleConsent = permissionRuleStores && permissionRuleProvider
168
- ? createRuleConsentLane({ ...permissionRuleStores, provider: permissionRuleProvider })
169
- : undefined;
170
- if (config.permissionRulesEnabled && permissionRuleStores === undefined) {
171
- logger.info("permission_rules_lane_unavailable", {
172
- knob: "PERMISSION_RULES_ENABLED",
173
- reason: backend === undefined ? "no_backend" : "backend_has_no_rule_store",
174
- backendKind: backend?.kind ?? null,
175
- note: "PERMISSION_RULES_ENABLED is on but no permission-rule store is wired — /v1/rules/* answer 501, approval cards carry no rule suggestions, and respond's persistRule is refused with rule_lane_unavailable",
176
- });
177
- }
178
- await auditDormantPermissionRules({ stores: permissionRuleStores, logger, explicit: config.permissionRulesEnabledExplicit });
179
- const deviceLane = config.remoteExec?.provider === "device" ? createDeviceLane({ config, logger, metrics, backend, replicaId: instanceId, rateGate: () => rateLimiter }) : undefined;
180
- const { perTaskImage, sessionEnvSelection, perSessionCwd, setSessionCwd, setSessionShellEnv, fenceSessionOwner, dropSessionScoped, executionEnvFactory, worktreeReap, sendUserFileTaskEnvs, lspManager, } = createExecutionEnv({ config, logger, metrics, taskAttachmentStore, ...(deviceLane ? { deviceLane } : {}) });
181
- assertDeviceLaneWired(config.remoteExec?.provider === "device", deviceLane, executionEnvFactory !== undefined);
182
- const toolTracer = config.toolTrace ? createToolTracer(logger) : undefined;
183
- if (toolTracer)
184
- logger.info("tool_trace_enabled", {});
185
- const deploymentHooks = {
186
- ...(toolTracer ? composeHooks(createPermissionDeniedMeter(metrics), toolTracer) : createPermissionDeniedMeter(metrics)),
187
- ...(config.hooksTimeoutMs !== undefined ? { timeoutMs: config.hooksTimeoutMs } : {}),
188
- };
189
- const { sqlWorkflowRunStore, workflowNotifyJournal, workflowCompletionInbox, deliverWorkflowCompletion, workflowNotifyGate, fleetBus, workflowRunStore, workflowJournalStore, outcomeSink, workflowRecoverOpts, workflowAgentRegistry, subagentSteerRegistry, workflowAgentSessionIndex, } = createWorkflowOrchestration({ config, logger, metrics, localRoot, backend, getRunStore: () => runStore });
190
- let parkedAskRedeem;
191
- const { elicitation, question, toolApproval, durableEnabled, streamApprovalGate, approvalAskAudit, sendUserFileEmitter, sendFileLedger, sendUserFileToolSpec } = createLiveCoordinators({
192
- config, logger, backend, sendUserFileTaskEnvs, ruleConsent,
193
- getParkedRedeem: () => parkedAskRedeem,
194
- ruleScopeRootFor: (sessionId) => cardRuleScopeRoot(sessionId !== undefined ? perSessionCwd.get(sessionId) : undefined, config),
195
- });
196
- const memoryOptOutGrantStore = backend?.memoryOptOutGrant();
197
- const { principalCaps, centerRuntimeCapsResolver, runtimeCapsResolver, runtimeCapsPeekResolver } = createRuntimeCaps({ config, logger, memoryOptOutGrant: memoryOptOutGrantStore });
198
- const orgMemoryAdmission = createOrgMemoryAdmissionWiring({ config, logger, metrics });
199
- const sharedMemoryStore = orgMemoryAdmission.directory !== undefined
200
- ? backend?.sharedMemoryStore?.(createSharedMemoryScopeAuthorizer({
201
- directory: orgMemoryAdmission.directory,
202
- deploymentScopes: config.requirePrincipal === true ? () => [] : orgMemoryAdmission.deploymentMemoryScopesLive,
203
- }))
204
- : undefined;
205
- if (sharedMemoryStore)
206
- logger.info("shared_memory_stores_enabled", { backend: backend?.kind });
207
- const runnerOffloadStore = toolResultStore ?? new InMemoryToolResultStore({ maxTotalChars: 64_000_000 });
208
- const commitHands = config.configProvider === "local" ? { commitCoAuthor: "Sema <noreply@vivi-ai.com>" } : undefined;
209
- const checkpointStore = backend?.checkpoint && config.durableApproval ? backend.checkpoint(logger) : undefined;
210
- const retentionExecutor = backend?.retention?.({ taskAttachmentTable: taskAttachmentStore !== undefined, taskListTables: taskListLane.backend !== "memory", logger });
211
- const retentionLaneStore = backend?.retentionLane?.();
212
- assertRetentionLaneWirable({
213
- intervalSec: config.retentionSweep.intervalSec,
214
- policy: config.retentionPolicy,
215
- executor: retentionExecutor,
216
- stores: [
217
- { name: "sessionStore", store: sessionStore },
218
- { name: "checkpointStore", store: checkpointStore },
219
- { name: "toolResultStore", store: runnerOffloadStore },
220
- ],
221
- locked: (config.lockedConfigKeys ?? []).includes("retentionPolicy"),
222
- });
223
- assertConsolidationDriverWirable({
224
- enabled: config.memoryConsolidationDriver.enabled,
225
- memoryEngineWired: memoryEngine !== undefined,
226
- controlPlaneOwned: backendOwnsControlPlane(memoryEngine?.backend),
227
- memoryEngineBackend: config.memoryEngineBackend,
228
- ...(config.memoryProvenance !== undefined ? { provenance: config.memoryProvenance } : {}),
229
- });
230
- const memoryConsolidationFaces = config.memoryConsolidationDriver.enabled && memoryEngine
231
- ? createMemoryConsolidationFaces(memoryEngine, {
232
- seat: resolveConsolidationDriverSeat({
233
- brain,
234
- models: config.models,
235
- tiers: config.tiers,
236
- roles: config.roles,
237
- getApiKeyAndHeaders: createPerModelAuthSeat(() => configCenter.getKeyResolver()),
238
- }),
239
- scopes: config.memoryConsolidationDriver.scopes,
240
- ...(config.memoryProvenance !== undefined ? { provenance: config.memoryProvenance } : {}),
241
- onIncident: (err) => logger.warn("memory_consolidation_incident", { code: err.code ?? null, detail: err.message }),
242
- onStopDetail: (audit) => logger.warn("memory_consolidation_stop_detail", audit),
243
- ...(sessionCaptureRecordStore !== undefined ? { captureRecordStore: sessionCaptureRecordStore } : {}),
244
- })
245
- : undefined;
246
- for (const w of buildConsolidationValveAudit({
247
- enabled: config.memoryConsolidationDriver.enabled,
248
- operatorPrincipals: config.operatorPrincipals,
249
- hasServiceAuth: hasServiceAuth(config),
250
- allowUnauthedWrites: config.allowUnauthedWrites ?? false,
251
- }).warnings) {
252
- logger.warn(w.tag, { detail: w.detail });
253
- }
254
- if (memoryConsolidationFaces !== undefined) {
255
- logger.info("memory_consolidation_driver_armed", {
256
- seat: memoryConsolidationFaces.seat,
257
- model: memoryConsolidationFaces.model,
258
- scopes: memoryConsolidationFaces.scopes,
259
- periodic: false,
260
- });
261
- }
262
- const governanceSeams = createGovernanceSeams({
263
- config,
264
- logger,
265
- retentionStores: [
266
- { name: "sessionStore", store: sessionStore },
267
- { name: "checkpointStore", store: checkpointStore },
268
- { name: "toolResultStore", store: runnerOffloadStore },
269
- ],
270
- retentionExecutorWired: config.retentionSweep.intervalSec > 0 && retentionExecutor !== undefined && retentionLaneStore !== undefined,
271
- });
272
- const mcpRevocations = configCenter.takeMcpRevocations();
273
- const workflowModelAllowlistSnapshot = workflowModelAllowlistFor(config) ?? [];
274
- const sessionShellGateRegistry = createSessionShellGateRegistry();
275
- const runnerDeps = createRunnerDeps({
276
- hands: commitHands,
277
- mcpRevocations,
278
- sessionShellGateExplicitlyOff: sessionShellGateRegistry.explicitlyOff,
279
- config, logger, metrics, localRoot, promptSource: configCenter.promptSource, rosterStore, backgroundAgentStore, mailboxStore, usageWindowStore, brain,
280
- pricing, tracer, outcomeSink, elicitation, question, toolApproval, sessionStore, memoryEngine,
281
- sessionCaptureRecords,
282
- memorySyncRunner, toolResultStore: runnerOffloadStore, checkpointStore, sessionPolicyStore, runtimeCapsResolver, fileHistoryStore,
283
- permissionRuleStore: permissionRuleProvider,
284
- executionEnvFactory, lspManager, fleetBus, deploymentHooks, workflowRunStore, workflowJournalStore,
285
- workflowAgentRegistry, workflowNotifyGate, workflowCompletionInbox, deliverWorkflowCompletion, orgMemoryAdmission,
286
- governanceSeams,
287
- sharedMemoryStores: sharedMemoryStore ? sharedMemoryStore : undefined,
288
- getRunStore: () => runStore,
289
- });
290
- const runner = new Runner(runnerDeps);
291
- const handslessRunner = new Runner(withoutExecutionEnv(runnerDeps));
292
- const runnerTierFrozen = Object.keys(config.tiers).length > 0;
293
- const { hookModelFor, hookLlm } = createHookLlm({ config, getKeyResolver: () => configCenter.getKeyResolver(), metrics });
294
- const hookAgentRunner = new Runner({ ...runnerDeps, sessionStore: new TtlSessionStore({ defaultTtlDays: 1 / 24 }) });
295
- const hookAgent = async ({ prompt, model, timeoutMs, system }) => {
296
- const pick = hookModelFor(model);
297
- if (!pick.ok)
298
- return pick;
299
- try {
300
- const result = await hookAgentRunner.runTask({
301
- objective: prompt,
302
- sessionId: uuidv7(),
303
- model: pick.catalogRef,
304
- ...(system !== undefined ? { systemPrompt: system } : {}),
305
- handsReadOnly: true,
306
- enableFork: false,
307
- limits: { maxTurns: 10, maxCostUsd: 0.05, maxWalltimeMs: Math.max(30_000, timeoutMs) },
308
- toolPolicy: createAllowDenyPolicy({}),
309
- });
310
- metrics.inc("hook_llm_calls_total", { type: "agent" });
311
- if (result.terminal.kind !== "completed") {
312
- const plane = terminalProjection(result.terminal);
313
- return { ok: false, error: `hook agent ${plane.status}: ${clipHookErr(plane.errorMessage)}` };
314
- }
315
- return { ok: true, text: result.result ?? "" };
316
- }
317
- catch (e) {
318
- return { ok: false, error: String(e) };
319
- }
320
- };
321
- const clipHookErr = (s) => (s ?? "").slice(0, 300);
322
- const titleCapable = sessionStore;
323
- const sessionTitler = config.sessionAutoTitle && titleCapable.setTitleIfNull && titleCapable.probeTitle
324
- ? createSessionTitler({
325
- setTitleIfNull: titleCapable.setTitleIfNull.bind(sessionStore),
326
- probeTitle: titleCapable.probeTitle.bind(sessionStore),
327
- redact: redactSecrets,
328
- llm: (o) => hookLlm({ prompt: o.prompt, timeoutMs: o.timeoutMs, model: o.model }),
329
- logger,
330
- metrics,
331
- })
332
- : undefined;
333
- if (sessionTitler)
334
- logger.info("session_auto_title_enabled", {});
335
- const workflowsCapable = workflowsCapability(runnerDeps);
336
- const subRunnerSessions = new ForkRoutingSessionStore(sessionStore, new TtlSessionStore({ defaultTtlDays: 1 / 24 }));
337
- const subRunnerDeps = {
338
- ...createSharedRunnerDeps({
339
- metrics,
340
- config,
341
- logger,
342
- hands: commitHands,
343
- mcpRevocations,
344
- brain,
345
- pricing,
346
- tracer,
347
- promptSource: configCenter.promptSource,
348
- executionEnvFactory,
349
- lspManager,
350
- backgroundAgentStore,
351
- mailboxStore,
352
- rosterStore,
353
- deploymentHooks,
354
- toolResultStore: runnerOffloadStore,
355
- checkpointStore,
356
- sessionPolicyStore,
357
- usageWindowStore,
358
- orgMemoryAdmission,
359
- governanceSeams,
360
- sharedMemoryStores: sharedMemoryStore ? sharedMemoryStore : undefined,
361
- }),
362
- sessionStore: subRunnerSessions,
363
- onBackgroundChildEvent: runnerDeps.onBackgroundChildEvent ? runnerDeps.onBackgroundChildEvent : undefined,
364
- loadProjectMemory: runnerDeps.loadProjectMemory ? runnerDeps.loadProjectMemory : undefined,
365
- probeInstructionSources: runnerDeps.probeInstructionSources ? runnerDeps.probeInstructionSources : undefined,
366
- onError: runnerDeps.onError ? runnerDeps.onError : undefined,
367
- };
368
- const subRunner = new Runner(subRunnerDeps);
369
- const handslessSubRunner = new Runner(withoutExecutionEnv(subRunnerDeps));
370
- const authorize = createAuthorizer(config, sessionStore);
371
- const runStore = backend ? backend.run() : undefined;
372
- const resumeAnchorStore = backend ? backend.resumeAnchor() : undefined;
373
- const approvalExemptionStore = backend ? backend.approvalExemption() : undefined;
374
- const approvalNonceStore = backend ? backend.approvalNonce() : undefined;
375
- const taskTimeoutSec = Math.floor(parseNumOrFailNonNegative("TASK_TIMEOUT_SEC", process.env.TASK_TIMEOUT_SEC || "0"));
376
- const capEnv = (name) => {
377
- const r = parseCapEnv(name, process.env[name]);
378
- if (r.invalid !== undefined) {
379
- logger.warn("task_limit_cap_invalid", {
380
- env: name,
381
- raw: r.invalid,
382
- note: "this per-request rate cap is NOT in effect (a non-numeric or non-positive value parses to 'no cap'). Callers can self-report any value for this limit until the env is fixed.",
383
- });
384
- }
385
- return r.value;
386
- };
387
- const taskLimitCaps = {
388
- timeoutSec: capEnv("TASK_TIMEOUT_MAX_SEC"),
389
- maxOutputTokens: capEnv("TASK_MAX_OUTPUT_TOKENS_MAX"),
390
- maxTurns: capEnv("TASK_MAX_TURNS_MAX"),
391
- };
392
- const operatorGateIntent = hasOperatorGateIntent(config);
393
- assertGateIntentServiceable(config, checkpointStore !== undefined);
394
- const singleUserAutoAcceptBaseline = config.requirePrincipal !== true && !operatorGateIntent;
395
- await reclaimOrphansAtBoot(runStore, checkpointStore, logger);
396
- const imageIndex = backend?.imageIndex ? backend.imageIndex() : undefined;
397
- const selectEnvTool = config.selectEnvironmentTool && config.remoteExec?.provider === "k8s" && imageIndex
398
- ? selectEnvironmentTool({
399
- catalog: imageIndex,
400
- selection: sessionEnvSelection,
401
- viewerFor: (principal) => ({ operator: explicitOperatorOk(principal, config.operatorPrincipals), tenantId: principal ?? null }),
402
- })
403
- : undefined;
404
- const imageBakes = backend?.imageBake && config.imageBakes.enabled ? backend.imageBake() : undefined;
405
- if (imageBakes)
406
- logger.info("image_bakes_enabled", { operators: config.operatorPrincipals.length, runner: config.imageBakes.runnerPrincipal });
407
- if (durableEnabled)
408
- logger.info("durable_approval_enabled", { toolApprovalGate: config.approvalRequire.length });
409
- if (config.a2aServe) {
410
- logger.info("a2a_serve_enabled", {
411
- card: "/.well-known/agent-card.json",
412
- rpc: "/v1/a2a",
413
- advertisedUrl: config.a2aServe.url,
414
- skills: config.a2aServe.skills.length,
415
- blockingWaitMs: config.a2aServe.blockingWaitMs,
416
- tasksUsable: runStore !== undefined,
417
- });
418
- }
419
- if ((config.remoteExec === undefined || config.remoteExec.provider === "host") && !toolApproval && !durableEnabled) {
420
- logger.warn("fs_write_gate_no_responder", {
421
- hint: "host-semantics lane with no approval face: permissionMode default/auto Write/Edit asks will auto-deny (fail-closed); wire TOOL_APPROVAL_ENABLED=true or DURABLE_APPROVAL=true to answer them",
422
- });
423
- }
424
- if (config.selfOrchestrationEnabled && config.remoteExec !== undefined && config.remoteExec.provider !== "host" && !toolApproval && !durableEnabled) {
425
- logger.warn("workflow_gate_no_responder", {
426
- hint: "self-orchestration with no approval face: permissionMode default/auto/acceptEdits run_workflow asks will auto-deny (fail-closed); wire TOOL_APPROVAL_ENABLED=true or DURABLE_APPROVAL=true to answer them",
427
- });
428
- }
429
- if (singleUserAutoAcceptBaseline) {
430
- logger.info("tool_policy_single_user_default", {
431
- posture: "adjudicated auto-accept — ALL write/hand/MCP tool surfaces auto-allowed (core per-surface UNGATED enumeration suppressed for single-user turnkey)",
432
- tighten: "APPROVAL_REQUIRE / AUTONOMY / commandPolicy (re-surfaces + gates specific surfaces)",
433
- });
434
- }
435
- if (config.directDoorActive)
436
- logger.info("direct_door_active", { iss: config.principalJwtIss, aud: config.principalJwtAud, operators: config.operatorPrincipals.length });
437
- if (config.requirePrincipal && config.selfOrchestrationEnabled && !config.selfOrchestrationWorkerIsolation)
438
- logger.warn("self_orchestration_no_worker_isolation", { detail: "multi-tenant self-orchestration without SELF_ORCHESTRATION_WORKER_ISOLATION=true — a tenant workflow can starve the host event loop (availability risk). Set it to enable worker_thread resource isolation." });
439
- if (selfOrchestrationDenial(config, centerEntitlementSourceWired(config)) !== null)
440
- logger.warn("self_orchestration_no_entitlement_source", { detail: "SELF_ORCHESTRATION_ENABLED is on and REQUIRE_PRINCIPAL is on, but no per-principal entitlement source is wired (no config center, or it is in dry-run). core's allowWorkflows is tighten-only — an absent resolver leaves it ungated — so this service fail-closes self-orchestration for EVERY principal: no task on this worker can ever get the workflow engine. /v1/capabilities now reports workflows:false (workflowsGate.denial=\"entitlement_resolver_absent\") and a submit carrying selfOrchestration/settings.ultracode is refused 501 instead of silently downgraded. Wire a config center (SEMA_REGISTRY_URL + token, not dry-run), or set SELF_ORCHESTRATION_ENABLED=false." });
441
- {
442
- const inert = buildForceDurableGateInertNotice({
443
- entitlementSourceWired: centerEntitlementSourceWired(config),
444
- checkpointStorePresent: checkpointStore !== undefined,
445
- durableApproval: config.durableApproval,
446
- });
447
- if (inert)
448
- logger.warn(inert.event, inert.fields);
449
- }
450
- if (config.requirePrincipal && !config.authToken && Object.keys(config.authTokens ?? {}).length === 0 && !config.traceToken)
451
- logger.warn("multi_tenant_no_service_token", { detail: "REQUIRE_PRINCIPAL is on but no SERVICE_AUTH_TOKEN/authTokens/TRACE_TOKEN — fleet/trace/session-list are owner-gated only (never fleet-wide, tenant-isolation safe). Set a token for cross-tenant ops visibility." });
452
- const rateLimiter = backend?.rateLimiter
453
- ? backend.rateLimiter(config.rateLimitPerMin, counterDegradeHook).startRefresh()
454
- : new RateLimiter(config.rateLimitPerMin);
455
- let skills = loadSkills(config.skillsDir);
456
- skills = await configCenter.applyCenterCapabilities(skills);
457
- const repoClient = config.gitApiBaseUrl ? createRepoClient(config.gitApiKind, config.gitApiBaseUrl, config.gitApiToken) : undefined;
458
- const webSearchCfg = webSearchConfigFromEnv();
459
- const webSearch = webSearchCfg ? createWebSearchBackend(webSearchCfg) : undefined;
460
- if (webSearch)
461
- logger.info(`WebSearch enabled (provider=${webSearchCfg.provider}, maxResults=${webSearch.maxResults})`);
462
- if (webSearch && shouldProbeWebSearchOnBoot()) {
463
- void probeSearchBackend(webSearch.search, { timeoutMs: 10_000 })
464
- .then((r) => {
465
- if (r.ok)
466
- logger.info("web_search_probe_ok", { provider: webSearchCfg.provider, results: r.results });
467
- else
468
- logger.warn("web_search_probe_failed", { provider: webSearchCfg.provider, error: r.error, note: "WebSearch stays mounted — the tool will fail per-call until this is fixed; the service is not blocked by it." });
469
- })
470
- .catch((e) => logger.warn("web_search_probe_failed", { provider: webSearchCfg.provider, error: e instanceof Error ? e.message : String(e) }));
471
- }
472
- const ensureChildSessionDurable = checkpointStore && config.sessionBackend === "tidb" ? (sessionId) => ensureChildSessionDurableWithPromotion(sessionStore, subRunnerSessions, sessionId) : undefined;
473
- const webFetchSummarize = createWebFetchSummarizeLane({ brain, config, getKeyResolver: () => configCenter.getKeyResolver(), logger });
474
- const scenarioDeps = {
475
- runner, subRunner, handslessSubRunner, model: DEFAULT_MODEL_REF, skills, repoClient, requirePrincipal: config.requirePrincipal,
476
- webSearch: webSearch ? webSearch : undefined, metrics, logger, webFetchSummarize,
477
- backgroundAgentStore: backgroundAgentStore ? backgroundAgentStore : undefined,
478
- checkpointStore: checkpointStore ? checkpointStore : undefined,
479
- ensureChildSessionDurable: ensureChildSessionDurable ? ensureChildSessionDurable : undefined,
480
- taskListStoreFor: taskListLane.storeFor,
481
- brandIdentity: config.configProvider === "local",
482
- subagentExtraTools: sendUserFileToolSpec
483
- ? subagentSendUserFileExtraTools({
484
- spec: sendUserFileToolSpec,
485
- approvalGate: () => ({ deny: config.approvalDeny, require: config.approvalRequire, neverAuto: config.approvalNeverAuto }),
486
- })
487
- : undefined,
488
- };
489
- const scenarios = buildScenarios(scenarioDeps);
490
- const parkedReviveTool = checkpointStore && backgroundAgentStore ? scenarios.default?.({})?.tools.find((t) => t.name === DEFAULT_SUBAGENT_TOOL_NAME) : undefined;
491
- const parkedReviveInheritedGate = parkedReviveTool && config.durableApproval
492
- ? createParkedReviveInheritedGate({
493
- config, question, approvalExemptionStore, logger, localRoot,
494
- memoryEngineRoot: memoryEngine?.root,
495
- approverSeat: createRunnerDepsOnAsk(toolApproval),
496
- ...(runnerDeps.runtimeCapsResolver ? { resolveRuntimeCaps: runnerDeps.runtimeCapsResolver } : {}),
497
- autoModeSeatMounted: runnerDeps.autoMode !== undefined,
498
- })
499
- : undefined;
500
- const scenarioDetails = builtinScenarioDetails(scenarios, scenarioDeps);
501
- const builtinScenarioNames = Object.keys(scenarioDetails);
502
- configCenter.applyCenterScenarios({ scenarioDeps, scenarios, scenarioDetails, builtinScenarioNames });
503
- logger.info("capabilities", { skills: skills.length, scenarios: Object.keys(scenarios), repoTools: Boolean(repoClient) });
504
- let runDenySweep;
505
- const reaper = startReapers({
506
- config, logger, metrics, localRoot, backend, subRunner, runStore, checkpointStore,
507
- rateLimiter, costQuota, toolResultStore, fileHistoryStore, taskAttachmentStore, imageBakes, worktreeReap,
508
- workflowNotifyGate, workflowRecoverOpts, workflowJournalStore, sqlWorkflowRunStore, workflowNotifyJournal, rosterStore,
509
- backgroundAgentStore, mailboxStore, toolApproval, permissionRuleStores, approvalNonceStore,
510
- getRunDenySweep: () => runDenySweep,
511
- });
512
- const ttlMs = config.retentionSweep.intervalSec * 1000 * RETENTION_LEASE_TTL_FACTOR;
513
- const retentionLaneStarted = retentionExecutor !== undefined && retentionLaneStore !== undefined && config.retentionPolicy !== undefined
514
- ? startRetentionLane({
515
- intervalSec: config.retentionSweep.intervalSec,
516
- policy: config.retentionPolicy,
517
- mode: config.retentionSweep.mode,
518
- executor: retentionExecutor,
519
- lease: {
520
- acquire: async () => {
521
- const claim = await retentionLaneStore.acquire(instanceId, ttlMs, Date.now());
522
- return claim.held ? { held: true, fencingToken: claim.fencingToken } : { held: false };
523
- },
524
- renew: (fencingToken) => retentionLaneStore.renew(instanceId, fencingToken, ttlMs, Date.now()),
525
- release: () => retentionLaneStore.release(instanceId),
526
- },
527
- audit: { append: (row) => retentionLaneStore.appendAudit(row, Date.now()) },
528
- holdInForce: (domain) => retentionLaneStore.holdInForce(domain),
529
- logger,
530
- metrics,
531
- now: () => Date.now(),
532
- })
533
- : undefined;
534
- if (retentionLaneStarted !== undefined) {
535
- logger.info("retention_lane_started", {
536
- intervalSec: config.retentionSweep.intervalSec,
537
- mode: config.retentionSweep.mode,
538
- maxAgeDays: config.retentionPolicy?.maxAgeDays,
539
- holder: instanceId,
540
- });
541
- }
542
- const otelExporter = config.otel
543
- ? startOtlpExporter(metrics, {
544
- ...config.otel,
545
- onError: (err) => logger.warn("otel_export_failed", { err: String(err) }),
546
- })
547
- : undefined;
548
- const limitSync = createLimitSync({ config, rateGate: rateLimiter, quota: costQuota, logger });
549
- limitSync.sync();
550
- const bootRunners = [
551
- ["runner", runner],
552
- ["handsless", handslessRunner],
553
- ["hookAgent", hookAgentRunner],
554
- ["sub", subRunner],
555
- ["handslessSub", handslessSubRunner],
556
- ];
557
- const swapRunnerDeps = (next) => {
558
- for (let i = 0; i < bootRunners.length; i++) {
559
- const [name, rn] = bootRunners[i];
560
- try {
561
- rn.swapDeps(next);
562
- }
563
- catch (err) {
564
- if (i > 0)
565
- logger.error("runner_deps_swap_split", { failedAt: name, seats: Object.keys(next), swapped: bootRunners.slice(0, i).map(([n]) => n), err: String(err) });
566
- throw err;
567
- }
568
- }
569
- };
570
- configCenter.startRefreshLoop({ runnerTierFrozen, pricing, limitSync, swapRunnerDeps, ceilingVerdict });
571
- configCenter.initKeyResolver();
572
- const { ownerAware, sessionAudit, sessionWatchRegistry, purgeSession, instrumentDegenerate, planCacheProbe } = createSessionFaces({
573
- deviceStore: deviceLane?.store,
574
- dropSessionScoped,
575
- config, logger, metrics, localRoot, backend, sessionStore, runStore, checkpointStore, toolResultStore,
576
- resumeAnchorStore, approvalExemptionStore, sessionPolicyStore, taskAttachmentStore, fileHistoryStore,
577
- workflowCompletionInbox, taskListLane,
578
- });
579
- const leaderEndpoint = createLeaderFace({ config, logger, brain, pricing, executionEnvFactory, toolResultStore, sessionStore, checkpointStore, governanceSeams, backend, tracer, usageWindowStore, promptSource: configCenter.promptSource, onError: runnerDeps.onError });
580
- const drainState = { draining: false };
581
- const authBridgeIssuer = process.env.AUTH_BRIDGE_ISSUER || config.configCenter?.baseUrl;
582
- const registryJwtVerifier = authBridgeIssuer
583
- ? createRegistryJwtVerifier({
584
- issuer: authBridgeIssuer,
585
- ...(process.env.AUTH_BRIDGE_JWKS_URL ? { jwksUrl: process.env.AUTH_BRIDGE_JWKS_URL } : {}),
586
- ...(process.env.AUTH_BRIDGE_AUDIENCE ? { audience: process.env.AUTH_BRIDGE_AUDIENCE } : {}),
587
- logger,
588
- metrics,
589
- })
590
- : undefined;
591
- if (registryJwtVerifier)
592
- logger.info("auth_bridge_enabled", { issuer: authBridgeIssuer });
593
- const hookWakeBus = {};
594
- const wiringSpecTemplate = durableEnabled
595
- ? { checkpointStore, durableApproval: { scope: encodeCheckpointScope(undefined) } }
596
- : {};
597
- const staticWiring = describeStaticWiring(runnerDeps, wiringSpecTemplate);
598
- assertStaticWiringConsistent({ manifest: staticWiring, parkFacility: durableEnabled, backendKind: backend?.kind }, logger);
599
- logger.info("wiring_static", {
600
- fingerprint: staticWiring.configFingerprint ?? null,
601
- parkEffective: staticWiring.parkLane.effective,
602
- sessionDurability: staticWiring.session.store,
603
- posture: staticWiring.interaction.posture,
604
- streamApproval: streamApprovalGate.active ? "active" : streamApprovalGate.reason,
605
- subagentTranscripts: staticWiring.fleet.subagentTranscripts,
606
- subagentTranscriptRetentionMs: config.backgroundAgentRetentionMs,
607
- });
608
- const stores = {
609
- runStore,
610
- resumeAnchorStore: resumeAnchorStore ? resumeAnchorStore : undefined,
611
- approvalExemptionStore: approvalExemptionStore ? approvalExemptionStore : undefined,
612
- approvalNonceStore: approvalNonceStore ? approvalNonceStore : undefined,
613
- checkpointStore,
614
- sessionPolicyStore: sessionPolicyStore ? sessionPolicyStore : undefined,
615
- ruleConsent,
616
- fileHistoryStore: fileHistoryStore ? fileHistoryStore : undefined,
617
- toolResultStore,
618
- taskAttachmentStore: taskAttachmentStore ? taskAttachmentStore : undefined,
619
- backgroundAgentStore: backgroundAgentStore ? backgroundAgentStore : undefined,
620
- sessionStorage: ownerAware,
621
- workflowRunStore: workflowRunStore ? workflowRunStore : undefined,
622
- workflowAgentSessionIndex: workflowAgentSessionIndex ? workflowAgentSessionIndex : undefined,
623
- workflowJournalStore: workflowJournalStore ? workflowJournalStore : undefined,
624
- imageIndex,
625
- imageBakes,
626
- outcomeSink: outcomeSink ? outcomeSink : undefined,
627
- sendFileLedger: sendFileLedger ? sendFileLedger : undefined,
628
- backend: backend ? backend : undefined,
629
- };
630
- let resolveFleetRecovery;
631
- const fleetRecoveryDone = new Promise((r) => { resolveFleetRecovery = r; });
632
- const coordinators = {
633
- elicitation: elicitation ? elicitation : undefined,
634
- question: question ? question : undefined,
635
- toolApproval: toolApproval ? toolApproval : undefined,
636
- approvalAskAudit: approvalAskAudit ? approvalAskAudit : undefined,
637
- approvalLateSettle: approvalAskAudit ? approvalAskAudit : undefined,
638
- workflowAgentRegistry: workflowAgentRegistry ? workflowAgentRegistry : undefined,
639
- subagentSteerRegistry,
640
- workflowCompletionInbox: workflowCompletionInbox ? workflowCompletionInbox : undefined,
641
- fleetBus,
642
- fleetRecoveryDone,
643
- sessionWatch: sessionWatchRegistry ? sessionWatchRegistry : undefined,
644
- hookWakeBus,
645
- sendUserFile: sendUserFileEmitter ? sendUserFileEmitter : undefined,
646
- leaderEndpoint,
647
- sessionTitler: sessionTitler ? sessionTitler : undefined,
648
- };
649
- const seams = {
650
- deviceHub: deviceLane?.hub,
651
- deviceStore: deviceLane?.store,
652
- sessionAudit,
653
- routeJudgeBrain: brain,
654
- purgeSession: purgeSession ? purgeSession : undefined,
655
- subagentTaskOutput: (handle, access) => backgroundAgentOutput(defaultTaskRegistry, handle, access, backgroundAgentStore),
656
- taskHandleOutput: (handle, access) => taskHandleOutput(defaultTaskRegistry, handle, access, backgroundAgentStore),
657
- taskHandleStop: (handle, access) => taskHandleStop(defaultTaskRegistry, handle, access, backgroundAgentStore),
658
- memoryExport: memoryExportBackend ? (scope) => exportMemoryScope(memoryExportBackend, scope) : undefined,
659
- memorySync: memoryExportBackend && memorySyncCursors
660
- ? (scope, syncReq) => performMemorySync(memoryExportBackend, memorySyncCursors, scope, syncReq)
661
- : undefined,
662
- memoryBundleExport: memoryBundleFaces ? memoryBundleFaces.exportScopes : undefined,
663
- memoryBundleImport: memoryBundleFaces ? memoryBundleFaces.importBundle : undefined,
664
- memoryCompliance: memoryComplianceFaces,
665
- memoryOriginFace: memoryOriginFaces,
666
- sessionMemoryStatus: sessionMemoryStatusFace,
667
- memoryConsolidation: memoryConsolidationFaces,
668
- memoryOptOutGrant: memoryOptOutGrantStore,
669
- orgMemoryDirectory: orgMemoryAdmission.directory,
670
- sharedMemoryStore: sharedMemoryStore ? sharedMemoryStore : undefined,
671
- sessionMirrorRuling: principalCaps
672
- ? async (p) => (await principalCaps.executionRuling(p))?.sessionMirror
673
- : undefined,
674
- instrumentDegenerate,
675
- sideQueryAccounting,
676
- parkedReviveTool: parkedReviveTool ? parkedReviveTool : undefined,
677
- parkedReviveInheritedGate: parkedReviveInheritedGate ? parkedReviveInheritedGate : undefined,
678
- };
679
- const observability = {
680
- logger,
681
- metrics,
682
- modelUsage: modelUsageTracker,
683
- promptManifests: promptManifestTracker,
684
- planCacheProbe,
685
- };
686
- const governance = {
687
- authorize,
688
- registryJwtVerifier: registryJwtVerifier ? registryJwtVerifier : undefined,
689
- rateLimiter,
690
- costQuota,
691
- fleetLease: fleetLease ? fleetLease : undefined,
692
- usageWindowStore: usageWindowStore ? usageWindowStore : undefined,
693
- autoModeFace: {
694
- seatMounted: runnerDeps.autoMode !== undefined,
695
- engineArmsOnIntent: coreArmsAutoOnIntent(),
696
- resolveCaps: runtimeCapsPeekResolver,
697
- classifierModel: () => {
698
- const route = classifierRouteFor(runnerDeps);
699
- if (route.fault !== undefined)
700
- logger.debug("auto_mode_classifier_route_unresolved", { fault: route.fault });
701
- return route.id;
702
- },
703
- },
704
- };
705
- const storeLiveProbe = backend && backend.kind !== "local" && backend.dbNowMs && config.storeProbeIntervalMs > 0
706
- ? createStoreLiveProbe({ probe: () => backend.dbNowMs(), intervalMs: config.storeProbeIntervalMs, logger })
707
- : undefined;
708
- const deployment = {
709
- sessionStoreLabel: config.sessionBackend === "tidb" && backend ? `durable(${backend.kind})` : config.sessionBackend,
710
- modelReady: () => configCenter.modelReady(),
711
- scenarioDetails,
712
- workflowsCapable,
713
- workflowModelAllowlist: workflowModelAllowlistSnapshot,
714
- staticWiring,
715
- memoryPosture,
716
- sqlEngineFacts,
717
- writeProtection: buildWriteProtectionPosture(config),
718
- instanceId,
719
- capabilities: {
720
- version: serviceVersion(),
721
- scenarios: Object.keys(scenarios),
722
- get pricingConfigured() {
723
- return isPricingConfigured(pricing);
724
- },
725
- },
726
- restartState: () => configCenter.restartState(),
727
- planeDeferredState: () => configCenter.planeDeferredState(),
728
- configApplyState: () => configCenter.configApplyState(),
729
- mcpRevocations,
730
- mcpRevocationState: () => configCenter.mcpRevocationState(),
731
- configRefreshNow: () => configCenter.refreshNow(),
732
- configCenterManagedKeys: () => configCenter.centerManagedKeys(),
733
- drainState,
734
- storeDegraded: storeBackendDegraded,
735
- storeLiveState: storeLiveProbe ? () => storeLiveProbe.state() : undefined,
736
- };
737
- const knobs = {
738
- snapshotBlobSqlCapBytes: backend && backend.kind !== "local" && !config.snapshotBlobStore
739
- ? (config.snapshotBlobSqlMaxBytes ?? (backend.kind === "mysql" ? SQL_BLOB_DEFAULT_MAX_BYTES : undefined))
740
- : undefined,
741
- sessionEventsMaxConnections: sessionWatchRegistry ? posIntEnv(process.env.SESSION_EVENTS_MAX_CONNS, 256, 100_000) : undefined,
742
- };
743
- const resolveSpec = createResolveSpec({
744
- config, logger, metrics, localRoot, scenarios, principalCaps, centerRuntimeCapsResolver,
745
- getCenterPrompts: () => configCenter.getCenterPrompts(),
746
- getKeyResolver: () => configCenter.getKeyResolver(),
747
- taskAttachmentStore, perSessionCwd, setSessionCwd, setSessionShellEnv, fenceSessionOwner,
748
- hookLlm, hookAgent, fleetBus, hookWakeBus, resumeAnchorStore, ownerAware, taskLimitCaps, taskTimeoutSec,
749
- noteSessionShellGate: sessionShellGateRegistry.note,
750
- selectEnvTool, sendUserFileToolSpec, memoryEngine, durableEnabled, approvalExemptionStore,
751
- singleUserAutoAcceptBaseline, checkpointStore, deploymentHooks, imageIndex, perTaskImage,
752
- sessionEnvSelection,
753
- lockedKeys: governanceSeams.lockedKeys,
754
- liveQuestionFace: question,
755
- approverSeat: createRunnerDepsOnAsk(toolApproval),
756
- });
757
- const runnerFor = createHandsRunnerSelector({ full: runner, handsless: handslessRunner });
758
- const sideQuery = createSideQueryLane({ brain, config, getKeyResolver: () => configCenter.getKeyResolver() });
759
- const server = createHttpServer({ runner, runnerFor, sideQuery, config, resolveSpec, stores, coordinators, seams, observability, governance, deployment, knobs });
760
- runDenySweep = server.denyExpiredApprovals;
761
- if (!config.directDoorActive)
762
- parkedAskRedeem = server.redeemParkedAsk;
763
- else
764
- logger.info("parked_late_decision_disabled", { reason: "direct_door_requires_signed_decision_envelope" });
765
- const fleetReconcile = startFleetReconciler({
766
- bus: fleetBus,
767
- isLiveOnThisReplica: server.isRunLiveOnThisReplica,
768
- ...(runStore ? { runs: runStore } : {}),
769
- ...(workflowRunStore ? { workflows: workflowRunStore } : {}),
770
- instanceId,
771
- logger,
772
- metrics,
773
- });
774
- const bindHost = resolveBindHost(config);
775
- if (config.bindHostSource === "HOST" && bindHost !== config.bindHost) {
776
- logger.warn("bind_host_from_HOST_env_overridden", {
777
- bindHost,
778
- ignoredHostEnv: config.bindHost,
779
- 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.",
780
- });
781
- }
782
- else if (config.bindHostSource === "HOST") {
783
- logger.warn("bind_host_from_HOST_env", {
784
- bindHost,
785
- 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.",
786
- });
787
- }
788
- let onListenError;
789
- try {
790
- await new Promise((resolve, reject) => {
791
- onListenError = reject;
792
- server.once("error", onListenError);
793
- bindHost ? server.listen(config.port, bindHost, resolve) : server.listen(config.port, resolve);
794
- });
795
- }
796
- catch (e) {
797
- logger.error("listen_failed", {
798
- port: config.port,
799
- bindHost: bindHost ?? "0.0.0.0/::(all interfaces)",
800
- ...(config.bindHostSource ? { bindHostSource: config.bindHostSource } : {}),
801
- ...(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)." } : {}),
802
- error: e instanceof Error ? e.message : String(e),
803
- });
804
- throw e;
805
- }
806
- finally {
807
- if (onListenError)
808
- server.removeListener("error", onListenError);
809
- }
810
- server.on("error", (e) => {
811
- logger.error("server_error", {
812
- error: e.message,
813
- ...("code" in e ? { code: String(e.code) } : {}),
814
- });
815
- });
816
- const fleetClient = startFleetClientFromEnv(config, {
817
- instanceId,
818
- version: serviceVersion(),
819
- isDraining: () => drainState.draining,
820
- ...(fleetUsage ? { usage: fleetUsage } : {}),
821
- logger: { info: (m, d) => logger.info(m, d ?? {}), warn: (m, d) => logger.warn(m, d ?? {}) },
822
- });
823
- if (fleetClient)
824
- logger.info("fleet_client_started", { worker: config.configCenter?.worker, address: process.env.FLEET_ADVERTISE_ADDRESS });
825
- logger.info("listening", {
826
- port: config.port,
827
- bindHost: bindHost ?? "0.0.0.0/::(all interfaces)",
828
- ...(bindHost === "127.0.0.1" && !config.bindHost
829
- ? { bindHostNote: "auto-narrowed to loopback: write face is unauthenticated (ALLOW_UNAUTHED_WRITES with no service token). Set BIND_HOST explicitly to override." }
830
- : {}),
831
- model: config.model.id,
832
- brain: brainSummary(config),
833
- breakerState: config.resilience.circuitBreaker ? (breakerState ? `shared(${backend.kind})` : "in-process") : "off",
834
- session: config.sessionBackend === "tidb" && backend ? `durable(${backend.kind})` : config.sessionBackend,
835
- memory: memoryEngine ? `engine(${memoryEngine.root})` : "off",
836
- instanceId,
837
- rateLimitPerMin: config.rateLimitPerMin,
838
- rateLimit: config.rateLimitPerMin > 0 ? counterStoreLabel(backend?.rateLimiter, backend?.kind) : "off",
839
- maxPrincipalCostUsd: config.maxPrincipalCostUsd || null,
840
- costQuota: config.maxPrincipalCostUsd > 0 ? counterStoreLabel(backend?.costQuota, backend?.kind) : "off",
841
- toolResultStore: toolResultStore ? (backend?.kind === "local" ? "file(local)" : "shared(sql)") : "in-process",
842
- otel: config.otel ? config.otel.endpoint : null,
843
- perModelKeys: Object.keys(config.modelApiKeyEnv).length,
844
- sealedModelKeys: Object.values(config.modelApiKeys).filter((v) => typeof v === "string").length,
845
- sealedPoisonedModels: Object.values(config.modelApiKeys).filter((v) => typeof v !== "string").length,
846
- workflowRunStore: config.selfOrchestrationEnabled
847
- ? config.workflowRunStoreBackend === "memory"
848
- ? "in-process"
849
- : sqlWorkflowRunStore
850
- ? `db(${backend.kind})`
851
- : "file"
852
- : "off",
853
- });
854
- if (workflowNotifyGate) {
855
- void workflowNotifyGate
856
- .recover(workflowRecoverOpts)
857
- .then((tally) => logger.info("workflow_notify_recovered", tally))
858
- .catch((err) => logger.warn("workflow_notify_recover_failed", { err: String(err) }))
859
- .finally(() => resolveFleetRecovery());
860
- }
861
- else {
862
- resolveFleetRecovery();
863
- }
864
- void installShutdownHandlers({
865
- config, logger, server, reaper, fleetReconcile, otelExporter, breakerState, costQuota, rateLimiter,
866
- version: serviceVersion(),
867
- runner, subRunner, lspManager, workflowNotifyJournal, fleetClient, backend, drainState,
868
- storeLiveProbe, configCenter,
869
- deviceHub: deviceLane?.hub,
870
- retentionLane: retentionLaneStarted,
871
- releaseRetentionLease: retentionLaneStore !== undefined ? () => retentionLaneStore.release(instanceId) : undefined,
872
- });
13
+ const s01 = runStage01();
14
+ const s02 = await runStage02(s01);
15
+ const s03 = await runStage03(s02);
16
+ const s04 = await runStage04(s03);
17
+ const s05 = runStage05(s04);
18
+ const s06 = runStage06(s05);
19
+ const s07 = await runStage07(s06);
20
+ const s08 = runStage08(s07);
21
+ const s09 = runStage09(s08);
22
+ await runStage10(s09);
873
23
  }
874
24
  void main().catch((err) => {
875
25
  createLogger().error("fatal", { err: String(err) });