remote-codex 0.11.25 → 0.11.27

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.
@@ -10862,6 +10862,15 @@ var HIDDEN_ASK_USER_QUESTION_CONTINUATION_PREFIX = "The user answered the clarif
10862
10862
  var SUPPRESSED_ASSISTANT_TEXTS = /* @__PURE__ */ new Set([
10863
10863
  "No response requested."
10864
10864
  ]);
10865
+ var CLAUDE_LIMIT_ERROR_PATTERNS = [
10866
+ /\byou(?:'|’)ve hit your session limit\b/i,
10867
+ /\byou have hit your session limit\b/i,
10868
+ /\b(?:hit|reached|exceeded) (?:the )?(?:session|usage|rate) limit\b/i,
10869
+ /\b(?:session|usage|rate) limit (?:hit|reached|exceeded)\b/i,
10870
+ /\bquota exceeded\b/i,
10871
+ /\bcredit balance (?:is )?(?:too low|insufficient|exhausted)\b/i,
10872
+ /\binsufficient credits?\b/i
10873
+ ];
10865
10874
  function normalizedToolName(toolName) {
10866
10875
  return toolName.replace(/[\s_-]+/g, "").toLowerCase();
10867
10876
  }
@@ -10903,6 +10912,23 @@ function compactJson(value) {
10903
10912
  return String(value);
10904
10913
  }
10905
10914
  }
