@codexhost/cli-darwin-x64 0.13.3 → 0.14.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.
@@ -14662,10 +14662,19 @@ var model = external_exports.string().min(1).max(512);
14662
14662
  var project = external_exports.string().min(1).max(4096);
14663
14663
  var usageStatisticsParamsSchema = external_exports.strictObject({
14664
14664
  range: external_exports.enum(USAGE_STATISTICS_RANGES),
14665
+ /** Display timezone for ranges, dates and hourly buckets; omitted means the Host's local zone. */
14666
+ timeZone: external_exports.string().min(1).max(128).refine((value) => {
14667
+ try {
14668
+ new Intl.DateTimeFormat("en", { timeZone: value });
14669
+ return true;
14670
+ } catch {
14671
+ return false;
14672
+ }
14673
+ }, "Unsupported usage statistics timezone").optional(),
14665
14674
  harness: harness.optional(),
14666
14675
  model: model.nullable().optional(),
14667
14676
  project: project.nullable().optional(),
14668
- /** One local date inside the range. */
14677
+ /** One date in the query timezone inside the range. */
14669
14678
  date: localDate.optional()
14670
14679
  });
14671
14680
  var usageStatisticsTotalsSchema = external_exports.strictObject({
@@ -14701,7 +14710,7 @@ var usageStatisticsSessionSchema = external_exports.strictObject({
14701
14710
  });
14702
14711
  var usageStatisticsResultSchema = external_exports.strictObject({
14703
14712
  range: external_exports.enum(USAGE_STATISTICS_RANGES),
14704
- /** First local date of the range; null for all time. */
14713
+ /** First date in the query timezone (Host local when omitted); null for all time. */
14705
14714
  from: localDate.nullable(),
14706
14715
  to: localDate,
14707
14716
  /** The filters these figures apply, echoed so a late answer to older filters is recognised. */
@@ -14741,7 +14750,7 @@ var usageStatisticsResultSchema = external_exports.strictObject({
14741
14750
  totals: usageStatisticsTotalsSchema,
14742
14751
  /** Each date and Harness of the range: every filter except the day. */
14743
14752
  daily: external_exports.array(external_exports.strictObject({ date: localDate, harness, ...totals })).max(2e5),
14744
- /** Local weekday (0 = Sunday) and hour, all filters applied. */
14753
+ /** Weekday (0 = Sunday) and hour in the query timezone, all filters applied. */
14745
14754
  hourly: external_exports.array(external_exports.strictObject({
14746
14755
  weekday: external_exports.number().int().min(0).max(6),
14747
14756
  hour: external_exports.number().int().min(0).max(23),
@@ -14801,6 +14810,8 @@ var CONSOLE_HOST_METHODS = Object.freeze([
14801
14810
  "codexhost/harness/display-settings/set",
14802
14811
  "codexhost/harness/inspect",
14803
14812
  "codexhost/harness/installation",
14813
+ "codexhost/harness/installation/start",
14814
+ "codexhost/harness/installation/status",
14804
14815
  "codexhost/harness/launch-settings/get",
14805
14816
  "codexhost/harness/launch-settings/set",
14806
14817
  "codexhost/harness/web-ui/open",
@@ -14876,7 +14887,18 @@ var threadManualCompactionStartedSchema = external_exports.strictObject({
14876
14887
  var nonNegativeSafeIntegerSchema = external_exports.number().int().safe().nonnegative();
14877
14888
  var finiteNonNegativeNumberSchema = external_exports.number().finite().nonnegative();
14878
14889
  var cacheHitRatePercentSchema = external_exports.number().finite().min(0).max(100);
14890
+ var indicatorTextSchema = (maximum) => harnessLocalizedTextSchema.refine((entries) => Object.values(entries).every((text2) => text2.length <= maximum));
14891
+ var composerIndicatorsSchema = external_exports.array(external_exports.object({
14892
+ kind: external_exports.literal("countdown"),
14893
+ id: external_exports.string().min(1).max(64),
14894
+ expiresAtUnix: nonNegativeSafeIntegerSchema,
14895
+ label: indicatorTextSchema(256).optional(),
14896
+ tooltip: indicatorTextSchema(1024).optional()
14897
+ }).strict()).max(2).refine((entries) => new Set(entries.map(({ id: id2 }) => id2)).size === entries.length, {
14898
+ message: "Composer indicator IDs must be unique"
14899
+ });
14879
14900
  var threadUsageSnapshotSchema = external_exports.object({
14901
+ composerIndicators: composerIndicatorsSchema.optional(),
14880
14902
  inputTokens: nonNegativeSafeIntegerSchema.optional(),
14881
14903
  cachedInputTokens: nonNegativeSafeIntegerSchema.optional(),
14882
14904
  cacheWriteInputTokens: nonNegativeSafeIntegerSchema.optional(),
@@ -15284,7 +15306,9 @@ var harnessSessionCapabilitiesSchema = external_exports.object({
15284
15306
  }).strict().optional(),
15285
15307
  autonomousTurns: external_exports.object({
15286
15308
  observe: external_exports.boolean()
15287
- }).strict().optional()
15309
+ }).strict().optional(),
15310
+ /** True only when `turn.steer` delivers input into the active Turn through a native primitive. */
15311
+ steer: external_exports.boolean().optional()
15288
15312
  }).strict();
15289
15313
  var harnessConfigurationStateSchema = external_exports.object({
15290
15314
  effectiveModel: harnessModelRefSchema.optional(),
@@ -15331,7 +15355,9 @@ var harnessInspectionSchema = external_exports.union([
15331
15355
  var harnessInspectParamsSchema = external_exports.object({
15332
15356
  harnessId: harnessIdSchema,
15333
15357
  cwd: nonBlankTextSchema2.max(16384).optional(),
15334
- refresh: external_exports.boolean().optional()
15358
+ refresh: external_exports.boolean().optional(),
15359
+ /** `availability` asks only whether the Harness can run; see `InspectHarnessInput.purpose`. */
15360
+ purpose: external_exports.literal("availability").optional()
15335
15361
  }).strict();
15336
15362
  var harnessWebUiOpenParamsSchema = external_exports.object({
15337
15363
  harnessId: harnessIdSchema
@@ -15414,6 +15440,15 @@ var threadOwnershipListResultSchema = external_exports.object({
15414
15440
  seen.add(thread.threadId);
15415
15441
  }
15416
15442
  });
15443
+ var threadSteeringInspectParamsSchema = external_exports.object({
15444
+ threadId: hostThreadIdSchema,
15445
+ /** The text about to be steered; a Harness command always stops and restarts. */
15446
+ text: external_exports.string().optional()
15447
+ }).strict();
15448
+ var threadSteerDeliverySchema = external_exports.enum(["activeTurn", "newTurn"]);
15449
+ var threadSteeringInspectResultSchema = external_exports.object({
15450
+ delivery: external_exports.enum(["official", "activeTurn", "newTurn"])
15451
+ }).strict();
15417
15452
 
15418
15453
  // ../../shared-contracts/dist/harness-plugins.js
15419
15454
  var HARNESS_PLUGIN_MANIFEST_MAX_BYTES = 32 * 1024;
@@ -15515,6 +15550,10 @@ var harnessInstallationStateSchema = external_exports.object({
15515
15550
  latestVersion: external_exports.string().min(1).max(128),
15516
15551
  updateAvailable: external_exports.boolean(),
15517
15552
  canUpdate: external_exports.boolean(),
15553
+ /** Defaults to CLI; some Harnesses ship only inside a desktop application. */
15554
+ versionKind: external_exports.enum(["cli", "application"]).optional(),
15555
+ /** Official download opened by the user; does not imply an automatic installation. */
15556
+ manualUpdateUrl: external_exports.url().max(2048).refine((value) => /^https:\/\/[^/?#@]+(?:[/?#]|$)/iu.test(value), "Manual updates require a credential-free HTTPS URL").optional(),
15518
15557
  // Adapter-owned diagnostic text; UI uses messageCode rather than displaying it verbatim.
15519
15558
  message: external_exports.string().max(2048).optional(),
15520
15559
  messageCode: external_exports.string().min(1).max(128).optional(),
@@ -15522,6 +15561,20 @@ var harnessInstallationStateSchema = external_exports.object({
15522
15561
  notice: harnessLocalizedTextSchema.optional(),
15523
15562
  latestVersionKind: external_exports.enum(["unknown", "tracking-branch"]).optional()
15524
15563
  }).strict();
15564
+ var harnessInstallationTaskParamsSchema = external_exports.object({ taskId: external_exports.string().uuid() }).strict();
15565
+ var harnessInstallationTaskSchema = external_exports.discriminatedUnion("status", [
15566
+ external_exports.object({ taskId: external_exports.string().uuid(), status: external_exports.literal("running") }).strict(),
15567
+ external_exports.object({
15568
+ taskId: external_exports.string().uuid(),
15569
+ status: external_exports.literal("succeeded"),
15570
+ result: harnessInstallationStateSchema
15571
+ }).strict(),
15572
+ external_exports.object({
15573
+ taskId: external_exports.string().uuid(),
15574
+ status: external_exports.literal("failed"),
15575
+ error: external_exports.object({ code: external_exports.number().int(), message: external_exports.string().min(1).max(2048) }).strict()
15576
+ }).strict()
15577
+ ]);
15525
15578
 
15526
15579
  // ../../shared-contracts/dist/codex-accounts.js
15527
15580
  var accountIdSchema = external_exports.string().min(1).max(256).regex(/^[A-Za-z0-9._~-]+$/u);
@@ -16034,6 +16087,7 @@ var usageFields = /* @__PURE__ */ new Set([
16034
16087
  ...safeIntegerFields,
16035
16088
  ...percentFields,
16036
16089
  "sessionCacheUsage",
16090
+ "composerIndicators",
16037
16091
  "totalCostUsd",
16038
16092
  "totalCredits",
16039
16093
  "contextUsagePercent",
@@ -16056,6 +16110,7 @@ function parseHostUsage(value) {
16056
16110
  throw new Error(`Harness Usage contains unknown field '${key}'`);
16057
16111
  }
16058
16112
  }
16113
+ const indicators = value.composerIndicators === void 0 ? {} : { composerIndicators: composerIndicatorsSchema.parse(value.composerIndicators) };
16059
16114
  for (const field of [
16060
16115
  "totalCredits",
16061
16116
  "contextUsagePercent",
@@ -16126,9 +16181,9 @@ function parseHostUsage(value) {
16126
16181
  if (value.costSource !== "publicPrice") {
16127
16182
  throw new Error("Harness Usage 'unpricedModels' must be provided with a 'publicPrice' cost");
16128
16183
  }
16129
- return { ...value, unpricedModels: [...models] };
16184
+ return { ...value, ...indicators, unpricedModels: [...models] };
16130
16185
  }
16131
- return { ...value };
16186
+ return { ...value, ...indicators };
16132
16187
  }
16133
16188
  var requestTokenFields = [
16134
16189
  "inputTokens",
@@ -16327,6 +16382,7 @@ var harnessBrokerMethodSchema = external_exports.enum([
16327
16382
  "adapter.open",
16328
16383
  "adapter.subagent.readSnapshot",
16329
16384
  "session.readSnapshot",
16385
+ "session.readCapabilities",
16330
16386
  "session.refreshUsage",
16331
16387
  "session.execute",
16332
16388
  "session.commands.list",
@@ -16507,6 +16563,11 @@ var turnStartSchema = external_exports.object({
16507
16563
  turnId: hostTurnIdSchema,
16508
16564
  input: external_exports.array(textInputSchema)
16509
16565
  }).strict();
16566
+ var turnSteerSchema = external_exports.object({
16567
+ type: external_exports.literal("turn.steer"),
16568
+ turnId: hostTurnIdSchema,
16569
+ input: external_exports.array(textInputSchema)
16570
+ }).strict();
16510
16571
  var turnCancelSchema = external_exports.object({ type: external_exports.literal("turn.cancel"), turnId: hostTurnIdSchema }).strict();
16511
16572
  var interactionResponseSchema = external_exports.union([
16512
16573
  external_exports.object({
@@ -16532,6 +16593,7 @@ var permissionSelectSchema = external_exports.object({
16532
16593
  }).strict();
16533
16594
  var brokerHostCommandSchema = external_exports.discriminatedUnion("type", [
16534
16595
  turnStartSchema,
16596
+ turnSteerSchema,
16535
16597
  turnCancelSchema,
16536
16598
  interactionRespondSchema,
16537
16599
  modelSelectSchema,
@@ -16724,6 +16786,7 @@ function parseSessionMetadata(value) {
16724
16786
  sessionId: candidate.sessionId,
16725
16787
  sessionGeneration: candidate.sessionGeneration,
16726
16788
  capabilities: harnessSessionCapabilitiesSchema.parse(candidate.capabilities),
16789
+ readCapabilities: candidate.readCapabilities === true,
16727
16790
  initialState: state,
16728
16791
  initialUsage: candidate.initialUsage === null ? null : parseHostUsage(candidate.initialUsage),
16729
16792
  commands: candidate.commands === true
@@ -17075,6 +17138,11 @@ var BrokeredHarnessSession = class {
17075
17138
  event: { type: "session.faulted", error: unavailable(error52.message) }
17076
17139
  });
17077
17140
  }
17141
+ async readCapabilities() {
17142
+ if (!this.#metadata.readCapabilities)
17143
+ return { ...this.capabilities, steer: false };
17144
+ return harnessSessionCapabilitiesSchema.parse(await this.#request("session.readCapabilities", {}));
17145
+ }
17078
17146
  async refreshUsage() {
17079
17147
  await this.#request("session.refreshUsage", {});
17080
17148
  }
@@ -17106,6 +17174,8 @@ var BrokeredHarnessSession = class {
17106
17174
  try {
17107
17175
  return parseHarnessResult(await this.#request("session.execute", { command }));
17108
17176
  } catch (error52) {
17177
+ if (command.type === "turn.steer")
17178
+ throw error52;
17109
17179
  return {
17110
17180
  ok: false,
17111
17181
  error: unavailable(error52 instanceof Error ? error52.message : String(error52))
@@ -17492,10 +17562,13 @@ function usageSessionTitle(value) {
17492
17562
  return void 0;
17493
17563
  if (normalized.length <= MAX_SESSION_TITLE_LENGTH)
17494
17564
  return normalized;
17495
- const characters = [...normalized];
17496
- if (characters.length <= MAX_SESSION_TITLE_LENGTH)
17497
- return normalized;
17498
- return `${characters.slice(0, MAX_SESSION_TITLE_LENGTH - 1).join("").trimEnd()}…`;
17565
+ let title = "";
17566
+ for (const character of normalized) {
17567
+ if (title.length + character.length >= MAX_SESSION_TITLE_LENGTH)
17568
+ break;
17569
+ title += character;
17570
+ }
17571
+ return `${title.trimEnd()}…`;
17499
17572
  }
17500
17573
  function sessionIdOk(value) {
17501
17574
  return typeof value === "string" && value.length > 0 && value.length <= MAX_SESSION_ID_LENGTH;
@@ -17648,6 +17721,31 @@ function createClaudeUsageStatistics(environment) {
17648
17721
  });
17649
17722
  }
17650
17723
 
17724
+ // dist/claude-prompt-cache.js
17725
+ function lastClaudeAssistantResponseUnix(messages) {
17726
+ let latest;
17727
+ for (const entry of messages) {
17728
+ if (typeof entry !== "object" || entry === null || !("type" in entry) || entry.type !== "assistant" || "isSidechain" in entry && entry.isSidechain === true || "parent_tool_use_id" in entry && entry.parent_tool_use_id != null || !("timestamp" in entry) || typeof entry.timestamp !== "string")
17729
+ continue;
17730
+ const time3 = Math.floor(Date.parse(entry.timestamp) / 1e3);
17731
+ if (Number.isSafeInteger(time3) && time3 >= 0)
17732
+ latest = Math.max(latest ?? 0, time3);
17733
+ }
17734
+ return latest;
17735
+ }
17736
+ function claudePromptCacheIndicators(accountCreditsSupported, lastResponseAtUnix) {
17737
+ if (!accountCreditsSupported || lastResponseAtUnix === void 0)
17738
+ return [];
17739
+ return [
17740
+ {
17741
+ kind: "countdown",
17742
+ id: "prompt-cache",
17743
+ expiresAtUnix: lastResponseAtUnix + 3600,
17744
+ label: { en: "Prompt cache", "zh-CN": "提示词缓存" }
17745
+ }
17746
+ ];
17747
+ }
17748
+
17651
17749
  // dist/claude-code-adapter.js
17652
17750
  import { randomUUID as randomUUID5 } from "node:crypto";
17653
17751
  import path16 from "node:path";
@@ -54448,11 +54546,20 @@ function parseResultModelUsage(value) {
54448
54546
  if (!isRecord7(value))
54449
54547
  return void 0;
54450
54548
  const usage = [];
54451
- for (const entry of Object.values(value)) {
54549
+ for (const [model2, entry] of Object.entries(value)) {
54452
54550
  if (!isRecord7(entry) || !safeNonNegativeInteger(entry.inputTokens) || !safeNonNegativeInteger(entry.outputTokens)) {
54453
54551
  return void 0;
54454
54552
  }
54455
- usage.push({ inputTokens: entry.inputTokens, outputTokens: entry.outputTokens });
54553
+ const cacheRead = safeNonNegativeInteger(entry.cacheReadInputTokens) ? entry.cacheReadInputTokens : 0;
54554
+ const cacheWrite = safeNonNegativeInteger(entry.cacheCreationInputTokens) ? entry.cacheCreationInputTokens : 0;
54555
+ const promptTokens = entry.inputTokens + cacheRead + cacheWrite;
54556
+ usage.push({
54557
+ model: model2,
54558
+ inputTokens: entry.inputTokens,
54559
+ outputTokens: entry.outputTokens,
54560
+ ...Number.isSafeInteger(promptTokens) ? { promptTokens } : {},
54561
+ ...safeNonNegativeInteger(entry.contextWindow) && entry.contextWindow > 0 ? { contextWindowTokens: entry.contextWindow } : {}
54562
+ });
54456
54563
  }
54457
54564
  return usage;
54458
54565
  }
@@ -54803,6 +54910,7 @@ var ClaudeNativeTurnAccumulator = class {
54803
54910
  events.push({
54804
54911
  type: "message.completed",
54805
54912
  messageId,
54913
+ localCommand: true,
54806
54914
  ...checkpointId ? { checkpointId } : {}
54807
54915
  });
54808
54916
  }
@@ -55283,6 +55391,10 @@ function conversationMessages(values, sessionId) {
55283
55391
  const messages = [];
55284
55392
  const ids = /* @__PURE__ */ new Set();
55285
55393
  let promptId = null;
55394
+ const occupancy = new ClaudeBackgroundOccupancy();
55395
+ let accumulator = new ClaudeNativeTurnAccumulator();
55396
+ const sends = /* @__PURE__ */ new Set();
55397
+ let pendingNotification = false;
55286
55398
  for (const value of values) {
55287
55399
  if (!isRecord8(value))
55288
55400
  throw new Error("Claude history contains a malformed message");
@@ -55301,8 +55413,46 @@ function conversationMessages(values, sessionId) {
55301
55413
  message: value.message,
55302
55414
  nested: typeof value.parent_tool_use_id === "string" && value.parent_tool_use_id.length > 0,
55303
55415
  interrupted,
55416
+ startsTurn: false,
55304
55417
  syntheticUser: value.type === "user" && (interrupted || value.isSynthetic === true || value.isMeta === true || isTaskNotificationOrigin(value) || value.toolUseResult !== void 0 && value.toolUseResult !== null)
55305
55418
  };
55419
+ const notification = message.type === "user" && !message.nested && (isTaskNotificationOrigin(value) || textParts(message.message.content).some(isTaskNotificationRecord));
55420
+ message.startsTurn = isHumanUser(message) || notification && !occupancy.unsettled && !pendingNotification;
55421
+ if (message.startsTurn) {
55422
+ occupancy.clear();
55423
+ sends.clear();
55424
+ accumulator = new ClaudeNativeTurnAccumulator();
55425
+ }
55426
+ for (const event of accumulator.consume(value).events) {
55427
+ if (event.type === "subagent.started") {
55428
+ if (event.operation === "send") {
55429
+ sends.add(event.callId);
55430
+ if (event.nativeSubagentId)
55431
+ occupancy.occupyAgent(event.nativeSubagentId);
55432
+ } else if (event.background)
55433
+ occupancy.occupySpawn(event.callId, event.nativeSubagentId);
55434
+ } else if (event.type === "subagent.completed") {
55435
+ if (!event.isError && (event.continuesInBackground || sends.has(event.callId))) {
55436
+ occupancy.occupySpawn(event.callId, event.nativeSubagentId);
55437
+ } else
55438
+ occupancy.release(event.callId, event.nativeSubagentId);
55439
+ sends.delete(event.callId);
55440
+ } else if (event.type === "workflow.launched" && event.background && !event.isError) {
55441
+ occupancy.occupySpawn(event.callId, event.taskId);
55442
+ } else if (event.type === "subagent.settled") {
55443
+ occupancy.notify(event.callId, event.nativeSubagentId);
55444
+ }
55445
+ }
55446
+ if (notification)
55447
+ pendingNotification = true;
55448
+ if (message.type === "assistant" && !message.nested) {
55449
+ pendingNotification = false;
55450
+ if (["end_turn", "stop_sequence", "max_tokens"].includes(String(message.message.stop_reason))) {
55451
+ occupancy.releaseContinuations();
55452
+ }
55453
+ }
55454
+ if (interrupted)
55455
+ occupancy.clear();
55306
55456
  messages.push(message);
55307
55457
  if (isHumanUser(message)) {
55308
55458
  promptId = typeof value.promptId === "string" && value.promptId.length > 0 ? value.promptId : null;
@@ -55359,17 +55509,17 @@ function mapClaudeSnapshot(values, sessionId) {
55359
55509
  const turns = [];
55360
55510
  for (let index = 0; index < messages.length; ) {
55361
55511
  const user = messages[index];
55362
- if (!user || !isHumanUser(user)) {
55512
+ if (!user || !user.startsTurn) {
55363
55513
  index += 1;
55364
55514
  continue;
55365
55515
  }
55366
55516
  let end = index + 1;
55367
- while (end < messages.length && !isHumanUser(messages[end]))
55517
+ while (end < messages.length && !messages[end]?.startsTurn)
55368
55518
  end += 1;
55369
55519
  const turnMessages = messages.slice(index, end);
55370
55520
  const outcome = turnOutcome(turnMessages);
55371
55521
  const results = toolResultBlocks(turnMessages);
55372
- const checkpointMessage = turnMessages.findLast(({ type, interrupted }) => type === "assistant" || interrupted);
55522
+ const checkpointMessage = turnMessages.findLast(({ type, interrupted, nested }) => !nested && (type === "assistant" || interrupted));
55373
55523
  let agentMessageOrdinal = 0;
55374
55524
  let reasoningOrdinal = 0;
55375
55525
  let toolOrdinal = 0;
@@ -56533,12 +56683,21 @@ async function closeClaudeProcessGroup(child, timeoutMs) {
56533
56683
  throw new Error("Claude SDK process group did not exit");
56534
56684
  }
56535
56685
 
56686
+ // dist/transport.js
56687
+ var ClaudeSteerMissedTurnError = class extends Error {
56688
+ constructor() {
56689
+ super("Claude Code steer missed the active Turn");
56690
+ this.name = "ClaudeSteerMissedTurnError";
56691
+ }
56692
+ };
56693
+
56536
56694
  // dist/sdk-transport.js
56537
56695
  var CLIENT_APP = "codexhost-claude-code-adapter/0.0.0";
56538
56696
  var SESSION_ENTRYPOINT = "codexhost-sdk";
56539
56697
  var APPROVAL_TITLE_MAX_LENGTH = 120;
56540
56698
  var APPROVAL_DESCRIPTION_MAX_LENGTH = 500;
56541
56699
  var DEFAULT_ABORT_TIMEOUT_MS = 2e3;
56700
+ var DEFAULT_STEER_QUEUED_TIMEOUT_MS = 5e3;
56542
56701
  var WORKFLOW_AGENT_LABEL_LIMIT = 1e3;
56543
56702
  var INTERRUPT_TIMEOUT_MESSAGE = "Claude SDK interrupt timed out";
56544
56703
  var PushableInput = class {
@@ -56794,6 +56953,11 @@ var ClaudeSdkTransport = class {
56794
56953
  #queryFactory;
56795
56954
  #thinkingOptionId;
56796
56955
  #active = null;
56956
+ #steerQueuedTimeoutMs;
56957
+ #nativeSteer = false;
56958
+ /** Root tool calls of the requested Turn that have started and not yet returned a result. */
56959
+ #rootToolCalls = /* @__PURE__ */ new Set();
56960
+ #pendingSteers = /* @__PURE__ */ new Map();
56797
56961
  #autonomous = null;
56798
56962
  #autonomousTurnHandler = null;
56799
56963
  #idleHandler = null;
@@ -56817,6 +56981,7 @@ var ClaudeSdkTransport = class {
56817
56981
  this.sessionId = options.sessionId;
56818
56982
  this.#cwd = options.cwd;
56819
56983
  this.#abortTimeoutMs = options.abortTimeoutMs ?? DEFAULT_ABORT_TIMEOUT_MS;
56984
+ this.#steerQueuedTimeoutMs = options.steerQueuedTimeoutMs ?? DEFAULT_STEER_QUEUED_TIMEOUT_MS;
56820
56985
  this.#closeTimeoutMs = options.closeTimeoutMs;
56821
56986
  this.#command = options.command;
56822
56987
  this.#environment = options.environment ?? process.env;
@@ -56871,7 +57036,8 @@ var ClaudeSdkTransport = class {
56871
57036
  thinking: thinking.enabled ? { type: "adaptive", display: "summarized" } : { type: "disabled" },
56872
57037
  ...thinking.effort ? { effort: thinking.effort } : {},
56873
57038
  pathToClaudeCodeExecutable: executable,
56874
- settingSources: ["user"],
57039
+ // Omitted settingSources loads user, project and local settings like the
57040
+ // Claude Code CLI, so project CLAUDE.md and .claude/skills apply.
56875
57041
  permissionMode: this.#permissionMode,
56876
57042
  ...this.#allowDangerouslySkipPermissions ? { allowDangerouslySkipPermissions: true } : {},
56877
57043
  canUseTool: (toolName, input, options) => this.#canUseTool(toolName, input, options),
@@ -56908,6 +57074,40 @@ var ClaudeSdkTransport = class {
56908
57074
  return null;
56909
57075
  return { commands: this.#slashCommands, skillNames: this.#skillNames };
56910
57076
  }
57077
+ supportsNativeSteer() {
57078
+ return this.#nativeSteer;
57079
+ }
57080
+ /**
57081
+ * `priority: "next"` joins after the current tool call, and a tool result is always followed by
57082
+ * another model request. So a steer written while a root tool call runs folds into this Turn;
57083
+ * one written while Claude streams its final text may instead run as the next Turn.
57084
+ */
57085
+ canSteerActiveTurn() {
57086
+ return this.#nativeSteer && this.#active !== null && this.#rootToolCalls.size > 0;
57087
+ }
57088
+ #observeRootToolCalls(message) {
57089
+ if (!isRecord11(message) || message.parent_tool_use_id != null)
57090
+ return;
57091
+ if (message.type !== "assistant" && message.type !== "user")
57092
+ return;
57093
+ const body = message.message;
57094
+ if (!isRecord11(body) || !Array.isArray(body.content))
57095
+ return;
57096
+ for (const block of body.content) {
57097
+ if (!isRecord11(block))
57098
+ continue;
57099
+ if (message.type === "assistant" && block.type === "tool_use" && typeof block.id === "string") {
57100
+ this.#rootToolCalls.add(block.id);
57101
+ } else if (message.type === "user" && block.type === "tool_result" && typeof block.tool_use_id === "string") {
57102
+ this.#rootToolCalls.delete(block.tool_use_id);
57103
+ }
57104
+ }
57105
+ }
57106
+ #observeNativeCapabilities(message) {
57107
+ if (!isRecord11(message) || message.type !== "system" || message.subtype !== "init")
57108
+ return;
57109
+ this.#nativeSteer = Array.isArray(message.capabilities) && message.capabilities.includes("msg_lifecycle_v1");
57110
+ }
56911
57111
  #observeSlashCommands(message) {
56912
57112
  if (!isRecord11(message) || message.type !== "system")
56913
57113
  return;
@@ -57030,6 +57230,7 @@ var ClaudeSdkTransport = class {
57030
57230
  const unclaimed = this.#autonomous?.events ?? [];
57031
57231
  this.#autonomous = null;
57032
57232
  const promise2 = new Promise((resolve5, reject) => {
57233
+ this.#rootToolCalls.clear();
57033
57234
  this.#active = {
57034
57235
  accumulator: new ClaudeNativeTurnAccumulator(this.#provider ? { provider: this.#provider } : {}),
57035
57236
  onEvent,
@@ -57049,6 +57250,51 @@ var ClaudeSdkTransport = class {
57049
57250
  });
57050
57251
  return promise2;
57051
57252
  }
57253
+ /**
57254
+ * Claude accepts the input with `queued`; Claude Code 2.1.280 then emits `started` after the
57255
+ * current tool call, when `priority: "next"` joins the running Turn. Waiting for `started` would
57256
+ * hold the caller for a whole tool call.
57257
+ *
57258
+ * Once written, the input cannot be recalled: Claude delivers it in this Turn or runs it next.
57259
+ * The Turn ending first therefore does not reject it, and a missing `queued` receipt resolves
57260
+ * after a bounded wait so callers that serialize requests are never held indefinitely.
57261
+ */
57262
+ steer(text2, messageId) {
57263
+ if (this.#closePromise || !this.#started || !this.#query || !this.canSteerActiveTurn()) {
57264
+ return Promise.reject(new ClaudeSteerMissedTurnError());
57265
+ }
57266
+ const promise2 = new Promise((resolve5, reject) => {
57267
+ this.#pendingSteers.set(messageId, { resolve: resolve5, reject, timer: void 0 });
57268
+ });
57269
+ try {
57270
+ this.#input.push({
57271
+ type: "user",
57272
+ message: { role: "user", content: text2 },
57273
+ parent_tool_use_id: null,
57274
+ session_id: this.sessionId,
57275
+ uuid: messageId,
57276
+ origin: { kind: "human" },
57277
+ priority: "next"
57278
+ });
57279
+ } catch {
57280
+ this.#pendingSteers.delete(messageId);
57281
+ return Promise.reject(new ClaudeSteerMissedTurnError());
57282
+ }
57283
+ const pending = this.#pendingSteers.get(messageId);
57284
+ if (pending) {
57285
+ pending.timer = setTimeout(() => this.#acceptSteer(messageId), this.#steerQueuedTimeoutMs);
57286
+ pending.timer.unref?.();
57287
+ }
57288
+ return promise2;
57289
+ }
57290
+ #acceptSteer(messageId) {
57291
+ const pending = this.#pendingSteers.get(messageId);
57292
+ if (!pending)
57293
+ return;
57294
+ this.#pendingSteers.delete(messageId);
57295
+ clearTimeout(pending.timer);
57296
+ pending.resolve();
57297
+ }
57052
57298
  respondToInteraction(response) {
57053
57299
  const pending = this.#interactions.get(response.requestId);
57054
57300
  if (!pending) {
@@ -57220,6 +57466,7 @@ var ClaudeSdkTransport = class {
57220
57466
  }
57221
57467
  }
57222
57468
  async #close() {
57469
+ this.#rejectPendingSteers();
57223
57470
  const failures = [];
57224
57471
  this.#closeInteractions("all", "cancelled");
57225
57472
  try {
@@ -57273,6 +57520,7 @@ var ClaudeSdkTransport = class {
57273
57520
  }
57274
57521
  this.#query = null;
57275
57522
  const active = this.#active;
57523
+ this.#rootToolCalls.clear();
57276
57524
  this.#active = null;
57277
57525
  this.#autonomous = null;
57278
57526
  this.#idleAccumulator = null;
@@ -57327,6 +57575,26 @@ var ClaudeSdkTransport = class {
57327
57575
  await delay(10);
57328
57576
  }
57329
57577
  }
57578
+ #rejectPendingSteers() {
57579
+ const pending = [...this.#pendingSteers.values()];
57580
+ this.#pendingSteers.clear();
57581
+ const error52 = new Error("Claude Code steer receipt was lost after input was written");
57582
+ for (const entry of pending) {
57583
+ clearTimeout(entry.timer);
57584
+ entry.reject(error52);
57585
+ }
57586
+ }
57587
+ /** `queued` is Claude's acceptance of this message into the running Session. */
57588
+ #observeSteer(message) {
57589
+ if (this.#pendingSteers.size === 0 || !isRecord11(message) || message.type !== "command_lifecycle") {
57590
+ return;
57591
+ }
57592
+ if (message.state !== "queued")
57593
+ return;
57594
+ if (typeof message.command_uuid !== "string" || message.command_uuid.length === 0)
57595
+ return;
57596
+ this.#acceptSteer(message.command_uuid);
57597
+ }
57330
57598
  #observeBackgroundTasks(message) {
57331
57599
  if (!isRecord11(message) || message.type !== "system")
57332
57600
  return;
@@ -57367,6 +57635,7 @@ var ClaudeSdkTransport = class {
57367
57635
  this.#observeBackgroundTasks(message);
57368
57636
  this.#observeWorkflowAgents(message);
57369
57637
  this.#observeSlashCommands(message);
57638
+ this.#observeNativeCapabilities(message);
57370
57639
  const permissionMode = permissionModeFromMessage(message);
57371
57640
  if (permissionMode && permissionMode !== this.#permissionMode) {
57372
57641
  this.#permissionMode = permissionMode;
@@ -57375,13 +57644,16 @@ var ClaudeSdkTransport = class {
57375
57644
  const planLimit = parseClaudePlanLimitEvent(message);
57376
57645
  if (planLimit)
57377
57646
  this.#onPlanLimit(planLimit);
57647
+ this.#observeSteer(message);
57378
57648
  const active = this.#active;
57379
57649
  if (active) {
57650
+ this.#observeRootToolCalls(message);
57380
57651
  const interpreted2 = active.accumulator.consume(message);
57381
57652
  for (const event of interpreted2.events)
57382
57653
  active.onEvent(event);
57383
57654
  if (interpreted2.terminal) {
57384
57655
  this.#closeInteractions("root", "superseded");
57656
+ this.#rootToolCalls.clear();
57385
57657
  this.#active = null;
57386
57658
  active.resolve(interpreted2.terminal);
57387
57659
  }
@@ -57435,6 +57707,8 @@ var ClaudeSdkTransport = class {
57435
57707
  } catch (error52) {
57436
57708
  const active = this.#active;
57437
57709
  this.#closeInteractions("all", "cancelled");
57710
+ this.#rejectPendingSteers();
57711
+ this.#rootToolCalls.clear();
57438
57712
  this.#active = null;
57439
57713
  active?.reject(error52);
57440
57714
  if (!this.#closePromise)
@@ -58622,7 +58896,7 @@ function projectClaudePlanLimitToCredits(planLimit) {
58622
58896
  }
58623
58897
  var ClaudeHarnessSession = class {
58624
58898
  harnessId = claudeCodeHarnessId2;
58625
- capabilities = {
58899
+ capabilities = /* @__PURE__ */ ((session) => ({
58626
58900
  configuration: {
58627
58901
  selectModel: true,
58628
58902
  selectThinkingOption: true,
@@ -58630,11 +58904,16 @@ var ClaudeHarnessSession = class {
58630
58904
  permissionModeScope: "live"
58631
58905
  },
58632
58906
  history: { fork: true, forkAcrossCwd: false, rollbackLastTurn: true },
58633
- subagents: { observe: true, readTranscript: true }
58634
- };
58907
+ subagents: { observe: true, readTranscript: true },
58908
+ // Read live: native delivery joins this Turn only while a requested Turn runs a root tool call
58909
+ // on a CLI that confirms steers (`msg_lifecycle_v1`). Otherwise the Host stops and restarts.
58910
+ get steer() {
58911
+ return session.#transport?.canSteerActiveTurn?.() === true;
58912
+ }
58913
+ }))(this);
58635
58914
  commands;
58636
58915
  initialState;
58637
- initialUsage = null;
58916
+ initialUsage;
58638
58917
  outputs;
58639
58918
  #channel = new HarnessOutputChannel();
58640
58919
  #cancelTimeoutMs;
@@ -58673,7 +58952,10 @@ var ClaudeHarnessSession = class {
58673
58952
  #hardCancelTask = null;
58674
58953
  #usageGeneration = 0;
58675
58954
  #latestUsage = null;
58955
+ #lastAssistantResponseAtUnix;
58956
+ #accountCreditsSupported;
58676
58957
  #minimumContextUsedTokens = null;
58958
+ #latestRequestModel = null;
58677
58959
  #calibratedInputTokens = 0;
58678
58960
  #calibratedOutputTokens = 0;
58679
58961
  #calibratedCostUsd = 0;
@@ -58691,6 +58973,11 @@ var ClaudeHarnessSession = class {
58691
58973
  #continuationQuiescence = null;
58692
58974
  constructor(cwd, dependencies, closeTimeoutMs, onClosed, onPlanLimitObserved, options) {
58693
58975
  this.#cwd = cwd;
58976
+ this.#lastAssistantResponseAtUnix = options.usageHistory.lastResponseAtUnix;
58977
+ this.#accountCreditsSupported = options.accountCreditsSupported;
58978
+ const composerIndicators = claudePromptCacheIndicators(this.#accountCreditsSupported, this.#lastAssistantResponseAtUnix);
58979
+ this.initialUsage = composerIndicators.length ? { composerIndicators } : null;
58980
+ this.#latestUsage = this.initialUsage;
58694
58981
  this.#pendingSessions = options.pendingSessions;
58695
58982
  const environment = options.environment;
58696
58983
  this.#createTransport = environment ? (input) => dependencies.createTransport({ ...input, environment }) : dependencies.createTransport;
@@ -58845,6 +59132,8 @@ var ClaudeHarnessSession = class {
58845
59132
  }
58846
59133
  if (command.type === "turn.cancel")
58847
59134
  return this.#cancel(command);
59135
+ if (command.type === "turn.steer")
59136
+ return this.#steer(command);
58848
59137
  if (command.type === "interaction.respond")
58849
59138
  return this.#respond(command);
58850
59139
  if (command.type === "model.select")
@@ -58981,6 +59270,45 @@ var ClaudeHarnessSession = class {
58981
59270
  }
58982
59271
  return { ok: true, value: { turnId: command.turnId } };
58983
59272
  }
59273
+ async #steer(command) {
59274
+ if (!this.#active || this.#active.command.turnId !== command.turnId) {
59275
+ return { ok: false, error: invalidState("Claude Code steer target is not the active Turn") };
59276
+ }
59277
+ const text2 = command.input.map((input) => input.text).join("\n");
59278
+ if (text2.length === 0) {
59279
+ return {
59280
+ ok: false,
59281
+ error: {
59282
+ code: "invalidRequest",
59283
+ message: "Claude Code steer text must not be empty",
59284
+ retryable: false
59285
+ }
59286
+ };
59287
+ }
59288
+ const transport = this.#transport;
59289
+ if (!transport) {
59290
+ return { ok: false, error: invalidState("Claude Code steer missed the active Turn") };
59291
+ }
59292
+ if (transport.supportsNativeSteer?.() !== true) {
59293
+ return {
59294
+ ok: false,
59295
+ error: {
59296
+ code: "unsupported",
59297
+ message: "This Claude Code version does not confirm native steering",
59298
+ retryable: false
59299
+ }
59300
+ };
59301
+ }
59302
+ try {
59303
+ await transport.steer(text2, this.#randomUUID());
59304
+ } catch (error52) {
59305
+ if (error52 instanceof ClaudeSteerMissedTurnError) {
59306
+ return { ok: false, error: invalidState("Claude Code steer missed the active Turn") };
59307
+ }
59308
+ throw error52;
59309
+ }
59310
+ return { ok: true, value: { accepted: true } };
59311
+ }
58984
59312
  /** Built-ins plus the live commands and skills of the started native Session. */
58985
59313
  #liveCommandCatalog() {
58986
59314
  return claudeLiveCommandCatalog(claudeCommandCatalog, this.#transport?.slashCommands?.() ?? null);
@@ -59751,6 +60079,10 @@ var ClaudeHarnessSession = class {
59751
60079
  this.#completeReasoning(active, event.messageId, { status: "succeeded" });
59752
60080
  return;
59753
60081
  case "message.completed": {
60082
+ if (!event.localCommand) {
60083
+ this.#lastAssistantResponseAtUnix = Math.floor(Date.now() / 1e3);
60084
+ this.publishAccountCreditsSupport(this.#accountCreditsSupported);
60085
+ }
59754
60086
  this.#observeRootOutput(active);
59755
60087
  if (event.lastRequestUsage) {
59756
60088
  this.#requestUsageBoundary += 1;
@@ -59812,9 +60144,7 @@ var ClaudeHarnessSession = class {
59812
60144
  case "subagent.completed": {
59813
60145
  const subagent = active.subagents.complete(active.command.turnId, event, active.cancellationRequested);
59814
60146
  if (subagent.status === "running") {
59815
- if (subagent.nativeSubagentId) {
59816
- this.#occupancy.bind(event.callId, subagent.nativeSubagentId);
59817
- }
60147
+ this.#occupancy.occupySpawn(event.callId, subagent.nativeSubagentId);
59818
60148
  return;
59819
60149
  }
59820
60150
  this.#occupancy.release(event.callId, subagent.nativeSubagentId);
@@ -60373,6 +60703,8 @@ var ClaudeHarnessSession = class {
60373
60703
  const promptTokens = usage.inputTokens + usage.cacheCreationInputTokens + usage.cacheReadInputTokens;
60374
60704
  if (promptTokens > 0)
60375
60705
  this.#minimumContextUsedTokens = promptTokens;
60706
+ if (usage.model)
60707
+ this.#latestRequestModel = usage.model;
60376
60708
  const cacheHitRatePercent = claudeCacheHitRatePercent(usage);
60377
60709
  const contextWindowTokens = this.#latestUsage?.contextWindowTokens;
60378
60710
  this.#mergeAndPublishUsage({
@@ -60414,8 +60746,24 @@ var ClaudeHarnessSession = class {
60414
60746
  if (cacheHitRatePercent !== void 0)
60415
60747
  delta.cacheHitRatePercent = cacheHitRatePercent;
60416
60748
  }
60749
+ if (this.#latestUsage?.contextWindowTokens === void 0 && this.#minimumContextUsedTokens !== null) {
60750
+ const contextWindowTokens = this.#resultContextWindow(event.modelUsage);
60751
+ if (contextWindowTokens !== void 0) {
60752
+ delta.contextUsedTokens = this.#minimumContextUsedTokens;
60753
+ delta.contextWindowTokens = contextWindowTokens;
60754
+ }
60755
+ }
60417
60756
  this.#mergeAndPublishUsage(delta, active.command.turnId);
60418
60757
  }
60758
+ /** The latest request's Model, else the Model that carried the most prompt tokens. */
60759
+ #resultContextWindow(modelUsage) {
60760
+ if (!modelUsage?.length)
60761
+ return void 0;
60762
+ const latest = this.#latestRequestModel;
60763
+ const matched = latest ? modelUsage.find(({ model: model2 }) => model2 === latest) : void 0;
60764
+ const main = matched ?? modelUsage.reduce((best, entry) => (entry.promptTokens ?? entry.inputTokens) > (best.promptTokens ?? best.inputTokens) ? entry : best);
60765
+ return main.contextWindowTokens;
60766
+ }
60419
60767
  /**
60420
60768
  * Plan usage is account-wide, not Thread-scoped, so every observation is
60421
60769
  * offered to the Adapter's shared cache regardless of this Session's own
@@ -60428,6 +60776,15 @@ var ClaudeHarnessSession = class {
60428
60776
  if (effective)
60429
60777
  this.publishPlanLimit(effective);
60430
60778
  }
60779
+ publishAccountCreditsSupport(supported) {
60780
+ if (this.#phase !== "open")
60781
+ return;
60782
+ this.#accountCreditsSupported = supported;
60783
+ const composerIndicators = claudePromptCacheIndicators(supported, this.#lastAssistantResponseAtUnix);
60784
+ if (composerIndicators[0]?.expiresAtUnix === this.#latestUsage?.composerIndicators?.[0]?.expiresAtUnix)
60785
+ return;
60786
+ this.#mergeAndPublishUsage({ composerIndicators }, this.#active?.command.turnId);
60787
+ }
60431
60788
  publishPlanLimit(planLimit) {
60432
60789
  if (this.#phase !== "open")
60433
60790
  return;
@@ -60703,6 +61060,7 @@ var ClaudeCodeAdapter = class {
60703
61060
  #closePromise = null;
60704
61061
  #latestPlanLimit = null;
60705
61062
  #accountInspection = null;
61063
+ #accountCreditsSupported = false;
60706
61064
  constructor(options = {}, dependencies) {
60707
61065
  const environment = options.environment ?? process.env;
60708
61066
  this.#environment = environment;
@@ -60814,12 +61172,20 @@ var ClaudeCodeAdapter = class {
60814
61172
  return this.#accountInspection;
60815
61173
  }
60816
61174
  async #readAccount() {
61175
+ const planLimitAtStart = this.#latestPlanLimit;
60817
61176
  let inspector;
60818
61177
  try {
60819
61178
  this.#dependencies.inspectInstallation();
60820
61179
  inspector = this.#dependencies.createInspector({ cwd: process.cwd() });
60821
61180
  this.#inspectors.add(inspector);
60822
- return await inspector.inspectAccount?.() ?? null;
61181
+ const account = await inspector.inspectAccount?.() ?? null;
61182
+ if (this.#latestPlanLimit === planLimitAtStart) {
61183
+ this.#accountCreditsSupported = account?.credits !== void 0;
61184
+ for (const session of this.#sessions) {
61185
+ session.publishAccountCreditsSupport(this.#accountCreditsSupported);
61186
+ }
61187
+ }
61188
+ return account;
60823
61189
  } catch {
60824
61190
  return null;
60825
61191
  } finally {
@@ -61062,6 +61428,7 @@ var ClaudeCodeAdapter = class {
61062
61428
  ...durableRef ? { nativeRef: durableRef } : {},
61063
61429
  sessionId,
61064
61430
  usageHistory,
61431
+ accountCreditsSupported: this.#accountCreditsSupported,
61065
61432
  ...requestedModel ? { requestedModel } : {},
61066
61433
  requestedPermissionModeId,
61067
61434
  requestedThinkingOptionId,
@@ -61081,7 +61448,13 @@ var ClaudeCodeAdapter = class {
61081
61448
  return { requests: [], complete: true };
61082
61449
  try {
61083
61450
  const messages = await this.#dependencies.readSessionMessages({ cwd, sessionId });
61084
- return messages === null ? { requests: [], complete: false } : claudeUsageHistory(messages);
61451
+ if (messages === null)
61452
+ return { requests: [], complete: false };
61453
+ const lastResponseAtUnix = lastClaudeAssistantResponseUnix(messages);
61454
+ return {
61455
+ ...claudeUsageHistory(messages),
61456
+ ...lastResponseAtUnix !== void 0 ? { lastResponseAtUnix } : {}
61457
+ };
61085
61458
  } catch {
61086
61459
  return { requests: [], complete: false };
61087
61460
  }
@@ -61093,9 +61466,17 @@ var ClaudeCodeAdapter = class {
61093
61466
  next.fiveHour = planLimit.fiveHour;
61094
61467
  if (planLimit.sevenDay)
61095
61468
  next.sevenDay = planLimit.sevenDay;
61469
+ try {
61470
+ if (!accountCreditsSnapshotSchema.safeParse(projectClaudePlanLimitToCredits(next)).success)
61471
+ return null;
61472
+ } catch {
61473
+ return null;
61474
+ }
61096
61475
  this.#latestPlanLimit = next.fiveHour || next.sevenDay ? next : null;
61097
61476
  if (this.#latestPlanLimit) {
61477
+ this.#accountCreditsSupported = true;
61098
61478
  for (const session of this.#sessions) {
61479
+ session.publishAccountCreditsSupport(true);
61099
61480
  if (session !== origin)
61100
61481
  session.publishPlanLimit(this.#latestPlanLimit);
61101
61482
  }