@sema-agent/server 7.79.2 → 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.
- 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/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
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 {
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
-
import {
|
|
31
|
-
import {
|
|
32
|
-
import {
|
|
33
|
-
import {
|
|
34
|
-
import {
|
|
35
|
-
import {
|
|
36
|
-
import {
|
|
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
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
const
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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) });
|