@karlorz/codexhost-cli-linux-x64 0.13.3-7 → 0.14.0-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 +55 -4
- package/app/console-web.js +344 -54
- package/app/cpa-live-voice-hook.js +731 -112
- package/app/desktop-controller.mjs +140 -40
- package/app/host-runtime.mjs +1081 -334
- package/app/plugins/antigravity/plugin.mjs +88 -12
- package/app/plugins/claude-code/plugin.mjs +397 -21
- package/app/plugins/codebuddy/plugin.mjs +107 -17
- package/app/plugins/codex-usage/plugin.mjs +67 -7
- package/app/plugins/copilot/assets/icon.png +0 -0
- package/app/plugins/copilot/manifest.json +26 -0
- package/app/plugins/copilot/plugin.mjs +34645 -0
- package/app/plugins/cursor-cli/plugin.mjs +88 -6
- package/app/plugins/deepseek-harness/plugin.mjs +73 -6
- package/app/plugins/enabled.json +1 -0
- package/app/plugins/grok/plugin.mjs +272 -60
- package/app/plugins/hermes/plugin.mjs +70 -4
- package/app/plugins/kimi-code/plugin.mjs +73 -6
- package/app/plugins/kiro-cli/plugin.mjs +73 -6
- package/app/plugins/omp/plugin.mjs +73 -112
- package/app/plugins/opencode/plugin.mjs +75 -6
- package/app/plugins/pi/plugin.mjs +204 -44
- package/app/plugins/qoder/plugin.mjs +73 -6
- package/app/plugins/qoder-cn/plugin.mjs +73 -6
- package/app/plugins/workbuddy/plugin.mjs +368 -41
- package/app/plugins/zcode/plugin.mjs +74 -6
- package/app/renderer-extension.js +1569 -314
- package/bin/codexhost +0 -0
- package/libexec/codexhost-shim +0 -0
- package/libexec/codexhost-updater +0 -0
- package/package.json +1 -1
package/app/host-runtime.mjs
CHANGED
|
@@ -6155,9 +6155,9 @@ function floatSafeRemainder(val, step) {
|
|
|
6155
6155
|
return ratio - roundedRatio;
|
|
6156
6156
|
}
|
|
6157
6157
|
var EVALUATING = /* @__PURE__ */ Symbol("evaluating");
|
|
6158
|
-
function defineLazy(
|
|
6158
|
+
function defineLazy(object10, key, getter) {
|
|
6159
6159
|
let value2 = void 0;
|
|
6160
|
-
Object.defineProperty(
|
|
6160
|
+
Object.defineProperty(object10, key, {
|
|
6161
6161
|
get() {
|
|
6162
6162
|
if (value2 === EVALUATING) {
|
|
6163
6163
|
return void 0;
|
|
@@ -6169,7 +6169,7 @@ function defineLazy(object9, key, getter) {
|
|
|
6169
6169
|
return value2;
|
|
6170
6170
|
},
|
|
6171
6171
|
set(v) {
|
|
6172
|
-
Object.defineProperty(
|
|
6172
|
+
Object.defineProperty(object10, key, {
|
|
6173
6173
|
value: v
|
|
6174
6174
|
// configurable: true,
|
|
6175
6175
|
});
|
|
@@ -20094,10 +20094,19 @@ var model = external_exports.string().min(1).max(512);
|
|
|
20094
20094
|
var project = external_exports.string().min(1).max(4096);
|
|
20095
20095
|
var usageStatisticsParamsSchema = external_exports.strictObject({
|
|
20096
20096
|
range: external_exports.enum(USAGE_STATISTICS_RANGES),
|
|
20097
|
+
/** Display timezone for ranges, dates and hourly buckets; omitted means the Host's local zone. */
|
|
20098
|
+
timeZone: external_exports.string().min(1).max(128).refine((value2) => {
|
|
20099
|
+
try {
|
|
20100
|
+
new Intl.DateTimeFormat("en", { timeZone: value2 });
|
|
20101
|
+
return true;
|
|
20102
|
+
} catch {
|
|
20103
|
+
return false;
|
|
20104
|
+
}
|
|
20105
|
+
}, "Unsupported usage statistics timezone").optional(),
|
|
20097
20106
|
harness: harness.optional(),
|
|
20098
20107
|
model: model.nullable().optional(),
|
|
20099
20108
|
project: project.nullable().optional(),
|
|
20100
|
-
/** One
|
|
20109
|
+
/** One date in the query timezone inside the range. */
|
|
20101
20110
|
date: localDate.optional()
|
|
20102
20111
|
});
|
|
20103
20112
|
var usageStatisticsTotalsSchema = external_exports.strictObject({
|
|
@@ -20133,7 +20142,7 @@ var usageStatisticsSessionSchema = external_exports.strictObject({
|
|
|
20133
20142
|
});
|
|
20134
20143
|
var usageStatisticsResultSchema = external_exports.strictObject({
|
|
20135
20144
|
range: external_exports.enum(USAGE_STATISTICS_RANGES),
|
|
20136
|
-
/** First
|
|
20145
|
+
/** First date in the query timezone (Host local when omitted); null for all time. */
|
|
20137
20146
|
from: localDate.nullable(),
|
|
20138
20147
|
to: localDate,
|
|
20139
20148
|
/** The filters these figures apply, echoed so a late answer to older filters is recognised. */
|
|
@@ -20173,7 +20182,7 @@ var usageStatisticsResultSchema = external_exports.strictObject({
|
|
|
20173
20182
|
totals: usageStatisticsTotalsSchema,
|
|
20174
20183
|
/** Each date and Harness of the range: every filter except the day. */
|
|
20175
20184
|
daily: external_exports.array(external_exports.strictObject({ date: localDate, harness, ...totals })).max(2e5),
|
|
20176
|
-
/**
|
|
20185
|
+
/** Weekday (0 = Sunday) and hour in the query timezone, all filters applied. */
|
|
20177
20186
|
hourly: external_exports.array(external_exports.strictObject({
|
|
20178
20187
|
weekday: external_exports.number().int().min(0).max(6),
|
|
20179
20188
|
hour: external_exports.number().int().min(0).max(23),
|
|
@@ -20286,6 +20295,8 @@ var CONSOLE_HOST_METHODS = Object.freeze([
|
|
|
20286
20295
|
"codexhost/harness/display-settings/set",
|
|
20287
20296
|
"codexhost/harness/inspect",
|
|
20288
20297
|
"codexhost/harness/installation",
|
|
20298
|
+
"codexhost/harness/installation/start",
|
|
20299
|
+
"codexhost/harness/installation/status",
|
|
20289
20300
|
"codexhost/harness/launch-settings/get",
|
|
20290
20301
|
"codexhost/harness/launch-settings/set",
|
|
20291
20302
|
"codexhost/harness/grok-computer-use/get",
|
|
@@ -20369,7 +20380,18 @@ var threadManualCompactionStartedSchema = external_exports.strictObject({
|
|
|
20369
20380
|
var nonNegativeSafeIntegerSchema = external_exports.number().int().safe().nonnegative();
|
|
20370
20381
|
var finiteNonNegativeNumberSchema = external_exports.number().finite().nonnegative();
|
|
20371
20382
|
var cacheHitRatePercentSchema = external_exports.number().finite().min(0).max(100);
|
|
20383
|
+
var indicatorTextSchema = (maximum) => harnessLocalizedTextSchema.refine((entries) => Object.values(entries).every((text) => text.length <= maximum));
|
|
20384
|
+
var composerIndicatorsSchema = external_exports.array(external_exports.object({
|
|
20385
|
+
kind: external_exports.literal("countdown"),
|
|
20386
|
+
id: external_exports.string().min(1).max(64),
|
|
20387
|
+
expiresAtUnix: nonNegativeSafeIntegerSchema,
|
|
20388
|
+
label: indicatorTextSchema(256).optional(),
|
|
20389
|
+
tooltip: indicatorTextSchema(1024).optional()
|
|
20390
|
+
}).strict()).max(2).refine((entries) => new Set(entries.map(({ id: id2 }) => id2)).size === entries.length, {
|
|
20391
|
+
message: "Composer indicator IDs must be unique"
|
|
20392
|
+
});
|
|
20372
20393
|
var threadUsageSnapshotSchema = external_exports.object({
|
|
20394
|
+
composerIndicators: composerIndicatorsSchema.optional(),
|
|
20373
20395
|
inputTokens: nonNegativeSafeIntegerSchema.optional(),
|
|
20374
20396
|
cachedInputTokens: nonNegativeSafeIntegerSchema.optional(),
|
|
20375
20397
|
cacheWriteInputTokens: nonNegativeSafeIntegerSchema.optional(),
|
|
@@ -20785,7 +20807,9 @@ var harnessSessionCapabilitiesSchema = external_exports.object({
|
|
|
20785
20807
|
}).strict().optional(),
|
|
20786
20808
|
autonomousTurns: external_exports.object({
|
|
20787
20809
|
observe: external_exports.boolean()
|
|
20788
|
-
}).strict().optional()
|
|
20810
|
+
}).strict().optional(),
|
|
20811
|
+
/** True only when `turn.steer` delivers input into the active Turn through a native primitive. */
|
|
20812
|
+
steer: external_exports.boolean().optional()
|
|
20789
20813
|
}).strict();
|
|
20790
20814
|
var harnessConfigurationStateSchema = external_exports.object({
|
|
20791
20815
|
effectiveModel: harnessModelRefSchema.optional(),
|
|
@@ -20918,6 +20942,16 @@ var threadOwnershipListResultSchema = external_exports.object({
|
|
|
20918
20942
|
seen.add(thread.threadId);
|
|
20919
20943
|
}
|
|
20920
20944
|
});
|
|
20945
|
+
var threadSteeringInspectParamsSchema = external_exports.object({
|
|
20946
|
+
threadId: hostThreadIdSchema,
|
|
20947
|
+
/** The text about to be steered; a Harness command always stops and restarts. */
|
|
20948
|
+
text: external_exports.string().optional()
|
|
20949
|
+
}).strict();
|
|
20950
|
+
var THREAD_STEER_DELIVERY_PARAM = "codexhostSteerDelivery";
|
|
20951
|
+
var threadSteerDeliverySchema = external_exports.enum(["activeTurn", "newTurn"]);
|
|
20952
|
+
var threadSteeringInspectResultSchema = external_exports.object({
|
|
20953
|
+
delivery: external_exports.enum(["official", "activeTurn", "newTurn"])
|
|
20954
|
+
}).strict();
|
|
20921
20955
|
|
|
20922
20956
|
// packages/shared-contracts/dist/harness-plugins.js
|
|
20923
20957
|
var HARNESS_PLUGIN_API_VERSION = 1;
|
|
@@ -21060,6 +21094,8 @@ var grokComputerUseSettingsSchema = external_exports.object({
|
|
|
21060
21094
|
|
|
21061
21095
|
// packages/shared-contracts/dist/harness-installation.js
|
|
21062
21096
|
var HARNESS_INSTALLATION_METHOD = "codexhost/harness/installation";
|
|
21097
|
+
var HARNESS_INSTALLATION_START_METHOD = "codexhost/harness/installation/start";
|
|
21098
|
+
var HARNESS_INSTALLATION_STATUS_METHOD = "codexhost/harness/installation/status";
|
|
21063
21099
|
var harnessInstallationParamsSchema = external_exports.object({
|
|
21064
21100
|
harnessId: harnessIdSchema,
|
|
21065
21101
|
action: external_exports.enum(["check", "update", "install"])
|
|
@@ -21069,6 +21105,10 @@ var harnessInstallationStateSchema = external_exports.object({
|
|
|
21069
21105
|
latestVersion: external_exports.string().min(1).max(128),
|
|
21070
21106
|
updateAvailable: external_exports.boolean(),
|
|
21071
21107
|
canUpdate: external_exports.boolean(),
|
|
21108
|
+
/** Defaults to CLI; some Harnesses ship only inside a desktop application. */
|
|
21109
|
+
versionKind: external_exports.enum(["cli", "application"]).optional(),
|
|
21110
|
+
/** Official download opened by the user; does not imply an automatic installation. */
|
|
21111
|
+
manualUpdateUrl: external_exports.url().max(2048).refine((value2) => /^https:\/\/[^/?#@]+(?:[/?#]|$)/iu.test(value2), "Manual updates require a credential-free HTTPS URL").optional(),
|
|
21072
21112
|
// Adapter-owned diagnostic text; UI uses messageCode rather than displaying it verbatim.
|
|
21073
21113
|
message: external_exports.string().max(2048).optional(),
|
|
21074
21114
|
messageCode: external_exports.string().min(1).max(128).optional(),
|
|
@@ -21076,6 +21116,20 @@ var harnessInstallationStateSchema = external_exports.object({
|
|
|
21076
21116
|
notice: harnessLocalizedTextSchema.optional(),
|
|
21077
21117
|
latestVersionKind: external_exports.enum(["unknown", "tracking-branch"]).optional()
|
|
21078
21118
|
}).strict();
|
|
21119
|
+
var harnessInstallationTaskParamsSchema = external_exports.object({ taskId: external_exports.string().uuid() }).strict();
|
|
21120
|
+
var harnessInstallationTaskSchema = external_exports.discriminatedUnion("status", [
|
|
21121
|
+
external_exports.object({ taskId: external_exports.string().uuid(), status: external_exports.literal("running") }).strict(),
|
|
21122
|
+
external_exports.object({
|
|
21123
|
+
taskId: external_exports.string().uuid(),
|
|
21124
|
+
status: external_exports.literal("succeeded"),
|
|
21125
|
+
result: harnessInstallationStateSchema
|
|
21126
|
+
}).strict(),
|
|
21127
|
+
external_exports.object({
|
|
21128
|
+
taskId: external_exports.string().uuid(),
|
|
21129
|
+
status: external_exports.literal("failed"),
|
|
21130
|
+
error: external_exports.object({ code: external_exports.number().int(), message: external_exports.string().min(1).max(2048) }).strict()
|
|
21131
|
+
}).strict()
|
|
21132
|
+
]);
|
|
21079
21133
|
|
|
21080
21134
|
// packages/shared-contracts/dist/codex-accounts.js
|
|
21081
21135
|
var accountIdSchema = external_exports.string().min(1).max(256).regex(/^[A-Za-z0-9._~-]+$/u);
|
|
@@ -23260,7 +23314,7 @@ function retainRendererHostResponses(client, hostId2, target) {
|
|
|
23260
23314
|
if (typeof client.addRequestLifecycleListener !== "function" || typeof target.addEventListener !== "function" || typeof target.removeEventListener !== "function")
|
|
23261
23315
|
return () => {
|
|
23262
23316
|
};
|
|
23263
|
-
const
|
|
23317
|
+
const isRecord22 = (value2) => typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
|
|
23264
23318
|
const pending = /* @__PURE__ */ new Set();
|
|
23265
23319
|
let retired = false;
|
|
23266
23320
|
let unsubscribe = () => {
|
|
@@ -23276,15 +23330,15 @@ function retainRendererHostResponses(client, hostId2, target) {
|
|
|
23276
23330
|
const ownOrigin = target.location?.origin;
|
|
23277
23331
|
if (source === target && ownOrigin && ownOrigin !== "null" && origin !== ownOrigin)
|
|
23278
23332
|
return;
|
|
23279
|
-
if (!
|
|
23333
|
+
if (!isRecord22(data) || data.type !== "mcp-response" || data.hostId !== hostId2)
|
|
23280
23334
|
return;
|
|
23281
23335
|
const message2 = data.message;
|
|
23282
|
-
if (!
|
|
23336
|
+
if (!isRecord22(message2))
|
|
23283
23337
|
return;
|
|
23284
23338
|
const id2 = message2.id;
|
|
23285
23339
|
if (typeof id2 !== "string" && typeof id2 !== "number" || !pending.has(id2))
|
|
23286
23340
|
return;
|
|
23287
|
-
const hasError =
|
|
23341
|
+
const hasError = isRecord22(message2.error);
|
|
23288
23342
|
if (!hasError && !Object.prototype.hasOwnProperty.call(message2, "result"))
|
|
23289
23343
|
return;
|
|
23290
23344
|
queueMicrotask(() => {
|
|
@@ -23298,7 +23352,7 @@ function retainRendererHostResponses(client, hostId2, target) {
|
|
|
23298
23352
|
};
|
|
23299
23353
|
target.addEventListener("message", receive);
|
|
23300
23354
|
unsubscribe = client.addRequestLifecycleListener((event) => {
|
|
23301
|
-
if (!
|
|
23355
|
+
if (!isRecord22(event) || event.hostId !== hostId2)
|
|
23302
23356
|
return;
|
|
23303
23357
|
const id2 = event.id;
|
|
23304
23358
|
if (typeof id2 !== "string" && typeof id2 !== "number")
|
|
@@ -23328,13 +23382,13 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
|
|
|
23328
23382
|
let selectedModel = null;
|
|
23329
23383
|
let prewarmGeneration = 0;
|
|
23330
23384
|
const externalPrewarms = /* @__PURE__ */ new Set();
|
|
23331
|
-
const
|
|
23385
|
+
const isRecord22 = (value2) => typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
|
|
23332
23386
|
const isUnsupportedPosixBridgeSpawn = (value2) => {
|
|
23333
23387
|
const marker = "AbsolutePathBuf deserialized without a base path";
|
|
23334
23388
|
if (typeof value2 === "string") {
|
|
23335
23389
|
return value2.startsWith("Invalid request:") && value2.includes(marker);
|
|
23336
23390
|
}
|
|
23337
|
-
if (!
|
|
23391
|
+
if (!isRecord22(value2))
|
|
23338
23392
|
return false;
|
|
23339
23393
|
if (typeof value2.message === "string" && value2.message.includes(marker)) {
|
|
23340
23394
|
if (value2.code === -32600 || value2.message.startsWith("Invalid request:"))
|
|
@@ -23427,7 +23481,7 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
|
|
|
23427
23481
|
bridgeState = "idle";
|
|
23428
23482
|
};
|
|
23429
23483
|
const rememberExternalThread = (value2) => {
|
|
23430
|
-
if (!
|
|
23484
|
+
if (!isRecord22(value2) || typeof value2.id !== "string")
|
|
23431
23485
|
return;
|
|
23432
23486
|
if (value2.modelProvider === "codexhost" || value2.cliVersion === "codexhost") {
|
|
23433
23487
|
knownExternalThreadIds.add(value2.id);
|
|
@@ -23435,7 +23489,7 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
|
|
|
23435
23489
|
}
|
|
23436
23490
|
};
|
|
23437
23491
|
const observeBridgeResult = (request, result) => {
|
|
23438
|
-
if (!request || !
|
|
23492
|
+
if (!request || !isRecord22(result))
|
|
23439
23493
|
return;
|
|
23440
23494
|
if (request.method === "thread/list" && Array.isArray(result.data)) {
|
|
23441
23495
|
for (const thread of result.data)
|
|
@@ -23446,7 +23500,7 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
|
|
|
23446
23500
|
rememberExternalThread(result.thread);
|
|
23447
23501
|
return;
|
|
23448
23502
|
}
|
|
23449
|
-
if (request.method === "codexhost/thread/inspect" &&
|
|
23503
|
+
if (request.method === "codexhost/thread/inspect" && isRecord22(request.parameters) && typeof request.parameters.threadId === "string") {
|
|
23450
23504
|
if (result.owner === "external") {
|
|
23451
23505
|
knownExternalThreadIds.add(request.parameters.threadId);
|
|
23452
23506
|
knownOfficialThreadIds.delete(request.parameters.threadId);
|
|
@@ -23456,18 +23510,18 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
|
|
|
23456
23510
|
}
|
|
23457
23511
|
return;
|
|
23458
23512
|
}
|
|
23459
|
-
if (request.method === "thread/delete" &&
|
|
23513
|
+
if (request.method === "thread/delete" && isRecord22(request.parameters) && typeof request.parameters.threadId === "string") {
|
|
23460
23514
|
knownExternalThreadIds.delete(request.parameters.threadId);
|
|
23461
23515
|
knownOfficialThreadIds.delete(request.parameters.threadId);
|
|
23462
23516
|
}
|
|
23463
23517
|
};
|
|
23464
23518
|
const handleBridgeFrame = (value2) => {
|
|
23465
|
-
if (!
|
|
23519
|
+
if (!isRecord22(value2)) {
|
|
23466
23520
|
failBridge("received a non-object app-server frame");
|
|
23467
23521
|
return;
|
|
23468
23522
|
}
|
|
23469
23523
|
if (value2.method === bridgeReadyMethod && value2.id === void 0) {
|
|
23470
|
-
if (
|
|
23524
|
+
if (isRecord22(value2.params) && value2.params.protocolVersion === 1) {
|
|
23471
23525
|
bridgeState = "ready";
|
|
23472
23526
|
if (bridgeReadyTimeout !== null)
|
|
23473
23527
|
globalThis.clearTimeout(bridgeReadyTimeout);
|
|
@@ -23481,7 +23535,7 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
|
|
|
23481
23535
|
return;
|
|
23482
23536
|
}
|
|
23483
23537
|
if (typeof value2.method === "string" && value2.id === void 0) {
|
|
23484
|
-
if (value2.method === "thread/started" &&
|
|
23538
|
+
if (value2.method === "thread/started" && isRecord22(value2.params)) {
|
|
23485
23539
|
rememberExternalThread(value2.params.thread);
|
|
23486
23540
|
}
|
|
23487
23541
|
originalOnNotification.call(manager, value2.method, value2.params);
|
|
@@ -23532,13 +23586,13 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
|
|
|
23532
23586
|
}
|
|
23533
23587
|
};
|
|
23534
23588
|
const handleOuterNotification = (method, parameters) => {
|
|
23535
|
-
if (method === "process/exited" &&
|
|
23589
|
+
if (method === "process/exited" && isRecord22(parameters) && parameters.processHandle === bridgeProcessHandle) {
|
|
23536
23590
|
const exitCode = typeof parameters.exitCode === "number" ? parameters.exitCode : "unknown";
|
|
23537
23591
|
const stderr = typeof parameters.stderr === "string" ? parameters.stderr.trim() : "";
|
|
23538
23592
|
failBridge(`process exited unexpectedly with code ${exitCode}${stderr ? `: ${stderr}` : ""}`, false);
|
|
23539
23593
|
return true;
|
|
23540
23594
|
}
|
|
23541
|
-
if (method !== "process/outputDelta" || !
|
|
23595
|
+
if (method !== "process/outputDelta" || !isRecord22(parameters) || parameters.processHandle !== bridgeProcessHandle || parameters.stream !== "stdout" && parameters.stream !== "stderr" || typeof parameters.deltaBase64 !== "string") {
|
|
23542
23596
|
return false;
|
|
23543
23597
|
}
|
|
23544
23598
|
if (parameters.capReached === true) {
|
|
@@ -23642,7 +23696,7 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
|
|
|
23642
23696
|
return bridgeInitialization;
|
|
23643
23697
|
};
|
|
23644
23698
|
const threadIdFromParameters = (parameters) => {
|
|
23645
|
-
if (!
|
|
23699
|
+
if (!isRecord22(parameters))
|
|
23646
23700
|
return null;
|
|
23647
23701
|
const value2 = parameters.threadId ?? parameters.conversationId;
|
|
23648
23702
|
return typeof value2 === "string" ? value2 : null;
|
|
@@ -23659,9 +23713,9 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
|
|
|
23659
23713
|
const resolution = initializeBridge().then(() => enqueueBridgeRequest("codexhost/thread/ownership/list", {
|
|
23660
23714
|
threadIds: [threadId2]
|
|
23661
23715
|
})).then((value2) => {
|
|
23662
|
-
const ownerships =
|
|
23716
|
+
const ownerships = isRecord22(value2) && Array.isArray(value2.threads) ? value2.threads : null;
|
|
23663
23717
|
const ownership = ownerships?.[0];
|
|
23664
|
-
if (!ownerships || !
|
|
23718
|
+
if (!ownerships || !isRecord22(ownership) || ownerships.length !== 1 || ownership.threadId !== threadId2 || ownership.owner !== "external" && ownership.owner !== "codex") {
|
|
23665
23719
|
throw transportError("Thread ownership lookup returned an invalid result");
|
|
23666
23720
|
}
|
|
23667
23721
|
if (ownership.owner === "external") {
|
|
@@ -23700,7 +23754,7 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
|
|
|
23700
23754
|
if (method === "thread/list")
|
|
23701
23755
|
return true;
|
|
23702
23756
|
if (method === "thread/start") {
|
|
23703
|
-
return
|
|
23757
|
+
return isRecord22(parameters) && typeof parameters.model === "string" && parameters.model.startsWith("codexhost/");
|
|
23704
23758
|
}
|
|
23705
23759
|
const threadId2 = threadIdFromParameters(parameters);
|
|
23706
23760
|
if (threadId2 && knownExternalThreadIds.has(threadId2))
|
|
@@ -23710,7 +23764,7 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
|
|
|
23710
23764
|
return selectedModel !== null && (method.startsWith("thread/") || method.startsWith("turn/") || method.startsWith("review/"));
|
|
23711
23765
|
};
|
|
23712
23766
|
const routeThreadStart = (parameters) => {
|
|
23713
|
-
if (!
|
|
23767
|
+
if (!isRecord22(parameters) || parameters.ephemeral === true) {
|
|
23714
23768
|
return parameters;
|
|
23715
23769
|
}
|
|
23716
23770
|
return {
|
|
@@ -23743,12 +23797,12 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
|
|
|
23743
23797
|
return shouldUseBridge(method, routedParameters) ? sendBridged() : sendDirect();
|
|
23744
23798
|
};
|
|
23745
23799
|
const publishDraftWorkspace = (parameters) => {
|
|
23746
|
-
if (!
|
|
23800
|
+
if (!isRecord22(parameters) || parameters.ephemeral === true)
|
|
23747
23801
|
return;
|
|
23748
23802
|
const cwd = parameters.cwd;
|
|
23749
23803
|
if (typeof cwd !== "string" || cwd.length === 0)
|
|
23750
23804
|
return;
|
|
23751
|
-
const drafts =
|
|
23805
|
+
const drafts = isRecord22(target.__codexhostDraftWorkspacesV1) ? target.__codexhostDraftWorkspacesV1 : {};
|
|
23752
23806
|
drafts[hostId2] = cwd;
|
|
23753
23807
|
Object.defineProperty(target, "__codexhostDraftWorkspacesV1", {
|
|
23754
23808
|
configurable: true,
|
|
@@ -23771,16 +23825,16 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
|
|
|
23771
23825
|
};
|
|
23772
23826
|
const routedPrewarm = (parameters, options2) => {
|
|
23773
23827
|
const routed = routeThreadStart(parameters);
|
|
23774
|
-
const external =
|
|
23828
|
+
const external = isRecord22(routed) && routed.ephemeral !== true && typeof routed.model === "string" && routed.model.startsWith("codexhost/");
|
|
23775
23829
|
const routedParameters = external ? { ...routed, codexhostPrewarm: true } : routed;
|
|
23776
23830
|
const generation = prewarmGeneration;
|
|
23777
23831
|
publishDraftWorkspace(routedParameters);
|
|
23778
23832
|
const pending = shouldUseBridge("thread/start", routedParameters) ? routedSend("thread/start", routedParameters, options2) : options2 === void 0 ? originalPrewarm.call(bridge, routedParameters) : originalPrewarm.call(bridge, routedParameters, options2);
|
|
23779
|
-
if (
|
|
23833
|
+
if (isRecord22(parameters) && parameters.ephemeral === true || typeof pending !== "object" && typeof pending !== "function" || pending === null || typeof Reflect.get(pending, "then") !== "function") {
|
|
23780
23834
|
return pending;
|
|
23781
23835
|
}
|
|
23782
23836
|
return Promise.resolve(pending).then((result) => {
|
|
23783
|
-
const threadId2 = external &&
|
|
23837
|
+
const threadId2 = external && isRecord22(result) && isRecord22(result.thread) && typeof result.thread.id === "string" ? result.thread.id : null;
|
|
23784
23838
|
if (disposed || generation !== prewarmGeneration) {
|
|
23785
23839
|
if (threadId2)
|
|
23786
23840
|
discardExternalPrewarm(threadId2);
|
|
@@ -23796,7 +23850,7 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
|
|
|
23796
23850
|
bridge.prewarmThreadStart = routedPrewarm;
|
|
23797
23851
|
const routedWindowMessage = (event) => {
|
|
23798
23852
|
const message2 = event.data;
|
|
23799
|
-
if (!
|
|
23853
|
+
if (!isRecord22(message2) || message2.type !== "mcp-notification" || message2.hostId !== hostId2 || typeof message2.method !== "string") {
|
|
23800
23854
|
return;
|
|
23801
23855
|
}
|
|
23802
23856
|
handleOuterNotification(message2.method, message2.params);
|
|
@@ -23918,9 +23972,13 @@ function requestManagerFromHookState(value2, hostId2) {
|
|
|
23918
23972
|
const direct = manager(value2) ?? manager(value2.manager);
|
|
23919
23973
|
if (direct)
|
|
23920
23974
|
return direct;
|
|
23921
|
-
if (!hostId2 || typeof value2.addManager !== "function" || typeof value2.getForHostId !== "function"
|
|
23975
|
+
if (!hostId2 || typeof value2.addManager !== "function" || typeof value2.getForHostId !== "function")
|
|
23922
23976
|
return null;
|
|
23923
|
-
|
|
23977
|
+
try {
|
|
23978
|
+
return manager(value2.getForHostId(hostId2));
|
|
23979
|
+
} catch {
|
|
23980
|
+
return null;
|
|
23981
|
+
}
|
|
23924
23982
|
}
|
|
23925
23983
|
function discoverRendererHosts(root, ancestors = committedReactAncestors, managerFrom = requestManagerFromHookState) {
|
|
23926
23984
|
const editors = [
|
|
@@ -23956,7 +24014,7 @@ function discoverRendererHosts(root, ancestors = committedReactAncestors, manage
|
|
|
23956
24014
|
const manager = managerFrom(value2);
|
|
23957
24015
|
if (manager)
|
|
23958
24016
|
managers.add(manager);
|
|
23959
|
-
if (value2 && typeof value2 === "object" && "addManager" in value2 && typeof value2.addManager === "function" && "getForHostId" in value2 && typeof value2.getForHostId === "function"
|
|
24017
|
+
if (value2 && typeof value2 === "object" && "addManager" in value2 && typeof value2.addManager === "function" && "getForHostId" in value2 && typeof value2.getForHostId === "function") {
|
|
23960
24018
|
registries.add(value2);
|
|
23961
24019
|
}
|
|
23962
24020
|
hook = hook.next && typeof hook.next === "object" ? hook.next : null;
|
|
@@ -23972,7 +24030,13 @@ function discoverRendererHosts(root, ancestors = committedReactAncestors, manage
|
|
|
23972
24030
|
function resolveRendererHostManager(discovery, hostId2, managerFrom = requestManagerFromHookState) {
|
|
23973
24031
|
if (!hostId2)
|
|
23974
24032
|
return null;
|
|
23975
|
-
const candidates = discovery.registries.length ? discovery.registries.
|
|
24033
|
+
const candidates = discovery.registries.length ? discovery.registries.flatMap((registry2) => {
|
|
24034
|
+
try {
|
|
24035
|
+
return [managerFrom(registry2.getForHostId(hostId2))];
|
|
24036
|
+
} catch {
|
|
24037
|
+
return [];
|
|
24038
|
+
}
|
|
24039
|
+
}) : discovery.managers;
|
|
23976
24040
|
const matching = new Set(candidates.filter((manager) => manager && (manager.getHostId?.() ?? manager.requestClient.hostId) === hostId2 && (manager.requestClient.hostId === void 0 || manager.requestClient.hostId === hostId2)));
|
|
23977
24041
|
return matching.size === 1 ? matching.values().next().value ?? null : null;
|
|
23978
24042
|
}
|
|
@@ -25091,6 +25155,36 @@ var ExternalVoice = class {
|
|
|
25091
25155
|
}
|
|
25092
25156
|
};
|
|
25093
25157
|
|
|
25158
|
+
// packages/host-runtime/src/external-voice-presentation.ts
|
|
25159
|
+
var INLINE_MARKDOWN = "::codex-realtime-inline{}\n";
|
|
25160
|
+
var inlineMarker = /^::codex-realtime-inline\{\}\r?\n/u;
|
|
25161
|
+
function externalVoiceContentText(text) {
|
|
25162
|
+
return text.replace(inlineMarker, "");
|
|
25163
|
+
}
|
|
25164
|
+
function object5(value2) {
|
|
25165
|
+
return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
|
|
25166
|
+
}
|
|
25167
|
+
function presentItem(item) {
|
|
25168
|
+
if (!object5(item) || item.type !== "agentMessage" || typeof item.text !== "string") return item;
|
|
25169
|
+
if (!item.text.trim() || inlineMarker.test(item.text)) return item;
|
|
25170
|
+
return { ...item, text: INLINE_MARKDOWN + item.text };
|
|
25171
|
+
}
|
|
25172
|
+
function presentExternalVoiceTurn(turn) {
|
|
25173
|
+
if (!Array.isArray(turn.items)) return turn;
|
|
25174
|
+
return { ...turn, items: turn.items.map(presentItem) };
|
|
25175
|
+
}
|
|
25176
|
+
function presentExternalVoiceMessage(message2) {
|
|
25177
|
+
const params = message2.params;
|
|
25178
|
+
if (!object5(params)) return message2;
|
|
25179
|
+
if ((message2.method === "item/started" || message2.method === "item/completed") && params.item) {
|
|
25180
|
+
return { ...message2, params: { ...params, item: presentItem(params.item) } };
|
|
25181
|
+
}
|
|
25182
|
+
if ((message2.method === "turn/started" || message2.method === "turn/completed") && object5(params.turn)) {
|
|
25183
|
+
return { ...message2, params: { ...params, turn: presentExternalVoiceTurn(params.turn) } };
|
|
25184
|
+
}
|
|
25185
|
+
return message2;
|
|
25186
|
+
}
|
|
25187
|
+
|
|
25094
25188
|
// packages/host-runtime/src/external-voice-session-input.ts
|
|
25095
25189
|
var MAX_MESSAGES = 32;
|
|
25096
25190
|
var MAX_MESSAGE_CHARS = 2e3;
|
|
@@ -25129,7 +25223,7 @@ function voiceSessionInputFromTurns(turns) {
|
|
|
25129
25223
|
const text = userMessageText(item);
|
|
25130
25224
|
if (text) messages.push(liveMessage("user", text));
|
|
25131
25225
|
} else if (item.type === "agentMessage" && item.phase !== "commentary") {
|
|
25132
|
-
const text = typeof item.text === "string" ? item.text.trim() : "";
|
|
25226
|
+
const text = typeof item.text === "string" ? externalVoiceContentText(item.text).trim() : "";
|
|
25133
25227
|
if (text) messages.push(liveMessage("assistant", text));
|
|
25134
25228
|
}
|
|
25135
25229
|
}
|
|
@@ -25159,7 +25253,7 @@ function speakableFromProjectedTurn(turn) {
|
|
|
25159
25253
|
function speakableFromItems(items) {
|
|
25160
25254
|
const values = [...items];
|
|
25161
25255
|
const finals = values.filter((item) => item.phase === "final_answer");
|
|
25162
|
-
const text = (finals.length ? finals : values.filter((item) => item.phase !== "commentary").slice(-1)).map((item) => item.text).join("\n").trim();
|
|
25256
|
+
const text = (finals.length ? finals : values.filter((item) => item.phase !== "commentary").slice(-1)).map((item) => externalVoiceContentText(item.text)).join("\n").trim();
|
|
25163
25257
|
return text.length > 0 ? text : void 0;
|
|
25164
25258
|
}
|
|
25165
25259
|
var ExternalVoiceResults = class {
|
|
@@ -25259,7 +25353,7 @@ var import_websocket_server = __toESM(require_websocket_server(), 1);
|
|
|
25259
25353
|
var wrapper_default = import_websocket.default;
|
|
25260
25354
|
|
|
25261
25355
|
// packages/host-runtime/src/external-voice-gateway.ts
|
|
25262
|
-
function
|
|
25356
|
+
function object6(value2) {
|
|
25263
25357
|
return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
|
|
25264
25358
|
}
|
|
25265
25359
|
function configuredExternalVoiceGateway(environment) {
|
|
@@ -25342,7 +25436,7 @@ function configuredExternalVoiceGateway(environment) {
|
|
|
25342
25436
|
if (closed || input.signal.aborted) return;
|
|
25343
25437
|
try {
|
|
25344
25438
|
const event = JSON.parse(String(raw));
|
|
25345
|
-
if (
|
|
25439
|
+
if (object6(event) && typeof event.type === "string")
|
|
25346
25440
|
input.onEvent(event);
|
|
25347
25441
|
} catch {
|
|
25348
25442
|
input.onError();
|
|
@@ -25962,6 +26056,64 @@ async function handleHarnessInstallation(params, adapters) {
|
|
|
25962
26056
|
}
|
|
25963
26057
|
}
|
|
25964
26058
|
|
|
26059
|
+
// packages/host-runtime/src/harness-installation-tasks.ts
|
|
26060
|
+
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
26061
|
+
var HarnessInstallationTasks = class {
|
|
26062
|
+
#tasks = /* @__PURE__ */ new Map();
|
|
26063
|
+
#active = /* @__PURE__ */ new Map();
|
|
26064
|
+
#prune() {
|
|
26065
|
+
const cutoff = Date.now() - 15 * 6e4;
|
|
26066
|
+
for (const [id2, task] of this.#tasks) {
|
|
26067
|
+
if (task.finishedAt !== void 0 && task.finishedAt < cutoff) this.#tasks.delete(id2);
|
|
26068
|
+
}
|
|
26069
|
+
}
|
|
26070
|
+
start(params, adapters) {
|
|
26071
|
+
const parsed2 = harnessInstallationParamsSchema.safeParse(params);
|
|
26072
|
+
if (!parsed2.success)
|
|
26073
|
+
throw new HarnessInstallationError(-32602, "Invalid Harness installation request");
|
|
26074
|
+
this.#prune();
|
|
26075
|
+
const key = JSON.stringify([parsed2.data.harnessId, parsed2.data.action]);
|
|
26076
|
+
const activeId = this.#active.get(key);
|
|
26077
|
+
const active = activeId ? this.#tasks.get(activeId) : void 0;
|
|
26078
|
+
if (active) return active.state;
|
|
26079
|
+
const taskId = randomUUID5();
|
|
26080
|
+
const task = {
|
|
26081
|
+
state: { taskId, status: "running" }
|
|
26082
|
+
};
|
|
26083
|
+
this.#tasks.set(taskId, task);
|
|
26084
|
+
this.#active.set(key, taskId);
|
|
26085
|
+
void handleHarnessInstallation(parsed2.data, adapters).then(
|
|
26086
|
+
(result) => {
|
|
26087
|
+
task.state = { taskId, status: "succeeded", result };
|
|
26088
|
+
},
|
|
26089
|
+
(error51) => {
|
|
26090
|
+
task.state = {
|
|
26091
|
+
taskId,
|
|
26092
|
+
status: "failed",
|
|
26093
|
+
error: error51 instanceof HarnessInstallationError ? { code: error51.code, message: error51.message } : { code: -32077, message: "Harness version management failed" }
|
|
26094
|
+
};
|
|
26095
|
+
}
|
|
26096
|
+
).finally(() => {
|
|
26097
|
+
task.finishedAt = Date.now();
|
|
26098
|
+
this.#active.delete(key);
|
|
26099
|
+
});
|
|
26100
|
+
return task.state;
|
|
26101
|
+
}
|
|
26102
|
+
status(params) {
|
|
26103
|
+
const parsed2 = harnessInstallationTaskParamsSchema.safeParse(params);
|
|
26104
|
+
if (!parsed2.success)
|
|
26105
|
+
throw new HarnessInstallationError(-32602, "Invalid Harness installation task request");
|
|
26106
|
+
this.#prune();
|
|
26107
|
+
const task = this.#tasks.get(parsed2.data.taskId);
|
|
26108
|
+
if (!task)
|
|
26109
|
+
throw new HarnessInstallationError(
|
|
26110
|
+
-32079,
|
|
26111
|
+
"Harness installation task is unavailable on this Host"
|
|
26112
|
+
);
|
|
26113
|
+
return task.state;
|
|
26114
|
+
}
|
|
26115
|
+
};
|
|
26116
|
+
|
|
25965
26117
|
// packages/host-runtime/src/account/codex-credential-export.ts
|
|
25966
26118
|
import { createHash as createHash3 } from "node:crypto";
|
|
25967
26119
|
import { readFile as readFile10 } from "node:fs/promises";
|
|
@@ -26054,7 +26206,7 @@ async function listOthers(adapter) {
|
|
|
26054
26206
|
}
|
|
26055
26207
|
|
|
26056
26208
|
// packages/host-runtime/src/harness-display-settings.ts
|
|
26057
|
-
import { randomUUID as
|
|
26209
|
+
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
26058
26210
|
import { link, mkdir as mkdir8, readFile as readFile11, rename as rename5, rm as rm7, writeFile as writeFile7 } from "node:fs/promises";
|
|
26059
26211
|
import os5 from "node:os";
|
|
26060
26212
|
import path16 from "node:path";
|
|
@@ -26079,7 +26231,7 @@ var HarnessDisplaySettingsStore = class {
|
|
|
26079
26231
|
async set(input) {
|
|
26080
26232
|
const entries = harnessDisplayEntriesSchema.parse(input.entries);
|
|
26081
26233
|
await mkdir8(path16.dirname(this.#file), { recursive: true, mode: 448 });
|
|
26082
|
-
const temporary = `${this.#file}.${
|
|
26234
|
+
const temporary = `${this.#file}.${randomUUID6()}.tmp`;
|
|
26083
26235
|
try {
|
|
26084
26236
|
await writeFile7(temporary, `${JSON.stringify(entries)}
|
|
26085
26237
|
`, { mode: 384, flag: "wx" });
|
|
@@ -26100,7 +26252,7 @@ var HarnessDisplaySettingsStore = class {
|
|
|
26100
26252
|
};
|
|
26101
26253
|
|
|
26102
26254
|
// packages/host-runtime/src/model-price-overrides-file.ts
|
|
26103
|
-
import { randomUUID as
|
|
26255
|
+
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
26104
26256
|
import { mkdir as mkdir10, readFile as readFile13, rename as rename7, rm as rm8, writeFile as writeFile9 } from "node:fs/promises";
|
|
26105
26257
|
import path18 from "node:path";
|
|
26106
26258
|
|
|
@@ -26675,7 +26827,7 @@ async function updateModelPriceOverridesFile(file2, change) {
|
|
|
26675
26827
|
const updated = { ...document, models: next };
|
|
26676
26828
|
parseModelPriceOverrides(updated);
|
|
26677
26829
|
await mkdir10(path18.dirname(file2), { recursive: true });
|
|
26678
|
-
const temporary = `${file2}.${
|
|
26830
|
+
const temporary = `${file2}.${randomUUID7()}.tmp`;
|
|
26679
26831
|
try {
|
|
26680
26832
|
await writeFile9(temporary, `${JSON.stringify(updated, null, 2)}
|
|
26681
26833
|
`, { flag: "wx" });
|
|
@@ -26711,7 +26863,7 @@ async function handleModelPriceOverridesRequest(catalog, method, params) {
|
|
|
26711
26863
|
}
|
|
26712
26864
|
|
|
26713
26865
|
// packages/host-runtime/src/delegation-skill.ts
|
|
26714
|
-
import { createHash as createHash4, randomUUID as
|
|
26866
|
+
import { createHash as createHash4, randomUUID as randomUUID8 } from "node:crypto";
|
|
26715
26867
|
import { mkdir as mkdir11, open as open4, readFile as readFile14, rename as rename8, rm as rm9, stat as stat5 } from "node:fs/promises";
|
|
26716
26868
|
import os7 from "node:os";
|
|
26717
26869
|
import path19 from "node:path";
|
|
@@ -26811,7 +26963,7 @@ async function readOptional(filePath) {
|
|
|
26811
26963
|
}
|
|
26812
26964
|
async function atomicWrite(filePath, content) {
|
|
26813
26965
|
await mkdir11(path19.dirname(filePath), { recursive: true, mode: 448 });
|
|
26814
|
-
const temporaryPath = path19.join(path19.dirname(filePath), `.SKILL.md.${
|
|
26966
|
+
const temporaryPath = path19.join(path19.dirname(filePath), `.SKILL.md.${randomUUID8()}.tmp`);
|
|
26815
26967
|
const handle = await open4(temporaryPath, "wx", 384);
|
|
26816
26968
|
try {
|
|
26817
26969
|
await handle.writeFile(content, "utf8");
|
|
@@ -27048,6 +27200,7 @@ var usageFields = /* @__PURE__ */ new Set([
|
|
|
27048
27200
|
...safeIntegerFields,
|
|
27049
27201
|
...percentFields,
|
|
27050
27202
|
"sessionCacheUsage",
|
|
27203
|
+
"composerIndicators",
|
|
27051
27204
|
"totalCostUsd",
|
|
27052
27205
|
"totalCredits",
|
|
27053
27206
|
"contextUsagePercent",
|
|
@@ -27070,6 +27223,7 @@ function parseHostUsage(value2) {
|
|
|
27070
27223
|
throw new Error(`Harness Usage contains unknown field '${key}'`);
|
|
27071
27224
|
}
|
|
27072
27225
|
}
|
|
27226
|
+
const indicators = value2.composerIndicators === void 0 ? {} : { composerIndicators: composerIndicatorsSchema.parse(value2.composerIndicators) };
|
|
27073
27227
|
for (const field of [
|
|
27074
27228
|
"totalCredits",
|
|
27075
27229
|
"contextUsagePercent",
|
|
@@ -27140,9 +27294,9 @@ function parseHostUsage(value2) {
|
|
|
27140
27294
|
if (value2.costSource !== "publicPrice") {
|
|
27141
27295
|
throw new Error("Harness Usage 'unpricedModels' must be provided with a 'publicPrice' cost");
|
|
27142
27296
|
}
|
|
27143
|
-
return { ...value2, unpricedModels: [...models] };
|
|
27297
|
+
return { ...value2, ...indicators, unpricedModels: [...models] };
|
|
27144
27298
|
}
|
|
27145
|
-
return { ...value2 };
|
|
27299
|
+
return { ...value2, ...indicators };
|
|
27146
27300
|
}
|
|
27147
27301
|
var requestTokenFields = [
|
|
27148
27302
|
"inputTokens",
|
|
@@ -27293,7 +27447,7 @@ var packageMetadata = {
|
|
|
27293
27447
|
|
|
27294
27448
|
// packages/mapping-store/dist/mapping-store.js
|
|
27295
27449
|
import { execFileSync } from "node:child_process";
|
|
27296
|
-
import { randomUUID as
|
|
27450
|
+
import { randomUUID as randomUUID11 } from "node:crypto";
|
|
27297
27451
|
import { constants as constants3 } from "node:fs";
|
|
27298
27452
|
import { copyFile as copyFile3, mkdir as mkdir13, open as open7, readFile as readFile17, readdir as readdir4, rename as rename11, rm as rm12, stat as stat6 } from "node:fs/promises";
|
|
27299
27453
|
import path21 from "node:path";
|
|
@@ -27309,7 +27463,9 @@ var isoDateSchema = external_exports.string().refine((value2) => !Number.isNaN(D
|
|
|
27309
27463
|
var storedTurnMappingV1Schema = external_exports.object({
|
|
27310
27464
|
hostTurnId: hostTurnIdSchema,
|
|
27311
27465
|
nativeTurnRef: nativeTurnRefSchema,
|
|
27312
|
-
nativeCheckpointRef: nativeCheckpointRefSchema.optional()
|
|
27466
|
+
nativeCheckpointRef: nativeCheckpointRefSchema.optional(),
|
|
27467
|
+
/** Desktop presentation for work completed during an external voice call. */
|
|
27468
|
+
realtimeInline: external_exports.literal(true).optional()
|
|
27313
27469
|
}).strict();
|
|
27314
27470
|
var storedGitInfoV1Schema = external_exports.object({
|
|
27315
27471
|
branch: nonBlankTextSchema6.max(4096).optional(),
|
|
@@ -27449,7 +27605,7 @@ var storedDelegationRecordV1Schema = external_exports.object({
|
|
|
27449
27605
|
});
|
|
27450
27606
|
|
|
27451
27607
|
// packages/mapping-store/dist/section-placements.js
|
|
27452
|
-
import { randomUUID as
|
|
27608
|
+
import { randomUUID as randomUUID9 } from "node:crypto";
|
|
27453
27609
|
import { constants } from "node:fs";
|
|
27454
27610
|
import { open as open5, readFile as readFile15, rename as rename9, rm as rm10 } from "node:fs/promises";
|
|
27455
27611
|
var threadIdSchema = external_exports.string().min(1).max(1024);
|
|
@@ -27501,7 +27657,7 @@ async function readSectionPlacementsFile(file2) {
|
|
|
27501
27657
|
}
|
|
27502
27658
|
async function writeSectionPlacementsFile(file2, placements) {
|
|
27503
27659
|
const parsed2 = parseSectionPlacements({ formatVersion: 1, placements });
|
|
27504
|
-
const temp = `${file2}.tmp-${
|
|
27660
|
+
const temp = `${file2}.tmp-${randomUUID9()}`;
|
|
27505
27661
|
let handle = null;
|
|
27506
27662
|
try {
|
|
27507
27663
|
handle = await open5(temp, "wx", constants.S_IRUSR | constants.S_IWUSR);
|
|
@@ -27520,7 +27676,7 @@ async function writeSectionPlacementsFile(file2, placements) {
|
|
|
27520
27676
|
}
|
|
27521
27677
|
|
|
27522
27678
|
// packages/mapping-store/dist/superseded-sessions.js
|
|
27523
|
-
import { randomUUID as
|
|
27679
|
+
import { randomUUID as randomUUID10 } from "node:crypto";
|
|
27524
27680
|
import { constants as constants2 } from "node:fs";
|
|
27525
27681
|
import { mkdir as mkdir12, open as open6, readFile as readFile16, rename as rename10, rm as rm11 } from "node:fs/promises";
|
|
27526
27682
|
import path20 from "node:path";
|
|
@@ -27555,7 +27711,7 @@ async function writeSupersededSessionsFile(file2, sessions) {
|
|
|
27555
27711
|
formatVersion: 1,
|
|
27556
27712
|
sessions: sessions.slice(-SUPERSEDED_SESSIONS_MAX)
|
|
27557
27713
|
}).sessions;
|
|
27558
|
-
const temp = `${file2}.tmp-${
|
|
27714
|
+
const temp = `${file2}.tmp-${randomUUID10()}`;
|
|
27559
27715
|
let handle = null;
|
|
27560
27716
|
try {
|
|
27561
27717
|
await mkdir12(path20.dirname(file2), { recursive: true });
|
|
@@ -27810,7 +27966,7 @@ var MappingStore = class {
|
|
|
27810
27966
|
this.#sectionsDirectory = path21.join(this.#directory, "sections");
|
|
27811
27967
|
this.#metadataDirectory = path21.join(this.#directory, "thread-metadata");
|
|
27812
27968
|
this.#lockPath = path21.join(this.#directory, "store.lock");
|
|
27813
|
-
this.#instanceId = options2.instanceId ??
|
|
27969
|
+
this.#instanceId = options2.instanceId ?? randomUUID11();
|
|
27814
27970
|
this.#now = options2.now ?? (() => /* @__PURE__ */ new Date());
|
|
27815
27971
|
this.#beforeReplace = options2.beforeReplace;
|
|
27816
27972
|
}
|
|
@@ -28318,6 +28474,8 @@ var MappingStore = class {
|
|
|
28318
28474
|
if (!hostMatch.nativeCheckpointRef && update.nativeCheckpointRef) {
|
|
28319
28475
|
hostMatch.nativeCheckpointRef = update.nativeCheckpointRef;
|
|
28320
28476
|
}
|
|
28477
|
+
if (update.realtimeInline)
|
|
28478
|
+
hostMatch.realtimeInline = true;
|
|
28321
28479
|
continue;
|
|
28322
28480
|
}
|
|
28323
28481
|
const added = { ...update };
|
|
@@ -28334,7 +28492,7 @@ var MappingStore = class {
|
|
|
28334
28492
|
this.#rebuildIndexes();
|
|
28335
28493
|
}
|
|
28336
28494
|
async #replaceFile(target, record4, preserveBackup) {
|
|
28337
|
-
const temp = `${target}.tmp-${
|
|
28495
|
+
const temp = `${target}.tmp-${randomUUID11()}`;
|
|
28338
28496
|
let handle = null;
|
|
28339
28497
|
try {
|
|
28340
28498
|
await this.#beforeReplace?.(cloneRecord(record4));
|
|
@@ -28361,7 +28519,7 @@ var MappingStore = class {
|
|
|
28361
28519
|
/** Atomically patches owned metadata fields, retaining unknown fields on disk. */
|
|
28362
28520
|
async #writeMetadataFile(hostThreadId, metadata) {
|
|
28363
28521
|
const target = this.#metadataPath(hostThreadId);
|
|
28364
|
-
const temp = `${target}.tmp-${
|
|
28522
|
+
const temp = `${target}.tmp-${randomUUID11()}`;
|
|
28365
28523
|
let handle = null;
|
|
28366
28524
|
try {
|
|
28367
28525
|
const retained = Object.fromEntries(Object.entries(await this.#readMetadata(hostThreadId) ?? {}).filter(([name]) => !["formatVersion", "hostThreadId", ...THREAD_METADATA_FIELDS].includes(name)));
|
|
@@ -28408,7 +28566,7 @@ var MappingStore = class {
|
|
|
28408
28566
|
}
|
|
28409
28567
|
async #replaceDelegationFile(record4) {
|
|
28410
28568
|
const target = this.#delegationPath(record4.delegationId);
|
|
28411
|
-
const temp = `${target}.tmp-${
|
|
28569
|
+
const temp = `${target}.tmp-${randomUUID11()}`;
|
|
28412
28570
|
let handle = null;
|
|
28413
28571
|
try {
|
|
28414
28572
|
handle = await open7(temp, "wx", constants3.S_IRUSR | constants3.S_IWUSR);
|
|
@@ -30100,8 +30258,18 @@ function projectSubagentActivities(item) {
|
|
|
30100
30258
|
];
|
|
30101
30259
|
});
|
|
30102
30260
|
}
|
|
30261
|
+
function projectUserMessage(item, clientId) {
|
|
30262
|
+
return {
|
|
30263
|
+
id: item.itemId,
|
|
30264
|
+
type: "userMessage",
|
|
30265
|
+
clientId,
|
|
30266
|
+
content: item.input.map(({ text }) => ({ type: "text", text, text_elements: [] }))
|
|
30267
|
+
};
|
|
30268
|
+
}
|
|
30103
30269
|
function projectItem(item, outcome, defaultCwd, includeCommandOutput = true) {
|
|
30104
30270
|
switch (item.type) {
|
|
30271
|
+
case "userMessage":
|
|
30272
|
+
return projectUserMessage(item, null);
|
|
30105
30273
|
case "agentMessage":
|
|
30106
30274
|
return {
|
|
30107
30275
|
id: item.itemId,
|
|
@@ -30307,6 +30475,7 @@ var CodexTurnProjector = class {
|
|
|
30307
30475
|
#interactions = /* @__PURE__ */ new Map();
|
|
30308
30476
|
#items = /* @__PURE__ */ new Map();
|
|
30309
30477
|
#wireItemOrder = [];
|
|
30478
|
+
#userMessageClientIds = /* @__PURE__ */ new Map();
|
|
30310
30479
|
#startedAt;
|
|
30311
30480
|
#startedAtMs;
|
|
30312
30481
|
#threadId;
|
|
@@ -30348,6 +30517,10 @@ var CodexTurnProjector = class {
|
|
|
30348
30517
|
}
|
|
30349
30518
|
return items;
|
|
30350
30519
|
}
|
|
30520
|
+
/** Associate steered input with the Desktop message that submitted it, before it is published. */
|
|
30521
|
+
bindUserMessageClientId(itemId, clientId) {
|
|
30522
|
+
this.#userMessageClientIds.set(itemId, clientId);
|
|
30523
|
+
}
|
|
30351
30524
|
pendingTurn(startedAt = null) {
|
|
30352
30525
|
return {
|
|
30353
30526
|
id: this.#turnId,
|
|
@@ -30358,6 +30531,8 @@ var CodexTurnProjector = class {
|
|
|
30358
30531
|
const projected = this.#items.get(itemId);
|
|
30359
30532
|
if (!projected?.wireStarted)
|
|
30360
30533
|
return [];
|
|
30534
|
+
if (projected.item.type === "userMessage")
|
|
30535
|
+
return [this.#projectItem(projected.item)];
|
|
30361
30536
|
if (projected.item.type === "agentMessage") {
|
|
30362
30537
|
return [projectItem(projected.item, projected.outcome, this.#cwd)];
|
|
30363
30538
|
}
|
|
@@ -30690,7 +30865,7 @@ var CodexTurnProjector = class {
|
|
|
30690
30865
|
};
|
|
30691
30866
|
}
|
|
30692
30867
|
const messages = [
|
|
30693
|
-
completedItem(projectItem(projected.item, projected.outcome,
|
|
30868
|
+
completedItem(this.#projectItem(projected.item, projected.outcome, !projected.streamedCommandOutput))
|
|
30694
30869
|
];
|
|
30695
30870
|
if (projected.item.type === "reasoning") {
|
|
30696
30871
|
const reasoning = projected.item;
|
|
@@ -30755,6 +30930,8 @@ var CodexTurnProjector = class {
|
|
|
30755
30930
|
projectReasoningTranscriptItem(reasoning, projected.outcome, this.#cwd, projected.durationMs ?? null)
|
|
30756
30931
|
];
|
|
30757
30932
|
}
|
|
30933
|
+
if (projected.item.type === "userMessage")
|
|
30934
|
+
return [this.#projectItem(projected.item)];
|
|
30758
30935
|
if (projected.item.type === "agentMessage") {
|
|
30759
30936
|
return [projectItem(projected.item, projected.outcome, this.#cwd)];
|
|
30760
30937
|
}
|
|
@@ -30853,10 +31030,13 @@ var CodexTurnProjector = class {
|
|
|
30853
31030
|
threadId: this.#threadId,
|
|
30854
31031
|
turnId: this.#turnId,
|
|
30855
31032
|
startedAtMs,
|
|
30856
|
-
item: projectItem(item, null
|
|
31033
|
+
item: this.#projectItem(item, null)
|
|
30857
31034
|
}
|
|
30858
31035
|
};
|
|
30859
31036
|
}
|
|
31037
|
+
#projectItem(item, outcome = null, includeCommandOutput = true) {
|
|
31038
|
+
return item.type === "userMessage" ? projectUserMessage(item, this.#userMessageClientIds.get(item.itemId) ?? null) : projectItem(item, outcome, this.#cwd, includeCommandOutput);
|
|
31039
|
+
}
|
|
30860
31040
|
#startReasoningTranscript(item, startedAtMs) {
|
|
30861
31041
|
return {
|
|
30862
31042
|
method: "item/started",
|
|
@@ -32008,7 +32188,7 @@ var AccountRateLimits = class {
|
|
|
32008
32188
|
};
|
|
32009
32189
|
|
|
32010
32190
|
// packages/host-runtime/src/native-account-observer.ts
|
|
32011
|
-
var
|
|
32191
|
+
var object7 = (value2) => typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
|
|
32012
32192
|
var NativeAccountObserver = class {
|
|
32013
32193
|
constructor(input) {
|
|
32014
32194
|
this.input = input;
|
|
@@ -32031,7 +32211,7 @@ var NativeAccountObserver = class {
|
|
|
32031
32211
|
}
|
|
32032
32212
|
/** Called after forwarding the native frame. Identity read failure cannot alter its outcome. */
|
|
32033
32213
|
observe(value2) {
|
|
32034
|
-
if (!
|
|
32214
|
+
if (!object7(value2) || value2.method !== "account/updated" && value2.method !== "account/login/completed" || !this.input.control.refresh || !this.#ready())
|
|
32035
32215
|
return;
|
|
32036
32216
|
this.#collectRequested = true;
|
|
32037
32217
|
if (this.#collecting) return;
|
|
@@ -32070,13 +32250,13 @@ var NativeAccountObserver = class {
|
|
|
32070
32250
|
const generation = scope.owner.generation;
|
|
32071
32251
|
this.#lastGeneration = generation;
|
|
32072
32252
|
const response = await scope.owner.controlRequest("account/read", { refreshToken: false });
|
|
32073
|
-
if (response.error || !
|
|
32253
|
+
if (response.error || !object7(response.result))
|
|
32074
32254
|
throw new Error("Invalid native Account response");
|
|
32075
32255
|
const account = response.result.account;
|
|
32076
32256
|
let params;
|
|
32077
32257
|
if (account === null) params = { authMode: null, planType: null };
|
|
32078
32258
|
else {
|
|
32079
|
-
if (!
|
|
32259
|
+
if (!object7(account) || account.type !== "chatgpt")
|
|
32080
32260
|
throw new Error("Invalid native Account response");
|
|
32081
32261
|
params = {
|
|
32082
32262
|
authMode: "chatgpt",
|
|
@@ -32248,7 +32428,7 @@ var HarnessAccountInspectionCache = class {
|
|
|
32248
32428
|
};
|
|
32249
32429
|
|
|
32250
32430
|
// packages/host-runtime/src/app-server-host.ts
|
|
32251
|
-
import { createHash as createHash9, randomUUID as
|
|
32431
|
+
import { createHash as createHash9, randomUUID as randomUUID19 } from "node:crypto";
|
|
32252
32432
|
import os9 from "node:os";
|
|
32253
32433
|
import path28 from "node:path";
|
|
32254
32434
|
|
|
@@ -32256,12 +32436,12 @@ import path28 from "node:path";
|
|
|
32256
32436
|
import nodePath from "node:path";
|
|
32257
32437
|
|
|
32258
32438
|
// packages/host-runtime/src/external-thread-repository.ts
|
|
32259
|
-
import { randomUUID as
|
|
32439
|
+
import { randomUUID as randomUUID13 } from "node:crypto";
|
|
32260
32440
|
import os8 from "node:os";
|
|
32261
32441
|
import path25 from "node:path";
|
|
32262
32442
|
|
|
32263
32443
|
// packages/host-runtime/src/external-subagent-threads.ts
|
|
32264
|
-
import { createHash as createHash6, randomUUID as
|
|
32444
|
+
import { createHash as createHash6, randomUUID as randomUUID12 } from "node:crypto";
|
|
32265
32445
|
function childCreateRequest(parent, nativeRef, id2) {
|
|
32266
32446
|
const key = createHash6("sha256").update(JSON.stringify([parent.hostThreadId, parent.harnessId, nativeRef.nativeSessionId, id2])).digest("hex");
|
|
32267
32447
|
return `subagent:${key}`;
|
|
@@ -32343,7 +32523,7 @@ function subagentMaterializer(store, parent, previousParent) {
|
|
|
32343
32523
|
return configured(await rebind(existing, parent));
|
|
32344
32524
|
}
|
|
32345
32525
|
const provisional = existing ?? await store.createProvisional({
|
|
32346
|
-
hostThreadId: hostThreadIdSchema.parse(
|
|
32526
|
+
hostThreadId: hostThreadIdSchema.parse(randomUUID12()),
|
|
32347
32527
|
createRequestId,
|
|
32348
32528
|
harnessId: parent.harnessId,
|
|
32349
32529
|
cwd: parent.cwd,
|
|
@@ -32386,14 +32566,13 @@ async function projectExternalSnapshot(store, record4, snapshot2, previousParent
|
|
|
32386
32566
|
return { ...entry, item: { ...entry.item, subagents } };
|
|
32387
32567
|
})
|
|
32388
32568
|
);
|
|
32389
|
-
|
|
32390
|
-
|
|
32391
|
-
|
|
32392
|
-
|
|
32393
|
-
|
|
32394
|
-
|
|
32395
|
-
|
|
32396
|
-
);
|
|
32569
|
+
const projected = projectHistoricalTurn({
|
|
32570
|
+
threadId: record4.hostThreadId,
|
|
32571
|
+
turnId: mapping.hostTurnId,
|
|
32572
|
+
cwd: record4.cwd,
|
|
32573
|
+
snapshot: { ...turn, items }
|
|
32574
|
+
});
|
|
32575
|
+
turns.push(mapping.realtimeInline ? presentExternalVoiceTurn(projected) : projected);
|
|
32397
32576
|
}
|
|
32398
32577
|
return turns;
|
|
32399
32578
|
}
|
|
@@ -32497,7 +32676,7 @@ var ExternalThreadRepository = class {
|
|
|
32497
32676
|
removeThread(hostThreadId) {
|
|
32498
32677
|
return this.store.removeThread(hostThreadId);
|
|
32499
32678
|
}
|
|
32500
|
-
async persistTurn(record4, hostTurnId, nativeTurnRef, nativeCheckpointRef) {
|
|
32679
|
+
async persistTurn(record4, hostTurnId, nativeTurnRef, nativeCheckpointRef, realtimeInline) {
|
|
32501
32680
|
if (record4.state !== "ready" || !record4.nativeSessionRef || nativeTurnRef.harnessId !== record4.harnessId || nativeTurnRef.nativeSessionId !== record4.nativeSessionRef.nativeSessionId || nativeCheckpointRef && (nativeCheckpointRef.harnessId !== record4.harnessId || nativeCheckpointRef.nativeSessionId !== record4.nativeSessionRef.nativeSessionId)) {
|
|
32502
32681
|
throw new Error("Live Turn identity does not belong to the stored Thread");
|
|
32503
32682
|
}
|
|
@@ -32505,7 +32684,8 @@ var ExternalThreadRepository = class {
|
|
|
32505
32684
|
{
|
|
32506
32685
|
hostTurnId,
|
|
32507
32686
|
nativeTurnRef,
|
|
32508
|
-
...nativeCheckpointRef ? { nativeCheckpointRef } : {}
|
|
32687
|
+
...nativeCheckpointRef ? { nativeCheckpointRef } : {},
|
|
32688
|
+
...realtimeInline ? { realtimeInline } : {}
|
|
32509
32689
|
}
|
|
32510
32690
|
]);
|
|
32511
32691
|
}
|
|
@@ -32518,7 +32698,7 @@ var ExternalThreadRepository = class {
|
|
|
32518
32698
|
throw new Error("Derived Snapshot identity does not belong to its Native Session");
|
|
32519
32699
|
}
|
|
32520
32700
|
return {
|
|
32521
|
-
hostTurnId: hostTurnIdSchema.parse(
|
|
32701
|
+
hostTurnId: hostTurnIdSchema.parse(randomUUID13()),
|
|
32522
32702
|
nativeTurnRef: turn.nativeTurnRef,
|
|
32523
32703
|
...turn.checkpoint ? { nativeCheckpointRef: turn.checkpoint } : {}
|
|
32524
32704
|
};
|
|
@@ -32558,6 +32738,7 @@ var ExternalThreadRepository = class {
|
|
|
32558
32738
|
}
|
|
32559
32739
|
return {
|
|
32560
32740
|
hostTurnId: previous.hostTurnId,
|
|
32741
|
+
...previous.realtimeInline ? { realtimeInline: true } : {},
|
|
32561
32742
|
nativeTurnRef: turn.nativeTurnRef,
|
|
32562
32743
|
...turn.checkpoint ? { nativeCheckpointRef: turn.checkpoint } : {}
|
|
32563
32744
|
};
|
|
@@ -32589,6 +32770,7 @@ var ExternalThreadRepository = class {
|
|
|
32589
32770
|
}
|
|
32590
32771
|
return {
|
|
32591
32772
|
hostTurnId: previous.hostTurnId,
|
|
32773
|
+
...previous.realtimeInline ? { realtimeInline: true } : {},
|
|
32592
32774
|
nativeTurnRef: turn.nativeTurnRef,
|
|
32593
32775
|
...turn.checkpoint ? { nativeCheckpointRef: turn.checkpoint } : {}
|
|
32594
32776
|
};
|
|
@@ -32641,14 +32823,15 @@ var ExternalThreadRepository = class {
|
|
|
32641
32823
|
const aligned = snapshot2.turns.map((turn) => {
|
|
32642
32824
|
const existing = mappingsByNative.get(nativeTurnKey2(turn.nativeTurnRef));
|
|
32643
32825
|
const mapping = existing ?? {
|
|
32644
|
-
hostTurnId: hostTurnIdSchema.parse(
|
|
32826
|
+
hostTurnId: hostTurnIdSchema.parse(randomUUID13()),
|
|
32645
32827
|
nativeTurnRef: turn.nativeTurnRef,
|
|
32646
32828
|
...turn.checkpoint ? { nativeCheckpointRef: turn.checkpoint } : {}
|
|
32647
32829
|
};
|
|
32648
32830
|
return {
|
|
32649
32831
|
snapshot: turn,
|
|
32650
32832
|
mapping: {
|
|
32651
|
-
|
|
32833
|
+
hostTurnId: mapping.hostTurnId,
|
|
32834
|
+
...mapping.realtimeInline ? { realtimeInline: true } : {},
|
|
32652
32835
|
nativeTurnRef: turn.nativeTurnRef,
|
|
32653
32836
|
...turn.checkpoint ? { nativeCheckpointRef: turn.checkpoint } : {}
|
|
32654
32837
|
}
|
|
@@ -32668,8 +32851,8 @@ var ExternalThreadRepository = class {
|
|
|
32668
32851
|
};
|
|
32669
32852
|
function createExternalThreadRecordInput(input) {
|
|
32670
32853
|
return {
|
|
32671
|
-
hostThreadId: input.hostThreadId ?? hostThreadIdSchema.parse(
|
|
32672
|
-
createRequestId: input.createRequestId ??
|
|
32854
|
+
hostThreadId: input.hostThreadId ?? hostThreadIdSchema.parse(randomUUID13()),
|
|
32855
|
+
createRequestId: input.createRequestId ?? randomUUID13(),
|
|
32673
32856
|
harnessId: input.harnessId,
|
|
32674
32857
|
cwd: input.cwd,
|
|
32675
32858
|
...input.title ? { title: input.title } : {},
|
|
@@ -32791,6 +32974,15 @@ async function executeExternalThreadFork(input) {
|
|
|
32791
32974
|
boundaryIndex = mappings.length - 1;
|
|
32792
32975
|
}
|
|
32793
32976
|
const boundary = mappings[boundaryIndex];
|
|
32977
|
+
if (boundary && source.steeredTurnIds.has(boundary.hostTurnId)) {
|
|
32978
|
+
return {
|
|
32979
|
+
ok: false,
|
|
32980
|
+
error: {
|
|
32981
|
+
code: -32080,
|
|
32982
|
+
message: "This Turn took steered input; reopen the Thread before forking from it"
|
|
32983
|
+
}
|
|
32984
|
+
};
|
|
32985
|
+
}
|
|
32794
32986
|
if (boundaryIndex < 0 || !boundary?.nativeCheckpointRef) {
|
|
32795
32987
|
return {
|
|
32796
32988
|
ok: false,
|
|
@@ -33547,6 +33739,16 @@ async function executeExternalThreadRollback(input) {
|
|
|
33547
33739
|
if (derived.running) {
|
|
33548
33740
|
return { ok: false, error: { code: -32072, message: "External Thread has an active Turn" } };
|
|
33549
33741
|
}
|
|
33742
|
+
const undone = derived.record.turnMappings.slice(-rollback.numTurns);
|
|
33743
|
+
if (undone.some((mapping) => derived.steeredTurnIds.has(mapping.hostTurnId))) {
|
|
33744
|
+
return {
|
|
33745
|
+
ok: false,
|
|
33746
|
+
error: {
|
|
33747
|
+
code: -32080,
|
|
33748
|
+
message: "A Turn here took steered input; reopen the Thread before undoing Turns"
|
|
33749
|
+
}
|
|
33750
|
+
};
|
|
33751
|
+
}
|
|
33550
33752
|
const refreshError = await runtime.refresh(derived);
|
|
33551
33753
|
if (refreshError) return { ok: false, error: refreshError };
|
|
33552
33754
|
if (expectedLastTurnId !== void 0 && derived.record.turnMappings.at(-1)?.hostTurnId !== expectedLastTurnId) {
|
|
@@ -34346,6 +34548,7 @@ var ExternalThreadRuntime = class {
|
|
|
34346
34548
|
#repository;
|
|
34347
34549
|
#lifecycle = new ExternalThreadLifecycle();
|
|
34348
34550
|
#hasRunningDescendants;
|
|
34551
|
+
#steeredTurnIds = /* @__PURE__ */ new Map();
|
|
34349
34552
|
#subagentRunning;
|
|
34350
34553
|
#threads = /* @__PURE__ */ new Map();
|
|
34351
34554
|
constructor(input) {
|
|
@@ -34359,7 +34562,8 @@ var ExternalThreadRuntime = class {
|
|
|
34359
34562
|
this.idleRelease = new ExternalThreadIdleRelease({
|
|
34360
34563
|
threads: () => this.values(),
|
|
34361
34564
|
get: (id2) => this.get(id2),
|
|
34362
|
-
|
|
34565
|
+
// Idle release detaches only the Native Session. Host Thread state survives restoration.
|
|
34566
|
+
remove: (id2) => this.#detach(id2),
|
|
34363
34567
|
queue: input.idleRelease?.queue ?? new DesktopRequestQueue(),
|
|
34364
34568
|
canRelease: (thread) => !thread.sessionUnavailable && !this.#lifecycle.busy(thread.id) && (input.idleRelease?.canRelease(thread) ?? false),
|
|
34365
34569
|
...input.idleRelease?.onClosed ? { onClosed: input.idleRelease.onClosed } : {},
|
|
@@ -34369,14 +34573,21 @@ var ExternalThreadRuntime = class {
|
|
|
34369
34573
|
get(threadId2) {
|
|
34370
34574
|
return this.#threads.get(threadId2);
|
|
34371
34575
|
}
|
|
34576
|
+
#detach(threadId2) {
|
|
34577
|
+
const thread = this.#threads.get(threadId2);
|
|
34578
|
+
this.#threads.delete(threadId2);
|
|
34579
|
+
if (!thread || thread.steeredTurnIds.size === 0) this.#steeredTurnIds.delete(threadId2);
|
|
34580
|
+
}
|
|
34372
34581
|
values() {
|
|
34373
34582
|
return [...this.#threads.values()];
|
|
34374
34583
|
}
|
|
34375
34584
|
remove(threadId2) {
|
|
34376
34585
|
this.#threads.delete(threadId2);
|
|
34586
|
+
this.#steeredTurnIds.delete(threadId2);
|
|
34377
34587
|
}
|
|
34378
34588
|
clear() {
|
|
34379
34589
|
this.#threads.clear();
|
|
34590
|
+
this.#steeredTurnIds.clear();
|
|
34380
34591
|
}
|
|
34381
34592
|
drain() {
|
|
34382
34593
|
return this.#lifecycle.drain();
|
|
@@ -34433,6 +34644,11 @@ var ExternalThreadRuntime = class {
|
|
|
34433
34644
|
...effectivePermissionModeId ? { effectivePermissionModeId } : {}
|
|
34434
34645
|
};
|
|
34435
34646
|
const running = this.#subagentRunning(input.record.hostThreadId);
|
|
34647
|
+
let steeredTurnIds = this.#steeredTurnIds.get(input.record.hostThreadId);
|
|
34648
|
+
if (!steeredTurnIds) {
|
|
34649
|
+
steeredTurnIds = /* @__PURE__ */ new Set();
|
|
34650
|
+
this.#steeredTurnIds.set(input.record.hostThreadId, steeredTurnIds);
|
|
34651
|
+
}
|
|
34436
34652
|
const externalThread = {
|
|
34437
34653
|
id: input.record.hostThreadId,
|
|
34438
34654
|
cwd: input.record.cwd,
|
|
@@ -34457,11 +34673,13 @@ var ExternalThreadRuntime = class {
|
|
|
34457
34673
|
usageTurnId: null,
|
|
34458
34674
|
projectedTurns: /* @__PURE__ */ new Map(),
|
|
34459
34675
|
responseGates: /* @__PURE__ */ new Map(),
|
|
34676
|
+
pendingSteerProjections: /* @__PURE__ */ new Set(),
|
|
34460
34677
|
ephemeralTurnIds: /* @__PURE__ */ new Set(),
|
|
34461
34678
|
persistenceError: null,
|
|
34462
34679
|
projectedTerminalTurnId: null,
|
|
34463
34680
|
ignoredInteractionIds: /* @__PURE__ */ new Set(),
|
|
34464
|
-
sessionUnavailable: false
|
|
34681
|
+
sessionUnavailable: false,
|
|
34682
|
+
steeredTurnIds
|
|
34465
34683
|
};
|
|
34466
34684
|
this.idleRelease.touch(externalThread);
|
|
34467
34685
|
externalThread.outputTask = this.#consumeOutputs(externalThread);
|
|
@@ -34518,13 +34736,13 @@ var ExternalThreadRuntime = class {
|
|
|
34518
34736
|
const retire = async () => {
|
|
34519
34737
|
if (this.#threads.get(parentId) !== parent || this.#threads.get(child.id) !== child) return;
|
|
34520
34738
|
if (bestEffort) {
|
|
34521
|
-
this
|
|
34739
|
+
this.remove(child.id);
|
|
34522
34740
|
await child.session.close();
|
|
34523
34741
|
await child.outputTask;
|
|
34524
34742
|
} else {
|
|
34525
34743
|
child.sessionUnavailable = true;
|
|
34526
34744
|
await this.#lifecycle.release(child.id, child.session, child.outputTask);
|
|
34527
|
-
if (this.#threads.get(child.id) === child) this
|
|
34745
|
+
if (this.#threads.get(child.id) === child) this.remove(child.id);
|
|
34528
34746
|
}
|
|
34529
34747
|
};
|
|
34530
34748
|
if (bestEffort) await retire().catch(this.#diagnose);
|
|
@@ -34761,7 +34979,8 @@ var ExternalThreadRuntime = class {
|
|
|
34761
34979
|
thread.record,
|
|
34762
34980
|
event.turnId,
|
|
34763
34981
|
event.nativeTurnRef,
|
|
34764
|
-
event.outcome.checkpoint
|
|
34982
|
+
event.outcome.checkpoint,
|
|
34983
|
+
thread.projectedTurns.get(event.turnId)?.realtimeInline
|
|
34765
34984
|
);
|
|
34766
34985
|
return null;
|
|
34767
34986
|
} catch (error51) {
|
|
@@ -34897,6 +35116,71 @@ var ExternalThreadRuntime = class {
|
|
|
34897
35116
|
};
|
|
34898
35117
|
|
|
34899
35118
|
// packages/host-runtime/src/external-turn-steering.ts
|
|
35119
|
+
import { randomUUID as randomUUID14 } from "node:crypto";
|
|
35120
|
+
|
|
35121
|
+
// packages/host-runtime/src/external-command-routing.ts
|
|
35122
|
+
var ExternalCommandError = class extends Error {
|
|
35123
|
+
constructor(code, message2) {
|
|
35124
|
+
super(message2);
|
|
35125
|
+
this.code = code;
|
|
35126
|
+
}
|
|
35127
|
+
code;
|
|
35128
|
+
};
|
|
35129
|
+
function isExternalCommandCandidate(text) {
|
|
35130
|
+
return /^\/[^\s/]+(?:\s|$)/u.test(text.trimStart());
|
|
35131
|
+
}
|
|
35132
|
+
async function inspectLiveCommandCatalog(commands, timeoutMs = 1e3) {
|
|
35133
|
+
let timeout;
|
|
35134
|
+
try {
|
|
35135
|
+
const result = await Promise.race([
|
|
35136
|
+
commands.list(),
|
|
35137
|
+
new Promise((resolve) => {
|
|
35138
|
+
timeout = setTimeout(() => resolve(null), timeoutMs);
|
|
35139
|
+
})
|
|
35140
|
+
]);
|
|
35141
|
+
return result?.ok ? harnessCommandCatalogSchema.parse(result.value) : null;
|
|
35142
|
+
} catch {
|
|
35143
|
+
return null;
|
|
35144
|
+
} finally {
|
|
35145
|
+
if (timeout !== void 0) clearTimeout(timeout);
|
|
35146
|
+
}
|
|
35147
|
+
}
|
|
35148
|
+
async function resolveExternalCommand(commands, text, options2 = {}) {
|
|
35149
|
+
const catalog = await commands.list();
|
|
35150
|
+
if (!catalog.ok) throw new ExternalCommandError(-32073, catalog.error.message);
|
|
35151
|
+
const commandText = text.trim();
|
|
35152
|
+
const matched = catalog.value.commands.toSorted((left, right) => right.invocation.length - left.invocation.length).find((command) => {
|
|
35153
|
+
if (commandText === command.invocation) return true;
|
|
35154
|
+
return command.argumentMode === "text" && commandText.startsWith(`${command.invocation} `);
|
|
35155
|
+
});
|
|
35156
|
+
if (!matched) {
|
|
35157
|
+
const name = /^\/(\S+)/u.exec(commandText)?.[1] ?? "";
|
|
35158
|
+
if (name && !isExcludedLiveCommand(name, "command") && options2.liveCatalogPending?.(catalog.value)) {
|
|
35159
|
+
return null;
|
|
35160
|
+
}
|
|
35161
|
+
throw new ExternalCommandError(
|
|
35162
|
+
-32078,
|
|
35163
|
+
"External Harness does not expose the requested command"
|
|
35164
|
+
);
|
|
35165
|
+
}
|
|
35166
|
+
const argumentText = commandText.slice(matched.invocation.length).trimStart();
|
|
35167
|
+
return {
|
|
35168
|
+
descriptor: matched,
|
|
35169
|
+
...argumentText.length > 0 ? { arguments: { text: argumentText } } : {}
|
|
35170
|
+
};
|
|
35171
|
+
}
|
|
35172
|
+
|
|
35173
|
+
// packages/host-runtime/src/external-turn-steering.ts
|
|
35174
|
+
function isHarnessCommand(thread, text) {
|
|
35175
|
+
return thread.session.commands !== void 0 && isExternalCommandCandidate(restoreHarnessCommandMentions(text));
|
|
35176
|
+
}
|
|
35177
|
+
function externalSteeringDelivery(thread, text) {
|
|
35178
|
+
if (text !== void 0 && isHarnessCommand(thread, text)) return "newTurn";
|
|
35179
|
+
if (thread.session.readCapabilities) {
|
|
35180
|
+
return thread.session.readCapabilities().then((capabilities) => capabilities.steer === true ? "activeTurn" : "newTurn");
|
|
35181
|
+
}
|
|
35182
|
+
return thread.session.capabilities.steer === true ? "activeTurn" : "newTurn";
|
|
35183
|
+
}
|
|
34900
35184
|
var ExternalSteerError = class extends Error {
|
|
34901
35185
|
constructor(code, message2) {
|
|
34902
35186
|
super(message2);
|
|
@@ -34904,6 +35188,11 @@ var ExternalSteerError = class extends Error {
|
|
|
34904
35188
|
}
|
|
34905
35189
|
code;
|
|
34906
35190
|
};
|
|
35191
|
+
var ExternalSteerNotTakenError = class extends ExternalSteerError {
|
|
35192
|
+
constructor(message2) {
|
|
35193
|
+
super(-32074, message2);
|
|
35194
|
+
}
|
|
35195
|
+
};
|
|
34907
35196
|
function parseInput(params) {
|
|
34908
35197
|
if (typeof params.expectedTurnId !== "string" || !params.expectedTurnId.trim()) {
|
|
34909
35198
|
throw new ExternalSteerError(-32602, "External steering requires expectedTurnId");
|
|
@@ -34920,12 +35209,47 @@ function parseInput(params) {
|
|
|
34920
35209
|
if (clientUserMessageId != null && (typeof clientUserMessageId !== "string" || !clientUserMessageId.trim())) {
|
|
34921
35210
|
throw new ExternalSteerError(-32602, "External steering message identity is invalid");
|
|
34922
35211
|
}
|
|
35212
|
+
const delivery = params[THREAD_STEER_DELIVERY_PARAM];
|
|
35213
|
+
const parsedDelivery = delivery == null ? void 0 : threadSteerDeliverySchema.safeParse(delivery);
|
|
35214
|
+
if (parsedDelivery && !parsedDelivery.success) {
|
|
35215
|
+
throw new ExternalSteerError(-32602, "External steering delivery is invalid");
|
|
35216
|
+
}
|
|
34923
35217
|
return {
|
|
34924
35218
|
expectedTurnId: params.expectedTurnId,
|
|
34925
35219
|
text,
|
|
34926
|
-
...typeof clientUserMessageId === "string" ? { clientUserMessageId } : {}
|
|
35220
|
+
...typeof clientUserMessageId === "string" ? { clientUserMessageId } : {},
|
|
35221
|
+
...parsedDelivery ? { delivery: parsedDelivery.data } : {}
|
|
34927
35222
|
};
|
|
34928
35223
|
}
|
|
35224
|
+
async function insertNativeSteer(thread, input, host) {
|
|
35225
|
+
const restored = restoreHarnessCommandMentions(input.text);
|
|
35226
|
+
const steered = [{ type: "text", text: rewriteDelegationMentionText(restored) }];
|
|
35227
|
+
const displayed = [{ type: "text", text: restored }];
|
|
35228
|
+
const projectionDone = Promise.withResolvers();
|
|
35229
|
+
thread.pendingSteerProjections.add(projectionDone.promise);
|
|
35230
|
+
try {
|
|
35231
|
+
const result = await thread.session.execute({
|
|
35232
|
+
type: "turn.steer",
|
|
35233
|
+
turnId: input.turnId,
|
|
35234
|
+
input: steered
|
|
35235
|
+
});
|
|
35236
|
+
if (!result.ok) throw new ExternalSteerNotTakenError(result.error.message);
|
|
35237
|
+
thread.steeredTurnIds.add(input.turnId);
|
|
35238
|
+
const item = {
|
|
35239
|
+
type: "userMessage",
|
|
35240
|
+
itemId: hostItemIdSchema.parse(randomUUID14()),
|
|
35241
|
+
input: displayed
|
|
35242
|
+
};
|
|
35243
|
+
try {
|
|
35244
|
+
await host.project(input.turnId, item, input.clientUserMessageId);
|
|
35245
|
+
} catch (error51) {
|
|
35246
|
+
host.diagnose(error51);
|
|
35247
|
+
}
|
|
35248
|
+
} finally {
|
|
35249
|
+
projectionDone.resolve(void 0);
|
|
35250
|
+
thread.pendingSteerProjections.delete(projectionDone.promise);
|
|
35251
|
+
}
|
|
35252
|
+
}
|
|
34929
35253
|
var ExternalTurnSteering = class {
|
|
34930
35254
|
constructor(timeoutMs = 2e4) {
|
|
34931
35255
|
this.timeoutMs = timeoutMs;
|
|
@@ -34937,7 +35261,7 @@ var ExternalTurnSteering = class {
|
|
|
34937
35261
|
hasPending(threadId2) {
|
|
34938
35262
|
return threadId2 === void 0 ? this.#pending.size > 0 : this.#pending.has(threadId2);
|
|
34939
35263
|
}
|
|
34940
|
-
run(thread, params, start) {
|
|
35264
|
+
run(thread, params, start, insert) {
|
|
34941
35265
|
try {
|
|
34942
35266
|
const input = parseInput(params);
|
|
34943
35267
|
if (this.#closed)
|
|
@@ -34959,7 +35283,7 @@ var ExternalTurnSteering = class {
|
|
|
34959
35283
|
if (!thread.running || thread.activeTurnId !== input.expectedTurnId) {
|
|
34960
35284
|
throw new ExternalSteerError(-32074, "External steering must reference the active Turn");
|
|
34961
35285
|
}
|
|
34962
|
-
const result = this.#
|
|
35286
|
+
const result = this.#deliver(thread, input, start, insert);
|
|
34963
35287
|
if (key) {
|
|
34964
35288
|
const receipt2 = { fingerprint, result, settled: false };
|
|
34965
35289
|
this.#receipts.set(key, receipt2);
|
|
@@ -34982,6 +35306,56 @@ var ExternalTurnSteering = class {
|
|
|
34982
35306
|
return Promise.reject(error51);
|
|
34983
35307
|
}
|
|
34984
35308
|
}
|
|
35309
|
+
/**
|
|
35310
|
+
* A Renderer that already presented a delivery gets exactly that one. Otherwise native delivery
|
|
35311
|
+
* is tried only when the Session can take the input now, and input the Harness did not take
|
|
35312
|
+
* falls back to stopping and restarting, so no case is worse than the stop-then-start path.
|
|
35313
|
+
*/
|
|
35314
|
+
#deliver(thread, input, start, insert) {
|
|
35315
|
+
const delivery = input.delivery === "newTurn" || isHarnessCommand(thread, input.text) ? "newTurn" : input.delivery ?? externalSteeringDelivery(thread);
|
|
35316
|
+
const deliver = (mode) => {
|
|
35317
|
+
if (this.#closed || !thread.running || thread.activeTurnId !== input.expectedTurnId) {
|
|
35318
|
+
throw new ExternalSteerError(-32074, "External steering target is no longer active");
|
|
35319
|
+
}
|
|
35320
|
+
if (this.hasPending(thread.id))
|
|
35321
|
+
throw new ExternalSteerError(-32072, "External Thread is already changing direction");
|
|
35322
|
+
if (mode === "newTurn") return this.#replace(thread, input, start);
|
|
35323
|
+
const native = insert({
|
|
35324
|
+
turnId: thread.activeTurnId,
|
|
35325
|
+
text: input.text,
|
|
35326
|
+
...input.clientUserMessageId ? { clientUserMessageId: input.clientUserMessageId } : {}
|
|
35327
|
+
}).then((admitted) => ({ ...admitted, delivery: "activeTurn" }));
|
|
35328
|
+
if (input.delivery === "activeTurn") return native;
|
|
35329
|
+
return native.catch(async (error51) => {
|
|
35330
|
+
if (!(error51 instanceof ExternalSteerNotTakenError)) throw error51;
|
|
35331
|
+
if (thread.running || thread.activeTurnId) return deliver("newTurn");
|
|
35332
|
+
const assertActive = () => {
|
|
35333
|
+
if (this.#closed)
|
|
35334
|
+
throw new ExternalSteerError(-32074, "External steering connection is closed");
|
|
35335
|
+
};
|
|
35336
|
+
return { ...await start(input.text, assertActive), delivery: "newTurn" };
|
|
35337
|
+
});
|
|
35338
|
+
};
|
|
35339
|
+
if (typeof delivery === "string") return deliver(delivery);
|
|
35340
|
+
const failure = Promise.withResolvers();
|
|
35341
|
+
let failureReason = null;
|
|
35342
|
+
const pending = {
|
|
35343
|
+
turnId: input.expectedTurnId,
|
|
35344
|
+
resolve: () => void 0,
|
|
35345
|
+
reject(error51) {
|
|
35346
|
+
failureReason ??= error51;
|
|
35347
|
+
failure.reject(error51);
|
|
35348
|
+
}
|
|
35349
|
+
};
|
|
35350
|
+
this.#pending.set(thread.id, pending);
|
|
35351
|
+
return Promise.race([delivery, failure.promise]).then((mode) => {
|
|
35352
|
+
if (failureReason) throw failureReason;
|
|
35353
|
+
if (this.#pending.get(thread.id) === pending) this.#pending.delete(thread.id);
|
|
35354
|
+
return deliver(mode);
|
|
35355
|
+
}).finally(() => {
|
|
35356
|
+
if (this.#pending.get(thread.id) === pending) this.#pending.delete(thread.id);
|
|
35357
|
+
});
|
|
35358
|
+
}
|
|
34985
35359
|
terminal(threadId2, turnId, outcome) {
|
|
34986
35360
|
const pending = this.#pending.get(threadId2);
|
|
34987
35361
|
if (pending?.turnId === turnId) pending.resolve(outcome);
|
|
@@ -35036,7 +35410,9 @@ var ExternalTurnSteering = class {
|
|
|
35036
35410
|
thread.session.execute({ type: "turn.cancel", turnId }),
|
|
35037
35411
|
failure.promise
|
|
35038
35412
|
]);
|
|
35039
|
-
if (!cancelled.ok
|
|
35413
|
+
if (!cancelled.ok && cancelled.error.code !== "invalidState") {
|
|
35414
|
+
throw new ExternalSteerError(-32074, cancelled.error.message);
|
|
35415
|
+
}
|
|
35040
35416
|
const outcome = await Promise.race([terminal3.promise, failure.promise]);
|
|
35041
35417
|
clearTimeout(timeout);
|
|
35042
35418
|
const assertActive = () => {
|
|
@@ -35054,7 +35430,7 @@ var ExternalTurnSteering = class {
|
|
|
35054
35430
|
if (thread.running || thread.activeTurnId) {
|
|
35055
35431
|
throw new ExternalSteerError(-32072, "Another External Turn started before replacement");
|
|
35056
35432
|
}
|
|
35057
|
-
return await start(input.text, assertActive);
|
|
35433
|
+
return { ...await start(input.text, assertActive), delivery: "newTurn" };
|
|
35058
35434
|
} finally {
|
|
35059
35435
|
clearTimeout(timeout);
|
|
35060
35436
|
if (this.#pending.get(thread.id) === pending) this.#pending.delete(thread.id);
|
|
@@ -35062,58 +35438,6 @@ var ExternalTurnSteering = class {
|
|
|
35062
35438
|
}
|
|
35063
35439
|
};
|
|
35064
35440
|
|
|
35065
|
-
// packages/host-runtime/src/external-command-routing.ts
|
|
35066
|
-
var ExternalCommandError = class extends Error {
|
|
35067
|
-
constructor(code, message2) {
|
|
35068
|
-
super(message2);
|
|
35069
|
-
this.code = code;
|
|
35070
|
-
}
|
|
35071
|
-
code;
|
|
35072
|
-
};
|
|
35073
|
-
function isExternalCommandCandidate(text) {
|
|
35074
|
-
return /^\/[^\s/]+(?:\s|$)/u.test(text.trimStart());
|
|
35075
|
-
}
|
|
35076
|
-
async function inspectLiveCommandCatalog(commands, timeoutMs = 1e3) {
|
|
35077
|
-
let timeout;
|
|
35078
|
-
try {
|
|
35079
|
-
const result = await Promise.race([
|
|
35080
|
-
commands.list(),
|
|
35081
|
-
new Promise((resolve) => {
|
|
35082
|
-
timeout = setTimeout(() => resolve(null), timeoutMs);
|
|
35083
|
-
})
|
|
35084
|
-
]);
|
|
35085
|
-
return result?.ok ? harnessCommandCatalogSchema.parse(result.value) : null;
|
|
35086
|
-
} catch {
|
|
35087
|
-
return null;
|
|
35088
|
-
} finally {
|
|
35089
|
-
if (timeout !== void 0) clearTimeout(timeout);
|
|
35090
|
-
}
|
|
35091
|
-
}
|
|
35092
|
-
async function resolveExternalCommand(commands, text, options2 = {}) {
|
|
35093
|
-
const catalog = await commands.list();
|
|
35094
|
-
if (!catalog.ok) throw new ExternalCommandError(-32073, catalog.error.message);
|
|
35095
|
-
const commandText = text.trim();
|
|
35096
|
-
const matched = catalog.value.commands.toSorted((left, right) => right.invocation.length - left.invocation.length).find((command) => {
|
|
35097
|
-
if (commandText === command.invocation) return true;
|
|
35098
|
-
return command.argumentMode === "text" && commandText.startsWith(`${command.invocation} `);
|
|
35099
|
-
});
|
|
35100
|
-
if (!matched) {
|
|
35101
|
-
const name = /^\/(\S+)/u.exec(commandText)?.[1] ?? "";
|
|
35102
|
-
if (name && !isExcludedLiveCommand(name, "command") && options2.liveCatalogPending?.(catalog.value)) {
|
|
35103
|
-
return null;
|
|
35104
|
-
}
|
|
35105
|
-
throw new ExternalCommandError(
|
|
35106
|
-
-32078,
|
|
35107
|
-
"External Harness does not expose the requested command"
|
|
35108
|
-
);
|
|
35109
|
-
}
|
|
35110
|
-
const argumentText = commandText.slice(matched.invocation.length).trimStart();
|
|
35111
|
-
return {
|
|
35112
|
-
descriptor: matched,
|
|
35113
|
-
...argumentText.length > 0 ? { arguments: { text: argumentText } } : {}
|
|
35114
|
-
};
|
|
35115
|
-
}
|
|
35116
|
-
|
|
35117
35441
|
// packages/host-runtime/src/live-command-catalog-cache.ts
|
|
35118
35442
|
import path26 from "node:path";
|
|
35119
35443
|
var MAX_ENTRIES = 64;
|
|
@@ -35145,7 +35469,7 @@ function sameWorkspace(left, right) {
|
|
|
35145
35469
|
}
|
|
35146
35470
|
|
|
35147
35471
|
// packages/host-runtime/src/harness-delegation-coordinator.ts
|
|
35148
|
-
import { createHash as createHash8, randomUUID as
|
|
35472
|
+
import { createHash as createHash8, randomUUID as randomUUID15 } from "node:crypto";
|
|
35149
35473
|
import path27 from "node:path";
|
|
35150
35474
|
|
|
35151
35475
|
// packages/host-runtime/src/delegation-snapshot.ts
|
|
@@ -35449,10 +35773,10 @@ var HarnessDelegationCoordinator = class {
|
|
|
35449
35773
|
});
|
|
35450
35774
|
this.#validateConfiguration(inspected.inspection, input.model, input.thinkingOptionId);
|
|
35451
35775
|
}
|
|
35452
|
-
const delegationId = hostThreadIdSchema.parse(
|
|
35453
|
-
const childThreadId = hostThreadIdSchema.parse(
|
|
35454
|
-
const turnId = hostTurnIdSchema.parse(
|
|
35455
|
-
const createRequestId = input.requestId ? `delegation:${input.requestId}` :
|
|
35776
|
+
const delegationId = hostThreadIdSchema.parse(randomUUID15());
|
|
35777
|
+
const childThreadId = hostThreadIdSchema.parse(randomUUID15());
|
|
35778
|
+
const turnId = hostTurnIdSchema.parse(randomUUID15());
|
|
35779
|
+
const createRequestId = input.requestId ? `delegation:${input.requestId}` : randomUUID15();
|
|
35456
35780
|
let record4 = await this.#repository.createProvisional(
|
|
35457
35781
|
createExternalThreadRecordInput({
|
|
35458
35782
|
hostThreadId: childThreadId,
|
|
@@ -35606,7 +35930,7 @@ var HarnessDelegationCoordinator = class {
|
|
|
35606
35930
|
if (this.#externalThreadBusy(thread) || thread.activeTurnId) {
|
|
35607
35931
|
throw new DelegationControlError("THREAD_BUSY", "Thread already has an active Turn");
|
|
35608
35932
|
}
|
|
35609
|
-
const turnId = hostTurnIdSchema.parse(
|
|
35933
|
+
const turnId = hostTurnIdSchema.parse(randomUUID15());
|
|
35610
35934
|
try {
|
|
35611
35935
|
await this.#startExternalTurn(thread, input.message, turnId);
|
|
35612
35936
|
} catch (error51) {
|
|
@@ -35880,8 +36204,8 @@ import { pathToFileURL } from "node:url";
|
|
|
35880
36204
|
function isNullable(value2) {
|
|
35881
36205
|
return value2 === null || value2 === void 0;
|
|
35882
36206
|
}
|
|
35883
|
-
function defineProperty(
|
|
35884
|
-
return Object.defineProperty(
|
|
36207
|
+
function defineProperty(object10, key, value2) {
|
|
36208
|
+
return Object.defineProperty(object10, key, {
|
|
35885
36209
|
writable: true,
|
|
35886
36210
|
value: value2,
|
|
35887
36211
|
enumerable: false
|
|
@@ -37420,8 +37744,8 @@ var Fiber = class {
|
|
|
37420
37744
|
});
|
|
37421
37745
|
}
|
|
37422
37746
|
};
|
|
37423
|
-
function isApplicable(
|
|
37424
|
-
return
|
|
37747
|
+
function isApplicable(object10) {
|
|
37748
|
+
return object10 && typeof object10 === "object" && typeof object10.apply === "function";
|
|
37425
37749
|
}
|
|
37426
37750
|
function Inject(name, config2) {
|
|
37427
37751
|
return function(value2, decorator) {
|
|
@@ -38256,10 +38580,10 @@ var SingleNativeCodexAccount = class {
|
|
|
38256
38580
|
};
|
|
38257
38581
|
|
|
38258
38582
|
// packages/host-runtime/src/codex-runtime/official-runtime-owner.ts
|
|
38259
|
-
import { randomUUID as
|
|
38583
|
+
import { randomUUID as randomUUID17 } from "node:crypto";
|
|
38260
38584
|
|
|
38261
38585
|
// packages/host-runtime/src/official-request-broker.ts
|
|
38262
|
-
import { randomUUID as
|
|
38586
|
+
import { randomUUID as randomUUID16 } from "node:crypto";
|
|
38263
38587
|
var INTERNAL_REQUEST_PREFIX = "codexhost:official:";
|
|
38264
38588
|
var MAX_RETIRED_IDS = 1024;
|
|
38265
38589
|
function isRecord17(value2) {
|
|
@@ -38275,7 +38599,7 @@ var OfficialRequestBroker = class {
|
|
|
38275
38599
|
constructor(input) {
|
|
38276
38600
|
this.#send = input.send;
|
|
38277
38601
|
this.#timeoutMs = input.timeoutMs ?? 3e4;
|
|
38278
|
-
this.#nextId = input.nextId ?? (() => `${INTERNAL_REQUEST_PREFIX}${
|
|
38602
|
+
this.#nextId = input.nextId ?? (() => `${INTERNAL_REQUEST_PREFIX}${randomUUID16()}`);
|
|
38279
38603
|
}
|
|
38280
38604
|
get pendingCount() {
|
|
38281
38605
|
return this.#pending.size;
|
|
@@ -38484,7 +38808,7 @@ var OfficialWorkGate = class {
|
|
|
38484
38808
|
};
|
|
38485
38809
|
|
|
38486
38810
|
// packages/host-runtime/src/codex-runtime/official-runtime-owner.ts
|
|
38487
|
-
var
|
|
38811
|
+
var object8 = (value2) => typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
|
|
38488
38812
|
var requestKey = (id2) => JSON.stringify([typeof id2, id2]);
|
|
38489
38813
|
var RESUME_FIELDS = /* @__PURE__ */ new Set([
|
|
38490
38814
|
"model",
|
|
@@ -38629,7 +38953,7 @@ var OfficialRuntimeOwner = class {
|
|
|
38629
38953
|
}
|
|
38630
38954
|
#attach(role, output, onBackendStopped) {
|
|
38631
38955
|
const client = {
|
|
38632
|
-
id:
|
|
38956
|
+
id: randomUUID17(),
|
|
38633
38957
|
role,
|
|
38634
38958
|
output,
|
|
38635
38959
|
...onBackendStopped ? { onBackendStopped } : {},
|
|
@@ -38749,7 +39073,7 @@ var OfficialRuntimeOwner = class {
|
|
|
38749
39073
|
if (value2.method === "initialized") return;
|
|
38750
39074
|
if (typeof value2.id !== "string" && typeof value2.id !== "number")
|
|
38751
39075
|
throw new Error("Official methods require a request ID");
|
|
38752
|
-
const params =
|
|
39076
|
+
const params = object8(value2.params) ? value2.params : {};
|
|
38753
39077
|
this.#checkMethod(value2.method);
|
|
38754
39078
|
const finish = this.gate.admit();
|
|
38755
39079
|
let pendingKey;
|
|
@@ -38784,10 +39108,10 @@ var OfficialRuntimeOwner = class {
|
|
|
38784
39108
|
if (!this.#clients.has(client) || event.generation !== this.#generation || !["running", "starting"].includes(this.#phase))
|
|
38785
39109
|
return;
|
|
38786
39110
|
const value2 = event.value;
|
|
38787
|
-
if (!
|
|
39111
|
+
if (!object8(value2)) return client.output(event);
|
|
38788
39112
|
if (typeof value2.id === "string" || typeof value2.id === "number") {
|
|
38789
39113
|
if (typeof value2.method === "string") {
|
|
38790
|
-
const id2 = `codexhost:server:${client.id}:${event.generation}:${
|
|
39114
|
+
const id2 = `codexhost:server:${client.id}:${event.generation}:${randomUUID17()}`;
|
|
38791
39115
|
client.serverRequests.set(id2, value2.id);
|
|
38792
39116
|
const projected = { ...value2, id: id2 };
|
|
38793
39117
|
return client.output({
|
|
@@ -38810,7 +39134,7 @@ var OfficialRuntimeOwner = class {
|
|
|
38810
39134
|
if (response.error) return;
|
|
38811
39135
|
if (["thread/archive", "thread/unsubscribe"].includes(method) && typeof params.threadId === "string")
|
|
38812
39136
|
client.threads.delete(params.threadId);
|
|
38813
|
-
if (!["thread/start", "thread/resume", "thread/fork"].includes(method) || !
|
|
39137
|
+
if (!["thread/start", "thread/resume", "thread/fork"].includes(method) || !object8(response.result) || !object8(response.result.thread))
|
|
38814
39138
|
return;
|
|
38815
39139
|
const id2 = response.result.thread.id;
|
|
38816
39140
|
if (typeof id2 !== "string") return;
|
|
@@ -38832,7 +39156,7 @@ var OfficialRuntimeOwner = class {
|
|
|
38832
39156
|
const restoring = (async () => {
|
|
38833
39157
|
const resume = subscription.params;
|
|
38834
39158
|
const response = await runtime.request("thread/resume", resume);
|
|
38835
|
-
if (response.error || !
|
|
39159
|
+
if (response.error || !object8(response.result) || !object8(response.result.thread) || response.result.thread.id !== params.threadId)
|
|
38836
39160
|
throw new Error("Official Thread restoration failed");
|
|
38837
39161
|
if (client.runtime !== runtime || runtime.generation !== this.#generation)
|
|
38838
39162
|
throw new OfficialAdmissionError("unavailable");
|
|
@@ -38980,16 +39304,16 @@ var OfficialRuntimeScope = class {
|
|
|
38980
39304
|
#scheduleRecovery() {
|
|
38981
39305
|
if (!this.#recovery || this.#closed || this.#recoveryTimer || this.#starting) return;
|
|
38982
39306
|
const { delaysMs } = this.#recovery;
|
|
38983
|
-
const
|
|
39307
|
+
const delay8 = delaysMs[Math.min(this.#recoveryAttempt, delaysMs.length - 1)] ?? 0;
|
|
38984
39308
|
this.#recoveryAttempt++;
|
|
38985
39309
|
this.#diagnosticOutput.write(
|
|
38986
|
-
`codexhost: official Codex is unavailable; restarting in ${String(
|
|
39310
|
+
`codexhost: official Codex is unavailable; restarting in ${String(delay8)}ms
|
|
38987
39311
|
`
|
|
38988
39312
|
);
|
|
38989
39313
|
const timer = setTimeout(() => {
|
|
38990
39314
|
this.#recoveryTimer = void 0;
|
|
38991
39315
|
this.start().catch(() => void 0);
|
|
38992
|
-
},
|
|
39316
|
+
}, delay8);
|
|
38993
39317
|
timer.unref();
|
|
38994
39318
|
this.#recoveryTimer = timer;
|
|
38995
39319
|
}
|
|
@@ -39739,13 +40063,106 @@ async function moveThreadSection(input) {
|
|
|
39739
40063
|
// packages/host-runtime/src/external-thread-official-defaults.ts
|
|
39740
40064
|
var EMPTY_RESULTS = /* @__PURE__ */ new Map([
|
|
39741
40065
|
["thread/attachment/list", () => ({ data: [], nextCursor: null })],
|
|
39742
|
-
["thread/queue/list", () => ({ data: [], nextCursor: null })],
|
|
39743
40066
|
["thread/settings/update", () => ({})]
|
|
39744
40067
|
]);
|
|
39745
40068
|
function externalThreadEmptyOfficialResult(method) {
|
|
39746
40069
|
return EMPTY_RESULTS.get(method)?.();
|
|
39747
40070
|
}
|
|
39748
40071
|
|
|
40072
|
+
// packages/host-runtime/src/external-thread-follow-up-queue.ts
|
|
40073
|
+
import { randomUUID as randomUUID18 } from "node:crypto";
|
|
40074
|
+
function isRecord20(value2) {
|
|
40075
|
+
return value2 !== null && typeof value2 === "object" && !Array.isArray(value2);
|
|
40076
|
+
}
|
|
40077
|
+
function queuedSubmissionText(input) {
|
|
40078
|
+
return input.filter(isRecord20).map((item) => item.text).filter((value2) => typeof value2 === "string" && value2.length > 0).join("\n");
|
|
40079
|
+
}
|
|
40080
|
+
function queuedSubmissionInput(input) {
|
|
40081
|
+
return input.map((entry) => {
|
|
40082
|
+
if (!isRecord20(entry) || typeof entry.text !== "string" || entry.text.length === 0) {
|
|
40083
|
+
return entry;
|
|
40084
|
+
}
|
|
40085
|
+
if (entry.type === "input_text") {
|
|
40086
|
+
return {
|
|
40087
|
+
type: "text",
|
|
40088
|
+
text: entry.text,
|
|
40089
|
+
text_elements: Array.isArray(entry.text_elements) ? entry.text_elements : []
|
|
40090
|
+
};
|
|
40091
|
+
}
|
|
40092
|
+
if (entry.type !== "text" || Array.isArray(entry.text_elements)) return entry;
|
|
40093
|
+
return { ...entry, text_elements: [] };
|
|
40094
|
+
});
|
|
40095
|
+
}
|
|
40096
|
+
var ExternalThreadFollowUpQueue = class {
|
|
40097
|
+
#threads = /* @__PURE__ */ new Map();
|
|
40098
|
+
list(threadId2) {
|
|
40099
|
+
return { data: [...this.#threads.get(threadId2) ?? []], nextCursor: null };
|
|
40100
|
+
}
|
|
40101
|
+
add(threadId2, input, clientUserMessageId) {
|
|
40102
|
+
const item = {
|
|
40103
|
+
id: randomUUID18(),
|
|
40104
|
+
clientUserMessageId: clientUserMessageId?.trim() || randomUUID18(),
|
|
40105
|
+
input: queuedSubmissionInput(input)
|
|
40106
|
+
};
|
|
40107
|
+
const items = this.#threads.get(threadId2) ?? [];
|
|
40108
|
+
items.push(item);
|
|
40109
|
+
this.#threads.set(threadId2, items);
|
|
40110
|
+
return item;
|
|
40111
|
+
}
|
|
40112
|
+
update(threadId2, id2, input) {
|
|
40113
|
+
const item = this.#threads.get(threadId2)?.find((entry) => entry.id === id2);
|
|
40114
|
+
if (!item) return void 0;
|
|
40115
|
+
item.input = queuedSubmissionInput(input);
|
|
40116
|
+
return item;
|
|
40117
|
+
}
|
|
40118
|
+
delete(threadId2, id2) {
|
|
40119
|
+
const items = this.#threads.get(threadId2);
|
|
40120
|
+
if (!items) return false;
|
|
40121
|
+
const next = items.filter((entry) => entry.id !== id2);
|
|
40122
|
+
if (next.length === items.length) return false;
|
|
40123
|
+
if (next.length === 0) this.#threads.delete(threadId2);
|
|
40124
|
+
else this.#threads.set(threadId2, next);
|
|
40125
|
+
return true;
|
|
40126
|
+
}
|
|
40127
|
+
reorder(threadId2, ids) {
|
|
40128
|
+
const items = this.#threads.get(threadId2);
|
|
40129
|
+
if (!items) return false;
|
|
40130
|
+
const remaining = new Map(items.map((entry) => [entry.id, entry]));
|
|
40131
|
+
const next = [];
|
|
40132
|
+
for (const id2 of ids) {
|
|
40133
|
+
const item = remaining.get(id2);
|
|
40134
|
+
if (!item) return false;
|
|
40135
|
+
next.push(item);
|
|
40136
|
+
remaining.delete(id2);
|
|
40137
|
+
}
|
|
40138
|
+
next.push(...remaining.values());
|
|
40139
|
+
this.#threads.set(threadId2, next);
|
|
40140
|
+
return true;
|
|
40141
|
+
}
|
|
40142
|
+
peek(threadId2, id2) {
|
|
40143
|
+
const items = this.#threads.get(threadId2);
|
|
40144
|
+
if (!items?.length) return void 0;
|
|
40145
|
+
return id2 ? items.find((entry) => this.#matches(entry, id2)) : items[0];
|
|
40146
|
+
}
|
|
40147
|
+
take(threadId2, id2) {
|
|
40148
|
+
const items = this.#threads.get(threadId2);
|
|
40149
|
+
if (!items?.length) return void 0;
|
|
40150
|
+
const index = id2 ? items.findIndex((entry) => this.#matches(entry, id2)) : 0;
|
|
40151
|
+
if (index < 0) return void 0;
|
|
40152
|
+
const [item] = items.splice(index, 1);
|
|
40153
|
+
if (items.length === 0) this.#threads.delete(threadId2);
|
|
40154
|
+
return item;
|
|
40155
|
+
}
|
|
40156
|
+
restore(threadId2, item) {
|
|
40157
|
+
const items = this.#threads.get(threadId2) ?? [];
|
|
40158
|
+
items.unshift(item);
|
|
40159
|
+
this.#threads.set(threadId2, items);
|
|
40160
|
+
}
|
|
40161
|
+
#matches(entry, id2) {
|
|
40162
|
+
return entry.id === id2 || entry.clientUserMessageId === id2;
|
|
40163
|
+
}
|
|
40164
|
+
};
|
|
40165
|
+
|
|
39749
40166
|
// packages/host-runtime/src/observed-session-usage.ts
|
|
39750
40167
|
var ObservedSessionUsage = class {
|
|
39751
40168
|
constructor(providers, prices, diagnose) {
|
|
@@ -39905,14 +40322,14 @@ var THREAD_USAGE_UPDATED_METHOD = "codexhost/thread/usage/updated";
|
|
|
39905
40322
|
function delay5(milliseconds) {
|
|
39906
40323
|
return new Promise((resolve) => setTimeout(resolve, milliseconds));
|
|
39907
40324
|
}
|
|
39908
|
-
function
|
|
40325
|
+
function isRecord21(value2) {
|
|
39909
40326
|
return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
|
|
39910
40327
|
}
|
|
39911
40328
|
function officialThreadBusy(thread) {
|
|
39912
|
-
if (thread &&
|
|
40329
|
+
if (thread && isRecord21(thread.status) && thread.status.type === "active") return true;
|
|
39913
40330
|
const turns = thread && Array.isArray(thread.turns) ? thread.turns : [];
|
|
39914
40331
|
const latestTurn = turns.at(-1);
|
|
39915
|
-
return
|
|
40332
|
+
return isRecord21(latestTurn) && (latestTurn.status === "inProgress" || latestTurn.status === "running");
|
|
39916
40333
|
}
|
|
39917
40334
|
function errorMessage4(error51) {
|
|
39918
40335
|
return error51 instanceof Error ? error51.message : String(error51);
|
|
@@ -40019,15 +40436,15 @@ function classifyCreateRequestRoute(request) {
|
|
|
40019
40436
|
};
|
|
40020
40437
|
}
|
|
40021
40438
|
function routingParams(request) {
|
|
40022
|
-
return
|
|
40439
|
+
return isRecord21(request.params) ? request.params : {};
|
|
40023
40440
|
}
|
|
40024
40441
|
function requestObject(request) {
|
|
40025
|
-
if (!
|
|
40442
|
+
if (!isRecord21(request.params)) throw new Error(`${request.method} params must be an object`);
|
|
40026
40443
|
return request.params;
|
|
40027
40444
|
}
|
|
40028
40445
|
function requestText(params) {
|
|
40029
40446
|
if (!Array.isArray(params.input)) throw new Error("turn/start input must be an array");
|
|
40030
|
-
const text = params.input
|
|
40447
|
+
const text = queuedSubmissionText(params.input);
|
|
40031
40448
|
if (!text) throw new Error("turn/start must contain text input");
|
|
40032
40449
|
return text;
|
|
40033
40450
|
}
|
|
@@ -40075,10 +40492,12 @@ var AppServerHost = class {
|
|
|
40075
40492
|
#plugins;
|
|
40076
40493
|
#launchSettings;
|
|
40077
40494
|
#accountInspections = new HarnessAccountInspectionCache();
|
|
40495
|
+
#installationTasks = new HarnessInstallationTasks();
|
|
40078
40496
|
#externalRuntime;
|
|
40079
40497
|
#executionHosts = /* @__PURE__ */ new WeakMap();
|
|
40080
40498
|
#externalPrewarms = new ExternalThreadPrewarms();
|
|
40081
40499
|
#externalSteering = new ExternalTurnSteering();
|
|
40500
|
+
#followUps = new ExternalThreadFollowUpQueue();
|
|
40082
40501
|
#nativeVoiceGateway;
|
|
40083
40502
|
#externalVoice;
|
|
40084
40503
|
#externalVoiceResults = new ExternalVoiceResults(
|
|
@@ -40110,7 +40529,7 @@ var AppServerHost = class {
|
|
|
40110
40529
|
#sectionMoves = Promise.resolve();
|
|
40111
40530
|
#writer;
|
|
40112
40531
|
/** Console requests share Desktop handling; their replies return to the console. */
|
|
40113
|
-
#consoleRequestPrefix = `codexhost-console:${
|
|
40532
|
+
#consoleRequestPrefix = `codexhost-console:${randomUUID19()}:`;
|
|
40114
40533
|
#consoleReplies = /* @__PURE__ */ new Map();
|
|
40115
40534
|
#nextConsoleRequest = 0;
|
|
40116
40535
|
#subagentThreadStatuses = /* @__PURE__ */ new Map();
|
|
@@ -40468,19 +40887,19 @@ var AppServerHost = class {
|
|
|
40468
40887
|
for (const resolve of waiters) resolve();
|
|
40469
40888
|
}
|
|
40470
40889
|
#observeOfficialTurnStartResponse(value2) {
|
|
40471
|
-
if (!
|
|
40890
|
+
if (!isRecord21(value2) || !("id" in value2)) return;
|
|
40472
40891
|
const threadId2 = this.#pendingOfficialTurnStarts.get(value2.id);
|
|
40473
40892
|
if (!threadId2) return;
|
|
40474
40893
|
this.#pendingOfficialTurnStarts.delete(value2.id);
|
|
40475
|
-
const result =
|
|
40476
|
-
const turn = result &&
|
|
40894
|
+
const result = isRecord21(value2.result) ? value2.result : null;
|
|
40895
|
+
const turn = result && isRecord21(result.turn) ? result.turn : null;
|
|
40477
40896
|
if (turn && typeof turn.id === "string") {
|
|
40478
40897
|
this.#activeOfficialTurns.set(threadId2, turn.id);
|
|
40479
40898
|
}
|
|
40480
40899
|
this.#signalActiveWorkChanged();
|
|
40481
40900
|
}
|
|
40482
40901
|
#takeConsoleReply(value2) {
|
|
40483
|
-
if (!
|
|
40902
|
+
if (!isRecord21(value2) || typeof value2.id !== "string") return false;
|
|
40484
40903
|
const reply2 = this.#consoleReplies.get(value2.id);
|
|
40485
40904
|
if (!reply2) return false;
|
|
40486
40905
|
this.#consoleReplies.delete(value2.id);
|
|
@@ -40526,10 +40945,10 @@ var AppServerHost = class {
|
|
|
40526
40945
|
);
|
|
40527
40946
|
try {
|
|
40528
40947
|
const message2 = await reply2;
|
|
40529
|
-
if (
|
|
40948
|
+
if (isRecord21(message2) && "result" in message2) {
|
|
40530
40949
|
return { result: message2.result ?? null };
|
|
40531
40950
|
}
|
|
40532
|
-
const error51 =
|
|
40951
|
+
const error51 = isRecord21(message2) && isRecord21(message2.error) ? message2.error : void 0;
|
|
40533
40952
|
return {
|
|
40534
40953
|
error: {
|
|
40535
40954
|
code: typeof error51?.code === "number" ? error51.code : -32603,
|
|
@@ -40555,7 +40974,7 @@ var AppServerHost = class {
|
|
|
40555
40974
|
this.#diagnose(error51);
|
|
40556
40975
|
continue;
|
|
40557
40976
|
}
|
|
40558
|
-
if (
|
|
40977
|
+
if (isRecord21(parsed2) && parsed2.method === "initialized" && !("id" in parsed2)) {
|
|
40559
40978
|
continue;
|
|
40560
40979
|
}
|
|
40561
40980
|
if (await this.#handleDesktopApprovalResponse(parsed2)) continue;
|
|
@@ -40577,7 +40996,7 @@ var AppServerHost = class {
|
|
|
40577
40996
|
const options2 = this.#observedSessionUsage.requestOptions("initialize", params);
|
|
40578
40997
|
const nativeParams = options2 ? { ...params, ...options2 } : params;
|
|
40579
40998
|
const response = await this.#officialRuntime.initializeProtocol(nativeParams);
|
|
40580
|
-
if (!
|
|
40999
|
+
if (!isRecord21(response.error)) this.#observedSessionUsage.initialized(nativeParams);
|
|
40581
41000
|
await this.#writer.json({ ...response, id: request.id });
|
|
40582
41001
|
this.#nativeAccountObserver?.initialized(nativeGeneration);
|
|
40583
41002
|
} catch (error51) {
|
|
@@ -40585,7 +41004,7 @@ var AppServerHost = class {
|
|
|
40585
41004
|
}
|
|
40586
41005
|
continue;
|
|
40587
41006
|
}
|
|
40588
|
-
const threadId2 =
|
|
41007
|
+
const threadId2 = isRecord21(request.params) && typeof request.params.threadId === "string" ? request.params.threadId : void 0;
|
|
40589
41008
|
this.#dispatchDesktopRequest(
|
|
40590
41009
|
() => this.#desktopRequests.run(
|
|
40591
41010
|
threadId2,
|
|
@@ -40633,7 +41052,7 @@ var AppServerHost = class {
|
|
|
40633
41052
|
for (const guard of this.#replyGuards.get(id2) ?? []) guard.answered = true;
|
|
40634
41053
|
}
|
|
40635
41054
|
#noteDesktopReply(value2) {
|
|
40636
|
-
if (
|
|
41055
|
+
if (isRecord21(value2) && "id" in value2 && !("method" in value2)) {
|
|
40637
41056
|
this.#markDesktopRequestAnswered(value2.id);
|
|
40638
41057
|
}
|
|
40639
41058
|
}
|
|
@@ -40948,11 +41367,11 @@ var AppServerHost = class {
|
|
|
40948
41367
|
this.#dispatchDesktopReply(request, () => this.#inspectHarness(request));
|
|
40949
41368
|
return;
|
|
40950
41369
|
}
|
|
40951
|
-
if (request.method === HARNESS_INSTALLATION_METHOD) {
|
|
41370
|
+
if (request.method === HARNESS_INSTALLATION_METHOD || request.method === HARNESS_INSTALLATION_START_METHOD || request.method === HARNESS_INSTALLATION_STATUS_METHOD) {
|
|
40952
41371
|
this.#dispatchDesktopReply(request, async () => {
|
|
40953
|
-
await this.#waitForPlugins();
|
|
40954
41372
|
try {
|
|
40955
|
-
|
|
41373
|
+
if (request.method !== HARNESS_INSTALLATION_STATUS_METHOD) await this.#waitForPlugins();
|
|
41374
|
+
const result = request.method === HARNESS_INSTALLATION_START_METHOD ? this.#installationTasks.start(request.params, this.#externalAdapters) : request.method === HARNESS_INSTALLATION_STATUS_METHOD ? this.#installationTasks.status(request.params) : await handleHarnessInstallation(request.params, this.#externalAdapters);
|
|
40956
41375
|
await this.#writer.json(rpcEnvelope(request, { result: jsonValueSchema.parse(result) }));
|
|
40957
41376
|
} catch (error51) {
|
|
40958
41377
|
await this.#writer.json(
|
|
@@ -41057,6 +41476,10 @@ var AppServerHost = class {
|
|
|
41057
41476
|
await this.#listThreadOwnership(request);
|
|
41058
41477
|
return;
|
|
41059
41478
|
}
|
|
41479
|
+
if (request.method === "codexhost/thread/steering/inspect") {
|
|
41480
|
+
await this.#inspectThreadSteering(request);
|
|
41481
|
+
return;
|
|
41482
|
+
}
|
|
41060
41483
|
if (request.method === "codexhost/thread/model/select") {
|
|
41061
41484
|
await this.#selectThreadModel(request);
|
|
41062
41485
|
return;
|
|
@@ -41208,7 +41631,7 @@ var AppServerHost = class {
|
|
|
41208
41631
|
return;
|
|
41209
41632
|
}
|
|
41210
41633
|
if (request.method === "thread/fork") {
|
|
41211
|
-
const params =
|
|
41634
|
+
const params = isRecord21(request.params) ? request.params : {};
|
|
41212
41635
|
const resolution = typeof params.threadId === "string" ? await this.#resolveExternalThread(params.threadId) : { kind: "official" };
|
|
41213
41636
|
if (resolution.kind === "error") {
|
|
41214
41637
|
await this.#writer.json(rpcError(request, resolution.error.code, resolution.error.message));
|
|
@@ -41229,7 +41652,7 @@ var AppServerHost = class {
|
|
|
41229
41652
|
}
|
|
41230
41653
|
}
|
|
41231
41654
|
if (request.method === "thread/revert") {
|
|
41232
|
-
const params =
|
|
41655
|
+
const params = isRecord21(request.params) ? request.params : {};
|
|
41233
41656
|
const resolution = typeof params.threadId === "string" ? await this.#resolveExternalThread(params.threadId) : { kind: "official" };
|
|
41234
41657
|
if (resolution.kind === "error") {
|
|
41235
41658
|
await this.#writer.json(rpcError(request, resolution.error.code, resolution.error.message));
|
|
@@ -41250,7 +41673,7 @@ var AppServerHost = class {
|
|
|
41250
41673
|
}
|
|
41251
41674
|
}
|
|
41252
41675
|
if (request.method === "thread/rollback") {
|
|
41253
|
-
const params =
|
|
41676
|
+
const params = isRecord21(request.params) ? request.params : {};
|
|
41254
41677
|
const resolution = typeof params.threadId === "string" ? await this.#resolveExternalThread(params.threadId) : { kind: "official" };
|
|
41255
41678
|
if (resolution.kind === "error") {
|
|
41256
41679
|
await this.#writer.json(rpcError(request, resolution.error.code, resolution.error.message));
|
|
@@ -41309,6 +41732,24 @@ var AppServerHost = class {
|
|
|
41309
41732
|
this.#pendingOfficialTurnStarts.set(request.id, threadId2);
|
|
41310
41733
|
}
|
|
41311
41734
|
}
|
|
41735
|
+
if (request.method.startsWith("thread/queue/")) {
|
|
41736
|
+
const params = routingParams(request);
|
|
41737
|
+
const threadId2 = params.threadId;
|
|
41738
|
+
const resolution = typeof threadId2 === "string" ? await this.#resolveExternalThread(threadId2) : { kind: "official" };
|
|
41739
|
+
if (await this.#writeResolutionError(request, resolution)) return;
|
|
41740
|
+
if (resolution.kind === "external") {
|
|
41741
|
+
if (request.method === "thread/queue/start") {
|
|
41742
|
+
this.#dispatchDesktopReply(
|
|
41743
|
+
request,
|
|
41744
|
+
() => this.#startExternalQueuedTurn(request, resolution.thread),
|
|
41745
|
+
resolution.thread.id
|
|
41746
|
+
);
|
|
41747
|
+
return;
|
|
41748
|
+
}
|
|
41749
|
+
await this.#handleExternalQueueMutation(request, resolution.thread);
|
|
41750
|
+
return;
|
|
41751
|
+
}
|
|
41752
|
+
}
|
|
41312
41753
|
if (request.method === "turn/steer") {
|
|
41313
41754
|
const params = routingParams(request);
|
|
41314
41755
|
const resolution = typeof params.threadId === "string" ? await this.#resolveExternalThread(params.threadId) : { kind: "official" };
|
|
@@ -41408,7 +41849,7 @@ var AppServerHost = class {
|
|
|
41408
41849
|
return;
|
|
41409
41850
|
}
|
|
41410
41851
|
}
|
|
41411
|
-
if (request.method === "thread/backgroundTerminals/clean" &&
|
|
41852
|
+
if (request.method === "thread/backgroundTerminals/clean" && isRecord21(request.params) && typeof request.params.threadId === "string") {
|
|
41412
41853
|
const location = await this.#locateExternalThread(request.params.threadId);
|
|
41413
41854
|
if (await this.#writeResolutionError(request, location)) return;
|
|
41414
41855
|
if (location.kind === "external") {
|
|
@@ -41416,7 +41857,7 @@ var AppServerHost = class {
|
|
|
41416
41857
|
return;
|
|
41417
41858
|
}
|
|
41418
41859
|
}
|
|
41419
|
-
if (request.method.startsWith("thread/realtime/") &&
|
|
41860
|
+
if (request.method.startsWith("thread/realtime/") && isRecord21(request.params) && typeof request.params.threadId === "string") {
|
|
41420
41861
|
const resolution = await this.#resolveExternalThread(request.params.threadId);
|
|
41421
41862
|
if (await this.#writeResolutionError(request, resolution)) return;
|
|
41422
41863
|
if (resolution.kind === "external") {
|
|
@@ -41428,7 +41869,7 @@ var AppServerHost = class {
|
|
|
41428
41869
|
return;
|
|
41429
41870
|
}
|
|
41430
41871
|
}
|
|
41431
|
-
if (request.method.startsWith("thread/") && !EXPLICIT_EXTERNAL_THREAD_METHODS.has(request.method) &&
|
|
41872
|
+
if (request.method.startsWith("thread/") && !EXPLICIT_EXTERNAL_THREAD_METHODS.has(request.method) && isRecord21(request.params) && typeof request.params.threadId === "string") {
|
|
41432
41873
|
const location = await this.#locateExternalThread(request.params.threadId);
|
|
41433
41874
|
if (await this.#writeResolutionError(request, location)) return;
|
|
41434
41875
|
if (location.kind === "external") {
|
|
@@ -41447,10 +41888,10 @@ var AppServerHost = class {
|
|
|
41447
41888
|
/** Native Codex Turns: turn `#` delegation chips into an explicit Skill-backed request. */
|
|
41448
41889
|
async #rewriteOfficialDelegationMentions(request, frame) {
|
|
41449
41890
|
if (request.method !== "turn/start" && request.method !== "turn/steer") return frame;
|
|
41450
|
-
if (!
|
|
41891
|
+
if (!isRecord21(request.params) || !Array.isArray(request.params.input)) return frame;
|
|
41451
41892
|
const input = request.params.input;
|
|
41452
41893
|
if (!input.some(
|
|
41453
|
-
(item) =>
|
|
41894
|
+
(item) => isRecord21(item) && typeof item.text === "string" && item.text.includes(DELEGATION_MENTION_PATH_PREFIX)
|
|
41454
41895
|
)) {
|
|
41455
41896
|
return frame;
|
|
41456
41897
|
}
|
|
@@ -41463,7 +41904,7 @@ var AppServerHost = class {
|
|
|
41463
41904
|
}
|
|
41464
41905
|
async #forwardOfficialNonRequest(value2, frame) {
|
|
41465
41906
|
if (this.#options.externalOnly) return;
|
|
41466
|
-
const response =
|
|
41907
|
+
const response = isRecord21(value2) ? value2 : null;
|
|
41467
41908
|
const request = response && (typeof response.id === "string" || typeof response.id === "number") ? this.#officialServerRequests.get(response.id) : null;
|
|
41468
41909
|
if (request !== void 0 && response) {
|
|
41469
41910
|
this.#officialServerRequests.delete(response.id);
|
|
@@ -41483,13 +41924,13 @@ var AppServerHost = class {
|
|
|
41483
41924
|
return;
|
|
41484
41925
|
}
|
|
41485
41926
|
try {
|
|
41486
|
-
const options2 =
|
|
41927
|
+
const options2 = isRecord21(request.params) ? this.#observedSessionUsage.requestOptions(request.method, request.params) : null;
|
|
41487
41928
|
if (options2) {
|
|
41488
41929
|
const original = parseJsonFrame(frame);
|
|
41489
|
-
if (
|
|
41930
|
+
if (isRecord21(original))
|
|
41490
41931
|
frame = encodeJsonFrame({
|
|
41491
41932
|
...original,
|
|
41492
|
-
params: { ...
|
|
41933
|
+
params: { ...isRecord21(original.params) ? original.params : {}, ...options2 }
|
|
41493
41934
|
});
|
|
41494
41935
|
}
|
|
41495
41936
|
await this.#officialRuntime.sendFrame(frame);
|
|
@@ -41513,7 +41954,7 @@ var AppServerHost = class {
|
|
|
41513
41954
|
const observedAtMs = Date.now();
|
|
41514
41955
|
this.#observeOfficialTurnStartResponse(parsed2);
|
|
41515
41956
|
let forwarded = parsed2;
|
|
41516
|
-
if (
|
|
41957
|
+
if (isRecord21(parsed2) && typeof parsed2.method === "string" && "id" in parsed2) {
|
|
41517
41958
|
const originalId = parsed2.id;
|
|
41518
41959
|
if (typeof originalId === "string" || typeof originalId === "number") {
|
|
41519
41960
|
const forwardedId = `codexhost:official:${++this.#nextOfficialServerRequestId}`;
|
|
@@ -41521,7 +41962,7 @@ var AppServerHost = class {
|
|
|
41521
41962
|
forwarded = { ...parsed2, id: forwardedId };
|
|
41522
41963
|
}
|
|
41523
41964
|
}
|
|
41524
|
-
const accountScopedNotification =
|
|
41965
|
+
const accountScopedNotification = isRecord21(parsed2) && typeof parsed2.method === "string" && (parsed2.method === "account/updated" || parsed2.method.startsWith("account/rateLimits/"));
|
|
41525
41966
|
if (accountScopedNotification) {
|
|
41526
41967
|
if (parsed2.method === "account/updated") this.#officialRateLimits.reset(input.accountId);
|
|
41527
41968
|
}
|
|
@@ -41533,7 +41974,7 @@ var AppServerHost = class {
|
|
|
41533
41974
|
this.#diagnose(error51);
|
|
41534
41975
|
}
|
|
41535
41976
|
this.#routeObservationTracker.bindOfficialResponse(parsed2);
|
|
41536
|
-
const privateTelemetry =
|
|
41977
|
+
const privateTelemetry = isRecord21(parsed2) && typeof parsed2.method === "string" && !("id" in parsed2) && !this.#observedSessionUsage.shouldForwardNotification(parsed2);
|
|
41537
41978
|
if (!privateTelemetry) {
|
|
41538
41979
|
if (forwarded === parsed2) await this.#writer.frame(input.frame);
|
|
41539
41980
|
else await this.#writer.json(forwarded);
|
|
@@ -41599,10 +42040,10 @@ var AppServerHost = class {
|
|
|
41599
42040
|
}
|
|
41600
42041
|
}
|
|
41601
42042
|
async #observeOfficialTurnLifecycle(value2) {
|
|
41602
|
-
if (!
|
|
42043
|
+
if (!isRecord21(value2) || !isRecord21(value2.params)) return;
|
|
41603
42044
|
const params = value2.params;
|
|
41604
42045
|
if (value2.method === "turn/started" && typeof params.threadId === "string") {
|
|
41605
|
-
const turn =
|
|
42046
|
+
const turn = isRecord21(params.turn) ? params.turn : null;
|
|
41606
42047
|
if (turn && typeof turn.id === "string") {
|
|
41607
42048
|
this.#forgetPendingOfficialTurnStarts(params.threadId);
|
|
41608
42049
|
this.#activeOfficialTurns.set(params.threadId, turn.id);
|
|
@@ -41615,7 +42056,7 @@ var AppServerHost = class {
|
|
|
41615
42056
|
const delegation = await this.#repository.getDelegationByChild(
|
|
41616
42057
|
hostThreadIdSchema.parse(params.threadId)
|
|
41617
42058
|
);
|
|
41618
|
-
const turn =
|
|
42059
|
+
const turn = isRecord21(params.turn) ? params.turn : null;
|
|
41619
42060
|
const status2 = turn?.status === "failed" ? "failed" : turn?.status === "interrupted" || turn?.status === "cancelled" ? "interrupted" : "completed";
|
|
41620
42061
|
if (this.#pendingOfficialDelegationThreads.has(params.threadId)) {
|
|
41621
42062
|
this.#pendingOfficialTerminalStatuses.set(params.threadId, status2);
|
|
@@ -41648,9 +42089,9 @@ var AppServerHost = class {
|
|
|
41648
42089
|
}
|
|
41649
42090
|
async #readOfficialThreadMetadata(threadId2) {
|
|
41650
42091
|
const response = await this.#requestOfficial("thread/read", { threadId: threadId2, includeTurns: false });
|
|
41651
|
-
if (
|
|
41652
|
-
const result =
|
|
41653
|
-
const thread = result &&
|
|
42092
|
+
if (isRecord21(response.error)) return {};
|
|
42093
|
+
const result = isRecord21(response.result) ? response.result : null;
|
|
42094
|
+
const thread = result && isRecord21(result.thread) ? result.thread : null;
|
|
41654
42095
|
if (!thread) return {};
|
|
41655
42096
|
const title = typeof thread.name === "string" && thread.name.trim() ? thread.name : thread.preview;
|
|
41656
42097
|
return {
|
|
@@ -41660,21 +42101,21 @@ var AppServerHost = class {
|
|
|
41660
42101
|
}
|
|
41661
42102
|
async #inspectOfficialDelegationTarget(input) {
|
|
41662
42103
|
const response = await this.#requestOfficial("model/list", {});
|
|
41663
|
-
if (
|
|
42104
|
+
if (isRecord21(response.error)) {
|
|
41664
42105
|
throw new DelegationControlError(
|
|
41665
42106
|
"DELEGATION_FAILED",
|
|
41666
42107
|
typeof response.error.message === "string" ? response.error.message : "Official Model catalog could not be read"
|
|
41667
42108
|
);
|
|
41668
42109
|
}
|
|
41669
|
-
const result =
|
|
42110
|
+
const result = isRecord21(response.result) ? response.result : null;
|
|
41670
42111
|
const data = result && Array.isArray(result.data) ? result.data : [];
|
|
41671
42112
|
const thinkingById = /* @__PURE__ */ new Map();
|
|
41672
42113
|
const models = data.flatMap((candidate) => {
|
|
41673
|
-
if (!
|
|
42114
|
+
if (!isRecord21(candidate) || typeof candidate.model !== "string" || !candidate.model.trim()) {
|
|
41674
42115
|
return [];
|
|
41675
42116
|
}
|
|
41676
42117
|
const supportedThinkingOptionIds = Array.isArray(candidate.supportedReasoningEfforts) ? candidate.supportedReasoningEfforts.flatMap((option) => {
|
|
41677
|
-
if (!
|
|
42118
|
+
if (!isRecord21(option) || typeof option.reasoningEffort !== "string" || !option.reasoningEffort.trim()) {
|
|
41678
42119
|
return [];
|
|
41679
42120
|
}
|
|
41680
42121
|
const id2 = harnessThinkingOptionIdSchema.safeParse(option.reasoningEffort);
|
|
@@ -41694,9 +42135,9 @@ var AppServerHost = class {
|
|
|
41694
42135
|
];
|
|
41695
42136
|
});
|
|
41696
42137
|
const defaultEntry = data.find(
|
|
41697
|
-
(candidate) =>
|
|
42138
|
+
(candidate) => isRecord21(candidate) && candidate.isDefault === true
|
|
41698
42139
|
);
|
|
41699
|
-
const defaultModel =
|
|
42140
|
+
const defaultModel = isRecord21(defaultEntry) && typeof defaultEntry.model === "string" ? encodeOfficialCodexModelRef(defaultEntry.model) : void 0;
|
|
41700
42141
|
return {
|
|
41701
42142
|
harnessId: input.harnessId,
|
|
41702
42143
|
inspection: {
|
|
@@ -41802,8 +42243,8 @@ var AppServerHost = class {
|
|
|
41802
42243
|
ephemeral: false,
|
|
41803
42244
|
historyMode: "paginated"
|
|
41804
42245
|
});
|
|
41805
|
-
const startedResult =
|
|
41806
|
-
const thread = startedResult &&
|
|
42246
|
+
const startedResult = isRecord21(started.result) ? started.result : null;
|
|
42247
|
+
const thread = startedResult && isRecord21(startedResult.thread) ? startedResult.thread : null;
|
|
41807
42248
|
const threadId2 = thread && typeof thread.id === "string" ? thread.id : null;
|
|
41808
42249
|
if (!threadId2) throw new Error("Official thread/start returned no Thread identity");
|
|
41809
42250
|
this.#pendingOfficialDelegationThreads.add(threadId2);
|
|
@@ -41818,8 +42259,8 @@ var AppServerHost = class {
|
|
|
41818
42259
|
...nativeModelId ? { model: nativeModelId } : {},
|
|
41819
42260
|
...input.thinkingOptionId ? { effort: input.thinkingOptionId } : {}
|
|
41820
42261
|
});
|
|
41821
|
-
const turnResult =
|
|
41822
|
-
const turnValue = turnResult &&
|
|
42262
|
+
const turnResult = isRecord21(turn.result) ? turn.result : null;
|
|
42263
|
+
const turnValue = turnResult && isRecord21(turnResult.turn) ? turnResult.turn : null;
|
|
41823
42264
|
const parsedTurnId = turnValue && typeof turnValue.id === "string" ? turnValue.id : null;
|
|
41824
42265
|
if (!parsedTurnId) throw new Error("Official turn/start returned no Turn identity");
|
|
41825
42266
|
turnId = parsedTurnId;
|
|
@@ -41830,7 +42271,7 @@ var AppServerHost = class {
|
|
|
41830
42271
|
throw error51;
|
|
41831
42272
|
}
|
|
41832
42273
|
this.#activeOfficialTurns.set(threadId2, turnId);
|
|
41833
|
-
const delegationId = hostThreadIdSchema.parse(
|
|
42274
|
+
const delegationId = hostThreadIdSchema.parse(randomUUID19());
|
|
41834
42275
|
try {
|
|
41835
42276
|
const source = await this.#repository.find(input.parentThreadId);
|
|
41836
42277
|
const pendingTerminal = this.#pendingOfficialTerminalStatuses.get(threadId2);
|
|
@@ -41889,11 +42330,11 @@ var AppServerHost = class {
|
|
|
41889
42330
|
threadId: input.threadId,
|
|
41890
42331
|
includeTurns: true
|
|
41891
42332
|
});
|
|
41892
|
-
if (
|
|
41893
|
-
if (!
|
|
42333
|
+
if (isRecord21(current.error)) throw officialThreadReadError(current.error);
|
|
42334
|
+
if (!isRecord21(current.result)) {
|
|
41894
42335
|
throw new DelegationControlError("INTERNAL_ERROR", "Official Thread read returned no result");
|
|
41895
42336
|
}
|
|
41896
|
-
const currentThread =
|
|
42337
|
+
const currentThread = isRecord21(current.result.thread) ? current.result.thread : null;
|
|
41897
42338
|
if (officialThreadBusy(currentThread)) {
|
|
41898
42339
|
throw new DelegationControlError("THREAD_BUSY", "Thread already has an active Turn");
|
|
41899
42340
|
}
|
|
@@ -41901,14 +42342,14 @@ var AppServerHost = class {
|
|
|
41901
42342
|
threadId: input.threadId,
|
|
41902
42343
|
excludeTurns: true
|
|
41903
42344
|
});
|
|
41904
|
-
if (
|
|
42345
|
+
if (isRecord21(resumed.error) || !isRecord21(resumed.result)) {
|
|
41905
42346
|
throw new DelegationControlError(
|
|
41906
42347
|
"DELEGATION_FAILED",
|
|
41907
|
-
|
|
42348
|
+
isRecord21(resumed.error) && typeof resumed.error.message === "string" ? resumed.error.message : "Official Thread resume failed",
|
|
41908
42349
|
{ notStarted: true }
|
|
41909
42350
|
);
|
|
41910
42351
|
}
|
|
41911
|
-
const resumedThread =
|
|
42352
|
+
const resumedThread = isRecord21(resumed.result.thread) ? resumed.result.thread : null;
|
|
41912
42353
|
if (!resumedThread || resumedThread.id !== input.threadId) {
|
|
41913
42354
|
throw new DelegationControlError(
|
|
41914
42355
|
"DELEGATION_FAILED",
|
|
@@ -41919,7 +42360,7 @@ var AppServerHost = class {
|
|
|
41919
42360
|
if (officialThreadBusy(resumedThread)) {
|
|
41920
42361
|
throw new DelegationControlError("THREAD_BUSY", "Thread already has an active Turn");
|
|
41921
42362
|
}
|
|
41922
|
-
if (!
|
|
42363
|
+
if (!isRecord21(resumedThread.status) || resumedThread.status.type !== "idle") {
|
|
41923
42364
|
throw new DelegationControlError(
|
|
41924
42365
|
"DELEGATION_FAILED",
|
|
41925
42366
|
"Official Thread is not idle after resume",
|
|
@@ -41930,15 +42371,15 @@ var AppServerHost = class {
|
|
|
41930
42371
|
threadId: input.threadId,
|
|
41931
42372
|
input: [{ type: "text", text: input.message }]
|
|
41932
42373
|
});
|
|
41933
|
-
if (
|
|
42374
|
+
if (isRecord21(response.error)) {
|
|
41934
42375
|
throw new DelegationControlError(
|
|
41935
42376
|
"DELEGATION_FAILED",
|
|
41936
42377
|
typeof response.error.message === "string" ? response.error.message : "Turn start failed",
|
|
41937
42378
|
{ notStarted: true }
|
|
41938
42379
|
);
|
|
41939
42380
|
}
|
|
41940
|
-
const result =
|
|
41941
|
-
const turn = result &&
|
|
42381
|
+
const result = isRecord21(response.result) ? response.result : null;
|
|
42382
|
+
const turn = result && isRecord21(result.turn) ? result.turn : null;
|
|
41942
42383
|
const turnId = turn && typeof turn.id === "string" ? turn.id : null;
|
|
41943
42384
|
if (!turnId) throw new Error("Official turn/start returned no Turn identity");
|
|
41944
42385
|
this.#activeOfficialTurns.set(input.threadId, turnId);
|
|
@@ -41960,13 +42401,13 @@ var AppServerHost = class {
|
|
|
41960
42401
|
threadId: input.threadId,
|
|
41961
42402
|
includeTurns: true
|
|
41962
42403
|
});
|
|
41963
|
-
if (
|
|
42404
|
+
if (isRecord21(current.error) || !isRecord21(current.result)) {
|
|
41964
42405
|
throw new DelegationControlError("THREAD_NOT_FOUND", "Official Thread was not found");
|
|
41965
42406
|
}
|
|
41966
|
-
const currentThread =
|
|
42407
|
+
const currentThread = isRecord21(current.result.thread) ? current.result.thread : null;
|
|
41967
42408
|
const currentTurns = currentThread && Array.isArray(currentThread.turns) ? currentThread.turns : [];
|
|
41968
42409
|
const latestTurn = currentTurns.at(-1);
|
|
41969
|
-
if (
|
|
42410
|
+
if (isRecord21(latestTurn) && typeof latestTurn.id === "string" && (latestTurn.status === "inProgress" || latestTurn.status === "running")) {
|
|
41970
42411
|
turnId = latestTurn.id;
|
|
41971
42412
|
this.#activeOfficialTurns.set(input.threadId, turnId);
|
|
41972
42413
|
} else {
|
|
@@ -41977,7 +42418,7 @@ var AppServerHost = class {
|
|
|
41977
42418
|
threadId: input.threadId,
|
|
41978
42419
|
turnId
|
|
41979
42420
|
});
|
|
41980
|
-
if (
|
|
42421
|
+
if (isRecord21(response.error)) {
|
|
41981
42422
|
throw new DelegationControlError(
|
|
41982
42423
|
"DELEGATION_FAILED",
|
|
41983
42424
|
typeof response.error.message === "string" ? response.error.message : "Turn cancel failed"
|
|
@@ -41990,13 +42431,13 @@ var AppServerHost = class {
|
|
|
41990
42431
|
threadId: input.threadId,
|
|
41991
42432
|
includeTurns: true
|
|
41992
42433
|
});
|
|
41993
|
-
if (
|
|
41994
|
-
const result =
|
|
41995
|
-
const thread = result &&
|
|
42434
|
+
if (isRecord21(response.error)) throw officialThreadReadError(response.error);
|
|
42435
|
+
const result = isRecord21(response.result) ? response.result : null;
|
|
42436
|
+
const thread = result && isRecord21(result.thread) ? result.thread : null;
|
|
41996
42437
|
if (!thread)
|
|
41997
42438
|
throw new DelegationControlError("INTERNAL_ERROR", "Official Thread read returned no Thread");
|
|
41998
|
-
const turns = Array.isArray(thread.turns) ? thread.turns.filter((turn) =>
|
|
41999
|
-
const running = this.#activeOfficialTurns.has(input.threadId) ||
|
|
42439
|
+
const turns = Array.isArray(thread.turns) ? thread.turns.filter((turn) => isRecord21(turn)) : [];
|
|
42440
|
+
const running = this.#activeOfficialTurns.has(input.threadId) || isRecord21(thread.status) && thread.status.type === "active";
|
|
42000
42441
|
const snapshot2 = projectDelegationThreadSnapshot({
|
|
42001
42442
|
threadId: input.threadId,
|
|
42002
42443
|
harnessId: "codex",
|
|
@@ -42018,7 +42459,7 @@ var AppServerHost = class {
|
|
|
42018
42459
|
async #listDelegationThreads(input) {
|
|
42019
42460
|
const [sortKey, sortDirection2] = input.sort.split("-");
|
|
42020
42461
|
const request = {
|
|
42021
|
-
id: `codexhost:delegation-list:${
|
|
42462
|
+
id: `codexhost:delegation-list:${randomUUID19()}`,
|
|
42022
42463
|
method: "thread/list",
|
|
42023
42464
|
params: {
|
|
42024
42465
|
cwd: input.cwd ? [input.cwd] : null,
|
|
@@ -42044,7 +42485,7 @@ var AppServerHost = class {
|
|
|
42044
42485
|
threads: result.data.flatMap((entry) => {
|
|
42045
42486
|
if (typeof entry.id !== "string") return [];
|
|
42046
42487
|
const record4 = records.find((candidate) => candidate.hostThreadId === entry.id);
|
|
42047
|
-
const status2 =
|
|
42488
|
+
const status2 = isRecord21(entry.status) && entry.status.type === "active" ? "running" : "completed";
|
|
42048
42489
|
return [
|
|
42049
42490
|
{
|
|
42050
42491
|
threadId: entry.id,
|
|
@@ -42211,7 +42652,7 @@ var AppServerHost = class {
|
|
|
42211
42652
|
const exists2 = await this.#requestOfficial("project/read", {
|
|
42212
42653
|
projectId: update.projectId
|
|
42213
42654
|
}).then(
|
|
42214
|
-
(response) => !
|
|
42655
|
+
(response) => !isRecord21(response.error) && isRecord21(response.result) && isRecord21(response.result.project) && response.result.project.id === update.projectId,
|
|
42215
42656
|
() => false
|
|
42216
42657
|
);
|
|
42217
42658
|
if (!exists2) {
|
|
@@ -42561,6 +43002,28 @@ var AppServerHost = class {
|
|
|
42561
43002
|
);
|
|
42562
43003
|
}
|
|
42563
43004
|
}
|
|
43005
|
+
/** Read the same delivery decision that Desktop `turn/steer` will follow. */
|
|
43006
|
+
async #inspectThreadSteering(request) {
|
|
43007
|
+
const params = threadSteeringInspectParamsSchema.safeParse(request.params);
|
|
43008
|
+
if (!params.success) {
|
|
43009
|
+
await this.#writer.json(rpcError(request, -32602, "Invalid Thread steering params"));
|
|
43010
|
+
return;
|
|
43011
|
+
}
|
|
43012
|
+
let delivery;
|
|
43013
|
+
try {
|
|
43014
|
+
const location = await this.#locateExternalThread(params.data.threadId);
|
|
43015
|
+
if (await this.#writeResolutionError(request, location)) return;
|
|
43016
|
+
const thread = location.kind === "external" ? this.#externalRuntime.get(params.data.threadId) : void 0;
|
|
43017
|
+
delivery = location.kind !== "external" ? "official" : thread ? await externalSteeringDelivery(thread, params.data.text) : "newTurn";
|
|
43018
|
+
} catch {
|
|
43019
|
+
await this.#writer.json(
|
|
43020
|
+
rpcError(request, -32081, "Thread steering metadata could not be read")
|
|
43021
|
+
);
|
|
43022
|
+
return;
|
|
43023
|
+
}
|
|
43024
|
+
const result = threadSteeringInspectResultSchema.parse({ delivery });
|
|
43025
|
+
await this.#writer.json(rpcEnvelope(request, { result: jsonValueSchema.parse(result) }));
|
|
43026
|
+
}
|
|
42564
43027
|
async #inspectThreadCommands(request) {
|
|
42565
43028
|
const params = threadCommandsInspectParamsSchema.safeParse(request.params);
|
|
42566
43029
|
if (!params.success) {
|
|
@@ -42724,7 +43187,7 @@ var AppServerHost = class {
|
|
|
42724
43187
|
if (thread.running || thread.activeTurnId) {
|
|
42725
43188
|
throw new ExternalCommandError(-32072, "External Thread already has an active operation");
|
|
42726
43189
|
}
|
|
42727
|
-
const turnId = requestedTurnId ?? hostTurnIdSchema.parse(
|
|
43190
|
+
const turnId = requestedTurnId ?? hostTurnIdSchema.parse(randomUUID19());
|
|
42728
43191
|
const projection = {
|
|
42729
43192
|
projector: new CodexTurnProjector({
|
|
42730
43193
|
threadId: thread.id,
|
|
@@ -43161,9 +43624,20 @@ var AppServerHost = class {
|
|
|
43161
43624
|
await this.#writer.json(rpcError(request, resolution.error.code, resolution.error.message));
|
|
43162
43625
|
return true;
|
|
43163
43626
|
}
|
|
43627
|
+
/** Refresh history before Desktop acts on native Turn boundaries. */
|
|
43164
43628
|
#refreshExternalThread(thread) {
|
|
43165
43629
|
return this.#externalRuntime.refresh(thread);
|
|
43166
43630
|
}
|
|
43631
|
+
#markExternalHistoryRead(thread, turns) {
|
|
43632
|
+
if (!thread.historyHydrated) return;
|
|
43633
|
+
for (const turnId of thread.steeredTurnIds) {
|
|
43634
|
+
if (turnId !== thread.activeTurnId && turns.some(
|
|
43635
|
+
(turn) => turn.id === turnId && (turn.status === "completed" || turn.status === "failed" || turn.status === "interrupted")
|
|
43636
|
+
)) {
|
|
43637
|
+
thread.steeredTurnIds.delete(turnId);
|
|
43638
|
+
}
|
|
43639
|
+
}
|
|
43640
|
+
}
|
|
43167
43641
|
#persistTerminalIdentity(thread, event) {
|
|
43168
43642
|
return this.#externalRuntime.persistTerminalIdentity(thread, event);
|
|
43169
43643
|
}
|
|
@@ -43363,17 +43837,19 @@ var AppServerHost = class {
|
|
|
43363
43837
|
return;
|
|
43364
43838
|
}
|
|
43365
43839
|
}
|
|
43840
|
+
const readTurns = includeTurns ? [...this.#externalHistoryTurns(thread)] : [];
|
|
43366
43841
|
await this.#writer.json(
|
|
43367
43842
|
rpcEnvelope(request, {
|
|
43368
43843
|
result: {
|
|
43369
43844
|
thread: {
|
|
43370
43845
|
...thread.thread,
|
|
43371
43846
|
...await this.#externalSectionFields(thread.record.hostThreadId),
|
|
43372
|
-
turns:
|
|
43847
|
+
turns: readTurns
|
|
43373
43848
|
}
|
|
43374
43849
|
}
|
|
43375
43850
|
})
|
|
43376
43851
|
);
|
|
43852
|
+
if (includeTurns) this.#markExternalHistoryRead(thread, readTurns);
|
|
43377
43853
|
await this.#replayExternalUsage(thread);
|
|
43378
43854
|
}
|
|
43379
43855
|
async #listExternalHistory(request, thread, params, historyFresh) {
|
|
@@ -43390,6 +43866,9 @@ var AppServerHost = class {
|
|
|
43390
43866
|
const turns = this.#externalHistoryTurns(thread);
|
|
43391
43867
|
const result = request.method === "thread/turns/list" ? listExternalTurns(turns, params) : listExternalItems(turns, params);
|
|
43392
43868
|
await this.#writer.json(rpcEnvelope(request, { result }));
|
|
43869
|
+
if (request.method === "thread/turns/list") {
|
|
43870
|
+
this.#markExternalHistoryRead(thread, result.data);
|
|
43871
|
+
}
|
|
43393
43872
|
} catch (error51) {
|
|
43394
43873
|
await this.#writer.json(
|
|
43395
43874
|
rpcError(
|
|
@@ -43408,7 +43887,7 @@ var AppServerHost = class {
|
|
|
43408
43887
|
return;
|
|
43409
43888
|
}
|
|
43410
43889
|
}
|
|
43411
|
-
const turns = this.#externalHistoryTurns(thread);
|
|
43890
|
+
const turns = [...this.#externalHistoryTurns(thread)];
|
|
43412
43891
|
const responseThread = {
|
|
43413
43892
|
...await this.#withExternalSection(thread.thread),
|
|
43414
43893
|
turns: params.excludeTurns === true ? [] : turns
|
|
@@ -43424,10 +43903,10 @@ var AppServerHost = class {
|
|
|
43424
43903
|
if (thread.record.subagent)
|
|
43425
43904
|
result.reasoningEffort = thread.record.subagentConfiguration?.reasoningEffort ?? null;
|
|
43426
43905
|
try {
|
|
43427
|
-
if (params.initialTurnsPage !== void 0 && params.initialTurnsPage !== null && !
|
|
43906
|
+
if (params.initialTurnsPage !== void 0 && params.initialTurnsPage !== null && !isRecord21(params.initialTurnsPage)) {
|
|
43428
43907
|
throw new ExternalHistoryRequestError("initialTurnsPage must be an object");
|
|
43429
43908
|
}
|
|
43430
|
-
const initialPageParams =
|
|
43909
|
+
const initialPageParams = isRecord21(params.initialTurnsPage) ? params.initialTurnsPage : null;
|
|
43431
43910
|
const initialTurnsPage = initialPageParams ? listExternalTurns(turns, initialPageParams) : null;
|
|
43432
43911
|
const paginated = thread.record.historyMode === "paginated";
|
|
43433
43912
|
const turnsBackwardsCursor = paginated ? listExternalTurns(turns, { limit: 1, itemsView: "notLoaded" }).backwardsCursor : null;
|
|
@@ -43442,6 +43921,8 @@ var AppServerHost = class {
|
|
|
43442
43921
|
}
|
|
43443
43922
|
})
|
|
43444
43923
|
);
|
|
43924
|
+
if (params.excludeTurns !== true) this.#markExternalHistoryRead(thread, turns);
|
|
43925
|
+
else if (initialTurnsPage) this.#markExternalHistoryRead(thread, initialTurnsPage.data);
|
|
43445
43926
|
} catch (error51) {
|
|
43446
43927
|
await this.#writer.json(
|
|
43447
43928
|
rpcError(
|
|
@@ -43566,6 +44047,117 @@ var AppServerHost = class {
|
|
|
43566
44047
|
(signal) => this.#externalVoiceResults.watch(threadId2, turnId, signal)
|
|
43567
44048
|
);
|
|
43568
44049
|
}
|
|
44050
|
+
async #notifyFollowUpQueueChanged(threadId2) {
|
|
44051
|
+
await this.#writer.json({
|
|
44052
|
+
method: "thread/queue/changed",
|
|
44053
|
+
params: { threadId: threadId2 }
|
|
44054
|
+
});
|
|
44055
|
+
}
|
|
44056
|
+
async #handleExternalQueueMutation(request, thread) {
|
|
44057
|
+
const params = requestObject(request);
|
|
44058
|
+
try {
|
|
44059
|
+
if (request.method === "thread/queue/list") {
|
|
44060
|
+
await this.#writer.json(rpcEnvelope(request, { result: this.#followUps.list(thread.id) }));
|
|
44061
|
+
return;
|
|
44062
|
+
}
|
|
44063
|
+
if (request.method === "thread/queue/add") {
|
|
44064
|
+
if (!Array.isArray(params.input))
|
|
44065
|
+
throw new Error("thread/queue/add input must be an array");
|
|
44066
|
+
const text = queuedSubmissionText(params.input);
|
|
44067
|
+
if (!text) throw new Error("thread/queue/add must contain text input");
|
|
44068
|
+
const queuedSubmission = this.#followUps.add(
|
|
44069
|
+
thread.id,
|
|
44070
|
+
params.input,
|
|
44071
|
+
typeof params.clientUserMessageId === "string" ? params.clientUserMessageId : void 0
|
|
44072
|
+
);
|
|
44073
|
+
await this.#writer.json(rpcEnvelope(request, { result: { queuedSubmission } }));
|
|
44074
|
+
await this.#notifyFollowUpQueueChanged(thread.id);
|
|
44075
|
+
return;
|
|
44076
|
+
}
|
|
44077
|
+
if (request.method === "thread/queue/update") {
|
|
44078
|
+
if (typeof params.queuedSubmissionId !== "string" || !Array.isArray(params.input)) {
|
|
44079
|
+
throw new Error("thread/queue/update requires queuedSubmissionId and input");
|
|
44080
|
+
}
|
|
44081
|
+
const queuedSubmission = this.#followUps.update(
|
|
44082
|
+
thread.id,
|
|
44083
|
+
params.queuedSubmissionId,
|
|
44084
|
+
params.input
|
|
44085
|
+
);
|
|
44086
|
+
if (!queuedSubmission) throw new Error("Queued follow-up was not found");
|
|
44087
|
+
await this.#writer.json(rpcEnvelope(request, { result: { queuedSubmission } }));
|
|
44088
|
+
await this.#notifyFollowUpQueueChanged(thread.id);
|
|
44089
|
+
return;
|
|
44090
|
+
}
|
|
44091
|
+
if (request.method === "thread/queue/delete") {
|
|
44092
|
+
if (typeof params.queuedSubmissionId !== "string") {
|
|
44093
|
+
throw new Error("thread/queue/delete requires queuedSubmissionId");
|
|
44094
|
+
}
|
|
44095
|
+
const deleted = this.#followUps.delete(thread.id, params.queuedSubmissionId);
|
|
44096
|
+
await this.#writer.json(rpcEnvelope(request, { result: { deleted } }));
|
|
44097
|
+
if (deleted) await this.#notifyFollowUpQueueChanged(thread.id);
|
|
44098
|
+
return;
|
|
44099
|
+
}
|
|
44100
|
+
if (request.method === "thread/queue/reorder") {
|
|
44101
|
+
if (!Array.isArray(params.queuedSubmissionIds) || params.queuedSubmissionIds.some((id2) => typeof id2 !== "string")) {
|
|
44102
|
+
throw new Error("thread/queue/reorder requires queuedSubmissionIds");
|
|
44103
|
+
}
|
|
44104
|
+
if (!this.#followUps.reorder(thread.id, params.queuedSubmissionIds)) {
|
|
44105
|
+
throw new Error("Queued follow-up order could not be applied");
|
|
44106
|
+
}
|
|
44107
|
+
await this.#writer.json(rpcEnvelope(request, { result: {} }));
|
|
44108
|
+
await this.#notifyFollowUpQueueChanged(thread.id);
|
|
44109
|
+
return;
|
|
44110
|
+
}
|
|
44111
|
+
await this.#writer.json(
|
|
44112
|
+
rpcError(request, -32076, `External Thread does not support ${request.method}`)
|
|
44113
|
+
);
|
|
44114
|
+
} catch (error51) {
|
|
44115
|
+
await this.#writer.json(rpcError(request, -32602, errorMessage4(error51)));
|
|
44116
|
+
}
|
|
44117
|
+
}
|
|
44118
|
+
async #startExternalFromFollowUp(request, thread, queued, sourceHostId) {
|
|
44119
|
+
const text = queuedSubmissionText(queued.input);
|
|
44120
|
+
if (!text) {
|
|
44121
|
+
this.#followUps.restore(thread.id, queued);
|
|
44122
|
+
await this.#writer.json(rpcError(request, -32602, "Queued follow-up was not found"));
|
|
44123
|
+
return;
|
|
44124
|
+
}
|
|
44125
|
+
await this.#notifyFollowUpQueueChanged(thread.id);
|
|
44126
|
+
try {
|
|
44127
|
+
const started = await this.#beginExternalInputTurn(
|
|
44128
|
+
thread,
|
|
44129
|
+
text,
|
|
44130
|
+
void 0,
|
|
44131
|
+
queued.clientUserMessageId,
|
|
44132
|
+
sourceHostId
|
|
44133
|
+
);
|
|
44134
|
+
try {
|
|
44135
|
+
await this.#writer.json(rpcEnvelope(request, { result: { turn: started.turn } }));
|
|
44136
|
+
} finally {
|
|
44137
|
+
started.gate.resolve();
|
|
44138
|
+
}
|
|
44139
|
+
} catch (error51) {
|
|
44140
|
+
this.#followUps.restore(thread.id, queued);
|
|
44141
|
+
await this.#notifyFollowUpQueueChanged(thread.id);
|
|
44142
|
+
await this.#writer.json(
|
|
44143
|
+
rpcError(
|
|
44144
|
+
request,
|
|
44145
|
+
error51 instanceof ExternalSteerError || error51 instanceof ExternalCommandError ? error51.code : -32073,
|
|
44146
|
+
errorMessage4(error51)
|
|
44147
|
+
)
|
|
44148
|
+
);
|
|
44149
|
+
}
|
|
44150
|
+
}
|
|
44151
|
+
async #startExternalQueuedTurn(request, thread) {
|
|
44152
|
+
const params = requestObject(request);
|
|
44153
|
+
const queuedSubmissionId = typeof params.queuedSubmissionId === "string" ? params.queuedSubmissionId : void 0;
|
|
44154
|
+
const queued = this.#followUps.take(thread.id, queuedSubmissionId);
|
|
44155
|
+
if (!queued) {
|
|
44156
|
+
await this.#writer.json(rpcError(request, -32602, "Queued follow-up was not found"));
|
|
44157
|
+
return;
|
|
44158
|
+
}
|
|
44159
|
+
await this.#startExternalFromFollowUp(request, thread, queued);
|
|
44160
|
+
}
|
|
43569
44161
|
async #startExternalTurn(request, thread) {
|
|
43570
44162
|
if (this.#externalThreadBusy(thread) || this.#pendingExternalCommandRequests.has(thread.id)) {
|
|
43571
44163
|
await this.#writer.json(
|
|
@@ -43590,10 +44182,21 @@ var AppServerHost = class {
|
|
|
43590
44182
|
}
|
|
43591
44183
|
}
|
|
43592
44184
|
let text;
|
|
44185
|
+
const clientUserMessageId = typeof params.clientUserMessageId === "string" ? params.clientUserMessageId : void 0;
|
|
43593
44186
|
try {
|
|
43594
44187
|
text = requestText(params);
|
|
43595
44188
|
} catch (error51) {
|
|
43596
|
-
|
|
44189
|
+
const queued = this.#followUps.take(thread.id, clientUserMessageId) ?? this.#followUps.take(thread.id);
|
|
44190
|
+
if (!queued) {
|
|
44191
|
+
await this.#writer.json(rpcError(request, -32602, errorMessage4(error51)));
|
|
44192
|
+
return;
|
|
44193
|
+
}
|
|
44194
|
+
await this.#startExternalFromFollowUp(
|
|
44195
|
+
request,
|
|
44196
|
+
thread,
|
|
44197
|
+
queued,
|
|
44198
|
+
params[THREAD_REFERENCE_SOURCE_HOST_PARAM]
|
|
44199
|
+
);
|
|
43597
44200
|
return;
|
|
43598
44201
|
}
|
|
43599
44202
|
try {
|
|
@@ -43601,7 +44204,7 @@ var AppServerHost = class {
|
|
|
43601
44204
|
thread,
|
|
43602
44205
|
text,
|
|
43603
44206
|
void 0,
|
|
43604
|
-
|
|
44207
|
+
clientUserMessageId,
|
|
43605
44208
|
params[THREAD_REFERENCE_SOURCE_HOST_PARAM]
|
|
43606
44209
|
);
|
|
43607
44210
|
try {
|
|
@@ -43630,10 +44233,15 @@ var AppServerHost = class {
|
|
|
43630
44233
|
assertActive,
|
|
43631
44234
|
typeof requestObject(request).clientUserMessageId === "string" ? requestObject(request).clientUserMessageId : void 0,
|
|
43632
44235
|
requestObject(request)[THREAD_REFERENCE_SOURCE_HOST_PARAM]
|
|
43633
|
-
)
|
|
44236
|
+
),
|
|
44237
|
+
(input) => this.#insertExternalInput(thread, input)
|
|
43634
44238
|
);
|
|
43635
44239
|
try {
|
|
43636
|
-
await this.#writer.json(
|
|
44240
|
+
await this.#writer.json(
|
|
44241
|
+
rpcEnvelope(request, {
|
|
44242
|
+
result: { turnId: started.turnId, delivery: started.delivery }
|
|
44243
|
+
})
|
|
44244
|
+
);
|
|
43637
44245
|
} finally {
|
|
43638
44246
|
started.gate.resolve();
|
|
43639
44247
|
}
|
|
@@ -43649,6 +44257,34 @@ var AppServerHost = class {
|
|
|
43649
44257
|
this.#signalActiveWorkChanged();
|
|
43650
44258
|
}
|
|
43651
44259
|
}
|
|
44260
|
+
/** Native same-Turn input; `insertNativeSteer` owns the delivery and its fallback signal. */
|
|
44261
|
+
async #insertExternalInput(thread, input) {
|
|
44262
|
+
await insertNativeSteer(thread, input, {
|
|
44263
|
+
project: async (turnId, item, clientUserMessageId) => {
|
|
44264
|
+
const projection = this.#projectedTurn(thread, turnId);
|
|
44265
|
+
if (clientUserMessageId) {
|
|
44266
|
+
projection.projector.bindUserMessageClientId(item.itemId, clientUserMessageId);
|
|
44267
|
+
}
|
|
44268
|
+
await this.#projectHarnessOutput(thread, {
|
|
44269
|
+
kind: "event",
|
|
44270
|
+
event: { type: "item.started", turnId, item }
|
|
44271
|
+
});
|
|
44272
|
+
await this.#projectHarnessOutput(thread, {
|
|
44273
|
+
kind: "event",
|
|
44274
|
+
event: {
|
|
44275
|
+
type: "item.completed",
|
|
44276
|
+
turnId,
|
|
44277
|
+
snapshot: { item, outcome: { status: "succeeded" } }
|
|
44278
|
+
}
|
|
44279
|
+
});
|
|
44280
|
+
},
|
|
44281
|
+
diagnose: (error51) => this.#diagnose(error51)
|
|
44282
|
+
});
|
|
44283
|
+
return {
|
|
44284
|
+
turnId: input.turnId,
|
|
44285
|
+
gate: { promise: Promise.resolve(), resolve: () => void 0 }
|
|
44286
|
+
};
|
|
44287
|
+
}
|
|
43652
44288
|
/** Keep command restoration and dispatch identical for start and steer submissions. */
|
|
43653
44289
|
async #beginExternalInputTurn(thread, inputText, assertActive, clientUserMessageId, sourceHostId) {
|
|
43654
44290
|
const text = restoreHarnessCommandMentions(inputText);
|
|
@@ -43706,7 +44342,7 @@ var AppServerHost = class {
|
|
|
43706
44342
|
if (thread.running || thread.activeTurnId || this.#pendingExternalCommandRequests.has(thread.id)) {
|
|
43707
44343
|
throw new ExternalSteerError(-32072, "External Thread already has an active Turn");
|
|
43708
44344
|
}
|
|
43709
|
-
const turnId = hostTurnIdSchema.parse(
|
|
44345
|
+
const turnId = hostTurnIdSchema.parse(randomUUID19());
|
|
43710
44346
|
const startedAtMs = Date.now();
|
|
43711
44347
|
const projection = {
|
|
43712
44348
|
projector: new CodexTurnProjector({
|
|
@@ -44000,8 +44636,14 @@ var AppServerHost = class {
|
|
|
44000
44636
|
}
|
|
44001
44637
|
return;
|
|
44002
44638
|
}
|
|
44639
|
+
if (event.type === "turn.completed" && thread.pendingSteerProjections.size > 0) {
|
|
44640
|
+
await Promise.allSettled([...thread.pendingSteerProjections]);
|
|
44641
|
+
}
|
|
44003
44642
|
const projection = this.#projectedTurn(thread, event.turnId);
|
|
44004
44643
|
await this.#waitForTurnResponse(thread, event.turnId);
|
|
44644
|
+
if (event.type === "item.completed" && event.snapshot.item.type === "agentMessage" && this.#externalVoice.has(thread.id)) {
|
|
44645
|
+
projection.realtimeInline = true;
|
|
44646
|
+
}
|
|
44005
44647
|
if (event.type === "interaction.closed" && thread.ignoredInteractionIds.delete(event.interactionId)) {
|
|
44006
44648
|
return;
|
|
44007
44649
|
}
|
|
@@ -44041,7 +44683,9 @@ var AppServerHost = class {
|
|
|
44041
44683
|
thread.ephemeralTurnIds.delete(event.turnId);
|
|
44042
44684
|
this.#manualCompactionTurns.delete(thread);
|
|
44043
44685
|
} else {
|
|
44044
|
-
thread.turns.push(
|
|
44686
|
+
thread.turns.push(
|
|
44687
|
+
projection.realtimeInline ? presentExternalVoiceTurn(result.completedTurn) : result.completedTurn
|
|
44688
|
+
);
|
|
44045
44689
|
thread.projectedTerminalTurnId = event.turnId;
|
|
44046
44690
|
thread.thread.updatedAt = completedAt;
|
|
44047
44691
|
thread.thread.recencyAt = completedAt;
|
|
@@ -44051,6 +44695,7 @@ var AppServerHost = class {
|
|
|
44051
44695
|
thread.activeTurnId = null;
|
|
44052
44696
|
if (!projection.projector.hasOpenDetachedItems) thread.projectedTurns.delete(event.turnId);
|
|
44053
44697
|
thread.responseGates.delete(event.turnId);
|
|
44698
|
+
thread.pendingSteerProjections.clear();
|
|
44054
44699
|
this.#signalActiveWorkChanged();
|
|
44055
44700
|
const delegation = await this.#repository.getDelegationByChild(thread.record.hostThreadId);
|
|
44056
44701
|
if (delegation) {
|
|
@@ -44067,7 +44712,11 @@ var AppServerHost = class {
|
|
|
44067
44712
|
if (event.type === "item.completed" && projection.projector.completed && !projection.projector.hasOpenDetachedItems) {
|
|
44068
44713
|
thread.projectedTurns.delete(event.turnId);
|
|
44069
44714
|
}
|
|
44070
|
-
for (const message2 of result.messages)
|
|
44715
|
+
for (const message2 of result.messages) {
|
|
44716
|
+
await this.#writer.json(
|
|
44717
|
+
projection.realtimeInline ? presentExternalVoiceMessage(message2) : message2
|
|
44718
|
+
);
|
|
44719
|
+
}
|
|
44071
44720
|
this.#externalVoiceResults.observe(
|
|
44072
44721
|
thread.id,
|
|
44073
44722
|
event,
|
|
@@ -44126,7 +44775,7 @@ var AppServerHost = class {
|
|
|
44126
44775
|
const previousItems = new Map(
|
|
44127
44776
|
child.turns.flatMap(
|
|
44128
44777
|
(turn) => Array.isArray(turn.items) ? turn.items.flatMap(
|
|
44129
|
-
(item) =>
|
|
44778
|
+
(item) => isRecord21(item) && typeof item.id === "string" ? [[item.id, JSON.stringify(item)]] : []
|
|
44130
44779
|
) : []
|
|
44131
44780
|
)
|
|
44132
44781
|
);
|
|
@@ -44139,7 +44788,7 @@ var AppServerHost = class {
|
|
|
44139
44788
|
for (const turn of child.turns) {
|
|
44140
44789
|
if (typeof turn.id !== "string" || !Array.isArray(turn.items)) continue;
|
|
44141
44790
|
const changedItems = turn.items.filter(
|
|
44142
|
-
(item) =>
|
|
44791
|
+
(item) => isRecord21(item) && typeof item.id === "string" && previousItems.get(item.id) !== JSON.stringify(item)
|
|
44143
44792
|
);
|
|
44144
44793
|
if (changedItems.length > 0) {
|
|
44145
44794
|
await this.#writer.json({
|
|
@@ -44271,7 +44920,7 @@ var AppServerHost = class {
|
|
|
44271
44920
|
}
|
|
44272
44921
|
}
|
|
44273
44922
|
async #handleDesktopApprovalResponse(value2) {
|
|
44274
|
-
if (!
|
|
44923
|
+
if (!isRecord21(value2) || !isHostApprovalRequestId(value2.id)) return false;
|
|
44275
44924
|
const requestId2 = value2.id;
|
|
44276
44925
|
const pending = this.#pendingDesktopApprovals.get(requestId2);
|
|
44277
44926
|
if (!pending) return true;
|
|
@@ -44355,7 +45004,7 @@ var AppServerHost = class {
|
|
|
44355
45004
|
try {
|
|
44356
45005
|
result = projection.projector.projectQuestion(
|
|
44357
45006
|
interaction,
|
|
44358
|
-
hostItemIdSchema.parse(
|
|
45007
|
+
hostItemIdSchema.parse(randomUUID19())
|
|
44359
45008
|
);
|
|
44360
45009
|
} catch (error51) {
|
|
44361
45010
|
this.#diagnose(error51);
|
|
@@ -44400,7 +45049,7 @@ var AppServerHost = class {
|
|
|
44400
45049
|
}
|
|
44401
45050
|
}
|
|
44402
45051
|
async #handleDesktopQuestionResponse(value2) {
|
|
44403
|
-
if (!
|
|
45052
|
+
if (!isRecord21(value2) || !isHostQuestionRequestId(value2.id)) return false;
|
|
44404
45053
|
const requestId2 = value2.id;
|
|
44405
45054
|
const pending = this.#pendingDesktopQuestions.get(requestId2);
|
|
44406
45055
|
if (!pending) return true;
|
|
@@ -44583,7 +45232,7 @@ import path30 from "node:path";
|
|
|
44583
45232
|
import { PassThrough } from "node:stream";
|
|
44584
45233
|
|
|
44585
45234
|
// packages/host-runtime/src/remote-socket-lock.ts
|
|
44586
|
-
import { randomUUID as
|
|
45235
|
+
import { randomUUID as randomUUID20 } from "node:crypto";
|
|
44587
45236
|
import { chmod as chmod3, lstat as lstat5, mkdir as mkdir14, open as open9, readFile as readFile18, readdir as readdir5, rename as rename12, rm as rm13 } from "node:fs/promises";
|
|
44588
45237
|
import { uptime } from "node:os";
|
|
44589
45238
|
import path29 from "node:path";
|
|
@@ -44709,7 +45358,7 @@ async function preparePrivateLockDirectory(lockDirectory) {
|
|
|
44709
45358
|
await chmod3(lockDirectory, 448);
|
|
44710
45359
|
}
|
|
44711
45360
|
async function writeLockRecordAtomic(lockDirectory, entryPath, record4) {
|
|
44712
|
-
const temporary = path29.join(lockDirectory, `.tmp-${record4.ownerToken}-${
|
|
45361
|
+
const temporary = path29.join(lockDirectory, `.tmp-${record4.ownerToken}-${randomUUID20()}`);
|
|
44713
45362
|
const handle = await open9(temporary, "wx", 384);
|
|
44714
45363
|
try {
|
|
44715
45364
|
await handle.writeFile(`${JSON.stringify(record4)}
|
|
@@ -44784,7 +45433,7 @@ async function withRemoteAppServerSocketInitializationLock(socketPath, action) {
|
|
|
44784
45433
|
const legacyPath = `${socketPath}.initializing`;
|
|
44785
45434
|
const lockDirectory = `${socketPath}.initializers`;
|
|
44786
45435
|
await preparePrivateLockDirectory(lockDirectory);
|
|
44787
|
-
const ownerToken =
|
|
45436
|
+
const ownerToken = randomUUID20();
|
|
44788
45437
|
const entryPath = path29.join(lockDirectory, lockEntryName(ownerToken));
|
|
44789
45438
|
const baseRecord = {
|
|
44790
45439
|
version: 2,
|
|
@@ -45295,12 +45944,12 @@ function createRemoteAppServerWebSocketListener(input) {
|
|
|
45295
45944
|
|
|
45296
45945
|
// packages/host-runtime/src/remote-official-app-server.ts
|
|
45297
45946
|
import { spawn as spawn5 } from "node:child_process";
|
|
45298
|
-
import { randomUUID as
|
|
45947
|
+
import { randomUUID as randomUUID21 } from "node:crypto";
|
|
45299
45948
|
import { lstat as lstat7, rm as rm15, stat as stat7 } from "node:fs/promises";
|
|
45300
45949
|
import path31 from "node:path";
|
|
45301
45950
|
var DEFAULT_CLOSE_TIMEOUT_MS = 2e3;
|
|
45302
45951
|
var DEFAULT_LISTEN_TIMEOUT_MS = 1e4;
|
|
45303
|
-
function remoteOfficialAppServerSocketPath(desktopControlSocketPath, token =
|
|
45952
|
+
function remoteOfficialAppServerSocketPath(desktopControlSocketPath, token = randomUUID21()) {
|
|
45304
45953
|
if (!path31.posix.isAbsolute(desktopControlSocketPath)) {
|
|
45305
45954
|
throw new Error("Desktop control socket path must be absolute");
|
|
45306
45955
|
}
|
|
@@ -46586,12 +47235,12 @@ async function readRemoteDelegationThread(environment, input) {
|
|
|
46586
47235
|
}
|
|
46587
47236
|
|
|
46588
47237
|
// packages/host-runtime/src/shared-thread-owner.ts
|
|
46589
|
-
import { randomUUID as
|
|
47238
|
+
import { randomUUID as randomUUID23 } from "node:crypto";
|
|
46590
47239
|
import { PassThrough as PassThrough3 } from "node:stream";
|
|
46591
47240
|
|
|
46592
47241
|
// packages/host-runtime/src/shared-thread-peer.ts
|
|
46593
|
-
import { randomUUID as
|
|
46594
|
-
function
|
|
47242
|
+
import { randomUUID as randomUUID22 } from "node:crypto";
|
|
47243
|
+
function object9(value2) {
|
|
46595
47244
|
return value2 !== null && typeof value2 === "object" && !Array.isArray(value2);
|
|
46596
47245
|
}
|
|
46597
47246
|
var StreamThreadPeer = class {
|
|
@@ -46604,7 +47253,7 @@ var StreamThreadPeer = class {
|
|
|
46604
47253
|
input;
|
|
46605
47254
|
output;
|
|
46606
47255
|
stop;
|
|
46607
|
-
#prefix = `shared:${
|
|
47256
|
+
#prefix = `shared:${randomUUID22()}:`;
|
|
46608
47257
|
#pending = /* @__PURE__ */ new Map();
|
|
46609
47258
|
#listeners = /* @__PURE__ */ new Set();
|
|
46610
47259
|
#ended = Promise.withResolvers();
|
|
@@ -46647,7 +47296,7 @@ var StreamThreadPeer = class {
|
|
|
46647
47296
|
async #read() {
|
|
46648
47297
|
for await (const frame of readLfFrames(this.input)) {
|
|
46649
47298
|
const message2 = parseJsonFrame(frame);
|
|
46650
|
-
if (!
|
|
47299
|
+
if (!object9(message2)) throw new Error("Invalid shared Thread response");
|
|
46651
47300
|
if (typeof message2.method !== "string") {
|
|
46652
47301
|
const pending = typeof message2.id === "string" ? this.#pending.get(message2.id) : void 0;
|
|
46653
47302
|
if (pending) {
|
|
@@ -46682,7 +47331,7 @@ var SharedThreadOwner = class {
|
|
|
46682
47331
|
input = new PassThrough3();
|
|
46683
47332
|
output = new PassThrough3();
|
|
46684
47333
|
#peer = new StreamThreadPeer(this.output, this.input, () => this.input.end());
|
|
46685
|
-
#prefix = `shared-interaction:${
|
|
47334
|
+
#prefix = `shared-interaction:${randomUUID23()}:`;
|
|
46686
47335
|
#interactions = /* @__PURE__ */ new Map();
|
|
46687
47336
|
#listeners = /* @__PURE__ */ new Set();
|
|
46688
47337
|
#receipts = /* @__PURE__ */ new Map();
|
|
@@ -46693,7 +47342,7 @@ var SharedThreadOwner = class {
|
|
|
46693
47342
|
const id2 = `${this.#prefix}${message2.id}`;
|
|
46694
47343
|
event = { ...message2, id: id2 };
|
|
46695
47344
|
this.#interactions.set(id2, { nativeId: message2.id, message: event });
|
|
46696
|
-
} else if (message2.method === "serverRequest/resolved" &&
|
|
47345
|
+
} else if (message2.method === "serverRequest/resolved" && object9(message2.params)) {
|
|
46697
47346
|
const id2 = `${this.#prefix}${message2.params.requestId}`;
|
|
46698
47347
|
this.#interactions.delete(id2);
|
|
46699
47348
|
event = { ...message2, params: { ...message2.params, requestId: id2 } };
|
|
@@ -46788,7 +47437,7 @@ var SharedThreadOwner = class {
|
|
|
46788
47437
|
const parsed2 = jsonRpcRequestSchema.safeParse(message2);
|
|
46789
47438
|
if (parsed2.success) {
|
|
46790
47439
|
const request = parsed2.data;
|
|
46791
|
-
void peer.request(request.method,
|
|
47440
|
+
void peer.request(request.method, object9(request.params) ? request.params : {}).then(
|
|
46792
47441
|
(reply2) => send({ ...reply2, id: request.id }),
|
|
46793
47442
|
() => send({
|
|
46794
47443
|
id: request.id,
|
|
@@ -46798,7 +47447,7 @@ var SharedThreadOwner = class {
|
|
|
46798
47447
|
}
|
|
46799
47448
|
})
|
|
46800
47449
|
);
|
|
46801
|
-
} else if (
|
|
47450
|
+
} else if (object9(message2) && rpcId(message2.id)) {
|
|
46802
47451
|
await peer.respond(message2);
|
|
46803
47452
|
}
|
|
46804
47453
|
}
|
|
@@ -46883,8 +47532,8 @@ var SharedThreadBridge = class {
|
|
|
46883
47532
|
}
|
|
46884
47533
|
this.#peer = peer;
|
|
46885
47534
|
peer.subscribe((message2) => {
|
|
46886
|
-
const params =
|
|
46887
|
-
if (
|
|
47535
|
+
const params = object9(message2.params) ? message2.params : {};
|
|
47536
|
+
if (object9(params.thread) && params.thread.modelProvider === "codexhost" && typeof params.thread.id === "string") {
|
|
46888
47537
|
this.#known.add(params.thread.id);
|
|
46889
47538
|
}
|
|
46890
47539
|
this.#publish(message2);
|
|
@@ -46928,7 +47577,7 @@ var SharedThreadBridge = class {
|
|
|
46928
47577
|
return owners;
|
|
46929
47578
|
}
|
|
46930
47579
|
async route(request) {
|
|
46931
|
-
const params =
|
|
47580
|
+
const params = object9(request.params) ? request.params : {};
|
|
46932
47581
|
const create = this.options.delegateCreates ? classifyCreateRequestRoute(request) : null;
|
|
46933
47582
|
let shared = create !== null && create.selectedHarness !== "codex";
|
|
46934
47583
|
if (!shared && typeof params.threadId === "string") {
|
|
@@ -46945,10 +47594,10 @@ var SharedThreadBridge = class {
|
|
|
46945
47594
|
const seen = /* @__PURE__ */ new Set();
|
|
46946
47595
|
do {
|
|
46947
47596
|
const reply2 = await peer.request("thread/list", { ...params, cursor, limit: 200 });
|
|
46948
|
-
if (!
|
|
47597
|
+
if (!object9(reply2.result) || !Array.isArray(reply2.result.data))
|
|
46949
47598
|
throw new Error("Shared Thread list failed");
|
|
46950
47599
|
for (const row of reply2.result.data) {
|
|
46951
|
-
if (!
|
|
47600
|
+
if (!object9(row) || typeof row.id !== "string")
|
|
46952
47601
|
throw new Error("Invalid shared Thread row");
|
|
46953
47602
|
rows.push(row);
|
|
46954
47603
|
this.#known.add(row.id);
|
|
@@ -46977,7 +47626,7 @@ var SharedThreadBridge = class {
|
|
|
46977
47626
|
return storedSectionPlacementV1Schema.array().parse(reply2.result);
|
|
46978
47627
|
}
|
|
46979
47628
|
async respond(message2) {
|
|
46980
|
-
if (!
|
|
47629
|
+
if (!object9(message2) || typeof message2.method === "string" || typeof message2.id !== "string" || !message2.id.startsWith("shared-interaction:"))
|
|
46981
47630
|
return false;
|
|
46982
47631
|
if (!this.#peer) throw new Error("Shared Thread Host is disconnected");
|
|
46983
47632
|
await this.#peer.respond(message2);
|
|
@@ -46992,7 +47641,7 @@ var SharedThreadBridge = class {
|
|
|
46992
47641
|
};
|
|
46993
47642
|
|
|
46994
47643
|
// packages/host-runtime/src/remote-control-app-server.ts
|
|
46995
|
-
import { randomUUID as
|
|
47644
|
+
import { randomUUID as randomUUID24 } from "node:crypto";
|
|
46996
47645
|
import { mkdir as mkdir17, open as open10, rename as rename13, rm as rm17 } from "node:fs/promises";
|
|
46997
47646
|
import path37 from "node:path";
|
|
46998
47647
|
var REMOTE_CONTROL_BRIDGE_PIPE_ENV = "CODEXHOST_REMOTE_CONTROL_BRIDGE_PIPE";
|
|
@@ -47013,7 +47662,7 @@ function nodeCompatibleWindowsPath(value2) {
|
|
|
47013
47662
|
if (value2.startsWith("\\\\?\\")) return value2.slice(4);
|
|
47014
47663
|
return value2;
|
|
47015
47664
|
}
|
|
47016
|
-
function remoteControlBridgePipePath(processId = process.pid, instanceId =
|
|
47665
|
+
function remoteControlBridgePipePath(processId = process.pid, instanceId = randomUUID24()) {
|
|
47017
47666
|
const safeInstance = instanceId.replaceAll(/[^a-zA-Z0-9-]/gu, "");
|
|
47018
47667
|
if (!safeInstance) throw new Error("Remote Control bridge instance ID is invalid");
|
|
47019
47668
|
return `\\\\.\\pipe\\codexhost-remote-control-${processId}-${safeInstance}`;
|
|
@@ -47028,7 +47677,7 @@ async function publishRemoteControlAppServerDescriptor(plan) {
|
|
|
47028
47677
|
await mkdir17(directory, { recursive: true, mode: 448 });
|
|
47029
47678
|
const temporaryPath = path37.join(
|
|
47030
47679
|
directory,
|
|
47031
|
-
`.${REMOTE_CONTROL_BRIDGE_DESCRIPTOR_FILE}.${plan.descriptor.ownerPid}.${
|
|
47680
|
+
`.${REMOTE_CONTROL_BRIDGE_DESCRIPTOR_FILE}.${plan.descriptor.ownerPid}.${randomUUID24()}.tmp`
|
|
47032
47681
|
);
|
|
47033
47682
|
const handle = await open10(temporaryPath, "wx", 384);
|
|
47034
47683
|
try {
|
|
@@ -47569,12 +48218,19 @@ function createHostUpdateCoordinator(options2) {
|
|
|
47569
48218
|
}
|
|
47570
48219
|
|
|
47571
48220
|
// packages/host-runtime/src/usage-statistics.ts
|
|
47572
|
-
import { randomUUID as
|
|
48221
|
+
import { randomUUID as randomUUID25 } from "node:crypto";
|
|
47573
48222
|
import { mkdir as mkdir19, readFile as readFile20, readdir as readdir6, rename as rename15, rm as rm19, writeFile as writeFile11 } from "node:fs/promises";
|
|
47574
48223
|
import path40 from "node:path";
|
|
47575
48224
|
import { setImmediate as yieldToEventLoop } from "node:timers/promises";
|
|
47576
48225
|
|
|
47577
48226
|
// packages/harness-adapter/dist/usage-statistics.js
|
|
48227
|
+
var HarnessUsageSourceChangedError = class extends Error {
|
|
48228
|
+
code = "HARNESS_USAGE_SOURCE_CHANGED";
|
|
48229
|
+
/** Plugins may bundle their own copy of this contract, so instanceof is insufficient. */
|
|
48230
|
+
static is(error51) {
|
|
48231
|
+
return typeof error51 === "object" && error51 !== null && "code" in error51 && error51.code === "HARNESS_USAGE_SOURCE_CHANGED";
|
|
48232
|
+
}
|
|
48233
|
+
};
|
|
47578
48234
|
var MAX_SESSION_ID_LENGTH = 512;
|
|
47579
48235
|
var MAX_CWD_LENGTH = 4096;
|
|
47580
48236
|
var MAX_SESSION_TITLE_LENGTH = 200;
|
|
@@ -47677,6 +48333,95 @@ function withHostSessionTitles(result, records) {
|
|
|
47677
48333
|
};
|
|
47678
48334
|
}
|
|
47679
48335
|
|
|
48336
|
+
// packages/host-runtime/src/usage-statistics-sources.ts
|
|
48337
|
+
import { setTimeout as delay7 } from "node:timers/promises";
|
|
48338
|
+
async function* readUsageStatisticsSources(capability, sources, signal) {
|
|
48339
|
+
let pending = sources;
|
|
48340
|
+
for (let attempt = 0; ; attempt++) {
|
|
48341
|
+
const changed = [];
|
|
48342
|
+
for (const source of pending) {
|
|
48343
|
+
signal.throwIfAborted();
|
|
48344
|
+
try {
|
|
48345
|
+
const entries = (await capability.readSource(source.id, signal)).map(parseHarnessUsageEntry).filter((entry) => entry !== null);
|
|
48346
|
+
yield { source, entries };
|
|
48347
|
+
} catch (error51) {
|
|
48348
|
+
signal.throwIfAborted();
|
|
48349
|
+
if (HarnessUsageSourceChangedError.is(error51) && attempt < 2) changed.push(source);
|
|
48350
|
+
else yield { source, error: error51 };
|
|
48351
|
+
}
|
|
48352
|
+
}
|
|
48353
|
+
if (!changed.length) return;
|
|
48354
|
+
await delay7(50 * (attempt + 1), void 0, { signal });
|
|
48355
|
+
let current;
|
|
48356
|
+
try {
|
|
48357
|
+
current = new Map(
|
|
48358
|
+
(await capability.listSources(signal)).map((source) => [source.id, source])
|
|
48359
|
+
);
|
|
48360
|
+
} catch (error51) {
|
|
48361
|
+
signal.throwIfAborted();
|
|
48362
|
+
for (const source of changed) yield { source, error: error51 };
|
|
48363
|
+
return;
|
|
48364
|
+
}
|
|
48365
|
+
const next = [];
|
|
48366
|
+
for (const source of changed) {
|
|
48367
|
+
const fresh = current.get(source.id);
|
|
48368
|
+
if (fresh) next.push(fresh);
|
|
48369
|
+
else yield { source, removed: true };
|
|
48370
|
+
}
|
|
48371
|
+
pending = next;
|
|
48372
|
+
}
|
|
48373
|
+
}
|
|
48374
|
+
|
|
48375
|
+
// packages/host-runtime/src/usage-statistics-calendar.ts
|
|
48376
|
+
function dateKey(year, month, day) {
|
|
48377
|
+
return `${year}-${String(month).padStart(2, "0")}-${String(day).padStart(2, "0")}`;
|
|
48378
|
+
}
|
|
48379
|
+
function createUsageStatisticsCalendar(timeZone) {
|
|
48380
|
+
const localZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
48381
|
+
const zone = timeZone ?? localZone;
|
|
48382
|
+
if (zone === localZone) {
|
|
48383
|
+
return {
|
|
48384
|
+
timeZone: zone,
|
|
48385
|
+
at(ms) {
|
|
48386
|
+
const date5 = new Date(ms);
|
|
48387
|
+
return {
|
|
48388
|
+
date: dateKey(date5.getFullYear(), date5.getMonth() + 1, date5.getDate()),
|
|
48389
|
+
weekday: date5.getDay(),
|
|
48390
|
+
hour: date5.getHours()
|
|
48391
|
+
};
|
|
48392
|
+
}
|
|
48393
|
+
};
|
|
48394
|
+
}
|
|
48395
|
+
const format = new Intl.DateTimeFormat("en-US", {
|
|
48396
|
+
timeZone: zone,
|
|
48397
|
+
calendar: "gregory",
|
|
48398
|
+
numberingSystem: "latn",
|
|
48399
|
+
year: "numeric",
|
|
48400
|
+
month: "2-digit",
|
|
48401
|
+
day: "2-digit",
|
|
48402
|
+
hour: "2-digit",
|
|
48403
|
+
hourCycle: "h23"
|
|
48404
|
+
});
|
|
48405
|
+
return {
|
|
48406
|
+
timeZone: zone,
|
|
48407
|
+
at(ms) {
|
|
48408
|
+
const parts = format.formatToParts(ms);
|
|
48409
|
+
const part = (type) => Number(parts.find((value2) => value2.type === type)?.value);
|
|
48410
|
+
const year = part("year"), month = part("month"), day = part("day");
|
|
48411
|
+
return {
|
|
48412
|
+
date: dateKey(year, month, day),
|
|
48413
|
+
weekday: new Date(Date.UTC(year, month - 1, day)).getUTCDay(),
|
|
48414
|
+
hour: part("hour")
|
|
48415
|
+
};
|
|
48416
|
+
}
|
|
48417
|
+
};
|
|
48418
|
+
}
|
|
48419
|
+
function shiftUsageDate(date5, days) {
|
|
48420
|
+
const value2 = /* @__PURE__ */ new Date(`${date5}T12:00:00Z`);
|
|
48421
|
+
value2.setUTCDate(value2.getUTCDate() + days);
|
|
48422
|
+
return dateKey(value2.getUTCFullYear(), value2.getUTCMonth() + 1, value2.getUTCDate());
|
|
48423
|
+
}
|
|
48424
|
+
|
|
47680
48425
|
// packages/host-runtime/src/usage-statistics.ts
|
|
47681
48426
|
var CACHE_VERSION = 7;
|
|
47682
48427
|
var STALE_AFTER_MS = 1e4;
|
|
@@ -47737,17 +48482,6 @@ function expand(value2, intern) {
|
|
|
47737
48482
|
function message(error51) {
|
|
47738
48483
|
return error51 instanceof Error ? error51.message : String(error51);
|
|
47739
48484
|
}
|
|
47740
|
-
function localDate2(ms) {
|
|
47741
|
-
const date5 = new Date(ms);
|
|
47742
|
-
const month = String(date5.getMonth() + 1).padStart(2, "0");
|
|
47743
|
-
const day = String(date5.getDate()).padStart(2, "0");
|
|
47744
|
-
return `${date5.getFullYear()}-${month}-${day}`;
|
|
47745
|
-
}
|
|
47746
|
-
function shiftDate(date5, days) {
|
|
47747
|
-
const value2 = /* @__PURE__ */ new Date(`${date5}T12:00:00`);
|
|
47748
|
-
value2.setDate(value2.getDate() + days);
|
|
47749
|
-
return localDate2(value2.getTime());
|
|
47750
|
-
}
|
|
47751
48485
|
var SESSIONS_PER_MEASURE = 50;
|
|
47752
48486
|
var MODELS_PER_SESSION = 16;
|
|
47753
48487
|
function emptyTotals() {
|
|
@@ -47934,23 +48668,27 @@ var UsageStatistics = class {
|
|
|
47934
48668
|
}
|
|
47935
48669
|
for (const { harness: harness2, capability, ids } of listed) {
|
|
47936
48670
|
const cache = this.#cache(harness2);
|
|
47937
|
-
const present =
|
|
48671
|
+
const present = new Set(ids.map(({ id: id2 }) => id2));
|
|
47938
48672
|
let failed = null;
|
|
47939
|
-
|
|
47940
|
-
|
|
47941
|
-
|
|
47942
|
-
|
|
47943
|
-
|
|
47944
|
-
|
|
48673
|
+
const pending = ids.filter(
|
|
48674
|
+
({ id: id2, fingerprint }) => cache.sources.get(id2)?.fingerprint !== fingerprint
|
|
48675
|
+
);
|
|
48676
|
+
this.#progress.read += ids.length - pending.length;
|
|
48677
|
+
try {
|
|
48678
|
+
for await (const result of readUsageStatisticsSources(capability, pending, signal)) {
|
|
48679
|
+
const { id: id2, fingerprint } = result.source;
|
|
48680
|
+
if ("entries" in result) {
|
|
48681
|
+
cache.sources.set(id2, { fingerprint, entries: result.entries });
|
|
47945
48682
|
cache.dirty = true;
|
|
47946
48683
|
this.#generation += 1;
|
|
47947
|
-
}
|
|
47948
|
-
|
|
47949
|
-
|
|
47950
|
-
}
|
|
48684
|
+
} else if ("error" in result) failed ??= message(result.error);
|
|
48685
|
+
else present.delete(id2);
|
|
48686
|
+
this.#progress.read += 1;
|
|
47951
48687
|
await yieldToEventLoop();
|
|
47952
48688
|
}
|
|
47953
|
-
|
|
48689
|
+
} catch (error51) {
|
|
48690
|
+
if (signal.aborted) return;
|
|
48691
|
+
throw error51;
|
|
47954
48692
|
}
|
|
47955
48693
|
for (const id2 of cache.sources.keys()) {
|
|
47956
48694
|
if (!present.has(id2)) {
|
|
@@ -48015,7 +48753,7 @@ var UsageStatistics = class {
|
|
|
48015
48753
|
async #persist(harness2, cache) {
|
|
48016
48754
|
if (!cache.dirty || this.#now() - cache.persistedAtMs < PERSIST_INTERVAL_MS) return;
|
|
48017
48755
|
const file2 = this.#file(harness2);
|
|
48018
|
-
const temporary = `${file2}.${
|
|
48756
|
+
const temporary = `${file2}.${randomUUID25()}.tmp`;
|
|
48019
48757
|
try {
|
|
48020
48758
|
await mkdir19(this.#directory, { recursive: true });
|
|
48021
48759
|
const sources = [...cache.sources].map(([id2, source]) => [
|
|
@@ -48033,9 +48771,10 @@ var UsageStatistics = class {
|
|
|
48033
48771
|
await rm19(temporary, { force: true });
|
|
48034
48772
|
}
|
|
48035
48773
|
}
|
|
48036
|
-
/** Every request once, per Harness in source order,
|
|
48037
|
-
#indexed() {
|
|
48038
|
-
if (this.#index?.generation === this.#generation
|
|
48774
|
+
/** Every request once, per Harness in source order, in the requested calendar. */
|
|
48775
|
+
#indexed(calendar) {
|
|
48776
|
+
if (this.#index?.generation === this.#generation && this.#index.timeZone === calendar.timeZone)
|
|
48777
|
+
return this.#index.entries;
|
|
48039
48778
|
const entries = [];
|
|
48040
48779
|
for (const [harness2, cache] of this.#caches) {
|
|
48041
48780
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -48043,26 +48782,20 @@ var UsageStatistics = class {
|
|
|
48043
48782
|
for (const entry of parsed2) {
|
|
48044
48783
|
if (seen.has(entry.id)) continue;
|
|
48045
48784
|
seen.add(entry.id);
|
|
48046
|
-
|
|
48047
|
-
entries.push({
|
|
48048
|
-
harness: harness2,
|
|
48049
|
-
entry,
|
|
48050
|
-
date: localDate2(entry.occurredAtMs),
|
|
48051
|
-
weekday: at.getDay(),
|
|
48052
|
-
hour: at.getHours()
|
|
48053
|
-
});
|
|
48785
|
+
entries.push({ harness: harness2, entry, ...calendar.at(entry.occurredAtMs) });
|
|
48054
48786
|
}
|
|
48055
48787
|
}
|
|
48056
48788
|
}
|
|
48057
|
-
this.#index = { generation: this.#generation, entries };
|
|
48789
|
+
this.#index = { generation: this.#generation, timeZone: calendar.timeZone, entries };
|
|
48058
48790
|
return entries;
|
|
48059
48791
|
}
|
|
48060
48792
|
#aggregate(params, now, lookup) {
|
|
48061
48793
|
const { range } = params;
|
|
48062
48794
|
const days = RANGE_DAYS[range];
|
|
48063
|
-
const
|
|
48795
|
+
const calendar = createUsageStatisticsCalendar(params.timeZone);
|
|
48796
|
+
const to = calendar.at(now).date;
|
|
48064
48797
|
let from = null;
|
|
48065
|
-
if (days !== null) from =
|
|
48798
|
+
if (days !== null) from = shiftUsageDate(to, -days + 1);
|
|
48066
48799
|
const inRange = (date5) => (from === null || date5 >= from) && date5 <= to;
|
|
48067
48800
|
const day = params.date !== void 0 && inRange(params.date) ? params.date : null;
|
|
48068
48801
|
const harnessFilter = params.harness ?? null;
|
|
@@ -48103,7 +48836,7 @@ var UsageStatistics = class {
|
|
|
48103
48836
|
const harnessPriced = /* @__PURE__ */ new Map();
|
|
48104
48837
|
const byProject = /* @__PURE__ */ new Map();
|
|
48105
48838
|
const sessions = /* @__PURE__ */ new Map();
|
|
48106
|
-
for (const indexed of this.#indexed()) {
|
|
48839
|
+
for (const indexed of this.#indexed(calendar)) {
|
|
48107
48840
|
const { harness: harness2, entry, date: date5 } = indexed;
|
|
48108
48841
|
if (!inRange(date5)) continue;
|
|
48109
48842
|
const model2 = entry.model ?? null;
|
|
@@ -48636,7 +49369,7 @@ async function runHostRuntime(input) {
|
|
|
48636
49369
|
}
|
|
48637
49370
|
|
|
48638
49371
|
// packages/host-runtime/src/remote-host-install.ts
|
|
48639
|
-
import { createHash as createHash12, randomUUID as
|
|
49372
|
+
import { createHash as createHash12, randomUUID as randomUUID26 } from "node:crypto";
|
|
48640
49373
|
import { constants as fsConstants } from "node:fs";
|
|
48641
49374
|
import {
|
|
48642
49375
|
access as access4,
|
|
@@ -48735,7 +49468,7 @@ async function writeAtomic(filePath, contents, mode) {
|
|
|
48735
49468
|
await mkdir20(path42.dirname(filePath), { recursive: true, mode: 448 });
|
|
48736
49469
|
const temporary = path42.join(
|
|
48737
49470
|
path42.dirname(filePath),
|
|
48738
|
-
`.${path42.basename(filePath)}.${process.pid}.${
|
|
49471
|
+
`.${path42.basename(filePath)}.${process.pid}.${randomUUID26()}.tmp`
|
|
48739
49472
|
);
|
|
48740
49473
|
try {
|
|
48741
49474
|
if (typeof contents === "string") {
|
|
@@ -48759,7 +49492,7 @@ async function writeAtomicExecutable(filePath, sourcePath) {
|
|
|
48759
49492
|
await mkdir20(path42.dirname(filePath), { recursive: true, mode: 448 });
|
|
48760
49493
|
const temporary = path42.join(
|
|
48761
49494
|
path42.dirname(filePath),
|
|
48762
|
-
`.${path42.basename(filePath)}.${process.pid}.${
|
|
49495
|
+
`.${path42.basename(filePath)}.${process.pid}.${randomUUID26()}.tmp`
|
|
48763
49496
|
);
|
|
48764
49497
|
try {
|
|
48765
49498
|
await copyFile4(sourcePath, temporary);
|
|
@@ -49500,6 +50233,7 @@ var harnessBrokerMethodSchema = external_exports.enum([
|
|
|
49500
50233
|
"adapter.open",
|
|
49501
50234
|
"adapter.subagent.readSnapshot",
|
|
49502
50235
|
"session.readSnapshot",
|
|
50236
|
+
"session.readCapabilities",
|
|
49503
50237
|
"session.refreshUsage",
|
|
49504
50238
|
"session.execute",
|
|
49505
50239
|
"session.commands.list",
|
|
@@ -49682,6 +50416,11 @@ var turnStartSchema = external_exports.object({
|
|
|
49682
50416
|
turnId: hostTurnIdSchema,
|
|
49683
50417
|
input: external_exports.array(textInputSchema)
|
|
49684
50418
|
}).strict();
|
|
50419
|
+
var turnSteerSchema = external_exports.object({
|
|
50420
|
+
type: external_exports.literal("turn.steer"),
|
|
50421
|
+
turnId: hostTurnIdSchema,
|
|
50422
|
+
input: external_exports.array(textInputSchema)
|
|
50423
|
+
}).strict();
|
|
49685
50424
|
var turnCancelSchema = external_exports.object({ type: external_exports.literal("turn.cancel"), turnId: hostTurnIdSchema }).strict();
|
|
49686
50425
|
var interactionResponseSchema = external_exports.union([
|
|
49687
50426
|
external_exports.object({
|
|
@@ -49707,6 +50446,7 @@ var permissionSelectSchema = external_exports.object({
|
|
|
49707
50446
|
}).strict();
|
|
49708
50447
|
var brokerHostCommandSchema = external_exports.discriminatedUnion("type", [
|
|
49709
50448
|
turnStartSchema,
|
|
50449
|
+
turnSteerSchema,
|
|
49710
50450
|
turnCancelSchema,
|
|
49711
50451
|
interactionRespondSchema,
|
|
49712
50452
|
modelSelectSchema,
|
|
@@ -49841,7 +50581,7 @@ var harnessOutputSchema = external_exports.custom((value2) => {
|
|
|
49841
50581
|
});
|
|
49842
50582
|
|
|
49843
50583
|
// packages/harness-broker/dist/server.js
|
|
49844
|
-
import { randomBytes as randomBytes5, randomUUID as
|
|
50584
|
+
import { randomBytes as randomBytes5, randomUUID as randomUUID27 } from "node:crypto";
|
|
49845
50585
|
import { chmod as chmod6, lstat as lstat10, mkdir as mkdir21, open as open11, readFile as readFile22, rename as rename17, rm as rm21 } from "node:fs/promises";
|
|
49846
50586
|
import net4, {} from "node:net";
|
|
49847
50587
|
import path45 from "node:path";
|
|
@@ -49900,7 +50640,7 @@ async function assertNoLiveDescriptor(descriptorPath) {
|
|
|
49900
50640
|
}
|
|
49901
50641
|
}
|
|
49902
50642
|
async function publishDescriptor(descriptorPath, descriptor) {
|
|
49903
|
-
const temporary = `${descriptorPath}.${process.pid}.${
|
|
50643
|
+
const temporary = `${descriptorPath}.${process.pid}.${randomUUID27()}.tmp`;
|
|
49904
50644
|
const handle = await open11(temporary, "wx", 384);
|
|
49905
50645
|
try {
|
|
49906
50646
|
await handle.writeFile(`${JSON.stringify(descriptor)}
|
|
@@ -49925,6 +50665,7 @@ function sessionMetadata(record4) {
|
|
|
49925
50665
|
sessionId: record4.id,
|
|
49926
50666
|
sessionGeneration: record4.generation,
|
|
49927
50667
|
capabilities: record4.session.capabilities,
|
|
50668
|
+
readCapabilities: true,
|
|
49928
50669
|
initialState: {
|
|
49929
50670
|
...initialState,
|
|
49930
50671
|
...record4.nativeRef ? { nativeRef: record4.nativeRef } : {},
|
|
@@ -49977,7 +50718,7 @@ async function startHarnessBrokerServer(input) {
|
|
|
49977
50718
|
await assertNoLiveDescriptor(input.descriptorPath);
|
|
49978
50719
|
if (process.platform !== "win32")
|
|
49979
50720
|
await prepareUnixSocketPath(input.socketPath);
|
|
49980
|
-
const generation = input.generation ??
|
|
50721
|
+
const generation = input.generation ?? randomUUID27();
|
|
49981
50722
|
const token = input.token ?? randomBytes5(32).toString("hex");
|
|
49982
50723
|
const descriptor = {
|
|
49983
50724
|
schemaVersion: 1,
|
|
@@ -50018,7 +50759,7 @@ async function startHarnessBrokerServer(input) {
|
|
|
50018
50759
|
};
|
|
50019
50760
|
const server = net4.createServer((socket) => {
|
|
50020
50761
|
const state = {
|
|
50021
|
-
id:
|
|
50762
|
+
id: randomUUID27(),
|
|
50022
50763
|
socket,
|
|
50023
50764
|
authenticated: false,
|
|
50024
50765
|
inputSequence: 0,
|
|
@@ -50256,7 +50997,7 @@ async function startHarnessBrokerServer(input) {
|
|
|
50256
50997
|
}
|
|
50257
50998
|
};
|
|
50258
50999
|
}
|
|
50259
|
-
const openReservation =
|
|
51000
|
+
const openReservation = randomUUID27();
|
|
50260
51001
|
if (sourceKey)
|
|
50261
51002
|
nativeWriters.set(sourceKey, openReservation);
|
|
50262
51003
|
const provisionalReservation = openInput.kind === "create" ? openReservation : void 0;
|
|
@@ -50400,6 +51141,8 @@ async function startHarnessBrokerServer(input) {
|
|
|
50400
51141
|
let result;
|
|
50401
51142
|
if (command.type === "turn.start")
|
|
50402
51143
|
result = await record5.session.execute(command);
|
|
51144
|
+
else if (command.type === "turn.steer")
|
|
51145
|
+
result = await record5.session.execute(command);
|
|
50403
51146
|
else if (command.type === "turn.cancel")
|
|
50404
51147
|
result = await record5.session.execute(command);
|
|
50405
51148
|
else if (command.type === "interaction.respond") {
|
|
@@ -50431,6 +51174,10 @@ async function startHarnessBrokerServer(input) {
|
|
|
50431
51174
|
}
|
|
50432
51175
|
return result;
|
|
50433
51176
|
}
|
|
51177
|
+
if (request.method === "session.readCapabilities") {
|
|
51178
|
+
const session = requireSession(request.params).session;
|
|
51179
|
+
return session.readCapabilities ? session.readCapabilities() : session.capabilities;
|
|
51180
|
+
}
|
|
50434
51181
|
if (request.method === "session.readSnapshot") {
|
|
50435
51182
|
return requireSession(request.params).session.readSnapshot();
|
|
50436
51183
|
}
|
|
@@ -50557,7 +51304,7 @@ async function startHarnessBrokerServer(input) {
|
|
|
50557
51304
|
}
|
|
50558
51305
|
state.authenticated = true;
|
|
50559
51306
|
state.inputSequence = 1;
|
|
50560
|
-
await send({ kind: "response", id:
|
|
51307
|
+
await send({ kind: "response", id: randomUUID27(), ok: true, value: { ready: true } });
|
|
50561
51308
|
return;
|
|
50562
51309
|
}
|
|
50563
51310
|
const parsed2 = harnessBrokerRequestSchema.safeParse(raw);
|