10915
+ function joinReasoningText(left, right) {
10916
+ if (!left) {
10917
+ return right;
10918
+ }
10919
+ if (!right) {
10920
+ return left;
10921
+ }
10922
+ if (right.startsWith(left)) {
10923
+ return right;
10924
+ }
10925
+ if (left.endsWith(right)) {
10926
+ return left;
10927
+ }
10928
+ return `${left}
10929
+
10930
+ ${right}`;
10931
+ }
10906
10932
  function readableToolName(toolName) {
10907
10933
  if (CLAUDE_TOOL_LABELS[toolName]) {
10908
10934
  return CLAUDE_TOOL_LABELS[toolName];
@@ -11026,6 +11052,26 @@ function isHiddenContinuationMessage(message) {
11026
11052
  function shouldSuppressAssistantText(text2) {
11027
11053
  return SUPPRESSED_ASSISTANT_TEXTS.has(text2.trim());
11028
11054
  }
11055
+ function claudeLimitErrorMessage(text2) {
11056
+ const normalized = text2?.trim();
11057
+ if (!normalized) {
11058
+ return null;
11059
+ }
11060
+ return CLAUDE_LIMIT_ERROR_PATTERNS.some((pattern) => pattern.test(normalized)) ? normalized : null;
11061
+ }
11062
+ function limitErrorFromHistoryItems(items) {
11063
+ for (let index = items.length - 1; index >= 0; index -= 1) {
11064
+ const item = items[index];
11065
+ if (item?.kind !== "agentMessage") {
11066
+ continue;
11067
+ }
11068
+ const error = claudeLimitErrorMessage(item.text);
11069
+ if (error) {
11070
+ return error;
11071
+ }
11072
+ }
11073
+ return null;
11074
+ }
11029
11075
  function userMessageToHistoryItem(id, message) {
11030
11076
  return {
11031
11077
  id,
@@ -11165,6 +11211,28 @@ function toolResultBlocks(message) {
11165
11211
  };
11166
11212
  }).filter((block) => Boolean(block));
11167
11213
  }
11214
+ function xmlTagText(input, tagName) {
11215
+ const match = new RegExp(`<${tagName}>([\\s\\S]*?)</${tagName}>`, "i").exec(input);
11216
+ return match?.[1]?.trim() || null;
11217
+ }
11218
+ function decodeBasicXmlEntities(input) {
11219
+ return input.replace(/&quot;/g, '"').replace(/&apos;/g, "'").replace(/&gt;/g, ">").replace(/&lt;/g, "<").replace(/&amp;/g, "&");
11220
+ }
11221
+ function taskNotificationToolResult(message) {
11222
+ const text2 = messageContentText(message).trim();
11223
+ if (!text2.startsWith("<task-notification>") || !text2.includes("</task-notification>")) {
11224
+ return null;
11225
+ }
11226
+ const toolUseId = xmlTagText(text2, "tool-use-id");
11227
+ if (!toolUseId) {
11228
+ return null;
11229
+ }
11230
+ const result = xmlTagText(text2, "result") ?? xmlTagText(text2, "summary") ?? text2;
11231
+ return {
11232
+ toolUseId,
11233
+ result: decodeBasicXmlEntities(result)
11234
+ };
11235
+ }
11168
11236
  function suppressedClaudeToolUseIds(message) {
11169
11237
  const ids = /* @__PURE__ */ new Set();
11170
11238
  for (const block of contentBlocks(message)) {
@@ -11207,11 +11275,16 @@ function assistantMessageToHistoryItems(input) {
11207
11275
  if (type === "thinking") {
11208
11276
  const thinking = thinkingTextFromBlock(block);
11209
11277
  if (thinking) {
11210
- items.push({
11211
- id: `${input.messageId}:content:${index}`,
11212
- kind: "reasoning",
11213
- text: thinking
11214
- });
11278
+ const previous = items.at(-1);
11279
+ if (previous?.kind === "reasoning") {
11280
+ previous.text = joinReasoningText(previous.text, thinking);
11281
+ } else {
11282
+ items.push({
11283
+ id: `${input.messageId}:content:${index}`,
11284
+ kind: "reasoning",
11285
+ text: thinking
11286
+ });
11287
+ }
11215
11288
  }
11216
11289
  continue;
11217
11290
  }
@@ -11403,12 +11476,15 @@ function resultForToolUse(input) {
11403
11476
  };
11404
11477
  }
11405
11478
  function buildAgentTurn(input) {
11479
+ const startedAt = input.startedAt ?? null;
11406
11480
  const turn = {
11407
11481
  providerTurnId: input.providerTurnId,
11408
- startedAt: input.startedAt ?? null,
11482
+ startedAt,
11409
11483
  status: input.status,
11410
11484
  error: input.error ? { message: input.error } : null,
11411
- items: input.items
11485
+ items: input.items.map(
11486
+ (item) => item.createdAt || !startedAt ? item : { ...item, createdAt: startedAt }
11487
+ )
11412
11488
  };
11413
11489
  if (input.rawTurn !== void 0) {
11414
11490
  turn.rawTurn = input.rawTurn;
@@ -11867,6 +11943,13 @@ function queryResultError(message) {
11867
11943
  }
11868
11944
  return message.errors?.join("\n") || message.stop_reason || "Claude turn failed.";
11869
11945
  }
11946
+ function statusForHistoricalItems(items) {
11947
+ const limitError = limitErrorFromHistoryItems(items);
11948
+ return {
11949
+ status: limitError ? "failed" : "completed",
11950
+ error: limitError
11951
+ };
11952
+ }
11870
11953
  function assistantMessagePayload(message) {
11871
11954
  return message.type === "assistant" ? message.message : null;
11872
11955
  }
@@ -11955,6 +12038,9 @@ function streamMessageId(event) {
11955
12038
  const message = event.message;
11956
12039
  return messageIdFromPayload(message);
11957
12040
  }
12041
+ function sessionMessageTimestamp(message) {
12042
+ return typeof message.uuid === "string" ? isoFromUuidV7(message.uuid) : null;
12043
+ }
11958
12044
  function addOrUpdateItem(state, item) {
11959
12045
  if (!state.items.has(item.id)) {
11960
12046
  state.itemOrder.push(item.id);
@@ -11964,6 +12050,53 @@ function addOrUpdateItem(state, item) {
11964
12050
  function orderedItems(state) {
11965
12051
  return state.itemOrder.map((id) => state.items.get(id)).filter((item) => Boolean(item));
11966
12052
  }
12053
+ function withHistoryItemCreatedAt(item, createdAt) {
12054
+ if (item.createdAt || !createdAt) {
12055
+ return item;
12056
+ }
12057
+ return { ...item, createdAt };
12058
+ }
12059
+ function latestReasoningItem(state) {
12060
+ const lastItemId = state.itemOrder.at(-1);
12061
+ const lastItem = lastItemId ? state.items.get(lastItemId) : null;
12062
+ return lastItem?.kind === "reasoning" ? lastItem : null;
12063
+ }
12064
+ function joinReasoningText2(left, right) {
12065
+ if (!left) {
12066
+ return right;
12067
+ }
12068
+ if (!right) {
12069
+ return left;
12070
+ }
12071
+ if (right.startsWith(left)) {
12072
+ return right;
12073
+ }
12074
+ if (left.endsWith(right)) {
12075
+ return left;
12076
+ }
12077
+ return `${left}
12078
+
12079
+ ${right}`;
12080
+ }
12081
+ function isRunningHistoryItemStatus(status) {
12082
+ const normalized = status?.trim().toLowerCase();
12083
+ return normalized === "running" || normalized === "pending" || normalized === "in_progress" || normalized === "in progress";
12084
+ }
12085
+ function finalizeTurnItems(state, status, completedAt) {
12086
+ return orderedItems(state).map((item) => {
12087
+ if (item.kind === "userMessage") {
12088
+ return item;
12089
+ }
12090
+ if (status === "completed" && isRunningHistoryItemStatus(item.status)) {
12091
+ return {
12092
+ ...item,
12093
+ status: "completed",
12094
+ createdAt: item.createdAt ?? completedAt
12095
+ };
12096
+ }
12097
+ return withHistoryItemCreatedAt(item, completedAt);
12098
+ });
12099
+ }
11967
12100
  function stringFromRecord(value, key) {
11968
12101
  const raw = value[key];
11969
12102
  return typeof raw === "string" && raw.trim() ? raw : null;
@@ -12286,7 +12419,13 @@ var ClaudeRuntimeAdapter = class extends EventEmitter5 {
12286
12419
  const sessions = await this.withClaudeConfigEnv(() => this.listSessionsFn({}));
12287
12420
  return sessions.map((session) => {
12288
12421
  this.knownSessionIds.add(session.sessionId);
12289
- return sessionSummaryFromInfo(session);
12422
+ const summary = sessionSummaryFromInfo(session);
12423
+ const activeTurn = this.activeTurnForSession(summary.providerSessionId);
12424
+ return activeTurn ? {
12425
+ ...summary,
12426
+ status: "running",
12427
+ updatedAt: summary.updatedAt ?? activeTurn.startedAt
12428
+ } : summary;
12290
12429
  });
12291
12430
  }
12292
12431
  async listLoadedSessions() {
@@ -12453,9 +12592,12 @@ var ClaudeRuntimeAdapter = class extends EventEmitter5 {
12453
12592
  tools: { type: "preset", preset: "claude_code" }
12454
12593
  })
12455
12594
  });
12456
- const userItem = userMessageToHistoryItem(`${providerTurnId}:user`, {
12457
- content: input.prompt
12458
- });
12595
+ const userItem = withHistoryItemCreatedAt(
12596
+ userMessageToHistoryItem(`${providerTurnId}:user`, {
12597
+ content: input.prompt
12598
+ }),
12599
+ startedAt
12600
+ );
12459
12601
  const initialItems = input.hidden ? [] : [userItem];
12460
12602
  const state = {
12461
12603
  providerSessionId: input.providerSessionId,
@@ -12538,6 +12680,14 @@ var ClaudeRuntimeAdapter = class extends EventEmitter5 {
12538
12680
  this.liveUserPrompts.delete(state.providerSessionId);
12539
12681
  }
12540
12682
  }
12683
+ activeTurnForSession(providerSessionId) {
12684
+ for (const state of this.activeTurns.values()) {
12685
+ if (state.providerSessionId === providerSessionId && !state.completed) {
12686
+ return state;
12687
+ }
12688
+ }
12689
+ return null;
12690
+ }
12541
12691
  reconcileActiveTranscriptTurn(providerSessionId, turns, activeTurn) {
12542
12692
  if (!activeTurn || turns.length === 0) {
12543
12693
  return turns;
@@ -12590,37 +12740,25 @@ var ClaudeRuntimeAdapter = class extends EventEmitter5 {
12590
12740
  }
12591
12741
  async consumeQuery(state) {
12592
12742
  const rawMessages = [];
12743
+ let terminalStatus = null;
12744
+ let terminalError = null;
12593
12745
  try {
12594
12746
  for await (const message of state.query) {
12595
12747
  rawMessages.push(message);
12596
- if (state.completed) {
12597
- continue;
12598
- }
12599
12748
  this.consumeMessage(state, message);
12600
12749
  const status = queryResultStatus(message);
12601
12750
  if (status) {
12602
- state.completed = true;
12603
- this.deleteActiveTurn(state);
12604
- this.emitUsage(state);
12605
- this.emitRuntimeEvent({
12606
- type: "turn.completed",
12607
- provider: "claude",
12608
- providerSessionId: state.providerSessionId,
12609
- turn: buildAgentTurn({
12610
- providerTurnId: state.providerTurnId,
12611
- startedAt: state.startedAt,
12612
- status: state.interrupted ? "interrupted" : status,
12613
- error: queryResultError(message),
12614
- items: orderedItems(state),
12615
- rawTurn: rawMessages
12616
- })
12617
- });
12751
+ terminalStatus = status;
12752
+ terminalError = queryResultError(message);
12618
12753
  }
12619
12754
  }
12620
12755
  if (!state.completed) {
12621
12756
  state.completed = true;
12622
12757
  this.deleteActiveTurn(state);
12623
12758
  this.emitUsage(state);
12759
+ const completedAt = (/* @__PURE__ */ new Date()).toISOString();
12760
+ const limitError = limitErrorFromHistoryItems(orderedItems(state));
12761
+ const status = state.interrupted ? "interrupted" : limitError ? "failed" : terminalStatus ?? "completed";
12624
12762
  this.emitRuntimeEvent({
12625
12763
  type: "turn.completed",
12626
12764
  provider: "claude",
@@ -12628,8 +12766,9 @@ var ClaudeRuntimeAdapter = class extends EventEmitter5 {
12628
12766
  turn: buildAgentTurn({
12629
12767
  providerTurnId: state.providerTurnId,
12630
12768
  startedAt: state.startedAt,
12631
- status: state.interrupted ? "interrupted" : "completed",
12632
- items: orderedItems(state),
12769
+ status,
12770
+ error: limitError ?? terminalError,
12771
+ items: finalizeTurnItems(state, status, completedAt),
12633
12772
  rawTurn: rawMessages
12634
12773
  })
12635
12774
  });
@@ -12650,6 +12789,7 @@ var ClaudeRuntimeAdapter = class extends EventEmitter5 {
12650
12789
  }
12651
12790
  consumeMessage(state, message) {
12652
12791
  this.captureUsage(state, message);
12792
+ const messageCreatedAt = (/* @__PURE__ */ new Date()).toISOString();
12653
12793
  if (message.type === "system" && message.subtype === "init") {
12654
12794
  this.updateToolboxItemsFromSystemInit(message);
12655
12795
  if (message.session_id) {
@@ -12669,8 +12809,9 @@ var ClaudeRuntimeAdapter = class extends EventEmitter5 {
12669
12809
  event: message.event
12670
12810
  });
12671
12811
  if (toolItem) {
12672
- addOrUpdateItem(state, toolItem);
12673
- this.emitItem(state, toolItem, "item.started");
12812
+ const nextItem = withHistoryItemCreatedAt(toolItem, messageCreatedAt);
12813
+ addOrUpdateItem(state, nextItem);
12814
+ this.emitItem(state, nextItem, "item.started");
12674
12815
  return;
12675
12816
  }
12676
12817
  const reasoningItem = partialReasoningDelta({
@@ -12679,14 +12820,15 @@ var ClaudeRuntimeAdapter = class extends EventEmitter5 {
12679
12820
  });
12680
12821
  if (reasoningItem) {
12681
12822
  const existing = state.items.get(reasoningItem.id);
12682
- const nextItem = existing?.kind === "reasoning" ? {
12683
- ...existing,
12684
- text: `${existing.text}${reasoningItem.text}`,
12685
- status: reasoningItem.status ?? existing.status ?? null
12686
- } : reasoningItem;
12823
+ const previousReasoning = existing?.kind === "reasoning" ? existing : latestReasoningItem(state);
12824
+ const nextItem = previousReasoning ? {
12825
+ ...previousReasoning,
12826
+ text: previousReasoning.id === reasoningItem.id ? `${previousReasoning.text}${reasoningItem.text}` : joinReasoningText2(previousReasoning.text, reasoningItem.text),
12827
+ status: reasoningItem.status ?? previousReasoning.status ?? null
12828
+ } : withHistoryItemCreatedAt(reasoningItem, messageCreatedAt);
12687
12829
  addOrUpdateItem(state, nextItem);
12688
- this.emitItem(state, nextItem, existing ? "item.completed" : "item.started", {
12689
- force: Boolean(existing)
12830
+ this.emitItem(state, nextItem, previousReasoning ? "item.completed" : "item.started", {
12831
+ force: Boolean(previousReasoning)
12690
12832
  });
12691
12833
  return;
12692
12834
  }
@@ -12701,6 +12843,7 @@ var ClaudeRuntimeAdapter = class extends EventEmitter5 {
12701
12843
  text: `${existing.text}${delta.delta}`
12702
12844
  }) : markTransientAgentHistoryItem({
12703
12845
  id: delta.itemId,
12846
+ createdAt: messageCreatedAt,
12704
12847
  kind: "agentMessage",
12705
12848
  text: delta.delta
12706
12849
  });
@@ -12717,6 +12860,18 @@ var ClaudeRuntimeAdapter = class extends EventEmitter5 {
12717
12860
  return;
12718
12861
  }
12719
12862
  if (message.type === "user") {
12863
+ const taskNotification = taskNotificationToolResult(message.message);
12864
+ if (taskNotification && !state.suppressedToolUseIds.has(taskNotification.toolUseId)) {
12865
+ const item = resultForToolUse({
12866
+ toolUseId: taskNotification.toolUseId,
12867
+ result: message.tool_use_result ?? taskNotification.result,
12868
+ previous: state.items.get(taskNotification.toolUseId) ?? null
12869
+ });
12870
+ const nextItem = withHistoryItemCreatedAt(item, messageCreatedAt);
12871
+ addOrUpdateItem(state, nextItem);
12872
+ this.emitItem(state, nextItem, "item.completed");
12873
+ return;
12874
+ }
12720
12875
  const rawToolResults = toolResultBlocks(message.message);
12721
12876
  const toolResults = rawToolResults.filter(
12722
12877
  (toolResult) => !state.suppressedToolUseIds.has(toolResult.toolUseId)
@@ -12728,8 +12883,9 @@ var ClaudeRuntimeAdapter = class extends EventEmitter5 {
12728
12883
  result: message.tool_use_result ?? toolResult.result,
12729
12884
  previous: state.items.get(toolResult.toolUseId) ?? null
12730
12885
  });
12731
- addOrUpdateItem(state, item);
12732
- this.emitItem(state, item, "item.completed");
12886
+ const nextItem = withHistoryItemCreatedAt(item, messageCreatedAt);
12887
+ addOrUpdateItem(state, nextItem);
12888
+ this.emitItem(state, nextItem, "item.completed");
12733
12889
  }
12734
12890
  return;
12735
12891
  }
@@ -12760,12 +12916,13 @@ var ClaudeRuntimeAdapter = class extends EventEmitter5 {
12760
12916
  messageId: assistantMessageId,
12761
12917
  message: payload
12762
12918
  })) {
12763
- const existing = state.items.get(item.id);
12764
- addOrUpdateItem(state, item);
12765
- if (item.kind !== "agentMessage" && !existing) {
12766
- this.emitItem(state, item, "item.started");
12767
- } else if (item.kind !== "agentMessage" && existing) {
12768
- this.emitItem(state, item, "item.started", { force: true });
12919
+ const nextItem = withHistoryItemCreatedAt(item, messageCreatedAt);
12920
+ const existing = state.items.get(nextItem.id);
12921
+ addOrUpdateItem(state, nextItem);
12922
+ if (nextItem.kind !== "agentMessage" && !existing) {
12923
+ this.emitItem(state, nextItem, "item.started");
12924
+ } else if (nextItem.kind !== "agentMessage" && existing) {
12925
+ this.emitItem(state, nextItem, "item.started", { force: true });
12769
12926
  }
12770
12927
  }
12771
12928
  return;
@@ -12779,8 +12936,9 @@ var ClaudeRuntimeAdapter = class extends EventEmitter5 {
12779
12936
  result: message.tool_use_result ?? message.message,
12780
12937
  previous: state.items.get(message.parent_tool_use_id) ?? null
12781
12938
  });
12782
- addOrUpdateItem(state, item);
12783
- this.emitItem(state, item, "item.completed");
12939
+ const nextItem = withHistoryItemCreatedAt(item, messageCreatedAt);
12940
+ addOrUpdateItem(state, nextItem);
12941
+ this.emitItem(state, nextItem, "item.completed");
12784
12942
  return;
12785
12943
  }
12786
12944
  if (message.type === "tool_progress") {
@@ -12799,8 +12957,9 @@ var ClaudeRuntimeAdapter = class extends EventEmitter5 {
12799
12957
  status: "running"
12800
12958
  });
12801
12959
  if (item) {
12802
- addOrUpdateItem(state, item);
12803
- this.emitItem(state, item, "item.started");
12960
+ const nextItem = withHistoryItemCreatedAt(item, messageCreatedAt);
12961
+ addOrUpdateItem(state, nextItem);
12962
+ this.emitItem(state, nextItem, "item.started");
12804
12963
  } else {
12805
12964
  state.suppressedToolUseIds.add(toolUseId);
12806
12965
  }
@@ -12819,13 +12978,15 @@ var ClaudeRuntimeAdapter = class extends EventEmitter5 {
12819
12978
  detailText: [previous.detailText ?? previous.text, "", message.message].join("\n")
12820
12979
  } : {
12821
12980
  id: toolUseId,
12981
+ createdAt: messageCreatedAt,
12822
12982
  kind: "toolCall",
12823
12983
  text: `${message.tool_name} denied`,
12824
12984
  detailText: typeof message.message === "string" ? message.message : null,
12825
12985
  status: "denied"
12826
12986
  };
12827
- addOrUpdateItem(state, item);
12828
- this.emitItem(state, item, "item.completed");
12987
+ const nextItem = withHistoryItemCreatedAt(item, messageCreatedAt);
12988
+ addOrUpdateItem(state, nextItem);
12989
+ this.emitItem(state, nextItem, "item.completed");
12829
12990
  }
12830
12991
  }
12831
12992
  captureUsage(state, message) {
@@ -12996,6 +13157,18 @@ var ClaudeRuntimeAdapter = class extends EventEmitter5 {
12996
13157
  itemsById: /* @__PURE__ */ new Map()
12997
13158
  };
12998
13159
  }
13160
+ const previous = current.items.at(-1);
13161
+ if (item.kind === "reasoning" && previous?.kind === "reasoning") {
13162
+ const merged = {
13163
+ ...previous,
13164
+ text: joinReasoningText2(previous.text, item.text),
13165
+ status: item.status ?? previous.status ?? null
13166
+ };
13167
+ current.items[current.items.length - 1] = merged;
13168
+ current.itemsById.set(previous.id, merged);
13169
+ current.itemsById.set(item.id, merged);
13170
+ return;
13171
+ }
12999
13172
  const existingIndex = current.items.findIndex((entry) => entry.id === item.id);
13000
13173
  if (existingIndex >= 0) {
13001
13174
  current.items[existingIndex] = item;
@@ -13006,6 +13179,24 @@ var ClaudeRuntimeAdapter = class extends EventEmitter5 {
13006
13179
  };
13007
13180
  for (const message of messages) {
13008
13181
  if (message.type === "user") {
13182
+ const taskNotification = taskNotificationToolResult(message.message);
13183
+ if (taskNotification) {
13184
+ if (suppressedToolUseIds.has(taskNotification.toolUseId)) {
13185
+ continue;
13186
+ }
13187
+ const previous = current?.itemsById.get(taskNotification.toolUseId) ?? null;
13188
+ upsertCurrentItem(
13189
+ withHistoryItemCreatedAt(
13190
+ resultForToolUse({
13191
+ toolUseId: taskNotification.toolUseId,
13192
+ result: message.tool_use_result ?? taskNotification.result,
13193
+ previous
13194
+ }),
13195
+ sessionMessageTimestamp(message) ?? current?.startedAt
13196
+ )
13197
+ );
13198
+ continue;
13199
+ }
13009
13200
  const rawToolResults = toolResultBlocks(message.message);
13010
13201
  const toolResults = rawToolResults.filter(
13011
13202
  (toolResult) => !suppressedToolUseIds.has(toolResult.toolUseId)
@@ -13013,11 +13204,16 @@ var ClaudeRuntimeAdapter = class extends EventEmitter5 {
13013
13204
  if (toolResults.length > 0) {
13014
13205
  for (const toolResult of toolResults) {
13015
13206
  const previous = current?.itemsById.get(toolResult.toolUseId) ?? null;
13016
- upsertCurrentItem(resultForToolUse({
13017
- toolUseId: toolResult.toolUseId,
13018
- result: toolResult.result,
13019
- previous
13020
- }));
13207
+ upsertCurrentItem(
13208
+ withHistoryItemCreatedAt(
13209
+ resultForToolUse({
13210
+ toolUseId: toolResult.toolUseId,
13211
+ result: toolResult.result,
13212
+ previous
13213
+ }),
13214
+ sessionMessageTimestamp(message) ?? current?.startedAt
13215
+ )
13216
+ );
13021
13217
  }
13022
13218
  continue;
13023
13219
  }
@@ -13036,24 +13232,28 @@ var ClaudeRuntimeAdapter = class extends EventEmitter5 {
13036
13232
  }
13037
13233
  skippingHiddenInit = false;
13038
13234
  if (current && current.items.length > 0) {
13235
+ const outcome = statusForHistoricalItems(current.items);
13039
13236
  turns.push(buildAgentTurn({
13040
13237
  providerTurnId: current.providerTurnId,
13041
13238
  startedAt: current.startedAt,
13042
- status: "completed",
13239
+ status: outcome.status,
13240
+ error: outcome.error,
13043
13241
  items: current.items
13044
13242
  }));
13045
13243
  }
13046
13244
  const messageUuid2 = message.uuid ?? randomUUID2();
13245
+ const userStartedAt = isoFromUuidV7(messageUuid2);
13047
13246
  const userItem = await this.userMessageToHistoryItem(
13048
13247
  messageUuid2,
13049
13248
  message.message,
13050
13249
  context
13051
13250
  );
13251
+ const stampedUserItem = withHistoryItemCreatedAt(userItem, userStartedAt);
13052
13252
  current = {
13053
13253
  providerTurnId: `claude-turn-${messageUuid2}`,
13054
- startedAt: isoFromUuidV7(messageUuid2),
13055
- items: [userItem],
13056
- itemsById: /* @__PURE__ */ new Map([[messageUuid2, userItem]])
13254
+ startedAt: userStartedAt,
13255
+ items: [stampedUserItem],
13256
+ itemsById: /* @__PURE__ */ new Map([[messageUuid2, stampedUserItem]])
13057
13257
  };
13058
13258
  continue;
13059
13259
  }
@@ -13061,6 +13261,7 @@ var ClaudeRuntimeAdapter = class extends EventEmitter5 {
13061
13261
  continue;
13062
13262
  }
13063
13263
  if (message.type === "assistant") {
13264
+ const assistantCreatedAt = sessionMessageTimestamp(message) ?? current?.startedAt;
13064
13265
  for (const toolUseId of suppressedClaudeToolUseIds(message.message)) {
13065
13266
  suppressedToolUseIds.add(toolUseId);
13066
13267
  current?.itemsById.delete(toolUseId);
@@ -13069,7 +13270,7 @@ var ClaudeRuntimeAdapter = class extends EventEmitter5 {
13069
13270
  messageId: message.uuid ?? randomUUID2(),
13070
13271
  message: message.message
13071
13272
  })) {
13072
- upsertCurrentItem(item);
13273
+ upsertCurrentItem(withHistoryItemCreatedAt(item, assistantCreatedAt));
13073
13274
  }
13074
13275
  continue;
13075
13276
  }
@@ -13078,18 +13279,25 @@ var ClaudeRuntimeAdapter = class extends EventEmitter5 {
13078
13279
  continue;
13079
13280
  }
13080
13281
  const previous = current?.itemsById.get(message.parent_tool_use_id) ?? null;
13081
- upsertCurrentItem(resultForToolUse({
13082
- toolUseId: message.parent_tool_use_id,
13083
- result: isRecord8(message.message) && "content" in message.message ? message.message.content : message.message,
13084
- previous
13085
- }));
13282
+ upsertCurrentItem(
13283
+ withHistoryItemCreatedAt(
13284
+ resultForToolUse({
13285
+ toolUseId: message.parent_tool_use_id,
13286
+ result: isRecord8(message.message) && "content" in message.message ? message.message.content : message.message,
13287
+ previous
13288
+ }),
13289
+ sessionMessageTimestamp(message) ?? current?.startedAt
13290
+ )
13291
+ );
13086
13292
  }
13087
13293
  }
13088
13294
  if (current && current.items.length > 0) {
13295
+ const outcome = statusForHistoricalItems(current.items);
13089
13296
  turns.push(buildAgentTurn({
13090
13297
  providerTurnId: current.providerTurnId,
13091
13298
  startedAt: current.startedAt,
13092
- status: "completed",
13299
+ status: outcome.status,
13300
+ error: outcome.error,
13093
13301
  items: current.items
13094
13302
  }));
13095
13303
  }
@@ -14954,7 +15162,7 @@ var E2EFakeRuntime = class extends EventEmitter7 {
14954
15162
  permissionRequests: false,
14955
15163
  sandboxMode: false,
14956
15164
  performanceMode: false,
14957
- goals: false
15165
+ goals: true
14958
15166
  },
14959
15167
  management: {
14960
15168
  models: true,
@@ -14970,6 +15178,12 @@ var E2EFakeRuntime = class extends EventEmitter7 {
14970
15178
  managementSchema = {
14971
15179
  hostConfigFiles: [],
14972
15180
  toolboxItems: [
15181
+ {
15182
+ action: "goal",
15183
+ command: "/goal",
15184
+ label: "Goal",
15185
+ description: "Manage the current goal."
15186
+ },
14973
15187
  {
14974
15188
  action: "fork",
14975
15189
  command: "/fork",
@@ -14996,6 +15210,7 @@ var E2EFakeRuntime = class extends EventEmitter7 {
14996
15210
  };
14997
15211
  sessions = /* @__PURE__ */ new Map();
14998
15212
  providerRequests = /* @__PURE__ */ new Map();
15213
+ goals = /* @__PURE__ */ new Map();
14999
15214
  activeTurnId = null;
15000
15215
  startedAt = null;
15001
15216
  getStatus() {
@@ -15107,6 +15322,42 @@ var E2EFakeRuntime = class extends EventEmitter7 {
15107
15322
  rawSession: session
15108
15323
  };
15109
15324
  }
15325
+ async getGoal(providerSessionId) {
15326
+ return this.goals.get(providerSessionId) ?? null;
15327
+ }
15328
+ async setGoal(input) {
15329
+ const existing = this.goals.get(input.providerSessionId);
15330
+ const now = Date.now();
15331
+ const goal = {
15332
+ providerSessionId: input.providerSessionId,
15333
+ objective: input.objective ?? existing?.objective ?? "E2E shared goal",
15334
+ status: input.status ?? existing?.status ?? "active",
15335
+ tokenBudget: input.tokenBudget !== void 0 ? input.tokenBudget : existing?.tokenBudget ?? null,
15336
+ tokensUsed: existing?.tokensUsed ?? 0,
15337
+ timeUsedSeconds: existing?.timeUsedSeconds ?? 0,
15338
+ createdAt: existing?.createdAt ?? now,
15339
+ updatedAt: now,
15340
+ rawGoal: null
15341
+ };
15342
+ this.goals.set(input.providerSessionId, goal);
15343
+ this.emitRuntimeEvent({
15344
+ type: "goal.updated",
15345
+ provider,
15346
+ providerSessionId: input.providerSessionId,
15347
+ providerTurnId: null,
15348
+ goal
15349
+ });
15350
+ return goal;
15351
+ }
15352
+ async clearGoal(providerSessionId) {
15353
+ const existed = this.goals.delete(providerSessionId);
15354
+ this.emitRuntimeEvent({
15355
+ type: "goal.cleared",
15356
+ provider,
15357
+ providerSessionId
15358
+ });
15359
+ return existed;
15360
+ }
15110
15361
  async startTurn(input) {
15111
15362
  const session = await this.readSession(input.providerSessionId);
15112
15363
  const providerTurnId = `e2e-turn-${session.turns.length + 1}`;
@@ -16369,7 +16620,7 @@ function deferLargeHistoryItemDetails(turn, deferredDetails) {
16369
16620
  };
16370
16621
  }
16371
16622
  function shouldPersistLiveHistoryItem(item) {
16372
- return item.kind === "commandExecution" || item.kind === "fileChange" || item.kind === "fileRead" || item.kind === "hook" || item.kind === "agentToolCall" || item.kind === "skillToolCall" || item.kind === "toolCall" || item.kind === "webSearch";
16623
+ return item.kind === "commandExecution" || item.kind === "fileChange" || item.kind === "fileRead" || item.kind === "hook" || item.kind === "agentToolCall" || item.kind === "skillToolCall" || item.kind === "toolCall" || item.kind === "reasoning" || item.kind === "webSearch";
16373
16624
  }
16374
16625
  function shouldPersistFinalHistoryItem(item) {
16375
16626
  return item.kind === "agentMessage" || shouldPersistLiveHistoryItem(item);
@@ -17419,7 +17670,7 @@ var ThreadRuntimeEventProjector = class {
17419
17670
  const sequence = liveState.recordTurnItemOrder(record.id, turnId, item.id);
17420
17671
  const eventTimestamp = (/* @__PURE__ */ new Date()).toISOString();
17421
17672
  const orderedLiveItem = {
17422
- ...withHistoryItemCreatedAt(item, eventTimestamp),
17673
+ ...withHistoryItemCreatedAt2(item, eventTimestamp),
17423
17674
  sequence
17424
17675
  };
17425
17676
  const transportLiveItem = deferHistoryItemDetailForTransport(orderedLiveItem);
@@ -17470,7 +17721,7 @@ var ThreadRuntimeEventProjector = class {
17470
17721
  }
17471
17722
  const eventTimestamp = (/* @__PURE__ */ new Date()).toISOString();
17472
17723
  const liveItem = {
17473
- ...withHistoryItemCreatedAt(event.item, eventTimestamp),
17724
+ ...withHistoryItemCreatedAt2(event.item, eventTimestamp),
17474
17725
  sequence: liveState.recordTurnItemOrder(record.id, turnId, event.item.id)
17475
17726
  };
17476
17727
  const transportLiveItem = deferHistoryItemDetailForTransport(liveItem);
@@ -17503,7 +17754,7 @@ var ThreadRuntimeEventProjector = class {
17503
17754
  );
17504
17755
  const eventTimestamp = (/* @__PURE__ */ new Date()).toISOString();
17505
17756
  const orderedLiveItem = {
17506
- ...withHistoryItemCreatedAt(event.item, eventTimestamp),
17757
+ ...withHistoryItemCreatedAt2(event.item, eventTimestamp),
17507
17758
  sequence
17508
17759
  };
17509
17760
  const transportLiveItem = deferHistoryItemDetailForTransport(orderedLiveItem);
@@ -17639,8 +17890,10 @@ var ThreadRuntimeEventProjector = class {
17639
17890
  }
17640
17891
  const turnId = liveState.displayTurnIdForRuntimeTurn(record.id, event.providerTurnId) ?? event.providerTurnId;
17641
17892
  updateThreadRecord(db, record.id, {
17893
+ providerTurnId: null,
17642
17894
  status: "failed",
17643
- lastError: event.error
17895
+ lastError: event.error,
17896
+ lastTurnCompletedAt: (/* @__PURE__ */ new Date()).toISOString()
17644
17897
  });
17645
17898
  liveState.setLivePlan(record.id, null);
17646
17899
  liveState.setLiveItems(record.id, null);
@@ -17676,7 +17929,7 @@ var ThreadRuntimeEventProjector = class {
17676
17929
  return typeof value === "object" && value !== null && !Array.isArray(value);
17677
17930
  }
17678
17931
  };
17679
- function withHistoryItemCreatedAt(item, createdAt) {
17932
+ function withHistoryItemCreatedAt2(item, createdAt) {
17680
17933
  return item.createdAt ? item : { ...item, createdAt };
17681
17934
  }
17682
17935
 
@@ -18120,7 +18373,11 @@ var ThreadDetailAssembler = class {
18120
18373
  if (input.record.providerTurnId && threadPatch.status === "idle" && activeLiveItems && activeLiveItems.items.length > 0) {
18121
18374
  threadPatch.status = "running";
18122
18375
  }
18123
- this.input.callbacks.updateThreadRecord(input.record.id, threadPatch);
18376
+ const nextThreadPatch = {
18377
+ ...threadPatch,
18378
+ ...threadPatch.status !== "running" ? { providerTurnId: null } : {}
18379
+ };
18380
+ this.input.callbacks.updateThreadRecord(input.record.id, nextThreadPatch);
18124
18381
  const updated = this.input.callbacks.getUpdatedThreadRecord(input.record.id);
18125
18382
  this.input.callbacks.syncAfterRemoteSession(updated.id, remoteSession);
18126
18383
  const deferredDetails = /* @__PURE__ */ new Map();
@@ -18970,6 +19227,7 @@ function buildThreadPatch(remoteSession, model, reasoningEffort) {
18970
19227
  };
18971
19228
  }
18972
19229
  function toThreadDto(record, loadedIds, callbacks) {
19230
+ const status = record.status ?? "idle";
18973
19231
  return {
18974
19232
  id: record.id,
18975
19233
  workspaceId: record.workspaceId,
@@ -18983,10 +19241,10 @@ function toThreadDto(record, loadedIds, callbacks) {
18983
19241
  collaborationMode: normalizeCollaborationMode(record.collaborationMode),
18984
19242
  approvalMode: record.approvalMode ?? "yolo",
18985
19243
  sandboxMode: normalizeSandboxMode(record.sandboxMode) ?? defaultSandboxModeForApprovalMode(record.approvalMode ?? "yolo"),
18986
- status: record.status ?? "idle",
19244
+ status,
18987
19245
  summaryText: record.summaryText ?? null,
18988
19246
  lastError: record.lastError ?? null,
18989
- activeTurnId: record.providerTurnId ?? null,
19247
+ activeTurnId: status === "running" ? record.providerTurnId ?? null : null,
18990
19248
  isLoaded: record.isConnected !== false && (record.providerSessionId ? loadedIds.has(record.providerSessionId) : false),
18991
19249
  isPinned: record.isPinned,
18992
19250
  createdAt: record.createdAt,