@agent-native/core 0.12.15 → 0.12.16
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/agent/run-manager.d.ts.map +1 -1
- package/dist/agent/run-manager.js +56 -42
- package/dist/agent/run-manager.js.map +1 -1
- package/dist/cli/workspace-dev.js +26 -5
- package/dist/cli/workspace-dev.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +33 -6
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +7 -2
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/NewWorkspaceAppFlow.d.ts.map +1 -1
- package/dist/client/NewWorkspaceAppFlow.js +2 -0
- package/dist/client/NewWorkspaceAppFlow.js.map +1 -1
- package/dist/client/sharing/ShareButton.js +6 -1
- package/dist/client/sharing/ShareButton.js.map +1 -1
- package/dist/client/sharing/ShareButton.spec.d.ts +2 -0
- package/dist/client/sharing/ShareButton.spec.d.ts.map +1 -0
- package/dist/client/sharing/ShareButton.spec.js +90 -0
- package/dist/client/sharing/ShareButton.spec.js.map +1 -0
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +10 -2
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/client/use-chat-threads.d.ts.map +1 -1
- package/dist/client/use-chat-threads.js +19 -2
- package/dist/client/use-chat-threads.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +11 -7
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/templates/default/AGENTS.md +7 -1
- package/dist/templates/default/DEVELOPING.md +12 -0
- package/dist/templates/default/app/hooks/use-navigation-state.ts +81 -0
- package/dist/templates/default/app/root.tsx +11 -5
- package/package.json +1 -1
- package/src/templates/default/AGENTS.md +7 -1
- package/src/templates/default/DEVELOPING.md +12 -0
- package/src/templates/default/app/hooks/use-navigation-state.ts +81 -0
- package/src/templates/default/app/root.tsx +11 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-manager.d.ts","sourceRoot":"","sources":["../../src/agent/run-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAgBtE,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,QAAQ,EAAE,CAAC;IACnB,MAAM,EAAE,SAAS,CAAC;IAClB,WAAW,EAAE,GAAG,CAAC,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,CAAC,CAAC;IAC5C,KAAK,EAAE,eAAe,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB;AAQD,8DAA8D;AAC9D,eAAO,MAAM,kCAAkC,QAAS,CAAC;AAEzD,6EAA6E;AAC7E,eAAO,MAAM,kCAAkC,QAAsB,CAAC;AAEtE;;;;;GAKG;AACH,eAAO,MAAM,gCAAgC,QAAiB,CAAC;AAE/D,MAAM,WAAW,eAAe;IAC9B;;2CAEuC;IACvC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;4DACwD;IACxD,2BAA2B,CAAC,EAAE,OAAO,CAAC;CACvC;AAED,MAAM,WAAW,4BAA4B;IAC3C,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AA0BD,wBAAgB,uBAAuB,CACrC,UAAU,CAAC,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,4BAA4B,GACrC,MAAM,CAYR;AAED,wBAAgB,8BAA8B,IAAI,MAAM,CAOvD;AA6BD;;;;;;GAMG;AACH,wBAAgB,QAAQ,CACtB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,CACL,IAAI,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,EACrC,MAAM,EAAE,WAAW,KAChB,OAAO,CAAC,IAAI,CAAC,EAClB,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,SAAS,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,EACrD,OAAO,CAAC,EAAE,eAAe,GACxB,SAAS,
|
|
1
|
+
{"version":3,"file":"run-manager.d.ts","sourceRoot":"","sources":["../../src/agent/run-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAgBtE,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,QAAQ,EAAE,CAAC;IACnB,MAAM,EAAE,SAAS,CAAC;IAClB,WAAW,EAAE,GAAG,CAAC,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,CAAC,CAAC;IAC5C,KAAK,EAAE,eAAe,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB;AAQD,8DAA8D;AAC9D,eAAO,MAAM,kCAAkC,QAAS,CAAC;AAEzD,6EAA6E;AAC7E,eAAO,MAAM,kCAAkC,QAAsB,CAAC;AAEtE;;;;;GAKG;AACH,eAAO,MAAM,gCAAgC,QAAiB,CAAC;AAE/D,MAAM,WAAW,eAAe;IAC9B;;2CAEuC;IACvC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;4DACwD;IACxD,2BAA2B,CAAC,EAAE,OAAO,CAAC;CACvC;AAED,MAAM,WAAW,4BAA4B;IAC3C,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AA0BD,wBAAgB,uBAAuB,CACrC,UAAU,CAAC,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,4BAA4B,GACrC,MAAM,CAYR;AAED,wBAAgB,8BAA8B,IAAI,MAAM,CAOvD;AA6BD;;;;;;GAMG;AACH,wBAAgB,QAAQ,CACtB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,CACL,IAAI,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,EACrC,MAAM,EAAE,WAAW,KAChB,OAAO,CAAC,IAAI,CAAC,EAClB,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,SAAS,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,EACrD,OAAO,CAAC,EAAE,eAAe,GACxB,SAAS,CAuOX;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,GACd,cAAc,CAAC,UAAU,CAAC,GAAG,IAAI,CAOnC;AAuPD,wEAAwE;AACxE,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAOxE;AAED;;;;;;GAMG;AACH,wBAAsB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IAC1E,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;CACrB,GAAG,IAAI,CAAC,CAiER;AAED,sBAAsB;AACtB,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAEtD;AAED,gDAAgD;AAChD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,GAAE,MAAe,GAAG,OAAO,CAQxE"}
|
|
@@ -147,10 +147,8 @@ export function startRun(runId, threadId, runFn, onComplete, options) {
|
|
|
147
147
|
abort.abort();
|
|
148
148
|
}, softTimeoutMs)
|
|
149
149
|
: null;
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
return;
|
|
153
|
-
const runEvent = { seq: run.events.length, event };
|
|
150
|
+
let pendingTerminalEvent = null;
|
|
151
|
+
const emitRunEvent = (runEvent) => {
|
|
154
152
|
run.events.push(runEvent);
|
|
155
153
|
// Notify in-memory subscribers (same isolate, fast path)
|
|
156
154
|
for (const subscriber of run.subscribers) {
|
|
@@ -162,9 +160,19 @@ export function startRun(runId, threadId, runFn, onComplete, options) {
|
|
|
162
160
|
}
|
|
163
161
|
}
|
|
164
162
|
// Persist event to SQL (fire-and-forget)
|
|
165
|
-
insertRunEvent(runId, runEvent.seq, JSON.stringify(event)).catch(() => { });
|
|
163
|
+
insertRunEvent(runId, runEvent.seq, JSON.stringify(runEvent.event)).catch(() => { });
|
|
166
164
|
checkSqlAbort();
|
|
167
165
|
};
|
|
166
|
+
const send = (event) => {
|
|
167
|
+
if (run.status === "aborted" && abort.signal.aborted)
|
|
168
|
+
return;
|
|
169
|
+
const runEvent = { seq: run.events.length, event };
|
|
170
|
+
if (isTerminalRunEvent(event)) {
|
|
171
|
+
pendingTerminalEvent = runEvent;
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
emitRunEvent(runEvent);
|
|
175
|
+
};
|
|
168
176
|
// Run in background — intentionally detached from any HTTP connection
|
|
169
177
|
const runPromise = runFn(send, abort.signal)
|
|
170
178
|
.then(() => {
|
|
@@ -199,59 +207,65 @@ export function startRun(runId, threadId, runFn, onComplete, options) {
|
|
|
199
207
|
// reconnecting clients trust the simple rule "status != running →
|
|
200
208
|
// fetch thread_data" without polling/retrying for a race window
|
|
201
209
|
// where onComplete was still pending.
|
|
202
|
-
// 1.
|
|
203
|
-
// in-flight SSE streams close promptly. Thread-data save below
|
|
204
|
-
// runs in parallel with subscribers disconnecting.
|
|
205
|
-
if (run.status === "errored" || run.status === "completed") {
|
|
206
|
-
const terminal = {
|
|
207
|
-
seq: run.events.length,
|
|
208
|
-
event: run.status === "errored"
|
|
209
|
-
? { type: "error", error: "Agent run ended unexpectedly" }
|
|
210
|
-
: { type: "done" },
|
|
211
|
-
};
|
|
212
|
-
const last = run.events[run.events.length - 1];
|
|
213
|
-
if (!last || !isTerminalRunEvent(last.event)) {
|
|
214
|
-
run.events.push(terminal);
|
|
215
|
-
insertRunEvent(runId, terminal.seq, JSON.stringify(terminal.event)).catch(() => { });
|
|
216
|
-
for (const subscriber of run.subscribers) {
|
|
217
|
-
try {
|
|
218
|
-
subscriber(terminal);
|
|
219
|
-
}
|
|
220
|
-
catch {
|
|
221
|
-
// ignore — subscriber will be cleaned up below
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
for (const subscriber of run.subscribers) {
|
|
227
|
-
run.subscribers.delete(subscriber);
|
|
228
|
-
}
|
|
229
|
-
// 2. Await the completion callback (thread_data save). Heartbeat is
|
|
210
|
+
// 1. Await the completion callback (thread_data save). Heartbeat is
|
|
230
211
|
// still ticking so the run doesn't look stale to any concurrent
|
|
231
212
|
// /runs/active check while we wait for SQL writes to land.
|
|
232
213
|
let completionError = null;
|
|
233
214
|
if (onComplete &&
|
|
234
215
|
!(run.status === "aborted" && run.abortReason === "no_progress")) {
|
|
235
216
|
try {
|
|
236
|
-
|
|
217
|
+
const completionRun = pendingTerminalEvent
|
|
218
|
+
? { ...run, events: [...run.events, pendingTerminalEvent] }
|
|
219
|
+
: run;
|
|
220
|
+
await onComplete(completionRun);
|
|
237
221
|
}
|
|
238
222
|
catch (err) {
|
|
239
223
|
completionError = err;
|
|
240
224
|
console.error("[run-manager] onComplete callback error:", err instanceof Error ? err.message : err);
|
|
241
225
|
}
|
|
242
226
|
}
|
|
243
|
-
//
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
clearTimeout(softTimeoutTimer);
|
|
247
|
-
// 4. Persist final status to SQL. If the completion callback threw,
|
|
248
|
-
// we'd rather mark the run errored than claim success with
|
|
249
|
-
// incomplete thread_data.
|
|
227
|
+
// 2. Compute final status. If the completion callback threw, we'd
|
|
228
|
+
// rather mark the run errored than claim success with incomplete
|
|
229
|
+
// thread_data.
|
|
250
230
|
const finalStatus = run.status === "aborted"
|
|
251
231
|
? "aborted"
|
|
252
232
|
: run.status === "errored" || completionError
|
|
253
233
|
? "errored"
|
|
254
234
|
: "completed";
|
|
235
|
+
// 3. Emit the terminal event only after thread_data is durable. Live
|
|
236
|
+
// SSE clients close on this event and usually fetch thread_data
|
|
237
|
+
// immediately, so emitting it earlier recreates the final-message
|
|
238
|
+
// race this manager is meant to avoid.
|
|
239
|
+
if (finalStatus === "completed" || finalStatus === "errored") {
|
|
240
|
+
const terminal = finalStatus === "completed"
|
|
241
|
+
? (pendingTerminalEvent ?? {
|
|
242
|
+
seq: run.events.length,
|
|
243
|
+
event: { type: "done" },
|
|
244
|
+
})
|
|
245
|
+
: pendingTerminalEvent?.event.type === "error"
|
|
246
|
+
? pendingTerminalEvent
|
|
247
|
+
: {
|
|
248
|
+
seq: pendingTerminalEvent?.seq ?? run.events.length,
|
|
249
|
+
event: {
|
|
250
|
+
type: "error",
|
|
251
|
+
error: completionError
|
|
252
|
+
? "Agent response could not be saved."
|
|
253
|
+
: "Agent run ended unexpectedly",
|
|
254
|
+
},
|
|
255
|
+
};
|
|
256
|
+
const last = run.events[run.events.length - 1];
|
|
257
|
+
if (!last || !isTerminalRunEvent(last.event)) {
|
|
258
|
+
emitRunEvent(terminal);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
for (const subscriber of run.subscribers) {
|
|
262
|
+
run.subscribers.delete(subscriber);
|
|
263
|
+
}
|
|
264
|
+
// 4. Stop the heartbeat — all liveness writes are done.
|
|
265
|
+
clearInterval(heartbeatTimer);
|
|
266
|
+
if (softTimeoutTimer)
|
|
267
|
+
clearTimeout(softTimeoutTimer);
|
|
268
|
+
// 5. Persist final status to SQL.
|
|
255
269
|
try {
|
|
256
270
|
await insertRunPromise;
|
|
257
271
|
await updateRunStatus(runId, finalStatus);
|
|
@@ -260,7 +274,7 @@ export function startRun(runId, threadId, runFn, onComplete, options) {
|
|
|
260
274
|
// Best-effort — reapIfStale will eventually clean this up via
|
|
261
275
|
// the heartbeat-stale path.
|
|
262
276
|
}
|
|
263
|
-
//
|
|
277
|
+
// 6. Schedule in-memory cleanup + opportunistic old-run pruning.
|
|
264
278
|
setTimeout(() => {
|
|
265
279
|
activeRuns.delete(runId);
|
|
266
280
|
if (threadToRun.get(threadId) === runId) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-manager.js","sourceRoot":"","sources":["../../src/agent/run-manager.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentChatEvent, RunEvent, RunStatus } from \"./types.js\";\nimport { EngineError } from \"./engine/types.js\";\nimport {\n insertRun,\n insertRunEvent,\n updateRunStatus,\n markRunAborted,\n getRunAbortState,\n getRunEventsSince,\n getRunById,\n getRunByThread,\n cleanupOldRuns,\n updateRunHeartbeat,\n reapIfStale,\n} from \"./run-store.js\";\n\nexport interface ActiveRun {\n runId: string;\n threadId: string;\n events: RunEvent[];\n status: RunStatus;\n subscribers: Set<(event: RunEvent) => void>;\n abort: AbortController;\n abortReason?: string;\n startedAt: number;\n}\n\nconst activeRuns = new Map<string, ActiveRun>();\nconst threadToRun = new Map<string, string>();\n\n/** How long to keep completed runs in memory before cleanup (5 min) */\nconst CLEANUP_DELAY_MS = 5 * 60 * 1000;\n\n/** Default run chunk budget for hosted/serverless deploys. */\nexport const DEFAULT_HOSTED_RUN_SOFT_TIMEOUT_MS = 55_000;\n\n/** Default SQL retention for completed/errored run event logs (24 hours). */\nexport const DEFAULT_COMPLETED_RUN_RETENTION_MS = 24 * 60 * 60 * 1000;\n\n/**\n * How recently a terminal run must have started for `/runs/active` to surface\n * it. Reconnect after this window won't replay the run — typical real-world\n * disconnects resolve in seconds, so 10 minutes is generous while keeping us\n * from resurrecting ancient turns when the user reopens an old thread.\n */\nexport const TERMINAL_RUN_RECONNECT_WINDOW_MS = 10 * 60 * 1000;\n\nexport interface StartRunOptions {\n /** Optional internal run chunk budget. When reached, the framework emits an\n * auto-continuation signal instead of a user-facing timeout. Leave unset for\n * no framework-imposed run timeout. */\n softTimeoutMs?: number;\n /** Opt into the hosted/serverless default chunk budget. Only callers with\n * automatic continuation support should enable this. */\n useHostedSoftTimeoutDefault?: boolean;\n}\n\nexport interface ResolveRunSoftTimeoutOptions {\n useHostedDefault?: boolean;\n}\n\nfunction isHostedRuntime(): boolean {\n if (\n process.env.NETLIFY &&\n process.env.NETLIFY !== \"false\" &&\n process.env.NETLIFY_LOCAL !== \"true\"\n ) {\n return true;\n }\n if (\n process.env.AWS_LAMBDA_FUNCTION_NAME &&\n process.env.NETLIFY_LOCAL !== \"true\"\n ) {\n return true;\n }\n return Boolean(\n process.env.CF_PAGES ||\n process.env.VERCEL ||\n process.env.VERCEL_ENV ||\n process.env.RENDER ||\n process.env.FLY_APP_NAME ||\n process.env.K_SERVICE,\n );\n}\n\nexport function resolveRunSoftTimeoutMs(\n overrideMs?: number,\n options?: ResolveRunSoftTimeoutOptions,\n): number {\n if (typeof overrideMs === \"number\" && Number.isFinite(overrideMs)) {\n return Math.max(0, overrideMs);\n }\n const envValue = process.env.AGENT_RUN_SOFT_TIMEOUT_MS;\n if (envValue !== undefined) {\n const raw = Number(envValue);\n if (Number.isFinite(raw) && raw >= 0) return raw;\n }\n return options?.useHostedDefault && isHostedRuntime()\n ? DEFAULT_HOSTED_RUN_SOFT_TIMEOUT_MS\n : 0;\n}\n\nexport function resolveCompletedRunRetentionMs(): number {\n const envValue = process.env.AGENT_RUN_RETENTION_MS;\n if (envValue !== undefined) {\n const raw = Number(envValue);\n if (Number.isFinite(raw) && raw >= 0) return raw;\n }\n return DEFAULT_COMPLETED_RUN_RETENTION_MS;\n}\n\nfunction isTerminalRunEvent(event: AgentChatEvent): boolean {\n return (\n event.type === \"done\" ||\n event.type === \"error\" ||\n event.type === \"missing_api_key\" ||\n event.type === \"loop_limit\" ||\n event.type === \"auto_continue\"\n );\n}\n\nfunction abortInMemoryRun(run: ActiveRun, reason: string = \"user\") {\n run.abortReason = reason;\n run.status = \"aborted\";\n if (threadToRun.get(run.threadId) === run.runId) {\n threadToRun.delete(run.threadId);\n }\n run.abort.abort(reason);\n for (const subscriber of run.subscribers) {\n try {\n subscriber({ seq: run.events.length, event: { type: \"done\" } });\n } catch {\n // ignore — subscriber is being removed below\n }\n }\n run.subscribers.clear();\n}\n\n/**\n * Start a new agent run in the background.\n * `runFn` receives a `send` callback and an `AbortSignal`.\n * The run continues even if all SSE subscribers disconnect.\n *\n * Events are persisted to SQL for cross-isolate access (Cloudflare Workers).\n */\nexport function startRun(\n runId: string,\n threadId: string,\n runFn: (\n send: (event: AgentChatEvent) => void,\n signal: AbortSignal,\n ) => Promise<void>,\n onComplete?: (run: ActiveRun) => void | Promise<void>,\n options?: StartRunOptions,\n): ActiveRun {\n // If there's already a run for this thread, abort it\n const existingRunId = threadToRun.get(threadId);\n if (existingRunId) {\n abortRun(existingRunId);\n }\n\n const abort = new AbortController();\n let softTimedOut = false;\n const run: ActiveRun = {\n runId,\n threadId,\n events: [],\n status: \"running\",\n subscribers: new Set(),\n abort,\n startedAt: Date.now(),\n };\n\n activeRuns.set(runId, run);\n threadToRun.set(threadId, runId);\n\n // Persist run to SQL without blocking the response. Keep the promise so\n // final status cannot race ahead of a slow initial INSERT and then get\n // overwritten by a late row stuck at status='running'.\n const insertRunPromise = insertRun(runId, threadId).catch(() => {});\n\n // Periodic SQL abort check interval (for cross-isolate abort on Workers)\n let lastAbortCheck = Date.now() - 3000;\n const checkSqlAbort = () => {\n const now = Date.now();\n if (now - lastAbortCheck < 3000) return;\n lastAbortCheck = now;\n getRunAbortState(runId)\n .then((state) => {\n if (state.aborted && !abort.signal.aborted) {\n abortInMemoryRun(run, state.reason ?? \"user\");\n }\n })\n .catch(() => {});\n };\n\n // Heartbeat: bump heartbeat_at every 1.5s so watchers can detect a dead\n // producer (process crash, HMR restart, isolate eviction) quickly and\n // reap the row. Paired with RUN_STALE_MS (6s) — 4x the interval to\n // tolerate transient DB slowness without false positives.\n const heartbeatTimer: ReturnType<typeof setInterval> = setInterval(() => {\n updateRunHeartbeat(runId).catch(() => {});\n checkSqlAbort();\n }, 1500);\n const softTimeoutMs = resolveRunSoftTimeoutMs(options?.softTimeoutMs, {\n useHostedDefault: options?.useHostedSoftTimeoutDefault === true,\n });\n const softTimeoutTimer =\n softTimeoutMs > 0\n ? setTimeout(() => {\n if (run.status !== \"running\" || abort.signal.aborted) return;\n softTimedOut = true;\n send({\n type: \"auto_continue\",\n reason: \"run_timeout\",\n });\n abort.abort();\n }, softTimeoutMs)\n : null;\n\n const send = (event: AgentChatEvent) => {\n if (run.status === \"aborted\" && abort.signal.aborted) return;\n\n const runEvent: RunEvent = { seq: run.events.length, event };\n run.events.push(runEvent);\n\n // Notify in-memory subscribers (same isolate, fast path)\n for (const subscriber of run.subscribers) {\n try {\n subscriber(runEvent);\n } catch {\n run.subscribers.delete(subscriber);\n }\n }\n\n // Persist event to SQL (fire-and-forget)\n insertRunEvent(runId, runEvent.seq, JSON.stringify(event)).catch(() => {});\n\n checkSqlAbort();\n };\n\n // Run in background — intentionally detached from any HTTP connection\n const runPromise = runFn(send, abort.signal)\n .then(() => {\n if (abort.signal.aborted) {\n run.status = softTimedOut ? \"completed\" : \"aborted\";\n return;\n }\n run.status = \"completed\";\n })\n .catch((err) => {\n // Don't surface abort errors — the run was intentionally stopped\n if (abort.signal.aborted) {\n run.status = softTimedOut ? \"completed\" : \"aborted\";\n return;\n }\n run.status = \"errored\";\n send({\n type: \"error\",\n error: err?.message ?? \"Unknown error\",\n ...(err instanceof EngineError && err.errorCode\n ? { errorCode: err.errorCode }\n : {}),\n ...(err instanceof EngineError && err.upgradeUrl\n ? { upgradeUrl: err.upgradeUrl }\n : {}),\n });\n })\n .finally(async () => {\n // Ordering matters here — this is the atomic-complete boundary.\n // Invariant: once agent_runs.status flips to \"completed\"/\"errored\"\n // in SQL, thread_data for this turn is already durable. This lets\n // reconnecting clients trust the simple rule \"status != running →\n // fetch thread_data\" without polling/retrying for a race window\n // where onComplete was still pending.\n\n // 1. Emit terminal event to live subscribers + SQL event log so\n // in-flight SSE streams close promptly. Thread-data save below\n // runs in parallel with subscribers disconnecting.\n if (run.status === \"errored\" || run.status === \"completed\") {\n const terminal: RunEvent = {\n seq: run.events.length,\n event:\n run.status === \"errored\"\n ? { type: \"error\", error: \"Agent run ended unexpectedly\" }\n : { type: \"done\" },\n };\n const last = run.events[run.events.length - 1];\n if (!last || !isTerminalRunEvent(last.event)) {\n run.events.push(terminal);\n insertRunEvent(\n runId,\n terminal.seq,\n JSON.stringify(terminal.event),\n ).catch(() => {});\n for (const subscriber of run.subscribers) {\n try {\n subscriber(terminal);\n } catch {\n // ignore — subscriber will be cleaned up below\n }\n }\n }\n }\n for (const subscriber of run.subscribers) {\n run.subscribers.delete(subscriber);\n }\n\n // 2. Await the completion callback (thread_data save). Heartbeat is\n // still ticking so the run doesn't look stale to any concurrent\n // /runs/active check while we wait for SQL writes to land.\n let completionError: unknown = null;\n if (\n onComplete &&\n !(run.status === \"aborted\" && run.abortReason === \"no_progress\")\n ) {\n try {\n await onComplete(run);\n } catch (err) {\n completionError = err;\n console.error(\n \"[run-manager] onComplete callback error:\",\n err instanceof Error ? err.message : err,\n );\n }\n }\n\n // 3. Stop the heartbeat — all liveness writes are done.\n clearInterval(heartbeatTimer);\n if (softTimeoutTimer) clearTimeout(softTimeoutTimer);\n\n // 4. Persist final status to SQL. If the completion callback threw,\n // we'd rather mark the run errored than claim success with\n // incomplete thread_data.\n const finalStatus =\n run.status === \"aborted\"\n ? \"aborted\"\n : run.status === \"errored\" || completionError\n ? \"errored\"\n : \"completed\";\n try {\n await insertRunPromise;\n await updateRunStatus(runId, finalStatus);\n } catch {\n // Best-effort — reapIfStale will eventually clean this up via\n // the heartbeat-stale path.\n }\n\n // 5. Schedule in-memory cleanup + opportunistic old-run pruning.\n setTimeout(() => {\n activeRuns.delete(runId);\n if (threadToRun.get(threadId) === runId) {\n threadToRun.delete(threadId);\n }\n }, CLEANUP_DELAY_MS);\n cleanupOldRuns(resolveCompletedRunRetentionMs()).catch(() => {});\n });\n\n // On Cloudflare Workers, keep the isolate alive for this run\n try {\n const cfCtx = globalThis.__cf_ctx;\n if (cfCtx?.waitUntil) {\n cfCtx.waitUntil(runPromise);\n }\n } catch {\n // Not on Workers — ignore\n }\n\n return run;\n}\n\n/**\n * Subscribe to a run's events starting from `fromSeq`.\n * Returns a ReadableStream that replays buffered events then live-tails.\n * Cancelling the stream only unsubscribes — does NOT abort the agent.\n *\n * Falls back to SQL polling when the run is not in local memory\n * (cross-isolate reconnection on Workers).\n */\nexport function subscribeToRun(\n runId: string,\n fromSeq: number,\n): ReadableStream<Uint8Array> | null {\n const run = activeRuns.get(runId);\n if (run) {\n return subscribeInMemory(run, fromSeq);\n }\n // Not in local memory — try SQL (cross-isolate path)\n return subscribeFromSQL(runId, fromSeq);\n}\n\n/** In-memory subscription (same isolate, fast path) */\nfunction subscribeInMemory(\n run: ActiveRun,\n fromSeq: number,\n): ReadableStream<Uint8Array> {\n const encoder = new TextEncoder();\n let subscriberRef: ((event: RunEvent) => void) | null = null;\n let pingTimer: ReturnType<typeof setInterval> | null = null;\n\n return new ReadableStream({\n start(controller) {\n const ping = () => {\n try {\n controller.enqueue(encoder.encode(`: ping ${Date.now()}\\n\\n`));\n } catch {\n if (subscriberRef) run.subscribers.delete(subscriberRef);\n if (pingTimer) clearInterval(pingTimer);\n }\n };\n ping();\n pingTimer = setInterval(ping, 10_000);\n\n // Replay buffered events from fromSeq\n for (let i = fromSeq; i < run.events.length; i++) {\n try {\n controller.enqueue(\n encoder.encode(\n `data: ${JSON.stringify({ ...run.events[i].event, seq: run.events[i].seq })}\\n\\n`,\n ),\n );\n } catch {\n return;\n }\n }\n\n // If run is already done, close immediately\n if (run.status !== \"running\") {\n if (pingTimer) clearInterval(pingTimer);\n controller.close();\n return;\n }\n\n // Subscribe to live events\n subscriberRef = (event: RunEvent) => {\n try {\n controller.enqueue(\n encoder.encode(\n `data: ${JSON.stringify({ ...event.event, seq: event.seq })}\\n\\n`,\n ),\n );\n // Close stream after terminal events\n if (isTerminalRunEvent(event.event)) {\n run.subscribers.delete(subscriberRef!);\n if (pingTimer) clearInterval(pingTimer);\n controller.close();\n }\n } catch {\n run.subscribers.delete(subscriberRef!);\n }\n };\n\n run.subscribers.add(subscriberRef);\n },\n cancel() {\n // Only unsubscribe — do NOT abort the agent run\n if (subscriberRef) run.subscribers.delete(subscriberRef);\n if (pingTimer) clearInterval(pingTimer);\n },\n });\n}\n\n/** SQL-based subscription (cross-isolate, polling) */\nfunction subscribeFromSQL(\n runId: string,\n fromSeq: number,\n): ReadableStream<Uint8Array> | null {\n const encoder = new TextEncoder();\n let cancelled = false;\n let pollTimer: ReturnType<typeof setTimeout> | null = null;\n let pingTimer: ReturnType<typeof setInterval> | null = null;\n\n return new ReadableStream({\n async start(controller) {\n let lastSeq = fromSeq;\n const ping = () => {\n try {\n controller.enqueue(encoder.encode(`: ping ${Date.now()}\\n\\n`));\n } catch {\n cancelled = true;\n if (pingTimer) clearInterval(pingTimer);\n }\n };\n ping();\n pingTimer = setInterval(ping, 10_000);\n\n const poll = async () => {\n if (cancelled) return;\n try {\n // Read new events from SQL\n const events = await getRunEventsSince(runId, lastSeq);\n for (const { seq, eventData } of events) {\n let parsed: any;\n try {\n parsed = JSON.parse(eventData);\n } catch {\n continue;\n }\n try {\n controller.enqueue(\n encoder.encode(\n `data: ${JSON.stringify({ ...parsed, seq })}\\n\\n`,\n ),\n );\n } catch {\n cancelled = true;\n return;\n }\n lastSeq = seq + 1;\n\n // Close on terminal events\n if (isTerminalRunEvent(parsed)) {\n if (pingTimer) clearInterval(pingTimer);\n controller.close();\n return;\n }\n }\n\n // Check if run completed (no terminal event but status changed)\n if (events.length === 0) {\n // Opportunistically reap a stale producer before trusting SQL's\n // \"running\" status — otherwise a crashed server leaves us polling\n // forever.\n await reapIfStale(runId).catch(() => {});\n const run = await getRunById(runId);\n if (!run || run.status !== \"running\") {\n // Run ended — do one final event read, then close\n const finalEvents = await getRunEventsSince(runId, lastSeq);\n for (const { seq, eventData } of finalEvents) {\n let parsed: any;\n try {\n parsed = JSON.parse(eventData);\n } catch {\n continue;\n }\n try {\n controller.enqueue(\n encoder.encode(\n `data: ${JSON.stringify({ ...parsed, seq })}\\n\\n`,\n ),\n );\n } catch {\n cancelled = true;\n return;\n }\n lastSeq = seq + 1;\n if (isTerminalRunEvent(parsed)) {\n if (pingTimer) clearInterval(pingTimer);\n controller.close();\n return;\n }\n }\n if (run?.status === \"aborted\") {\n try {\n controller.enqueue(\n encoder.encode(\n `data: ${JSON.stringify({ type: \"done\", seq: lastSeq })}\\n\\n`,\n ),\n );\n } catch {\n cancelled = true;\n return;\n }\n } else if (run?.status === \"completed\") {\n try {\n controller.enqueue(\n encoder.encode(\n `data: ${JSON.stringify({ type: \"done\", seq: lastSeq })}\\n\\n`,\n ),\n );\n } catch {\n cancelled = true;\n return;\n }\n } else if (run?.status === \"errored\") {\n try {\n controller.enqueue(\n encoder.encode(\n `data: ${JSON.stringify({\n type: \"error\",\n error:\n \"Agent run ended before its final error event was persisted.\",\n errorCode: \"run_terminal_event_missing\",\n details:\n \"The persisted run status is errored, but no terminal SSE event was available during reconnect.\",\n seq: lastSeq,\n })}\\n\\n`,\n ),\n );\n } catch {\n cancelled = true;\n return;\n }\n }\n if (pingTimer) clearInterval(pingTimer);\n controller.close();\n return;\n }\n }\n\n // Schedule next poll\n if (!cancelled) {\n pollTimer = setTimeout(poll, 500);\n }\n } catch {\n // SQL error — close stream\n try {\n if (pingTimer) clearInterval(pingTimer);\n controller.close();\n } catch {}\n }\n };\n\n // Verify run exists before starting poll\n try {\n const run = await getRunById(runId);\n if (!run) {\n if (pingTimer) clearInterval(pingTimer);\n controller.close();\n return;\n }\n } catch {\n controller.close();\n return;\n }\n\n await poll();\n },\n cancel() {\n cancelled = true;\n if (pollTimer) clearTimeout(pollTimer);\n if (pingTimer) clearInterval(pingTimer);\n },\n });\n}\n\n/** Get the active run for a thread (if any) — checks memory then SQL */\nexport function getActiveRunForThread(threadId: string): ActiveRun | null {\n const runId = threadToRun.get(threadId);\n if (runId) {\n const run = activeRuns.get(runId);\n if (run) return run;\n }\n return null;\n}\n\n/**\n * Async version that also checks SQL — for cross-isolate access.\n * Used by the /runs/active endpoint.\n *\n * Returns `heartbeatAt` so the client can independently decide a run is\n * dead even before the server-side stale reap has fired.\n */\nexport async function getActiveRunForThreadAsync(threadId: string): Promise<{\n runId: string;\n threadId: string;\n status: string;\n heartbeatAt: number;\n} | null> {\n // Check memory first — return both running AND recently-completed runs\n // that still have events in memory. This allows sub-agent tabs to replay\n // the full conversation from completed runs via SSE.\n const memRun = getActiveRunForThread(threadId);\n if (memRun && (memRun.status === \"running\" || memRun.events.length > 0)) {\n return {\n runId: memRun.runId,\n threadId: memRun.threadId,\n status: memRun.status,\n // In-memory means this isolate is the producer. By definition, the\n // heartbeat is fresh as of \"now\" — the client can trust this.\n heartbeatAt: Date.now(),\n };\n }\n // Fall back to SQL — also surface recently terminated runs so the client\n // can reconnect and replay synthesized done/error events instead of\n // retrying the original POST. Without this, a POST that fails after the\n // server already accepted (and finished) the run would re-execute the\n // turn and double-apply mutations: the in-memory branch above already\n // returns terminal runs whose events are still buffered, but the SQL\n // path is the only authority once memory has been evicted.\n try {\n const sqlRun = await getRunByThread(threadId, { includeTerminal: true });\n if (!sqlRun) return null;\n if (sqlRun.status === \"running\") {\n // If the producer is dead (no recent heartbeat), reap before the\n // client can see a stale \"running\" status and enter a reconnect\n // loop it can never exit.\n const reaped = await reapIfStale(sqlRun.id).catch(() => false);\n if (reaped) return null;\n return {\n runId: sqlRun.id,\n threadId: sqlRun.threadId,\n status: sqlRun.status,\n heartbeatAt: sqlRun.heartbeatAt ?? sqlRun.startedAt,\n };\n }\n if (sqlRun.status === \"completed\" || sqlRun.status === \"errored\") {\n // Cap how far back we'll surface terminal runs as \"active\". The goal\n // is to catch the recently-completed-but-reconnecting case, not to\n // resurrect ancient turns when the user reopens an old thread.\n //\n // Measure age from the run's terminal timestamp, not its start. A\n // long-running task that ran 11 minutes and completed five seconds\n // ago should still be reachable — the client's disconnect happened\n // around completion, so completion time is what matters for the\n // \"is the user still here waiting?\" question. Fall back to the last\n // heartbeat (older deployments may have unset completed_at) and\n // finally to startedAt for ancient rows.\n const referenceAt =\n sqlRun.completedAt ?? sqlRun.heartbeatAt ?? sqlRun.startedAt;\n const terminalAge = Date.now() - referenceAt;\n if (terminalAge > TERMINAL_RUN_RECONNECT_WINDOW_MS) return null;\n return {\n runId: sqlRun.id,\n threadId: sqlRun.threadId,\n status: sqlRun.status,\n heartbeatAt: sqlRun.heartbeatAt ?? sqlRun.startedAt,\n };\n }\n } catch {\n // SQL error — fall through\n }\n return null;\n}\n\n/** Get a run by ID */\nexport function getRun(runId: string): ActiveRun | null {\n return activeRuns.get(runId) ?? null;\n}\n\n/** Explicitly abort a run (e.g. Stop button) */\nexport function abortRun(runId: string, reason: string = \"user\"): boolean {\n const run = activeRuns.get(runId);\n if (run) {\n abortInMemoryRun(run, reason);\n }\n // Also mark as aborted in SQL (for cross-isolate abort on Workers)\n markRunAborted(runId, reason).catch(() => {});\n return !!run;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"run-manager.js","sourceRoot":"","sources":["../../src/agent/run-manager.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EACL,SAAS,EACT,cAAc,EACd,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,UAAU,EACV,cAAc,EACd,cAAc,EACd,kBAAkB,EAClB,WAAW,GACZ,MAAM,gBAAgB,CAAC;AAaxB,MAAM,UAAU,GAAG,IAAI,GAAG,EAAqB,CAAC;AAChD,MAAM,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAC;AAE9C,uEAAuE;AACvE,MAAM,gBAAgB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AAEvC,8DAA8D;AAC9D,MAAM,CAAC,MAAM,kCAAkC,GAAG,MAAM,CAAC;AAEzD,6EAA6E;AAC7E,MAAM,CAAC,MAAM,kCAAkC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAEtE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gCAAgC,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAgB/D,SAAS,eAAe;IACtB,IACE,OAAO,CAAC,GAAG,CAAC,OAAO;QACnB,OAAO,CAAC,GAAG,CAAC,OAAO,KAAK,OAAO;QAC/B,OAAO,CAAC,GAAG,CAAC,aAAa,KAAK,MAAM,EACpC,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IACE,OAAO,CAAC,GAAG,CAAC,wBAAwB;QACpC,OAAO,CAAC,GAAG,CAAC,aAAa,KAAK,MAAM,EACpC,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,OAAO,CACZ,OAAO,CAAC,GAAG,CAAC,QAAQ;QACpB,OAAO,CAAC,GAAG,CAAC,MAAM;QAClB,OAAO,CAAC,GAAG,CAAC,UAAU;QACtB,OAAO,CAAC,GAAG,CAAC,MAAM;QAClB,OAAO,CAAC,GAAG,CAAC,YAAY;QACxB,OAAO,CAAC,GAAG,CAAC,SAAS,CACtB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,uBAAuB,CACrC,UAAmB,EACnB,OAAsC;IAEtC,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QAClE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;IACjC,CAAC;IACD,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC;IACvD,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,MAAM,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC7B,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;YAAE,OAAO,GAAG,CAAC;IACnD,CAAC;IACD,OAAO,OAAO,EAAE,gBAAgB,IAAI,eAAe,EAAE;QACnD,CAAC,CAAC,kCAAkC;QACpC,CAAC,CAAC,CAAC,CAAC;AACR,CAAC;AAED,MAAM,UAAU,8BAA8B;IAC5C,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC;IACpD,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,MAAM,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC7B,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;YAAE,OAAO,GAAG,CAAC;IACnD,CAAC;IACD,OAAO,kCAAkC,CAAC;AAC5C,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAqB;IAC/C,OAAO,CACL,KAAK,CAAC,IAAI,KAAK,MAAM;QACrB,KAAK,CAAC,IAAI,KAAK,OAAO;QACtB,KAAK,CAAC,IAAI,KAAK,iBAAiB;QAChC,KAAK,CAAC,IAAI,KAAK,YAAY;QAC3B,KAAK,CAAC,IAAI,KAAK,eAAe,CAC/B,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CAAC,GAAc,EAAE,SAAiB,MAAM;IAC/D,GAAG,CAAC,WAAW,GAAG,MAAM,CAAC;IACzB,GAAG,CAAC,MAAM,GAAG,SAAS,CAAC;IACvB,IAAI,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,GAAG,CAAC,KAAK,EAAE,CAAC;QAChD,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACnC,CAAC;IACD,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACxB,KAAK,MAAM,UAAU,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC;QACzC,IAAI,CAAC;YACH,UAAU,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;QAClE,CAAC;QAAC,MAAM,CAAC;YACP,6CAA6C;QAC/C,CAAC;IACH,CAAC;IACD,GAAG,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC;AAC1B,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,QAAQ,CACtB,KAAa,EACb,QAAgB,EAChB,KAGkB,EAClB,UAAqD,EACrD,OAAyB;IAEzB,qDAAqD;IACrD,MAAM,aAAa,GAAG,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAChD,IAAI,aAAa,EAAE,CAAC;QAClB,QAAQ,CAAC,aAAa,CAAC,CAAC;IAC1B,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,eAAe,EAAE,CAAC;IACpC,IAAI,YAAY,GAAG,KAAK,CAAC;IACzB,MAAM,GAAG,GAAc;QACrB,KAAK;QACL,QAAQ;QACR,MAAM,EAAE,EAAE;QACV,MAAM,EAAE,SAAS;QACjB,WAAW,EAAE,IAAI,GAAG,EAAE;QACtB,KAAK;QACL,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;KACtB,CAAC;IAEF,UAAU,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC3B,WAAW,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAEjC,wEAAwE;IACxE,uEAAuE;IACvE,uDAAuD;IACvD,MAAM,gBAAgB,GAAG,SAAS,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAEpE,yEAAyE;IACzE,IAAI,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;IACvC,MAAM,aAAa,GAAG,GAAG,EAAE;QACzB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,IAAI,GAAG,GAAG,cAAc,GAAG,IAAI;YAAE,OAAO;QACxC,cAAc,GAAG,GAAG,CAAC;QACrB,gBAAgB,CAAC,KAAK,CAAC;aACpB,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE;YACd,IAAI,KAAK,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBAC3C,gBAAgB,CAAC,GAAG,EAAE,KAAK,CAAC,MAAM,IAAI,MAAM,CAAC,CAAC;YAChD,CAAC;QACH,CAAC,CAAC;aACD,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACrB,CAAC,CAAC;IAEF,wEAAwE;IACxE,sEAAsE;IACtE,mEAAmE;IACnE,0DAA0D;IAC1D,MAAM,cAAc,GAAmC,WAAW,CAAC,GAAG,EAAE;QACtE,kBAAkB,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAC1C,aAAa,EAAE,CAAC;IAClB,CAAC,EAAE,IAAI,CAAC,CAAC;IACT,MAAM,aAAa,GAAG,uBAAuB,CAAC,OAAO,EAAE,aAAa,EAAE;QACpE,gBAAgB,EAAE,OAAO,EAAE,2BAA2B,KAAK,IAAI;KAChE,CAAC,CAAC;IACH,MAAM,gBAAgB,GACpB,aAAa,GAAG,CAAC;QACf,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE;YACd,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,CAAC,OAAO;gBAAE,OAAO;YAC7D,YAAY,GAAG,IAAI,CAAC;YACpB,IAAI,CAAC;gBACH,IAAI,EAAE,eAAe;gBACrB,MAAM,EAAE,aAAa;aACtB,CAAC,CAAC;YACH,KAAK,CAAC,KAAK,EAAE,CAAC;QAChB,CAAC,EAAE,aAAa,CAAC;QACnB,CAAC,CAAC,IAAI,CAAC;IACX,IAAI,oBAAoB,GAAoB,IAAI,CAAC;IAEjD,MAAM,YAAY,GAAG,CAAC,QAAkB,EAAE,EAAE;QAC1C,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAE1B,yDAAyD;QACzD,KAAK,MAAM,UAAU,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC;YACzC,IAAI,CAAC;gBACH,UAAU,CAAC,QAAQ,CAAC,CAAC;YACvB,CAAC;YAAC,MAAM,CAAC;gBACP,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YACrC,CAAC;QACH,CAAC;QAED,yCAAyC;QACzC,cAAc,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CACvE,GAAG,EAAE,GAAE,CAAC,CACT,CAAC;QAEF,aAAa,EAAE,CAAC;IAClB,CAAC,CAAC;IAEF,MAAM,IAAI,GAAG,CAAC,KAAqB,EAAE,EAAE;QACrC,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,CAAC,OAAO;YAAE,OAAO;QAE7D,MAAM,QAAQ,GAAa,EAAE,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC;QAC7D,IAAI,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC;YAC9B,oBAAoB,GAAG,QAAQ,CAAC;YAChC,OAAO;QACT,CAAC;QAED,YAAY,CAAC,QAAQ,CAAC,CAAC;IACzB,CAAC,CAAC;IAEF,sEAAsE;IACtE,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC;SACzC,IAAI,CAAC,GAAG,EAAE;QACT,IAAI,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACzB,GAAG,CAAC,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC;YACpD,OAAO;QACT,CAAC;QACD,GAAG,CAAC,MAAM,GAAG,WAAW,CAAC;IAC3B,CAAC,CAAC;SACD,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;QACb,iEAAiE;QACjE,IAAI,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACzB,GAAG,CAAC,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC;YACpD,OAAO;QACT,CAAC;QACD,GAAG,CAAC,MAAM,GAAG,SAAS,CAAC;QACvB,IAAI,CAAC;YACH,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,GAAG,EAAE,OAAO,IAAI,eAAe;YACtC,GAAG,CAAC,GAAG,YAAY,WAAW,IAAI,GAAG,CAAC,SAAS;gBAC7C,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE;gBAC9B,CAAC,CAAC,EAAE,CAAC;YACP,GAAG,CAAC,GAAG,YAAY,WAAW,IAAI,GAAG,CAAC,UAAU;gBAC9C,CAAC,CAAC,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE;gBAChC,CAAC,CAAC,EAAE,CAAC;SACR,CAAC,CAAC;IACL,CAAC,CAAC;SACD,OAAO,CAAC,KAAK,IAAI,EAAE;QAClB,gEAAgE;QAChE,mEAAmE;QACnE,kEAAkE;QAClE,kEAAkE;QAClE,gEAAgE;QAChE,sCAAsC;QAEtC,oEAAoE;QACpE,mEAAmE;QACnE,8DAA8D;QAC9D,IAAI,eAAe,GAAY,IAAI,CAAC;QACpC,IACE,UAAU;YACV,CAAC,CAAC,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,GAAG,CAAC,WAAW,KAAK,aAAa,CAAC,EAChE,CAAC;YACD,IAAI,CAAC;gBACH,MAAM,aAAa,GAAc,oBAAoB;oBACnD,CAAC,CAAC,EAAE,GAAG,GAAG,EAAE,MAAM,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,oBAAoB,CAAC,EAAE;oBAC3D,CAAC,CAAC,GAAG,CAAC;gBACR,MAAM,UAAU,CAAC,aAAa,CAAC,CAAC;YAClC,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,eAAe,GAAG,GAAG,CAAC;gBACtB,OAAO,CAAC,KAAK,CACX,0CAA0C,EAC1C,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CACzC,CAAC;YACJ,CAAC;QACH,CAAC;QAED,kEAAkE;QAClE,oEAAoE;QACpE,kBAAkB;QAClB,MAAM,WAAW,GACf,GAAG,CAAC,MAAM,KAAK,SAAS;YACtB,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,eAAe;gBAC3C,CAAC,CAAC,SAAS;gBACX,CAAC,CAAC,WAAW,CAAC;QAEpB,qEAAqE;QACrE,mEAAmE;QACnE,qEAAqE;QACrE,0CAA0C;QAC1C,IAAI,WAAW,KAAK,WAAW,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YAC7D,MAAM,QAAQ,GACZ,WAAW,KAAK,WAAW;gBACzB,CAAC,CAAC,CAAC,oBAAoB,IAAI;oBACvB,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,MAAM;oBACtB,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;iBACxB,CAAC;gBACJ,CAAC,CAAC,oBAAoB,EAAE,KAAK,CAAC,IAAI,KAAK,OAAO;oBAC5C,CAAC,CAAC,oBAAoB;oBACtB,CAAC,CAAC;wBACE,GAAG,EAAE,oBAAoB,EAAE,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM;wBACnD,KAAK,EAAE;4BACL,IAAI,EAAE,OAAO;4BACb,KAAK,EAAE,eAAe;gCACpB,CAAC,CAAC,oCAAoC;gCACtC,CAAC,CAAC,8BAA8B;yBACnC;qBACF,CAAC;YACV,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAC/C,IAAI,CAAC,IAAI,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC7C,YAAY,CAAC,QAAQ,CAAC,CAAC;YACzB,CAAC;QACH,CAAC;QACD,KAAK,MAAM,UAAU,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC;YACzC,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QACrC,CAAC;QAED,wDAAwD;QACxD,aAAa,CAAC,cAAc,CAAC,CAAC;QAC9B,IAAI,gBAAgB;YAAE,YAAY,CAAC,gBAAgB,CAAC,CAAC;QAErD,kCAAkC;QAClC,IAAI,CAAC;YACH,MAAM,gBAAgB,CAAC;YACvB,MAAM,eAAe,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;QAC5C,CAAC;QAAC,MAAM,CAAC;YACP,8DAA8D;YAC9D,4BAA4B;QAC9B,CAAC;QAED,iEAAiE;QACjE,UAAU,CAAC,GAAG,EAAE;YACd,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACzB,IAAI,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,KAAK,EAAE,CAAC;gBACxC,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC/B,CAAC;QACH,CAAC,EAAE,gBAAgB,CAAC,CAAC;QACrB,cAAc,CAAC,8BAA8B,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;IAEL,6DAA6D;IAC7D,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,UAAU,CAAC,QAAQ,CAAC;QAClC,IAAI,KAAK,EAAE,SAAS,EAAE,CAAC;YACrB,KAAK,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,0BAA0B;IAC5B,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAC5B,KAAa,EACb,OAAe;IAEf,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAClC,IAAI,GAAG,EAAE,CAAC;QACR,OAAO,iBAAiB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACzC,CAAC;IACD,qDAAqD;IACrD,OAAO,gBAAgB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;AAC1C,CAAC;AAED,uDAAuD;AACvD,SAAS,iBAAiB,CACxB,GAAc,EACd,OAAe;IAEf,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;IAClC,IAAI,aAAa,GAAuC,IAAI,CAAC;IAC7D,IAAI,SAAS,GAA0C,IAAI,CAAC;IAE5D,OAAO,IAAI,cAAc,CAAC;QACxB,KAAK,CAAC,UAAU;YACd,MAAM,IAAI,GAAG,GAAG,EAAE;gBAChB,IAAI,CAAC;oBACH,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC;gBACjE,CAAC;gBAAC,MAAM,CAAC;oBACP,IAAI,aAAa;wBAAE,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;oBACzD,IAAI,SAAS;wBAAE,aAAa,CAAC,SAAS,CAAC,CAAC;gBAC1C,CAAC;YACH,CAAC,CAAC;YACF,IAAI,EAAE,CAAC;YACP,SAAS,GAAG,WAAW,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAEtC,sCAAsC;YACtC,KAAK,IAAI,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACjD,IAAI,CAAC;oBACH,UAAU,CAAC,OAAO,CAChB,OAAO,CAAC,MAAM,CACZ,SAAS,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,MAAM,CAClF,CACF,CAAC;gBACJ,CAAC;gBAAC,MAAM,CAAC;oBACP,OAAO;gBACT,CAAC;YACH,CAAC;YAED,4CAA4C;YAC5C,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBAC7B,IAAI,SAAS;oBAAE,aAAa,CAAC,SAAS,CAAC,CAAC;gBACxC,UAAU,CAAC,KAAK,EAAE,CAAC;gBACnB,OAAO;YACT,CAAC;YAED,2BAA2B;YAC3B,aAAa,GAAG,CAAC,KAAe,EAAE,EAAE;gBAClC,IAAI,CAAC;oBACH,UAAU,CAAC,OAAO,CAChB,OAAO,CAAC,MAAM,CACZ,SAAS,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,KAAK,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,MAAM,CAClE,CACF,CAAC;oBACF,qCAAqC;oBACrC,IAAI,kBAAkB,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;wBACpC,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,aAAc,CAAC,CAAC;wBACvC,IAAI,SAAS;4BAAE,aAAa,CAAC,SAAS,CAAC,CAAC;wBACxC,UAAU,CAAC,KAAK,EAAE,CAAC;oBACrB,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,aAAc,CAAC,CAAC;gBACzC,CAAC;YACH,CAAC,CAAC;YAEF,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QACrC,CAAC;QACD,MAAM;YACJ,gDAAgD;YAChD,IAAI,aAAa;gBAAE,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;YACzD,IAAI,SAAS;gBAAE,aAAa,CAAC,SAAS,CAAC,CAAC;QAC1C,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED,sDAAsD;AACtD,SAAS,gBAAgB,CACvB,KAAa,EACb,OAAe;IAEf,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;IAClC,IAAI,SAAS,GAAG,KAAK,CAAC;IACtB,IAAI,SAAS,GAAyC,IAAI,CAAC;IAC3D,IAAI,SAAS,GAA0C,IAAI,CAAC;IAE5D,OAAO,IAAI,cAAc,CAAC;QACxB,KAAK,CAAC,KAAK,CAAC,UAAU;YACpB,IAAI,OAAO,GAAG,OAAO,CAAC;YACtB,MAAM,IAAI,GAAG,GAAG,EAAE;gBAChB,IAAI,CAAC;oBACH,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC;gBACjE,CAAC;gBAAC,MAAM,CAAC;oBACP,SAAS,GAAG,IAAI,CAAC;oBACjB,IAAI,SAAS;wBAAE,aAAa,CAAC,SAAS,CAAC,CAAC;gBAC1C,CAAC;YACH,CAAC,CAAC;YACF,IAAI,EAAE,CAAC;YACP,SAAS,GAAG,WAAW,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAEtC,MAAM,IAAI,GAAG,KAAK,IAAI,EAAE;gBACtB,IAAI,SAAS;oBAAE,OAAO;gBACtB,IAAI,CAAC;oBACH,2BAA2B;oBAC3B,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;oBACvD,KAAK,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,MAAM,EAAE,CAAC;wBACxC,IAAI,MAAW,CAAC;wBAChB,IAAI,CAAC;4BACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;wBACjC,CAAC;wBAAC,MAAM,CAAC;4BACP,SAAS;wBACX,CAAC;wBACD,IAAI,CAAC;4BACH,UAAU,CAAC,OAAO,CAChB,OAAO,CAAC,MAAM,CACZ,SAAS,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,CAClD,CACF,CAAC;wBACJ,CAAC;wBAAC,MAAM,CAAC;4BACP,SAAS,GAAG,IAAI,CAAC;4BACjB,OAAO;wBACT,CAAC;wBACD,OAAO,GAAG,GAAG,GAAG,CAAC,CAAC;wBAElB,2BAA2B;wBAC3B,IAAI,kBAAkB,CAAC,MAAM,CAAC,EAAE,CAAC;4BAC/B,IAAI,SAAS;gCAAE,aAAa,CAAC,SAAS,CAAC,CAAC;4BACxC,UAAU,CAAC,KAAK,EAAE,CAAC;4BACnB,OAAO;wBACT,CAAC;oBACH,CAAC;oBAED,gEAAgE;oBAChE,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;wBACxB,gEAAgE;wBAChE,kEAAkE;wBAClE,WAAW;wBACX,MAAM,WAAW,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;wBACzC,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,CAAC;wBACpC,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;4BACrC,kDAAkD;4BAClD,MAAM,WAAW,GAAG,MAAM,iBAAiB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;4BAC5D,KAAK,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,WAAW,EAAE,CAAC;gCAC7C,IAAI,MAAW,CAAC;gCAChB,IAAI,CAAC;oCACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;gCACjC,CAAC;gCAAC,MAAM,CAAC;oCACP,SAAS;gCACX,CAAC;gCACD,IAAI,CAAC;oCACH,UAAU,CAAC,OAAO,CAChB,OAAO,CAAC,MAAM,CACZ,SAAS,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,CAClD,CACF,CAAC;gCACJ,CAAC;gCAAC,MAAM,CAAC;oCACP,SAAS,GAAG,IAAI,CAAC;oCACjB,OAAO;gCACT,CAAC;gCACD,OAAO,GAAG,GAAG,GAAG,CAAC,CAAC;gCAClB,IAAI,kBAAkB,CAAC,MAAM,CAAC,EAAE,CAAC;oCAC/B,IAAI,SAAS;wCAAE,aAAa,CAAC,SAAS,CAAC,CAAC;oCACxC,UAAU,CAAC,KAAK,EAAE,CAAC;oCACnB,OAAO;gCACT,CAAC;4BACH,CAAC;4BACD,IAAI,GAAG,EAAE,MAAM,KAAK,SAAS,EAAE,CAAC;gCAC9B,IAAI,CAAC;oCACH,UAAU,CAAC,OAAO,CAChB,OAAO,CAAC,MAAM,CACZ,SAAS,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,MAAM,CAC9D,CACF,CAAC;gCACJ,CAAC;gCAAC,MAAM,CAAC;oCACP,SAAS,GAAG,IAAI,CAAC;oCACjB,OAAO;gCACT,CAAC;4BACH,CAAC;iCAAM,IAAI,GAAG,EAAE,MAAM,KAAK,WAAW,EAAE,CAAC;gCACvC,IAAI,CAAC;oCACH,UAAU,CAAC,OAAO,CAChB,OAAO,CAAC,MAAM,CACZ,SAAS,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,MAAM,CAC9D,CACF,CAAC;gCACJ,CAAC;gCAAC,MAAM,CAAC;oCACP,SAAS,GAAG,IAAI,CAAC;oCACjB,OAAO;gCACT,CAAC;4BACH,CAAC;iCAAM,IAAI,GAAG,EAAE,MAAM,KAAK,SAAS,EAAE,CAAC;gCACrC,IAAI,CAAC;oCACH,UAAU,CAAC,OAAO,CAChB,OAAO,CAAC,MAAM,CACZ,SAAS,IAAI,CAAC,SAAS,CAAC;wCACtB,IAAI,EAAE,OAAO;wCACb,KAAK,EACH,6DAA6D;wCAC/D,SAAS,EAAE,4BAA4B;wCACvC,OAAO,EACL,gGAAgG;wCAClG,GAAG,EAAE,OAAO;qCACb,CAAC,MAAM,CACT,CACF,CAAC;gCACJ,CAAC;gCAAC,MAAM,CAAC;oCACP,SAAS,GAAG,IAAI,CAAC;oCACjB,OAAO;gCACT,CAAC;4BACH,CAAC;4BACD,IAAI,SAAS;gCAAE,aAAa,CAAC,SAAS,CAAC,CAAC;4BACxC,UAAU,CAAC,KAAK,EAAE,CAAC;4BACnB,OAAO;wBACT,CAAC;oBACH,CAAC;oBAED,qBAAqB;oBACrB,IAAI,CAAC,SAAS,EAAE,CAAC;wBACf,SAAS,GAAG,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;oBACpC,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,2BAA2B;oBAC3B,IAAI,CAAC;wBACH,IAAI,SAAS;4BAAE,aAAa,CAAC,SAAS,CAAC,CAAC;wBACxC,UAAU,CAAC,KAAK,EAAE,CAAC;oBACrB,CAAC;oBAAC,MAAM,CAAC,CAAA,CAAC;gBACZ,CAAC;YACH,CAAC,CAAC;YAEF,yCAAyC;YACzC,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,CAAC;gBACpC,IAAI,CAAC,GAAG,EAAE,CAAC;oBACT,IAAI,SAAS;wBAAE,aAAa,CAAC,SAAS,CAAC,CAAC;oBACxC,UAAU,CAAC,KAAK,EAAE,CAAC;oBACnB,OAAO;gBACT,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,UAAU,CAAC,KAAK,EAAE,CAAC;gBACnB,OAAO;YACT,CAAC;YAED,MAAM,IAAI,EAAE,CAAC;QACf,CAAC;QACD,MAAM;YACJ,SAAS,GAAG,IAAI,CAAC;YACjB,IAAI,SAAS;gBAAE,YAAY,CAAC,SAAS,CAAC,CAAC;YACvC,IAAI,SAAS;gBAAE,aAAa,CAAC,SAAS,CAAC,CAAC;QAC1C,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,qBAAqB,CAAC,QAAgB;IACpD,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACxC,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAClC,IAAI,GAAG;YAAE,OAAO,GAAG,CAAC;IACtB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAAC,QAAgB;IAM/D,uEAAuE;IACvE,yEAAyE;IACzE,qDAAqD;IACrD,MAAM,MAAM,GAAG,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IAC/C,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC;QACxE,OAAO;YACL,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,mEAAmE;YACnE,8DAA8D;YAC9D,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;SACxB,CAAC;IACJ,CAAC;IACD,yEAAyE;IACzE,oEAAoE;IACpE,wEAAwE;IACxE,sEAAsE;IACtE,sEAAsE;IACtE,qEAAqE;IACrE,2DAA2D;IAC3D,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,QAAQ,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC,CAAC;QACzE,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QACzB,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAChC,iEAAiE;YACjE,gEAAgE;YAChE,0BAA0B;YAC1B,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC;YAC/D,IAAI,MAAM;gBAAE,OAAO,IAAI,CAAC;YACxB,OAAO;gBACL,KAAK,EAAE,MAAM,CAAC,EAAE;gBAChB,QAAQ,EAAE,MAAM,CAAC,QAAQ;gBACzB,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,SAAS;aACpD,CAAC;QACJ,CAAC;QACD,IAAI,MAAM,CAAC,MAAM,KAAK,WAAW,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACjE,qEAAqE;YACrE,mEAAmE;YACnE,+DAA+D;YAC/D,EAAE;YACF,kEAAkE;YAClE,mEAAmE;YACnE,mEAAmE;YACnE,gEAAgE;YAChE,oEAAoE;YACpE,gEAAgE;YAChE,yCAAyC;YACzC,MAAM,WAAW,GACf,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,SAAS,CAAC;YAC/D,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,WAAW,CAAC;YAC7C,IAAI,WAAW,GAAG,gCAAgC;gBAAE,OAAO,IAAI,CAAC;YAChE,OAAO;gBACL,KAAK,EAAE,MAAM,CAAC,EAAE;gBAChB,QAAQ,EAAE,MAAM,CAAC,QAAQ;gBACzB,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,SAAS;aACpD,CAAC;QACJ,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,2BAA2B;IAC7B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,sBAAsB;AACtB,MAAM,UAAU,MAAM,CAAC,KAAa;IAClC,OAAO,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC;AACvC,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,QAAQ,CAAC,KAAa,EAAE,SAAiB,MAAM;IAC7D,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAClC,IAAI,GAAG,EAAE,CAAC;QACR,gBAAgB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAChC,CAAC;IACD,mEAAmE;IACnE,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAC9C,OAAO,CAAC,CAAC,GAAG,CAAC;AACf,CAAC","sourcesContent":["import type { AgentChatEvent, RunEvent, RunStatus } from \"./types.js\";\nimport { EngineError } from \"./engine/types.js\";\nimport {\n insertRun,\n insertRunEvent,\n updateRunStatus,\n markRunAborted,\n getRunAbortState,\n getRunEventsSince,\n getRunById,\n getRunByThread,\n cleanupOldRuns,\n updateRunHeartbeat,\n reapIfStale,\n} from \"./run-store.js\";\n\nexport interface ActiveRun {\n runId: string;\n threadId: string;\n events: RunEvent[];\n status: RunStatus;\n subscribers: Set<(event: RunEvent) => void>;\n abort: AbortController;\n abortReason?: string;\n startedAt: number;\n}\n\nconst activeRuns = new Map<string, ActiveRun>();\nconst threadToRun = new Map<string, string>();\n\n/** How long to keep completed runs in memory before cleanup (5 min) */\nconst CLEANUP_DELAY_MS = 5 * 60 * 1000;\n\n/** Default run chunk budget for hosted/serverless deploys. */\nexport const DEFAULT_HOSTED_RUN_SOFT_TIMEOUT_MS = 55_000;\n\n/** Default SQL retention for completed/errored run event logs (24 hours). */\nexport const DEFAULT_COMPLETED_RUN_RETENTION_MS = 24 * 60 * 60 * 1000;\n\n/**\n * How recently a terminal run must have started for `/runs/active` to surface\n * it. Reconnect after this window won't replay the run — typical real-world\n * disconnects resolve in seconds, so 10 minutes is generous while keeping us\n * from resurrecting ancient turns when the user reopens an old thread.\n */\nexport const TERMINAL_RUN_RECONNECT_WINDOW_MS = 10 * 60 * 1000;\n\nexport interface StartRunOptions {\n /** Optional internal run chunk budget. When reached, the framework emits an\n * auto-continuation signal instead of a user-facing timeout. Leave unset for\n * no framework-imposed run timeout. */\n softTimeoutMs?: number;\n /** Opt into the hosted/serverless default chunk budget. Only callers with\n * automatic continuation support should enable this. */\n useHostedSoftTimeoutDefault?: boolean;\n}\n\nexport interface ResolveRunSoftTimeoutOptions {\n useHostedDefault?: boolean;\n}\n\nfunction isHostedRuntime(): boolean {\n if (\n process.env.NETLIFY &&\n process.env.NETLIFY !== \"false\" &&\n process.env.NETLIFY_LOCAL !== \"true\"\n ) {\n return true;\n }\n if (\n process.env.AWS_LAMBDA_FUNCTION_NAME &&\n process.env.NETLIFY_LOCAL !== \"true\"\n ) {\n return true;\n }\n return Boolean(\n process.env.CF_PAGES ||\n process.env.VERCEL ||\n process.env.VERCEL_ENV ||\n process.env.RENDER ||\n process.env.FLY_APP_NAME ||\n process.env.K_SERVICE,\n );\n}\n\nexport function resolveRunSoftTimeoutMs(\n overrideMs?: number,\n options?: ResolveRunSoftTimeoutOptions,\n): number {\n if (typeof overrideMs === \"number\" && Number.isFinite(overrideMs)) {\n return Math.max(0, overrideMs);\n }\n const envValue = process.env.AGENT_RUN_SOFT_TIMEOUT_MS;\n if (envValue !== undefined) {\n const raw = Number(envValue);\n if (Number.isFinite(raw) && raw >= 0) return raw;\n }\n return options?.useHostedDefault && isHostedRuntime()\n ? DEFAULT_HOSTED_RUN_SOFT_TIMEOUT_MS\n : 0;\n}\n\nexport function resolveCompletedRunRetentionMs(): number {\n const envValue = process.env.AGENT_RUN_RETENTION_MS;\n if (envValue !== undefined) {\n const raw = Number(envValue);\n if (Number.isFinite(raw) && raw >= 0) return raw;\n }\n return DEFAULT_COMPLETED_RUN_RETENTION_MS;\n}\n\nfunction isTerminalRunEvent(event: AgentChatEvent): boolean {\n return (\n event.type === \"done\" ||\n event.type === \"error\" ||\n event.type === \"missing_api_key\" ||\n event.type === \"loop_limit\" ||\n event.type === \"auto_continue\"\n );\n}\n\nfunction abortInMemoryRun(run: ActiveRun, reason: string = \"user\") {\n run.abortReason = reason;\n run.status = \"aborted\";\n if (threadToRun.get(run.threadId) === run.runId) {\n threadToRun.delete(run.threadId);\n }\n run.abort.abort(reason);\n for (const subscriber of run.subscribers) {\n try {\n subscriber({ seq: run.events.length, event: { type: \"done\" } });\n } catch {\n // ignore — subscriber is being removed below\n }\n }\n run.subscribers.clear();\n}\n\n/**\n * Start a new agent run in the background.\n * `runFn` receives a `send` callback and an `AbortSignal`.\n * The run continues even if all SSE subscribers disconnect.\n *\n * Events are persisted to SQL for cross-isolate access (Cloudflare Workers).\n */\nexport function startRun(\n runId: string,\n threadId: string,\n runFn: (\n send: (event: AgentChatEvent) => void,\n signal: AbortSignal,\n ) => Promise<void>,\n onComplete?: (run: ActiveRun) => void | Promise<void>,\n options?: StartRunOptions,\n): ActiveRun {\n // If there's already a run for this thread, abort it\n const existingRunId = threadToRun.get(threadId);\n if (existingRunId) {\n abortRun(existingRunId);\n }\n\n const abort = new AbortController();\n let softTimedOut = false;\n const run: ActiveRun = {\n runId,\n threadId,\n events: [],\n status: \"running\",\n subscribers: new Set(),\n abort,\n startedAt: Date.now(),\n };\n\n activeRuns.set(runId, run);\n threadToRun.set(threadId, runId);\n\n // Persist run to SQL without blocking the response. Keep the promise so\n // final status cannot race ahead of a slow initial INSERT and then get\n // overwritten by a late row stuck at status='running'.\n const insertRunPromise = insertRun(runId, threadId).catch(() => {});\n\n // Periodic SQL abort check interval (for cross-isolate abort on Workers)\n let lastAbortCheck = Date.now() - 3000;\n const checkSqlAbort = () => {\n const now = Date.now();\n if (now - lastAbortCheck < 3000) return;\n lastAbortCheck = now;\n getRunAbortState(runId)\n .then((state) => {\n if (state.aborted && !abort.signal.aborted) {\n abortInMemoryRun(run, state.reason ?? \"user\");\n }\n })\n .catch(() => {});\n };\n\n // Heartbeat: bump heartbeat_at every 1.5s so watchers can detect a dead\n // producer (process crash, HMR restart, isolate eviction) quickly and\n // reap the row. Paired with RUN_STALE_MS (6s) — 4x the interval to\n // tolerate transient DB slowness without false positives.\n const heartbeatTimer: ReturnType<typeof setInterval> = setInterval(() => {\n updateRunHeartbeat(runId).catch(() => {});\n checkSqlAbort();\n }, 1500);\n const softTimeoutMs = resolveRunSoftTimeoutMs(options?.softTimeoutMs, {\n useHostedDefault: options?.useHostedSoftTimeoutDefault === true,\n });\n const softTimeoutTimer =\n softTimeoutMs > 0\n ? setTimeout(() => {\n if (run.status !== \"running\" || abort.signal.aborted) return;\n softTimedOut = true;\n send({\n type: \"auto_continue\",\n reason: \"run_timeout\",\n });\n abort.abort();\n }, softTimeoutMs)\n : null;\n let pendingTerminalEvent: RunEvent | null = null;\n\n const emitRunEvent = (runEvent: RunEvent) => {\n run.events.push(runEvent);\n\n // Notify in-memory subscribers (same isolate, fast path)\n for (const subscriber of run.subscribers) {\n try {\n subscriber(runEvent);\n } catch {\n run.subscribers.delete(subscriber);\n }\n }\n\n // Persist event to SQL (fire-and-forget)\n insertRunEvent(runId, runEvent.seq, JSON.stringify(runEvent.event)).catch(\n () => {},\n );\n\n checkSqlAbort();\n };\n\n const send = (event: AgentChatEvent) => {\n if (run.status === \"aborted\" && abort.signal.aborted) return;\n\n const runEvent: RunEvent = { seq: run.events.length, event };\n if (isTerminalRunEvent(event)) {\n pendingTerminalEvent = runEvent;\n return;\n }\n\n emitRunEvent(runEvent);\n };\n\n // Run in background — intentionally detached from any HTTP connection\n const runPromise = runFn(send, abort.signal)\n .then(() => {\n if (abort.signal.aborted) {\n run.status = softTimedOut ? \"completed\" : \"aborted\";\n return;\n }\n run.status = \"completed\";\n })\n .catch((err) => {\n // Don't surface abort errors — the run was intentionally stopped\n if (abort.signal.aborted) {\n run.status = softTimedOut ? \"completed\" : \"aborted\";\n return;\n }\n run.status = \"errored\";\n send({\n type: \"error\",\n error: err?.message ?? \"Unknown error\",\n ...(err instanceof EngineError && err.errorCode\n ? { errorCode: err.errorCode }\n : {}),\n ...(err instanceof EngineError && err.upgradeUrl\n ? { upgradeUrl: err.upgradeUrl }\n : {}),\n });\n })\n .finally(async () => {\n // Ordering matters here — this is the atomic-complete boundary.\n // Invariant: once agent_runs.status flips to \"completed\"/\"errored\"\n // in SQL, thread_data for this turn is already durable. This lets\n // reconnecting clients trust the simple rule \"status != running →\n // fetch thread_data\" without polling/retrying for a race window\n // where onComplete was still pending.\n\n // 1. Await the completion callback (thread_data save). Heartbeat is\n // still ticking so the run doesn't look stale to any concurrent\n // /runs/active check while we wait for SQL writes to land.\n let completionError: unknown = null;\n if (\n onComplete &&\n !(run.status === \"aborted\" && run.abortReason === \"no_progress\")\n ) {\n try {\n const completionRun: ActiveRun = pendingTerminalEvent\n ? { ...run, events: [...run.events, pendingTerminalEvent] }\n : run;\n await onComplete(completionRun);\n } catch (err) {\n completionError = err;\n console.error(\n \"[run-manager] onComplete callback error:\",\n err instanceof Error ? err.message : err,\n );\n }\n }\n\n // 2. Compute final status. If the completion callback threw, we'd\n // rather mark the run errored than claim success with incomplete\n // thread_data.\n const finalStatus =\n run.status === \"aborted\"\n ? \"aborted\"\n : run.status === \"errored\" || completionError\n ? \"errored\"\n : \"completed\";\n\n // 3. Emit the terminal event only after thread_data is durable. Live\n // SSE clients close on this event and usually fetch thread_data\n // immediately, so emitting it earlier recreates the final-message\n // race this manager is meant to avoid.\n if (finalStatus === \"completed\" || finalStatus === \"errored\") {\n const terminal: RunEvent =\n finalStatus === \"completed\"\n ? (pendingTerminalEvent ?? {\n seq: run.events.length,\n event: { type: \"done\" },\n })\n : pendingTerminalEvent?.event.type === \"error\"\n ? pendingTerminalEvent\n : {\n seq: pendingTerminalEvent?.seq ?? run.events.length,\n event: {\n type: \"error\",\n error: completionError\n ? \"Agent response could not be saved.\"\n : \"Agent run ended unexpectedly\",\n },\n };\n const last = run.events[run.events.length - 1];\n if (!last || !isTerminalRunEvent(last.event)) {\n emitRunEvent(terminal);\n }\n }\n for (const subscriber of run.subscribers) {\n run.subscribers.delete(subscriber);\n }\n\n // 4. Stop the heartbeat — all liveness writes are done.\n clearInterval(heartbeatTimer);\n if (softTimeoutTimer) clearTimeout(softTimeoutTimer);\n\n // 5. Persist final status to SQL.\n try {\n await insertRunPromise;\n await updateRunStatus(runId, finalStatus);\n } catch {\n // Best-effort — reapIfStale will eventually clean this up via\n // the heartbeat-stale path.\n }\n\n // 6. Schedule in-memory cleanup + opportunistic old-run pruning.\n setTimeout(() => {\n activeRuns.delete(runId);\n if (threadToRun.get(threadId) === runId) {\n threadToRun.delete(threadId);\n }\n }, CLEANUP_DELAY_MS);\n cleanupOldRuns(resolveCompletedRunRetentionMs()).catch(() => {});\n });\n\n // On Cloudflare Workers, keep the isolate alive for this run\n try {\n const cfCtx = globalThis.__cf_ctx;\n if (cfCtx?.waitUntil) {\n cfCtx.waitUntil(runPromise);\n }\n } catch {\n // Not on Workers — ignore\n }\n\n return run;\n}\n\n/**\n * Subscribe to a run's events starting from `fromSeq`.\n * Returns a ReadableStream that replays buffered events then live-tails.\n * Cancelling the stream only unsubscribes — does NOT abort the agent.\n *\n * Falls back to SQL polling when the run is not in local memory\n * (cross-isolate reconnection on Workers).\n */\nexport function subscribeToRun(\n runId: string,\n fromSeq: number,\n): ReadableStream<Uint8Array> | null {\n const run = activeRuns.get(runId);\n if (run) {\n return subscribeInMemory(run, fromSeq);\n }\n // Not in local memory — try SQL (cross-isolate path)\n return subscribeFromSQL(runId, fromSeq);\n}\n\n/** In-memory subscription (same isolate, fast path) */\nfunction subscribeInMemory(\n run: ActiveRun,\n fromSeq: number,\n): ReadableStream<Uint8Array> {\n const encoder = new TextEncoder();\n let subscriberRef: ((event: RunEvent) => void) | null = null;\n let pingTimer: ReturnType<typeof setInterval> | null = null;\n\n return new ReadableStream({\n start(controller) {\n const ping = () => {\n try {\n controller.enqueue(encoder.encode(`: ping ${Date.now()}\\n\\n`));\n } catch {\n if (subscriberRef) run.subscribers.delete(subscriberRef);\n if (pingTimer) clearInterval(pingTimer);\n }\n };\n ping();\n pingTimer = setInterval(ping, 10_000);\n\n // Replay buffered events from fromSeq\n for (let i = fromSeq; i < run.events.length; i++) {\n try {\n controller.enqueue(\n encoder.encode(\n `data: ${JSON.stringify({ ...run.events[i].event, seq: run.events[i].seq })}\\n\\n`,\n ),\n );\n } catch {\n return;\n }\n }\n\n // If run is already done, close immediately\n if (run.status !== \"running\") {\n if (pingTimer) clearInterval(pingTimer);\n controller.close();\n return;\n }\n\n // Subscribe to live events\n subscriberRef = (event: RunEvent) => {\n try {\n controller.enqueue(\n encoder.encode(\n `data: ${JSON.stringify({ ...event.event, seq: event.seq })}\\n\\n`,\n ),\n );\n // Close stream after terminal events\n if (isTerminalRunEvent(event.event)) {\n run.subscribers.delete(subscriberRef!);\n if (pingTimer) clearInterval(pingTimer);\n controller.close();\n }\n } catch {\n run.subscribers.delete(subscriberRef!);\n }\n };\n\n run.subscribers.add(subscriberRef);\n },\n cancel() {\n // Only unsubscribe — do NOT abort the agent run\n if (subscriberRef) run.subscribers.delete(subscriberRef);\n if (pingTimer) clearInterval(pingTimer);\n },\n });\n}\n\n/** SQL-based subscription (cross-isolate, polling) */\nfunction subscribeFromSQL(\n runId: string,\n fromSeq: number,\n): ReadableStream<Uint8Array> | null {\n const encoder = new TextEncoder();\n let cancelled = false;\n let pollTimer: ReturnType<typeof setTimeout> | null = null;\n let pingTimer: ReturnType<typeof setInterval> | null = null;\n\n return new ReadableStream({\n async start(controller) {\n let lastSeq = fromSeq;\n const ping = () => {\n try {\n controller.enqueue(encoder.encode(`: ping ${Date.now()}\\n\\n`));\n } catch {\n cancelled = true;\n if (pingTimer) clearInterval(pingTimer);\n }\n };\n ping();\n pingTimer = setInterval(ping, 10_000);\n\n const poll = async () => {\n if (cancelled) return;\n try {\n // Read new events from SQL\n const events = await getRunEventsSince(runId, lastSeq);\n for (const { seq, eventData } of events) {\n let parsed: any;\n try {\n parsed = JSON.parse(eventData);\n } catch {\n continue;\n }\n try {\n controller.enqueue(\n encoder.encode(\n `data: ${JSON.stringify({ ...parsed, seq })}\\n\\n`,\n ),\n );\n } catch {\n cancelled = true;\n return;\n }\n lastSeq = seq + 1;\n\n // Close on terminal events\n if (isTerminalRunEvent(parsed)) {\n if (pingTimer) clearInterval(pingTimer);\n controller.close();\n return;\n }\n }\n\n // Check if run completed (no terminal event but status changed)\n if (events.length === 0) {\n // Opportunistically reap a stale producer before trusting SQL's\n // \"running\" status — otherwise a crashed server leaves us polling\n // forever.\n await reapIfStale(runId).catch(() => {});\n const run = await getRunById(runId);\n if (!run || run.status !== \"running\") {\n // Run ended — do one final event read, then close\n const finalEvents = await getRunEventsSince(runId, lastSeq);\n for (const { seq, eventData } of finalEvents) {\n let parsed: any;\n try {\n parsed = JSON.parse(eventData);\n } catch {\n continue;\n }\n try {\n controller.enqueue(\n encoder.encode(\n `data: ${JSON.stringify({ ...parsed, seq })}\\n\\n`,\n ),\n );\n } catch {\n cancelled = true;\n return;\n }\n lastSeq = seq + 1;\n if (isTerminalRunEvent(parsed)) {\n if (pingTimer) clearInterval(pingTimer);\n controller.close();\n return;\n }\n }\n if (run?.status === \"aborted\") {\n try {\n controller.enqueue(\n encoder.encode(\n `data: ${JSON.stringify({ type: \"done\", seq: lastSeq })}\\n\\n`,\n ),\n );\n } catch {\n cancelled = true;\n return;\n }\n } else if (run?.status === \"completed\") {\n try {\n controller.enqueue(\n encoder.encode(\n `data: ${JSON.stringify({ type: \"done\", seq: lastSeq })}\\n\\n`,\n ),\n );\n } catch {\n cancelled = true;\n return;\n }\n } else if (run?.status === \"errored\") {\n try {\n controller.enqueue(\n encoder.encode(\n `data: ${JSON.stringify({\n type: \"error\",\n error:\n \"Agent run ended before its final error event was persisted.\",\n errorCode: \"run_terminal_event_missing\",\n details:\n \"The persisted run status is errored, but no terminal SSE event was available during reconnect.\",\n seq: lastSeq,\n })}\\n\\n`,\n ),\n );\n } catch {\n cancelled = true;\n return;\n }\n }\n if (pingTimer) clearInterval(pingTimer);\n controller.close();\n return;\n }\n }\n\n // Schedule next poll\n if (!cancelled) {\n pollTimer = setTimeout(poll, 500);\n }\n } catch {\n // SQL error — close stream\n try {\n if (pingTimer) clearInterval(pingTimer);\n controller.close();\n } catch {}\n }\n };\n\n // Verify run exists before starting poll\n try {\n const run = await getRunById(runId);\n if (!run) {\n if (pingTimer) clearInterval(pingTimer);\n controller.close();\n return;\n }\n } catch {\n controller.close();\n return;\n }\n\n await poll();\n },\n cancel() {\n cancelled = true;\n if (pollTimer) clearTimeout(pollTimer);\n if (pingTimer) clearInterval(pingTimer);\n },\n });\n}\n\n/** Get the active run for a thread (if any) — checks memory then SQL */\nexport function getActiveRunForThread(threadId: string): ActiveRun | null {\n const runId = threadToRun.get(threadId);\n if (runId) {\n const run = activeRuns.get(runId);\n if (run) return run;\n }\n return null;\n}\n\n/**\n * Async version that also checks SQL — for cross-isolate access.\n * Used by the /runs/active endpoint.\n *\n * Returns `heartbeatAt` so the client can independently decide a run is\n * dead even before the server-side stale reap has fired.\n */\nexport async function getActiveRunForThreadAsync(threadId: string): Promise<{\n runId: string;\n threadId: string;\n status: string;\n heartbeatAt: number;\n} | null> {\n // Check memory first — return both running AND recently-completed runs\n // that still have events in memory. This allows sub-agent tabs to replay\n // the full conversation from completed runs via SSE.\n const memRun = getActiveRunForThread(threadId);\n if (memRun && (memRun.status === \"running\" || memRun.events.length > 0)) {\n return {\n runId: memRun.runId,\n threadId: memRun.threadId,\n status: memRun.status,\n // In-memory means this isolate is the producer. By definition, the\n // heartbeat is fresh as of \"now\" — the client can trust this.\n heartbeatAt: Date.now(),\n };\n }\n // Fall back to SQL — also surface recently terminated runs so the client\n // can reconnect and replay synthesized done/error events instead of\n // retrying the original POST. Without this, a POST that fails after the\n // server already accepted (and finished) the run would re-execute the\n // turn and double-apply mutations: the in-memory branch above already\n // returns terminal runs whose events are still buffered, but the SQL\n // path is the only authority once memory has been evicted.\n try {\n const sqlRun = await getRunByThread(threadId, { includeTerminal: true });\n if (!sqlRun) return null;\n if (sqlRun.status === \"running\") {\n // If the producer is dead (no recent heartbeat), reap before the\n // client can see a stale \"running\" status and enter a reconnect\n // loop it can never exit.\n const reaped = await reapIfStale(sqlRun.id).catch(() => false);\n if (reaped) return null;\n return {\n runId: sqlRun.id,\n threadId: sqlRun.threadId,\n status: sqlRun.status,\n heartbeatAt: sqlRun.heartbeatAt ?? sqlRun.startedAt,\n };\n }\n if (sqlRun.status === \"completed\" || sqlRun.status === \"errored\") {\n // Cap how far back we'll surface terminal runs as \"active\". The goal\n // is to catch the recently-completed-but-reconnecting case, not to\n // resurrect ancient turns when the user reopens an old thread.\n //\n // Measure age from the run's terminal timestamp, not its start. A\n // long-running task that ran 11 minutes and completed five seconds\n // ago should still be reachable — the client's disconnect happened\n // around completion, so completion time is what matters for the\n // \"is the user still here waiting?\" question. Fall back to the last\n // heartbeat (older deployments may have unset completed_at) and\n // finally to startedAt for ancient rows.\n const referenceAt =\n sqlRun.completedAt ?? sqlRun.heartbeatAt ?? sqlRun.startedAt;\n const terminalAge = Date.now() - referenceAt;\n if (terminalAge > TERMINAL_RUN_RECONNECT_WINDOW_MS) return null;\n return {\n runId: sqlRun.id,\n threadId: sqlRun.threadId,\n status: sqlRun.status,\n heartbeatAt: sqlRun.heartbeatAt ?? sqlRun.startedAt,\n };\n }\n } catch {\n // SQL error — fall through\n }\n return null;\n}\n\n/** Get a run by ID */\nexport function getRun(runId: string): ActiveRun | null {\n return activeRuns.get(runId) ?? null;\n}\n\n/** Explicitly abort a run (e.g. Stop button) */\nexport function abortRun(runId: string, reason: string = \"user\"): boolean {\n const run = activeRuns.get(runId);\n if (run) {\n abortInMemoryRun(run, reason);\n }\n // Also mark as aborted in SQL (for cross-isolate abort on Workers)\n markRunAborted(runId, reason).catch(() => {});\n return !!run;\n}\n"]}
|
|
@@ -281,6 +281,30 @@ function probePort(port, timeoutMs = 1_000) {
|
|
|
281
281
|
socket.connect(port, "127.0.0.1");
|
|
282
282
|
});
|
|
283
283
|
}
|
|
284
|
+
function firstHeaderValue(value) {
|
|
285
|
+
if (Array.isArray(value))
|
|
286
|
+
return value[0];
|
|
287
|
+
if (value === undefined)
|
|
288
|
+
return undefined;
|
|
289
|
+
return String(value);
|
|
290
|
+
}
|
|
291
|
+
function forwardedProto(req) {
|
|
292
|
+
return (firstHeaderValue(req.headers["x-forwarded-proto"]) ||
|
|
293
|
+
(req.socket.encrypted ? "https" : "http"));
|
|
294
|
+
}
|
|
295
|
+
function forwardedHost(req) {
|
|
296
|
+
return (firstHeaderValue(req.headers["x-forwarded-host"]) ||
|
|
297
|
+
firstHeaderValue(req.headers.host) ||
|
|
298
|
+
new URL(gatewayUrl).host);
|
|
299
|
+
}
|
|
300
|
+
function proxyHeaders(req, targetHost) {
|
|
301
|
+
return {
|
|
302
|
+
...req.headers,
|
|
303
|
+
"x-forwarded-host": forwardedHost(req),
|
|
304
|
+
"x-forwarded-proto": forwardedProto(req),
|
|
305
|
+
host: targetHost,
|
|
306
|
+
};
|
|
307
|
+
}
|
|
284
308
|
async function waitForPort(port, deadline) {
|
|
285
309
|
while (Date.now() < deadline) {
|
|
286
310
|
if (await probePort(port))
|
|
@@ -291,7 +315,7 @@ async function waitForPort(port, deadline) {
|
|
|
291
315
|
}
|
|
292
316
|
function proxyHttp(app, req, res) {
|
|
293
317
|
const dispatch = () => {
|
|
294
|
-
const headers =
|
|
318
|
+
const headers = proxyHeaders(req, `127.0.0.1:${app.port}`);
|
|
295
319
|
const proxyReq = http.request({
|
|
296
320
|
hostname: "127.0.0.1",
|
|
297
321
|
port: app.port,
|
|
@@ -339,10 +363,7 @@ function proxyHttp(app, req, res) {
|
|
|
339
363
|
}
|
|
340
364
|
function proxyUpgrade(app, req, socket, head) {
|
|
341
365
|
const target = net.connect(app.port, "127.0.0.1", () => {
|
|
342
|
-
const headers = Object.entries({
|
|
343
|
-
...req.headers,
|
|
344
|
-
host: `127.0.0.1:${app.port}`,
|
|
345
|
-
})
|
|
366
|
+
const headers = Object.entries(proxyHeaders(req, `127.0.0.1:${app.port}`))
|
|
346
367
|
.flatMap(([key, value]) => Array.isArray(value)
|
|
347
368
|
? value.map((item) => `${key}: ${item}`)
|
|
348
369
|
: [`${key}: ${value ?? ""}`])
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace-dev.js","sourceRoot":"","sources":["../../src/cli/workspace-dev.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env tsx\nimport { spawn, type ChildProcess } from \"node:child_process\";\nimport fs from \"node:fs\";\nimport http from \"node:http\";\nimport net from \"node:net\";\nimport path from \"node:path\";\nimport type { Duplex } from \"node:stream\";\nimport * as Sentry from \"@sentry/node\";\nimport { extractOAuthStateAppId } from \"../shared/oauth-state.js\";\n\ninterface WorkspaceApp {\n id: string;\n name: string;\n dir: string;\n port: number;\n process?: ChildProcess;\n restartTimer?: NodeJS.Timeout;\n restartAttempts?: number;\n /**\n * Set true once we've successfully connected to the upstream. After that we\n * skip the readiness probe on every request — the child server stays\n * listening for the rest of the dev session.\n */\n ready?: boolean;\n}\n\nconst root = process.cwd();\nconst appsDir = path.join(root, \"apps\");\nfs.mkdirSync(path.join(root, \"data\"), { recursive: true });\nconst gatewayHost = process.env.WORKSPACE_HOST || \"127.0.0.1\";\nconst requestedPort = Number(\n process.env.WORKSPACE_PORT || process.env.PORT || 8080,\n);\nconst appPortStart = Number(process.env.WORKSPACE_APP_PORT_START || 8100);\nconst forceVite = process.env.WORKSPACE_VITE_FORCE === \"1\";\nlet gatewayUrl = `http://${gatewayHost}:${requestedPort}`;\n\nfunction readJson(file: string): any {\n try {\n return JSON.parse(fs.readFileSync(file, \"utf8\"));\n } catch {\n return null;\n }\n}\n\nfunction discoverApps(): WorkspaceApp[] {\n if (!fs.existsSync(appsDir)) return [];\n // existsSync → readdirSync is a TOCTOU race — appsDir can vanish between\n // the two calls (e.g. user running `git checkout` on the workspace mid-dev).\n // Treat ENOENT as \"no apps right now\" and let the next 2s sync recover.\n // Other errors get surfaced to Sentry so we learn about new failure modes.\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(appsDir, { withFileTypes: true });\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code !== \"ENOENT\") {\n console.warn(\n `[workspace] Could not read ${appsDir} (${code ?? \"unknown\"}): ` +\n `${(err as Error).message}`,\n );\n Sentry.captureException(err, {\n tags: { handled: \"dev-discover-readdir\" },\n level: \"warning\",\n });\n }\n return [];\n }\n return entries\n .filter((entry) => entry.isDirectory())\n .map((entry) => {\n const dir = path.join(appsDir, entry.name);\n const pkg = readJson(path.join(dir, \"package.json\"));\n if (!pkg) return null;\n return {\n id: entry.name,\n name: pkg.displayName || pkg.name || entry.name,\n dir,\n port: appPortStart,\n } satisfies WorkspaceApp;\n })\n .filter((app): app is WorkspaceApp => !!app)\n .sort((a, b) => {\n if (a.id === \"dispatch\") return -1;\n if (b.id === \"dispatch\") return 1;\n return a.id.localeCompare(b.id);\n })\n .map((app, index) => ({ ...app, port: appPortStart + index }));\n}\n\nconst apps = discoverApps();\nif (apps.length === 0) {\n console.error(\"[workspace] No apps found under ./apps\");\n process.exit(1);\n}\n\nconst appById = new Map(apps.map((app) => [app.id, app]));\nconst defaultApp =\n process.env.WORKSPACE_DEFAULT_APP &&\n appById.has(process.env.WORKSPACE_DEFAULT_APP)\n ? process.env.WORKSPACE_DEFAULT_APP\n : appById.has(\"dispatch\")\n ? \"dispatch\"\n : apps[0].id;\n\nfunction isChildDevServerUrlLine(line: string): boolean {\n return /^\\s*➜\\s+(?:Local|Network):\\s+https?:\\/\\/(?:localhost|127\\.0\\.0\\.1|\\[::1\\]):\\d+(?:\\/\\S*)?\\s*$/i.test(\n line,\n );\n}\n\nfunction pipeAppOutput(\n prefix: string,\n chunk: unknown,\n write: (value: string) => void,\n): void {\n const lines = String(chunk)\n .split(/\\r?\\n/)\n .filter(Boolean)\n .filter((line) => !isChildDevServerUrlLine(line));\n if (lines.length === 0) return;\n write(lines.map((line) => `${prefix} ${line}`).join(\"\\n\") + \"\\n\");\n}\n\nfunction syncApps(): void {\n const discovered = discoverApps();\n for (const app of discovered) {\n const existing = appById.get(app.id);\n if (existing) {\n existing.name = app.name;\n existing.dir = app.dir;\n continue;\n }\n const usedPorts = new Set(apps.map((existing) => existing.port));\n let port = appPortStart;\n while (usedPorts.has(port)) port++;\n const next = { ...app, port };\n apps.push(next);\n apps.sort((a, b) => {\n if (a.id === \"dispatch\") return -1;\n if (b.id === \"dispatch\") return 1;\n return a.id.localeCompare(b.id);\n });\n appById.set(next.id, next);\n console.log(`[workspace] Detected new app: /${next.id}`);\n startApp(next);\n }\n}\n\nlet syncTimer: NodeJS.Timeout | undefined;\nfunction scheduleSync(): void {\n if (syncTimer) clearTimeout(syncTimer);\n syncTimer = setTimeout(syncApps, 400);\n}\n\nfunction firstPathSegment(url: string | undefined): string | null {\n if (!url) return null;\n try {\n const parsed = new URL(url, \"http://workspace.local\");\n const [segment] = parsed.pathname.split(\"/\").filter(Boolean);\n return segment || null;\n } catch {\n return null;\n }\n}\n\nfunction appForRequest(req: http.IncomingMessage): WorkspaceApp | null {\n const params = new URL(req.url || \"/\", \"http://workspace.local\").searchParams;\n const explicit = params.get(\"_app\");\n if (explicit && appById.has(explicit)) return appById.get(explicit) ?? null;\n\n const direct = firstPathSegment(req.url);\n if (direct && appById.has(direct)) return appById.get(direct) ?? null;\n\n const fromState = extractOAuthStateAppId(params.get(\"state\"));\n if (fromState && appById.has(fromState)) {\n return appById.get(fromState) ?? null;\n }\n\n const referer = req.headers.referer;\n const fromReferer =\n typeof referer === \"string\" ? firstPathSegment(referer) : null;\n return fromReferer && appById.has(fromReferer)\n ? (appById.get(fromReferer) ?? null)\n : null;\n}\n\nfunction startApp(app: WorkspaceApp): void {\n if (app.process && !app.process.killed) return;\n if (app.restartTimer) {\n clearTimeout(app.restartTimer);\n app.restartTimer = undefined;\n }\n\n const basePath = `/${app.id}`;\n const workspaceAppsJson = JSON.stringify(\n apps.map((workspaceApp) => ({\n id: workspaceApp.id,\n name: workspaceApp.name,\n path: `/${workspaceApp.id}`,\n })),\n );\n const child = spawn(\n \"pnpm\",\n [\n \"--dir\",\n app.dir,\n \"exec\",\n \"vite\",\n \"--host\",\n \"127.0.0.1\",\n \"--port\",\n String(app.port),\n \"--strictPort\",\n ...(forceVite ? [\"--force\"] : []),\n ],\n {\n cwd: root,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n env: {\n ...process.env,\n APP_NAME: app.id,\n AGENT_NATIVE_WORKSPACE: \"1\",\n AGENT_NATIVE_WORKSPACE_APPS_JSON: workspaceAppsJson,\n APP_BASE_PATH: basePath,\n VITE_AGENT_NATIVE_WORKSPACE: \"1\",\n VITE_APP_BASE_PATH: basePath,\n PORT: String(app.port),\n WORKSPACE_GATEWAY_URL: gatewayUrl,\n },\n },\n );\n app.process = child;\n\n const prefix = `[${app.id}]`;\n const stableTimer = setTimeout(() => {\n app.restartAttempts = 0;\n }, 5_000);\n stableTimer.unref();\n\n child.stdout?.on(\"data\", (chunk) => {\n pipeAppOutput(prefix, chunk, (value) => process.stdout.write(value));\n });\n child.stderr?.on(\"data\", (chunk) => {\n pipeAppOutput(prefix, chunk, (value) => process.stderr.write(value));\n });\n child.on(\"exit\", (code) => {\n clearTimeout(stableTimer);\n app.process = undefined;\n app.ready = false;\n if (code === 0 || shuttingDown) return;\n app.restartAttempts = (app.restartAttempts ?? 0) + 1;\n const delay = appRestartDelay(app.restartAttempts);\n console.error(\n `${prefix} exited with code ${code}; retrying in ${Math.round(\n delay / 1000,\n )}s`,\n );\n app.restartTimer = setTimeout(() => {\n app.restartTimer = undefined;\n startApp(app);\n }, delay);\n app.restartTimer.unref();\n });\n}\n\nfunction renderIndex(): string {\n return `<!doctype html>\n<html>\n <head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <title>Agent-Native Workspace</title>\n <style>\n body { font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif; margin: 0; padding: 32px; background: #fafafa; color: #171717; }\n main { max-width: 760px; margin: 0 auto; }\n a { color: inherit; text-decoration: none; }\n .grid { display: grid; gap: 12px; margin-top: 20px; }\n .card { display: flex; justify-content: space-between; border: 1px solid #d4d4d4; border-radius: 8px; padding: 14px 16px; background: white; }\n .muted { color: #737373; }\n </style>\n </head>\n <body>\n <main>\n <h1>Agent-Native Workspace</h1>\n <p class=\"muted\">Open an app below. Dispatch is the workspace control plane.</p>\n <div class=\"grid\">\n ${apps\n .map(\n (app) =>\n `<a class=\"card\" href=\"/${app.id}\"><strong>${app.name}</strong><span class=\"muted\">/${app.id}</span></a>`,\n )\n .join(\"\")}\n </div>\n </main>\n </body>\n</html>`;\n}\n\n// On `pnpm dev` the gateway answers requests immediately, but each app's vite\n// server takes a beat to bind its port. Without retry, the user sees an\n// \"App is not ready yet: ECONNREFUSED\" banner on the first page load and has\n// to refresh manually. We do a quick pre-flight TCP connect with retry so\n// startup is invisible for the common case (small/no body, slow boot).\nconst PROXY_READY_TIMEOUT_MS = Number(\n process.env.WORKSPACE_PROXY_READY_TIMEOUT_MS ?? 30_000,\n);\nconst PROXY_READY_RETRY_DELAY_MS = 250;\nconst APP_RESTART_MAX_DELAY_MS = 10_000;\n\nfunction appRestartDelay(attempts: number): number {\n return Math.min(\n 1_000 * 2 ** Math.max(0, attempts - 1),\n APP_RESTART_MAX_DELAY_MS,\n );\n}\n\nfunction probePort(port: number, timeoutMs = 1_000): Promise<boolean> {\n return new Promise((resolve) => {\n const socket = new net.Socket();\n let settled = false;\n const finish = (ok: boolean) => {\n if (settled) return;\n settled = true;\n socket.destroy();\n resolve(ok);\n };\n socket.setTimeout(timeoutMs);\n socket.once(\"connect\", () => finish(true));\n socket.once(\"error\", () => finish(false));\n socket.once(\"timeout\", () => finish(false));\n socket.connect(port, \"127.0.0.1\");\n });\n}\n\nasync function waitForPort(port: number, deadline: number): Promise<boolean> {\n while (Date.now() < deadline) {\n if (await probePort(port)) return true;\n await new Promise((r) => setTimeout(r, PROXY_READY_RETRY_DELAY_MS));\n }\n return false;\n}\n\nfunction proxyHttp(\n app: WorkspaceApp,\n req: http.IncomingMessage,\n res: http.ServerResponse,\n): void {\n const dispatch = () => {\n const headers = { ...req.headers, host: `127.0.0.1:${app.port}` };\n const proxyReq = http.request(\n {\n hostname: \"127.0.0.1\",\n port: app.port,\n method: req.method,\n path: req.url,\n headers,\n },\n (proxyRes) => {\n app.ready = true;\n res.writeHead(proxyRes.statusCode ?? 502, proxyRes.headers);\n proxyRes.pipe(res);\n },\n );\n\n proxyReq.on(\"error\", (err) => {\n if (res.headersSent) {\n res.end();\n return;\n }\n res.writeHead(502, { \"content-type\": \"text/plain\" });\n res.end(`App \"${app.id}\" is not ready yet: ${err.message}`);\n });\n\n req.pipe(proxyReq);\n };\n\n // Fast path: the upstream has accepted at least one request before, so it's\n // listening. Skip the probe so steady-state requests stay zero-latency.\n if (app.ready) {\n dispatch();\n return;\n }\n\n // Cold path: hold the request open while the child server boots. Node\n // keeps the request body in paused mode until a consumer attaches via\n // pipe(), so awaiting waitForPort() doesn't lose data.\n void waitForPort(app.port, Date.now() + PROXY_READY_TIMEOUT_MS).then(\n (ready) => {\n if (!ready) {\n if (!res.headersSent) {\n res.writeHead(502, { \"content-type\": \"text/plain\" });\n res.end(\n `App \"${app.id}\" is not ready yet: connect ECONNREFUSED 127.0.0.1:${app.port}`,\n );\n } else {\n res.end();\n }\n return;\n }\n app.ready = true;\n dispatch();\n },\n );\n}\n\nfunction proxyUpgrade(\n app: WorkspaceApp,\n req: http.IncomingMessage,\n socket: Duplex,\n head: Buffer,\n): void {\n const target = net.connect(app.port, \"127.0.0.1\", () => {\n const headers = Object.entries({\n ...req.headers,\n host: `127.0.0.1:${app.port}`,\n })\n .flatMap(([key, value]) =>\n Array.isArray(value)\n ? value.map((item) => `${key}: ${item}`)\n : [`${key}: ${value ?? \"\"}`],\n )\n .join(\"\\r\\n\");\n target.write(\n `${req.method} ${req.url} HTTP/${req.httpVersion}\\r\\n${headers}\\r\\n\\r\\n`,\n );\n if (head.length) target.write(head);\n socket.pipe(target).pipe(socket);\n });\n\n target.on(\"error\", () => socket.destroy());\n}\n\nlet shuttingDown = false;\nlet workspaceStarted = false;\n\nfunction handleWatcherError(err: NodeJS.ErrnoException): void {\n // ENOSPC: system inotify watcher limit hit (Linux). Userland-fixable;\n // capture as a warning so we still see frequency in Sentry but don't get\n // paged. Print actionable guidance and continue without watching — the\n // 2s polling interval below keeps app discovery working.\n if (err.code === \"ENOSPC\") {\n console.warn(\n `[workspace] Recursive file watcher hit the system limit (ENOSPC). ` +\n `New apps will still be detected via polling every ~2s. ` +\n `On Linux you can raise the limit with ` +\n `\\`sudo sysctl fs.inotify.max_user_watches=524288\\` ` +\n `(persist via /etc/sysctl.d/*.conf). On macOS/Windows this usually ` +\n `means too many other watchers are running.`,\n );\n Sentry.captureException(err, {\n tags: { handled: \"dev-watch-enospc\" },\n level: \"warning\",\n });\n return;\n }\n // ENOENT: a watched directory disappeared (or a transient subdir under\n // appsDir vanished mid-enumeration). Benign — the polling fallback and\n // future scheduleSync calls will re-establish state. Don't capture.\n if (err.code === \"ENOENT\") {\n console.debug(\n `[workspace] Recursive file watcher saw a directory disappear ` +\n `(ENOENT: ${err.path ?? \"unknown\"}). Polling fallback will recover.`,\n );\n return;\n }\n // Unknown failure mode — keep the dev experience alive (polling still\n // runs) but surface to Sentry as a warning so we learn about new cases.\n console.warn(\n `[workspace] Recursive file watcher failed (${err.code ?? \"unknown\"}): ${err.message}. ` +\n `Falling back to polling.`,\n );\n Sentry.captureException(err, {\n tags: { handled: \"dev-watch-unknown\" },\n level: \"warning\",\n });\n}\n\nfunction startWorkspaceProcesses(): void {\n if (workspaceStarted) return;\n workspaceStarted = true;\n for (const app of apps) startApp(app);\n try {\n const watcher = fs.watch(appsDir, { recursive: true }, scheduleSync);\n // Async errors (e.g. ENOENT when a subdir vanishes mid-watch) surface on\n // the watcher rather than the original call site. Without an `error`\n // listener, Node would treat them as uncaught and crash the dev process.\n watcher.on(\"error\", (err) => {\n handleWatcherError(err as NodeJS.ErrnoException);\n });\n } catch (err) {\n handleWatcherError(err as NodeJS.ErrnoException);\n }\n setInterval(syncApps, 2_000).unref();\n}\n\nfunction openBrowser(url: string): void {\n if (process.env.WORKSPACE_NO_OPEN === \"1\") return;\n const command =\n process.platform === \"darwin\"\n ? \"open\"\n : process.platform === \"win32\"\n ? \"cmd\"\n : \"xdg-open\";\n const args = process.platform === \"win32\" ? [\"/c\", \"start\", \"\", url] : [url];\n const child = spawn(command, args, {\n stdio: \"ignore\",\n detached: true,\n });\n child.unref();\n}\n\nconst server = http.createServer((req, res) => {\n if (req.url === \"/\" || req.url === \"/index.html\") {\n res.writeHead(302, { location: `/${defaultApp}` });\n res.end();\n return;\n }\n\n if (req.url === \"/_workspace/apps\") {\n res.writeHead(200, { \"content-type\": \"application/json\" });\n res.end(\n JSON.stringify(\n apps.map((app) => ({\n id: app.id,\n name: app.name,\n path: `/${app.id}`,\n port: app.port,\n })),\n ),\n );\n return;\n }\n\n const app = appForRequest(req);\n if (!app) {\n res.writeHead(404, { \"content-type\": \"text/html\" });\n res.end(renderIndex());\n return;\n }\n proxyHttp(app, req, res);\n});\n\nserver.on(\"upgrade\", (req, socket, head) => {\n const app = appForRequest(req);\n if (!app) {\n socket.destroy();\n return;\n }\n proxyUpgrade(app, req, socket, head);\n});\n\nfunction listen(port: number, attempts = 20): void {\n server.once(\"error\", (err: NodeJS.ErrnoException) => {\n if (err.code === \"EADDRINUSE\" && attempts > 0) {\n listen(port + 1, attempts - 1);\n return;\n }\n console.error(`[workspace] Could not start gateway: ${err.message}`);\n process.exit(1);\n });\n server.listen(port, gatewayHost, () => {\n const address = server.address();\n const actualPort =\n typeof address === \"object\" && address ? address.port : port;\n gatewayUrl = `http://${gatewayHost}:${actualPort}`;\n console.log(\n `[workspace] Default: http://${gatewayHost}:${actualPort}/${defaultApp}`,\n );\n console.log(`[workspace] Gateway: http://${gatewayHost}:${actualPort}`);\n for (const app of apps) {\n console.log(`[workspace] ${app.id}: /${app.id} -> 127.0.0.1:${app.port}`);\n }\n startWorkspaceProcesses();\n openBrowser(`http://${gatewayHost}:${actualPort}/${defaultApp}`);\n });\n}\n\nfunction shutdown(): void {\n if (shuttingDown) return;\n shuttingDown = true;\n server.close();\n for (const app of apps) {\n app.process?.kill(\"SIGTERM\");\n }\n setTimeout(() => process.exit(0), 300).unref();\n}\n\nprocess.on(\"SIGINT\", shutdown);\nprocess.on(\"SIGTERM\", shutdown);\n\nlisten(requestedPort);\n"]}
|
|
1
|
+
{"version":3,"file":"workspace-dev.js","sourceRoot":"","sources":["../../src/cli/workspace-dev.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env tsx\nimport { spawn, type ChildProcess } from \"node:child_process\";\nimport fs from \"node:fs\";\nimport http from \"node:http\";\nimport net from \"node:net\";\nimport path from \"node:path\";\nimport type { Duplex } from \"node:stream\";\nimport * as Sentry from \"@sentry/node\";\nimport { extractOAuthStateAppId } from \"../shared/oauth-state.js\";\n\ninterface WorkspaceApp {\n id: string;\n name: string;\n dir: string;\n port: number;\n process?: ChildProcess;\n restartTimer?: NodeJS.Timeout;\n restartAttempts?: number;\n /**\n * Set true once we've successfully connected to the upstream. After that we\n * skip the readiness probe on every request — the child server stays\n * listening for the rest of the dev session.\n */\n ready?: boolean;\n}\n\nconst root = process.cwd();\nconst appsDir = path.join(root, \"apps\");\nfs.mkdirSync(path.join(root, \"data\"), { recursive: true });\nconst gatewayHost = process.env.WORKSPACE_HOST || \"127.0.0.1\";\nconst requestedPort = Number(\n process.env.WORKSPACE_PORT || process.env.PORT || 8080,\n);\nconst appPortStart = Number(process.env.WORKSPACE_APP_PORT_START || 8100);\nconst forceVite = process.env.WORKSPACE_VITE_FORCE === \"1\";\nlet gatewayUrl = `http://${gatewayHost}:${requestedPort}`;\n\nfunction readJson(file: string): any {\n try {\n return JSON.parse(fs.readFileSync(file, \"utf8\"));\n } catch {\n return null;\n }\n}\n\nfunction discoverApps(): WorkspaceApp[] {\n if (!fs.existsSync(appsDir)) return [];\n // existsSync → readdirSync is a TOCTOU race — appsDir can vanish between\n // the two calls (e.g. user running `git checkout` on the workspace mid-dev).\n // Treat ENOENT as \"no apps right now\" and let the next 2s sync recover.\n // Other errors get surfaced to Sentry so we learn about new failure modes.\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(appsDir, { withFileTypes: true });\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code !== \"ENOENT\") {\n console.warn(\n `[workspace] Could not read ${appsDir} (${code ?? \"unknown\"}): ` +\n `${(err as Error).message}`,\n );\n Sentry.captureException(err, {\n tags: { handled: \"dev-discover-readdir\" },\n level: \"warning\",\n });\n }\n return [];\n }\n return entries\n .filter((entry) => entry.isDirectory())\n .map((entry) => {\n const dir = path.join(appsDir, entry.name);\n const pkg = readJson(path.join(dir, \"package.json\"));\n if (!pkg) return null;\n return {\n id: entry.name,\n name: pkg.displayName || pkg.name || entry.name,\n dir,\n port: appPortStart,\n } satisfies WorkspaceApp;\n })\n .filter((app): app is WorkspaceApp => !!app)\n .sort((a, b) => {\n if (a.id === \"dispatch\") return -1;\n if (b.id === \"dispatch\") return 1;\n return a.id.localeCompare(b.id);\n })\n .map((app, index) => ({ ...app, port: appPortStart + index }));\n}\n\nconst apps = discoverApps();\nif (apps.length === 0) {\n console.error(\"[workspace] No apps found under ./apps\");\n process.exit(1);\n}\n\nconst appById = new Map(apps.map((app) => [app.id, app]));\nconst defaultApp =\n process.env.WORKSPACE_DEFAULT_APP &&\n appById.has(process.env.WORKSPACE_DEFAULT_APP)\n ? process.env.WORKSPACE_DEFAULT_APP\n : appById.has(\"dispatch\")\n ? \"dispatch\"\n : apps[0].id;\n\nfunction isChildDevServerUrlLine(line: string): boolean {\n return /^\\s*➜\\s+(?:Local|Network):\\s+https?:\\/\\/(?:localhost|127\\.0\\.0\\.1|\\[::1\\]):\\d+(?:\\/\\S*)?\\s*$/i.test(\n line,\n );\n}\n\nfunction pipeAppOutput(\n prefix: string,\n chunk: unknown,\n write: (value: string) => void,\n): void {\n const lines = String(chunk)\n .split(/\\r?\\n/)\n .filter(Boolean)\n .filter((line) => !isChildDevServerUrlLine(line));\n if (lines.length === 0) return;\n write(lines.map((line) => `${prefix} ${line}`).join(\"\\n\") + \"\\n\");\n}\n\nfunction syncApps(): void {\n const discovered = discoverApps();\n for (const app of discovered) {\n const existing = appById.get(app.id);\n if (existing) {\n existing.name = app.name;\n existing.dir = app.dir;\n continue;\n }\n const usedPorts = new Set(apps.map((existing) => existing.port));\n let port = appPortStart;\n while (usedPorts.has(port)) port++;\n const next = { ...app, port };\n apps.push(next);\n apps.sort((a, b) => {\n if (a.id === \"dispatch\") return -1;\n if (b.id === \"dispatch\") return 1;\n return a.id.localeCompare(b.id);\n });\n appById.set(next.id, next);\n console.log(`[workspace] Detected new app: /${next.id}`);\n startApp(next);\n }\n}\n\nlet syncTimer: NodeJS.Timeout | undefined;\nfunction scheduleSync(): void {\n if (syncTimer) clearTimeout(syncTimer);\n syncTimer = setTimeout(syncApps, 400);\n}\n\nfunction firstPathSegment(url: string | undefined): string | null {\n if (!url) return null;\n try {\n const parsed = new URL(url, \"http://workspace.local\");\n const [segment] = parsed.pathname.split(\"/\").filter(Boolean);\n return segment || null;\n } catch {\n return null;\n }\n}\n\nfunction appForRequest(req: http.IncomingMessage): WorkspaceApp | null {\n const params = new URL(req.url || \"/\", \"http://workspace.local\").searchParams;\n const explicit = params.get(\"_app\");\n if (explicit && appById.has(explicit)) return appById.get(explicit) ?? null;\n\n const direct = firstPathSegment(req.url);\n if (direct && appById.has(direct)) return appById.get(direct) ?? null;\n\n const fromState = extractOAuthStateAppId(params.get(\"state\"));\n if (fromState && appById.has(fromState)) {\n return appById.get(fromState) ?? null;\n }\n\n const referer = req.headers.referer;\n const fromReferer =\n typeof referer === \"string\" ? firstPathSegment(referer) : null;\n return fromReferer && appById.has(fromReferer)\n ? (appById.get(fromReferer) ?? null)\n : null;\n}\n\nfunction startApp(app: WorkspaceApp): void {\n if (app.process && !app.process.killed) return;\n if (app.restartTimer) {\n clearTimeout(app.restartTimer);\n app.restartTimer = undefined;\n }\n\n const basePath = `/${app.id}`;\n const workspaceAppsJson = JSON.stringify(\n apps.map((workspaceApp) => ({\n id: workspaceApp.id,\n name: workspaceApp.name,\n path: `/${workspaceApp.id}`,\n })),\n );\n const child = spawn(\n \"pnpm\",\n [\n \"--dir\",\n app.dir,\n \"exec\",\n \"vite\",\n \"--host\",\n \"127.0.0.1\",\n \"--port\",\n String(app.port),\n \"--strictPort\",\n ...(forceVite ? [\"--force\"] : []),\n ],\n {\n cwd: root,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n env: {\n ...process.env,\n APP_NAME: app.id,\n AGENT_NATIVE_WORKSPACE: \"1\",\n AGENT_NATIVE_WORKSPACE_APPS_JSON: workspaceAppsJson,\n APP_BASE_PATH: basePath,\n VITE_AGENT_NATIVE_WORKSPACE: \"1\",\n VITE_APP_BASE_PATH: basePath,\n PORT: String(app.port),\n WORKSPACE_GATEWAY_URL: gatewayUrl,\n },\n },\n );\n app.process = child;\n\n const prefix = `[${app.id}]`;\n const stableTimer = setTimeout(() => {\n app.restartAttempts = 0;\n }, 5_000);\n stableTimer.unref();\n\n child.stdout?.on(\"data\", (chunk) => {\n pipeAppOutput(prefix, chunk, (value) => process.stdout.write(value));\n });\n child.stderr?.on(\"data\", (chunk) => {\n pipeAppOutput(prefix, chunk, (value) => process.stderr.write(value));\n });\n child.on(\"exit\", (code) => {\n clearTimeout(stableTimer);\n app.process = undefined;\n app.ready = false;\n if (code === 0 || shuttingDown) return;\n app.restartAttempts = (app.restartAttempts ?? 0) + 1;\n const delay = appRestartDelay(app.restartAttempts);\n console.error(\n `${prefix} exited with code ${code}; retrying in ${Math.round(\n delay / 1000,\n )}s`,\n );\n app.restartTimer = setTimeout(() => {\n app.restartTimer = undefined;\n startApp(app);\n }, delay);\n app.restartTimer.unref();\n });\n}\n\nfunction renderIndex(): string {\n return `<!doctype html>\n<html>\n <head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <title>Agent-Native Workspace</title>\n <style>\n body { font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif; margin: 0; padding: 32px; background: #fafafa; color: #171717; }\n main { max-width: 760px; margin: 0 auto; }\n a { color: inherit; text-decoration: none; }\n .grid { display: grid; gap: 12px; margin-top: 20px; }\n .card { display: flex; justify-content: space-between; border: 1px solid #d4d4d4; border-radius: 8px; padding: 14px 16px; background: white; }\n .muted { color: #737373; }\n </style>\n </head>\n <body>\n <main>\n <h1>Agent-Native Workspace</h1>\n <p class=\"muted\">Open an app below. Dispatch is the workspace control plane.</p>\n <div class=\"grid\">\n ${apps\n .map(\n (app) =>\n `<a class=\"card\" href=\"/${app.id}\"><strong>${app.name}</strong><span class=\"muted\">/${app.id}</span></a>`,\n )\n .join(\"\")}\n </div>\n </main>\n </body>\n</html>`;\n}\n\n// On `pnpm dev` the gateway answers requests immediately, but each app's vite\n// server takes a beat to bind its port. Without retry, the user sees an\n// \"App is not ready yet: ECONNREFUSED\" banner on the first page load and has\n// to refresh manually. We do a quick pre-flight TCP connect with retry so\n// startup is invisible for the common case (small/no body, slow boot).\nconst PROXY_READY_TIMEOUT_MS = Number(\n process.env.WORKSPACE_PROXY_READY_TIMEOUT_MS ?? 30_000,\n);\nconst PROXY_READY_RETRY_DELAY_MS = 250;\nconst APP_RESTART_MAX_DELAY_MS = 10_000;\n\nfunction appRestartDelay(attempts: number): number {\n return Math.min(\n 1_000 * 2 ** Math.max(0, attempts - 1),\n APP_RESTART_MAX_DELAY_MS,\n );\n}\n\nfunction probePort(port: number, timeoutMs = 1_000): Promise<boolean> {\n return new Promise((resolve) => {\n const socket = new net.Socket();\n let settled = false;\n const finish = (ok: boolean) => {\n if (settled) return;\n settled = true;\n socket.destroy();\n resolve(ok);\n };\n socket.setTimeout(timeoutMs);\n socket.once(\"connect\", () => finish(true));\n socket.once(\"error\", () => finish(false));\n socket.once(\"timeout\", () => finish(false));\n socket.connect(port, \"127.0.0.1\");\n });\n}\n\nfunction firstHeaderValue(\n value: string | string[] | number | undefined,\n): string | undefined {\n if (Array.isArray(value)) return value[0];\n if (value === undefined) return undefined;\n return String(value);\n}\n\nfunction forwardedProto(req: http.IncomingMessage): string {\n return (\n firstHeaderValue(req.headers[\"x-forwarded-proto\"]) ||\n ((req.socket as { encrypted?: boolean }).encrypted ? \"https\" : \"http\")\n );\n}\n\nfunction forwardedHost(req: http.IncomingMessage): string {\n return (\n firstHeaderValue(req.headers[\"x-forwarded-host\"]) ||\n firstHeaderValue(req.headers.host) ||\n new URL(gatewayUrl).host\n );\n}\n\nfunction proxyHeaders(\n req: http.IncomingMessage,\n targetHost: string,\n): http.OutgoingHttpHeaders {\n return {\n ...req.headers,\n \"x-forwarded-host\": forwardedHost(req),\n \"x-forwarded-proto\": forwardedProto(req),\n host: targetHost,\n };\n}\n\nasync function waitForPort(port: number, deadline: number): Promise<boolean> {\n while (Date.now() < deadline) {\n if (await probePort(port)) return true;\n await new Promise((r) => setTimeout(r, PROXY_READY_RETRY_DELAY_MS));\n }\n return false;\n}\n\nfunction proxyHttp(\n app: WorkspaceApp,\n req: http.IncomingMessage,\n res: http.ServerResponse,\n): void {\n const dispatch = () => {\n const headers = proxyHeaders(req, `127.0.0.1:${app.port}`);\n const proxyReq = http.request(\n {\n hostname: \"127.0.0.1\",\n port: app.port,\n method: req.method,\n path: req.url,\n headers,\n },\n (proxyRes) => {\n app.ready = true;\n res.writeHead(proxyRes.statusCode ?? 502, proxyRes.headers);\n proxyRes.pipe(res);\n },\n );\n\n proxyReq.on(\"error\", (err) => {\n if (res.headersSent) {\n res.end();\n return;\n }\n res.writeHead(502, { \"content-type\": \"text/plain\" });\n res.end(`App \"${app.id}\" is not ready yet: ${err.message}`);\n });\n\n req.pipe(proxyReq);\n };\n\n // Fast path: the upstream has accepted at least one request before, so it's\n // listening. Skip the probe so steady-state requests stay zero-latency.\n if (app.ready) {\n dispatch();\n return;\n }\n\n // Cold path: hold the request open while the child server boots. Node\n // keeps the request body in paused mode until a consumer attaches via\n // pipe(), so awaiting waitForPort() doesn't lose data.\n void waitForPort(app.port, Date.now() + PROXY_READY_TIMEOUT_MS).then(\n (ready) => {\n if (!ready) {\n if (!res.headersSent) {\n res.writeHead(502, { \"content-type\": \"text/plain\" });\n res.end(\n `App \"${app.id}\" is not ready yet: connect ECONNREFUSED 127.0.0.1:${app.port}`,\n );\n } else {\n res.end();\n }\n return;\n }\n app.ready = true;\n dispatch();\n },\n );\n}\n\nfunction proxyUpgrade(\n app: WorkspaceApp,\n req: http.IncomingMessage,\n socket: Duplex,\n head: Buffer,\n): void {\n const target = net.connect(app.port, \"127.0.0.1\", () => {\n const headers = Object.entries(proxyHeaders(req, `127.0.0.1:${app.port}`))\n .flatMap(([key, value]) =>\n Array.isArray(value)\n ? value.map((item) => `${key}: ${item}`)\n : [`${key}: ${value ?? \"\"}`],\n )\n .join(\"\\r\\n\");\n target.write(\n `${req.method} ${req.url} HTTP/${req.httpVersion}\\r\\n${headers}\\r\\n\\r\\n`,\n );\n if (head.length) target.write(head);\n socket.pipe(target).pipe(socket);\n });\n\n target.on(\"error\", () => socket.destroy());\n}\n\nlet shuttingDown = false;\nlet workspaceStarted = false;\n\nfunction handleWatcherError(err: NodeJS.ErrnoException): void {\n // ENOSPC: system inotify watcher limit hit (Linux). Userland-fixable;\n // capture as a warning so we still see frequency in Sentry but don't get\n // paged. Print actionable guidance and continue without watching — the\n // 2s polling interval below keeps app discovery working.\n if (err.code === \"ENOSPC\") {\n console.warn(\n `[workspace] Recursive file watcher hit the system limit (ENOSPC). ` +\n `New apps will still be detected via polling every ~2s. ` +\n `On Linux you can raise the limit with ` +\n `\\`sudo sysctl fs.inotify.max_user_watches=524288\\` ` +\n `(persist via /etc/sysctl.d/*.conf). On macOS/Windows this usually ` +\n `means too many other watchers are running.`,\n );\n Sentry.captureException(err, {\n tags: { handled: \"dev-watch-enospc\" },\n level: \"warning\",\n });\n return;\n }\n // ENOENT: a watched directory disappeared (or a transient subdir under\n // appsDir vanished mid-enumeration). Benign — the polling fallback and\n // future scheduleSync calls will re-establish state. Don't capture.\n if (err.code === \"ENOENT\") {\n console.debug(\n `[workspace] Recursive file watcher saw a directory disappear ` +\n `(ENOENT: ${err.path ?? \"unknown\"}). Polling fallback will recover.`,\n );\n return;\n }\n // Unknown failure mode — keep the dev experience alive (polling still\n // runs) but surface to Sentry as a warning so we learn about new cases.\n console.warn(\n `[workspace] Recursive file watcher failed (${err.code ?? \"unknown\"}): ${err.message}. ` +\n `Falling back to polling.`,\n );\n Sentry.captureException(err, {\n tags: { handled: \"dev-watch-unknown\" },\n level: \"warning\",\n });\n}\n\nfunction startWorkspaceProcesses(): void {\n if (workspaceStarted) return;\n workspaceStarted = true;\n for (const app of apps) startApp(app);\n try {\n const watcher = fs.watch(appsDir, { recursive: true }, scheduleSync);\n // Async errors (e.g. ENOENT when a subdir vanishes mid-watch) surface on\n // the watcher rather than the original call site. Without an `error`\n // listener, Node would treat them as uncaught and crash the dev process.\n watcher.on(\"error\", (err) => {\n handleWatcherError(err as NodeJS.ErrnoException);\n });\n } catch (err) {\n handleWatcherError(err as NodeJS.ErrnoException);\n }\n setInterval(syncApps, 2_000).unref();\n}\n\nfunction openBrowser(url: string): void {\n if (process.env.WORKSPACE_NO_OPEN === \"1\") return;\n const command =\n process.platform === \"darwin\"\n ? \"open\"\n : process.platform === \"win32\"\n ? \"cmd\"\n : \"xdg-open\";\n const args = process.platform === \"win32\" ? [\"/c\", \"start\", \"\", url] : [url];\n const child = spawn(command, args, {\n stdio: \"ignore\",\n detached: true,\n });\n child.unref();\n}\n\nconst server = http.createServer((req, res) => {\n if (req.url === \"/\" || req.url === \"/index.html\") {\n res.writeHead(302, { location: `/${defaultApp}` });\n res.end();\n return;\n }\n\n if (req.url === \"/_workspace/apps\") {\n res.writeHead(200, { \"content-type\": \"application/json\" });\n res.end(\n JSON.stringify(\n apps.map((app) => ({\n id: app.id,\n name: app.name,\n path: `/${app.id}`,\n port: app.port,\n })),\n ),\n );\n return;\n }\n\n const app = appForRequest(req);\n if (!app) {\n res.writeHead(404, { \"content-type\": \"text/html\" });\n res.end(renderIndex());\n return;\n }\n proxyHttp(app, req, res);\n});\n\nserver.on(\"upgrade\", (req, socket, head) => {\n const app = appForRequest(req);\n if (!app) {\n socket.destroy();\n return;\n }\n proxyUpgrade(app, req, socket, head);\n});\n\nfunction listen(port: number, attempts = 20): void {\n server.once(\"error\", (err: NodeJS.ErrnoException) => {\n if (err.code === \"EADDRINUSE\" && attempts > 0) {\n listen(port + 1, attempts - 1);\n return;\n }\n console.error(`[workspace] Could not start gateway: ${err.message}`);\n process.exit(1);\n });\n server.listen(port, gatewayHost, () => {\n const address = server.address();\n const actualPort =\n typeof address === \"object\" && address ? address.port : port;\n gatewayUrl = `http://${gatewayHost}:${actualPort}`;\n console.log(\n `[workspace] Default: http://${gatewayHost}:${actualPort}/${defaultApp}`,\n );\n console.log(`[workspace] Gateway: http://${gatewayHost}:${actualPort}`);\n for (const app of apps) {\n console.log(`[workspace] ${app.id}: /${app.id} -> 127.0.0.1:${app.port}`);\n }\n startWorkspaceProcesses();\n openBrowser(`http://${gatewayHost}:${actualPort}/${defaultApp}`);\n });\n}\n\nfunction shutdown(): void {\n if (shuttingDown) return;\n shuttingDown = true;\n server.close();\n for (const app of apps) {\n app.process?.kill(\"SIGTERM\");\n }\n setTimeout(() => process.exit(0), 300).unref();\n}\n\nprocess.on(\"SIGINT\", shutdown);\nprocess.on(\"SIGTERM\", shutdown);\n\nlisten(requestedPort);\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AssistantChat.d.ts","sourceRoot":"","sources":["../../src/client/AssistantChat.tsx"],"names":[],"mappings":"AAAA,OAAO,KAQN,MAAM,OAAO,CAAC;AA6Bf,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"AssistantChat.d.ts","sourceRoot":"","sources":["../../src/client/AssistantChat.tsx"],"names":[],"mappings":"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"}
|