@codexhost/cli-win32-arm64 0.15.0 → 0.16.1
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/README.md +1 -1
- package/app/codexhost-distribution.json +1 -1
- package/app/console-server.mjs +8 -2
- package/app/console-web.js +73 -16
- package/app/desktop-controller.mjs +593 -30
- package/app/host-runtime.mjs +1474 -565
- package/app/plugins/antigravity/plugin.mjs +6 -1
- package/app/plugins/claude-code/plugin.mjs +24 -31
- package/app/plugins/codebuddy/plugin.mjs +44 -4
- package/app/plugins/codex-usage/plugin.mjs +6 -1
- package/app/plugins/copilot/plugin.mjs +6 -1
- package/app/plugins/cursor-cli/plugin.mjs +6 -1
- package/app/plugins/deepseek-harness/plugin.mjs +30 -5
- package/app/plugins/grok/plugin.mjs +6 -1
- package/app/plugins/hermes/plugin.mjs +6 -1
- package/app/plugins/kimi-code/plugin.mjs +6 -1
- package/app/plugins/kiro-cli/plugin.mjs +6 -1
- package/app/plugins/omp/plugin.mjs +6 -1
- package/app/plugins/opencode/plugin.mjs +6 -1
- package/app/plugins/pi/plugin.mjs +25 -8
- package/app/plugins/qoder/plugin.mjs +6 -1
- package/app/plugins/qoder-cn/plugin.mjs +6 -1
- package/app/plugins/workbuddy/plugin.mjs +44 -4
- package/app/plugins/zcode/plugin.mjs +6 -1
- package/app/renderer-extension.js +1702 -100
- package/bin/codexhost.exe +0 -0
- package/libexec/codexhost-node-repl.exe +0 -0
- package/libexec/codexhost-shim.exe +0 -0
- package/libexec/codexhost-updater.exe +0 -0
- package/package.json +1 -1
package/app/host-runtime.mjs
CHANGED
|
@@ -5369,7 +5369,8 @@ function createBackgroundUpdateManager(dependencies2 = {}) {
|
|
|
5369
5369
|
kind: "npm",
|
|
5370
5370
|
node_path: await requireRegularFile(options2.nodePath, "npm Node.js executable"),
|
|
5371
5371
|
npm_cli_path: await requireRegularFile(options2.npmCliPath, "npm CLI"),
|
|
5372
|
-
npm_launcher_path: await requireRegularFile(options2.npmLauncherPath, "npm codexhost launcher")
|
|
5372
|
+
npm_launcher_path: await requireRegularFile(options2.npmLauncherPath, "npm codexhost launcher"),
|
|
5373
|
+
npm_package_root: requireAbsolutePath(options2.packageRoot, "npm platform package root")
|
|
5373
5374
|
});
|
|
5374
5375
|
} catch (error51) {
|
|
5375
5376
|
await writeFailedStatus(common.statusPath, common.version, "npm", error51);
|
|
@@ -20114,6 +20115,8 @@ var usageStatisticsTotalsSchema = external_exports.strictObject({
|
|
|
20114
20115
|
cachedInputTokens: count,
|
|
20115
20116
|
cacheWriteInputTokens: count,
|
|
20116
20117
|
cacheKnownInputTokens: count,
|
|
20118
|
+
cacheHitCachedInputTokens: count,
|
|
20119
|
+
cacheHitInputTokens: count,
|
|
20117
20120
|
outputTokens: count,
|
|
20118
20121
|
reasoningOutputTokens: count,
|
|
20119
20122
|
/** USD at the public price, summed over the priced requests only. */
|
|
@@ -21024,7 +21027,10 @@ var harnessPluginRouteSchema = external_exports.object({
|
|
|
21024
21027
|
harnessId: harnessPluginIdSchema,
|
|
21025
21028
|
model: harnessModelRefSchema.optional(),
|
|
21026
21029
|
thinkingOptionId: harnessThinkingOptionIdSchema.optional(),
|
|
21027
|
-
permissionModeId: harnessPermissionModeIdSchema.optional()
|
|
21030
|
+
permissionModeId: harnessPermissionModeIdSchema.optional(),
|
|
21031
|
+
/** A draft prewarm create: stays unsubmitted until the user's first Turn.
|
|
21032
|
+
* Desktop forwards only the Model of a main-process prewarm to thread/start. */
|
|
21033
|
+
prewarm: external_exports.literal(true).optional()
|
|
21028
21034
|
}).strict();
|
|
21029
21035
|
function encodeHarnessPluginRoute(route) {
|
|
21030
21036
|
const parsed2 = harnessPluginRouteSchema.parse(route);
|
|
@@ -22494,8 +22500,110 @@ function retainRendererHostResponses(client, hostId2, target) {
|
|
|
22494
22500
|
};
|
|
22495
22501
|
}
|
|
22496
22502
|
|
|
22503
|
+
// packages/desktop-control/dist/renderer-prewarm-consumption.js
|
|
22504
|
+
function isolateRendererPrewarmConsumption(manager, discardExternal) {
|
|
22505
|
+
const record5 = (value2) => value2 !== null && typeof value2 === "object";
|
|
22506
|
+
if (!record5(manager) || !record5(manager.threadCreation))
|
|
22507
|
+
return null;
|
|
22508
|
+
const creation = manager.threadCreation;
|
|
22509
|
+
const originalStart = manager.startConversation;
|
|
22510
|
+
const original = creation.createConversation;
|
|
22511
|
+
const params = creation.params;
|
|
22512
|
+
if (typeof originalStart !== "function" || typeof original !== "function" || !record5(params))
|
|
22513
|
+
return null;
|
|
22514
|
+
const prototype = Object.getPrototypeOf(creation);
|
|
22515
|
+
if (!record5(prototype) || typeof prototype.constructor !== "function")
|
|
22516
|
+
return null;
|
|
22517
|
+
if (Object.keys(creation).some((key) => key !== "params" && typeof creation[key] !== "function") || /#[A-Za-z_$]/u.test(Function.prototype.toString.call(prototype.constructor)))
|
|
22518
|
+
return null;
|
|
22519
|
+
const pool = params.prewarmedThreadManager;
|
|
22520
|
+
if (!record5(pool) || typeof pool.hasPrewarmedThread !== "function" || typeof pool.consumePrewarmedThread !== "function" || typeof pool.deletePrewarmedThread !== "function")
|
|
22521
|
+
return null;
|
|
22522
|
+
const consume = pool.consumePrewarmedThread;
|
|
22523
|
+
const hasPrewarm = pool.hasPrewarmedThread;
|
|
22524
|
+
const draftModels = /* @__PURE__ */ new Map();
|
|
22525
|
+
const draftIdentity = /* @__PURE__ */ Symbol("codexhost draft creation");
|
|
22526
|
+
const external = (model2) => typeof model2 === "string" && model2.startsWith("codexhost/");
|
|
22527
|
+
const routedStart = function(input, options2, ...args) {
|
|
22528
|
+
const draftId = record5(options2) ? options2.clientThreadId : null;
|
|
22529
|
+
const mode = record5(input) && record5(input.collaborationMode) ? input.collaborationMode : null;
|
|
22530
|
+
const origin = mode ? Reflect.get(mode, draftIdentity) : void 0;
|
|
22531
|
+
if (mode && record5(mode.settings) && external(mode.settings.model))
|
|
22532
|
+
return originalStart.call(this, input, options2, ...args);
|
|
22533
|
+
const model2 = (typeof draftId === "string" ? draftModels.get(draftId) : void 0) ?? (typeof origin === "string" ? draftModels.get(origin) : void 0);
|
|
22534
|
+
if (!model2)
|
|
22535
|
+
return originalStart.call(this, input, options2, ...args);
|
|
22536
|
+
if (!record5(input) || !record5(input.collaborationMode) || !record5(input.collaborationMode.settings))
|
|
22537
|
+
throw new Error("External draft creation is missing its native Model settings");
|
|
22538
|
+
const routed = {
|
|
22539
|
+
...input,
|
|
22540
|
+
collaborationMode: {
|
|
22541
|
+
...input.collaborationMode,
|
|
22542
|
+
settings: { ...input.collaborationMode.settings, model: model2 }
|
|
22543
|
+
}
|
|
22544
|
+
};
|
|
22545
|
+
return originalStart.call(this, routed, options2, ...args);
|
|
22546
|
+
};
|
|
22547
|
+
const wrapped = function(input, ...args) {
|
|
22548
|
+
const mode = record5(input) && record5(input.collaborationMode) ? input.collaborationMode : null;
|
|
22549
|
+
const expected = mode && record5(mode.settings) ? mode.settings.model : null;
|
|
22550
|
+
const scopedPool = Object.create(pool);
|
|
22551
|
+
scopedPool.hasPrewarmedThread = (...parameters) => hasPrewarm.apply(pool, parameters);
|
|
22552
|
+
scopedPool.consumePrewarmedThread = async (...consumeArgs) => {
|
|
22553
|
+
const warmed = await consume.apply(pool, consumeArgs);
|
|
22554
|
+
if (!record5(warmed) || !record5(warmed.response))
|
|
22555
|
+
return warmed;
|
|
22556
|
+
const response = warmed.response;
|
|
22557
|
+
if (!external(expected) && !external(response.model))
|
|
22558
|
+
return warmed;
|
|
22559
|
+
if (external(expected) && expected === response.model)
|
|
22560
|
+
return warmed;
|
|
22561
|
+
if (record5(response.thread) && typeof response.thread.id === "string") {
|
|
22562
|
+
const threadId2 = response.thread.id;
|
|
22563
|
+
if (external(response.model))
|
|
22564
|
+
discardExternal(threadId2);
|
|
22565
|
+
else
|
|
22566
|
+
void Promise.resolve().then(() => pool.deletePrewarmedThread(threadId2)).catch(() => void 0);
|
|
22567
|
+
}
|
|
22568
|
+
return null;
|
|
22569
|
+
};
|
|
22570
|
+
const invocation = Object.create(creation);
|
|
22571
|
+
invocation.params = { ...params, prewarmedThreadManager: scopedPool };
|
|
22572
|
+
return original.call(invocation, input, ...args);
|
|
22573
|
+
};
|
|
22574
|
+
creation.createConversation = wrapped;
|
|
22575
|
+
manager.startConversation = routedStart;
|
|
22576
|
+
return {
|
|
22577
|
+
selectDraft(draftId, model2, creationModes = []) {
|
|
22578
|
+
if (draftId === void 0) {
|
|
22579
|
+
if (model2 === null)
|
|
22580
|
+
draftModels.clear();
|
|
22581
|
+
} else if (model2 === null)
|
|
22582
|
+
draftModels.delete(draftId);
|
|
22583
|
+
else {
|
|
22584
|
+
if (!draftId.startsWith("client-new-thread:") || !external(model2))
|
|
22585
|
+
throw new Error("External draft route is missing its client Thread identity");
|
|
22586
|
+
draftModels.set(draftId, model2);
|
|
22587
|
+
for (const mode of creationModes)
|
|
22588
|
+
Object.defineProperty(mode, draftIdentity, {
|
|
22589
|
+
configurable: true,
|
|
22590
|
+
enumerable: true,
|
|
22591
|
+
value: draftId
|
|
22592
|
+
});
|
|
22593
|
+
}
|
|
22594
|
+
},
|
|
22595
|
+
dispose() {
|
|
22596
|
+
draftModels.clear();
|
|
22597
|
+
if (manager.startConversation === routedStart)
|
|
22598
|
+
manager.startConversation = originalStart;
|
|
22599
|
+
if (creation.createConversation === wrapped)
|
|
22600
|
+
creation.createConversation = original;
|
|
22601
|
+
}
|
|
22602
|
+
};
|
|
22603
|
+
}
|
|
22604
|
+
|
|
22497
22605
|
// packages/desktop-control/dist/renderer-draft-prewarm-runtime.js
|
|
22498
|
-
function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewarmedThreadManager, isCurrentManager, retainResponses = retainRendererHostResponses) {
|
|
22606
|
+
function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewarmedThreadManager, isCurrentManager, retainResponses = retainRendererHostResponses, isolateConsumption = isolateRendererPrewarmConsumption) {
|
|
22499
22607
|
let disposed = false;
|
|
22500
22608
|
const originalSend = bridge.sendRequest;
|
|
22501
22609
|
const originalPrewarm = bridge.prewarmThreadStart;
|
|
@@ -22885,25 +22993,15 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
|
|
|
22885
22993
|
return false;
|
|
22886
22994
|
return selectedModel !== null && (method.startsWith("thread/") || method.startsWith("turn/") || method.startsWith("review/"));
|
|
22887
22995
|
};
|
|
22888
|
-
const routeThreadStart = (parameters) => {
|
|
22889
|
-
if (!isRecord19(parameters) || parameters.ephemeral === true) {
|
|
22890
|
-
return parameters;
|
|
22891
|
-
}
|
|
22892
|
-
return {
|
|
22893
|
-
...parameters,
|
|
22894
|
-
...selectedModel === null ? {} : { model: selectedModel }
|
|
22895
|
-
};
|
|
22896
|
-
};
|
|
22897
22996
|
const routedSend = (method, parameters, options2) => {
|
|
22898
22997
|
if (method === "turn/start" || method === "thread/resume" || method === "codexhost/thread/command/execute") {
|
|
22899
22998
|
const threadId2 = threadIdFromParameters(parameters);
|
|
22900
22999
|
if (threadId2)
|
|
22901
23000
|
externalPrewarms.delete(threadId2);
|
|
22902
23001
|
}
|
|
22903
|
-
const
|
|
22904
|
-
const
|
|
22905
|
-
const
|
|
22906
|
-
const unresolvedThreadId = shouldResolveThreadOwnership(method, routedParameters);
|
|
23002
|
+
const sendBridged = () => initializeBridge().then(() => enqueueBridgeRequest(method, parameters, options2));
|
|
23003
|
+
const sendDirect = () => options2 === void 0 ? originalSend.call(bridge, method, parameters) : originalSend.call(bridge, method, parameters, options2);
|
|
23004
|
+
const unresolvedThreadId = shouldResolveThreadOwnership(method, parameters);
|
|
22907
23005
|
if (unresolvedThreadId) {
|
|
22908
23006
|
return resolveThreadOwnership(unresolvedThreadId).then((owner) => owner === "external" ? sendBridged() : sendDirect(), (error51) => {
|
|
22909
23007
|
if ((method === "thread/read" || method === "thread/resume") && isUnsupportedPosixBridgeSpawn(error51)) {
|
|
@@ -22916,7 +23014,7 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
|
|
|
22916
23014
|
throw error51;
|
|
22917
23015
|
});
|
|
22918
23016
|
}
|
|
22919
|
-
return shouldUseBridge(method,
|
|
23017
|
+
return shouldUseBridge(method, parameters) ? sendBridged() : sendDirect();
|
|
22920
23018
|
};
|
|
22921
23019
|
const publishDraftWorkspace = (parameters) => {
|
|
22922
23020
|
if (!isRecord19(parameters) || parameters.ephemeral === true)
|
|
@@ -22945,10 +23043,10 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
|
|
|
22945
23043
|
for (const threadId2 of externalPrewarms)
|
|
22946
23044
|
discardExternalPrewarm(threadId2);
|
|
22947
23045
|
};
|
|
23046
|
+
const restoreConsumption = isolateConsumption(manager, discardExternalPrewarm);
|
|
22948
23047
|
const routedPrewarm = (parameters, options2) => {
|
|
22949
|
-
const
|
|
22950
|
-
const
|
|
22951
|
-
const routedParameters = external ? { ...routed, codexhostPrewarm: true } : routed;
|
|
23048
|
+
const external = isRecord19(parameters) && parameters.ephemeral !== true && typeof parameters.model === "string" && parameters.model.startsWith("codexhost/");
|
|
23049
|
+
const routedParameters = external ? { ...parameters, codexhostPrewarm: true } : parameters;
|
|
22952
23050
|
const generation = prewarmGeneration;
|
|
22953
23051
|
publishDraftWorkspace(routedParameters);
|
|
22954
23052
|
const pending = shouldUseBridge("thread/start", routedParameters) ? routedSend("thread/start", routedParameters, options2) : options2 === void 0 ? originalPrewarm.call(bridge, routedParameters) : originalPrewarm.call(bridge, routedParameters, options2);
|
|
@@ -23004,6 +23102,7 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
|
|
|
23004
23102
|
const policy = Object.freeze({
|
|
23005
23103
|
state: "ready",
|
|
23006
23104
|
hostId: hostId2,
|
|
23105
|
+
scopedCreation: restoreConsumption !== null,
|
|
23007
23106
|
owns(candidateManager, candidate, candidateHostId, candidatePrewarmedThreadManager, requiresCurrentManager) {
|
|
23008
23107
|
return !disposed && candidateManager === manager && candidate === bridge && candidateHostId === hostId2 && candidatePrewarmedThreadManager === prewarmedThreadManager && requiresCurrentManager === !!isCurrentManager;
|
|
23009
23108
|
},
|
|
@@ -23012,12 +23111,13 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
|
|
|
23012
23111
|
throw new Error("Renderer request manager is retired");
|
|
23013
23112
|
return manager;
|
|
23014
23113
|
},
|
|
23015
|
-
select(model2) {
|
|
23114
|
+
select(model2, draftId, creationModes) {
|
|
23016
23115
|
if (disposed || isCurrentManager && !isCurrentManager())
|
|
23017
23116
|
throw new Error("Renderer request manager is retired");
|
|
23018
23117
|
if (model2 !== null && (typeof model2 !== "string" || !model2.startsWith("codexhost/"))) {
|
|
23019
23118
|
throw new Error("Draft route Model must be a codexhost transport carrier");
|
|
23020
23119
|
}
|
|
23120
|
+
restoreConsumption?.selectDraft(draftId, model2, creationModes);
|
|
23021
23121
|
if (selectedModel === model2)
|
|
23022
23122
|
return false;
|
|
23023
23123
|
selectedModel = model2;
|
|
@@ -23040,6 +23140,7 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
|
|
|
23040
23140
|
disposed = true;
|
|
23041
23141
|
prewarmGeneration += 1;
|
|
23042
23142
|
retireResponses();
|
|
23143
|
+
restoreConsumption?.dispose();
|
|
23043
23144
|
if (bridge.sendRequest === routedSend)
|
|
23044
23145
|
bridge.sendRequest = originalSend;
|
|
23045
23146
|
if (bridge.prewarmThreadStart === routedPrewarm) {
|
|
@@ -23077,14 +23178,14 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
|
|
|
23077
23178
|
|
|
23078
23179
|
// packages/desktop-control/dist/renderer-host-discovery.js
|
|
23079
23180
|
function requestManagerFromHookState(value2, hostId2) {
|
|
23080
|
-
const
|
|
23181
|
+
const record5 = (candidate) => typeof candidate === "object" && candidate !== null;
|
|
23081
23182
|
const manager = (candidate) => {
|
|
23082
|
-
if (!
|
|
23183
|
+
if (!record5(candidate) || !record5(candidate.requestClient) || !record5(candidate.prewarmedThreadManager))
|
|
23083
23184
|
return null;
|
|
23084
23185
|
const bridge = candidate.requestClient;
|
|
23085
23186
|
return typeof candidate.sendRequest === "function" && typeof bridge.sendRequest === "function" && typeof bridge.prewarmThreadStart === "function" && typeof bridge.enqueueRequest === "function" && typeof candidate.prewarmedThreadManager.discardAllPrewarmedThreads === "function" ? candidate : null;
|
|
23086
23187
|
};
|
|
23087
|
-
if (!
|
|
23188
|
+
if (!record5(value2))
|
|
23088
23189
|
return null;
|
|
23089
23190
|
const direct = manager(value2) ?? manager(value2.manager);
|
|
23090
23191
|
if (direct)
|
|
@@ -23288,6 +23389,372 @@ function installRendererHostRouting(root, target, discover, resolve, createPolic
|
|
|
23288
23389
|
return routing;
|
|
23289
23390
|
}
|
|
23290
23391
|
|
|
23392
|
+
// packages/desktop-control/dist/renderer-host-rpc-discovery.js
|
|
23393
|
+
function findRendererAppScopeStore(root) {
|
|
23394
|
+
const MAX_VISITED_FIBERS = 5e4;
|
|
23395
|
+
const record5 = (value2) => typeof value2 === "object" && value2 !== null;
|
|
23396
|
+
const container = root.getElementById?.("root");
|
|
23397
|
+
if (!record5(container))
|
|
23398
|
+
return null;
|
|
23399
|
+
const key = Object.getOwnPropertyNames(container).find((name) => name.startsWith("__reactContainer$"));
|
|
23400
|
+
const first = key ? container[key] : null;
|
|
23401
|
+
if (!record5(first))
|
|
23402
|
+
return null;
|
|
23403
|
+
const isScopeHandle = (value2) => record5(value2) && record5(value2.node) && "chain" in value2 && "scope" in value2 && typeof value2.get === "function" && typeof value2.set === "function" && typeof value2.watch === "function";
|
|
23404
|
+
const stack = [first];
|
|
23405
|
+
const seen = /* @__PURE__ */ new Set();
|
|
23406
|
+
while (stack.length && seen.size < MAX_VISITED_FIBERS) {
|
|
23407
|
+
const fiber = stack.pop();
|
|
23408
|
+
if (seen.has(fiber))
|
|
23409
|
+
continue;
|
|
23410
|
+
seen.add(fiber);
|
|
23411
|
+
let hook = fiber.memoizedState;
|
|
23412
|
+
for (let index = 0; record5(hook) && "next" in hook && index < 150; index += 1) {
|
|
23413
|
+
const state = hook.memoizedState;
|
|
23414
|
+
const handle = record5(state) ? state.current : null;
|
|
23415
|
+
if (isScopeHandle(handle)) {
|
|
23416
|
+
let node = handle.node;
|
|
23417
|
+
const nodes = /* @__PURE__ */ new Set();
|
|
23418
|
+
while (record5(node.parent) && !nodes.has(node.parent)) {
|
|
23419
|
+
nodes.add(node);
|
|
23420
|
+
node = node.parent;
|
|
23421
|
+
}
|
|
23422
|
+
const bindings = node.familyBindings;
|
|
23423
|
+
return record5(bindings) && typeof bindings.get === "function" && typeof bindings.entries === "function" ? node : null;
|
|
23424
|
+
}
|
|
23425
|
+
hook = hook.next;
|
|
23426
|
+
}
|
|
23427
|
+
if (record5(fiber.sibling))
|
|
23428
|
+
stack.push(fiber.sibling);
|
|
23429
|
+
if (record5(fiber.child))
|
|
23430
|
+
stack.push(fiber.child);
|
|
23431
|
+
}
|
|
23432
|
+
return null;
|
|
23433
|
+
}
|
|
23434
|
+
function findRendererHostRpcFamily(store) {
|
|
23435
|
+
const record5 = (value2) => typeof value2 === "object" && value2 !== null;
|
|
23436
|
+
const families = /* @__PURE__ */ new Set();
|
|
23437
|
+
for (const [definition, members] of store.familyBindings) {
|
|
23438
|
+
if (!record5(definition) || definition.kind !== "signal-family")
|
|
23439
|
+
continue;
|
|
23440
|
+
if (!record5(members) || typeof members.get !== "function")
|
|
23441
|
+
continue;
|
|
23442
|
+
for (const [hostId2, member] of members) {
|
|
23443
|
+
if (typeof hostId2 !== "string" || !record5(member))
|
|
23444
|
+
continue;
|
|
23445
|
+
const signal = member.value;
|
|
23446
|
+
if (!record5(signal) || typeof signal.get !== "function")
|
|
23447
|
+
continue;
|
|
23448
|
+
let value2;
|
|
23449
|
+
try {
|
|
23450
|
+
value2 = signal.get();
|
|
23451
|
+
} catch {
|
|
23452
|
+
continue;
|
|
23453
|
+
}
|
|
23454
|
+
if (record5(value2) && Object.keys(value2).length === 2 && typeof value2.status === "string" && record5(value2.client) && value2.client.hostId === hostId2 && "rpc" in value2.client) {
|
|
23455
|
+
families.add(members);
|
|
23456
|
+
break;
|
|
23457
|
+
}
|
|
23458
|
+
}
|
|
23459
|
+
}
|
|
23460
|
+
if (families.size !== 1)
|
|
23461
|
+
return null;
|
|
23462
|
+
return { store, family: families.values().next().value };
|
|
23463
|
+
}
|
|
23464
|
+
function resolveRendererHostRpc(discovery, hostId2) {
|
|
23465
|
+
const record5 = (value3) => typeof value3 === "object" && value3 !== null;
|
|
23466
|
+
const signal = discovery.family.get(hostId2)?.value;
|
|
23467
|
+
if (!record5(signal) || typeof signal.get !== "function")
|
|
23468
|
+
return null;
|
|
23469
|
+
let value2;
|
|
23470
|
+
try {
|
|
23471
|
+
value2 = signal.get();
|
|
23472
|
+
} catch {
|
|
23473
|
+
return null;
|
|
23474
|
+
}
|
|
23475
|
+
if (!record5(value2) || value2.status !== "ready" || !record5(value2.client) || value2.client.hostId !== hostId2)
|
|
23476
|
+
return null;
|
|
23477
|
+
const rpc = value2.client.rpc;
|
|
23478
|
+
return typeof rpc === "function" || record5(rpc) ? rpc : null;
|
|
23479
|
+
}
|
|
23480
|
+
function rendererHostRpcHostIds(discovery) {
|
|
23481
|
+
return [...discovery.family.keys()].filter((hostId2) => typeof hostId2 === "string");
|
|
23482
|
+
}
|
|
23483
|
+
|
|
23484
|
+
// packages/desktop-control/dist/renderer-host-rpc-routing.js
|
|
23485
|
+
function installRendererHostRpcRouting(root, target, dependencies2) {
|
|
23486
|
+
const existing = target.__codexhostHostRoutingV1;
|
|
23487
|
+
if (existing)
|
|
23488
|
+
return existing;
|
|
23489
|
+
let disposed = false;
|
|
23490
|
+
let discovery = null;
|
|
23491
|
+
const routes = /* @__PURE__ */ new Map();
|
|
23492
|
+
const read = () => {
|
|
23493
|
+
if (disposed)
|
|
23494
|
+
return null;
|
|
23495
|
+
if (!discovery) {
|
|
23496
|
+
const store = dependencies2.findStore(root);
|
|
23497
|
+
discovery = store ? dependencies2.findFamily(store) : null;
|
|
23498
|
+
}
|
|
23499
|
+
return discovery;
|
|
23500
|
+
};
|
|
23501
|
+
if (!read())
|
|
23502
|
+
return null;
|
|
23503
|
+
const isRecord19 = (value2) => typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
|
|
23504
|
+
const externalDrafts = /* @__PURE__ */ new Map();
|
|
23505
|
+
const selectedModels = /* @__PURE__ */ new Map();
|
|
23506
|
+
const prewarmCarrier = (carrier) => {
|
|
23507
|
+
const prefix = "codexhost/plugin-v1@";
|
|
23508
|
+
if (!carrier.startsWith(prefix))
|
|
23509
|
+
return null;
|
|
23510
|
+
try {
|
|
23511
|
+
const json2 = carrier.slice(prefix.length).replace(/[a-f0-9]{2}/gu, (byte) => String.fromCharCode(Number.parseInt(byte, 16)));
|
|
23512
|
+
const route = JSON.parse(json2);
|
|
23513
|
+
if (!isRecord19(route))
|
|
23514
|
+
return null;
|
|
23515
|
+
const payload = [...JSON.stringify({ ...route, prewarm: true })].map((character) => character.charCodeAt(0).toString(16).padStart(2, "0")).join("");
|
|
23516
|
+
return `${prefix}${payload}`;
|
|
23517
|
+
} catch {
|
|
23518
|
+
return null;
|
|
23519
|
+
}
|
|
23520
|
+
};
|
|
23521
|
+
const publishDraftWorkspace = (hostId2, cwd) => {
|
|
23522
|
+
if (typeof cwd !== "string" || cwd.length === 0)
|
|
23523
|
+
return;
|
|
23524
|
+
const drafts = isRecord19(target.__codexhostDraftWorkspacesV1) ? target.__codexhostDraftWorkspacesV1 : {};
|
|
23525
|
+
if (drafts[hostId2] === cwd)
|
|
23526
|
+
return;
|
|
23527
|
+
drafts[hostId2] = cwd;
|
|
23528
|
+
Object.defineProperty(target, "__codexhostDraftWorkspacesV1", {
|
|
23529
|
+
configurable: true,
|
|
23530
|
+
value: drafts
|
|
23531
|
+
});
|
|
23532
|
+
if (typeof target.dispatchEvent === "function" && typeof CustomEvent === "function") {
|
|
23533
|
+
target.dispatchEvent(new CustomEvent("codexhost:draft-workspace", { detail: { hostId: hostId2, cwd } }));
|
|
23534
|
+
}
|
|
23535
|
+
};
|
|
23536
|
+
const routeCreationCall = (message2) => {
|
|
23537
|
+
if (!Array.isArray(message2) || message2.length !== 2 || message2[0] !== "push")
|
|
23538
|
+
return message2;
|
|
23539
|
+
const expression = message2[1];
|
|
23540
|
+
if (!Array.isArray(expression) || expression.length !== 4 || expression[0] !== "pipeline")
|
|
23541
|
+
return message2;
|
|
23542
|
+
const [, importId, path43, args] = expression;
|
|
23543
|
+
if (!Array.isArray(path43) || path43.length !== 1 || !Array.isArray(args))
|
|
23544
|
+
return message2;
|
|
23545
|
+
const [input, options2] = args;
|
|
23546
|
+
if (!isRecord19(input) || !isRecord19(input.collaborationMode))
|
|
23547
|
+
return message2;
|
|
23548
|
+
const settings = input.collaborationMode.settings;
|
|
23549
|
+
if (!isRecord19(settings))
|
|
23550
|
+
return message2;
|
|
23551
|
+
let model2 = null;
|
|
23552
|
+
if (path43[0] === "startConversation") {
|
|
23553
|
+
const draftId = isRecord19(options2) ? options2.clientThreadId : null;
|
|
23554
|
+
model2 = typeof draftId === "string" ? externalDrafts.get(draftId)?.model ?? null : null;
|
|
23555
|
+
} else if (path43[0] === "prewarmConversation") {
|
|
23556
|
+
if (input.ephemeral !== true)
|
|
23557
|
+
publishDraftWorkspace("local", input.cwd);
|
|
23558
|
+
const selected = selectedModels.get("local");
|
|
23559
|
+
model2 = selected ? prewarmCarrier(selected) : null;
|
|
23560
|
+
}
|
|
23561
|
+
if (!model2)
|
|
23562
|
+
return message2;
|
|
23563
|
+
return [
|
|
23564
|
+
"push",
|
|
23565
|
+
[
|
|
23566
|
+
"pipeline",
|
|
23567
|
+
importId,
|
|
23568
|
+
path43,
|
|
23569
|
+
[
|
|
23570
|
+
{
|
|
23571
|
+
...input,
|
|
23572
|
+
collaborationMode: { ...input.collaborationMode, settings: { ...settings, model: model2 } }
|
|
23573
|
+
},
|
|
23574
|
+
...args.slice(1)
|
|
23575
|
+
]
|
|
23576
|
+
]
|
|
23577
|
+
];
|
|
23578
|
+
};
|
|
23579
|
+
const port = dependencies2.portPrototype;
|
|
23580
|
+
const originalPostMessage = port.postMessage;
|
|
23581
|
+
const postMessage = function(message2, ...rest) {
|
|
23582
|
+
let routed = message2;
|
|
23583
|
+
try {
|
|
23584
|
+
routed = disposed ? message2 : routeCreationCall(message2);
|
|
23585
|
+
} catch {
|
|
23586
|
+
routed = message2;
|
|
23587
|
+
}
|
|
23588
|
+
return originalPostMessage.call(this, routed, ...rest);
|
|
23589
|
+
};
|
|
23590
|
+
port.postMessage = postMessage;
|
|
23591
|
+
const createRoute = (hostId2, rpc) => {
|
|
23592
|
+
let retired = false;
|
|
23593
|
+
const isCurrent = () => !retired && !disposed && routes.get(hostId2)?.rpc === rpc;
|
|
23594
|
+
const manager = Object.freeze({
|
|
23595
|
+
kind: "main-process-rpc",
|
|
23596
|
+
getHostId: () => hostId2,
|
|
23597
|
+
sendRequest(method, params, options2) {
|
|
23598
|
+
if (!isCurrent())
|
|
23599
|
+
return Promise.reject(new Error(`Renderer request manager is retired for ${hostId2}`));
|
|
23600
|
+
return options2 === void 0 ? rpc.sendRequest(method, params) : rpc.sendRequest(method, params, options2);
|
|
23601
|
+
},
|
|
23602
|
+
// The main process broadcasts every app-server notification to its windows,
|
|
23603
|
+
// including codexhost methods Desktop's own notification table drops.
|
|
23604
|
+
addNotificationCallback(methods, listener) {
|
|
23605
|
+
const accepted = new Set(typeof methods === "string" ? [methods] : methods);
|
|
23606
|
+
const onMessage = (event) => {
|
|
23607
|
+
const { source, data } = event;
|
|
23608
|
+
if (source != null && source !== target)
|
|
23609
|
+
return;
|
|
23610
|
+
if (!isRecord19(data) || data.type !== "mcp-notification" || data.hostId !== hostId2 || typeof data.method !== "string" || !accepted.has(data.method) || !isCurrent())
|
|
23611
|
+
return;
|
|
23612
|
+
listener({ method: data.method, params: data.params });
|
|
23613
|
+
};
|
|
23614
|
+
target.addEventListener?.("message", onMessage);
|
|
23615
|
+
return () => target.removeEventListener?.("message", onMessage);
|
|
23616
|
+
}
|
|
23617
|
+
});
|
|
23618
|
+
const clearDrafts = () => {
|
|
23619
|
+
for (const [draftId, draft] of externalDrafts) {
|
|
23620
|
+
if (draft.owner === policy)
|
|
23621
|
+
externalDrafts.delete(draftId);
|
|
23622
|
+
}
|
|
23623
|
+
};
|
|
23624
|
+
const clear = () => isCurrent() ? Promise.resolve(rpc.clearPrewarmedThreads()).then(() => void 0) : Promise.reject(new Error("Renderer request manager is retired"));
|
|
23625
|
+
const policy = Object.freeze({
|
|
23626
|
+
state: "ready",
|
|
23627
|
+
hostId: hostId2,
|
|
23628
|
+
scopedCreation: true,
|
|
23629
|
+
requestTarget: () => {
|
|
23630
|
+
if (!isCurrent())
|
|
23631
|
+
throw new Error("Renderer request manager is retired");
|
|
23632
|
+
return manager;
|
|
23633
|
+
},
|
|
23634
|
+
select(model2, draftId) {
|
|
23635
|
+
if (!isCurrent())
|
|
23636
|
+
throw new Error("Renderer request manager is retired");
|
|
23637
|
+
if (model2 !== null && (typeof model2 !== "string" || !model2.startsWith("codexhost/"))) {
|
|
23638
|
+
throw new Error("Draft route Model must be a codexhost transport carrier");
|
|
23639
|
+
}
|
|
23640
|
+
if (draftId === void 0) {
|
|
23641
|
+
if (model2 === null)
|
|
23642
|
+
clearDrafts();
|
|
23643
|
+
} else if (model2 === null) {
|
|
23644
|
+
if (externalDrafts.get(draftId)?.owner === policy)
|
|
23645
|
+
externalDrafts.delete(draftId);
|
|
23646
|
+
} else {
|
|
23647
|
+
if (!draftId.startsWith("client-new-thread:"))
|
|
23648
|
+
throw new Error("External draft route is missing its client Thread identity");
|
|
23649
|
+
externalDrafts.set(draftId, { model: model2, owner: policy });
|
|
23650
|
+
}
|
|
23651
|
+
if ((selectedModels.get(hostId2) ?? null) === model2)
|
|
23652
|
+
return false;
|
|
23653
|
+
if (model2 === null)
|
|
23654
|
+
selectedModels.delete(hostId2);
|
|
23655
|
+
else
|
|
23656
|
+
selectedModels.set(hostId2, model2);
|
|
23657
|
+
void clear().catch(() => void 0);
|
|
23658
|
+
return true;
|
|
23659
|
+
},
|
|
23660
|
+
clear,
|
|
23661
|
+
dispose() {
|
|
23662
|
+
if (retired)
|
|
23663
|
+
return;
|
|
23664
|
+
retired = true;
|
|
23665
|
+
clearDrafts();
|
|
23666
|
+
selectedModels.delete(hostId2);
|
|
23667
|
+
}
|
|
23668
|
+
});
|
|
23669
|
+
return { hostId: hostId2, manager, policy };
|
|
23670
|
+
};
|
|
23671
|
+
const retire = (hostId2) => {
|
|
23672
|
+
const entry = routes.get(hostId2);
|
|
23673
|
+
routes.delete(hostId2);
|
|
23674
|
+
entry?.route.policy.dispose();
|
|
23675
|
+
};
|
|
23676
|
+
const routeFor = (hostId2) => {
|
|
23677
|
+
const current = read();
|
|
23678
|
+
const rpc = current ? dependencies2.resolve(current, hostId2) : null;
|
|
23679
|
+
const previous = routes.get(hostId2);
|
|
23680
|
+
if (rpc && previous?.rpc === rpc)
|
|
23681
|
+
return previous.route;
|
|
23682
|
+
retire(hostId2);
|
|
23683
|
+
if (!rpc)
|
|
23684
|
+
return null;
|
|
23685
|
+
const route = createRoute(hostId2, rpc);
|
|
23686
|
+
routes.set(hostId2, { route, rpc });
|
|
23687
|
+
return route;
|
|
23688
|
+
};
|
|
23689
|
+
const publish = (route) => {
|
|
23690
|
+
const policy = route?.policy;
|
|
23691
|
+
if (target.__codexhostDraftPrewarmPolicyV1 === policy)
|
|
23692
|
+
return;
|
|
23693
|
+
Object.defineProperty(target, "__codexhostDraftPrewarmPolicyV1", {
|
|
23694
|
+
configurable: true,
|
|
23695
|
+
value: policy
|
|
23696
|
+
});
|
|
23697
|
+
if (typeof target.dispatchEvent === "function" && typeof CustomEvent === "function") {
|
|
23698
|
+
target.dispatchEvent(new CustomEvent("codexhost:draft-prewarm-policy-changed"));
|
|
23699
|
+
}
|
|
23700
|
+
};
|
|
23701
|
+
const composerHostId = (composer) => {
|
|
23702
|
+
const hostIds = new Set(dependencies2.composerHostIds(composer).hostIds);
|
|
23703
|
+
const hostId2 = hostIds.size === 1 ? hostIds.values().next().value : null;
|
|
23704
|
+
return typeof hostId2 === "string" && hostId2 ? hostId2 : null;
|
|
23705
|
+
};
|
|
23706
|
+
const routing = {
|
|
23707
|
+
knownHostIds() {
|
|
23708
|
+
const current = read();
|
|
23709
|
+
return current ? dependencies2.hostIds(current) : [];
|
|
23710
|
+
},
|
|
23711
|
+
forHost(hostId2) {
|
|
23712
|
+
return hostId2 && !disposed ? routeFor(hostId2) : null;
|
|
23713
|
+
},
|
|
23714
|
+
hostIdForComposer(composer) {
|
|
23715
|
+
if (disposed)
|
|
23716
|
+
return null;
|
|
23717
|
+
try {
|
|
23718
|
+
return composerHostId(composer);
|
|
23719
|
+
} catch {
|
|
23720
|
+
return null;
|
|
23721
|
+
}
|
|
23722
|
+
},
|
|
23723
|
+
forComposer(composer) {
|
|
23724
|
+
if (disposed)
|
|
23725
|
+
return null;
|
|
23726
|
+
let hostId2;
|
|
23727
|
+
try {
|
|
23728
|
+
hostId2 = composerHostId(composer);
|
|
23729
|
+
} catch {
|
|
23730
|
+
hostId2 = null;
|
|
23731
|
+
}
|
|
23732
|
+
const route = hostId2 ? routeFor(hostId2) : null;
|
|
23733
|
+
if (!composer)
|
|
23734
|
+
publish(route);
|
|
23735
|
+
return route;
|
|
23736
|
+
},
|
|
23737
|
+
dispose() {
|
|
23738
|
+
if (disposed)
|
|
23739
|
+
return;
|
|
23740
|
+
disposed = true;
|
|
23741
|
+
for (const hostId2 of [...routes.keys()])
|
|
23742
|
+
retire(hostId2);
|
|
23743
|
+
discovery = null;
|
|
23744
|
+
externalDrafts.clear();
|
|
23745
|
+
selectedModels.clear();
|
|
23746
|
+
if (port.postMessage === postMessage)
|
|
23747
|
+
port.postMessage = originalPostMessage;
|
|
23748
|
+
if (target.__codexhostHostRoutingV1 === routing) {
|
|
23749
|
+
delete target.__codexhostHostRoutingV1;
|
|
23750
|
+
publish(null);
|
|
23751
|
+
}
|
|
23752
|
+
}
|
|
23753
|
+
};
|
|
23754
|
+
Object.defineProperty(target, "__codexhostHostRoutingV1", { configurable: true, value: routing });
|
|
23755
|
+
return routing;
|
|
23756
|
+
}
|
|
23757
|
+
|
|
23291
23758
|
// packages/desktop-control/dist/renderer-draft-prewarm-policy.js
|
|
23292
23759
|
var REQUEST_MANAGER_WAIT_TIMEOUT_MS = 6e4;
|
|
23293
23760
|
var REQUEST_MANAGER_POLL_INTERVAL_MS = 25;
|
|
@@ -23299,14 +23766,41 @@ function directRendererInstaller() {
|
|
|
23299
23766
|
const resolveRendererHostManager = ${resolveRendererHostManager.toString()};
|
|
23300
23767
|
const retainRendererHostResponses = ${retainRendererHostResponses.toString()};
|
|
23301
23768
|
const createDraftPrewarmPolicyBridge = ${createDraftPrewarmPolicyBridge.toString()};
|
|
23302
|
-
const
|
|
23303
|
-
|
|
23304
|
-
|
|
23769
|
+
const isolateRendererPrewarmConsumption = ${isolateRendererPrewarmConsumption.toString()};
|
|
23770
|
+
const discover = (root) =>
|
|
23771
|
+
discoverRendererHosts(root, committedReactAncestors, requestManagerFromHookState);
|
|
23772
|
+
const installNative = () => (${installRendererHostRouting.toString()})(
|
|
23773
|
+
document, window, discover,
|
|
23305
23774
|
(discovery, hostId) => resolveRendererHostManager(discovery, hostId, requestManagerFromHookState),
|
|
23306
23775
|
(manager, bridge, hostId, target, prewarmed, isCurrent) => createDraftPrewarmPolicyBridge(
|
|
23307
23776
|
manager, bridge, hostId, target, prewarmed, isCurrent, retainRendererHostResponses,
|
|
23777
|
+
isolateRendererPrewarmConsumption,
|
|
23308
23778
|
),
|
|
23309
23779
|
);
|
|
23780
|
+
const installRpc = () => typeof MessagePort !== 'function' ? null : (${installRendererHostRpcRouting.toString()})(document, window, {
|
|
23781
|
+
findStore: ${findRendererAppScopeStore.toString()},
|
|
23782
|
+
findFamily: ${findRendererHostRpcFamily.toString()},
|
|
23783
|
+
resolve: ${resolveRendererHostRpc.toString()},
|
|
23784
|
+
hostIds: ${rendererHostRpcHostIds.toString()},
|
|
23785
|
+
composerHostIds: (composer) => {
|
|
23786
|
+
const source = composer?.matches?.('[data-codex-composer], [contenteditable="true"][role="textbox"]')
|
|
23787
|
+
? { querySelectorAll: () => [composer] }
|
|
23788
|
+
: (composer ?? document);
|
|
23789
|
+
return discover(source);
|
|
23790
|
+
},
|
|
23791
|
+
portPrototype: MessagePort.prototype,
|
|
23792
|
+
});
|
|
23793
|
+
// Desktop 26.1027 moved AppServerManagers to the main process. Older builds
|
|
23794
|
+
// expose native managers in Renderer hook state; the main-process mode only
|
|
23795
|
+
// applies when none is visible and its per-Host RPC store is identified.
|
|
23796
|
+
const routing = (() => {
|
|
23797
|
+
if (window.__codexhostHostRoutingV1) return window.__codexhostHostRoutingV1;
|
|
23798
|
+
const native = discover(document);
|
|
23799
|
+
if (native.managers.length || native.registries.length) return installNative();
|
|
23800
|
+
const rpc = installRpc();
|
|
23801
|
+
if (rpc) return rpc;
|
|
23802
|
+
throw new Error('Renderer Host request manager is unavailable');
|
|
23803
|
+
})();
|
|
23310
23804
|
// Publish a default draft policy only when its Host is unambiguous. Host
|
|
23311
23805
|
// connections can be ready even when multiple Composers coexist.
|
|
23312
23806
|
const composerRoute = routing.forComposer();
|
|
@@ -23341,6 +23835,119 @@ function installRendererDraftPrewarmPolicyDirect(renderer) {
|
|
|
23341
23835
|
// packages/desktop-control/dist/renderer-control-session.js
|
|
23342
23836
|
var startupTraceStartedAt = Date.now();
|
|
23343
23837
|
|
|
23838
|
+
// packages/desktop-control/dist/renderer-loaded-modules.js
|
|
23839
|
+
var record3 = (value2) => typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
|
|
23840
|
+
var MAX_MODULES = 4096;
|
|
23841
|
+
function nativeModuleCatalogExpression(urls, complete, owner) {
|
|
23842
|
+
return `Object.defineProperty(globalThis, '__codexhostLoadedModulesV1', {
|
|
23843
|
+
configurable: true,
|
|
23844
|
+
value: Object.freeze({ owner: ${JSON.stringify(owner)}, documentUrl: location.href, complete: ${complete}, urls: Object.freeze(${JSON.stringify(urls)}) })
|
|
23845
|
+
}); void 0`;
|
|
23846
|
+
}
|
|
23847
|
+
async function installRendererLoadedModules(renderer) {
|
|
23848
|
+
const owner = crypto.randomUUID();
|
|
23849
|
+
const contexts = /* @__PURE__ */ new Map();
|
|
23850
|
+
const contextIds = /* @__PURE__ */ new Map();
|
|
23851
|
+
const dirty = /* @__PURE__ */ new Set();
|
|
23852
|
+
let ready = false;
|
|
23853
|
+
let disposed = false;
|
|
23854
|
+
let timer;
|
|
23855
|
+
let publishing = Promise.resolve();
|
|
23856
|
+
const flush = () => {
|
|
23857
|
+
clearTimeout(timer);
|
|
23858
|
+
timer = void 0;
|
|
23859
|
+
const pending = [...dirty];
|
|
23860
|
+
dirty.clear();
|
|
23861
|
+
publishing = publishing.catch(() => void 0).then(async () => {
|
|
23862
|
+
for (const uniqueId of pending) {
|
|
23863
|
+
const context = contexts.get(uniqueId);
|
|
23864
|
+
if (!context || disposed)
|
|
23865
|
+
continue;
|
|
23866
|
+
const response = await renderer.command("Runtime.evaluate", {
|
|
23867
|
+
expression: nativeModuleCatalogExpression([...context.urls], context.complete, owner),
|
|
23868
|
+
uniqueContextId: uniqueId
|
|
23869
|
+
});
|
|
23870
|
+
if (record3(response) && record3(response.exceptionDetails))
|
|
23871
|
+
throw new Error("Loaded Renderer module catalog publication failed");
|
|
23872
|
+
}
|
|
23873
|
+
});
|
|
23874
|
+
return publishing;
|
|
23875
|
+
};
|
|
23876
|
+
const schedule = (uniqueId) => {
|
|
23877
|
+
dirty.add(uniqueId);
|
|
23878
|
+
if (ready && timer === void 0)
|
|
23879
|
+
timer = setTimeout(() => {
|
|
23880
|
+
void flush().catch((error51) => {
|
|
23881
|
+
console.error("Could not publish loaded Renderer modules", error51);
|
|
23882
|
+
});
|
|
23883
|
+
}, 10);
|
|
23884
|
+
};
|
|
23885
|
+
const remove = (id2) => {
|
|
23886
|
+
const uniqueId = contextIds.get(id2);
|
|
23887
|
+
contextIds.delete(id2);
|
|
23888
|
+
if (uniqueId) {
|
|
23889
|
+
contexts.delete(uniqueId);
|
|
23890
|
+
dirty.delete(uniqueId);
|
|
23891
|
+
}
|
|
23892
|
+
};
|
|
23893
|
+
const listeners = [
|
|
23894
|
+
renderer.on("Runtime.executionContextCreated", (params) => {
|
|
23895
|
+
const context = record3(params) ? params.context : null;
|
|
23896
|
+
if (!record3(context) || typeof context.id !== "number" || typeof context.uniqueId !== "string" || !record3(context.auxData) || context.auxData.isDefault !== true)
|
|
23897
|
+
return;
|
|
23898
|
+
contextIds.set(context.id, context.uniqueId);
|
|
23899
|
+
contexts.set(context.uniqueId, { urls: /* @__PURE__ */ new Set(), complete: true });
|
|
23900
|
+
schedule(context.uniqueId);
|
|
23901
|
+
}),
|
|
23902
|
+
renderer.on("Runtime.executionContextDestroyed", (params) => {
|
|
23903
|
+
if (record3(params) && typeof params.executionContextId === "number")
|
|
23904
|
+
remove(params.executionContextId);
|
|
23905
|
+
}),
|
|
23906
|
+
renderer.on("Runtime.executionContextsCleared", () => {
|
|
23907
|
+
contextIds.clear();
|
|
23908
|
+
contexts.clear();
|
|
23909
|
+
dirty.clear();
|
|
23910
|
+
}),
|
|
23911
|
+
renderer.on("Debugger.scriptParsed", (params) => {
|
|
23912
|
+
if (!record3(params) || params.isModule !== true || params.hasSourceURL === true || typeof params.url !== "string" || typeof params.executionContextId !== "number")
|
|
23913
|
+
return;
|
|
23914
|
+
const uniqueId = contextIds.get(params.executionContextId);
|
|
23915
|
+
const context = uniqueId ? contexts.get(uniqueId) : null;
|
|
23916
|
+
if (!context || !uniqueId || context.urls.has(params.url))
|
|
23917
|
+
return;
|
|
23918
|
+
if (context.urls.size >= MAX_MODULES)
|
|
23919
|
+
context.complete = false;
|
|
23920
|
+
else
|
|
23921
|
+
context.urls.add(params.url);
|
|
23922
|
+
schedule(uniqueId);
|
|
23923
|
+
})
|
|
23924
|
+
];
|
|
23925
|
+
const dispose = () => {
|
|
23926
|
+
disposed = true;
|
|
23927
|
+
clearTimeout(timer);
|
|
23928
|
+
for (const unsubscribe of listeners)
|
|
23929
|
+
unsubscribe();
|
|
23930
|
+
for (const uniqueId of contexts.keys())
|
|
23931
|
+
void renderer.command("Runtime.evaluate", {
|
|
23932
|
+
expression: `if (globalThis.__codexhostLoadedModulesV1 === undefined || globalThis.__codexhostLoadedModulesV1?.owner === ${JSON.stringify(owner)}) { ${nativeModuleCatalogExpression([], false, owner)} }`,
|
|
23933
|
+
uniqueContextId: uniqueId
|
|
23934
|
+
}).catch(() => void 0);
|
|
23935
|
+
contexts.clear();
|
|
23936
|
+
contextIds.clear();
|
|
23937
|
+
dirty.clear();
|
|
23938
|
+
};
|
|
23939
|
+
try {
|
|
23940
|
+
await renderer.command("Runtime.enable");
|
|
23941
|
+
await renderer.command("Debugger.enable");
|
|
23942
|
+
ready = true;
|
|
23943
|
+
await flush();
|
|
23944
|
+
return dispose;
|
|
23945
|
+
} catch (error51) {
|
|
23946
|
+
dispose();
|
|
23947
|
+
throw error51;
|
|
23948
|
+
}
|
|
23949
|
+
}
|
|
23950
|
+
|
|
23344
23951
|
// packages/desktop-control/dist/renderer-cdp-control-session.js
|
|
23345
23952
|
function isRecord2(value2) {
|
|
23346
23953
|
return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
|
|
@@ -23475,15 +24082,17 @@ async function waitForBinding(renderer, enabledAgents, timeoutMs, pollIntervalMs
|
|
|
23475
24082
|
}
|
|
23476
24083
|
async function installTarget(target, rendererSource, enabledAgents, timeoutMs, pollIntervalMs, operations) {
|
|
23477
24084
|
const renderer = await operations.connect(target.webSocketDebuggerUrl);
|
|
24085
|
+
let disposeModules;
|
|
23478
24086
|
try {
|
|
23479
|
-
await renderer
|
|
24087
|
+
disposeModules = await installRendererLoadedModules(renderer);
|
|
23480
24088
|
await renderer.command("Page.enable");
|
|
23481
24089
|
await renderer.command("Page.addScriptToEvaluateOnNewDocument", { source: rendererSource });
|
|
23482
24090
|
await evaluateSource(renderer, rendererSource);
|
|
23483
24091
|
const draftPrewarmPolicy = await operations.installDraftPrewarmPolicy(renderer);
|
|
23484
24092
|
const binding = await waitForBinding(renderer, enabledAgents, timeoutMs, pollIntervalMs);
|
|
23485
|
-
return { renderer, snapshot: { target, draftPrewarmPolicy, binding } };
|
|
24093
|
+
return { renderer, snapshot: { target, draftPrewarmPolicy, binding }, disposeModules };
|
|
23486
24094
|
} catch (error51) {
|
|
24095
|
+
disposeModules?.();
|
|
23487
24096
|
renderer.close();
|
|
23488
24097
|
throw error51;
|
|
23489
24098
|
}
|
|
@@ -23497,8 +24106,9 @@ var InstalledRendererCdpControlSession = class {
|
|
|
23497
24106
|
pollIntervalMs;
|
|
23498
24107
|
operations;
|
|
23499
24108
|
currentSnapshot;
|
|
24109
|
+
disposeModules;
|
|
23500
24110
|
#closed = false;
|
|
23501
|
-
constructor(renderer, rendererCdpEndpoint, rendererSource, enabledAgents, timeoutMs, pollIntervalMs, operations, currentSnapshot) {
|
|
24111
|
+
constructor(renderer, rendererCdpEndpoint, rendererSource, enabledAgents, timeoutMs, pollIntervalMs, operations, currentSnapshot, disposeModules) {
|
|
23502
24112
|
this.renderer = renderer;
|
|
23503
24113
|
this.rendererCdpEndpoint = rendererCdpEndpoint;
|
|
23504
24114
|
this.rendererSource = rendererSource;
|
|
@@ -23507,6 +24117,7 @@ var InstalledRendererCdpControlSession = class {
|
|
|
23507
24117
|
this.pollIntervalMs = pollIntervalMs;
|
|
23508
24118
|
this.operations = operations;
|
|
23509
24119
|
this.currentSnapshot = currentSnapshot;
|
|
24120
|
+
this.disposeModules = disposeModules;
|
|
23510
24121
|
}
|
|
23511
24122
|
get snapshot() {
|
|
23512
24123
|
return this.currentSnapshot;
|
|
@@ -23517,8 +24128,10 @@ var InstalledRendererCdpControlSession = class {
|
|
|
23517
24128
|
const target = await waitForPrimaryTarget(this.rendererCdpEndpoint, this.operations, this.timeoutMs, this.pollIntervalMs, this.currentSnapshot.target.id);
|
|
23518
24129
|
if (target.id !== this.currentSnapshot.target.id) {
|
|
23519
24130
|
const replacement = await installTarget(target, this.rendererSource, this.enabledAgents, this.timeoutMs, this.pollIntervalMs, this.operations);
|
|
24131
|
+
this.disposeModules();
|
|
23520
24132
|
this.renderer.close();
|
|
23521
24133
|
this.renderer = replacement.renderer;
|
|
24134
|
+
this.disposeModules = replacement.disposeModules;
|
|
23522
24135
|
this.currentSnapshot = replacement.snapshot;
|
|
23523
24136
|
return this.currentSnapshot;
|
|
23524
24137
|
}
|
|
@@ -23532,8 +24145,10 @@ var InstalledRendererCdpControlSession = class {
|
|
|
23532
24145
|
return this.currentSnapshot;
|
|
23533
24146
|
} catch {
|
|
23534
24147
|
const replacement = await installTarget(target, this.rendererSource, this.enabledAgents, this.timeoutMs, this.pollIntervalMs, this.operations);
|
|
24148
|
+
this.disposeModules();
|
|
23535
24149
|
this.renderer.close();
|
|
23536
24150
|
this.renderer = replacement.renderer;
|
|
24151
|
+
this.disposeModules = replacement.disposeModules;
|
|
23537
24152
|
this.currentSnapshot = replacement.snapshot;
|
|
23538
24153
|
return this.currentSnapshot;
|
|
23539
24154
|
}
|
|
@@ -23553,6 +24168,7 @@ var InstalledRendererCdpControlSession = class {
|
|
|
23553
24168
|
if (this.#closed)
|
|
23554
24169
|
return;
|
|
23555
24170
|
this.#closed = true;
|
|
24171
|
+
this.disposeModules();
|
|
23556
24172
|
this.renderer.close();
|
|
23557
24173
|
}
|
|
23558
24174
|
};
|
|
@@ -23568,7 +24184,7 @@ async function createRendererCdpControlSession(options2) {
|
|
|
23568
24184
|
const operations = options2.operations ?? defaultOperations;
|
|
23569
24185
|
const target = await waitForPrimaryTarget(options2.rendererCdpEndpoint, operations, timeoutMs, pollIntervalMs, void 0, options2.signal);
|
|
23570
24186
|
const installed = await installTarget(target, options2.rendererSource, enabledAgents, timeoutMs, pollIntervalMs, operations);
|
|
23571
|
-
return new InstalledRendererCdpControlSession(installed.renderer, options2.rendererCdpEndpoint, options2.rendererSource, enabledAgents, timeoutMs, pollIntervalMs, operations, installed.snapshot);
|
|
24187
|
+
return new InstalledRendererCdpControlSession(installed.renderer, options2.rendererCdpEndpoint, options2.rendererSource, enabledAgents, timeoutMs, pollIntervalMs, operations, installed.snapshot, installed.disposeModules);
|
|
23572
24188
|
}
|
|
23573
24189
|
function installRendererCdpControlSession(options2) {
|
|
23574
24190
|
return createRendererCdpControlSession(options2);
|
|
@@ -25653,15 +26269,15 @@ var storedThreadMetadataV1Schema = external_exports.object({
|
|
|
25653
26269
|
hostThreadId: storedHostThreadIdSchema,
|
|
25654
26270
|
...storedThreadMetadataFieldsShape
|
|
25655
26271
|
}).passthrough();
|
|
25656
|
-
function refineThreadRecord(
|
|
25657
|
-
if (
|
|
26272
|
+
function refineThreadRecord(record5, context) {
|
|
26273
|
+
if (record5.state === "ready" && !record5.nativeSessionRef) {
|
|
25658
26274
|
context.addIssue({
|
|
25659
26275
|
code: "custom",
|
|
25660
26276
|
path: ["nativeSessionRef"],
|
|
25661
26277
|
message: "Ready Thread must have a Native Session Ref"
|
|
25662
26278
|
});
|
|
25663
26279
|
}
|
|
25664
|
-
if (
|
|
26280
|
+
if (record5.nativeSessionRef && record5.nativeSessionRef.harnessId !== record5.harnessId) {
|
|
25665
26281
|
context.addIssue({
|
|
25666
26282
|
code: "custom",
|
|
25667
26283
|
path: ["nativeSessionRef", "harnessId"],
|
|
@@ -25670,7 +26286,7 @@ function refineThreadRecord(record4, context) {
|
|
|
25670
26286
|
}
|
|
25671
26287
|
const hostTurnIds = /* @__PURE__ */ new Set();
|
|
25672
26288
|
const nativeTurnKeys = /* @__PURE__ */ new Set();
|
|
25673
|
-
for (const [index, mapping] of
|
|
26289
|
+
for (const [index, mapping] of record5.turnMappings.entries()) {
|
|
25674
26290
|
if (hostTurnIds.has(mapping.hostTurnId)) {
|
|
25675
26291
|
context.addIssue({
|
|
25676
26292
|
code: "custom",
|
|
@@ -25694,14 +26310,14 @@ function refineThreadRecord(record4, context) {
|
|
|
25694
26310
|
]) {
|
|
25695
26311
|
if (!ref)
|
|
25696
26312
|
continue;
|
|
25697
|
-
if (ref.harnessId !==
|
|
26313
|
+
if (ref.harnessId !== record5.harnessId) {
|
|
25698
26314
|
context.addIssue({
|
|
25699
26315
|
code: "custom",
|
|
25700
26316
|
path: ["turnMappings", index, name, "harnessId"],
|
|
25701
26317
|
message: "Turn Ref Harness must match the Thread Harness"
|
|
25702
26318
|
});
|
|
25703
26319
|
}
|
|
25704
|
-
if (
|
|
26320
|
+
if (record5.nativeSessionRef && ref.nativeSessionId !== record5.nativeSessionRef.nativeSessionId) {
|
|
25705
26321
|
context.addIssue({
|
|
25706
26322
|
code: "custom",
|
|
25707
26323
|
path: ["turnMappings", index, name, "nativeSessionId"],
|
|
@@ -25733,7 +26349,7 @@ var storedDelegationRecordV1Schema = external_exports.object({
|
|
|
25733
26349
|
taskDigest: external_exports.string().regex(/^[a-f0-9]{64}$/u),
|
|
25734
26350
|
createdAt: isoDateSchema,
|
|
25735
26351
|
updatedAt: isoDateSchema
|
|
25736
|
-
}).strict().refine((
|
|
26352
|
+
}).strict().refine((record5) => record5.parentHostThreadId !== record5.childHostThreadId, {
|
|
25737
26353
|
path: ["childHostThreadId"],
|
|
25738
26354
|
message: "Delegation child Thread must differ from its parent"
|
|
25739
26355
|
});
|
|
@@ -25873,8 +26489,8 @@ var MappingStoreError = class extends Error {
|
|
|
25873
26489
|
this.name = "MappingStoreError";
|
|
25874
26490
|
}
|
|
25875
26491
|
};
|
|
25876
|
-
function cloneRecord(
|
|
25877
|
-
return JSON.parse(JSON.stringify(
|
|
26492
|
+
function cloneRecord(record5) {
|
|
26493
|
+
return JSON.parse(JSON.stringify(record5));
|
|
25878
26494
|
}
|
|
25879
26495
|
function nativeSessionKey(ref) {
|
|
25880
26496
|
return `${ref.harnessId}\0${ref.nativeSessionId}`;
|
|
@@ -25917,22 +26533,22 @@ function withoutUnparsedUrlCredentials(value2) {
|
|
|
25917
26533
|
const kept = keepUser && !userInfo.includes(":") ? `${userInfo}@` : "";
|
|
25918
26534
|
return value2.slice(0, authorityStart) + kept + value2.slice(authorityStart + at + 1);
|
|
25919
26535
|
}
|
|
25920
|
-
function threadMetadataOf(
|
|
25921
|
-
const fields = Object.fromEntries(THREAD_METADATA_FIELDS.filter((name) =>
|
|
26536
|
+
function threadMetadataOf(record5) {
|
|
26537
|
+
const fields = Object.fromEntries(THREAD_METADATA_FIELDS.filter((name) => record5[name] !== void 0).map((name) => [
|
|
25922
26538
|
name,
|
|
25923
|
-
|
|
26539
|
+
record5[name]
|
|
25924
26540
|
]));
|
|
25925
26541
|
if (Object.keys(fields).length === 0)
|
|
25926
26542
|
return null;
|
|
25927
|
-
return { formatVersion: 1, hostThreadId:
|
|
26543
|
+
return { formatVersion: 1, hostThreadId: record5.hostThreadId, ...fields };
|
|
25928
26544
|
}
|
|
25929
|
-
function withoutThreadMetadata(
|
|
25930
|
-
const { projectId, daybreakEnabled, gitInfo, ...core } =
|
|
26545
|
+
function withoutThreadMetadata(record5) {
|
|
26546
|
+
const { projectId, daybreakEnabled, gitInfo, ...core } = record5;
|
|
25931
26547
|
void [projectId, daybreakEnabled, gitInfo];
|
|
25932
26548
|
return core;
|
|
25933
26549
|
}
|
|
25934
|
-
function withThreadMetadata(
|
|
25935
|
-
const core = withoutThreadMetadata(
|
|
26550
|
+
function withThreadMetadata(record5, metadata) {
|
|
26551
|
+
const core = withoutThreadMetadata(record5);
|
|
25936
26552
|
for (const name of THREAD_METADATA_FIELDS) {
|
|
25937
26553
|
if (metadata[name] !== void 0)
|
|
25938
26554
|
Object.assign(core, { [name]: metadata[name] });
|
|
@@ -26117,13 +26733,13 @@ var MappingStore = class {
|
|
|
26117
26733
|
for (const name of names) {
|
|
26118
26734
|
const primary = path18.join(this.#threadsDirectory, name);
|
|
26119
26735
|
const backup = path18.join(this.#backupsDirectory, name);
|
|
26120
|
-
let
|
|
26736
|
+
let record5 = null;
|
|
26121
26737
|
try {
|
|
26122
|
-
|
|
26738
|
+
record5 = await this.#readRecord(primary, name);
|
|
26123
26739
|
} catch (primaryError) {
|
|
26124
26740
|
try {
|
|
26125
|
-
|
|
26126
|
-
await this.#replaceFile(primary,
|
|
26741
|
+
record5 = await this.#readRecord(backup, name);
|
|
26742
|
+
await this.#replaceFile(primary, record5, false);
|
|
26127
26743
|
} catch (backupError) {
|
|
26128
26744
|
const quarantine = path18.join(this.#quarantineDirectory, `${name}.${this.#now().getTime()}.invalid`);
|
|
26129
26745
|
await rename10(primary, quarantine).catch(() => void 0);
|
|
@@ -26132,20 +26748,20 @@ var MappingStore = class {
|
|
|
26132
26748
|
continue;
|
|
26133
26749
|
}
|
|
26134
26750
|
}
|
|
26135
|
-
if (
|
|
26751
|
+
if (record5.state === "creating" && !record5.nativeSessionRef) {
|
|
26136
26752
|
await rm10(primary, { force: true });
|
|
26137
26753
|
await rm10(backup, { force: true });
|
|
26138
|
-
await rm10(this.#metadataPath(
|
|
26754
|
+
await rm10(this.#metadataPath(record5.hostThreadId), { force: true });
|
|
26139
26755
|
continue;
|
|
26140
26756
|
}
|
|
26141
|
-
const metadata = await this.#readMetadata(
|
|
26757
|
+
const metadata = await this.#readMetadata(record5.hostThreadId);
|
|
26142
26758
|
if (metadata) {
|
|
26143
|
-
|
|
26144
|
-
} else if (threadMetadataOf(
|
|
26145
|
-
await this.#writeMetadataFile(
|
|
26146
|
-
await this.#replaceFile(primary,
|
|
26759
|
+
record5 = withThreadMetadata(record5, metadata);
|
|
26760
|
+
} else if (threadMetadataOf(record5)) {
|
|
26761
|
+
await this.#writeMetadataFile(record5.hostThreadId, threadMetadataOf(record5));
|
|
26762
|
+
await this.#replaceFile(primary, record5, false);
|
|
26147
26763
|
}
|
|
26148
|
-
this.#records.set(
|
|
26764
|
+
this.#records.set(record5.hostThreadId, record5);
|
|
26149
26765
|
}
|
|
26150
26766
|
await Promise.all((await readdir4(this.#metadataDirectory)).filter((name) => name.endsWith(".json") && !this.#records.has(name.slice(0, -5))).map((name) => rm10(path18.join(this.#metadataDirectory, name), { force: true })));
|
|
26151
26767
|
const delegationNames = (await readdir4(this.#delegationsDirectory)).filter((name) => name.endsWith(".json"));
|
|
@@ -26182,8 +26798,8 @@ var MappingStore = class {
|
|
|
26182
26798
|
}
|
|
26183
26799
|
async getThread(hostThreadId) {
|
|
26184
26800
|
this.#requireInitialized();
|
|
26185
|
-
const
|
|
26186
|
-
return
|
|
26801
|
+
const record5 = this.#records.get(hostThreadId);
|
|
26802
|
+
return record5 ? cloneRecord(record5) : null;
|
|
26187
26803
|
}
|
|
26188
26804
|
async listThreads() {
|
|
26189
26805
|
this.#requireInitialized();
|
|
@@ -26196,8 +26812,8 @@ var MappingStore = class {
|
|
|
26196
26812
|
}
|
|
26197
26813
|
async getDelegation(delegationId) {
|
|
26198
26814
|
this.#requireInitialized();
|
|
26199
|
-
const
|
|
26200
|
-
return
|
|
26815
|
+
const record5 = this.#delegations.get(delegationId);
|
|
26816
|
+
return record5 ? cloneRecord(record5) : null;
|
|
26201
26817
|
}
|
|
26202
26818
|
async getDelegationByChild(childHostThreadId) {
|
|
26203
26819
|
this.#requireInitialized();
|
|
@@ -26211,12 +26827,12 @@ var MappingStore = class {
|
|
|
26211
26827
|
}
|
|
26212
26828
|
async listDelegations(parentHostThreadId) {
|
|
26213
26829
|
this.#requireInitialized();
|
|
26214
|
-
return [...this.#delegations.values()].filter((
|
|
26830
|
+
return [...this.#delegations.values()].filter((record5) => !parentHostThreadId || record5.parentHostThreadId === parentHostThreadId).map(cloneRecord);
|
|
26215
26831
|
}
|
|
26216
26832
|
async findRecentDelegation(input) {
|
|
26217
26833
|
this.#requireInitialized();
|
|
26218
26834
|
const threshold = input.since.getTime();
|
|
26219
|
-
const found = [...this.#delegations.values()].filter((
|
|
26835
|
+
const found = [...this.#delegations.values()].filter((record5) => record5.parentHostThreadId === input.parentHostThreadId && record5.targetHarnessId === input.targetHarnessId && record5.taskDigest === input.taskDigest && Date.parse(record5.createdAt) >= threshold).toSorted((left, right) => Date.parse(right.createdAt) - Date.parse(left.createdAt))[0];
|
|
26220
26836
|
return found ? cloneRecord(found) : null;
|
|
26221
26837
|
}
|
|
26222
26838
|
async createDelegation(input) {
|
|
@@ -26231,7 +26847,7 @@ var MappingStore = class {
|
|
|
26231
26847
|
throw new MappingStoreError("DUPLICATE_CREATE_REQUEST", "Delegation Request ID already exists");
|
|
26232
26848
|
}
|
|
26233
26849
|
const timestamp = this.#now().toISOString();
|
|
26234
|
-
const
|
|
26850
|
+
const record5 = storedDelegationRecordV1Schema.parse({
|
|
26235
26851
|
formatVersion: 1,
|
|
26236
26852
|
revision: 1,
|
|
26237
26853
|
...input,
|
|
@@ -26239,10 +26855,10 @@ var MappingStore = class {
|
|
|
26239
26855
|
createdAt: timestamp,
|
|
26240
26856
|
updatedAt: timestamp
|
|
26241
26857
|
});
|
|
26242
|
-
await this.#replaceDelegationFile(
|
|
26243
|
-
this.#delegations.set(
|
|
26858
|
+
await this.#replaceDelegationFile(record5);
|
|
26859
|
+
this.#delegations.set(record5.delegationId, record5);
|
|
26244
26860
|
this.#rebuildIndexes();
|
|
26245
|
-
return cloneRecord(
|
|
26861
|
+
return cloneRecord(record5);
|
|
26246
26862
|
}
|
|
26247
26863
|
async setDelegationStatus(delegationId, status2) {
|
|
26248
26864
|
this.#requireInitialized();
|
|
@@ -26293,7 +26909,7 @@ var MappingStore = class {
|
|
|
26293
26909
|
throw new MappingStoreError("DUPLICATE_THREAD_ID", "Host Thread ID already exists");
|
|
26294
26910
|
}
|
|
26295
26911
|
const timestamp = this.#now().toISOString();
|
|
26296
|
-
const
|
|
26912
|
+
const record5 = storedThreadRecordV1Schema.parse({
|
|
26297
26913
|
formatVersion: 1,
|
|
26298
26914
|
revision: 1,
|
|
26299
26915
|
hostThreadId: input.hostThreadId,
|
|
@@ -26312,8 +26928,8 @@ var MappingStore = class {
|
|
|
26312
26928
|
createdAt: timestamp,
|
|
26313
26929
|
updatedAt: timestamp
|
|
26314
26930
|
});
|
|
26315
|
-
await this.#writeNew(
|
|
26316
|
-
result = cloneRecord(
|
|
26931
|
+
await this.#writeNew(record5);
|
|
26932
|
+
result = cloneRecord(record5);
|
|
26317
26933
|
});
|
|
26318
26934
|
if (!result)
|
|
26319
26935
|
throw new MappingStoreError("IO_ERROR", "Provisional create produced no result");
|
|
@@ -26484,8 +27100,8 @@ var MappingStore = class {
|
|
|
26484
27100
|
async removeProvisional(hostThreadId) {
|
|
26485
27101
|
this.#requireInitialized();
|
|
26486
27102
|
await this.#enqueue(async () => {
|
|
26487
|
-
const
|
|
26488
|
-
if (
|
|
27103
|
+
const record5 = this.#records.get(hostThreadId);
|
|
27104
|
+
if (record5?.state === "ready") {
|
|
26489
27105
|
throw new MappingStoreError("MAPPING_CONFLICT", "Ready Thread cannot be removed as provisional");
|
|
26490
27106
|
}
|
|
26491
27107
|
await this.#remove(hostThreadId);
|
|
@@ -26523,13 +27139,17 @@ var MappingStore = class {
|
|
|
26523
27139
|
await this.#enqueue(() => this.#remove(hostThreadId));
|
|
26524
27140
|
}
|
|
26525
27141
|
async #remove(hostThreadId) {
|
|
26526
|
-
|
|
27142
|
+
const current = this.#records.get(hostThreadId);
|
|
27143
|
+
if (!current)
|
|
26527
27144
|
return;
|
|
26528
|
-
await
|
|
26529
|
-
|
|
26530
|
-
rm10(this.#backupPath(hostThreadId), { force: true })
|
|
26531
|
-
rm10(this.#metadataPath(hostThreadId), { force: true })
|
|
26532
|
-
|
|
27145
|
+
await rm10(this.#recordPath(hostThreadId), { force: true });
|
|
27146
|
+
try {
|
|
27147
|
+
await rm10(this.#backupPath(hostThreadId), { force: true });
|
|
27148
|
+
await rm10(this.#metadataPath(hostThreadId), { force: true });
|
|
27149
|
+
} catch (error51) {
|
|
27150
|
+
await this.#replaceFile(this.#recordPath(hostThreadId), current, false);
|
|
27151
|
+
throw error51;
|
|
27152
|
+
}
|
|
26533
27153
|
this.#records.delete(hostThreadId);
|
|
26534
27154
|
this.#rebuildIndexes();
|
|
26535
27155
|
}
|
|
@@ -26612,25 +27232,25 @@ var MappingStore = class {
|
|
|
26612
27232
|
}
|
|
26613
27233
|
return merged;
|
|
26614
27234
|
}
|
|
26615
|
-
async #writeNew(
|
|
26616
|
-
this.#validateGlobal(
|
|
26617
|
-
await this.#replaceFile(this.#recordPath(
|
|
26618
|
-
this.#records.set(
|
|
27235
|
+
async #writeNew(record5) {
|
|
27236
|
+
this.#validateGlobal(record5, null);
|
|
27237
|
+
await this.#replaceFile(this.#recordPath(record5.hostThreadId), record5, false);
|
|
27238
|
+
this.#records.set(record5.hostThreadId, record5);
|
|
26619
27239
|
this.#rebuildIndexes();
|
|
26620
27240
|
}
|
|
26621
|
-
async #replaceFile(target,
|
|
27241
|
+
async #replaceFile(target, record5, preserveBackup) {
|
|
26622
27242
|
const temp = `${target}.tmp-${randomUUID9()}`;
|
|
26623
27243
|
let handle = null;
|
|
26624
27244
|
try {
|
|
26625
|
-
await this.#beforeReplace?.(cloneRecord(
|
|
27245
|
+
await this.#beforeReplace?.(cloneRecord(record5));
|
|
26626
27246
|
handle = await open7(temp, "wx", constants3.S_IRUSR | constants3.S_IWUSR);
|
|
26627
|
-
await handle.writeFile(`${JSON.stringify(withoutThreadMetadata(
|
|
27247
|
+
await handle.writeFile(`${JSON.stringify(withoutThreadMetadata(record5), null, 2)}
|
|
26628
27248
|
`, "utf8");
|
|
26629
27249
|
await handle.sync();
|
|
26630
27250
|
await handle.close();
|
|
26631
27251
|
handle = null;
|
|
26632
27252
|
if (preserveBackup && await exists(target)) {
|
|
26633
|
-
await copyFile3(target, this.#backupPath(
|
|
27253
|
+
await copyFile3(target, this.#backupPath(record5.hostThreadId));
|
|
26634
27254
|
}
|
|
26635
27255
|
await rename10(temp, target);
|
|
26636
27256
|
} catch (error51) {
|
|
@@ -26691,13 +27311,13 @@ var MappingStore = class {
|
|
|
26691
27311
|
return null;
|
|
26692
27312
|
}
|
|
26693
27313
|
}
|
|
26694
|
-
async #replaceDelegationFile(
|
|
26695
|
-
const target = this.#delegationPath(
|
|
27314
|
+
async #replaceDelegationFile(record5) {
|
|
27315
|
+
const target = this.#delegationPath(record5.delegationId);
|
|
26696
27316
|
const temp = `${target}.tmp-${randomUUID9()}`;
|
|
26697
27317
|
let handle = null;
|
|
26698
27318
|
try {
|
|
26699
27319
|
handle = await open7(temp, "wx", constants3.S_IRUSR | constants3.S_IWUSR);
|
|
26700
|
-
await handle.writeFile(`${JSON.stringify(
|
|
27320
|
+
await handle.writeFile(`${JSON.stringify(record5, null, 2)}
|
|
26701
27321
|
`, "utf8");
|
|
26702
27322
|
await handle.sync();
|
|
26703
27323
|
await handle.close();
|
|
@@ -26781,18 +27401,18 @@ var MappingStore = class {
|
|
|
26781
27401
|
});
|
|
26782
27402
|
}
|
|
26783
27403
|
}
|
|
26784
|
-
#validateGlobal(
|
|
26785
|
-
const duplicateCreate = this.#createRequests.get(
|
|
27404
|
+
#validateGlobal(record5, replacing) {
|
|
27405
|
+
const duplicateCreate = this.#createRequests.get(record5.createRequestId);
|
|
26786
27406
|
if (duplicateCreate && duplicateCreate !== replacing) {
|
|
26787
27407
|
throw new MappingStoreError("DUPLICATE_CREATE_REQUEST", "Create request is already stored");
|
|
26788
27408
|
}
|
|
26789
|
-
if (
|
|
26790
|
-
const duplicateSession = this.#nativeSessions.get(nativeSessionKey(
|
|
27409
|
+
if (record5.nativeSessionRef && !record5.subagent) {
|
|
27410
|
+
const duplicateSession = this.#nativeSessions.get(nativeSessionKey(record5.nativeSessionRef));
|
|
26791
27411
|
if (duplicateSession && duplicateSession !== replacing) {
|
|
26792
27412
|
throw new MappingStoreError("DUPLICATE_NATIVE_SESSION", "Native Session is already mapped");
|
|
26793
27413
|
}
|
|
26794
27414
|
}
|
|
26795
|
-
for (const mapping of
|
|
27415
|
+
for (const mapping of record5.turnMappings) {
|
|
26796
27416
|
const duplicateHostTurn = this.#hostTurns.get(mapping.hostTurnId);
|
|
26797
27417
|
if (duplicateHostTurn && duplicateHostTurn !== replacing) {
|
|
26798
27418
|
throw new MappingStoreError("MAPPING_CONFLICT", "Host Turn is already mapped");
|
|
@@ -26822,14 +27442,14 @@ var MappingStore = class {
|
|
|
26822
27442
|
this.#delegationRequests.set(delegation.requestId, delegation.delegationId);
|
|
26823
27443
|
}
|
|
26824
27444
|
}
|
|
26825
|
-
for (const
|
|
26826
|
-
this.#validateGlobal(
|
|
26827
|
-
this.#createRequests.set(
|
|
26828
|
-
if (
|
|
26829
|
-
this.#nativeSessions.set(nativeSessionKey(
|
|
27445
|
+
for (const record5 of this.#records.values()) {
|
|
27446
|
+
this.#validateGlobal(record5, record5.hostThreadId);
|
|
27447
|
+
this.#createRequests.set(record5.createRequestId, record5.hostThreadId);
|
|
27448
|
+
if (record5.nativeSessionRef && !record5.subagent) {
|
|
27449
|
+
this.#nativeSessions.set(nativeSessionKey(record5.nativeSessionRef), record5.hostThreadId);
|
|
26830
27450
|
}
|
|
26831
|
-
for (const mapping of
|
|
26832
|
-
this.#hostTurns.set(mapping.hostTurnId,
|
|
27451
|
+
for (const mapping of record5.turnMappings) {
|
|
27452
|
+
this.#hostTurns.set(mapping.hostTurnId, record5.hostThreadId);
|
|
26833
27453
|
this.#nativeTurns.set(nativeTurnKey(mapping), mapping.hostTurnId);
|
|
26834
27454
|
}
|
|
26835
27455
|
}
|
|
@@ -28260,16 +28880,16 @@ function planFromTodoValue(value2) {
|
|
|
28260
28880
|
return fromText;
|
|
28261
28881
|
}
|
|
28262
28882
|
}
|
|
28263
|
-
const
|
|
28264
|
-
if (!
|
|
28883
|
+
const record5 = unwrapToolRecord(value2);
|
|
28884
|
+
if (!record5)
|
|
28265
28885
|
return planFromChecklistText(typeof value2 === "string" ? value2 : null);
|
|
28266
|
-
if (isRecord10(
|
|
28267
|
-
const nested = planFromTodoValue(
|
|
28886
|
+
if (isRecord10(record5.TodosUpdated)) {
|
|
28887
|
+
const nested = planFromTodoValue(record5.TodosUpdated);
|
|
28268
28888
|
if (nested)
|
|
28269
28889
|
return nested;
|
|
28270
28890
|
}
|
|
28271
|
-
const explanation = nestedString(
|
|
28272
|
-
const list = coerceTodoList(
|
|
28891
|
+
const explanation = nestedString(record5, ["explanation", "message", "summary"]) ?? null;
|
|
28892
|
+
const list = coerceTodoList(record5.todos ?? record5.items ?? record5.plan ?? record5.tasks ?? record5.entries);
|
|
28273
28893
|
if (!list || list.length === 0)
|
|
28274
28894
|
return planFromChecklistText(explanation);
|
|
28275
28895
|
const plan = [];
|
|
@@ -28299,8 +28919,8 @@ function coerceTodoList(value2) {
|
|
|
28299
28919
|
const parsed2 = JSON.parse(trimmed);
|
|
28300
28920
|
if (Array.isArray(parsed2))
|
|
28301
28921
|
return parsed2;
|
|
28302
|
-
const
|
|
28303
|
-
return
|
|
28922
|
+
const record5 = unwrapToolRecord(parsed2);
|
|
28923
|
+
return record5 ? coerceTodoList(record5.todos ?? record5.items ?? record5.plan ?? record5.tasks ?? record5.entries) : null;
|
|
28304
28924
|
} catch {
|
|
28305
28925
|
return planFromChecklistText(trimmed)?.plan.map(({ step, status: status2 }) => ({ content: step, status: status2 })) ?? null;
|
|
28306
28926
|
}
|
|
@@ -30065,10 +30685,12 @@ function decodeCreateRoute(request) {
|
|
|
30065
30685
|
return null;
|
|
30066
30686
|
const pluginRoute = decodeHarnessPluginRoute(request.params.model);
|
|
30067
30687
|
if (pluginRoute) {
|
|
30688
|
+
const { prewarm, ...selection } = pluginRoute;
|
|
30068
30689
|
return {
|
|
30069
30690
|
harnessId: pluginRoute.harnessId,
|
|
30070
30691
|
routeMode: "native",
|
|
30071
|
-
transportModelId: request.params.model,
|
|
30692
|
+
transportModelId: prewarm ? encodeHarnessPluginRoute(selection) : request.params.model,
|
|
30693
|
+
...prewarm ? { prewarm } : {},
|
|
30072
30694
|
...pluginRoute.model ? { model: pluginRoute.model } : {},
|
|
30073
30695
|
...pluginRoute.thinkingOptionId ? { thinkingOptionId: pluginRoute.thinkingOptionId } : {},
|
|
30074
30696
|
...pluginRoute.permissionModeId ? { permissionModeId: pluginRoute.permissionModeId } : {}
|
|
@@ -30385,7 +31007,7 @@ import { open as open8, realpath as realpath4 } from "node:fs/promises";
|
|
|
30385
31007
|
import path21 from "node:path";
|
|
30386
31008
|
var MAX_METADATA_BYTES = 1024 * 1024;
|
|
30387
31009
|
var REFERENCE_READ_TIMEOUT_MS = 2e3;
|
|
30388
|
-
var
|
|
31010
|
+
var record4 = (value2) => typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
|
|
30389
31011
|
async function nativeThreadSupportsReferences(input) {
|
|
30390
31012
|
try {
|
|
30391
31013
|
let timer;
|
|
@@ -30395,8 +31017,8 @@ async function nativeThreadSupportsReferences(input) {
|
|
|
30395
31017
|
timer = setTimeout(() => resolve(null), REFERENCE_READ_TIMEOUT_MS);
|
|
30396
31018
|
})
|
|
30397
31019
|
]).finally(() => clearTimeout(timer));
|
|
30398
|
-
const result =
|
|
30399
|
-
const thread = result &&
|
|
31020
|
+
const result = record4(response) && record4(response.result) ? response.result : null;
|
|
31021
|
+
const thread = result && record4(result.thread) ? result.thread : null;
|
|
30400
31022
|
if (thread?.id !== input.threadId || typeof thread.path !== "string") return false;
|
|
30401
31023
|
const rollout = await realpath4(thread.path);
|
|
30402
31024
|
let allowed = false;
|
|
@@ -30418,13 +31040,13 @@ async function nativeThreadSupportsReferences(input) {
|
|
|
30418
31040
|
const newline2 = bytes.subarray(0, bytesRead).indexOf(10);
|
|
30419
31041
|
if (newline2 < 0) return false;
|
|
30420
31042
|
const line = JSON.parse(bytes.subarray(0, newline2).toString("utf8"));
|
|
30421
|
-
if (!
|
|
31043
|
+
if (!record4(line) || line.type !== "session_meta" || !record4(line.payload)) return false;
|
|
30422
31044
|
const metadata = line.payload;
|
|
30423
31045
|
if (metadata.id !== input.threadId || !Array.isArray(metadata.dynamic_tools)) return false;
|
|
30424
31046
|
return metadata.dynamic_tools.some((tool) => {
|
|
30425
|
-
if (!
|
|
31047
|
+
if (!record4(tool)) return false;
|
|
30426
31048
|
if (tool.type === "namespace") {
|
|
30427
|
-
return tool.name === "codex_app" && Array.isArray(tool.tools) && tool.tools.some((item) =>
|
|
31049
|
+
return tool.name === "codex_app" && Array.isArray(tool.tools) && tool.tools.some((item) => record4(item) && item.name === "read_thread");
|
|
30428
31050
|
}
|
|
30429
31051
|
return tool.name === "read_thread";
|
|
30430
31052
|
});
|
|
@@ -30536,7 +31158,7 @@ var HarnessAccountInspectionCache = class {
|
|
|
30536
31158
|
};
|
|
30537
31159
|
|
|
30538
31160
|
// packages/host-runtime/src/app-server-host.ts
|
|
30539
|
-
import { createHash as createHash9, randomUUID as
|
|
31161
|
+
import { createHash as createHash9, randomUUID as randomUUID17 } from "node:crypto";
|
|
30540
31162
|
import os8 from "node:os";
|
|
30541
31163
|
import path25 from "node:path";
|
|
30542
31164
|
|
|
@@ -30563,21 +31185,21 @@ function subagentMaterializer(store, parent, previousParent) {
|
|
|
30563
31185
|
const legacyRecords = () => legacy ??= store.listThreads().then((records) => {
|
|
30564
31186
|
const byRequest = /* @__PURE__ */ new Map();
|
|
30565
31187
|
const children = /* @__PURE__ */ new Map();
|
|
30566
|
-
for (const
|
|
30567
|
-
if (!
|
|
31188
|
+
for (const record5 of records) {
|
|
31189
|
+
if (!record5.subagent || record5.harnessId !== parent.harnessId || !record5.nativeSessionRef)
|
|
30568
31190
|
continue;
|
|
30569
31191
|
const owner = {
|
|
30570
|
-
hostThreadId:
|
|
30571
|
-
harnessId:
|
|
31192
|
+
hostThreadId: record5.subagent.parentHostThreadId,
|
|
31193
|
+
harnessId: record5.harnessId
|
|
30572
31194
|
};
|
|
30573
31195
|
const key = childCreateRequest(
|
|
30574
31196
|
owner,
|
|
30575
|
-
|
|
30576
|
-
|
|
31197
|
+
record5.nativeSessionRef,
|
|
31198
|
+
record5.subagent.nativeSubagentId
|
|
30577
31199
|
);
|
|
30578
|
-
if (!byRequest.has(key) ||
|
|
31200
|
+
if (!byRequest.has(key) || record5.state === "ready") byRequest.set(key, record5);
|
|
30579
31201
|
const siblings = children.get(owner.hostThreadId) ?? [];
|
|
30580
|
-
siblings.push(
|
|
31202
|
+
siblings.push(record5);
|
|
30581
31203
|
children.set(owner.hostThreadId, siblings);
|
|
30582
31204
|
}
|
|
30583
31205
|
return { byRequest, children };
|
|
@@ -30647,11 +31269,11 @@ function subagentMaterializer(store, parent, previousParent) {
|
|
|
30647
31269
|
async function materializeExternalSubagent(store, parent, child) {
|
|
30648
31270
|
return subagentMaterializer(store, parent)(child);
|
|
30649
31271
|
}
|
|
30650
|
-
async function projectExternalSnapshot(store,
|
|
30651
|
-
const materialize = subagentMaterializer(store,
|
|
31272
|
+
async function projectExternalSnapshot(store, record5, snapshot2, previousParent) {
|
|
31273
|
+
const materialize = subagentMaterializer(store, record5, previousParent);
|
|
30652
31274
|
const turns = [];
|
|
30653
31275
|
for (const [index, turn] of snapshot2.turns.entries()) {
|
|
30654
|
-
const mapping =
|
|
31276
|
+
const mapping = record5.turnMappings[index];
|
|
30655
31277
|
if (!mapping) throw new Error("External Snapshot mapping is incomplete");
|
|
30656
31278
|
const items = await Promise.all(
|
|
30657
31279
|
turn.items.map(async (entry) => {
|
|
@@ -30667,9 +31289,9 @@ async function projectExternalSnapshot(store, record4, snapshot2, previousParent
|
|
|
30667
31289
|
);
|
|
30668
31290
|
turns.push(
|
|
30669
31291
|
projectHistoricalTurn({
|
|
30670
|
-
threadId:
|
|
31292
|
+
threadId: record5.hostThreadId,
|
|
30671
31293
|
turnId: mapping.hostTurnId,
|
|
30672
|
-
cwd:
|
|
31294
|
+
cwd: record5.cwd,
|
|
30673
31295
|
snapshot: { ...turn, items }
|
|
30674
31296
|
})
|
|
30675
31297
|
);
|
|
@@ -30776,11 +31398,11 @@ var ExternalThreadRepository = class {
|
|
|
30776
31398
|
removeThread(hostThreadId) {
|
|
30777
31399
|
return this.store.removeThread(hostThreadId);
|
|
30778
31400
|
}
|
|
30779
|
-
async persistTurn(
|
|
30780
|
-
if (
|
|
31401
|
+
async persistTurn(record5, hostTurnId, nativeTurnRef, nativeCheckpointRef) {
|
|
31402
|
+
if (record5.state !== "ready" || !record5.nativeSessionRef || nativeTurnRef.harnessId !== record5.harnessId || nativeTurnRef.nativeSessionId !== record5.nativeSessionRef.nativeSessionId || nativeCheckpointRef && (nativeCheckpointRef.harnessId !== record5.harnessId || nativeCheckpointRef.nativeSessionId !== record5.nativeSessionRef.nativeSessionId)) {
|
|
30781
31403
|
throw new Error("Live Turn identity does not belong to the stored Thread");
|
|
30782
31404
|
}
|
|
30783
|
-
return this.store.upsertTurnMappings(
|
|
31405
|
+
return this.store.upsertTurnMappings(record5.hostThreadId, [
|
|
30784
31406
|
{
|
|
30785
31407
|
hostTurnId,
|
|
30786
31408
|
nativeTurnRef,
|
|
@@ -30788,12 +31410,12 @@ var ExternalThreadRepository = class {
|
|
|
30788
31410
|
}
|
|
30789
31411
|
]);
|
|
30790
31412
|
}
|
|
30791
|
-
async commitDerivedSnapshot(
|
|
30792
|
-
if (
|
|
31413
|
+
async commitDerivedSnapshot(record5, nativeSessionRef, snapshot2) {
|
|
31414
|
+
if (record5.state !== "creating" || record5.turnMappings.length !== 0) {
|
|
30793
31415
|
throw new Error("Derived Thread must be provisional before Snapshot commit");
|
|
30794
31416
|
}
|
|
30795
31417
|
const mappings = snapshot2.turns.map((turn) => {
|
|
30796
|
-
if (turn.nativeTurnRef.harnessId !==
|
|
31418
|
+
if (turn.nativeTurnRef.harnessId !== record5.harnessId || turn.nativeTurnRef.nativeSessionId !== nativeSessionRef.nativeSessionId || turn.checkpoint && (turn.checkpoint.harnessId !== record5.harnessId || turn.checkpoint.nativeSessionId !== nativeSessionRef.nativeSessionId)) {
|
|
30797
31419
|
throw new Error("Derived Snapshot identity does not belong to its Native Session");
|
|
30798
31420
|
}
|
|
30799
31421
|
return {
|
|
@@ -30803,7 +31425,7 @@ var ExternalThreadRepository = class {
|
|
|
30803
31425
|
};
|
|
30804
31426
|
});
|
|
30805
31427
|
const nextRecord = await this.store.commitReady({
|
|
30806
|
-
hostThreadId:
|
|
31428
|
+
hostThreadId: record5.hostThreadId,
|
|
30807
31429
|
nativeSessionRef,
|
|
30808
31430
|
turnMappings: mappings
|
|
30809
31431
|
});
|
|
@@ -30884,8 +31506,8 @@ var ExternalThreadRepository = class {
|
|
|
30884
31506
|
turns: await projectExternalSnapshot(this.store, nextRecord, snapshot2, current)
|
|
30885
31507
|
};
|
|
30886
31508
|
}
|
|
30887
|
-
async sessionTreeId(
|
|
30888
|
-
let current =
|
|
31509
|
+
async sessionTreeId(record5) {
|
|
31510
|
+
let current = record5;
|
|
30889
31511
|
const visited = /* @__PURE__ */ new Set();
|
|
30890
31512
|
while (current.subagent || current.forkSource) {
|
|
30891
31513
|
if (visited.has(current.hostThreadId))
|
|
@@ -30899,21 +31521,21 @@ var ExternalThreadRepository = class {
|
|
|
30899
31521
|
}
|
|
30900
31522
|
return current.hostThreadId;
|
|
30901
31523
|
}
|
|
30902
|
-
async alignSnapshot(
|
|
30903
|
-
const nativeSessionRef =
|
|
30904
|
-
if (
|
|
30905
|
-
return { record:
|
|
31524
|
+
async alignSnapshot(record5, snapshot2) {
|
|
31525
|
+
const nativeSessionRef = record5.nativeSessionRef;
|
|
31526
|
+
if (record5.state === "creating" && !nativeSessionRef && snapshot2.turns.length === 0) {
|
|
31527
|
+
return { record: record5, turns: [] };
|
|
30906
31528
|
}
|
|
30907
|
-
if (!nativeSessionRef ||
|
|
31529
|
+
if (!nativeSessionRef || record5.state !== "ready") {
|
|
30908
31530
|
throw new Error("External Thread has no committed Native Session identity");
|
|
30909
31531
|
}
|
|
30910
31532
|
for (const turn of snapshot2.turns) {
|
|
30911
|
-
if (turn.nativeTurnRef.harnessId !==
|
|
31533
|
+
if (turn.nativeTurnRef.harnessId !== record5.harnessId || turn.nativeTurnRef.nativeSessionId !== nativeSessionRef.nativeSessionId || turn.checkpoint && (turn.checkpoint.harnessId !== record5.harnessId || turn.checkpoint.nativeSessionId !== nativeSessionRef.nativeSessionId)) {
|
|
30912
31534
|
throw new Error("External Snapshot identity does not belong to the stored Thread");
|
|
30913
31535
|
}
|
|
30914
31536
|
}
|
|
30915
31537
|
const mappingsByNative = new Map(
|
|
30916
|
-
|
|
31538
|
+
record5.turnMappings.map(
|
|
30917
31539
|
(mapping) => [nativeTurnKey2(mapping.nativeTurnRef), mapping]
|
|
30918
31540
|
)
|
|
30919
31541
|
);
|
|
@@ -30934,11 +31556,11 @@ var ExternalThreadRepository = class {
|
|
|
30934
31556
|
};
|
|
30935
31557
|
});
|
|
30936
31558
|
const orderedMappings = aligned.map(({ mapping }) => mapping);
|
|
30937
|
-
const mappingsChanged = orderedMappings.length !==
|
|
30938
|
-
const persisted =
|
|
31559
|
+
const mappingsChanged = orderedMappings.length !== record5.turnMappings.length || orderedMappings.some((mapping, index) => {
|
|
31560
|
+
const persisted = record5.turnMappings[index];
|
|
30939
31561
|
return !persisted || !sameMapping(mapping, persisted);
|
|
30940
31562
|
});
|
|
30941
|
-
const nextRecord = mappingsChanged ? await this.store.reconcileTurnMappings(
|
|
31563
|
+
const nextRecord = mappingsChanged ? await this.store.reconcileTurnMappings(record5.hostThreadId, orderedMappings) : record5;
|
|
30942
31564
|
return {
|
|
30943
31565
|
record: nextRecord,
|
|
30944
31566
|
turns: await projectExternalSnapshot(this.store, nextRecord, snapshot2)
|
|
@@ -30966,9 +31588,9 @@ function threadSectionFields(placement) {
|
|
|
30966
31588
|
} : { section: null, sectionEnteredAt: null };
|
|
30967
31589
|
}
|
|
30968
31590
|
function externalThreadValue(input) {
|
|
30969
|
-
const { record:
|
|
30970
|
-
const createdAt = Math.floor(Date.parse(
|
|
30971
|
-
const updatedAt = Math.floor(Date.parse(
|
|
31591
|
+
const { record: record5 } = input;
|
|
31592
|
+
const createdAt = Math.floor(Date.parse(record5.createdAt) / 1e3);
|
|
31593
|
+
const updatedAt = Math.floor(Date.parse(record5.updatedAt) / 1e3);
|
|
30972
31594
|
const preview = input.turns.flatMap((turn) => Array.isArray(turn.items) ? turn.items : []).find(
|
|
30973
31595
|
(item) => typeof item === "object" && item !== null && !Array.isArray(item) && item.type === "userMessage"
|
|
30974
31596
|
);
|
|
@@ -30977,22 +31599,22 @@ function externalThreadValue(input) {
|
|
|
30977
31599
|
(part) => typeof part === "object" && part !== null && !Array.isArray(part) && part.type === "text"
|
|
30978
31600
|
).map((part) => typeof part.text === "string" ? part.text : "").join("\n") : "";
|
|
30979
31601
|
return {
|
|
30980
|
-
id:
|
|
31602
|
+
id: record5.hostThreadId,
|
|
30981
31603
|
sessionId: input.sessionId,
|
|
30982
31604
|
path: null,
|
|
30983
|
-
cwd:
|
|
30984
|
-
source:
|
|
31605
|
+
cwd: record5.cwd,
|
|
31606
|
+
source: record5.subagent ? {
|
|
30985
31607
|
subAgent: {
|
|
30986
31608
|
thread_spawn: {
|
|
30987
|
-
parent_thread_id:
|
|
31609
|
+
parent_thread_id: record5.subagent.parentHostThreadId,
|
|
30988
31610
|
depth: 1,
|
|
30989
31611
|
agent_path: null,
|
|
30990
|
-
agent_nickname:
|
|
30991
|
-
agent_role:
|
|
31612
|
+
agent_nickname: record5.title || null,
|
|
31613
|
+
agent_role: record5.subagent.role ?? null
|
|
30992
31614
|
}
|
|
30993
31615
|
}
|
|
30994
31616
|
} : "vscode",
|
|
30995
|
-
threadSource:
|
|
31617
|
+
threadSource: record5.subagent ? "subAgentThreadSpawn" : null,
|
|
30996
31618
|
modelProvider: "codexhost",
|
|
30997
31619
|
cliVersion: "codexhost",
|
|
30998
31620
|
createdAt,
|
|
@@ -31001,23 +31623,23 @@ function externalThreadValue(input) {
|
|
|
31001
31623
|
status: input.loaded === false ? { type: "notLoaded" } : input.running ? { type: "active", activeFlags: [] } : { type: "idle" },
|
|
31002
31624
|
turns: input.turns,
|
|
31003
31625
|
preview: previewText,
|
|
31004
|
-
name:
|
|
31005
|
-
gitInfo:
|
|
31006
|
-
branch:
|
|
31007
|
-
originUrl:
|
|
31008
|
-
sha:
|
|
31626
|
+
name: record5.title || null,
|
|
31627
|
+
gitInfo: record5.gitInfo ? {
|
|
31628
|
+
branch: record5.gitInfo.branch ?? null,
|
|
31629
|
+
originUrl: record5.gitInfo.originUrl ?? null,
|
|
31630
|
+
sha: record5.gitInfo.sha ?? null
|
|
31009
31631
|
} : null,
|
|
31010
|
-
forkedFromId:
|
|
31011
|
-
parentThreadId:
|
|
31012
|
-
ephemeral:
|
|
31013
|
-
canAcceptDirectInput:
|
|
31014
|
-
historyMode:
|
|
31632
|
+
forkedFromId: record5.forkSource?.hostThreadId ?? null,
|
|
31633
|
+
parentThreadId: record5.subagent?.parentHostThreadId ?? null,
|
|
31634
|
+
ephemeral: record5.ephemeral,
|
|
31635
|
+
canAcceptDirectInput: record5.subagent ? false : input.loaded === false ? null : true,
|
|
31636
|
+
historyMode: record5.historyMode,
|
|
31015
31637
|
isPinned: false,
|
|
31016
|
-
projectId:
|
|
31017
|
-
daybreakEnabled:
|
|
31638
|
+
projectId: record5.projectId ?? null,
|
|
31639
|
+
daybreakEnabled: record5.daybreakEnabled ?? null,
|
|
31018
31640
|
...threadSectionFields(input.placement),
|
|
31019
|
-
agentNickname:
|
|
31020
|
-
agentRole:
|
|
31641
|
+
agentNickname: record5.subagent ? record5.title || null : null,
|
|
31642
|
+
agentRole: record5.subagent?.role ?? null,
|
|
31021
31643
|
extra: null
|
|
31022
31644
|
};
|
|
31023
31645
|
}
|
|
@@ -31256,14 +31878,14 @@ async function settleExternalOutputFailure(thread, error51, project2, diagnose)
|
|
|
31256
31878
|
function fixedError(code, message2) {
|
|
31257
31879
|
return { code, message: message2 };
|
|
31258
31880
|
}
|
|
31259
|
-
function importedThread(
|
|
31881
|
+
function importedThread(record5) {
|
|
31260
31882
|
return {
|
|
31261
31883
|
ok: true,
|
|
31262
|
-
threadId:
|
|
31884
|
+
threadId: record5.hostThreadId,
|
|
31263
31885
|
thread: externalThreadValue({
|
|
31264
|
-
record:
|
|
31886
|
+
record: record5,
|
|
31265
31887
|
turns: [],
|
|
31266
|
-
sessionId:
|
|
31888
|
+
sessionId: record5.hostThreadId,
|
|
31267
31889
|
loaded: false
|
|
31268
31890
|
})
|
|
31269
31891
|
};
|
|
@@ -31284,7 +31906,7 @@ var HarnessSessionImporter = class {
|
|
|
31284
31906
|
}
|
|
31285
31907
|
#mappedRecord(records, nativeSessionId) {
|
|
31286
31908
|
return records.find(
|
|
31287
|
-
(
|
|
31909
|
+
(record5) => !record5.subagent && record5.state === "ready" && record5.nativeSessionRef?.harnessId === this.#harnessId && record5.nativeSessionRef.nativeSessionId === nativeSessionId
|
|
31288
31910
|
);
|
|
31289
31911
|
}
|
|
31290
31912
|
#unavailable() {
|
|
@@ -31303,7 +31925,7 @@ var HarnessSessionImporter = class {
|
|
|
31303
31925
|
}
|
|
31304
31926
|
const mapped = new Set(
|
|
31305
31927
|
(await this.#repository.list()).flatMap(
|
|
31306
|
-
(
|
|
31928
|
+
(record5) => !record5.subagent && record5.state === "ready" && record5.nativeSessionRef?.harnessId === this.#harnessId ? [record5.nativeSessionRef.nativeSessionId] : []
|
|
31307
31929
|
)
|
|
31308
31930
|
);
|
|
31309
31931
|
const superseded = this.#repository.supersededNativeSessionIds(this.#harnessId);
|
|
@@ -31395,8 +32017,8 @@ var HarnessSessionImporter = class {
|
|
|
31395
32017
|
return { ok: false, error: fixedError(-32081, "Session import could not be persisted") };
|
|
31396
32018
|
}
|
|
31397
32019
|
try {
|
|
31398
|
-
const
|
|
31399
|
-
return importedThread(
|
|
32020
|
+
const record5 = await this.#repository.commitNative(provisional.hostThreadId, ref.data, []);
|
|
32021
|
+
return importedThread(record5);
|
|
31400
32022
|
} catch (error51) {
|
|
31401
32023
|
await this.#repository.removeProvisional(provisional.hostThreadId).catch((cleanupError) => this.#diagnose(cleanupError));
|
|
31402
32024
|
if (error51 instanceof MappingStoreError && error51.code === "DUPLICATE_NATIVE_SESSION") {
|
|
@@ -32693,6 +33315,19 @@ var ExternalThreadRuntime = class {
|
|
|
32693
33315
|
this.#threads.delete(threadId2);
|
|
32694
33316
|
this.#steeredTurnIds.delete(threadId2);
|
|
32695
33317
|
}
|
|
33318
|
+
/** Confirm release before forgetting either the Session owner or its persisted mapping. */
|
|
33319
|
+
async deleteThread(hostThreadId) {
|
|
33320
|
+
await this.#withLifecycle(hostThreadId, async () => {
|
|
33321
|
+
const thread = this.#threads.get(hostThreadId);
|
|
33322
|
+
if (thread) {
|
|
33323
|
+
thread.sessionUnavailable = true;
|
|
33324
|
+
thread.stateObserver.fault(new Error("External Thread is being deleted"));
|
|
33325
|
+
await this.#lifecycle.release(hostThreadId, thread.session, thread.outputTask);
|
|
33326
|
+
}
|
|
33327
|
+
this.remove(hostThreadId);
|
|
33328
|
+
await this.#repository.removeThread(hostThreadId);
|
|
33329
|
+
});
|
|
33330
|
+
}
|
|
32696
33331
|
clear() {
|
|
32697
33332
|
this.#threads.clear();
|
|
32698
33333
|
this.#steeredTurnIds.clear();
|
|
@@ -32821,9 +33456,9 @@ var ExternalThreadRuntime = class {
|
|
|
32821
33456
|
async #retireSubagents(parent, bestEffort = false) {
|
|
32822
33457
|
const parentId = parent.id;
|
|
32823
33458
|
const ancestors = /* @__PURE__ */ new Map();
|
|
32824
|
-
const descendant = async (
|
|
33459
|
+
const descendant = async (record5) => {
|
|
32825
33460
|
const visited = /* @__PURE__ */ new Set();
|
|
32826
|
-
let ownerId =
|
|
33461
|
+
let ownerId = record5?.subagent?.parentHostThreadId;
|
|
32827
33462
|
while (ownerId && !visited.has(ownerId)) {
|
|
32828
33463
|
if (ownerId === parentId) return true;
|
|
32829
33464
|
visited.add(ownerId);
|
|
@@ -32871,23 +33506,23 @@ var ExternalThreadRuntime = class {
|
|
|
32871
33506
|
if (failure) return { kind: "error", error: { code: -32075, message: failure } };
|
|
32872
33507
|
return { kind: "external", record: loaded.record, thread: loaded };
|
|
32873
33508
|
}
|
|
32874
|
-
let
|
|
33509
|
+
let record5;
|
|
32875
33510
|
try {
|
|
32876
|
-
|
|
33511
|
+
record5 = await this.#repository.find(threadId2);
|
|
32877
33512
|
} catch {
|
|
32878
33513
|
return {
|
|
32879
33514
|
kind: "error",
|
|
32880
33515
|
error: { code: -32081, message: "External Thread ownership could not be read" }
|
|
32881
33516
|
};
|
|
32882
33517
|
}
|
|
32883
|
-
if (!
|
|
32884
|
-
if (
|
|
33518
|
+
if (!record5) return { kind: "official" };
|
|
33519
|
+
if (record5.state !== "ready" || !record5.nativeSessionRef) {
|
|
32885
33520
|
return {
|
|
32886
33521
|
kind: "error",
|
|
32887
33522
|
error: { code: -32079, message: "External Native Session is unavailable" }
|
|
32888
33523
|
};
|
|
32889
33524
|
}
|
|
32890
|
-
return { kind: "external", record:
|
|
33525
|
+
return { kind: "external", record: record5, thread: null };
|
|
32891
33526
|
}
|
|
32892
33527
|
async resolve(threadId2) {
|
|
32893
33528
|
try {
|
|
@@ -33098,16 +33733,16 @@ var ExternalThreadRuntime = class {
|
|
|
33098
33733
|
return failure;
|
|
33099
33734
|
}
|
|
33100
33735
|
}
|
|
33101
|
-
async #restore(
|
|
33102
|
-
const harnessId =
|
|
33736
|
+
async #restore(record5) {
|
|
33737
|
+
const harnessId = record5.harnessId;
|
|
33103
33738
|
const adapter = this.#adapters.get(harnessId);
|
|
33104
|
-
if (!adapter || !
|
|
33739
|
+
if (!adapter || !record5.nativeSessionRef) {
|
|
33105
33740
|
throw new ExternalThreadOpenError({
|
|
33106
33741
|
code: -32077,
|
|
33107
33742
|
message: "External Harness is unavailable"
|
|
33108
33743
|
});
|
|
33109
33744
|
}
|
|
33110
|
-
if (
|
|
33745
|
+
if (record5.subagent) {
|
|
33111
33746
|
const subagents = adapter.subagents;
|
|
33112
33747
|
if (!subagents) {
|
|
33113
33748
|
throw new ExternalThreadOpenError({
|
|
@@ -33115,14 +33750,14 @@ var ExternalThreadRuntime = class {
|
|
|
33115
33750
|
message: "External Harness Subagent history is unavailable"
|
|
33116
33751
|
});
|
|
33117
33752
|
}
|
|
33118
|
-
const subagent =
|
|
33119
|
-
const parent =
|
|
33753
|
+
const subagent = record5.subagent;
|
|
33754
|
+
const parent = record5.nativeSessionRef;
|
|
33120
33755
|
const snapshot2 = await subagents.readSnapshot({
|
|
33121
33756
|
parent,
|
|
33122
33757
|
nativeSubagentId: subagent.nativeSubagentId,
|
|
33123
|
-
cwd:
|
|
33758
|
+
cwd: record5.cwd
|
|
33124
33759
|
});
|
|
33125
|
-
const latest = await this.#repository.find(
|
|
33760
|
+
const latest = await this.#repository.find(record5.hostThreadId);
|
|
33126
33761
|
if (latest?.state === "ready" && latest.nativeSessionRef && JSON.stringify(latest.nativeSessionRef) !== JSON.stringify(parent)) {
|
|
33127
33762
|
return this.#restore(latest);
|
|
33128
33763
|
}
|
|
@@ -33130,16 +33765,16 @@ var ExternalThreadRuntime = class {
|
|
|
33130
33765
|
throw new ExternalThreadOpenError(mapExternalThreadHarnessError(snapshot2.error, "read"));
|
|
33131
33766
|
}
|
|
33132
33767
|
const session2 = new ReadonlySnapshotSession(
|
|
33133
|
-
|
|
33134
|
-
|
|
33768
|
+
record5.harnessId,
|
|
33769
|
+
record5.nativeSessionRef,
|
|
33135
33770
|
snapshot2.value,
|
|
33136
33771
|
() => subagents.readSnapshot({
|
|
33137
33772
|
parent,
|
|
33138
33773
|
nativeSubagentId: subagent.nativeSubagentId,
|
|
33139
|
-
cwd:
|
|
33774
|
+
cwd: record5.cwd
|
|
33140
33775
|
})
|
|
33141
33776
|
);
|
|
33142
|
-
const aligned = await this.#repository.alignSnapshot(
|
|
33777
|
+
const aligned = await this.#repository.alignSnapshot(record5, snapshot2.value);
|
|
33143
33778
|
const sessionId = await this.#repository.sessionTreeId(aligned.record);
|
|
33144
33779
|
return this.register({
|
|
33145
33780
|
record: aligned.record,
|
|
@@ -33150,13 +33785,13 @@ var ExternalThreadRuntime = class {
|
|
|
33150
33785
|
...snapshot2.value.state ? { restoredState: snapshot2.value.state } : {}
|
|
33151
33786
|
});
|
|
33152
33787
|
}
|
|
33153
|
-
const restoredSelection = decodeExternalTransportSelection(harnessId,
|
|
33788
|
+
const restoredSelection = decodeExternalTransportSelection(harnessId, record5.transportModelId);
|
|
33154
33789
|
const opened = await adapter.open({
|
|
33155
33790
|
kind: "resume",
|
|
33156
|
-
cwd:
|
|
33157
|
-
environment: { ...this.#environment, [DELEGATION_THREAD_ID_ENV]:
|
|
33158
|
-
nativeRef:
|
|
33159
|
-
knownTurnRefs:
|
|
33791
|
+
cwd: record5.cwd,
|
|
33792
|
+
environment: { ...this.#environment, [DELEGATION_THREAD_ID_ENV]: record5.hostThreadId },
|
|
33793
|
+
nativeRef: record5.nativeSessionRef,
|
|
33794
|
+
knownTurnRefs: record5.turnMappings.map(({ nativeTurnRef }) => nativeTurnRef),
|
|
33160
33795
|
...restoredSelection?.model ? { model: restoredSelection.model } : {},
|
|
33161
33796
|
...restoredSelection?.thinkingOptionId ? { thinkingOptionId: restoredSelection.thinkingOptionId } : {},
|
|
33162
33797
|
...restoredSelection?.permissionModeId ? { permissionModeId: restoredSelection.permissionModeId } : {}
|
|
@@ -33170,7 +33805,7 @@ var ExternalThreadRuntime = class {
|
|
|
33170
33805
|
if (!snapshot2.ok) {
|
|
33171
33806
|
throw new ExternalThreadOpenError(mapExternalThreadHarnessError(snapshot2.error, "read"));
|
|
33172
33807
|
}
|
|
33173
|
-
let aligned = await this.#repository.alignSnapshot(
|
|
33808
|
+
let aligned = await this.#repository.alignSnapshot(record5, snapshot2.value);
|
|
33174
33809
|
const restoredState = snapshot2.value.state;
|
|
33175
33810
|
const effectiveModel = restoredState ? restoredState.effectiveModel : restoredSelection?.model;
|
|
33176
33811
|
const effectiveThinkingOptionId = restoredState ? restoredState.effectiveThinkingOptionId : restoredSelection?.thinkingOptionId;
|
|
@@ -33216,14 +33851,136 @@ var ExternalThreadRuntime = class {
|
|
|
33216
33851
|
});
|
|
33217
33852
|
} catch (error51) {
|
|
33218
33853
|
if (error51 instanceof ExternalSessionReleaseError) throw error51;
|
|
33219
|
-
await this.#lifecycle.release(
|
|
33854
|
+
await this.#lifecycle.release(record5.hostThreadId, session, Promise.resolve());
|
|
33220
33855
|
throw error51;
|
|
33221
33856
|
}
|
|
33222
33857
|
}
|
|
33223
33858
|
};
|
|
33224
33859
|
|
|
33225
|
-
// packages/host-runtime/src/external-
|
|
33860
|
+
// packages/host-runtime/src/external-thread-queue.ts
|
|
33226
33861
|
import { randomUUID as randomUUID12 } from "node:crypto";
|
|
33862
|
+
var ExternalQueueError = class extends Error {
|
|
33863
|
+
constructor(code, message2) {
|
|
33864
|
+
super(message2);
|
|
33865
|
+
this.code = code;
|
|
33866
|
+
}
|
|
33867
|
+
code;
|
|
33868
|
+
};
|
|
33869
|
+
var publicSubmission = ({
|
|
33870
|
+
id: id2,
|
|
33871
|
+
input,
|
|
33872
|
+
clientUserMessageId
|
|
33873
|
+
}) => ({
|
|
33874
|
+
id: id2,
|
|
33875
|
+
input,
|
|
33876
|
+
clientUserMessageId
|
|
33877
|
+
});
|
|
33878
|
+
var DEFAULT_PAGE_SIZE3 = 50;
|
|
33879
|
+
var ExternalThreadQueue = class {
|
|
33880
|
+
#queues = /* @__PURE__ */ new Map();
|
|
33881
|
+
#notifyChanged;
|
|
33882
|
+
#createId;
|
|
33883
|
+
constructor(options2) {
|
|
33884
|
+
this.#notifyChanged = options2.notifyChanged;
|
|
33885
|
+
this.#createId = options2.createId ?? randomUUID12;
|
|
33886
|
+
}
|
|
33887
|
+
has(threadId2) {
|
|
33888
|
+
return (this.#queues.get(threadId2)?.length ?? 0) > 0;
|
|
33889
|
+
}
|
|
33890
|
+
list(threadId2, params) {
|
|
33891
|
+
const items = this.#queues.get(threadId2) ?? [];
|
|
33892
|
+
const start = params.cursor == null ? 0 : Number(params.cursor);
|
|
33893
|
+
if (!Number.isSafeInteger(start) || start < 0 || start > items.length) {
|
|
33894
|
+
throw new ExternalQueueError(-32602, "Invalid thread/queue/list cursor");
|
|
33895
|
+
}
|
|
33896
|
+
const limit = typeof params.limit === "number" && Number.isSafeInteger(params.limit) && params.limit > 0 ? params.limit : DEFAULT_PAGE_SIZE3;
|
|
33897
|
+
const end = Math.min(items.length, start + limit);
|
|
33898
|
+
return {
|
|
33899
|
+
data: items.slice(start, end).map((item) => publicSubmission(item)),
|
|
33900
|
+
nextCursor: end < items.length ? String(end) : null
|
|
33901
|
+
};
|
|
33902
|
+
}
|
|
33903
|
+
async add(threadId2, input, clientUserMessageId, sourceHostId) {
|
|
33904
|
+
const submission = { id: this.#createId(), input, clientUserMessageId, sourceHostId };
|
|
33905
|
+
this.#items(threadId2).push(submission);
|
|
33906
|
+
await this.#notifyChanged(threadId2);
|
|
33907
|
+
return publicSubmission(submission);
|
|
33908
|
+
}
|
|
33909
|
+
async update(threadId2, id2, input) {
|
|
33910
|
+
const items = this.#queues.get(threadId2) ?? [];
|
|
33911
|
+
const index = items.findIndex((item) => item.id === id2);
|
|
33912
|
+
const current = items[index];
|
|
33913
|
+
if (!current) throw new ExternalQueueError(-32602, "Queued submission was not found");
|
|
33914
|
+
const submission = { ...current, input };
|
|
33915
|
+
items[index] = submission;
|
|
33916
|
+
await this.#notifyChanged(threadId2);
|
|
33917
|
+
return publicSubmission(submission);
|
|
33918
|
+
}
|
|
33919
|
+
async delete(threadId2, id2) {
|
|
33920
|
+
const items = this.#queues.get(threadId2);
|
|
33921
|
+
const index = items?.findIndex((item) => item.id === id2) ?? -1;
|
|
33922
|
+
if (!items || index === -1) return false;
|
|
33923
|
+
items.splice(index, 1);
|
|
33924
|
+
this.#prune(threadId2);
|
|
33925
|
+
await this.#notifyChanged(threadId2);
|
|
33926
|
+
return true;
|
|
33927
|
+
}
|
|
33928
|
+
/** Listed IDs move to the front in the given order; unlisted entries keep their order. */
|
|
33929
|
+
async reorder(threadId2, ids) {
|
|
33930
|
+
const items = this.#queues.get(threadId2);
|
|
33931
|
+
if (!items) return;
|
|
33932
|
+
const byId = new Map(items.map((item) => [item.id, item]));
|
|
33933
|
+
const ordered = ids.flatMap((id2) => {
|
|
33934
|
+
const item = byId.get(id2);
|
|
33935
|
+
byId.delete(id2);
|
|
33936
|
+
return item ? [item] : [];
|
|
33937
|
+
});
|
|
33938
|
+
items.splice(0, items.length, ...ordered, ...byId.values());
|
|
33939
|
+
await this.#notifyChanged(threadId2);
|
|
33940
|
+
}
|
|
33941
|
+
/** Removes the submission a Turn is about to start; `restore` returns it if the start fails. */
|
|
33942
|
+
take(threadId2, id2) {
|
|
33943
|
+
const items = this.#queues.get(threadId2) ?? [];
|
|
33944
|
+
const index = id2 == null ? 0 : items.findIndex((item) => item.id === id2);
|
|
33945
|
+
const submission = index === -1 ? void 0 : items[index];
|
|
33946
|
+
if (!submission) throw new ExternalQueueError(-32602, "Queued submission was not found");
|
|
33947
|
+
items.splice(index, 1);
|
|
33948
|
+
this.#prune(threadId2);
|
|
33949
|
+
return {
|
|
33950
|
+
submission: publicSubmission(submission),
|
|
33951
|
+
sourceHostId: submission.sourceHostId,
|
|
33952
|
+
index
|
|
33953
|
+
};
|
|
33954
|
+
}
|
|
33955
|
+
restore(threadId2, taken) {
|
|
33956
|
+
const items = this.#items(threadId2);
|
|
33957
|
+
if (items.some((item) => item.id === taken.submission.id)) return;
|
|
33958
|
+
items.splice(Math.min(taken.index, items.length), 0, {
|
|
33959
|
+
...taken.submission,
|
|
33960
|
+
sourceHostId: taken.sourceHostId
|
|
33961
|
+
});
|
|
33962
|
+
}
|
|
33963
|
+
notifyChanged(threadId2) {
|
|
33964
|
+
return this.#notifyChanged(threadId2);
|
|
33965
|
+
}
|
|
33966
|
+
forget(threadId2) {
|
|
33967
|
+
this.#queues.delete(threadId2);
|
|
33968
|
+
}
|
|
33969
|
+
#items(threadId2) {
|
|
33970
|
+
let items = this.#queues.get(threadId2);
|
|
33971
|
+
if (!items) {
|
|
33972
|
+
items = [];
|
|
33973
|
+
this.#queues.set(threadId2, items);
|
|
33974
|
+
}
|
|
33975
|
+
return items;
|
|
33976
|
+
}
|
|
33977
|
+
#prune(threadId2) {
|
|
33978
|
+
if (this.#queues.get(threadId2)?.length === 0) this.#queues.delete(threadId2);
|
|
33979
|
+
}
|
|
33980
|
+
};
|
|
33981
|
+
|
|
33982
|
+
// packages/host-runtime/src/external-turn-steering.ts
|
|
33983
|
+
import { randomUUID as randomUUID13 } from "node:crypto";
|
|
33227
33984
|
|
|
33228
33985
|
// packages/host-runtime/src/external-command-routing.ts
|
|
33229
33986
|
var ExternalCommandError = class extends Error {
|
|
@@ -33344,7 +34101,7 @@ async function insertNativeSteer(thread, input, host) {
|
|
|
33344
34101
|
thread.steeredTurnIds.add(input.turnId);
|
|
33345
34102
|
const item = {
|
|
33346
34103
|
type: "userMessage",
|
|
33347
|
-
itemId: hostItemIdSchema.parse(
|
|
34104
|
+
itemId: hostItemIdSchema.parse(randomUUID13()),
|
|
33348
34105
|
input: displayed
|
|
33349
34106
|
};
|
|
33350
34107
|
try {
|
|
@@ -33576,7 +34333,7 @@ function sameWorkspace(left, right) {
|
|
|
33576
34333
|
}
|
|
33577
34334
|
|
|
33578
34335
|
// packages/host-runtime/src/harness-delegation-coordinator.ts
|
|
33579
|
-
import { createHash as createHash8, randomUUID as
|
|
34336
|
+
import { createHash as createHash8, randomUUID as randomUUID14 } from "node:crypto";
|
|
33580
34337
|
import path24 from "node:path";
|
|
33581
34338
|
|
|
33582
34339
|
// packages/host-runtime/src/delegation-snapshot.ts
|
|
@@ -33880,11 +34637,11 @@ var HarnessDelegationCoordinator = class {
|
|
|
33880
34637
|
});
|
|
33881
34638
|
this.#validateConfiguration(inspected.inspection, input.model, input.thinkingOptionId);
|
|
33882
34639
|
}
|
|
33883
|
-
const delegationId = hostThreadIdSchema.parse(
|
|
33884
|
-
const childThreadId = hostThreadIdSchema.parse(
|
|
33885
|
-
const turnId = hostTurnIdSchema.parse(
|
|
33886
|
-
const createRequestId = input.requestId ? `delegation:${input.requestId}` :
|
|
33887
|
-
let
|
|
34640
|
+
const delegationId = hostThreadIdSchema.parse(randomUUID14());
|
|
34641
|
+
const childThreadId = hostThreadIdSchema.parse(randomUUID14());
|
|
34642
|
+
const turnId = hostTurnIdSchema.parse(randomUUID14());
|
|
34643
|
+
const createRequestId = input.requestId ? `delegation:${input.requestId}` : randomUUID14();
|
|
34644
|
+
let record5 = await this.#repository.createProvisional(
|
|
33888
34645
|
createExternalThreadRecordInput({
|
|
33889
34646
|
hostThreadId: childThreadId,
|
|
33890
34647
|
createRequestId,
|
|
@@ -33915,7 +34672,7 @@ var HarnessDelegationCoordinator = class {
|
|
|
33915
34672
|
});
|
|
33916
34673
|
const opened = await adapter.open({
|
|
33917
34674
|
kind: "create",
|
|
33918
|
-
cwd:
|
|
34675
|
+
cwd: record5.cwd,
|
|
33919
34676
|
environment: { ...this.#environment, [DELEGATION_THREAD_ID_ENV]: childThreadId },
|
|
33920
34677
|
executionPolicy: "unattended-full-access",
|
|
33921
34678
|
...input.model ? { model: input.model } : {},
|
|
@@ -33924,21 +34681,21 @@ var HarnessDelegationCoordinator = class {
|
|
|
33924
34681
|
if (!opened.ok) throw new DelegationControlError("DELEGATION_FAILED", opened.error.message);
|
|
33925
34682
|
session = opened.value;
|
|
33926
34683
|
if (session.initialState.nativeRef) {
|
|
33927
|
-
|
|
33928
|
-
|
|
34684
|
+
record5 = await this.#repository.commitNative(
|
|
34685
|
+
record5.hostThreadId,
|
|
33929
34686
|
session.initialState.nativeRef
|
|
33930
34687
|
);
|
|
33931
34688
|
}
|
|
33932
34689
|
const threadValue = externalThreadValue({
|
|
33933
|
-
record:
|
|
34690
|
+
record: record5,
|
|
33934
34691
|
turns: [],
|
|
33935
|
-
sessionId:
|
|
34692
|
+
sessionId: record5.hostThreadId,
|
|
33936
34693
|
running: true
|
|
33937
34694
|
});
|
|
33938
34695
|
const thread = this.#registerExternalThread({
|
|
33939
|
-
record:
|
|
34696
|
+
record: record5,
|
|
33940
34697
|
session,
|
|
33941
|
-
sessionId:
|
|
34698
|
+
sessionId: record5.hostThreadId,
|
|
33942
34699
|
thread: threadValue,
|
|
33943
34700
|
turns: [],
|
|
33944
34701
|
...input.model ? { requestedModel: input.model } : {},
|
|
@@ -33995,7 +34752,7 @@ var HarnessDelegationCoordinator = class {
|
|
|
33995
34752
|
} : {}
|
|
33996
34753
|
}
|
|
33997
34754
|
}),
|
|
33998
|
-
cwd:
|
|
34755
|
+
cwd: record5.cwd,
|
|
33999
34756
|
parentThreadId
|
|
34000
34757
|
};
|
|
34001
34758
|
} catch (error51) {
|
|
@@ -34037,7 +34794,7 @@ var HarnessDelegationCoordinator = class {
|
|
|
34037
34794
|
if (this.#externalThreadBusy(thread) || thread.activeTurnId) {
|
|
34038
34795
|
throw new DelegationControlError("THREAD_BUSY", "Thread already has an active Turn");
|
|
34039
34796
|
}
|
|
34040
|
-
const turnId = hostTurnIdSchema.parse(
|
|
34797
|
+
const turnId = hostTurnIdSchema.parse(randomUUID14());
|
|
34041
34798
|
try {
|
|
34042
34799
|
await this.#startExternalTurn(thread, input.message, turnId);
|
|
34043
34800
|
} catch (error51) {
|
|
@@ -34144,19 +34901,19 @@ var HarnessDelegationCoordinator = class {
|
|
|
34144
34901
|
const parent = hostThreadIdSchema.parse(input.parentThreadId);
|
|
34145
34902
|
const delegations = await this.#repository.listDelegations(parent);
|
|
34146
34903
|
const records = await this.#repository.list();
|
|
34147
|
-
const byId = new Map(records.map((
|
|
34904
|
+
const byId = new Map(records.map((record5) => [record5.hostThreadId, record5]));
|
|
34148
34905
|
const rows = delegations.map((delegation) => {
|
|
34149
|
-
const
|
|
34906
|
+
const record5 = byId.get(delegation.childHostThreadId);
|
|
34150
34907
|
return {
|
|
34151
34908
|
threadId: delegation.childHostThreadId,
|
|
34152
34909
|
harnessId: delegation.targetHarnessId,
|
|
34153
34910
|
deepLink: `codex://threads/${delegation.childHostThreadId}`,
|
|
34154
34911
|
status: delegation.status,
|
|
34155
|
-
...
|
|
34156
|
-
cwd:
|
|
34157
|
-
title:
|
|
34158
|
-
createdAt:
|
|
34159
|
-
updatedAt:
|
|
34912
|
+
...record5 ? {
|
|
34913
|
+
cwd: record5.cwd,
|
|
34914
|
+
title: record5.title,
|
|
34915
|
+
createdAt: record5.createdAt,
|
|
34916
|
+
updatedAt: record5.updatedAt
|
|
34160
34917
|
} : {
|
|
34161
34918
|
createdAt: delegation.createdAt,
|
|
34162
34919
|
updatedAt: delegation.updatedAt
|
|
@@ -34250,19 +35007,19 @@ var HarnessDelegationCoordinator = class {
|
|
|
34250
35007
|
}
|
|
34251
35008
|
}
|
|
34252
35009
|
async #parentMetadata(parentThreadId) {
|
|
34253
|
-
const
|
|
34254
|
-
if (
|
|
35010
|
+
const record5 = await this.#repository.find(parentThreadId);
|
|
35011
|
+
if (record5)
|
|
34255
35012
|
return {
|
|
34256
|
-
harnessId:
|
|
34257
|
-
cwd:
|
|
34258
|
-
title:
|
|
35013
|
+
harnessId: record5.harnessId,
|
|
35014
|
+
cwd: record5.cwd,
|
|
35015
|
+
title: record5.title
|
|
34259
35016
|
};
|
|
34260
35017
|
const metadata = await this.#officialThreadMetadata(parentThreadId).catch(() => ({}));
|
|
34261
35018
|
return { harnessId: "codex", ...metadata };
|
|
34262
35019
|
}
|
|
34263
35020
|
async #existingResult(delegation) {
|
|
34264
|
-
const
|
|
34265
|
-
const turnId =
|
|
35021
|
+
const record5 = await this.#repository.find(delegation.childHostThreadId);
|
|
35022
|
+
const turnId = record5?.turnMappings.at(-1)?.hostTurnId ?? "pending";
|
|
34266
35023
|
return {
|
|
34267
35024
|
...this.#result(
|
|
34268
35025
|
delegation.delegationId,
|
|
@@ -34271,7 +35028,7 @@ var HarnessDelegationCoordinator = class {
|
|
|
34271
35028
|
delegation.targetHarnessId,
|
|
34272
35029
|
delegation.status
|
|
34273
35030
|
),
|
|
34274
|
-
...
|
|
35031
|
+
...record5 ? { cwd: record5.cwd } : {},
|
|
34275
35032
|
parentThreadId: delegation.parentHostThreadId
|
|
34276
35033
|
};
|
|
34277
35034
|
}
|
|
@@ -36687,10 +37444,10 @@ var SingleNativeCodexAccount = class {
|
|
|
36687
37444
|
};
|
|
36688
37445
|
|
|
36689
37446
|
// packages/host-runtime/src/codex-runtime/official-runtime-owner.ts
|
|
36690
|
-
import { randomUUID as
|
|
37447
|
+
import { randomUUID as randomUUID16 } from "node:crypto";
|
|
36691
37448
|
|
|
36692
37449
|
// packages/host-runtime/src/official-request-broker.ts
|
|
36693
|
-
import { randomUUID as
|
|
37450
|
+
import { randomUUID as randomUUID15 } from "node:crypto";
|
|
36694
37451
|
var INTERNAL_REQUEST_PREFIX = "codexhost:official:";
|
|
36695
37452
|
var MAX_RETIRED_IDS = 1024;
|
|
36696
37453
|
function isRecord15(value2) {
|
|
@@ -36706,7 +37463,7 @@ var OfficialRequestBroker = class {
|
|
|
36706
37463
|
constructor(input) {
|
|
36707
37464
|
this.#send = input.send;
|
|
36708
37465
|
this.#timeoutMs = input.timeoutMs ?? 3e4;
|
|
36709
|
-
this.#nextId = input.nextId ?? (() => `${INTERNAL_REQUEST_PREFIX}${
|
|
37466
|
+
this.#nextId = input.nextId ?? (() => `${INTERNAL_REQUEST_PREFIX}${randomUUID15()}`);
|
|
36710
37467
|
}
|
|
36711
37468
|
get pendingCount() {
|
|
36712
37469
|
return this.#pending.size;
|
|
@@ -37060,7 +37817,7 @@ var OfficialRuntimeOwner = class {
|
|
|
37060
37817
|
}
|
|
37061
37818
|
#attach(role, output, onBackendStopped) {
|
|
37062
37819
|
const client = {
|
|
37063
|
-
id:
|
|
37820
|
+
id: randomUUID16(),
|
|
37064
37821
|
role,
|
|
37065
37822
|
output,
|
|
37066
37823
|
...onBackendStopped ? { onBackendStopped } : {},
|
|
@@ -37218,7 +37975,7 @@ var OfficialRuntimeOwner = class {
|
|
|
37218
37975
|
if (!object4(value2)) return client.output(event);
|
|
37219
37976
|
if (typeof value2.id === "string" || typeof value2.id === "number") {
|
|
37220
37977
|
if (typeof value2.method === "string") {
|
|
37221
|
-
const id2 = `codexhost:server:${client.id}:${event.generation}:${
|
|
37978
|
+
const id2 = `codexhost:server:${client.id}:${event.generation}:${randomUUID16()}`;
|
|
37222
37979
|
client.serverRequests.set(id2, value2.id);
|
|
37223
37980
|
const projected = { ...value2, id: id2 };
|
|
37224
37981
|
return client.output({
|
|
@@ -37606,9 +38363,9 @@ function externalAnchor(entry) {
|
|
|
37606
38363
|
if (entry.source !== "external") throw new Error("Expected an External Thread list entry");
|
|
37607
38364
|
return { timestamp: entry.timestamp, threadId: threadId(entry.thread) };
|
|
37608
38365
|
}
|
|
37609
|
-
function includesExternalRecord(
|
|
37610
|
-
if (
|
|
37611
|
-
let current =
|
|
38366
|
+
function includesExternalRecord(record5, query, byId, sectionId) {
|
|
38367
|
+
if (record5.state !== "ready" || !record5.nativeSessionRef) return false;
|
|
38368
|
+
let current = record5;
|
|
37612
38369
|
const owners = /* @__PURE__ */ new Set();
|
|
37613
38370
|
while (current.subagent) {
|
|
37614
38371
|
if (owners.has(current.hostThreadId)) return false;
|
|
@@ -37618,32 +38375,32 @@ function includesExternalRecord(record4, query, byId, sectionId) {
|
|
|
37618
38375
|
return false;
|
|
37619
38376
|
current = parent;
|
|
37620
38377
|
}
|
|
37621
|
-
const sourceKind =
|
|
38378
|
+
const sourceKind = record5.subagent ? "subAgentThreadSpawn" : "vscode";
|
|
37622
38379
|
const scoped = query.parentThreadId !== null || query.ancestorThreadId !== null;
|
|
37623
|
-
if (
|
|
38380
|
+
if (record5.subagent && !scoped && !query.sourceKinds?.some((kind) => kind === "subAgent" || kind === "subAgentThreadSpawn"))
|
|
37624
38381
|
return false;
|
|
37625
|
-
if (query.parentThreadId !== null &&
|
|
38382
|
+
if (query.parentThreadId !== null && record5.subagent?.parentHostThreadId !== query.parentThreadId)
|
|
37626
38383
|
return false;
|
|
37627
38384
|
if (query.ancestorThreadId !== null) {
|
|
37628
|
-
let parentId =
|
|
37629
|
-
const visited = /* @__PURE__ */ new Set([
|
|
38385
|
+
let parentId = record5.subagent?.parentHostThreadId;
|
|
38386
|
+
const visited = /* @__PURE__ */ new Set([record5.hostThreadId]);
|
|
37630
38387
|
while (parentId && parentId !== query.ancestorThreadId && !visited.has(parentId)) {
|
|
37631
38388
|
visited.add(parentId);
|
|
37632
38389
|
parentId = byId.get(parentId)?.subagent?.parentHostThreadId;
|
|
37633
38390
|
}
|
|
37634
|
-
if (
|
|
38391
|
+
if (record5.hostThreadId === query.ancestorThreadId || parentId !== query.ancestorThreadId)
|
|
37635
38392
|
return false;
|
|
37636
38393
|
}
|
|
37637
|
-
if (
|
|
37638
|
-
if (query.projectId !== void 0 && (
|
|
37639
|
-
if (query.cwd !== null && !query.cwd.includes(
|
|
38394
|
+
if (record5.archived !== query.archived) return false;
|
|
38395
|
+
if (query.projectId !== void 0 && (record5.projectId ?? null) !== query.projectId) return false;
|
|
38396
|
+
if (query.cwd !== null && !query.cwd.includes(record5.cwd)) return false;
|
|
37640
38397
|
if (query.modelProviders !== null && query.modelProviders.length > 0 && !query.modelProviders.includes("codexhost")) {
|
|
37641
38398
|
return false;
|
|
37642
38399
|
}
|
|
37643
|
-
if (query.sourceKinds !== null && query.sourceKinds.length > 0 && !query.sourceKinds.includes(sourceKind) && !(
|
|
38400
|
+
if (query.sourceKinds !== null && query.sourceKinds.length > 0 && !query.sourceKinds.includes(sourceKind) && !(record5.subagent && query.sourceKinds.includes("subAgent"))) {
|
|
37644
38401
|
return false;
|
|
37645
38402
|
}
|
|
37646
|
-
if (query.searchTerm !== null && !
|
|
38403
|
+
if (query.searchTerm !== null && !record5.title.toLowerCase().includes(query.searchTerm.toLowerCase())) {
|
|
37647
38404
|
return false;
|
|
37648
38405
|
}
|
|
37649
38406
|
if (query.isPinned === true) return false;
|
|
@@ -37651,7 +38408,7 @@ function includesExternalRecord(record4, query, byId, sectionId) {
|
|
|
37651
38408
|
return true;
|
|
37652
38409
|
}
|
|
37653
38410
|
function resolveExternalSessionTreeIds(records) {
|
|
37654
|
-
const byId = new Map(records.map((
|
|
38411
|
+
const byId = new Map(records.map((record5) => [record5.hostThreadId, record5]));
|
|
37655
38412
|
const resolved = /* @__PURE__ */ new Map();
|
|
37656
38413
|
const resolve = (start) => {
|
|
37657
38414
|
const cached2 = resolved.get(start.hostThreadId);
|
|
@@ -37662,7 +38419,7 @@ function resolveExternalSessionTreeIds(records) {
|
|
|
37662
38419
|
while (true) {
|
|
37663
38420
|
const known = resolved.get(current.hostThreadId);
|
|
37664
38421
|
if (known) {
|
|
37665
|
-
for (const
|
|
38422
|
+
for (const record5 of path43) resolved.set(record5.hostThreadId, known);
|
|
37666
38423
|
return known;
|
|
37667
38424
|
}
|
|
37668
38425
|
if (visited.has(current.hostThreadId)) {
|
|
@@ -37674,32 +38431,32 @@ function resolveExternalSessionTreeIds(records) {
|
|
|
37674
38431
|
const source = sourceId ? byId.get(sourceId) : void 0;
|
|
37675
38432
|
if (!source) {
|
|
37676
38433
|
const root = current.hostThreadId;
|
|
37677
|
-
for (const
|
|
38434
|
+
for (const record5 of path43) resolved.set(record5.hostThreadId, root);
|
|
37678
38435
|
return root;
|
|
37679
38436
|
}
|
|
37680
38437
|
current = source;
|
|
37681
38438
|
}
|
|
37682
38439
|
};
|
|
37683
|
-
for (const
|
|
38440
|
+
for (const record5 of records) resolve(record5);
|
|
37684
38441
|
return resolved;
|
|
37685
38442
|
}
|
|
37686
38443
|
function externalThreadListEntries(input) {
|
|
37687
38444
|
const sessionIds = resolveExternalSessionTreeIds(input.records);
|
|
37688
|
-
const byId = new Map(input.records.map((
|
|
38445
|
+
const byId = new Map(input.records.map((record5) => [record5.hostThreadId, record5]));
|
|
37689
38446
|
return input.records.filter(
|
|
37690
|
-
(
|
|
37691
|
-
|
|
38447
|
+
(record5) => includesExternalRecord(
|
|
38448
|
+
record5,
|
|
37692
38449
|
input.query,
|
|
37693
38450
|
byId,
|
|
37694
|
-
input.placementOf?.(
|
|
38451
|
+
input.placementOf?.(record5.hostThreadId)?.section.id ?? null
|
|
37695
38452
|
)
|
|
37696
|
-
).map((
|
|
37697
|
-
const runtime = input.runtimeFor(
|
|
37698
|
-
const sessionId = sessionIds.get(
|
|
38453
|
+
).map((record5) => {
|
|
38454
|
+
const runtime = input.runtimeFor(record5.hostThreadId);
|
|
38455
|
+
const sessionId = sessionIds.get(record5.hostThreadId);
|
|
37699
38456
|
if (!sessionId) throw new Error("External Thread Session tree could not be resolved");
|
|
37700
|
-
const placement = input.placementOf?.(
|
|
38457
|
+
const placement = input.placementOf?.(record5.hostThreadId);
|
|
37701
38458
|
const thread = externalThreadValue({
|
|
37702
|
-
record:
|
|
38459
|
+
record: record5,
|
|
37703
38460
|
turns: [],
|
|
37704
38461
|
sessionId,
|
|
37705
38462
|
...runtime ? { running: runtime.running } : { loaded: false },
|
|
@@ -37708,7 +38465,7 @@ function externalThreadListEntries(input) {
|
|
|
37708
38465
|
return {
|
|
37709
38466
|
source: "external",
|
|
37710
38467
|
thread,
|
|
37711
|
-
timestamp: input.query.sortKey === "created_at" ? unixTimestamp(
|
|
38468
|
+
timestamp: input.query.sortKey === "created_at" ? unixTimestamp(record5.createdAt, "createdAt") : unixTimestamp(record5.updatedAt, "updatedAt")
|
|
37712
38469
|
};
|
|
37713
38470
|
});
|
|
37714
38471
|
}
|
|
@@ -37811,7 +38568,7 @@ async function aggregateThreadList(input) {
|
|
|
37811
38568
|
let officialIndex = 0;
|
|
37812
38569
|
let firstOfficialBackwardsCursor;
|
|
37813
38570
|
let officialRequestCount = 0;
|
|
37814
|
-
const externalIds = new Set(input.records.map((
|
|
38571
|
+
const externalIds = new Set(input.records.map((record5) => record5.hostThreadId));
|
|
37815
38572
|
for (const thread of input.sharedThreads ?? []) externalIds.add(String(thread.id));
|
|
37816
38573
|
const requestOfficial = async (cursor, limit) => {
|
|
37817
38574
|
officialRequestCount += 1;
|
|
@@ -38153,7 +38910,6 @@ async function moveThreadSection(input) {
|
|
|
38153
38910
|
// packages/host-runtime/src/external-thread-official-defaults.ts
|
|
38154
38911
|
var EMPTY_RESULTS = /* @__PURE__ */ new Map([
|
|
38155
38912
|
["thread/attachment/list", () => ({ data: [], nextCursor: null })],
|
|
38156
|
-
["thread/queue/list", () => ({ data: [], nextCursor: null })],
|
|
38157
38913
|
["thread/settings/update", () => ({})]
|
|
38158
38914
|
]);
|
|
38159
38915
|
function externalThreadEmptyOfficialResult(method) {
|
|
@@ -38503,6 +39259,9 @@ var AppServerHost = class {
|
|
|
38503
39259
|
#executionHosts = /* @__PURE__ */ new WeakMap();
|
|
38504
39260
|
#externalPrewarms = new ExternalThreadPrewarms();
|
|
38505
39261
|
#externalSteering = new ExternalTurnSteering();
|
|
39262
|
+
#externalQueue = new ExternalThreadQueue({
|
|
39263
|
+
notifyChanged: (threadId2) => this.#writer.json({ method: "thread/queue/changed", params: { threadId: threadId2 } })
|
|
39264
|
+
});
|
|
38506
39265
|
#liveCommandCache = new LiveCommandCatalogCache();
|
|
38507
39266
|
#modelPrices;
|
|
38508
39267
|
#observedSessionUsage;
|
|
@@ -38529,7 +39288,7 @@ var AppServerHost = class {
|
|
|
38529
39288
|
#sectionMoves = Promise.resolve();
|
|
38530
39289
|
#writer;
|
|
38531
39290
|
/** Console requests share Desktop handling; their replies return to the console. */
|
|
38532
|
-
#consoleRequestPrefix = `codexhost-console:${
|
|
39291
|
+
#consoleRequestPrefix = `codexhost-console:${randomUUID17()}:`;
|
|
38533
39292
|
#consoleReplies = /* @__PURE__ */ new Map();
|
|
38534
39293
|
#nextConsoleRequest = 0;
|
|
38535
39294
|
#subagentThreadStatuses = /* @__PURE__ */ new Map();
|
|
@@ -38638,16 +39397,7 @@ var AppServerHost = class {
|
|
|
38638
39397
|
hasRunningDescendants: (threadId2) => this.#hasRunningSubagents(threadId2),
|
|
38639
39398
|
idleRelease: {
|
|
38640
39399
|
queue: this.#desktopRequests,
|
|
38641
|
-
onClosed:
|
|
38642
|
-
for (const pending of [...this.#pendingDesktopApprovals.values()]) {
|
|
38643
|
-
if (pending.thread === thread)
|
|
38644
|
-
await this.#resolveDesktopApproval(pending.interaction.interactionId);
|
|
38645
|
-
}
|
|
38646
|
-
for (const pending of [...this.#pendingDesktopQuestions.values()]) {
|
|
38647
|
-
if (pending.thread === thread)
|
|
38648
|
-
await this.#resolveDesktopQuestion(pending.interaction.interactionId);
|
|
38649
|
-
}
|
|
38650
|
-
},
|
|
39400
|
+
onClosed: (thread) => this.#resolveThreadInteractions(thread),
|
|
38651
39401
|
canRelease: (thread) => !this.#hasRunningSubagents(thread.id) && !thread.session.hasBackgroundWork?.() && !this.#externalSteering.hasPending(thread.id) && !this.#pendingExternalCommandRequests.has(thread.id) && ![...this.#pendingDesktopApprovals.values()].some(
|
|
38652
39402
|
(pending) => pending.thread === thread
|
|
38653
39403
|
) && ![...this.#pendingDesktopQuestions.values()].some((pending) => pending.thread === thread)
|
|
@@ -38837,12 +39587,12 @@ var AppServerHost = class {
|
|
|
38837
39587
|
await this.#closeAdapters();
|
|
38838
39588
|
await this.#externalRuntime.drain();
|
|
38839
39589
|
for (const pending of [...this.#pendingDesktopApprovals.values()]) {
|
|
38840
|
-
await this.#resolveDesktopApproval(pending.interaction.interactionId).catch(
|
|
39590
|
+
await this.#resolveDesktopApproval(pending.interaction.interactionId, pending.thread).catch(
|
|
38841
39591
|
() => void 0
|
|
38842
39592
|
);
|
|
38843
39593
|
}
|
|
38844
39594
|
for (const pending of [...this.#pendingDesktopQuestions.values()]) {
|
|
38845
|
-
await this.#resolveDesktopQuestion(pending.interaction.interactionId).catch(
|
|
39595
|
+
await this.#resolveDesktopQuestion(pending.interaction.interactionId, pending.thread).catch(
|
|
38846
39596
|
() => void 0
|
|
38847
39597
|
);
|
|
38848
39598
|
}
|
|
@@ -39766,6 +40516,18 @@ var AppServerHost = class {
|
|
|
39766
40516
|
return;
|
|
39767
40517
|
}
|
|
39768
40518
|
}
|
|
40519
|
+
if (request.method.startsWith("thread/queue/") && isRecord18(request.params) && typeof request.params.threadId === "string") {
|
|
40520
|
+
const location = await this.#locateExternalThread(request.params.threadId);
|
|
40521
|
+
if (await this.#writeResolutionError(request, location)) return;
|
|
40522
|
+
if (location.kind === "external") {
|
|
40523
|
+
this.#dispatchDesktopReply(
|
|
40524
|
+
request,
|
|
40525
|
+
() => this.#handleExternalQueueRequest(request, location.record.hostThreadId),
|
|
40526
|
+
location.record.hostThreadId
|
|
40527
|
+
);
|
|
40528
|
+
return;
|
|
40529
|
+
}
|
|
40530
|
+
}
|
|
39769
40531
|
if (request.method === "thread/backgroundTerminals/clean" && isRecord18(request.params) && typeof request.params.threadId === "string") {
|
|
39770
40532
|
const location = await this.#locateExternalThread(request.params.threadId);
|
|
39771
40533
|
if (await this.#writeResolutionError(request, location)) return;
|
|
@@ -40176,7 +40938,7 @@ var AppServerHost = class {
|
|
|
40176
40938
|
throw error51;
|
|
40177
40939
|
}
|
|
40178
40940
|
this.#activeOfficialTurns.set(threadId2, turnId);
|
|
40179
|
-
const delegationId = hostThreadIdSchema.parse(
|
|
40941
|
+
const delegationId = hostThreadIdSchema.parse(randomUUID17());
|
|
40180
40942
|
try {
|
|
40181
40943
|
const source = await this.#repository.find(input.parentThreadId);
|
|
40182
40944
|
const pendingTerminal = this.#pendingOfficialTerminalStatuses.get(threadId2);
|
|
@@ -40364,7 +41126,7 @@ var AppServerHost = class {
|
|
|
40364
41126
|
async #listDelegationThreads(input) {
|
|
40365
41127
|
const [sortKey, sortDirection2] = input.sort.split("-");
|
|
40366
41128
|
const request = {
|
|
40367
|
-
id: `codexhost:delegation-list:${
|
|
41129
|
+
id: `codexhost:delegation-list:${randomUUID17()}`,
|
|
40368
41130
|
method: "thread/list",
|
|
40369
41131
|
params: {
|
|
40370
41132
|
cwd: input.cwd ? [input.cwd] : null,
|
|
@@ -40389,12 +41151,12 @@ var AppServerHost = class {
|
|
|
40389
41151
|
return {
|
|
40390
41152
|
threads: result.data.flatMap((entry) => {
|
|
40391
41153
|
if (typeof entry.id !== "string") return [];
|
|
40392
|
-
const
|
|
41154
|
+
const record5 = records.find((candidate) => candidate.hostThreadId === entry.id);
|
|
40393
41155
|
const status2 = isRecord18(entry.status) && entry.status.type === "active" ? "running" : "completed";
|
|
40394
41156
|
return [
|
|
40395
41157
|
{
|
|
40396
41158
|
threadId: entry.id,
|
|
40397
|
-
harnessId:
|
|
41159
|
+
harnessId: record5 ? record5.harnessId : "codex",
|
|
40398
41160
|
deepLink: `codex://threads/${entry.id}`,
|
|
40399
41161
|
status: status2,
|
|
40400
41162
|
...typeof entry.cwd === "string" ? { cwd: entry.cwd } : {},
|
|
@@ -40501,7 +41263,7 @@ var AppServerHost = class {
|
|
|
40501
41263
|
const outcome = await moveThreadSection({
|
|
40502
41264
|
move,
|
|
40503
41265
|
movingExternal: location.kind === "external",
|
|
40504
|
-
externalThreadIds: new Set(records.map((
|
|
41266
|
+
externalThreadIds: new Set(records.map((record5) => record5.hostThreadId)),
|
|
40505
41267
|
placements,
|
|
40506
41268
|
requestOfficial: (method, params) => this.#requestOfficial(method, params),
|
|
40507
41269
|
savePlacements: (next) => this.#repository.replaceSectionPlacements(next),
|
|
@@ -40591,10 +41353,10 @@ var AppServerHost = class {
|
|
|
40591
41353
|
/** Clear External assignments to a project official Codex reported as deleted. */
|
|
40592
41354
|
async #clearDeletedProjectAssignments(projectId) {
|
|
40593
41355
|
const records = await this.#repository.list();
|
|
40594
|
-
for (const
|
|
40595
|
-
if (
|
|
41356
|
+
for (const record5 of records) {
|
|
41357
|
+
if (record5.projectId !== projectId) continue;
|
|
40596
41358
|
const updated = await this.#repository.updateMetadata(
|
|
40597
|
-
|
|
41359
|
+
record5.hostThreadId,
|
|
40598
41360
|
{ projectId: null },
|
|
40599
41361
|
{ ifProjectId: projectId }
|
|
40600
41362
|
);
|
|
@@ -40607,14 +41369,14 @@ var AppServerHost = class {
|
|
|
40607
41369
|
});
|
|
40608
41370
|
}
|
|
40609
41371
|
}
|
|
40610
|
-
#syncLoadedExternalThread(thread,
|
|
41372
|
+
#syncLoadedExternalThread(thread, record5) {
|
|
40611
41373
|
const projected = externalThreadValue({
|
|
40612
|
-
record:
|
|
41374
|
+
record: record5,
|
|
40613
41375
|
turns: [],
|
|
40614
41376
|
sessionId: thread.sessionId,
|
|
40615
41377
|
running: thread.running
|
|
40616
41378
|
});
|
|
40617
|
-
thread.record =
|
|
41379
|
+
thread.record = record5;
|
|
40618
41380
|
thread.thread = { ...thread.thread, ...projected, turns: thread.thread.turns ?? [] };
|
|
40619
41381
|
return projected;
|
|
40620
41382
|
}
|
|
@@ -40631,15 +41393,15 @@ var AppServerHost = class {
|
|
|
40631
41393
|
);
|
|
40632
41394
|
return null;
|
|
40633
41395
|
}
|
|
40634
|
-
let
|
|
41396
|
+
let record5;
|
|
40635
41397
|
try {
|
|
40636
|
-
|
|
41398
|
+
record5 = await write(location.record.hostThreadId);
|
|
40637
41399
|
} catch {
|
|
40638
41400
|
await this.#writer.json(rpcError(request, -32081, failureMessage));
|
|
40639
41401
|
return null;
|
|
40640
41402
|
}
|
|
40641
|
-
const projected = location.thread ? this.#syncLoadedExternalThread(location.thread,
|
|
40642
|
-
return { record:
|
|
41403
|
+
const projected = location.thread ? this.#syncLoadedExternalThread(location.thread, record5) : externalThreadValue({ record: record5, turns: [], sessionId, loaded: false });
|
|
41404
|
+
return { record: record5, thread: await this.#withExternalSection(projected) };
|
|
40643
41405
|
}
|
|
40644
41406
|
async #handleConsoleOpen(request) {
|
|
40645
41407
|
if (!consoleOpenParamsSchema.safeParse(request.params ?? {}).success) {
|
|
@@ -40895,8 +41657,8 @@ var AppServerHost = class {
|
|
|
40895
41657
|
const sharedHarness = shared?.get(threadId2);
|
|
40896
41658
|
if (sharedHarness)
|
|
40897
41659
|
return { threadId: threadId2, owner: "external", harnessId: sharedHarness };
|
|
40898
|
-
const
|
|
40899
|
-
return
|
|
41660
|
+
const record5 = await this.#repository.find(threadId2);
|
|
41661
|
+
return record5 ? { threadId: threadId2, owner: "external", harnessId: record5.harnessId } : { threadId: threadId2, owner: "codex" };
|
|
40900
41662
|
})
|
|
40901
41663
|
);
|
|
40902
41664
|
const result = threadOwnershipListResultSchema.parse({ threads });
|
|
@@ -41092,7 +41854,7 @@ var AppServerHost = class {
|
|
|
41092
41854
|
if (thread.running || thread.activeTurnId) {
|
|
41093
41855
|
throw new ExternalCommandError(-32072, "External Thread already has an active operation");
|
|
41094
41856
|
}
|
|
41095
|
-
const turnId = requestedTurnId ?? hostTurnIdSchema.parse(
|
|
41857
|
+
const turnId = requestedTurnId ?? hostTurnIdSchema.parse(randomUUID17());
|
|
41096
41858
|
const projection = {
|
|
41097
41859
|
projector: new CodexTurnProjector({
|
|
41098
41860
|
threadId: thread.id,
|
|
@@ -41407,6 +42169,7 @@ var AppServerHost = class {
|
|
|
41407
42169
|
}
|
|
41408
42170
|
const params = requestObject(request);
|
|
41409
42171
|
const route = decodeCreateRoute(request);
|
|
42172
|
+
const prewarm = params[EXTERNAL_THREAD_PREWARM_PARAM] === true || route?.prewarm === true;
|
|
41410
42173
|
const requestedModel = route && route.harnessId !== "codex" ? route.model : void 0;
|
|
41411
42174
|
const requestedThinkingOptionId = route && route.harnessId !== "codex" ? route.thinkingOptionId : void 0;
|
|
41412
42175
|
const requestedPermissionModeId = route && route.harnessId !== "codex" ? route.permissionModeId : void 0;
|
|
@@ -41426,9 +42189,9 @@ var AppServerHost = class {
|
|
|
41426
42189
|
ephemeral: params.ephemeral === true,
|
|
41427
42190
|
historyMode: params.historyMode === "paginated" ? "paginated" : "legacy"
|
|
41428
42191
|
});
|
|
41429
|
-
let
|
|
42192
|
+
let record5;
|
|
41430
42193
|
try {
|
|
41431
|
-
|
|
42194
|
+
record5 = await this.#repository.createProvisional(recordInput);
|
|
41432
42195
|
} catch {
|
|
41433
42196
|
this.#routeObservationTracker.rejectCreate(request.id);
|
|
41434
42197
|
await this.#writer.json(rpcError(request, -32081, "External Thread could not be persisted"));
|
|
@@ -41439,7 +42202,7 @@ var AppServerHost = class {
|
|
|
41439
42202
|
cwd,
|
|
41440
42203
|
environment: {
|
|
41441
42204
|
...this.#options.environment ?? process.env,
|
|
41442
|
-
[DELEGATION_THREAD_ID_ENV]:
|
|
42205
|
+
[DELEGATION_THREAD_ID_ENV]: record5.hostThreadId
|
|
41443
42206
|
},
|
|
41444
42207
|
...requestedModel ? { model: requestedModel } : {},
|
|
41445
42208
|
...requestedThinkingOptionId ? { thinkingOptionId: requestedThinkingOptionId } : {},
|
|
@@ -41447,37 +42210,37 @@ var AppServerHost = class {
|
|
|
41447
42210
|
});
|
|
41448
42211
|
if (!sessionResult.ok) {
|
|
41449
42212
|
this.#routeObservationTracker.rejectCreate(request.id);
|
|
41450
|
-
await this.#repository.removeProvisional(
|
|
42213
|
+
await this.#repository.removeProvisional(record5.hostThreadId).catch(() => void 0);
|
|
41451
42214
|
const mapped = mapExternalThreadHarnessError(sessionResult.error, "create");
|
|
41452
42215
|
await this.#writer.json(rpcError(request, mapped.code, mapped.message));
|
|
41453
42216
|
return;
|
|
41454
42217
|
}
|
|
41455
42218
|
const session = sessionResult.value;
|
|
41456
|
-
await this.#externalRuntime.idleRelease.runOperation(
|
|
42219
|
+
await this.#externalRuntime.idleRelease.runOperation(record5.hostThreadId, async () => {
|
|
41457
42220
|
try {
|
|
41458
|
-
if (session.initialState.nativeRef &&
|
|
41459
|
-
|
|
41460
|
-
|
|
42221
|
+
if (session.initialState.nativeRef && !prewarm) {
|
|
42222
|
+
record5 = await this.#repository.commitNative(
|
|
42223
|
+
record5.hostThreadId,
|
|
41461
42224
|
session.initialState.nativeRef
|
|
41462
42225
|
);
|
|
41463
42226
|
}
|
|
41464
42227
|
const thread = externalThreadValue({
|
|
41465
|
-
record:
|
|
42228
|
+
record: record5,
|
|
41466
42229
|
turns: [],
|
|
41467
|
-
sessionId:
|
|
42230
|
+
sessionId: record5.hostThreadId
|
|
41468
42231
|
});
|
|
41469
42232
|
const externalThread = this.#registerExternalThread({
|
|
41470
|
-
record:
|
|
42233
|
+
record: record5,
|
|
41471
42234
|
session,
|
|
41472
|
-
unsubmittedPrewarm:
|
|
41473
|
-
sessionId:
|
|
42235
|
+
unsubmittedPrewarm: prewarm,
|
|
42236
|
+
sessionId: record5.hostThreadId,
|
|
41474
42237
|
thread,
|
|
41475
42238
|
turns: [],
|
|
41476
42239
|
...requestedModel ? { requestedModel } : {},
|
|
41477
42240
|
...requestedThinkingOptionId ? { requestedThinkingOptionId } : {},
|
|
41478
42241
|
...requestedPermissionModeId ? { requestedPermissionModeId } : {}
|
|
41479
42242
|
});
|
|
41480
|
-
if (
|
|
42243
|
+
if (prewarm) {
|
|
41481
42244
|
this.#externalPrewarms.register(externalThread);
|
|
41482
42245
|
}
|
|
41483
42246
|
this.#routeObservationTracker.bindCreatedThread(request.id, externalThread.id);
|
|
@@ -41500,12 +42263,12 @@ var AppServerHost = class {
|
|
|
41500
42263
|
}
|
|
41501
42264
|
})
|
|
41502
42265
|
);
|
|
41503
|
-
if (
|
|
42266
|
+
if (record5.state === "ready") await this.#notifyExternalThreadStarted(thread);
|
|
41504
42267
|
} catch {
|
|
41505
|
-
this.#externalRuntime.remove(
|
|
41506
|
-
this.#routeObservationTracker.forgetThread(
|
|
42268
|
+
this.#externalRuntime.remove(record5.hostThreadId);
|
|
42269
|
+
this.#routeObservationTracker.forgetThread(record5.hostThreadId);
|
|
41507
42270
|
await session.close().catch(() => void 0);
|
|
41508
|
-
await this.#repository.removeProvisional(
|
|
42271
|
+
await this.#repository.removeProvisional(record5.hostThreadId).catch(() => void 0);
|
|
41509
42272
|
await this.#writer.json(
|
|
41510
42273
|
rpcError(request, -32081, "External Thread could not be persisted")
|
|
41511
42274
|
);
|
|
@@ -41667,9 +42430,9 @@ var AppServerHost = class {
|
|
|
41667
42430
|
);
|
|
41668
42431
|
return;
|
|
41669
42432
|
}
|
|
41670
|
-
let
|
|
42433
|
+
let record5;
|
|
41671
42434
|
try {
|
|
41672
|
-
|
|
42435
|
+
record5 = await this.#repository.setTitle(location.record.hostThreadId, name);
|
|
41673
42436
|
} catch {
|
|
41674
42437
|
await this.#writer.json(
|
|
41675
42438
|
rpcError(request, -32081, "External Thread title could not be persisted")
|
|
@@ -41677,7 +42440,7 @@ var AppServerHost = class {
|
|
|
41677
42440
|
return;
|
|
41678
42441
|
}
|
|
41679
42442
|
if (location.thread) {
|
|
41680
|
-
location.thread.record =
|
|
42443
|
+
location.thread.record = record5;
|
|
41681
42444
|
location.thread.thread.name = name;
|
|
41682
42445
|
location.thread.thread.updatedAt = unixSeconds();
|
|
41683
42446
|
}
|
|
@@ -41688,29 +42451,24 @@ var AppServerHost = class {
|
|
|
41688
42451
|
});
|
|
41689
42452
|
}
|
|
41690
42453
|
async #deleteExternalThread(request, location) {
|
|
41691
|
-
const thread = location.thread;
|
|
41692
42454
|
try {
|
|
41693
|
-
await this.#
|
|
41694
|
-
} catch {
|
|
41695
|
-
await this.#writer.json(rpcError(request, -32081, "External Thread could not be removed"));
|
|
41696
|
-
return;
|
|
41697
|
-
}
|
|
41698
|
-
this.#externalRuntime.remove(location.record.hostThreadId);
|
|
41699
|
-
this.#routeObservationTracker.forgetThread(location.record.hostThreadId);
|
|
41700
|
-
if (!thread) {
|
|
41701
|
-
await this.#writer.json(rpcEnvelope(request, { result: {} }));
|
|
41702
|
-
return;
|
|
41703
|
-
}
|
|
41704
|
-
thread.stateObserver.fault(new Error("External Thread was deleted"));
|
|
41705
|
-
try {
|
|
41706
|
-
await thread.session.close();
|
|
41707
|
-
await thread.outputTask;
|
|
41708
|
-
await this.#writer.json(rpcEnvelope(request, { result: {} }));
|
|
42455
|
+
await this.#externalRuntime.deleteThread(location.record.hostThreadId);
|
|
41709
42456
|
} catch (error51) {
|
|
42457
|
+
if (!(error51 instanceof ExternalSessionReleaseError) && location.thread)
|
|
42458
|
+
await this.#resolveThreadInteractions(location.thread);
|
|
41710
42459
|
await this.#writer.json(
|
|
41711
|
-
rpcError(request, -32075,
|
|
42460
|
+
error51 instanceof ExternalSessionReleaseError ? rpcError(request, -32075, error51.message) : rpcError(request, -32081, "External Thread could not be removed")
|
|
41712
42461
|
);
|
|
42462
|
+
return;
|
|
41713
42463
|
}
|
|
42464
|
+
if (location.thread) await this.#resolveThreadInteractions(location.thread);
|
|
42465
|
+
this.#routeObservationTracker.forgetThread(location.record.hostThreadId);
|
|
42466
|
+
this.#externalQueue.forget(location.record.hostThreadId);
|
|
42467
|
+
await this.#writer.json(rpcEnvelope(request, { result: {} }));
|
|
42468
|
+
await this.#writer.json({
|
|
42469
|
+
method: "thread/deleted",
|
|
42470
|
+
params: { threadId: location.record.hostThreadId }
|
|
42471
|
+
});
|
|
41714
42472
|
}
|
|
41715
42473
|
async #readExternalThreadMetadata(request, location) {
|
|
41716
42474
|
try {
|
|
@@ -41959,6 +42717,125 @@ var AppServerHost = class {
|
|
|
41959
42717
|
);
|
|
41960
42718
|
}
|
|
41961
42719
|
}
|
|
42720
|
+
async #handleExternalQueueRequest(request, threadId2) {
|
|
42721
|
+
const queue = this.#externalQueue;
|
|
42722
|
+
try {
|
|
42723
|
+
const params = requestObject(request);
|
|
42724
|
+
const input = () => {
|
|
42725
|
+
requestText(params);
|
|
42726
|
+
return params.input;
|
|
42727
|
+
};
|
|
42728
|
+
const submissionId = () => {
|
|
42729
|
+
if (typeof params.queuedSubmissionId !== "string")
|
|
42730
|
+
throw new ExternalQueueError(-32602, "queuedSubmissionId must be a string");
|
|
42731
|
+
return params.queuedSubmissionId;
|
|
42732
|
+
};
|
|
42733
|
+
let result;
|
|
42734
|
+
switch (request.method) {
|
|
42735
|
+
case "thread/queue/list":
|
|
42736
|
+
result = queue.list(threadId2, params);
|
|
42737
|
+
break;
|
|
42738
|
+
case "thread/queue/add": {
|
|
42739
|
+
if (typeof params.clientUserMessageId !== "string" || !params.clientUserMessageId)
|
|
42740
|
+
throw new ExternalQueueError(-32602, "clientUserMessageId must be a string");
|
|
42741
|
+
const sourceHostId = params[THREAD_REFERENCE_SOURCE_HOST_PARAM];
|
|
42742
|
+
const submission = await queue.add(
|
|
42743
|
+
threadId2,
|
|
42744
|
+
input(),
|
|
42745
|
+
params.clientUserMessageId,
|
|
42746
|
+
typeof sourceHostId === "string" ? sourceHostId : void 0
|
|
42747
|
+
);
|
|
42748
|
+
result = { queuedSubmission: submission };
|
|
42749
|
+
break;
|
|
42750
|
+
}
|
|
42751
|
+
case "thread/queue/update": {
|
|
42752
|
+
const submission = await queue.update(threadId2, submissionId(), input());
|
|
42753
|
+
result = { queuedSubmission: submission };
|
|
42754
|
+
break;
|
|
42755
|
+
}
|
|
42756
|
+
case "thread/queue/delete":
|
|
42757
|
+
result = { deleted: await queue.delete(threadId2, submissionId()) };
|
|
42758
|
+
break;
|
|
42759
|
+
case "thread/queue/reorder": {
|
|
42760
|
+
const ids = params.queuedSubmissionIds;
|
|
42761
|
+
if (!Array.isArray(ids) || !ids.every((id2) => typeof id2 === "string"))
|
|
42762
|
+
throw new ExternalQueueError(-32602, "queuedSubmissionIds must be strings");
|
|
42763
|
+
await queue.reorder(threadId2, ids);
|
|
42764
|
+
result = {};
|
|
42765
|
+
break;
|
|
42766
|
+
}
|
|
42767
|
+
case "thread/queue/start": {
|
|
42768
|
+
const resolution = await this.#resolveExternalThread(threadId2);
|
|
42769
|
+
if (await this.#writeResolutionError(request, resolution)) return;
|
|
42770
|
+
if (resolution.kind !== "external")
|
|
42771
|
+
throw new ExternalQueueError(-32073, "External Thread is no longer available");
|
|
42772
|
+
const started = await this.#startQueuedSubmission(
|
|
42773
|
+
resolution.thread,
|
|
42774
|
+
params.queuedSubmissionId == null ? null : submissionId()
|
|
42775
|
+
);
|
|
42776
|
+
try {
|
|
42777
|
+
await this.#writer.json(rpcEnvelope(request, { result: { turn: started.turn } }));
|
|
42778
|
+
} finally {
|
|
42779
|
+
started.gate.resolve();
|
|
42780
|
+
}
|
|
42781
|
+
return;
|
|
42782
|
+
}
|
|
42783
|
+
default:
|
|
42784
|
+
throw new ExternalQueueError(
|
|
42785
|
+
-32076,
|
|
42786
|
+
`External Thread does not support ${request.method}`
|
|
42787
|
+
);
|
|
42788
|
+
}
|
|
42789
|
+
await this.#writer.json(rpcEnvelope(request, { result }));
|
|
42790
|
+
if (request.method === "thread/queue/add") {
|
|
42791
|
+
const thread = this.#externalRuntime.get(threadId2);
|
|
42792
|
+
const lastTurn = thread?.turns.at(-1);
|
|
42793
|
+
if (thread && thread.projectedTerminalTurnId === lastTurn?.id && lastTurn?.status === "completed" && isRecord18(thread.thread.status) && thread.thread.status.type === "idle") {
|
|
42794
|
+
void this.#drainExternalQueue(thread);
|
|
42795
|
+
}
|
|
42796
|
+
}
|
|
42797
|
+
} catch (error51) {
|
|
42798
|
+
await this.#writer.json(
|
|
42799
|
+
rpcError(
|
|
42800
|
+
request,
|
|
42801
|
+
error51 instanceof ExternalQueueError || error51 instanceof ExternalSteerError || error51 instanceof ExternalCommandError ? error51.code : -32602,
|
|
42802
|
+
errorMessage4(error51)
|
|
42803
|
+
)
|
|
42804
|
+
);
|
|
42805
|
+
}
|
|
42806
|
+
}
|
|
42807
|
+
/** Starts a queued follow-up as a Turn; it returns to its place when the start fails. */
|
|
42808
|
+
async #startQueuedSubmission(thread, submissionId) {
|
|
42809
|
+
if (this.#externalThreadBusy(thread) || this.#pendingExternalCommandRequests.has(thread.id))
|
|
42810
|
+
throw new ExternalSteerError(-32072, "External Thread already has an active Turn");
|
|
42811
|
+
const taken = this.#externalQueue.take(thread.id, submissionId);
|
|
42812
|
+
try {
|
|
42813
|
+
const started = await this.#beginExternalInputTurn(
|
|
42814
|
+
thread,
|
|
42815
|
+
requestText({ input: taken.submission.input }),
|
|
42816
|
+
void 0,
|
|
42817
|
+
taken.submission.clientUserMessageId,
|
|
42818
|
+
taken.sourceHostId,
|
|
42819
|
+
true
|
|
42820
|
+
);
|
|
42821
|
+
await this.#externalQueue.notifyChanged(thread.id);
|
|
42822
|
+
return started;
|
|
42823
|
+
} catch (error51) {
|
|
42824
|
+
this.#externalQueue.restore(thread.id, taken);
|
|
42825
|
+
await this.#externalQueue.notifyChanged(thread.id);
|
|
42826
|
+
throw error51;
|
|
42827
|
+
}
|
|
42828
|
+
}
|
|
42829
|
+
/** Desktop leaves queued follow-ups to the app-server once a Turn completes normally. */
|
|
42830
|
+
async #drainExternalQueue(thread) {
|
|
42831
|
+
if (!this.#externalQueue.has(thread.id) || this.#externalThreadBusy(thread) || this.#pendingExternalCommandRequests.has(thread.id))
|
|
42832
|
+
return;
|
|
42833
|
+
try {
|
|
42834
|
+
(await this.#startQueuedSubmission(thread)).gate.resolve();
|
|
42835
|
+
} catch (error51) {
|
|
42836
|
+
this.#diagnose(error51);
|
|
42837
|
+
}
|
|
42838
|
+
}
|
|
41962
42839
|
async #steerExternalTurn(request, thread) {
|
|
41963
42840
|
try {
|
|
41964
42841
|
const started = await this.#externalSteering.run(
|
|
@@ -42023,12 +42900,12 @@ var AppServerHost = class {
|
|
|
42023
42900
|
};
|
|
42024
42901
|
}
|
|
42025
42902
|
/** Keep command restoration and dispatch identical for start and steer submissions. */
|
|
42026
|
-
async #beginExternalInputTurn(thread, inputText, assertActive, clientUserMessageId, sourceHostId) {
|
|
42903
|
+
async #beginExternalInputTurn(thread, inputText, assertActive, clientUserMessageId, sourceHostId, projectInput = false) {
|
|
42027
42904
|
const text = restoreHarnessCommandMentions(inputText);
|
|
42028
42905
|
const commands = thread.session.commands;
|
|
42029
42906
|
if (!commands || !isExternalCommandCandidate(text)) {
|
|
42030
42907
|
assertActive?.();
|
|
42031
|
-
return this.#beginExternalTurn(thread, text, clientUserMessageId, sourceHostId);
|
|
42908
|
+
return this.#beginExternalTurn(thread, text, clientUserMessageId, sourceHostId, projectInput);
|
|
42032
42909
|
}
|
|
42033
42910
|
this.#pendingExternalCommandRequests.add(thread.id);
|
|
42034
42911
|
try {
|
|
@@ -42039,7 +42916,13 @@ var AppServerHost = class {
|
|
|
42039
42916
|
assertActive?.();
|
|
42040
42917
|
if (!command) {
|
|
42041
42918
|
this.#pendingExternalCommandRequests.delete(thread.id);
|
|
42042
|
-
return await this.#beginExternalTurn(
|
|
42919
|
+
return await this.#beginExternalTurn(
|
|
42920
|
+
thread,
|
|
42921
|
+
text,
|
|
42922
|
+
clientUserMessageId,
|
|
42923
|
+
sourceHostId,
|
|
42924
|
+
projectInput
|
|
42925
|
+
);
|
|
42043
42926
|
}
|
|
42044
42927
|
return await this.#beginExternalCommand(
|
|
42045
42928
|
thread,
|
|
@@ -42072,14 +42955,18 @@ var AppServerHost = class {
|
|
|
42072
42955
|
else this.#executionHosts.set(thread, previousHostId);
|
|
42073
42956
|
};
|
|
42074
42957
|
}
|
|
42075
|
-
|
|
42958
|
+
/**
|
|
42959
|
+
* Desktop renders the input of its own `turn/start` locally. Other starts (Host-only clients
|
|
42960
|
+
* and queued follow-ups) need the user message projected with the Turn.
|
|
42961
|
+
*/
|
|
42962
|
+
async #beginExternalTurn(thread, text, clientUserMessageId, sourceHostId, projectInput = false) {
|
|
42076
42963
|
if (this.#closeRequested || this.#externalRuntime.get(thread.id) !== thread) {
|
|
42077
42964
|
throw new ExternalSteerError(-32073, "External Thread is no longer available");
|
|
42078
42965
|
}
|
|
42079
42966
|
if (thread.running || thread.activeTurnId || this.#pendingExternalCommandRequests.has(thread.id)) {
|
|
42080
42967
|
throw new ExternalSteerError(-32072, "External Thread already has an active Turn");
|
|
42081
42968
|
}
|
|
42082
|
-
const turnId = hostTurnIdSchema.parse(
|
|
42969
|
+
const turnId = hostTurnIdSchema.parse(randomUUID17());
|
|
42083
42970
|
const startedAtMs = Date.now();
|
|
42084
42971
|
const projection = {
|
|
42085
42972
|
projector: new CodexTurnProjector({
|
|
@@ -42087,7 +42974,7 @@ var AppServerHost = class {
|
|
|
42087
42974
|
turnId,
|
|
42088
42975
|
cwd: thread.cwd,
|
|
42089
42976
|
startedAtMs,
|
|
42090
|
-
...this.#options.externalOnly ? {
|
|
42977
|
+
...this.#options.externalOnly || projectInput ? {
|
|
42091
42978
|
initialInput: [{ type: "text", text }],
|
|
42092
42979
|
...clientUserMessageId ? { clientUserMessageId } : {}
|
|
42093
42980
|
} : {}
|
|
@@ -42318,21 +43205,21 @@ var AppServerHost = class {
|
|
|
42318
43205
|
}
|
|
42319
43206
|
if (event.type === "subagent.transcript.changed") {
|
|
42320
43207
|
const nativeSubagentId = event.nativeSubagentId;
|
|
42321
|
-
const
|
|
43208
|
+
const record5 = (await this.#repository.list()).find(
|
|
42322
43209
|
(candidate) => candidate.subagent?.parentHostThreadId === thread.id && candidate.subagent.nativeSubagentId === nativeSubagentId && candidate.nativeSessionRef?.nativeSessionId === thread.record.nativeSessionRef?.nativeSessionId
|
|
42323
43210
|
);
|
|
42324
|
-
if (
|
|
43211
|
+
if (record5) await this.#refreshOpenSubagentThread(record5.hostThreadId, false);
|
|
42325
43212
|
return;
|
|
42326
43213
|
}
|
|
42327
43214
|
if (event.type === "subagent.state.changed") {
|
|
42328
43215
|
const nativeSubagentId = event.nativeSubagentId;
|
|
42329
|
-
const
|
|
43216
|
+
const record5 = (await this.#repository.list()).find(
|
|
42330
43217
|
(candidate) => candidate.subagent?.parentHostThreadId === thread.id && candidate.subagent.nativeSubagentId === nativeSubagentId && candidate.nativeSessionRef?.nativeSessionId === thread.record.nativeSessionRef?.nativeSessionId
|
|
42331
43218
|
);
|
|
42332
|
-
if (!
|
|
43219
|
+
if (!record5) return;
|
|
42333
43220
|
const status2 = event.status === "pending" || event.status === "running" ? "active" : "idle";
|
|
42334
|
-
this.#trackRunningSubagent(thread.id,
|
|
42335
|
-
await this.#setSubagentThreadStatus(
|
|
43221
|
+
this.#trackRunningSubagent(thread.id, record5.hostThreadId, status2);
|
|
43222
|
+
await this.#setSubagentThreadStatus(record5.hostThreadId, status2);
|
|
42336
43223
|
if (!thread.running && !thread.activeTurnId && !this.#hasRunningSubagents(thread.id)) {
|
|
42337
43224
|
await this.#setThreadStatus(thread, { type: "idle" });
|
|
42338
43225
|
}
|
|
@@ -42341,7 +43228,7 @@ var AppServerHost = class {
|
|
|
42341
43228
|
if (event.type === "session.faulted") {
|
|
42342
43229
|
for (const pending of [...this.#pendingDesktopQuestions.values()]) {
|
|
42343
43230
|
if (pending.shared && pending.thread === thread)
|
|
42344
|
-
this.#retireDesktopQuestion(pending.interaction.interactionId);
|
|
43231
|
+
this.#retireDesktopQuestion(pending.interaction.interactionId, thread);
|
|
42345
43232
|
}
|
|
42346
43233
|
this.#externalSteering.fault(thread.id, new Error(event.error.message));
|
|
42347
43234
|
thread.stateObserver.fault(new Error(event.error.message));
|
|
@@ -42389,12 +43276,12 @@ var AppServerHost = class {
|
|
|
42389
43276
|
if (event.type === "turn.completed") {
|
|
42390
43277
|
for (const pending of [...this.#pendingDesktopQuestions.values()]) {
|
|
42391
43278
|
if (pending.shared && pending.thread === thread && pending.interaction.turnId === event.turnId)
|
|
42392
|
-
this.#retireDesktopQuestion(pending.interaction.interactionId);
|
|
43279
|
+
this.#retireDesktopQuestion(pending.interaction.interactionId, thread);
|
|
42393
43280
|
}
|
|
42394
43281
|
}
|
|
42395
43282
|
if (event.type === "interaction.closed") {
|
|
42396
|
-
await this.#resolveDesktopApproval(event.interactionId);
|
|
42397
|
-
await this.#resolveDesktopQuestion(event.interactionId);
|
|
43283
|
+
await this.#resolveDesktopApproval(event.interactionId, thread);
|
|
43284
|
+
await this.#resolveDesktopQuestion(event.interactionId, thread);
|
|
42398
43285
|
}
|
|
42399
43286
|
const ephemeralTurn = event.type === "turn.completed" && (event.ephemeral === true || thread.ephemeralTurnIds.has(event.turnId));
|
|
42400
43287
|
if (event.type === "turn.completed" && !ephemeralTurn) {
|
|
@@ -42460,32 +43347,35 @@ var AppServerHost = class {
|
|
|
42460
43347
|
this.#hasRunningSubagents(thread.id) ? { type: "active", activeFlags: [] } : { type: "idle" }
|
|
42461
43348
|
);
|
|
42462
43349
|
this.#externalSteering.terminal(thread.id, event.turnId, event.outcome);
|
|
43350
|
+
if (!ephemeralTurn && result.completedTurn?.status === "completed" && this.#externalQueue.has(thread.id)) {
|
|
43351
|
+
void this.#drainExternalQueue(thread);
|
|
43352
|
+
}
|
|
42463
43353
|
}
|
|
42464
43354
|
}
|
|
42465
43355
|
async #materializeSubagent(parent, subagent) {
|
|
42466
43356
|
if (!subagent.nativeSubagentId || !parent.record.nativeSessionRef) return subagent;
|
|
42467
43357
|
const status2 = subagent.status === "pending" || subagent.status === "running" ? "active" : "idle";
|
|
42468
|
-
const
|
|
42469
|
-
if (!
|
|
42470
|
-
if (this.#subagentThreadStatuses.has(
|
|
42471
|
-
this.#trackRunningSubagent(parent.id,
|
|
42472
|
-
await this.#setSubagentThreadStatus(
|
|
42473
|
-
return { ...subagent, subagentId:
|
|
43358
|
+
const record5 = await this.#repository.materializeSubagent(parent.record, subagent);
|
|
43359
|
+
if (!record5) return subagent;
|
|
43360
|
+
if (this.#subagentThreadStatuses.has(record5.hostThreadId)) {
|
|
43361
|
+
this.#trackRunningSubagent(parent.id, record5.hostThreadId, status2);
|
|
43362
|
+
await this.#setSubagentThreadStatus(record5.hostThreadId, status2);
|
|
43363
|
+
return { ...subagent, subagentId: record5.hostThreadId };
|
|
42474
43364
|
}
|
|
42475
43365
|
const thread = externalThreadValue({
|
|
42476
|
-
record:
|
|
43366
|
+
record: record5,
|
|
42477
43367
|
turns: [],
|
|
42478
43368
|
sessionId: parent.sessionId,
|
|
42479
43369
|
running: status2 === "active"
|
|
42480
43370
|
});
|
|
42481
|
-
this.#subagentThreadStatuses.set(
|
|
42482
|
-
this.#trackRunningSubagent(parent.id,
|
|
43371
|
+
this.#subagentThreadStatuses.set(record5.hostThreadId, status2);
|
|
43372
|
+
this.#trackRunningSubagent(parent.id, record5.hostThreadId, status2);
|
|
42483
43373
|
await this.#writer.json({
|
|
42484
43374
|
method: "thread/started",
|
|
42485
43375
|
emittedAtMs: Date.now(),
|
|
42486
43376
|
params: { thread }
|
|
42487
43377
|
});
|
|
42488
|
-
return { ...subagent, subagentId:
|
|
43378
|
+
return { ...subagent, subagentId: record5.hostThreadId };
|
|
42489
43379
|
}
|
|
42490
43380
|
async #refreshOpenSubagentThread(threadId2, terminal3 = true) {
|
|
42491
43381
|
await this.#desktopRequests.run(threadId2, async () => {
|
|
@@ -42651,7 +43541,7 @@ var AppServerHost = class {
|
|
|
42651
43541
|
if (this.#externalRuntime.get(pending.thread.id) !== pending.thread || this.#externalRuntime.idleRelease.failure(pending.thread))
|
|
42652
43542
|
return true;
|
|
42653
43543
|
if (this.#options.externalOnly)
|
|
42654
|
-
await this.#resolveDesktopApproval(pending.interaction.interactionId);
|
|
43544
|
+
await this.#resolveDesktopApproval(pending.interaction.interactionId, pending.thread);
|
|
42655
43545
|
else this.#pendingDesktopApprovals.delete(requestId);
|
|
42656
43546
|
let response;
|
|
42657
43547
|
try {
|
|
@@ -42702,9 +43592,20 @@ var AppServerHost = class {
|
|
|
42702
43592
|
}
|
|
42703
43593
|
return denied.ok;
|
|
42704
43594
|
}
|
|
42705
|
-
async #
|
|
43595
|
+
async #resolveThreadInteractions(thread) {
|
|
43596
|
+
for (const pending of [...this.#pendingDesktopApprovals.values()]) {
|
|
43597
|
+
if (pending.thread === thread)
|
|
43598
|
+
await this.#resolveDesktopApproval(pending.interaction.interactionId, thread);
|
|
43599
|
+
}
|
|
43600
|
+
for (const pending of [...this.#pendingDesktopQuestions.values()]) {
|
|
43601
|
+
if (pending.thread === thread)
|
|
43602
|
+
await this.#resolveDesktopQuestion(pending.interaction.interactionId, thread);
|
|
43603
|
+
}
|
|
43604
|
+
}
|
|
43605
|
+
async #resolveDesktopApproval(interactionId, thread) {
|
|
42706
43606
|
for (const [requestId, pending] of this.#pendingDesktopApprovals) {
|
|
42707
|
-
if (pending.interaction.interactionId !== interactionId)
|
|
43607
|
+
if (pending.thread !== thread || pending.interaction.interactionId !== interactionId)
|
|
43608
|
+
continue;
|
|
42708
43609
|
this.#pendingDesktopApprovals.delete(requestId);
|
|
42709
43610
|
await this.#writer.json({
|
|
42710
43611
|
method: "serverRequest/resolved",
|
|
@@ -42763,16 +43664,16 @@ var AppServerHost = class {
|
|
|
42763
43664
|
response
|
|
42764
43665
|
});
|
|
42765
43666
|
} catch (error51) {
|
|
42766
|
-
this.#retireDesktopQuestion(pending.interaction.interactionId);
|
|
43667
|
+
this.#retireDesktopQuestion(pending.interaction.interactionId, thread);
|
|
42767
43668
|
throw error51;
|
|
42768
43669
|
}
|
|
42769
43670
|
if (!result.ok) {
|
|
42770
43671
|
pending.responding = false;
|
|
42771
43672
|
if (result.error.code === "invalidState")
|
|
42772
|
-
this.#retireDesktopQuestion(pending.interaction.interactionId);
|
|
43673
|
+
this.#retireDesktopQuestion(pending.interaction.interactionId, thread);
|
|
42773
43674
|
throw new Error(result.error.message);
|
|
42774
43675
|
}
|
|
42775
|
-
this.#retireDesktopQuestion(pending.interaction.interactionId);
|
|
43676
|
+
this.#retireDesktopQuestion(pending.interaction.interactionId, thread);
|
|
42776
43677
|
await this.#writer.json(rpcEnvelope(request, { result: { accepted: true } }));
|
|
42777
43678
|
});
|
|
42778
43679
|
} catch (error51) {
|
|
@@ -42788,7 +43689,7 @@ var AppServerHost = class {
|
|
|
42788
43689
|
if (shared) sharedQuestion(interaction);
|
|
42789
43690
|
result = projection.projector.projectQuestion(
|
|
42790
43691
|
interaction,
|
|
42791
|
-
hostItemIdSchema.parse(
|
|
43692
|
+
hostItemIdSchema.parse(randomUUID17())
|
|
42792
43693
|
);
|
|
42793
43694
|
} catch (error51) {
|
|
42794
43695
|
this.#diagnose(error51);
|
|
@@ -42826,7 +43727,7 @@ var AppServerHost = class {
|
|
|
42826
43727
|
try {
|
|
42827
43728
|
await this.#writer.json({ id: requestId, ...result.questionRequest.request });
|
|
42828
43729
|
} catch (error51) {
|
|
42829
|
-
this.#retireDesktopQuestion(interaction.interactionId);
|
|
43730
|
+
this.#retireDesktopQuestion(interaction.interactionId, thread);
|
|
42830
43731
|
await thread.session.execute({
|
|
42831
43732
|
type: "interaction.respond",
|
|
42832
43733
|
interactionId: interaction.interactionId,
|
|
@@ -42844,7 +43745,7 @@ var AppServerHost = class {
|
|
|
42844
43745
|
if (this.#externalRuntime.get(pending.thread.id) !== pending.thread || this.#externalRuntime.idleRelease.failure(pending.thread))
|
|
42845
43746
|
return true;
|
|
42846
43747
|
if (this.#options.externalOnly)
|
|
42847
|
-
await this.#resolveDesktopQuestion(pending.interaction.interactionId);
|
|
43748
|
+
await this.#resolveDesktopQuestion(pending.interaction.interactionId, pending.thread);
|
|
42848
43749
|
else this.#pendingDesktopQuestions.delete(requestId);
|
|
42849
43750
|
if (pending.timeout) clearTimeout(pending.timeout);
|
|
42850
43751
|
let response;
|
|
@@ -42871,7 +43772,7 @@ var AppServerHost = class {
|
|
|
42871
43772
|
await this.#externalRuntime.idleRelease.runOperation(pending.thread.id, async () => {
|
|
42872
43773
|
if (this.#externalRuntime.get(pending.thread.id) !== pending.thread || this.#externalRuntime.idleRelease.failure(pending.thread))
|
|
42873
43774
|
return;
|
|
42874
|
-
await this.#resolveDesktopQuestion(pending.interaction.interactionId);
|
|
43775
|
+
await this.#resolveDesktopQuestion(pending.interaction.interactionId, pending.thread);
|
|
42875
43776
|
if (pending.responding) return;
|
|
42876
43777
|
const result = await pending.thread.session.execute({
|
|
42877
43778
|
type: "interaction.respond",
|
|
@@ -42883,16 +43784,18 @@ var AppServerHost = class {
|
|
|
42883
43784
|
}
|
|
42884
43785
|
});
|
|
42885
43786
|
}
|
|
42886
|
-
#retireDesktopQuestion(interactionId) {
|
|
43787
|
+
#retireDesktopQuestion(interactionId, thread) {
|
|
42887
43788
|
for (const [requestId, pending] of this.#pendingDesktopQuestions) {
|
|
42888
|
-
if (pending.interaction.interactionId !== interactionId)
|
|
43789
|
+
if (pending.thread !== thread || pending.interaction.interactionId !== interactionId)
|
|
43790
|
+
continue;
|
|
42889
43791
|
if (pending.timeout) clearTimeout(pending.timeout);
|
|
42890
43792
|
this.#pendingDesktopQuestions.delete(requestId);
|
|
42891
43793
|
}
|
|
42892
43794
|
}
|
|
42893
|
-
async #resolveDesktopQuestion(interactionId) {
|
|
43795
|
+
async #resolveDesktopQuestion(interactionId, thread) {
|
|
42894
43796
|
for (const [requestId, pending] of this.#pendingDesktopQuestions) {
|
|
42895
|
-
if (pending.interaction.interactionId !== interactionId)
|
|
43797
|
+
if (pending.thread !== thread || pending.interaction.interactionId !== interactionId)
|
|
43798
|
+
continue;
|
|
42896
43799
|
if (pending.timeout) clearTimeout(pending.timeout);
|
|
42897
43800
|
this.#pendingDesktopQuestions.delete(requestId);
|
|
42898
43801
|
if (pending.shared) continue;
|
|
@@ -43032,7 +43935,7 @@ var import_websocket_server = __toESM(require_websocket_server(), 1);
|
|
|
43032
43935
|
var wrapper_default = import_websocket.default;
|
|
43033
43936
|
|
|
43034
43937
|
// packages/host-runtime/src/remote-socket-lock.ts
|
|
43035
|
-
import { randomUUID as
|
|
43938
|
+
import { randomUUID as randomUUID18 } from "node:crypto";
|
|
43036
43939
|
import { chmod as chmod3, lstat as lstat5, mkdir as mkdir12, open as open9, readFile as readFile16, readdir as readdir5, rename as rename11, rm as rm11 } from "node:fs/promises";
|
|
43037
43940
|
import { uptime } from "node:os";
|
|
43038
43941
|
import path26 from "node:path";
|
|
@@ -43046,18 +43949,18 @@ var LOCK_ENTRY_SUFFIX = ".json";
|
|
|
43046
43949
|
function currentBootTimeSeconds() {
|
|
43047
43950
|
return Math.round(Date.now() / 1e3 - uptime());
|
|
43048
43951
|
}
|
|
43049
|
-
function validOwnerFields(
|
|
43050
|
-
return typeof
|
|
43952
|
+
function validOwnerFields(record5) {
|
|
43953
|
+
return typeof record5.ownerToken === "string" && record5.ownerToken.length > 0 && typeof record5.pid === "number" && Number.isSafeInteger(record5.pid) && record5.pid > 0 && typeof record5.bootTimeSeconds === "number" && Number.isSafeInteger(record5.bootTimeSeconds);
|
|
43051
43954
|
}
|
|
43052
43955
|
function parseLockRecord(source) {
|
|
43053
43956
|
try {
|
|
43054
43957
|
const value2 = JSON.parse(source);
|
|
43055
43958
|
if (typeof value2 !== "object" || value2 === null || Array.isArray(value2)) return null;
|
|
43056
|
-
const
|
|
43057
|
-
if (
|
|
43959
|
+
const record5 = value2;
|
|
43960
|
+
if (record5.version !== 2 || !validOwnerFields(record5) || typeof record5.choosing !== "boolean" || typeof record5.ticket !== "number" || !Number.isSafeInteger(record5.ticket) || record5.ticket < 0 || (record5.choosing ? record5.ticket !== 0 : record5.ticket === 0)) {
|
|
43058
43961
|
return null;
|
|
43059
43962
|
}
|
|
43060
|
-
return
|
|
43963
|
+
return record5;
|
|
43061
43964
|
} catch {
|
|
43062
43965
|
return null;
|
|
43063
43966
|
}
|
|
@@ -43066,9 +43969,9 @@ function parseLegacyLockRecord(source) {
|
|
|
43066
43969
|
try {
|
|
43067
43970
|
const value2 = JSON.parse(source);
|
|
43068
43971
|
if (typeof value2 !== "object" || value2 === null || Array.isArray(value2)) return null;
|
|
43069
|
-
const
|
|
43070
|
-
if (
|
|
43071
|
-
return
|
|
43972
|
+
const record5 = value2;
|
|
43973
|
+
if (record5.version !== 1 || !validOwnerFields(record5)) return null;
|
|
43974
|
+
return record5;
|
|
43072
43975
|
} catch {
|
|
43073
43976
|
return null;
|
|
43074
43977
|
}
|
|
@@ -43081,10 +43984,10 @@ function processIsRunning(pid) {
|
|
|
43081
43984
|
return error51.code !== "ESRCH";
|
|
43082
43985
|
}
|
|
43083
43986
|
}
|
|
43084
|
-
function ownerIsAbandoned(
|
|
43085
|
-
if (Math.abs(
|
|
43987
|
+
function ownerIsAbandoned(record5, mtimeMs) {
|
|
43988
|
+
if (Math.abs(record5.bootTimeSeconds - currentBootTimeSeconds()) > 5) return true;
|
|
43086
43989
|
if (Math.max(0, Date.now() - mtimeMs) >= LOCK_MAX_AGE_MS) return true;
|
|
43087
|
-
return !processIsRunning(
|
|
43990
|
+
return !processIsRunning(record5.pid);
|
|
43088
43991
|
}
|
|
43089
43992
|
function sameUnixFileIdentity(left, right) {
|
|
43090
43993
|
return left.dev === right.dev && left.ino === right.ino;
|
|
@@ -43103,13 +44006,13 @@ async function readLockEntrySnapshot(filePath) {
|
|
|
43103
44006
|
throw error51;
|
|
43104
44007
|
});
|
|
43105
44008
|
if (source === null) return null;
|
|
43106
|
-
const
|
|
44009
|
+
const record5 = parseLockRecord(source);
|
|
43107
44010
|
return {
|
|
43108
44011
|
filePath,
|
|
43109
44012
|
source,
|
|
43110
44013
|
identity: { dev: metadata.dev, ino: metadata.ino },
|
|
43111
44014
|
mtimeMs: metadata.mtimeMs,
|
|
43112
|
-
record:
|
|
44015
|
+
record: record5 && path26.basename(filePath) === lockEntryName(record5.ownerToken) ? record5 : null
|
|
43113
44016
|
};
|
|
43114
44017
|
}
|
|
43115
44018
|
function lockEntryIsAbandoned(snapshot2) {
|
|
@@ -43157,11 +44060,11 @@ async function preparePrivateLockDirectory(lockDirectory) {
|
|
|
43157
44060
|
}
|
|
43158
44061
|
await chmod3(lockDirectory, 448);
|
|
43159
44062
|
}
|
|
43160
|
-
async function writeLockRecordAtomic(lockDirectory, entryPath,
|
|
43161
|
-
const temporary = path26.join(lockDirectory, `.tmp-${
|
|
44063
|
+
async function writeLockRecordAtomic(lockDirectory, entryPath, record5) {
|
|
44064
|
+
const temporary = path26.join(lockDirectory, `.tmp-${record5.ownerToken}-${randomUUID18()}`);
|
|
43162
44065
|
const handle = await open9(temporary, "wx", 384);
|
|
43163
44066
|
try {
|
|
43164
|
-
await handle.writeFile(`${JSON.stringify(
|
|
44067
|
+
await handle.writeFile(`${JSON.stringify(record5)}
|
|
43165
44068
|
`, "utf8");
|
|
43166
44069
|
await handle.sync();
|
|
43167
44070
|
} finally {
|
|
@@ -43191,11 +44094,11 @@ async function legacyLockState(legacyPath) {
|
|
|
43191
44094
|
});
|
|
43192
44095
|
if (source === null) return "absent";
|
|
43193
44096
|
const ageMs = Math.max(0, Date.now() - metadata.mtimeMs);
|
|
43194
|
-
const
|
|
43195
|
-
if (
|
|
43196
|
-
return ownerIsAbandoned(
|
|
44097
|
+
const record5 = parseLegacyLockRecord(source);
|
|
44098
|
+
if (record5 === null) return ageMs < LOCK_MALFORMED_GRACE_MS ? "blocking" : "abandoned";
|
|
44099
|
+
return ownerIsAbandoned(record5, metadata.mtimeMs) ? "abandoned" : "blocking";
|
|
43197
44100
|
}
|
|
43198
|
-
async function tryAcquireLegacyCompatibilityGuard(legacyPath,
|
|
44101
|
+
async function tryAcquireLegacyCompatibilityGuard(legacyPath, record5) {
|
|
43199
44102
|
const handle = await open9(legacyPath, "wx", 384).catch((error51) => {
|
|
43200
44103
|
if (error51.code === "EEXIST") return null;
|
|
43201
44104
|
throw error51;
|
|
@@ -43204,7 +44107,7 @@ async function tryAcquireLegacyCompatibilityGuard(legacyPath, record4) {
|
|
|
43204
44107
|
const metadata = await handle.stat();
|
|
43205
44108
|
const guard = { handle, identity: { dev: metadata.dev, ino: metadata.ino } };
|
|
43206
44109
|
try {
|
|
43207
|
-
await handle.writeFile(`${JSON.stringify(
|
|
44110
|
+
await handle.writeFile(`${JSON.stringify(record5)}
|
|
43208
44111
|
`, "utf8");
|
|
43209
44112
|
await handle.sync();
|
|
43210
44113
|
return guard;
|
|
@@ -43233,7 +44136,7 @@ async function withRemoteAppServerSocketInitializationLock(socketPath, action) {
|
|
|
43233
44136
|
const legacyPath = `${socketPath}.initializing`;
|
|
43234
44137
|
const lockDirectory = `${socketPath}.initializers`;
|
|
43235
44138
|
await preparePrivateLockDirectory(lockDirectory);
|
|
43236
|
-
const ownerToken =
|
|
44139
|
+
const ownerToken = randomUUID18();
|
|
43237
44140
|
const entryPath = path26.join(lockDirectory, lockEntryName(ownerToken));
|
|
43238
44141
|
const baseRecord = {
|
|
43239
44142
|
version: 2,
|
|
@@ -43270,8 +44173,8 @@ async function withRemoteAppServerSocketInitializationLock(socketPath, action) {
|
|
|
43270
44173
|
throw new Error(`Remote app-server socket lock ownership was lost at ${socketPath}`);
|
|
43271
44174
|
}
|
|
43272
44175
|
const blockedByBakery = catalog.entries.some((entry) => {
|
|
43273
|
-
const
|
|
43274
|
-
return
|
|
44176
|
+
const record5 = entry.record;
|
|
44177
|
+
return record5 !== null && record5.ownerToken !== ownerToken && (record5.choosing || recordHasPriority(record5, ownRecord));
|
|
43275
44178
|
});
|
|
43276
44179
|
if (!catalog.unsettled && !blockedByBakery) {
|
|
43277
44180
|
const legacyGuard = await tryAcquireLegacyCompatibilityGuard(legacyPath, {
|
|
@@ -43744,12 +44647,12 @@ function createRemoteAppServerWebSocketListener(input) {
|
|
|
43744
44647
|
|
|
43745
44648
|
// packages/host-runtime/src/remote-official-app-server.ts
|
|
43746
44649
|
import { spawn as spawn5 } from "node:child_process";
|
|
43747
|
-
import { randomUUID as
|
|
44650
|
+
import { randomUUID as randomUUID19 } from "node:crypto";
|
|
43748
44651
|
import { lstat as lstat7, rm as rm13, stat as stat7 } from "node:fs/promises";
|
|
43749
44652
|
import path28 from "node:path";
|
|
43750
44653
|
var DEFAULT_CLOSE_TIMEOUT_MS = 2e3;
|
|
43751
44654
|
var DEFAULT_LISTEN_TIMEOUT_MS = 1e4;
|
|
43752
|
-
function remoteOfficialAppServerSocketPath(desktopControlSocketPath, token =
|
|
44655
|
+
function remoteOfficialAppServerSocketPath(desktopControlSocketPath, token = randomUUID19()) {
|
|
43753
44656
|
if (!path28.posix.isAbsolute(desktopControlSocketPath)) {
|
|
43754
44657
|
throw new Error("Desktop control socket path must be absolute");
|
|
43755
44658
|
}
|
|
@@ -44968,11 +45871,11 @@ async function readRemoteDelegationThread(environment, input) {
|
|
|
44968
45871
|
}
|
|
44969
45872
|
|
|
44970
45873
|
// packages/host-runtime/src/shared-thread-owner.ts
|
|
44971
|
-
import { randomUUID as
|
|
45874
|
+
import { randomUUID as randomUUID21 } from "node:crypto";
|
|
44972
45875
|
import { PassThrough as PassThrough3 } from "node:stream";
|
|
44973
45876
|
|
|
44974
45877
|
// packages/host-runtime/src/shared-thread-peer.ts
|
|
44975
|
-
import { randomUUID as
|
|
45878
|
+
import { randomUUID as randomUUID20 } from "node:crypto";
|
|
44976
45879
|
function object5(value2) {
|
|
44977
45880
|
return value2 !== null && typeof value2 === "object" && !Array.isArray(value2);
|
|
44978
45881
|
}
|
|
@@ -44986,7 +45889,7 @@ var StreamThreadPeer = class {
|
|
|
44986
45889
|
input;
|
|
44987
45890
|
output;
|
|
44988
45891
|
stop;
|
|
44989
|
-
#prefix = `shared:${
|
|
45892
|
+
#prefix = `shared:${randomUUID20()}:`;
|
|
44990
45893
|
#pending = /* @__PURE__ */ new Map();
|
|
44991
45894
|
#listeners = /* @__PURE__ */ new Set();
|
|
44992
45895
|
#ended = Promise.withResolvers();
|
|
@@ -45064,7 +45967,7 @@ var SharedThreadOwner = class {
|
|
|
45064
45967
|
input = new PassThrough3();
|
|
45065
45968
|
output = new PassThrough3();
|
|
45066
45969
|
#peer = new StreamThreadPeer(this.output, this.input, () => this.input.end());
|
|
45067
|
-
#prefix = `shared-interaction:${
|
|
45970
|
+
#prefix = `shared-interaction:${randomUUID21()}:`;
|
|
45068
45971
|
#interactions = /* @__PURE__ */ new Map();
|
|
45069
45972
|
#listeners = /* @__PURE__ */ new Set();
|
|
45070
45973
|
#receipts = /* @__PURE__ */ new Map();
|
|
@@ -45374,7 +46277,7 @@ var SharedThreadBridge = class {
|
|
|
45374
46277
|
};
|
|
45375
46278
|
|
|
45376
46279
|
// packages/host-runtime/src/remote-control-app-server.ts
|
|
45377
|
-
import { randomUUID as
|
|
46280
|
+
import { randomUUID as randomUUID22 } from "node:crypto";
|
|
45378
46281
|
import { mkdir as mkdir15, open as open10, rename as rename12, rm as rm14 } from "node:fs/promises";
|
|
45379
46282
|
import path33 from "node:path";
|
|
45380
46283
|
var REMOTE_CONTROL_BRIDGE_PIPE_ENV = "CODEXHOST_REMOTE_CONTROL_BRIDGE_PIPE";
|
|
@@ -45395,7 +46298,7 @@ function nodeCompatibleWindowsPath(value2) {
|
|
|
45395
46298
|
if (value2.startsWith("\\\\?\\")) return value2.slice(4);
|
|
45396
46299
|
return value2;
|
|
45397
46300
|
}
|
|
45398
|
-
function remoteControlBridgePipePath(processId = process.pid, instanceId =
|
|
46301
|
+
function remoteControlBridgePipePath(processId = process.pid, instanceId = randomUUID22()) {
|
|
45399
46302
|
const safeInstance = instanceId.replaceAll(/[^a-zA-Z0-9-]/gu, "");
|
|
45400
46303
|
if (!safeInstance) throw new Error("Remote Control bridge instance ID is invalid");
|
|
45401
46304
|
return `\\\\.\\pipe\\codexhost-remote-control-${processId}-${safeInstance}`;
|
|
@@ -45410,7 +46313,7 @@ async function publishRemoteControlAppServerDescriptor(plan) {
|
|
|
45410
46313
|
await mkdir15(directory, { recursive: true, mode: 448 });
|
|
45411
46314
|
const temporaryPath = path33.join(
|
|
45412
46315
|
directory,
|
|
45413
|
-
`.${REMOTE_CONTROL_BRIDGE_DESCRIPTOR_FILE}.${plan.descriptor.ownerPid}.${
|
|
46316
|
+
`.${REMOTE_CONTROL_BRIDGE_DESCRIPTOR_FILE}.${plan.descriptor.ownerPid}.${randomUUID22()}.tmp`
|
|
45414
46317
|
);
|
|
45415
46318
|
const handle = await open10(temporaryPath, "wx", 384);
|
|
45416
46319
|
try {
|
|
@@ -45603,12 +46506,12 @@ async function startConsoleControlServer(options2) {
|
|
|
45603
46506
|
reply(response, 400, { error: { code: -32700, message: "Invalid request body" } });
|
|
45604
46507
|
return;
|
|
45605
46508
|
}
|
|
45606
|
-
const
|
|
45607
|
-
if (typeof
|
|
46509
|
+
const record5 = typeof body === "object" && body !== null ? body : {};
|
|
46510
|
+
if (typeof record5.method !== "string") {
|
|
45608
46511
|
reply(response, 400, { error: { code: -32600, message: "method is required" } });
|
|
45609
46512
|
return;
|
|
45610
46513
|
}
|
|
45611
|
-
reply(response, 200, await options2.target.handleConsoleRequest(
|
|
46514
|
+
reply(response, 200, await options2.target.handleConsoleRequest(record5.method, record5.params));
|
|
45612
46515
|
})().catch((error51) => {
|
|
45613
46516
|
if (!response.headersSent) {
|
|
45614
46517
|
reply(response, 500, {
|
|
@@ -45903,7 +46806,7 @@ function createHostUpdateCoordinator(options2) {
|
|
|
45903
46806
|
onPrepared
|
|
45904
46807
|
});
|
|
45905
46808
|
}
|
|
45906
|
-
if (platform !== "darwin") await manager.start(prepared2);
|
|
46809
|
+
if (platform !== "darwin" && platform !== "win32") await manager.start(prepared2);
|
|
45907
46810
|
} catch (error51) {
|
|
45908
46811
|
await lock.release();
|
|
45909
46812
|
rejectPrepared(error51);
|
|
@@ -45932,7 +46835,7 @@ function createHostUpdateCoordinator(options2) {
|
|
|
45932
46835
|
}
|
|
45933
46836
|
|
|
45934
46837
|
// packages/host-runtime/src/usage-statistics.ts
|
|
45935
|
-
import { randomUUID as
|
|
46838
|
+
import { randomUUID as randomUUID23 } from "node:crypto";
|
|
45936
46839
|
import { mkdir as mkdir17, readFile as readFile17, readdir as readdir6, rename as rename14, rm as rm16, writeFile as writeFile10 } from "node:fs/promises";
|
|
45937
46840
|
import path36 from "node:path";
|
|
45938
46841
|
import { setImmediate as yieldToEventLoop } from "node:timers/promises";
|
|
@@ -46027,14 +46930,14 @@ function parseHarnessUsageEntry(value2) {
|
|
|
46027
46930
|
// packages/host-runtime/src/usage-session-titles.ts
|
|
46028
46931
|
function withHostSessionTitles(result, records) {
|
|
46029
46932
|
const titles = /* @__PURE__ */ new Map();
|
|
46030
|
-
for (const
|
|
46031
|
-
const ref =
|
|
46032
|
-
const title = usageSessionTitle(
|
|
46033
|
-
if (
|
|
46034
|
-
const key = `${
|
|
46933
|
+
for (const record5 of records) {
|
|
46934
|
+
const ref = record5.nativeSessionRef;
|
|
46935
|
+
const title = usageSessionTitle(record5.title);
|
|
46936
|
+
if (record5.state !== "ready" || !ref || ref.harnessId !== record5.harnessId || !title) continue;
|
|
46937
|
+
const key = `${record5.harnessId}\0${ref.nativeSessionId}`;
|
|
46035
46938
|
const previous = titles.get(key);
|
|
46036
|
-
if (!previous ||
|
|
46037
|
-
titles.set(key, { title, updatedAt:
|
|
46939
|
+
if (!previous || record5.updatedAt > previous.updatedAt)
|
|
46940
|
+
titles.set(key, { title, updatedAt: record5.updatedAt });
|
|
46038
46941
|
}
|
|
46039
46942
|
const decorate = (sessions) => sessions.map((session) => {
|
|
46040
46943
|
const title = titles.get(`${session.harness}\0${session.sessionId}`)?.title;
|
|
@@ -46205,6 +47108,8 @@ function emptyTotals() {
|
|
|
46205
47108
|
cachedInputTokens: 0,
|
|
46206
47109
|
cacheWriteInputTokens: 0,
|
|
46207
47110
|
cacheKnownInputTokens: 0,
|
|
47111
|
+
cacheHitCachedInputTokens: 0,
|
|
47112
|
+
cacheHitInputTokens: 0,
|
|
46208
47113
|
outputTokens: 0,
|
|
46209
47114
|
reasoningOutputTokens: 0,
|
|
46210
47115
|
costUsd: 0,
|
|
@@ -46221,6 +47126,10 @@ function addEntry(totals2, entry, cost) {
|
|
|
46221
47126
|
totals2.inputTokens += entry.inputTokens;
|
|
46222
47127
|
totals2.outputTokens += entry.outputTokens;
|
|
46223
47128
|
totals2.reasoningOutputTokens += entry.reasoningOutputTokens ?? 0;
|
|
47129
|
+
if (entry.cachedInputTokens !== void 0) {
|
|
47130
|
+
totals2.cacheHitCachedInputTokens += entry.cachedInputTokens;
|
|
47131
|
+
totals2.cacheHitInputTokens += entry.inputTokens;
|
|
47132
|
+
}
|
|
46224
47133
|
if (entry.cachedInputTokens !== void 0 && entry.cacheWriteInputTokens !== void 0) {
|
|
46225
47134
|
totals2.cachedInputTokens += entry.cachedInputTokens;
|
|
46226
47135
|
totals2.cacheWriteInputTokens += entry.cacheWriteInputTokens;
|
|
@@ -46467,7 +47376,7 @@ var UsageStatistics = class {
|
|
|
46467
47376
|
async #persist(harness2, cache) {
|
|
46468
47377
|
if (!cache.dirty || this.#now() - cache.persistedAtMs < PERSIST_INTERVAL_MS) return;
|
|
46469
47378
|
const file2 = this.#file(harness2);
|
|
46470
|
-
const temporary = `${file2}.${
|
|
47379
|
+
const temporary = `${file2}.${randomUUID23()}.tmp`;
|
|
46471
47380
|
try {
|
|
46472
47381
|
await mkdir17(this.#directory, { recursive: true });
|
|
46473
47382
|
const sources = [...cache.sources].map(([id2, source]) => [
|
|
@@ -47078,7 +47987,7 @@ async function runHostRuntime(input) {
|
|
|
47078
47987
|
}
|
|
47079
47988
|
|
|
47080
47989
|
// packages/host-runtime/src/remote-host-install.ts
|
|
47081
|
-
import { createHash as createHash11, randomUUID as
|
|
47990
|
+
import { createHash as createHash11, randomUUID as randomUUID24 } from "node:crypto";
|
|
47082
47991
|
import { constants as fsConstants } from "node:fs";
|
|
47083
47992
|
import {
|
|
47084
47993
|
access as access3,
|
|
@@ -47177,7 +48086,7 @@ async function writeAtomic(filePath, contents, mode) {
|
|
|
47177
48086
|
await mkdir18(path38.dirname(filePath), { recursive: true, mode: 448 });
|
|
47178
48087
|
const temporary = path38.join(
|
|
47179
48088
|
path38.dirname(filePath),
|
|
47180
|
-
`.${path38.basename(filePath)}.${process.pid}.${
|
|
48089
|
+
`.${path38.basename(filePath)}.${process.pid}.${randomUUID24()}.tmp`
|
|
47181
48090
|
);
|
|
47182
48091
|
try {
|
|
47183
48092
|
if (typeof contents === "string") {
|
|
@@ -47201,7 +48110,7 @@ async function writeAtomicExecutable(filePath, sourcePath) {
|
|
|
47201
48110
|
await mkdir18(path38.dirname(filePath), { recursive: true, mode: 448 });
|
|
47202
48111
|
const temporary = path38.join(
|
|
47203
48112
|
path38.dirname(filePath),
|
|
47204
|
-
`.${path38.basename(filePath)}.${process.pid}.${
|
|
48113
|
+
`.${path38.basename(filePath)}.${process.pid}.${randomUUID24()}.tmp`
|
|
47205
48114
|
);
|
|
47206
48115
|
try {
|
|
47207
48116
|
await copyFile4(sourcePath, temporary);
|
|
@@ -48209,7 +49118,7 @@ var harnessErrorSchema = external_exports.object({
|
|
|
48209
49118
|
var harnessSessionStateSchema = external_exports.custom((value2) => {
|
|
48210
49119
|
if (!value2 || typeof value2 !== "object" || Array.isArray(value2))
|
|
48211
49120
|
return false;
|
|
48212
|
-
const
|
|
49121
|
+
const record5 = value2;
|
|
48213
49122
|
const allowed = /* @__PURE__ */ new Set([
|
|
48214
49123
|
"nativeRef",
|
|
48215
49124
|
"effectiveModel",
|
|
@@ -48218,12 +49127,12 @@ var harnessSessionStateSchema = external_exports.custom((value2) => {
|
|
|
48218
49127
|
"availableThinkingOptions",
|
|
48219
49128
|
"effectivePermissionModeId"
|
|
48220
49129
|
]);
|
|
48221
|
-
if (Object.keys(
|
|
49130
|
+
if (Object.keys(record5).some((key) => !allowed.has(key)))
|
|
48222
49131
|
return false;
|
|
48223
|
-
if (
|
|
49132
|
+
if (record5.nativeRef !== void 0 && !nativeSessionRefSchema.safeParse(record5.nativeRef).success) {
|
|
48224
49133
|
return false;
|
|
48225
49134
|
}
|
|
48226
|
-
const { nativeRef: _nativeRef, ...configuration } =
|
|
49135
|
+
const { nativeRef: _nativeRef, ...configuration } = record5;
|
|
48227
49136
|
void _nativeRef;
|
|
48228
49137
|
return harnessConfigurationStateSchema.safeParse(configuration).success;
|
|
48229
49138
|
});
|
|
@@ -48317,7 +49226,7 @@ function defaultHarnessBrokerSocketPath(environment = process.env, harnessId = "
|
|
|
48317
49226
|
}
|
|
48318
49227
|
|
|
48319
49228
|
// packages/harness-broker/dist/server.js
|
|
48320
|
-
import { randomBytes as randomBytes5, randomUUID as
|
|
49229
|
+
import { randomBytes as randomBytes5, randomUUID as randomUUID25 } from "node:crypto";
|
|
48321
49230
|
import { chmod as chmod6, lstat as lstat10, mkdir as mkdir19, open as open11, readFile as readFile19, rename as rename16, rm as rm18 } from "node:fs/promises";
|
|
48322
49231
|
import net4, {} from "node:net";
|
|
48323
49232
|
import path41 from "node:path";
|
|
@@ -48376,7 +49285,7 @@ async function assertNoLiveDescriptor(descriptorPath) {
|
|
|
48376
49285
|
}
|
|
48377
49286
|
}
|
|
48378
49287
|
async function publishDescriptor(descriptorPath, descriptor) {
|
|
48379
|
-
const temporary = `${descriptorPath}.${process.pid}.${
|
|
49288
|
+
const temporary = `${descriptorPath}.${process.pid}.${randomUUID25()}.tmp`;
|
|
48380
49289
|
const handle = await open11(temporary, "wx", 384);
|
|
48381
49290
|
try {
|
|
48382
49291
|
await handle.writeFile(`${JSON.stringify(descriptor)}
|
|
@@ -48389,28 +49298,28 @@ async function publishDescriptor(descriptorPath, descriptor) {
|
|
|
48389
49298
|
if (process.platform !== "win32")
|
|
48390
49299
|
await chmod6(descriptorPath, 384);
|
|
48391
49300
|
}
|
|
48392
|
-
function sessionMetadata(
|
|
48393
|
-
const initialState = { ...
|
|
48394
|
-
if (
|
|
49301
|
+
function sessionMetadata(record5) {
|
|
49302
|
+
const initialState = { ...record5.session.initialState };
|
|
49303
|
+
if (record5.selection.model && initialState.effectiveModel?.id !== record5.selection.model.id) {
|
|
48395
49304
|
delete initialState.resolvedModelLabel;
|
|
48396
49305
|
}
|
|
48397
|
-
if (
|
|
49306
|
+
if (record5.selection.thinkingOptionId && initialState.effectiveThinkingOptionId !== record5.selection.thinkingOptionId) {
|
|
48398
49307
|
delete initialState.availableThinkingOptions;
|
|
48399
49308
|
}
|
|
48400
49309
|
return {
|
|
48401
|
-
sessionId:
|
|
48402
|
-
sessionGeneration:
|
|
48403
|
-
capabilities:
|
|
49310
|
+
sessionId: record5.id,
|
|
49311
|
+
sessionGeneration: record5.generation,
|
|
49312
|
+
capabilities: record5.session.capabilities,
|
|
48404
49313
|
readCapabilities: true,
|
|
48405
49314
|
initialState: {
|
|
48406
49315
|
...initialState,
|
|
48407
|
-
...
|
|
48408
|
-
...
|
|
48409
|
-
...
|
|
48410
|
-
...
|
|
49316
|
+
...record5.nativeRef ? { nativeRef: record5.nativeRef } : {},
|
|
49317
|
+
...record5.selection.model ? { effectiveModel: record5.selection.model } : {},
|
|
49318
|
+
...record5.selection.thinkingOptionId ? { effectiveThinkingOptionId: record5.selection.thinkingOptionId } : {},
|
|
49319
|
+
...record5.selection.permissionModeId ? { effectivePermissionModeId: record5.selection.permissionModeId } : {}
|
|
48411
49320
|
},
|
|
48412
|
-
initialUsage:
|
|
48413
|
-
commands:
|
|
49321
|
+
initialUsage: record5.session.initialUsage,
|
|
49322
|
+
commands: record5.session.commands !== void 0
|
|
48414
49323
|
};
|
|
48415
49324
|
}
|
|
48416
49325
|
async function socketAcceptsConnections(socketPath) {
|
|
@@ -48454,7 +49363,7 @@ async function startHarnessBrokerServer(input) {
|
|
|
48454
49363
|
await assertNoLiveDescriptor(input.descriptorPath);
|
|
48455
49364
|
if (process.platform !== "win32")
|
|
48456
49365
|
await prepareUnixSocketPath(input.socketPath);
|
|
48457
|
-
const generation = input.generation ??
|
|
49366
|
+
const generation = input.generation ?? randomUUID25();
|
|
48458
49367
|
const token = input.token ?? randomBytes5(32).toString("hex");
|
|
48459
49368
|
const descriptor = {
|
|
48460
49369
|
schemaVersion: 1,
|
|
@@ -48495,7 +49404,7 @@ async function startHarnessBrokerServer(input) {
|
|
|
48495
49404
|
};
|
|
48496
49405
|
const server = net4.createServer((socket) => {
|
|
48497
49406
|
const state = {
|
|
48498
|
-
id:
|
|
49407
|
+
id: randomUUID25(),
|
|
48499
49408
|
socket,
|
|
48500
49409
|
authenticated: false,
|
|
48501
49410
|
inputSequence: 0,
|
|
@@ -48522,15 +49431,15 @@ async function startHarnessBrokerServer(input) {
|
|
|
48522
49431
|
const respond2 = async (request, result) => {
|
|
48523
49432
|
await send({ kind: "response", id: request.id, ...result });
|
|
48524
49433
|
};
|
|
48525
|
-
const releaseProvisionalWriter = (
|
|
48526
|
-
if (
|
|
49434
|
+
const releaseProvisionalWriter = (record5) => {
|
|
49435
|
+
if (record5.provisionalWriterLease && provisionalNativeWriter === record5.id) {
|
|
48527
49436
|
provisionalNativeWriter = void 0;
|
|
48528
49437
|
}
|
|
48529
|
-
|
|
48530
|
-
|
|
49438
|
+
record5.provisionalWriterLease = false;
|
|
49439
|
+
record5.awaitingNativeIdentity = false;
|
|
48531
49440
|
};
|
|
48532
|
-
const forwardOutputs = async (
|
|
48533
|
-
const isCurrent = () => sessions.get(
|
|
49441
|
+
const forwardOutputs = async (record5, nativeSession, sessionGeneration, forwarderEpoch) => {
|
|
49442
|
+
const isCurrent = () => sessions.get(record5.id) === record5 && record5.session === nativeSession && record5.generation === sessionGeneration && record5.forwarderEpoch === forwarderEpoch;
|
|
48534
49443
|
try {
|
|
48535
49444
|
for await (const output of nativeSession.outputs) {
|
|
48536
49445
|
if (!isCurrent())
|
|
@@ -48538,13 +49447,13 @@ async function startHarnessBrokerServer(input) {
|
|
|
48538
49447
|
if (output.kind === "event" && output.event.type === "session.state.changed") {
|
|
48539
49448
|
const state2 = output.event.state;
|
|
48540
49449
|
const observedNativeId = state2.nativeRef?.nativeSessionId;
|
|
48541
|
-
const expectedRef =
|
|
49450
|
+
const expectedRef = record5.nativeWriterRef ?? record5.nativeRef;
|
|
48542
49451
|
if (state2.nativeRef && (state2.nativeRef.harnessId !== input.adapter.harnessId || expectedRef && (expectedRef.harnessId !== state2.nativeRef.harnessId || expectedRef.nativeSessionId !== state2.nativeRef.nativeSessionId || expectedRef.formatVersion !== state2.nativeRef.formatVersion))) {
|
|
48543
|
-
|
|
48544
|
-
releaseProvisionalWriter(
|
|
49452
|
+
record5.faulted = true;
|
|
49453
|
+
releaseProvisionalWriter(record5);
|
|
48545
49454
|
await send({
|
|
48546
49455
|
kind: "output",
|
|
48547
|
-
sessionId:
|
|
49456
|
+
sessionId: record5.id,
|
|
48548
49457
|
sessionGeneration,
|
|
48549
49458
|
output: {
|
|
48550
49459
|
kind: "event",
|
|
@@ -48562,15 +49471,15 @@ async function startHarnessBrokerServer(input) {
|
|
|
48562
49471
|
await nativeSession.close().catch(() => void 0);
|
|
48563
49472
|
break;
|
|
48564
49473
|
}
|
|
48565
|
-
if (observedNativeId && !
|
|
49474
|
+
if (observedNativeId && !record5.writerKey) {
|
|
48566
49475
|
const writerKey = nativeWriterKey(observedNativeId);
|
|
48567
49476
|
const owner = nativeWriters.get(writerKey);
|
|
48568
|
-
if (owner && owner !==
|
|
48569
|
-
|
|
48570
|
-
releaseProvisionalWriter(
|
|
49477
|
+
if (owner && owner !== record5.id) {
|
|
49478
|
+
record5.faulted = true;
|
|
49479
|
+
releaseProvisionalWriter(record5);
|
|
48571
49480
|
await send({
|
|
48572
49481
|
kind: "output",
|
|
48573
|
-
sessionId:
|
|
49482
|
+
sessionId: record5.id,
|
|
48574
49483
|
sessionGeneration,
|
|
48575
49484
|
output: {
|
|
48576
49485
|
kind: "event",
|
|
@@ -48588,38 +49497,38 @@ async function startHarnessBrokerServer(input) {
|
|
|
48588
49497
|
await nativeSession.close().catch(() => void 0);
|
|
48589
49498
|
break;
|
|
48590
49499
|
}
|
|
48591
|
-
nativeWriters.set(writerKey,
|
|
48592
|
-
|
|
48593
|
-
|
|
48594
|
-
|
|
48595
|
-
releaseProvisionalWriter(
|
|
49500
|
+
nativeWriters.set(writerKey, record5.id);
|
|
49501
|
+
record5.nativeId = observedNativeId;
|
|
49502
|
+
record5.nativeRef = state2.nativeRef;
|
|
49503
|
+
record5.writerKey = writerKey;
|
|
49504
|
+
releaseProvisionalWriter(record5);
|
|
48596
49505
|
}
|
|
48597
49506
|
if (state2.nativeRef) {
|
|
48598
|
-
|
|
48599
|
-
|
|
48600
|
-
releaseProvisionalWriter(
|
|
49507
|
+
record5.nativeId = state2.nativeRef.nativeSessionId;
|
|
49508
|
+
record5.nativeRef = state2.nativeRef;
|
|
49509
|
+
releaseProvisionalWriter(record5);
|
|
48601
49510
|
}
|
|
48602
49511
|
if (state2.effectiveModel)
|
|
48603
|
-
|
|
49512
|
+
record5.selection.model = state2.effectiveModel;
|
|
48604
49513
|
if (state2.effectiveThinkingOptionId) {
|
|
48605
|
-
|
|
49514
|
+
record5.selection.thinkingOptionId = state2.effectiveThinkingOptionId;
|
|
48606
49515
|
}
|
|
48607
49516
|
if (state2.effectivePermissionModeId) {
|
|
48608
|
-
|
|
49517
|
+
record5.selection.permissionModeId = state2.effectivePermissionModeId;
|
|
48609
49518
|
}
|
|
48610
49519
|
}
|
|
48611
49520
|
const authenticationTerminal = isAuthenticationTerminal(output);
|
|
48612
49521
|
if (output.kind === "event" && output.event.type === "session.faulted") {
|
|
48613
|
-
|
|
48614
|
-
releaseProvisionalWriter(
|
|
49522
|
+
record5.faulted = true;
|
|
49523
|
+
releaseProvisionalWriter(record5);
|
|
48615
49524
|
}
|
|
48616
49525
|
if (authenticationTerminal) {
|
|
48617
|
-
|
|
48618
|
-
releaseProvisionalWriter(
|
|
49526
|
+
record5.faulted = true;
|
|
49527
|
+
releaseProvisionalWriter(record5);
|
|
48619
49528
|
}
|
|
48620
49529
|
await send({
|
|
48621
49530
|
kind: "output",
|
|
48622
|
-
sessionId:
|
|
49531
|
+
sessionId: record5.id,
|
|
48623
49532
|
sessionGeneration,
|
|
48624
49533
|
output
|
|
48625
49534
|
});
|
|
@@ -48630,26 +49539,26 @@ async function startHarnessBrokerServer(input) {
|
|
|
48630
49539
|
}
|
|
48631
49540
|
} catch {
|
|
48632
49541
|
if (isCurrent()) {
|
|
48633
|
-
|
|
48634
|
-
releaseProvisionalWriter(
|
|
49542
|
+
record5.faulted = true;
|
|
49543
|
+
releaseProvisionalWriter(record5);
|
|
48635
49544
|
}
|
|
48636
49545
|
}
|
|
48637
49546
|
};
|
|
48638
|
-
const closeRecord = async (
|
|
48639
|
-
if (sessions.get(
|
|
49547
|
+
const closeRecord = async (record5) => {
|
|
49548
|
+
if (sessions.get(record5.id) !== record5)
|
|
48640
49549
|
return;
|
|
48641
|
-
sessions.delete(
|
|
49550
|
+
sessions.delete(record5.id);
|
|
48642
49551
|
scheduleIdle();
|
|
48643
|
-
state.sessions.delete(
|
|
48644
|
-
|
|
48645
|
-
const nativeSession =
|
|
48646
|
-
const outputTask =
|
|
49552
|
+
state.sessions.delete(record5.id);
|
|
49553
|
+
record5.forwarderEpoch += 1;
|
|
49554
|
+
const nativeSession = record5.session;
|
|
49555
|
+
const outputTask = record5.outputTask;
|
|
48647
49556
|
await nativeSession.close().catch(() => void 0);
|
|
48648
49557
|
await outputTask.catch(() => void 0);
|
|
48649
|
-
if (
|
|
48650
|
-
nativeWriters.delete(
|
|
49558
|
+
if (record5.writerKey && nativeWriters.get(record5.writerKey) === record5.id) {
|
|
49559
|
+
nativeWriters.delete(record5.writerKey);
|
|
48651
49560
|
}
|
|
48652
|
-
releaseProvisionalWriter(
|
|
49561
|
+
releaseProvisionalWriter(record5);
|
|
48653
49562
|
};
|
|
48654
49563
|
const requireSession = (params) => {
|
|
48655
49564
|
const candidate = params;
|
|
@@ -48657,13 +49566,13 @@ async function startHarnessBrokerServer(input) {
|
|
|
48657
49566
|
sessionId: candidate.sessionId,
|
|
48658
49567
|
sessionGeneration: candidate.sessionGeneration
|
|
48659
49568
|
});
|
|
48660
|
-
const
|
|
48661
|
-
if (!
|
|
49569
|
+
const record5 = sessions.get(parsed2.sessionId);
|
|
49570
|
+
if (!record5 || record5.owner !== state.id)
|
|
48662
49571
|
throw new Error("Harness broker Session is unavailable");
|
|
48663
|
-
if (
|
|
49572
|
+
if (record5.generation !== parsed2.sessionGeneration) {
|
|
48664
49573
|
throw new Error("Harness broker Session generation is stale");
|
|
48665
49574
|
}
|
|
48666
|
-
return
|
|
49575
|
+
return record5;
|
|
48667
49576
|
};
|
|
48668
49577
|
const handleRequest = async (request) => {
|
|
48669
49578
|
if (closed || state.closed)
|
|
@@ -48796,7 +49705,7 @@ async function startHarnessBrokerServer(input) {
|
|
|
48796
49705
|
}
|
|
48797
49706
|
};
|
|
48798
49707
|
}
|
|
48799
|
-
const openReservation =
|
|
49708
|
+
const openReservation = randomUUID25();
|
|
48800
49709
|
if (sourceKey)
|
|
48801
49710
|
nativeWriters.set(sourceKey, openReservation);
|
|
48802
49711
|
const provisionalReservation = openInput.kind === "create" ? openReservation : void 0;
|
|
@@ -48876,7 +49785,7 @@ async function startHarnessBrokerServer(input) {
|
|
|
48876
49785
|
};
|
|
48877
49786
|
}
|
|
48878
49787
|
const delayedCreateIdentity = openInput.kind === "create" && !nativeKey;
|
|
48879
|
-
const
|
|
49788
|
+
const record6 = {
|
|
48880
49789
|
id: openReservation,
|
|
48881
49790
|
generation: 1,
|
|
48882
49791
|
owner: state.id,
|
|
@@ -48897,18 +49806,18 @@ async function startHarnessBrokerServer(input) {
|
|
|
48897
49806
|
...opened.value.initialState.effectivePermissionModeId ? { permissionModeId: opened.value.initialState.effectivePermissionModeId } : {}
|
|
48898
49807
|
}
|
|
48899
49808
|
};
|
|
48900
|
-
sessions.set(
|
|
48901
|
-
state.sessions.add(
|
|
49809
|
+
sessions.set(record6.id, record6);
|
|
49810
|
+
state.sessions.add(record6.id);
|
|
48902
49811
|
if (nativeKey)
|
|
48903
|
-
nativeWriters.set(nativeKey,
|
|
48904
|
-
if (sourceKey && sourceKey !== nativeKey && nativeWriters.get(sourceKey) ===
|
|
49812
|
+
nativeWriters.set(nativeKey, record6.id);
|
|
49813
|
+
if (sourceKey && sourceKey !== nativeKey && nativeWriters.get(sourceKey) === record6.id) {
|
|
48905
49814
|
nativeWriters.delete(sourceKey);
|
|
48906
49815
|
}
|
|
48907
|
-
if (!
|
|
49816
|
+
if (!record6.provisionalWriterLease && provisionalNativeWriter === provisionalReservation) {
|
|
48908
49817
|
provisionalNativeWriter = void 0;
|
|
48909
49818
|
}
|
|
48910
|
-
|
|
48911
|
-
return { ok: true, value: sessionMetadata(
|
|
49819
|
+
record6.outputTask = forwardOutputs(record6, opened.value, record6.generation, record6.forwarderEpoch);
|
|
49820
|
+
return { ok: true, value: sessionMetadata(record6) };
|
|
48912
49821
|
} finally {
|
|
48913
49822
|
if (createSettled) {
|
|
48914
49823
|
openingCreate = void 0;
|
|
@@ -48918,11 +49827,11 @@ async function startHarnessBrokerServer(input) {
|
|
|
48918
49827
|
}
|
|
48919
49828
|
if (request.method === "session.execute") {
|
|
48920
49829
|
const parsed2 = sessionExecuteParamsSchema.parse(request.params);
|
|
48921
|
-
const
|
|
49830
|
+
const record6 = requireSession(parsed2);
|
|
48922
49831
|
const command = brokerHostCommandSchema.parse(parsed2.command);
|
|
48923
|
-
if (
|
|
48924
|
-
const isBootstrapTurn = command.type === "turn.start" &&
|
|
48925
|
-
const isBootstrapTurnContinuation =
|
|
49832
|
+
if (record6.awaitingNativeIdentity && !record6.writerKey) {
|
|
49833
|
+
const isBootstrapTurn = command.type === "turn.start" && record6.provisionalWriterLease && record6.bootstrapTurnId === void 0;
|
|
49834
|
+
const isBootstrapTurnContinuation = record6.bootstrapTurnId !== void 0 && (command.type === "turn.cancel" && command.turnId === record6.bootstrapTurnId || command.type === "interaction.respond");
|
|
48926
49835
|
if (!isBootstrapTurn && !isBootstrapTurnContinuation) {
|
|
48927
49836
|
return {
|
|
48928
49837
|
ok: false,
|
|
@@ -48935,17 +49844,17 @@ async function startHarnessBrokerServer(input) {
|
|
|
48935
49844
|
};
|
|
48936
49845
|
}
|
|
48937
49846
|
if (command.type === "turn.start")
|
|
48938
|
-
|
|
49847
|
+
record6.bootstrapTurnId = command.turnId;
|
|
48939
49848
|
}
|
|
48940
49849
|
let result;
|
|
48941
49850
|
if (command.type === "turn.start")
|
|
48942
|
-
result = await
|
|
49851
|
+
result = await record6.session.execute(command);
|
|
48943
49852
|
else if (command.type === "turn.steer")
|
|
48944
|
-
result = await
|
|
49853
|
+
result = await record6.session.execute(command);
|
|
48945
49854
|
else if (command.type === "turn.cancel")
|
|
48946
|
-
result = await
|
|
49855
|
+
result = await record6.session.execute(command);
|
|
48947
49856
|
else if (command.type === "interaction.respond") {
|
|
48948
|
-
result = await
|
|
49857
|
+
result = await record6.session.execute({
|
|
48949
49858
|
type: command.type,
|
|
48950
49859
|
interactionId: command.interactionId,
|
|
48951
49860
|
response: command.response.type === "question" ? {
|
|
@@ -48955,21 +49864,21 @@ async function startHarnessBrokerServer(input) {
|
|
|
48955
49864
|
} : command.response
|
|
48956
49865
|
});
|
|
48957
49866
|
} else if (command.type === "model.select")
|
|
48958
|
-
result = await
|
|
49867
|
+
result = await record6.session.execute(command);
|
|
48959
49868
|
else if (command.type === "thinking.select")
|
|
48960
|
-
result = await
|
|
49869
|
+
result = await record6.session.execute(command);
|
|
48961
49870
|
else
|
|
48962
|
-
result = await
|
|
48963
|
-
if (!result.ok && command.type === "turn.start" &&
|
|
48964
|
-
delete
|
|
49871
|
+
result = await record6.session.execute(command);
|
|
49872
|
+
if (!result.ok && command.type === "turn.start" && record6.awaitingNativeIdentity && record6.bootstrapTurnId === command.turnId) {
|
|
49873
|
+
delete record6.bootstrapTurnId;
|
|
48965
49874
|
}
|
|
48966
49875
|
if (result.ok) {
|
|
48967
49876
|
if (command.type === "model.select")
|
|
48968
|
-
|
|
49877
|
+
record6.selection.model = command.model;
|
|
48969
49878
|
if (command.type === "thinking.select")
|
|
48970
|
-
|
|
49879
|
+
record6.selection.thinkingOptionId = command.thinkingOptionId;
|
|
48971
49880
|
if (command.type === "permissionMode.select")
|
|
48972
|
-
|
|
49881
|
+
record6.selection.permissionModeId = command.permissionModeId;
|
|
48973
49882
|
}
|
|
48974
49883
|
return result;
|
|
48975
49884
|
}
|
|
@@ -48981,10 +49890,10 @@ async function startHarnessBrokerServer(input) {
|
|
|
48981
49890
|
return requireSession(request.params).session.readSnapshot();
|
|
48982
49891
|
}
|
|
48983
49892
|
if (request.method === "session.refreshUsage") {
|
|
48984
|
-
const
|
|
48985
|
-
const refreshUsage =
|
|
49893
|
+
const record6 = requireSession(request.params);
|
|
49894
|
+
const refreshUsage = record6.session.refreshUsage;
|
|
48986
49895
|
if (refreshUsage)
|
|
48987
|
-
await refreshUsage.call(
|
|
49896
|
+
await refreshUsage.call(record6.session);
|
|
48988
49897
|
return null;
|
|
48989
49898
|
}
|
|
48990
49899
|
if (request.method === "session.commands.list") {
|
|
@@ -49002,11 +49911,11 @@ async function startHarnessBrokerServer(input) {
|
|
|
49002
49911
|
}) : { ok: false, error: harnessError("Commands unavailable", false) };
|
|
49003
49912
|
}
|
|
49004
49913
|
if (request.method === "session.reopen") {
|
|
49005
|
-
const
|
|
49006
|
-
if (!
|
|
49007
|
-
return { ok: true, value: sessionMetadata(
|
|
49914
|
+
const record6 = requireSession(request.params);
|
|
49915
|
+
if (!record6.faulted) {
|
|
49916
|
+
return { ok: true, value: sessionMetadata(record6) };
|
|
49008
49917
|
}
|
|
49009
|
-
if (!
|
|
49918
|
+
if (!record6.nativeRef) {
|
|
49010
49919
|
return {
|
|
49011
49920
|
ok: false,
|
|
49012
49921
|
error: {
|
|
@@ -49017,17 +49926,17 @@ async function startHarnessBrokerServer(input) {
|
|
|
49017
49926
|
}
|
|
49018
49927
|
};
|
|
49019
49928
|
}
|
|
49020
|
-
const nativeRef =
|
|
49021
|
-
const oldSession =
|
|
49022
|
-
const oldOutputTask =
|
|
49023
|
-
|
|
49929
|
+
const nativeRef = record6.nativeRef;
|
|
49930
|
+
const oldSession = record6.session;
|
|
49931
|
+
const oldOutputTask = record6.outputTask;
|
|
49932
|
+
record6.forwarderEpoch += 1;
|
|
49024
49933
|
await oldSession.close().catch(() => void 0);
|
|
49025
49934
|
await oldOutputTask.catch(() => void 0);
|
|
49026
49935
|
const reopened = await input.adapter.open({
|
|
49027
49936
|
kind: "resume",
|
|
49028
|
-
cwd:
|
|
49937
|
+
cwd: record6.cwd,
|
|
49029
49938
|
nativeRef,
|
|
49030
|
-
...
|
|
49939
|
+
...record6.environment ? { environment: record6.environment } : {}
|
|
49031
49940
|
});
|
|
49032
49941
|
if (!reopened.ok)
|
|
49033
49942
|
return reopened;
|
|
@@ -49044,44 +49953,44 @@ async function startHarnessBrokerServer(input) {
|
|
|
49044
49953
|
}
|
|
49045
49954
|
};
|
|
49046
49955
|
}
|
|
49047
|
-
if (
|
|
49956
|
+
if (record6.selection.model && reopened.value.capabilities.configuration.selectModel) {
|
|
49048
49957
|
const selected = await reopened.value.execute({
|
|
49049
49958
|
type: "model.select",
|
|
49050
|
-
model:
|
|
49959
|
+
model: record6.selection.model
|
|
49051
49960
|
});
|
|
49052
49961
|
if (!selected.ok) {
|
|
49053
49962
|
await reopened.value.close().catch(() => void 0);
|
|
49054
49963
|
return selected;
|
|
49055
49964
|
}
|
|
49056
49965
|
}
|
|
49057
|
-
if (
|
|
49966
|
+
if (record6.selection.thinkingOptionId && reopened.value.capabilities.configuration.selectThinkingOption) {
|
|
49058
49967
|
const selected = await reopened.value.execute({
|
|
49059
49968
|
type: "thinking.select",
|
|
49060
|
-
thinkingOptionId:
|
|
49969
|
+
thinkingOptionId: record6.selection.thinkingOptionId
|
|
49061
49970
|
});
|
|
49062
49971
|
if (!selected.ok) {
|
|
49063
49972
|
await reopened.value.close().catch(() => void 0);
|
|
49064
49973
|
return selected;
|
|
49065
49974
|
}
|
|
49066
49975
|
}
|
|
49067
|
-
if (
|
|
49976
|
+
if (record6.selection.permissionModeId && reopened.value.capabilities.configuration.selectPermissionMode) {
|
|
49068
49977
|
const selected = await reopened.value.execute({
|
|
49069
49978
|
type: "permissionMode.select",
|
|
49070
|
-
permissionModeId:
|
|
49979
|
+
permissionModeId: record6.selection.permissionModeId
|
|
49071
49980
|
});
|
|
49072
49981
|
if (!selected.ok) {
|
|
49073
49982
|
await reopened.value.close().catch(() => void 0);
|
|
49074
49983
|
return selected;
|
|
49075
49984
|
}
|
|
49076
49985
|
}
|
|
49077
|
-
|
|
49078
|
-
|
|
49079
|
-
|
|
49080
|
-
|
|
49081
|
-
return { ok: true, value: sessionMetadata(
|
|
49986
|
+
record6.session = reopened.value;
|
|
49987
|
+
record6.generation += 1;
|
|
49988
|
+
record6.faulted = false;
|
|
49989
|
+
record6.outputTask = forwardOutputs(record6, reopened.value, record6.generation, record6.forwarderEpoch);
|
|
49990
|
+
return { ok: true, value: sessionMetadata(record6) };
|
|
49082
49991
|
}
|
|
49083
|
-
const
|
|
49084
|
-
await closeRecord(
|
|
49992
|
+
const record5 = requireSession(request.params);
|
|
49993
|
+
await closeRecord(record5);
|
|
49085
49994
|
return null;
|
|
49086
49995
|
};
|
|
49087
49996
|
consumeBrokerFrames(socket, (raw) => {
|
|
@@ -49103,7 +50012,7 @@ async function startHarnessBrokerServer(input) {
|
|
|
49103
50012
|
}
|
|
49104
50013
|
state.authenticated = true;
|
|
49105
50014
|
state.inputSequence = 1;
|
|
49106
|
-
await send({ kind: "response", id:
|
|
50015
|
+
await send({ kind: "response", id: randomUUID25(), ok: true, value: { ready: true } });
|
|
49107
50016
|
return;
|
|
49108
50017
|
}
|
|
49109
50018
|
const parsed2 = harnessBrokerRequestSchema.safeParse(raw);
|
|
@@ -49143,9 +50052,9 @@ async function startHarnessBrokerServer(input) {
|
|
|
49143
50052
|
state.closed = true;
|
|
49144
50053
|
connections.delete(state);
|
|
49145
50054
|
for (const sessionId of [...state.sessions]) {
|
|
49146
|
-
const
|
|
49147
|
-
if (
|
|
49148
|
-
void closeRecord(
|
|
50055
|
+
const record5 = sessions.get(sessionId);
|
|
50056
|
+
if (record5)
|
|
50057
|
+
void closeRecord(record5);
|
|
49149
50058
|
}
|
|
49150
50059
|
scheduleIdle();
|
|
49151
50060
|
});
|
|
@@ -49177,10 +50086,10 @@ async function startHarnessBrokerServer(input) {
|
|
|
49177
50086
|
clearTimeout(idleTimer);
|
|
49178
50087
|
for (const connection of connections)
|
|
49179
50088
|
connection.socket.destroy();
|
|
49180
|
-
for (const
|
|
49181
|
-
|
|
49182
|
-
await Promise.all([...sessions.values()].map((
|
|
49183
|
-
await Promise.all([...sessions.values()].map((
|
|
50089
|
+
for (const record5 of sessions.values())
|
|
50090
|
+
record5.forwarderEpoch += 1;
|
|
50091
|
+
await Promise.all([...sessions.values()].map((record5) => record5.session.close().catch(() => void 0)));
|
|
50092
|
+
await Promise.all([...sessions.values()].map((record5) => record5.outputTask.catch(() => void 0)));
|
|
49184
50093
|
await input.adapter.close().catch(() => void 0);
|
|
49185
50094
|
await new Promise((resolve) => server.close(() => resolve()));
|
|
49186
50095
|
if (process.platform !== "win32")
|