@codexhost/cli-linux-arm64 0.14.0 → 0.16.0

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.
@@ -5369,7 +5369,8 @@ function createBackgroundUpdateManager(dependencies2 = {}) {
5369
5369
  kind: "npm",
5370
5370
  node_path: await requireRegularFile(options2.nodePath, "npm Node.js executable"),
5371
5371
  npm_cli_path: await requireRegularFile(options2.npmCliPath, "npm CLI"),
5372
- npm_launcher_path: await requireRegularFile(options2.npmLauncherPath, "npm codexhost launcher")
5372
+ npm_launcher_path: await requireRegularFile(options2.npmLauncherPath, "npm codexhost launcher"),
5373
+ npm_package_root: requireAbsolutePath(options2.packageRoot, "npm platform package root")
5373
5374
  });
5374
5375
  } catch (error51) {
5375
5376
  await writeFailedStatus(common.statusPath, common.version, "npm", error51);
@@ -8461,10 +8462,10 @@ var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
8461
8462
  const shape = def.shape;
8462
8463
  const propValues = {};
8463
8464
  for (const key in shape) {
8464
- const field = shape[key]._zod;
8465
- if (field.values) {
8465
+ const field2 = shape[key]._zod;
8466
+ if (field2.values) {
8466
8467
  propValues[key] ?? (propValues[key] = /* @__PURE__ */ new Set());
8467
- for (const v of field.values)
8468
+ for (const v of field2.values)
8468
8469
  propValues[key].add(v);
8469
8470
  }
8470
8471
  }
@@ -20114,6 +20115,8 @@ var usageStatisticsTotalsSchema = external_exports.strictObject({
20114
20115
  cachedInputTokens: count,
20115
20116
  cacheWriteInputTokens: count,
20116
20117
  cacheKnownInputTokens: count,
20118
+ cacheHitCachedInputTokens: count,
20119
+ cacheHitInputTokens: count,
20117
20120
  outputTokens: count,
20118
20121
  reasoningOutputTokens: count,
20119
20122
  /** USD at the public price, summed over the priced requests only. */
@@ -20223,6 +20226,53 @@ var THREAD_PREWARM_DISCARD_METHOD = "codexhost/thread/prewarm/discard";
20223
20226
  var threadPrewarmDiscardParamsSchema = external_exports.object({ threadId: hostThreadIdSchema });
20224
20227
  var threadPrewarmDiscardResultSchema = external_exports.object({ discarded: external_exports.boolean() });
20225
20228
 
20229
+ // packages/shared-contracts/dist/thread-questions.js
20230
+ var THREAD_QUESTIONS_LIST_METHOD = "codexhost/thread/questions/list";
20231
+ var THREAD_QUESTION_RESPOND_METHOD = "codexhost/thread/question/respond";
20232
+ var field = external_exports.discriminatedUnion("type", [
20233
+ external_exports.object({
20234
+ id: external_exports.string().min(1),
20235
+ type: external_exports.literal("choice"),
20236
+ prompt: external_exports.string(),
20237
+ options: external_exports.array(external_exports.object({
20238
+ value: external_exports.string().min(1),
20239
+ label: external_exports.string(),
20240
+ description: external_exports.string().optional()
20241
+ })).min(1),
20242
+ multiple: external_exports.boolean(),
20243
+ allowOther: external_exports.boolean(),
20244
+ optional: external_exports.boolean()
20245
+ }),
20246
+ external_exports.object({
20247
+ id: external_exports.string().min(1),
20248
+ type: external_exports.literal("text"),
20249
+ prompt: external_exports.string(),
20250
+ multiline: external_exports.boolean(),
20251
+ secret: external_exports.literal(false),
20252
+ optional: external_exports.boolean(),
20253
+ placeholder: external_exports.string().optional(),
20254
+ prefill: external_exports.string().optional()
20255
+ })
20256
+ ]);
20257
+ var threadQuestionSchema = external_exports.object({
20258
+ interactionId: external_exports.string().min(1),
20259
+ turnId: external_exports.string().min(1),
20260
+ title: external_exports.string().optional(),
20261
+ questions: external_exports.array(field).min(1)
20262
+ }).refine(({ questions }) => questions.some((q) => q.type === "choice" && q.multiple), {
20263
+ message: "Shared cards require at least one multi-select question"
20264
+ });
20265
+ var threadQuestionsListParamsSchema = external_exports.strictObject({ threadId: external_exports.string().min(1) });
20266
+ var threadQuestionsResultSchema = external_exports.object({ questions: external_exports.array(threadQuestionSchema) });
20267
+ var threadQuestionRespondParamsSchema = external_exports.strictObject({
20268
+ threadId: external_exports.string().min(1),
20269
+ turnId: external_exports.string().min(1),
20270
+ interactionId: external_exports.string().min(1),
20271
+ answers: external_exports.record(external_exports.string(), external_exports.array(external_exports.string())),
20272
+ cancelled: external_exports.boolean().default(false)
20273
+ });
20274
+ var threadQuestionRespondResultSchema = external_exports.object({ accepted: external_exports.literal(true) });
20275
+
20226
20276
  // packages/shared-contracts/dist/console.js
20227
20277
  var consoleAnnouncementSchema = external_exports.strictObject({
20228
20278
  title: external_exports.string().trim().min(1).max(200),
@@ -22447,8 +22497,110 @@ function retainRendererHostResponses(client, hostId2, target) {
22447
22497
  };
22448
22498
  }
22449
22499
 
22500
+ // packages/desktop-control/dist/renderer-prewarm-consumption.js
22501
+ function isolateRendererPrewarmConsumption(manager, discardExternal) {
22502
+ const record4 = (value2) => value2 !== null && typeof value2 === "object";
22503
+ if (!record4(manager) || !record4(manager.threadCreation))
22504
+ return null;
22505
+ const creation = manager.threadCreation;
22506
+ const originalStart = manager.startConversation;
22507
+ const original = creation.createConversation;
22508
+ const params = creation.params;
22509
+ if (typeof originalStart !== "function" || typeof original !== "function" || !record4(params))
22510
+ return null;
22511
+ const prototype = Object.getPrototypeOf(creation);
22512
+ if (!record4(prototype) || typeof prototype.constructor !== "function")
22513
+ return null;
22514
+ if (Object.keys(creation).some((key) => key !== "params" && typeof creation[key] !== "function") || /#[A-Za-z_$]/u.test(Function.prototype.toString.call(prototype.constructor)))
22515
+ return null;
22516
+ const pool = params.prewarmedThreadManager;
22517
+ if (!record4(pool) || typeof pool.hasPrewarmedThread !== "function" || typeof pool.consumePrewarmedThread !== "function" || typeof pool.deletePrewarmedThread !== "function")
22518
+ return null;
22519
+ const consume = pool.consumePrewarmedThread;
22520
+ const hasPrewarm = pool.hasPrewarmedThread;
22521
+ const draftModels = /* @__PURE__ */ new Map();
22522
+ const draftIdentity = /* @__PURE__ */ Symbol("codexhost draft creation");
22523
+ const external = (model2) => typeof model2 === "string" && model2.startsWith("codexhost/");
22524
+ const routedStart = function(input, options2, ...args) {
22525
+ const draftId = record4(options2) ? options2.clientThreadId : null;
22526
+ const mode = record4(input) && record4(input.collaborationMode) ? input.collaborationMode : null;
22527
+ const origin = mode ? Reflect.get(mode, draftIdentity) : void 0;
22528
+ if (mode && record4(mode.settings) && external(mode.settings.model))
22529
+ return originalStart.call(this, input, options2, ...args);
22530
+ const model2 = (typeof draftId === "string" ? draftModels.get(draftId) : void 0) ?? (typeof origin === "string" ? draftModels.get(origin) : void 0);
22531
+ if (!model2)
22532
+ return originalStart.call(this, input, options2, ...args);
22533
+ if (!record4(input) || !record4(input.collaborationMode) || !record4(input.collaborationMode.settings))
22534
+ throw new Error("External draft creation is missing its native Model settings");
22535
+ const routed = {
22536
+ ...input,
22537
+ collaborationMode: {
22538
+ ...input.collaborationMode,
22539
+ settings: { ...input.collaborationMode.settings, model: model2 }
22540
+ }
22541
+ };
22542
+ return originalStart.call(this, routed, options2, ...args);
22543
+ };
22544
+ const wrapped = function(input, ...args) {
22545
+ const mode = record4(input) && record4(input.collaborationMode) ? input.collaborationMode : null;
22546
+ const expected = mode && record4(mode.settings) ? mode.settings.model : null;
22547
+ const scopedPool = Object.create(pool);
22548
+ scopedPool.hasPrewarmedThread = (...parameters) => hasPrewarm.apply(pool, parameters);
22549
+ scopedPool.consumePrewarmedThread = async (...consumeArgs) => {
22550
+ const warmed = await consume.apply(pool, consumeArgs);
22551
+ if (!record4(warmed) || !record4(warmed.response))
22552
+ return warmed;
22553
+ const response = warmed.response;
22554
+ if (!external(expected) && !external(response.model))
22555
+ return warmed;
22556
+ if (external(expected) && expected === response.model)
22557
+ return warmed;
22558
+ if (record4(response.thread) && typeof response.thread.id === "string") {
22559
+ const threadId2 = response.thread.id;
22560
+ if (external(response.model))
22561
+ discardExternal(threadId2);
22562
+ else
22563
+ void Promise.resolve().then(() => pool.deletePrewarmedThread(threadId2)).catch(() => void 0);
22564
+ }
22565
+ return null;
22566
+ };
22567
+ const invocation = Object.create(creation);
22568
+ invocation.params = { ...params, prewarmedThreadManager: scopedPool };
22569
+ return original.call(invocation, input, ...args);
22570
+ };
22571
+ creation.createConversation = wrapped;
22572
+ manager.startConversation = routedStart;
22573
+ return {
22574
+ selectDraft(draftId, model2, creationModes = []) {
22575
+ if (draftId === void 0) {
22576
+ if (model2 === null)
22577
+ draftModels.clear();
22578
+ } else if (model2 === null)
22579
+ draftModels.delete(draftId);
22580
+ else {
22581
+ if (!draftId.startsWith("client-new-thread:") || !external(model2))
22582
+ throw new Error("External draft route is missing its client Thread identity");
22583
+ draftModels.set(draftId, model2);
22584
+ for (const mode of creationModes)
22585
+ Object.defineProperty(mode, draftIdentity, {
22586
+ configurable: true,
22587
+ enumerable: true,
22588
+ value: draftId
22589
+ });
22590
+ }
22591
+ },
22592
+ dispose() {
22593
+ draftModels.clear();
22594
+ if (manager.startConversation === routedStart)
22595
+ manager.startConversation = originalStart;
22596
+ if (creation.createConversation === wrapped)
22597
+ creation.createConversation = original;
22598
+ }
22599
+ };
22600
+ }
22601
+
22450
22602
  // packages/desktop-control/dist/renderer-draft-prewarm-runtime.js
22451
- function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewarmedThreadManager, isCurrentManager, retainResponses = retainRendererHostResponses) {
22603
+ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewarmedThreadManager, isCurrentManager, retainResponses = retainRendererHostResponses, isolateConsumption = isolateRendererPrewarmConsumption) {
22452
22604
  let disposed = false;
22453
22605
  const originalSend = bridge.sendRequest;
22454
22606
  const originalPrewarm = bridge.prewarmThreadStart;
@@ -22838,25 +22990,15 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
22838
22990
  return false;
22839
22991
  return selectedModel !== null && (method.startsWith("thread/") || method.startsWith("turn/") || method.startsWith("review/"));
22840
22992
  };
22841
- const routeThreadStart = (parameters) => {
22842
- if (!isRecord19(parameters) || parameters.ephemeral === true) {
22843
- return parameters;
22844
- }
22845
- return {
22846
- ...parameters,
22847
- ...selectedModel === null ? {} : { model: selectedModel }
22848
- };
22849
- };
22850
22993
  const routedSend = (method, parameters, options2) => {
22851
22994
  if (method === "turn/start" || method === "thread/resume" || method === "codexhost/thread/command/execute") {
22852
22995
  const threadId2 = threadIdFromParameters(parameters);
22853
22996
  if (threadId2)
22854
22997
  externalPrewarms.delete(threadId2);
22855
22998
  }
22856
- const routedParameters = method === "thread/start" ? routeThreadStart(parameters) : parameters;
22857
- const sendBridged = () => initializeBridge().then(() => enqueueBridgeRequest(method, routedParameters, options2));
22858
- const sendDirect = () => options2 === void 0 ? originalSend.call(bridge, method, routedParameters) : originalSend.call(bridge, method, routedParameters, options2);
22859
- const unresolvedThreadId = shouldResolveThreadOwnership(method, routedParameters);
22999
+ const sendBridged = () => initializeBridge().then(() => enqueueBridgeRequest(method, parameters, options2));
23000
+ const sendDirect = () => options2 === void 0 ? originalSend.call(bridge, method, parameters) : originalSend.call(bridge, method, parameters, options2);
23001
+ const unresolvedThreadId = shouldResolveThreadOwnership(method, parameters);
22860
23002
  if (unresolvedThreadId) {
22861
23003
  return resolveThreadOwnership(unresolvedThreadId).then((owner) => owner === "external" ? sendBridged() : sendDirect(), (error51) => {
22862
23004
  if ((method === "thread/read" || method === "thread/resume") && isUnsupportedPosixBridgeSpawn(error51)) {
@@ -22869,7 +23011,7 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
22869
23011
  throw error51;
22870
23012
  });
22871
23013
  }
22872
- return shouldUseBridge(method, routedParameters) ? sendBridged() : sendDirect();
23014
+ return shouldUseBridge(method, parameters) ? sendBridged() : sendDirect();
22873
23015
  };
22874
23016
  const publishDraftWorkspace = (parameters) => {
22875
23017
  if (!isRecord19(parameters) || parameters.ephemeral === true)
@@ -22898,10 +23040,10 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
22898
23040
  for (const threadId2 of externalPrewarms)
22899
23041
  discardExternalPrewarm(threadId2);
22900
23042
  };
23043
+ const restoreConsumption = isolateConsumption(manager, discardExternalPrewarm);
22901
23044
  const routedPrewarm = (parameters, options2) => {
22902
- const routed = routeThreadStart(parameters);
22903
- const external = isRecord19(routed) && routed.ephemeral !== true && typeof routed.model === "string" && routed.model.startsWith("codexhost/");
22904
- const routedParameters = external ? { ...routed, codexhostPrewarm: true } : routed;
23045
+ const external = isRecord19(parameters) && parameters.ephemeral !== true && typeof parameters.model === "string" && parameters.model.startsWith("codexhost/");
23046
+ const routedParameters = external ? { ...parameters, codexhostPrewarm: true } : parameters;
22905
23047
  const generation = prewarmGeneration;
22906
23048
  publishDraftWorkspace(routedParameters);
22907
23049
  const pending = shouldUseBridge("thread/start", routedParameters) ? routedSend("thread/start", routedParameters, options2) : options2 === void 0 ? originalPrewarm.call(bridge, routedParameters) : originalPrewarm.call(bridge, routedParameters, options2);
@@ -22957,6 +23099,7 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
22957
23099
  const policy = Object.freeze({
22958
23100
  state: "ready",
22959
23101
  hostId: hostId2,
23102
+ scopedCreation: restoreConsumption !== null,
22960
23103
  owns(candidateManager, candidate, candidateHostId, candidatePrewarmedThreadManager, requiresCurrentManager) {
22961
23104
  return !disposed && candidateManager === manager && candidate === bridge && candidateHostId === hostId2 && candidatePrewarmedThreadManager === prewarmedThreadManager && requiresCurrentManager === !!isCurrentManager;
22962
23105
  },
@@ -22965,12 +23108,13 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
22965
23108
  throw new Error("Renderer request manager is retired");
22966
23109
  return manager;
22967
23110
  },
22968
- select(model2) {
23111
+ select(model2, draftId, creationModes) {
22969
23112
  if (disposed || isCurrentManager && !isCurrentManager())
22970
23113
  throw new Error("Renderer request manager is retired");
22971
23114
  if (model2 !== null && (typeof model2 !== "string" || !model2.startsWith("codexhost/"))) {
22972
23115
  throw new Error("Draft route Model must be a codexhost transport carrier");
22973
23116
  }
23117
+ restoreConsumption?.selectDraft(draftId, model2, creationModes);
22974
23118
  if (selectedModel === model2)
22975
23119
  return false;
22976
23120
  selectedModel = model2;
@@ -22993,6 +23137,7 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
22993
23137
  disposed = true;
22994
23138
  prewarmGeneration += 1;
22995
23139
  retireResponses();
23140
+ restoreConsumption?.dispose();
22996
23141
  if (bridge.sendRequest === routedSend)
22997
23142
  bridge.sendRequest = originalSend;
22998
23143
  if (bridge.prewarmThreadStart === routedPrewarm) {
@@ -23252,12 +23397,14 @@ function directRendererInstaller() {
23252
23397
  const resolveRendererHostManager = ${resolveRendererHostManager.toString()};
23253
23398
  const retainRendererHostResponses = ${retainRendererHostResponses.toString()};
23254
23399
  const createDraftPrewarmPolicyBridge = ${createDraftPrewarmPolicyBridge.toString()};
23400
+ const isolateRendererPrewarmConsumption = ${isolateRendererPrewarmConsumption.toString()};
23255
23401
  const routing = (${installRendererHostRouting.toString()})(
23256
23402
  document, window,
23257
23403
  (root) => discoverRendererHosts(root, committedReactAncestors, requestManagerFromHookState),
23258
23404
  (discovery, hostId) => resolveRendererHostManager(discovery, hostId, requestManagerFromHookState),
23259
23405
  (manager, bridge, hostId, target, prewarmed, isCurrent) => createDraftPrewarmPolicyBridge(
23260
23406
  manager, bridge, hostId, target, prewarmed, isCurrent, retainRendererHostResponses,
23407
+ isolateRendererPrewarmConsumption,
23261
23408
  ),
23262
23409
  );
23263
23410
  // Publish a default draft policy only when its Host is unambiguous. Host
@@ -24474,9 +24621,9 @@ function parseModelPriceOverrides(value2) {
24474
24621
  if (key.length === 0 || !isRecord3(entry)) {
24475
24622
  throw new Error(`Price override '${key}' is invalid`);
24476
24623
  }
24477
- for (const field of Object.keys(entry)) {
24478
- if (!["input", "output", "cacheRead", "cacheWrite", "cacheWrite1h"].includes(field)) {
24479
- throw new Error(`Price override '${key}' contains unknown field '${field}'`);
24624
+ for (const field2 of Object.keys(entry)) {
24625
+ if (!["input", "output", "cacheRead", "cacheWrite", "cacheWrite1h"].includes(field2)) {
24626
+ throw new Error(`Price override '${key}' contains unknown field '${field2}'`);
24480
24627
  }
24481
24628
  }
24482
24629
  const input = price(entry.input);
@@ -24485,11 +24632,11 @@ function parseModelPriceOverrides(value2) {
24485
24632
  throw new Error(`Price override '${key}' needs non-negative 'input' and 'output'`);
24486
24633
  }
24487
24634
  const resolved = { input, output };
24488
- for (const field of ["cacheRead", "cacheWrite", "cacheWrite1h"]) {
24489
- if (entry[field] === void 0) continue;
24490
- const candidate = price(entry[field]);
24491
- if (candidate === null) throw new Error(`Price override '${key}' has invalid '${field}'`);
24492
- resolved[field] = candidate;
24635
+ for (const field2 of ["cacheRead", "cacheWrite", "cacheWrite1h"]) {
24636
+ if (entry[field2] === void 0) continue;
24637
+ const candidate = price(entry[field2]);
24638
+ if (candidate === null) throw new Error(`Price override '${key}' has invalid '${field2}'`);
24639
+ resolved[field2] = candidate;
24493
24640
  }
24494
24641
  overrides.set(key, resolved);
24495
24642
  }
@@ -25180,6 +25327,42 @@ function parseHarnessAccountCredits(value2) {
25180
25327
  return parsed2.success ? parsed2.data : null;
25181
25328
  }
25182
25329
 
25330
+ // packages/harness-adapter/dist/question.js
25331
+ function invalidRequest(message2) {
25332
+ return { code: "invalidRequest", message: message2, retryable: false };
25333
+ }
25334
+ function validateHostQuestionResponse(interaction, response) {
25335
+ const questionIds = new Set(interaction.questions.map(({ id: id2 }) => id2));
25336
+ if (response.cancelled) {
25337
+ return Object.keys(response.answers).length === 0 ? null : invalidRequest("Cancelled Question Response must not contain answers");
25338
+ }
25339
+ for (const answerId of Object.keys(response.answers)) {
25340
+ if (!questionIds.has(answerId)) {
25341
+ return invalidRequest("Question Response contains an unknown Question ID");
25342
+ }
25343
+ }
25344
+ for (const question of interaction.questions) {
25345
+ const answers = response.answers[question.id] ?? [];
25346
+ if (!question.optional && answers.length === 0) {
25347
+ return invalidRequest("Question Response omits a required answer");
25348
+ }
25349
+ if (question.type === "text") {
25350
+ if (answers.length > 1) {
25351
+ return invalidRequest("Text Question accepts at most one answer");
25352
+ }
25353
+ continue;
25354
+ }
25355
+ if (!question.multiple && answers.length > 1) {
25356
+ return invalidRequest("Single-choice Question accepts at most one answer");
25357
+ }
25358
+ const declared = new Set(question.options.map(({ value: value2 }) => value2));
25359
+ if (!question.allowOther && answers.some((answer) => !declared.has(answer))) {
25360
+ return invalidRequest("Question Response contains an undeclared choice");
25361
+ }
25362
+ }
25363
+ return null;
25364
+ }
25365
+
25183
25366
  // packages/harness-adapter/dist/output-channel.js
25184
25367
  var HarnessOutputChannel = class {
25185
25368
  outputs;
@@ -25286,26 +25469,26 @@ function parseHostUsage(value2) {
25286
25469
  }
25287
25470
  }
25288
25471
  const indicators = value2.composerIndicators === void 0 ? {} : { composerIndicators: composerIndicatorsSchema.parse(value2.composerIndicators) };
25289
- for (const field of [
25472
+ for (const field2 of [
25290
25473
  "totalCredits",
25291
25474
  "contextUsagePercent",
25292
25475
  "apiOutputTokensPerSecond"
25293
25476
  ]) {
25294
- const candidate = value2[field];
25477
+ const candidate = value2[field2];
25295
25478
  if (candidate !== void 0 && (typeof candidate !== "number" || !Number.isFinite(candidate) || candidate < 0)) {
25296
- throw new Error(`Harness Usage '${field}' must be a finite non-negative number`);
25479
+ throw new Error(`Harness Usage '${field2}' must be a finite non-negative number`);
25297
25480
  }
25298
25481
  }
25299
- for (const field of tokenFields) {
25300
- const candidate = value2[field];
25482
+ for (const field2 of tokenFields) {
25483
+ const candidate = value2[field2];
25301
25484
  if (candidate !== void 0 && (typeof candidate !== "number" || !Number.isSafeInteger(candidate) || candidate < 0)) {
25302
- throw new Error(`Harness Usage '${field}' must be a non-negative safe integer`);
25485
+ throw new Error(`Harness Usage '${field2}' must be a non-negative safe integer`);
25303
25486
  }
25304
25487
  }
25305
- for (const field of safeIntegerFields) {
25306
- const candidate = value2[field];
25488
+ for (const field2 of safeIntegerFields) {
25489
+ const candidate = value2[field2];
25307
25490
  if (candidate !== void 0 && (typeof candidate !== "number" || !Number.isSafeInteger(candidate) || candidate < 0)) {
25308
- throw new Error(`Harness Usage '${field}' must be a non-negative safe integer`);
25491
+ throw new Error(`Harness Usage '${field2}' must be a non-negative safe integer`);
25309
25492
  }
25310
25493
  }
25311
25494
  if (value2.outputTokensPerSecond !== void 0 && (typeof value2.outputTokensPerSecond !== "number" || !Number.isFinite(value2.outputTokensPerSecond) || value2.outputTokensPerSecond < 0)) {
@@ -25314,10 +25497,10 @@ function parseHostUsage(value2) {
25314
25497
  if (value2.totalCostUsd !== void 0 && (typeof value2.totalCostUsd !== "number" || !Number.isFinite(value2.totalCostUsd) || value2.totalCostUsd < 0)) {
25315
25498
  throw new Error("Harness Usage 'totalCostUsd' must be a finite non-negative number");
25316
25499
  }
25317
- for (const field of percentFields) {
25318
- const candidate = value2[field];
25500
+ for (const field2 of percentFields) {
25501
+ const candidate = value2[field2];
25319
25502
  if (candidate !== void 0 && (typeof candidate !== "number" || !Number.isFinite(candidate) || candidate < 0 || candidate > 100)) {
25320
- throw new Error(`Harness Usage '${field}' must be between 0 and 100`);
25503
+ throw new Error(`Harness Usage '${field2}' must be between 0 and 100`);
25321
25504
  }
25322
25505
  }
25323
25506
  if (value2.sessionCacheUsage !== void 0) {
@@ -25388,19 +25571,19 @@ function parseHostUsageRequest(value2) {
25388
25571
  if (typeof value2.requestId !== "string" || value2.requestId.length === 0) {
25389
25572
  throw new Error("Harness Usage request 'requestId' must be a non-empty string");
25390
25573
  }
25391
- for (const field of ["model", "provider"]) {
25392
- const candidate = value2[field];
25574
+ for (const field2 of ["model", "provider"]) {
25575
+ const candidate = value2[field2];
25393
25576
  if (candidate !== void 0 && (typeof candidate !== "string" || candidate.length === 0)) {
25394
- throw new Error(`Harness Usage request '${field}' must be a non-empty string`);
25577
+ throw new Error(`Harness Usage request '${field2}' must be a non-empty string`);
25395
25578
  }
25396
25579
  }
25397
25580
  if (value2.historical !== void 0 && typeof value2.historical !== "boolean") {
25398
25581
  throw new Error("Harness Usage request 'historical' must be a boolean");
25399
25582
  }
25400
- for (const field of requestTokenFields) {
25401
- const candidate = value2[field];
25583
+ for (const field2 of requestTokenFields) {
25584
+ const candidate = value2[field2];
25402
25585
  if (candidate !== void 0 && (typeof candidate !== "number" || !Number.isSafeInteger(candidate) || candidate < 0)) {
25403
- throw new Error(`Harness Usage request '${field}' must be a non-negative safe integer`);
25586
+ throw new Error(`Harness Usage request '${field2}' must be a non-negative safe integer`);
25404
25587
  }
25405
25588
  }
25406
25589
  if (value2.inputTokens === void 0 || value2.outputTokens === void 0) {
@@ -25916,10 +26099,15 @@ function processIdentity(pid) {
25916
26099
  }
25917
26100
  const query = [
25918
26101
  "$ErrorActionPreference = 'Stop'",
25919
- `$process = Get-Process -Id ${pid}`,
25920
- "$process | Select-Object Path, StartTime | ConvertTo-Json -Compress"
26102
+ `$process = Get-CimInstance -ClassName Win32_Process -Filter 'ProcessId = ${pid}'`,
26103
+ "if ($null -ne $process) { [pscustomobject]@{ Path = $process.ExecutablePath; StartTime = $(if ($null -ne $process.CreationDate) { $process.CreationDate.ToUniversalTime().ToString('o', [Globalization.CultureInfo]::InvariantCulture) } else { $null }) } | ConvertTo-Json -Compress }"
25921
26104
  ].join("; ");
25922
- const result = execFileSync("powershell.exe", ["-NoProfile", "-NonInteractive", "-Command", query], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], windowsHide: true }).trim();
26105
+ const result = execFileSync("powershell.exe", ["-NoProfile", "-NonInteractive", "-Command", query], {
26106
+ encoding: "utf8",
26107
+ stdio: ["ignore", "pipe", "ignore"],
26108
+ windowsHide: true,
26109
+ timeout: 5e3
26110
+ }).trim();
25923
26111
  if (!result)
25924
26112
  return { executablePath: null, startedAt: null };
25925
26113
  const parsed2 = JSON.parse(result);
@@ -26435,13 +26623,17 @@ var MappingStore = class {
26435
26623
  await this.#enqueue(() => this.#remove(hostThreadId));
26436
26624
  }
26437
26625
  async #remove(hostThreadId) {
26438
- if (!this.#records.has(hostThreadId))
26626
+ const current = this.#records.get(hostThreadId);
26627
+ if (!current)
26439
26628
  return;
26440
- await Promise.all([
26441
- rm10(this.#recordPath(hostThreadId), { force: true }),
26442
- rm10(this.#backupPath(hostThreadId), { force: true }),
26443
- rm10(this.#metadataPath(hostThreadId), { force: true })
26444
- ]);
26629
+ await rm10(this.#recordPath(hostThreadId), { force: true });
26630
+ try {
26631
+ await rm10(this.#backupPath(hostThreadId), { force: true });
26632
+ await rm10(this.#metadataPath(hostThreadId), { force: true });
26633
+ } catch (error51) {
26634
+ await this.#replaceFile(this.#recordPath(hostThreadId), current, false);
26635
+ throw error51;
26636
+ }
26445
26637
  this.#records.delete(hostThreadId);
26446
26638
  this.#rebuildIndexes();
26447
26639
  }
@@ -26790,17 +26982,17 @@ var ELLIPSIS = "…";
26790
26982
  function isRecord7(value2) {
26791
26983
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
26792
26984
  }
26793
- function boundedText(value2, field, maxLength) {
26985
+ function boundedText(value2, field2, maxLength) {
26794
26986
  const text = value2.trim();
26795
26987
  if (text.length === 0 || text.length > maxLength) {
26796
- throw new Error(`Host Approval ${field} must contain 1 to ${maxLength} characters`);
26988
+ throw new Error(`Host Approval ${field2} must contain 1 to ${maxLength} characters`);
26797
26989
  }
26798
26990
  return text;
26799
26991
  }
26800
- function clampedText(value2, field, maxLength) {
26992
+ function clampedText(value2, field2, maxLength) {
26801
26993
  const text = value2.trim();
26802
26994
  if (text.length === 0) {
26803
- throw new Error(`Host Approval ${field} must contain at least 1 character`);
26995
+ throw new Error(`Host Approval ${field2} must contain at least 1 character`);
26804
26996
  }
26805
26997
  const characters = [...text];
26806
26998
  if (characters.length <= maxLength)
@@ -28015,9 +28207,9 @@ function nestedString(value2, keys, preserveText = false) {
28015
28207
  if (!isRecord10(value2))
28016
28208
  return void 0;
28017
28209
  for (const key of keys) {
28018
- const field = value2[key];
28019
- if (typeof field === "string" && (preserveText || field.trim().length > 0))
28020
- return preserveText ? field : field.trim();
28210
+ const field2 = value2[key];
28211
+ if (typeof field2 === "string" && (preserveText || field2.trim().length > 0))
28212
+ return preserveText ? field2 : field2.trim();
28021
28213
  }
28022
28214
  for (const wrapper of ["input", "arguments", "params"]) {
28023
28215
  const nested = nestedString(value2[wrapper], keys, preserveText);
@@ -31410,6 +31602,22 @@ var SessionImportRequests = class {
31410
31602
  }
31411
31603
  };
31412
31604
 
31605
+ // packages/host-runtime/src/shared-question.ts
31606
+ function usesSharedQuestionCard(interaction) {
31607
+ return interaction.questions.some((question) => question.type === "choice" && question.multiple);
31608
+ }
31609
+ function sharedQuestion(interaction) {
31610
+ return threadQuestionSchema.parse(interaction);
31611
+ }
31612
+ function validateSharedQuestionResponse(interaction, response) {
31613
+ const error51 = validateHostQuestionResponse(interaction, response);
31614
+ if (error51) throw new Error(error51.message);
31615
+ for (const values of Object.values(response.answers)) {
31616
+ if (new Set(values).size !== values.length) throw new Error("Duplicate Question answers");
31617
+ if (values.some((value2) => !value2.trim())) throw new Error("Empty Question answer");
31618
+ }
31619
+ }
31620
+
31413
31621
  // packages/host-runtime/src/external-thread-history.ts
31414
31622
  var DEFAULT_PAGE_SIZE2 = 25;
31415
31623
  var MAX_PAGE_SIZE2 = 100;
@@ -32367,7 +32575,7 @@ var UsageMeter = class {
32367
32575
  derive(native, prices) {
32368
32576
  const usage = Object.fromEntries(
32369
32577
  Object.entries(native ?? {}).filter(
32370
- ([field]) => !hostDerivedUsageFields.includes(field)
32578
+ ([field2]) => !hostDerivedUsageFields.includes(field2)
32371
32579
  )
32372
32580
  );
32373
32581
  const sessionCacheUsage = usage.sessionCacheUsage;
@@ -32589,6 +32797,19 @@ var ExternalThreadRuntime = class {
32589
32797
  this.#threads.delete(threadId2);
32590
32798
  this.#steeredTurnIds.delete(threadId2);
32591
32799
  }
32800
+ /** Confirm release before forgetting either the Session owner or its persisted mapping. */
32801
+ async deleteThread(hostThreadId) {
32802
+ await this.#withLifecycle(hostThreadId, async () => {
32803
+ const thread = this.#threads.get(hostThreadId);
32804
+ if (thread) {
32805
+ thread.sessionUnavailable = true;
32806
+ thread.stateObserver.fault(new Error("External Thread is being deleted"));
32807
+ await this.#lifecycle.release(hostThreadId, thread.session, thread.outputTask);
32808
+ }
32809
+ this.remove(hostThreadId);
32810
+ await this.#repository.removeThread(hostThreadId);
32811
+ });
32812
+ }
32592
32813
  clear() {
32593
32814
  this.#threads.clear();
32594
32815
  this.#steeredTurnIds.clear();
@@ -34059,10 +34280,10 @@ var HarnessDelegationCoordinator = class {
34059
34280
  }
34060
34281
  };
34061
34282
  });
34062
- const [field, direction] = input.sort.split("-");
34283
+ const [field2, direction] = input.sort.split("-");
34063
34284
  rows.sort((left, right) => {
34064
- const leftTimestamp = field === "created" ? left.createdAt : left.updatedAt;
34065
- const rightTimestamp = field === "created" ? right.createdAt : right.updatedAt;
34285
+ const leftTimestamp = field2 === "created" ? left.createdAt : left.updatedAt;
34286
+ const rightTimestamp = field2 === "created" ? right.createdAt : right.updatedAt;
34066
34287
  const leftTime = Date.parse(leftTimestamp ?? "");
34067
34288
  const rightTime = Date.parse(rightTimestamp ?? "");
34068
34289
  return direction === "asc" ? leftTime - rightTime : rightTime - leftTime;
@@ -37461,9 +37682,9 @@ var RequestRouteObservationTracker = class {
37461
37682
  };
37462
37683
 
37463
37684
  // packages/host-runtime/src/external-thread-list.ts
37464
- function unixTimestamp(value2, field) {
37685
+ function unixTimestamp(value2, field2) {
37465
37686
  const parsed2 = Date.parse(value2);
37466
- if (!Number.isFinite(parsed2)) throw new Error(`External Thread ${field} is invalid`);
37687
+ if (!Number.isFinite(parsed2)) throw new Error(`External Thread ${field2} is invalid`);
37467
37688
  return Math.floor(parsed2 / 1e3);
37468
37689
  }
37469
37690
  function threadId(thread) {
@@ -37473,11 +37694,11 @@ function threadId(thread) {
37473
37694
  return thread.id;
37474
37695
  }
37475
37696
  function threadListTimestamp(thread, sortKey) {
37476
- const field = sortKey === "created_at" ? thread.createdAt : sortKey === "updated_at" ? thread.updatedAt : thread.recencyAt ?? thread.updatedAt;
37477
- if (!Number.isSafeInteger(field)) {
37697
+ const field2 = sortKey === "created_at" ? thread.createdAt : sortKey === "updated_at" ? thread.updatedAt : thread.recencyAt ?? thread.updatedAt;
37698
+ if (!Number.isSafeInteger(field2)) {
37478
37699
  throw new Error(`Thread list row has no valid ${sortKey} timestamp`);
37479
37700
  }
37480
- return field;
37701
+ return field2;
37481
37702
  }
37482
37703
  function compareTimestamp(left, right, direction) {
37483
37704
  if (left === right) return 0;
@@ -38534,16 +38755,7 @@ var AppServerHost = class {
38534
38755
  hasRunningDescendants: (threadId2) => this.#hasRunningSubagents(threadId2),
38535
38756
  idleRelease: {
38536
38757
  queue: this.#desktopRequests,
38537
- onClosed: async (thread) => {
38538
- for (const pending of [...this.#pendingDesktopApprovals.values()]) {
38539
- if (pending.thread === thread)
38540
- await this.#resolveDesktopApproval(pending.interaction.interactionId);
38541
- }
38542
- for (const pending of [...this.#pendingDesktopQuestions.values()]) {
38543
- if (pending.thread === thread)
38544
- await this.#resolveDesktopQuestion(pending.interaction.interactionId);
38545
- }
38546
- },
38758
+ onClosed: (thread) => this.#resolveThreadInteractions(thread),
38547
38759
  canRelease: (thread) => !this.#hasRunningSubagents(thread.id) && !thread.session.hasBackgroundWork?.() && !this.#externalSteering.hasPending(thread.id) && !this.#pendingExternalCommandRequests.has(thread.id) && ![...this.#pendingDesktopApprovals.values()].some(
38548
38760
  (pending) => pending.thread === thread
38549
38761
  ) && ![...this.#pendingDesktopQuestions.values()].some((pending) => pending.thread === thread)
@@ -38733,12 +38945,12 @@ var AppServerHost = class {
38733
38945
  await this.#closeAdapters();
38734
38946
  await this.#externalRuntime.drain();
38735
38947
  for (const pending of [...this.#pendingDesktopApprovals.values()]) {
38736
- await this.#resolveDesktopApproval(pending.interaction.interactionId).catch(
38948
+ await this.#resolveDesktopApproval(pending.interaction.interactionId, pending.thread).catch(
38737
38949
  () => void 0
38738
38950
  );
38739
38951
  }
38740
38952
  for (const pending of [...this.#pendingDesktopQuestions.values()]) {
38741
- await this.#resolveDesktopQuestion(pending.interaction.interactionId).catch(
38953
+ await this.#resolveDesktopQuestion(pending.interaction.interactionId, pending.thread).catch(
38742
38954
  () => void 0
38743
38955
  );
38744
38956
  }
@@ -39298,6 +39510,15 @@ var AppServerHost = class {
39298
39510
  await this.#listThreadOwnership(request);
39299
39511
  return;
39300
39512
  }
39513
+ if (request.method === THREAD_QUESTIONS_LIST_METHOD || request.method === THREAD_QUESTION_RESPOND_METHOD) {
39514
+ const threadId2 = requestObject(request).threadId;
39515
+ this.#dispatchDesktopReply(
39516
+ request,
39517
+ () => this.#handleSharedQuestionRequest(request),
39518
+ request.method === THREAD_QUESTION_RESPOND_METHOD && typeof threadId2 === "string" ? threadId2 : void 0
39519
+ );
39520
+ return;
39521
+ }
39301
39522
  if (request.method === "codexhost/thread/steering/inspect") {
39302
39523
  await this.#inspectThreadSteering(request);
39303
39524
  return;
@@ -41575,29 +41796,23 @@ var AppServerHost = class {
41575
41796
  });
41576
41797
  }
41577
41798
  async #deleteExternalThread(request, location) {
41578
- const thread = location.thread;
41579
- try {
41580
- await this.#repository.removeThread(location.record.hostThreadId);
41581
- } catch {
41582
- await this.#writer.json(rpcError(request, -32081, "External Thread could not be removed"));
41583
- return;
41584
- }
41585
- this.#externalRuntime.remove(location.record.hostThreadId);
41586
- this.#routeObservationTracker.forgetThread(location.record.hostThreadId);
41587
- if (!thread) {
41588
- await this.#writer.json(rpcEnvelope(request, { result: {} }));
41589
- return;
41590
- }
41591
- thread.stateObserver.fault(new Error("External Thread was deleted"));
41592
41799
  try {
41593
- await thread.session.close();
41594
- await thread.outputTask;
41595
- await this.#writer.json(rpcEnvelope(request, { result: {} }));
41800
+ await this.#externalRuntime.deleteThread(location.record.hostThreadId);
41596
41801
  } catch (error51) {
41802
+ if (!(error51 instanceof ExternalSessionReleaseError) && location.thread)
41803
+ await this.#resolveThreadInteractions(location.thread);
41597
41804
  await this.#writer.json(
41598
- rpcError(request, -32075, `External Thread could not close: ${errorMessage4(error51)}`)
41805
+ error51 instanceof ExternalSessionReleaseError ? rpcError(request, -32075, error51.message) : rpcError(request, -32081, "External Thread could not be removed")
41599
41806
  );
41807
+ return;
41600
41808
  }
41809
+ if (location.thread) await this.#resolveThreadInteractions(location.thread);
41810
+ this.#routeObservationTracker.forgetThread(location.record.hostThreadId);
41811
+ await this.#writer.json(rpcEnvelope(request, { result: {} }));
41812
+ await this.#writer.json({
41813
+ method: "thread/deleted",
41814
+ params: { threadId: location.record.hostThreadId }
41815
+ });
41601
41816
  }
41602
41817
  async #readExternalThreadMetadata(request, location) {
41603
41818
  try {
@@ -42226,6 +42441,10 @@ var AppServerHost = class {
42226
42441
  return;
42227
42442
  }
42228
42443
  if (event.type === "session.faulted") {
42444
+ for (const pending of [...this.#pendingDesktopQuestions.values()]) {
42445
+ if (pending.shared && pending.thread === thread)
42446
+ this.#retireDesktopQuestion(pending.interaction.interactionId, thread);
42447
+ }
42229
42448
  this.#externalSteering.fault(thread.id, new Error(event.error.message));
42230
42449
  thread.stateObserver.fault(new Error(event.error.message));
42231
42450
  this.#externalRuntime.markSessionUnavailable(thread);
@@ -42269,9 +42488,15 @@ var AppServerHost = class {
42269
42488
  if (event.type === "interaction.closed" && thread.ignoredInteractionIds.delete(event.interactionId)) {
42270
42489
  return;
42271
42490
  }
42491
+ if (event.type === "turn.completed") {
42492
+ for (const pending of [...this.#pendingDesktopQuestions.values()]) {
42493
+ if (pending.shared && pending.thread === thread && pending.interaction.turnId === event.turnId)
42494
+ this.#retireDesktopQuestion(pending.interaction.interactionId, thread);
42495
+ }
42496
+ }
42272
42497
  if (event.type === "interaction.closed") {
42273
- await this.#resolveDesktopApproval(event.interactionId);
42274
- await this.#resolveDesktopQuestion(event.interactionId);
42498
+ await this.#resolveDesktopApproval(event.interactionId, thread);
42499
+ await this.#resolveDesktopQuestion(event.interactionId, thread);
42275
42500
  }
42276
42501
  const ephemeralTurn = event.type === "turn.completed" && (event.ephemeral === true || thread.ephemeralTurnIds.has(event.turnId));
42277
42502
  if (event.type === "turn.completed" && !ephemeralTurn) {
@@ -42528,7 +42753,7 @@ var AppServerHost = class {
42528
42753
  if (this.#externalRuntime.get(pending.thread.id) !== pending.thread || this.#externalRuntime.idleRelease.failure(pending.thread))
42529
42754
  return true;
42530
42755
  if (this.#options.externalOnly)
42531
- await this.#resolveDesktopApproval(pending.interaction.interactionId);
42756
+ await this.#resolveDesktopApproval(pending.interaction.interactionId, pending.thread);
42532
42757
  else this.#pendingDesktopApprovals.delete(requestId);
42533
42758
  let response;
42534
42759
  try {
@@ -42579,9 +42804,20 @@ var AppServerHost = class {
42579
42804
  }
42580
42805
  return denied.ok;
42581
42806
  }
42582
- async #resolveDesktopApproval(interactionId) {
42807
+ async #resolveThreadInteractions(thread) {
42808
+ for (const pending of [...this.#pendingDesktopApprovals.values()]) {
42809
+ if (pending.thread === thread)
42810
+ await this.#resolveDesktopApproval(pending.interaction.interactionId, thread);
42811
+ }
42812
+ for (const pending of [...this.#pendingDesktopQuestions.values()]) {
42813
+ if (pending.thread === thread)
42814
+ await this.#resolveDesktopQuestion(pending.interaction.interactionId, thread);
42815
+ }
42816
+ }
42817
+ async #resolveDesktopApproval(interactionId, thread) {
42583
42818
  for (const [requestId, pending] of this.#pendingDesktopApprovals) {
42584
- if (pending.interaction.interactionId !== interactionId) continue;
42819
+ if (pending.thread !== thread || pending.interaction.interactionId !== interactionId)
42820
+ continue;
42585
42821
  this.#pendingDesktopApprovals.delete(requestId);
42586
42822
  await this.#writer.json({
42587
42823
  method: "serverRequest/resolved",
@@ -42597,11 +42833,72 @@ var AppServerHost = class {
42597
42833
  this.#nextApprovalRequestId -= 1;
42598
42834
  return requestId;
42599
42835
  }
42836
+ async #handleSharedQuestionRequest(request) {
42837
+ const responding = request.method === THREAD_QUESTION_RESPOND_METHOD;
42838
+ const parsed2 = (responding ? threadQuestionRespondParamsSchema : threadQuestionsListParamsSchema).safeParse(request.params);
42839
+ if (!parsed2.success) {
42840
+ await this.#writer.json(rpcError(request, -32602, "Invalid Question params"));
42841
+ return;
42842
+ }
42843
+ const { threadId: threadId2 } = parsed2.data;
42844
+ const thread = this.#externalRuntime.get(threadId2);
42845
+ const pendingQuestions = () => [...this.#pendingDesktopQuestions.values()].filter(
42846
+ (pending) => pending.shared && pending.thread === thread && pending.interaction.turnId === thread?.activeTurnId && (!Number.isFinite(Date.parse(pending.interaction.expiresAt ?? "")) || Date.parse(pending.interaction.expiresAt ?? "") > Date.now())
42847
+ );
42848
+ if (!responding) {
42849
+ const questions = thread && !thread.sessionUnavailable && !this.#externalRuntime.idleRelease.failure(thread) ? pendingQuestions().map((pending) => sharedQuestion(pending.interaction)) : [];
42850
+ await this.#writer.json(
42851
+ rpcEnvelope(request, { result: jsonValueSchema.parse({ questions }) })
42852
+ );
42853
+ return;
42854
+ }
42855
+ const params = threadQuestionRespondParamsSchema.parse(parsed2.data);
42856
+ try {
42857
+ await this.#externalRuntime.idleRelease.runOperation(threadId2, async () => {
42858
+ const pending = pendingQuestions().find(
42859
+ ({ interaction }) => interaction.interactionId === params.interactionId && interaction.turnId === params.turnId
42860
+ );
42861
+ if (!thread || this.#externalRuntime.get(threadId2) !== thread || thread.sessionUnavailable || this.#externalRuntime.idleRelease.failure(thread) || !pending || pending.responding) {
42862
+ throw new Error("Question is no longer pending on this Thread and Turn");
42863
+ }
42864
+ const response = {
42865
+ type: "question",
42866
+ answers: params.answers,
42867
+ cancelled: params.cancelled
42868
+ };
42869
+ validateSharedQuestionResponse(pending.interaction, response);
42870
+ pending.responding = true;
42871
+ let result;
42872
+ try {
42873
+ result = await thread.session.execute({
42874
+ type: "interaction.respond",
42875
+ interactionId: pending.interaction.interactionId,
42876
+ response
42877
+ });
42878
+ } catch (error51) {
42879
+ this.#retireDesktopQuestion(pending.interaction.interactionId, thread);
42880
+ throw error51;
42881
+ }
42882
+ if (!result.ok) {
42883
+ pending.responding = false;
42884
+ if (result.error.code === "invalidState")
42885
+ this.#retireDesktopQuestion(pending.interaction.interactionId, thread);
42886
+ throw new Error(result.error.message);
42887
+ }
42888
+ this.#retireDesktopQuestion(pending.interaction.interactionId, thread);
42889
+ await this.#writer.json(rpcEnvelope(request, { result: { accepted: true } }));
42890
+ });
42891
+ } catch (error51) {
42892
+ await this.#writer.json(rpcError(request, -32602, errorMessage4(error51)));
42893
+ }
42894
+ }
42600
42895
  async #projectQuestion(thread, interaction) {
42601
42896
  const projection = this.#projectedTurn(thread, interaction.turnId);
42602
42897
  await this.#waitForTurnResponse(thread, interaction.turnId);
42603
42898
  let result;
42899
+ const shared = usesSharedQuestionCard(interaction);
42604
42900
  try {
42901
+ if (shared) sharedQuestion(interaction);
42605
42902
  result = projection.projector.projectQuestion(
42606
42903
  interaction,
42607
42904
  hostItemIdSchema.parse(randomUUID16())
@@ -42625,6 +42922,8 @@ var AppServerHost = class {
42625
42922
  const expiresAtMs = interaction.expiresAt ? Date.parse(interaction.expiresAt) : Number.NaN;
42626
42923
  const timeoutMs = Number.isFinite(expiresAtMs) ? Math.max(0, expiresAtMs - Date.now()) : null;
42627
42924
  const pending = {
42925
+ shared,
42926
+ responding: false,
42628
42927
  thread,
42629
42928
  interaction,
42630
42929
  projection: result.questionRequest,
@@ -42636,10 +42935,11 @@ var AppServerHost = class {
42636
42935
  }, timeoutMs);
42637
42936
  }
42638
42937
  this.#pendingDesktopQuestions.set(requestId, pending);
42938
+ if (shared) return;
42639
42939
  try {
42640
42940
  await this.#writer.json({ id: requestId, ...result.questionRequest.request });
42641
42941
  } catch (error51) {
42642
- this.#retireDesktopQuestion(interaction.interactionId);
42942
+ this.#retireDesktopQuestion(interaction.interactionId, thread);
42643
42943
  await thread.session.execute({
42644
42944
  type: "interaction.respond",
42645
42945
  interactionId: interaction.interactionId,
@@ -42652,12 +42952,12 @@ var AppServerHost = class {
42652
42952
  if (!isRecord18(value2) || !isHostQuestionRequestId(value2.id)) return false;
42653
42953
  const requestId = value2.id;
42654
42954
  const pending = this.#pendingDesktopQuestions.get(requestId);
42655
- if (!pending) return true;
42955
+ if (!pending || pending.shared) return true;
42656
42956
  return this.#externalRuntime.idleRelease.runOperation(pending.thread.id, async () => {
42657
42957
  if (this.#externalRuntime.get(pending.thread.id) !== pending.thread || this.#externalRuntime.idleRelease.failure(pending.thread))
42658
42958
  return true;
42659
42959
  if (this.#options.externalOnly)
42660
- await this.#resolveDesktopQuestion(pending.interaction.interactionId);
42960
+ await this.#resolveDesktopQuestion(pending.interaction.interactionId, pending.thread);
42661
42961
  else this.#pendingDesktopQuestions.delete(requestId);
42662
42962
  if (pending.timeout) clearTimeout(pending.timeout);
42663
42963
  let response;
@@ -42684,7 +42984,8 @@ var AppServerHost = class {
42684
42984
  await this.#externalRuntime.idleRelease.runOperation(pending.thread.id, async () => {
42685
42985
  if (this.#externalRuntime.get(pending.thread.id) !== pending.thread || this.#externalRuntime.idleRelease.failure(pending.thread))
42686
42986
  return;
42687
- await this.#resolveDesktopQuestion(pending.interaction.interactionId);
42987
+ await this.#resolveDesktopQuestion(pending.interaction.interactionId, pending.thread);
42988
+ if (pending.responding) return;
42688
42989
  const result = await pending.thread.session.execute({
42689
42990
  type: "interaction.respond",
42690
42991
  interactionId: pending.interaction.interactionId,
@@ -42695,18 +42996,21 @@ var AppServerHost = class {
42695
42996
  }
42696
42997
  });
42697
42998
  }
42698
- #retireDesktopQuestion(interactionId) {
42999
+ #retireDesktopQuestion(interactionId, thread) {
42699
43000
  for (const [requestId, pending] of this.#pendingDesktopQuestions) {
42700
- if (pending.interaction.interactionId !== interactionId) continue;
43001
+ if (pending.thread !== thread || pending.interaction.interactionId !== interactionId)
43002
+ continue;
42701
43003
  if (pending.timeout) clearTimeout(pending.timeout);
42702
43004
  this.#pendingDesktopQuestions.delete(requestId);
42703
43005
  }
42704
43006
  }
42705
- async #resolveDesktopQuestion(interactionId) {
43007
+ async #resolveDesktopQuestion(interactionId, thread) {
42706
43008
  for (const [requestId, pending] of this.#pendingDesktopQuestions) {
42707
- if (pending.interaction.interactionId !== interactionId) continue;
43009
+ if (pending.thread !== thread || pending.interaction.interactionId !== interactionId)
43010
+ continue;
42708
43011
  if (pending.timeout) clearTimeout(pending.timeout);
42709
43012
  this.#pendingDesktopQuestions.delete(requestId);
43013
+ if (pending.shared) continue;
42710
43014
  await this.#writer.json({
42711
43015
  method: "serverRequest/resolved",
42712
43016
  params: { threadId: pending.thread.id, requestId }
@@ -44486,10 +44790,10 @@ var DelegationControlRegistry = class {
44486
44790
  );
44487
44791
  }
44488
44792
  #compareThreads(left, right, sort) {
44489
- const field = sort.startsWith("created") ? "createdAt" : "updatedAt";
44793
+ const field2 = sort.startsWith("created") ? "createdAt" : "updatedAt";
44490
44794
  const direction = sort.endsWith("asc") ? 1 : -1;
44491
- const leftValue = left[field] ? Date.parse(left[field]) : 0;
44492
- const rightValue = right[field] ? Date.parse(right[field]) : 0;
44795
+ const leftValue = left[field2] ? Date.parse(left[field2]) : 0;
44796
+ const rightValue = right[field2] ? Date.parse(right[field2]) : 0;
44493
44797
  return (leftValue - rightValue) * direction || left.threadId.localeCompare(right.threadId);
44494
44798
  }
44495
44799
  async #matching(predicate) {
@@ -45714,7 +46018,7 @@ function createHostUpdateCoordinator(options2) {
45714
46018
  onPrepared
45715
46019
  });
45716
46020
  }
45717
- if (platform !== "darwin") await manager.start(prepared2);
46021
+ if (platform !== "darwin" && platform !== "win32") await manager.start(prepared2);
45718
46022
  } catch (error51) {
45719
46023
  await lock.release();
45720
46024
  rejectPrepared(error51);
@@ -45797,13 +46101,13 @@ function parseHarnessUsageEntry(value2) {
45797
46101
  }
45798
46102
  if (!tokenCount(entry.inputTokens) || !tokenCount(entry.outputTokens))
45799
46103
  return null;
45800
- for (const field of [
46104
+ for (const field2 of [
45801
46105
  "cachedInputTokens",
45802
46106
  "cacheWriteInputTokens",
45803
46107
  "cacheWrite1hInputTokens",
45804
46108
  "reasoningOutputTokens"
45805
46109
  ]) {
45806
- if (entry[field] !== void 0 && !tokenCount(entry[field]))
46110
+ if (entry[field2] !== void 0 && !tokenCount(entry[field2]))
45807
46111
  return null;
45808
46112
  }
45809
46113
  const cached2 = entry.cachedInputTokens ?? 0;
@@ -46016,6 +46320,8 @@ function emptyTotals() {
46016
46320
  cachedInputTokens: 0,
46017
46321
  cacheWriteInputTokens: 0,
46018
46322
  cacheKnownInputTokens: 0,
46323
+ cacheHitCachedInputTokens: 0,
46324
+ cacheHitInputTokens: 0,
46019
46325
  outputTokens: 0,
46020
46326
  reasoningOutputTokens: 0,
46021
46327
  costUsd: 0,
@@ -46032,6 +46338,10 @@ function addEntry(totals2, entry, cost) {
46032
46338
  totals2.inputTokens += entry.inputTokens;
46033
46339
  totals2.outputTokens += entry.outputTokens;
46034
46340
  totals2.reasoningOutputTokens += entry.reasoningOutputTokens ?? 0;
46341
+ if (entry.cachedInputTokens !== void 0) {
46342
+ totals2.cacheHitCachedInputTokens += entry.cachedInputTokens;
46343
+ totals2.cacheHitInputTokens += entry.inputTokens;
46344
+ }
46035
46345
  if (entry.cachedInputTokens !== void 0 && entry.cacheWriteInputTokens !== void 0) {
46036
46346
  totals2.cachedInputTokens += entry.cachedInputTokens;
46037
46347
  totals2.cacheWriteInputTokens += entry.cacheWriteInputTokens;
@@ -47744,6 +48054,7 @@ async function runRemoteHostCli(input) {
47744
48054
  var HARNESS_BROKER_PROTOCOL_VERSION = 1;
47745
48055
  var HARNESS_BROKER_MAX_FRAME_BYTES = 8 * 1024 * 1024;
47746
48056
  var HARNESS_BROKER_MAX_PENDING_REQUESTS = 32;
48057
+ var HARNESS_BROKER_SESSION_IMPORT_PAGE_SIZE = 100;
47747
48058
  var HARNESS_BROKER_IDLE_TIMEOUT_MS = 60 * 60 * 1e3;
47748
48059
  var HARNESS_BROKER_RETIRING_ERROR_CODE = "brokerRetiring";
47749
48060
  var harnessBrokerMethodSchema = external_exports.enum([
@@ -47751,6 +48062,8 @@ var harnessBrokerMethodSchema = external_exports.enum([
47751
48062
  "adapter.inspectAccount",
47752
48063
  "adapter.credits",
47753
48064
  "adapter.open",
48065
+ "adapter.sessionImport.list",
48066
+ "adapter.sessionImport.resolve",
47754
48067
  "adapter.subagent.readSnapshot",
47755
48068
  "session.readSnapshot",
47756
48069
  "session.readCapabilities",
@@ -47856,29 +48169,6 @@ function consumeBrokerFrames(socket, onFrame, onError) {
47856
48169
  });
47857
48170
  }
47858
48171
 
47859
- // packages/harness-broker/dist/paths.js
47860
- import os11 from "node:os";
47861
- import path40 from "node:path";
47862
- var HARNESS_BROKER_DESCRIPTOR_ENV = "CODEXHOST_CLAUDE_BROKER_DESCRIPTOR";
47863
- var HARNESS_BROKER_DESCRIPTOR_FILE = "claude-code-broker-v1.json";
47864
- var HARNESS_BROKER_SOCKET_FILE = "claude-code-broker-v1.sock";
47865
- function defaultHarnessBrokerDirectory(environment = process.env) {
47866
- const home = environment.HOME || os11.homedir();
47867
- return path40.join(home, ".codexhost", "harness-broker");
47868
- }
47869
- function defaultHarnessBrokerDescriptorPath(environment = process.env, harnessId = "claude-code") {
47870
- harnessPluginIdSchema.parse(harnessId);
47871
- if (harnessId !== "claude-code")
47872
- return path40.join(defaultHarnessBrokerDirectory(environment), `${harnessId}-broker-v1.json`);
47873
- return environment[HARNESS_BROKER_DESCRIPTOR_ENV] ?? path40.join(defaultHarnessBrokerDirectory(environment), HARNESS_BROKER_DESCRIPTOR_FILE);
47874
- }
47875
- function defaultHarnessBrokerSocketPath(environment = process.env, harnessId = "claude-code") {
47876
- harnessPluginIdSchema.parse(harnessId);
47877
- if (harnessId !== "claude-code")
47878
- return path40.join(defaultHarnessBrokerDirectory(environment), `${harnessId}-broker-v1.sock`);
47879
- return path40.join(defaultHarnessBrokerDirectory(environment), HARNESS_BROKER_SOCKET_FILE);
47880
- }
47881
-
47882
48172
  // packages/harness-broker/dist/validation.js
47883
48173
  var cwdSchema = external_exports.string().min(1).max(16384);
47884
48174
  var brokerEnvironmentSchema = external_exports.object({
@@ -47929,7 +48219,31 @@ var brokerOpenInputSchema = external_exports.discriminatedUnion("kind", [
47929
48219
  forkSchema,
47930
48220
  rollbackSchema
47931
48221
  ]);
47932
- var brokerInspectInputSchema = external_exports.object({ cwd: cwdSchema.optional(), refresh: external_exports.boolean().optional() }).strict();
48222
+ var brokerInspectInputSchema = external_exports.object({
48223
+ cwd: cwdSchema.optional(),
48224
+ refresh: external_exports.boolean().optional(),
48225
+ purpose: external_exports.literal("availability").optional()
48226
+ }).strict();
48227
+ var brokerSessionImportListParamsSchema = external_exports.object({
48228
+ offset: external_exports.number().int().nonnegative().safe(),
48229
+ limit: external_exports.number().int().min(1).max(HARNESS_BROKER_SESSION_IMPORT_PAGE_SIZE)
48230
+ }).strict();
48231
+ var brokerSessionImportResolveParamsSchema = external_exports.object({ nativeSessionId: harnessSessionImportIdSchema }).strict();
48232
+ var brokerSessionImportPageSchema = external_exports.object({
48233
+ candidates: external_exports.array(harnessSessionImportCandidateSchema).max(HARNESS_BROKER_SESSION_IMPORT_PAGE_SIZE),
48234
+ total: external_exports.number().int().nonnegative().safe()
48235
+ }).strict();
48236
+ var brokerSessionImportSourceSchema = external_exports.object({
48237
+ candidate: harnessSessionImportCandidateSchema,
48238
+ nativeRef: nativeSessionRefSchema
48239
+ }).strict().superRefine((source, context) => {
48240
+ if (source.nativeRef.nativeSessionId !== source.candidate.nativeSessionId) {
48241
+ context.addIssue({
48242
+ code: "custom",
48243
+ message: "Session import source identity does not match"
48244
+ });
48245
+ }
48246
+ });
47933
48247
  var textInputSchema = external_exports.object({ type: external_exports.literal("text"), text: external_exports.string().max(4e6) }).strict();
47934
48248
  var turnStartSchema = external_exports.object({
47935
48249
  type: external_exports.literal("turn.start"),
@@ -48100,6 +48414,29 @@ var harnessOutputSchema = external_exports.custom((value2) => {
48100
48414
  return false;
48101
48415
  });
48102
48416
 
48417
+ // packages/harness-broker/dist/paths.js
48418
+ import os11 from "node:os";
48419
+ import path40 from "node:path";
48420
+ var HARNESS_BROKER_DESCRIPTOR_ENV = "CODEXHOST_CLAUDE_BROKER_DESCRIPTOR";
48421
+ var HARNESS_BROKER_DESCRIPTOR_FILE = "claude-code-broker-v1.json";
48422
+ var HARNESS_BROKER_SOCKET_FILE = "claude-code-broker-v1.sock";
48423
+ function defaultHarnessBrokerDirectory(environment = process.env) {
48424
+ const home = environment.HOME || os11.homedir();
48425
+ return path40.join(home, ".codexhost", "harness-broker");
48426
+ }
48427
+ function defaultHarnessBrokerDescriptorPath(environment = process.env, harnessId = "claude-code") {
48428
+ harnessPluginIdSchema.parse(harnessId);
48429
+ if (harnessId !== "claude-code")
48430
+ return path40.join(defaultHarnessBrokerDirectory(environment), `${harnessId}-broker-v1.json`);
48431
+ return environment[HARNESS_BROKER_DESCRIPTOR_ENV] ?? path40.join(defaultHarnessBrokerDirectory(environment), HARNESS_BROKER_DESCRIPTOR_FILE);
48432
+ }
48433
+ function defaultHarnessBrokerSocketPath(environment = process.env, harnessId = "claude-code") {
48434
+ harnessPluginIdSchema.parse(harnessId);
48435
+ if (harnessId !== "claude-code")
48436
+ return path40.join(defaultHarnessBrokerDirectory(environment), `${harnessId}-broker-v1.sock`);
48437
+ return path40.join(defaultHarnessBrokerDirectory(environment), HARNESS_BROKER_SOCKET_FILE);
48438
+ }
48439
+
48103
48440
  // packages/harness-broker/dist/server.js
48104
48441
  import { randomBytes as randomBytes5, randomUUID as randomUUID24 } from "node:crypto";
48105
48442
  import { chmod as chmod6, lstat as lstat10, mkdir as mkdir19, open as open11, readFile as readFile19, rename as rename16, rm as rm18 } from "node:fs/promises";
@@ -48470,11 +48807,74 @@ async function startHarnessBrokerServer(input) {
48470
48807
  const parsed2 = brokerInspectInputSchema.parse(request.params);
48471
48808
  const inspection = await input.adapter.inspect({
48472
48809
  ...parsed2.cwd ? { cwd: parsed2.cwd } : {},
48473
- ...parsed2.refresh !== void 0 ? { refresh: parsed2.refresh } : {}
48810
+ ...parsed2.refresh !== void 0 ? { refresh: parsed2.refresh } : {},
48811
+ ...parsed2.purpose !== void 0 ? { purpose: parsed2.purpose } : {}
48474
48812
  });
48475
48813
  retireWhenIdle = inspection.status !== "ready";
48476
48814
  return inspection;
48477
48815
  }
48816
+ if (request.method === "adapter.sessionImport.list") {
48817
+ const { limit, offset } = brokerSessionImportListParamsSchema.parse(request.params);
48818
+ const capability = input.adapter.sessionImport;
48819
+ if (!capability?.resolveCandidate) {
48820
+ return {
48821
+ ok: false,
48822
+ error: {
48823
+ code: "unsupported",
48824
+ message: "Harness Session import is unavailable",
48825
+ retryable: false
48826
+ }
48827
+ };
48828
+ }
48829
+ if (offset === 0) {
48830
+ delete state.sessionImportCandidates;
48831
+ const result = await capability.listCandidates();
48832
+ if (!result.ok)
48833
+ return result;
48834
+ state.sessionImportCandidates = result.value.map((candidate) => harnessSessionImportCandidateSchema.parse(candidate));
48835
+ }
48836
+ const candidates = state.sessionImportCandidates;
48837
+ if (!candidates) {
48838
+ return {
48839
+ ok: false,
48840
+ error: {
48841
+ code: "invalidState",
48842
+ message: "Session import snapshot is unavailable; refresh the list",
48843
+ retryable: true
48844
+ }
48845
+ };
48846
+ }
48847
+ const page = candidates.slice(offset, offset + limit);
48848
+ const total = candidates.length;
48849
+ if (offset + page.length >= total)
48850
+ delete state.sessionImportCandidates;
48851
+ return { ok: true, value: { candidates: page, total } };
48852
+ }
48853
+ if (request.method === "adapter.sessionImport.resolve") {
48854
+ const { nativeSessionId } = brokerSessionImportResolveParamsSchema.parse(request.params);
48855
+ const capability = input.adapter.sessionImport;
48856
+ if (!capability?.resolveCandidate) {
48857
+ return {
48858
+ ok: false,
48859
+ error: {
48860
+ code: "unsupported",
48861
+ message: "Harness Session import is unavailable",
48862
+ retryable: false
48863
+ }
48864
+ };
48865
+ }
48866
+ const result = await capability.resolveCandidate(nativeSessionId);
48867
+ if (!result.ok)
48868
+ return result;
48869
+ const source = brokerSessionImportSourceSchema.safeParse(result.value);
48870
+ if (!source.success || source.data.nativeRef.harnessId !== input.adapter.harnessId || source.data.candidate.nativeSessionId !== nativeSessionId) {
48871
+ return {
48872
+ ok: false,
48873
+ error: protocolError("Session import source identity does not match")
48874
+ };
48875
+ }
48876
+ return { ok: true, value: source.data };
48877
+ }
48478
48878
  if (request.method === "adapter.subagent.readSnapshot") {
48479
48879
  const subagents = input.adapter.subagents;
48480
48880
  if (!subagents)