@autohq/cli 0.1.592 → 0.1.594

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.
@@ -37736,7 +37736,7 @@ Object.assign(lookup, {
37736
37736
  // package.json
37737
37737
  var package_default = {
37738
37738
  name: "@autohq/cli",
37739
- version: "0.1.592",
37739
+ version: "0.1.594",
37740
37740
  license: "SEE LICENSE IN README.md",
37741
37741
  publishConfig: {
37742
37742
  access: "public"
@@ -40412,6 +40412,35 @@ var TranscriptActivitySchema = external_exports.discriminatedUnion("type", [
40412
40412
  external_exports.object({
40413
40413
  type: external_exports.literal("run"),
40414
40414
  command: external_exports.string()
40415
+ }),
40416
+ external_exports.object({
40417
+ type: external_exports.literal("edit"),
40418
+ paths: external_exports.array(external_exports.string()).optional()
40419
+ }),
40420
+ external_exports.object({
40421
+ type: external_exports.literal("tool"),
40422
+ name: external_exports.string(),
40423
+ provider: external_exports.string().optional()
40424
+ }),
40425
+ external_exports.object({
40426
+ type: external_exports.literal("webSearch"),
40427
+ query: external_exports.string()
40428
+ }),
40429
+ external_exports.object({
40430
+ type: external_exports.literal("imageView"),
40431
+ path: external_exports.string()
40432
+ }),
40433
+ external_exports.object({
40434
+ type: external_exports.literal("collaboration"),
40435
+ action: external_exports.string()
40436
+ }),
40437
+ external_exports.object({
40438
+ type: external_exports.literal("wait"),
40439
+ durationMs: external_exports.number().nonnegative()
40440
+ }),
40441
+ external_exports.object({
40442
+ type: external_exports.literal("imageGeneration"),
40443
+ savedPath: external_exports.string().optional()
40415
40444
  })
40416
40445
  ]);
40417
40446
  var TranscriptToolMetadataSchema = external_exports.object({
@@ -40499,13 +40528,74 @@ var CodexMcpToolCallItemSchema = external_exports.object({
40499
40528
  error: external_exports.object({ message: external_exports.string() }).passthrough().nullish(),
40500
40529
  durationMs: external_exports.number().nonnegative().nullish()
40501
40530
  }).passthrough();
40531
+ var CodexDynamicToolCallItemSchema = external_exports.object({
40532
+ type: external_exports.literal("dynamicToolCall"),
40533
+ id: external_exports.string(),
40534
+ namespace: external_exports.string().nullish(),
40535
+ tool: external_exports.string().default(""),
40536
+ arguments: external_exports.unknown().optional(),
40537
+ status: external_exports.string().optional(),
40538
+ contentItems: external_exports.array(external_exports.unknown()).nullish(),
40539
+ success: external_exports.boolean().nullish(),
40540
+ durationMs: external_exports.number().nonnegative().nullish()
40541
+ }).passthrough();
40542
+ var CodexCollabAgentToolCallItemSchema = external_exports.object({
40543
+ type: external_exports.literal("collabAgentToolCall"),
40544
+ id: external_exports.string(),
40545
+ tool: external_exports.string(),
40546
+ status: external_exports.string().optional(),
40547
+ senderThreadId: external_exports.string().default(""),
40548
+ receiverThreadIds: external_exports.array(external_exports.string()).default([]),
40549
+ prompt: external_exports.string().nullish(),
40550
+ model: external_exports.string().nullish(),
40551
+ reasoningEffort: external_exports.string().nullish(),
40552
+ agentsStates: external_exports.record(external_exports.string(), external_exports.unknown()).default({})
40553
+ }).passthrough();
40554
+ var CodexSubAgentActivityItemSchema = external_exports.object({
40555
+ type: external_exports.literal("subAgentActivity"),
40556
+ id: external_exports.string(),
40557
+ kind: external_exports.string(),
40558
+ agentThreadId: external_exports.string(),
40559
+ agentPath: external_exports.string()
40560
+ }).passthrough();
40561
+ var CodexWebSearchItemSchema = external_exports.object({
40562
+ type: external_exports.literal("webSearch"),
40563
+ id: external_exports.string(),
40564
+ query: external_exports.string().default(""),
40565
+ action: external_exports.unknown().nullish()
40566
+ }).passthrough();
40567
+ var CodexImageViewItemSchema = external_exports.object({
40568
+ type: external_exports.literal("imageView"),
40569
+ id: external_exports.string(),
40570
+ path: external_exports.string()
40571
+ }).passthrough();
40572
+ var CodexSleepItemSchema = external_exports.object({
40573
+ type: external_exports.literal("sleep"),
40574
+ id: external_exports.string(),
40575
+ durationMs: external_exports.number().nonnegative()
40576
+ }).passthrough();
40577
+ var CodexImageGenerationItemSchema = external_exports.object({
40578
+ type: external_exports.literal("imageGeneration"),
40579
+ id: external_exports.string(),
40580
+ status: external_exports.string().optional(),
40581
+ revisedPrompt: external_exports.string().nullish(),
40582
+ result: external_exports.string().default(""),
40583
+ savedPath: external_exports.string().optional()
40584
+ }).passthrough();
40502
40585
  var CodexItemSchema = external_exports.discriminatedUnion("type", [
40503
40586
  CodexUserMessageItemSchema,
40504
40587
  CodexAgentMessageItemSchema,
40505
40588
  CodexReasoningItemSchema,
40506
40589
  CodexCommandExecutionItemSchema,
40507
40590
  CodexFileChangeItemSchema,
40508
- CodexMcpToolCallItemSchema
40591
+ CodexMcpToolCallItemSchema,
40592
+ CodexDynamicToolCallItemSchema,
40593
+ CodexCollabAgentToolCallItemSchema,
40594
+ CodexSubAgentActivityItemSchema,
40595
+ CodexWebSearchItemSchema,
40596
+ CodexImageViewItemSchema,
40597
+ CodexSleepItemSchema,
40598
+ CodexImageGenerationItemSchema
40509
40599
  ]);
40510
40600
  var OptionalCodexItemSchema = external_exports.unknown().transform((value2) => {
40511
40601
  const parsed = CodexItemSchema.safeParse(value2);
@@ -82875,67 +82965,263 @@ var defaultDownload2 = createDownload();
82875
82965
  import { Buffer as Buffer2 } from "buffer";
82876
82966
  var AGENT_BRIDGE_OUTPUT_MAX_ENVELOPE_BYTES = 512 * 1024;
82877
82967
  var AGENT_BRIDGE_OUTPUT_QUARANTINE_MAX_ENVELOPE_BYTES = 8 * 1024;
82878
- var MIN_STRING_BUDGET_CHARS = 64;
82968
+ var MAX_TARGETED_PAYLOAD_NOTICES = 4;
82969
+ var PAYLOAD_FIELD_RULES = {
82970
+ output: { label: "tool output", priority: 0 },
82971
+ errorText: { label: "tool error", priority: 0 },
82972
+ details: { label: "tool error details", priority: 1 },
82973
+ input: { label: "tool input", priority: 1 },
82974
+ text: { label: "text content", priority: 2 },
82975
+ delta: { label: "streamed content", priority: 2 },
82976
+ data: { label: "data content", priority: 2 },
82977
+ metadata: { label: "message metadata", priority: 3 },
82978
+ messageMetadata: { label: "message metadata", priority: 3 },
82979
+ providerMetadata: { label: "provider metadata", priority: 3 },
82980
+ callProviderMetadata: { label: "provider metadata", priority: 3 },
82981
+ toolMetadata: { label: "tool metadata", priority: 3 }
82982
+ };
82983
+ var STRUCTURAL_STRING_FIELDS = /* @__PURE__ */ new Set([
82984
+ "type",
82985
+ "id",
82986
+ "role",
82987
+ "state",
82988
+ "status",
82989
+ "name",
82990
+ "toolName",
82991
+ "toolCallId",
82992
+ "toolUseId",
82993
+ "messageId",
82994
+ "sourceId",
82995
+ "approvalId",
82996
+ "mediaType",
82997
+ "url",
82998
+ "title",
82999
+ "createdAt",
83000
+ "completedAt"
83001
+ ]);
82879
83002
  function boundOutputEnvelope(envelope, maxBytes = AGENT_BRIDGE_OUTPUT_MAX_ENVELOPE_BYTES) {
82880
83003
  const originalBytes = serializedByteLength(envelope);
82881
83004
  if (originalBytes <= maxBytes) {
82882
83005
  return { envelope, originalBytes, truncated: false };
82883
83006
  }
82884
- for (let budget = initialStringBudget(maxBytes); budget >= MIN_STRING_BUDGET_CHARS; budget = Math.floor(budget / 8)) {
82885
- const candidate = truncateLongStrings(envelope, budget);
82886
- if (serializedByteLength(candidate) <= maxBytes) {
82887
- return {
82888
- envelope: RuntimeBridgeOutputEnvelopeSchema.parse(candidate),
82889
- originalBytes,
82890
- truncated: true
82891
- };
82892
- }
83007
+ const targeted = truncatePayloads(envelope, maxBytes);
83008
+ if (targeted) {
83009
+ return {
83010
+ envelope: RuntimeBridgeOutputEnvelopeSchema.parse(targeted),
83011
+ originalBytes,
83012
+ truncated: true
83013
+ };
82893
83014
  }
82894
83015
  return {
82895
83016
  envelope: RuntimeBridgeOutputEnvelopeSchema.parse(
82896
- replacePayloadWithMarker(envelope, originalBytes)
83017
+ replacePayloadWithMarker(envelope)
82897
83018
  ),
82898
83019
  originalBytes,
82899
83020
  truncated: true
82900
83021
  };
82901
83022
  }
82902
- function serializedByteLength(value2) {
82903
- return Buffer2.byteLength(JSON.stringify(value2), "utf8");
82904
- }
82905
- function initialStringBudget(maxBytes) {
82906
- return Math.max(MIN_STRING_BUDGET_CHARS, Math.floor(maxBytes / 8));
82907
- }
82908
- function truncateLongStrings(value2, budget) {
82909
- if (typeof value2 === "string") {
82910
- if (value2.length <= budget) {
82911
- return value2;
83023
+ function truncatePayloads(envelope, maxBytes) {
83024
+ const candidateEnvelope = structuredClone(envelope);
83025
+ const candidates = collectPayloadCandidates(envelope);
83026
+ for (let noticeCount = 0; noticeCount < MAX_TARGETED_PAYLOAD_NOTICES; noticeCount += 1) {
83027
+ const currentBytes = serializedByteLength(candidateEnvelope);
83028
+ if (currentBytes <= maxBytes) {
83029
+ return candidateEnvelope;
83030
+ }
83031
+ const candidate = takePayloadCandidate(candidates, currentBytes - maxBytes);
83032
+ if (!candidate) {
83033
+ return null;
82912
83034
  }
82913
- return `${value2.slice(0, budget)}${truncationMarker(value2.length - budget)}`;
83035
+ setValueAtPath(
83036
+ candidateEnvelope,
83037
+ candidate.path,
83038
+ truncationNotice(candidate, "")
83039
+ );
83040
+ if (serializedByteLength(candidateEnvelope) <= maxBytes) {
83041
+ maximizePreview(candidateEnvelope, candidate, maxBytes);
83042
+ return candidateEnvelope;
83043
+ }
83044
+ }
83045
+ return serializedByteLength(candidateEnvelope) <= maxBytes ? candidateEnvelope : null;
83046
+ }
83047
+ function collectPayloadCandidates(envelope) {
83048
+ let seeds;
83049
+ switch (envelope.type) {
83050
+ case "conversation.entry":
83051
+ seeds = collectJsonPayloadCandidates(envelope.content, ["content"]);
83052
+ break;
83053
+ case "conversation.delta":
83054
+ seeds = collectJsonPayloadCandidates(envelope.delta, ["delta"]);
83055
+ break;
83056
+ case "ui.message.chunk":
83057
+ seeds = collectJsonPayloadCandidates(envelope.chunk, ["chunk"]);
83058
+ break;
83059
+ case "ui.message.part":
83060
+ seeds = collectJsonPayloadCandidates(envelope.part, ["part"]);
83061
+ if (envelope.messageMetadata !== void 0) {
83062
+ seeds.push(
83063
+ toCandidateSeed(
83064
+ ["messageMetadata"],
83065
+ "message metadata",
83066
+ 3,
83067
+ envelope.messageMetadata
83068
+ )
83069
+ );
83070
+ }
83071
+ break;
83072
+ case "ui.message.completed":
83073
+ seeds = collectJsonPayloadCandidates(envelope.message, ["message"]);
83074
+ break;
83075
+ case "runtime.liveness":
83076
+ case "runtime.usage_turn":
83077
+ return [];
82914
83078
  }
83079
+ return seeds.map(toPayloadCandidate).filter((candidate) => candidate.potentialSavings > 0);
83080
+ }
83081
+ function collectJsonPayloadCandidates(value2, path2) {
82915
83082
  if (Array.isArray(value2)) {
82916
- return value2.map((item) => truncateLongStrings(item, budget));
83083
+ return value2.flatMap(
83084
+ (item, index) => collectJsonPayloadCandidates(item, [...path2, index])
83085
+ );
82917
83086
  }
82918
83087
  if (typeof value2 === "object" && value2 !== null) {
82919
- return Object.fromEntries(
82920
- Object.entries(value2).map(([key, item]) => [
82921
- key,
82922
- truncateLongStrings(item, budget)
82923
- ])
83088
+ return Object.entries(value2).flatMap(([key, item]) => {
83089
+ const itemPath = [...path2, key];
83090
+ const rule = PAYLOAD_FIELD_RULES[key];
83091
+ if (rule) {
83092
+ return [toCandidateSeed(itemPath, rule.label, rule.priority, item)];
83093
+ }
83094
+ if (typeof item === "string" && !STRUCTURAL_STRING_FIELDS.has(key)) {
83095
+ return [toCandidateSeed(itemPath, "content", 4, item)];
83096
+ }
83097
+ return collectJsonPayloadCandidates(item, itemPath);
83098
+ });
83099
+ }
83100
+ return [];
83101
+ }
83102
+ function toCandidateSeed(path2, label, priority, value2) {
83103
+ return { path: path2, label, priority, value: value2 };
83104
+ }
83105
+ function toPayloadCandidate(seed, order) {
83106
+ const preview = payloadPreview(seed.value);
83107
+ const originalBytes = Buffer2.byteLength(preview, "utf8");
83108
+ const candidate = {
83109
+ ...seed,
83110
+ order,
83111
+ preview,
83112
+ originalBytes,
83113
+ potentialSavings: 0
83114
+ };
83115
+ return {
83116
+ ...candidate,
83117
+ potentialSavings: serializedByteLength(seed.value) - serializedByteLength(truncationNotice(candidate, ""))
83118
+ };
83119
+ }
83120
+ function payloadPreview(value2) {
83121
+ if (typeof value2 === "string") {
83122
+ return value2;
83123
+ }
83124
+ return JSON.stringify(value2) ?? String(value2);
83125
+ }
83126
+ function takePayloadCandidate(candidates, bytesToRemove) {
83127
+ const sufficient = candidates.filter(
83128
+ (candidate) => candidate.potentialSavings >= bytesToRemove
83129
+ );
83130
+ const pool = sufficient.length > 0 ? sufficient : candidates;
83131
+ pool.sort((left, right) => {
83132
+ if (sufficient.length > 0 && left.priority !== right.priority) {
83133
+ return left.priority - right.priority;
83134
+ }
83135
+ if (left.potentialSavings !== right.potentialSavings) {
83136
+ return right.potentialSavings - left.potentialSavings;
83137
+ }
83138
+ if (left.priority !== right.priority) {
83139
+ return left.priority - right.priority;
83140
+ }
83141
+ return left.order - right.order;
83142
+ });
83143
+ const selected = pool[0];
83144
+ if (!selected) {
83145
+ return void 0;
83146
+ }
83147
+ const candidateIndex = candidates.indexOf(selected);
83148
+ candidates.splice(candidateIndex, 1);
83149
+ return selected;
83150
+ }
83151
+ function maximizePreview(envelope, candidate, maxBytes) {
83152
+ let bestPrefix = "";
83153
+ let lower = 0;
83154
+ let upper = Math.max(0, candidate.preview.length - 1);
83155
+ while (lower <= upper) {
83156
+ const midpoint = Math.floor((lower + upper) / 2);
83157
+ const prefix = safeStringPrefix(candidate.preview, midpoint);
83158
+ setValueAtPath(
83159
+ envelope,
83160
+ candidate.path,
83161
+ truncationNotice(candidate, prefix)
82924
83162
  );
83163
+ if (serializedByteLength(envelope) <= maxBytes) {
83164
+ bestPrefix = prefix;
83165
+ lower = midpoint + 1;
83166
+ } else {
83167
+ upper = midpoint - 1;
83168
+ }
82925
83169
  }
82926
- return value2;
83170
+ setValueAtPath(
83171
+ envelope,
83172
+ candidate.path,
83173
+ truncationNotice(candidate, bestPrefix)
83174
+ );
83175
+ }
83176
+ function safeStringPrefix(value2, length) {
83177
+ let safeLength = Math.min(length, value2.length);
83178
+ if (safeLength > 0) {
83179
+ const lastCodeUnit = value2.charCodeAt(safeLength - 1);
83180
+ if (lastCodeUnit >= 55296 && lastCodeUnit <= 56319) {
83181
+ safeLength -= 1;
83182
+ }
83183
+ }
83184
+ return value2.slice(0, safeLength);
83185
+ }
83186
+ function setValueAtPath(root, path2, value2) {
83187
+ let parent = root;
83188
+ for (const segment of path2.slice(0, -1)) {
83189
+ if (typeof parent !== "object" || parent === null) {
83190
+ throw new Error("Invalid payload candidate path");
83191
+ }
83192
+ parent = parent[segment];
83193
+ }
83194
+ if (typeof parent !== "object" || parent === null) {
83195
+ throw new Error("Invalid payload candidate parent");
83196
+ }
83197
+ const finalSegment = path2.at(-1);
83198
+ if (finalSegment === void 0) {
83199
+ throw new Error("Payload candidate path cannot be empty");
83200
+ }
83201
+ parent[finalSegment] = value2;
82927
83202
  }
82928
- function truncationMarker(droppedChars) {
82929
- return `\u2026 [agent-bridge truncated ${droppedChars} chars: output exceeded the bridge envelope size limit]`;
83203
+ function truncationNotice(candidate, preview) {
83204
+ const keptBytes = Buffer2.byteLength(preview, "utf8");
83205
+ const omittedBytes = candidate.originalBytes - keptBytes;
83206
+ const separator = preview.length > 0 ? "\n" : "";
83207
+ return `${preview}${separator}[agent-bridge ${candidate.label} truncated: original ${candidate.originalBytes} UTF-8 bytes; kept ${keptBytes}; omitted ${omittedBytes}. Omitted content was not persisted in this transcript.]`;
83208
+ }
83209
+ function serializedByteLength(value2) {
83210
+ const serialized = JSON.stringify(value2);
83211
+ return serialized === void 0 ? 0 : Buffer2.byteLength(serialized, "utf8");
82930
83212
  }
82931
- function replacePayloadWithMarker(envelope, originalBytes) {
82932
- const text2 = `[agent-bridge removed a ${originalBytes}-byte payload: it exceeded the bridge envelope size limit and could not be truncated]`;
83213
+ function replacePayloadWithMarker(envelope) {
82933
83214
  switch (envelope.type) {
82934
- case "conversation.entry":
83215
+ case "conversation.entry": {
83216
+ const text2 = payloadRemovalNotice(envelope.content);
82935
83217
  return { ...envelope, content: { parts: [{ type: "text", text: text2 }] } };
82936
- case "conversation.delta":
83218
+ }
83219
+ case "conversation.delta": {
83220
+ const text2 = payloadRemovalNotice(envelope.delta);
82937
83221
  return { ...envelope, delta: { type: "text", text: text2 } };
82938
- case "ui.message.chunk":
83222
+ }
83223
+ case "ui.message.chunk": {
83224
+ const text2 = payloadRemovalNotice(envelope.chunk);
82939
83225
  return {
82940
83226
  ...envelope,
82941
83227
  chunk: {
@@ -82944,11 +83230,17 @@ function replacePayloadWithMarker(envelope, originalBytes) {
82944
83230
  delta: text2
82945
83231
  }
82946
83232
  };
83233
+ }
82947
83234
  case "ui.message.part": {
82948
83235
  const { messageMetadata: _dropped, ...rest } = envelope;
83236
+ const text2 = payloadRemovalNotice({
83237
+ part: envelope.part,
83238
+ ...envelope.messageMetadata === void 0 ? {} : { messageMetadata: envelope.messageMetadata }
83239
+ });
82949
83240
  return { ...rest, part: { type: "text", text: text2, state: "done" } };
82950
83241
  }
82951
- case "ui.message.completed":
83242
+ case "ui.message.completed": {
83243
+ const text2 = payloadRemovalNotice(envelope.message);
82952
83244
  return {
82953
83245
  ...envelope,
82954
83246
  message: {
@@ -82957,11 +83249,16 @@ function replacePayloadWithMarker(envelope, originalBytes) {
82957
83249
  parts: [{ type: "text", text: text2, state: "done" }]
82958
83250
  }
82959
83251
  };
83252
+ }
82960
83253
  case "runtime.liveness":
82961
83254
  case "runtime.usage_turn":
82962
83255
  return envelope;
82963
83256
  }
82964
83257
  }
83258
+ function payloadRemovalNotice(payload) {
83259
+ const originalBytes = Buffer2.byteLength(payloadPreview(payload), "utf8");
83260
+ return `[agent-bridge payload removed: original ${originalBytes} UTF-8 bytes; kept 0; omitted ${originalBytes}. Omitted content was not persisted in this transcript. Targeted truncation could not fit the bridge envelope.]`;
83261
+ }
82965
83262
 
82966
83263
  // src/commands/agent-bridge/harness/ui-message-part-tracker.ts
82967
83264
  var UiMessagePartTracker = class {
@@ -84522,7 +84819,10 @@ var ClaudeCodeProjector = class {
84522
84819
  this.activeParts.clear();
84523
84820
  this.activeToolInputs.clear();
84524
84821
  this.interruptMarkerSeen = false;
84525
- return this.ensureResponseStarted(this.currentMessageId);
84822
+ return [
84823
+ ...this.ensureResponseStarted(this.currentMessageId),
84824
+ uiChunk({ type: "start-step" })
84825
+ ];
84526
84826
  }
84527
84827
  if (message.event.type === "message_stop") {
84528
84828
  const outputs = [
@@ -84695,7 +84995,8 @@ var ClaudeCodeProjector = class {
84695
84995
  const messageId = messageProjection?.messageId ?? toolCallProjections.find((projection) => projection.messageId)?.messageId ?? UNKNOWN_MESSAGE_ID;
84696
84996
  const standalone = this.activeResponseMessageId === null;
84697
84997
  const outputs = [
84698
- ...this.ensureResponseStarted(messageId)
84998
+ ...this.ensureResponseStarted(messageId),
84999
+ uiChunk({ type: "start-step" })
84699
85000
  ];
84700
85001
  if (messageProjection) {
84701
85002
  outputs.push(...messagePartChunks(messageProjection));
@@ -84703,7 +85004,8 @@ var ClaudeCodeProjector = class {
84703
85004
  outputs.push(
84704
85005
  ...toolCallProjections.flatMap(
84705
85006
  (projection) => toolCallChunks(projection)
84706
- )
85007
+ ),
85008
+ uiChunk({ type: "finish-step" })
84707
85009
  );
84708
85010
  if (standalone && toolCallProjections.length === 0) {
84709
85011
  outputs.push(uiChunk({ type: "finish", finishReason: "stop" }));
@@ -87245,12 +87547,14 @@ var CodexProjector = class {
87245
87547
  activeToolCalls = /* @__PURE__ */ new Set();
87246
87548
  activeToolMetadata = /* @__PURE__ */ new Map();
87247
87549
  activeToolOutput = /* @__PURE__ */ new Map();
87550
+ activeSteps = /* @__PURE__ */ new Set();
87248
87551
  activeResponseMessageId = null;
87249
87552
  project(notification) {
87250
87553
  switch (notification.type) {
87251
87554
  case "agentMessageDelta":
87252
87555
  return [
87253
87556
  ...this.ensureResponseStarted(notification.itemId),
87557
+ ...this.ensureStepStarted(notification.itemId),
87254
87558
  ...this.projectAgentMessageDelta(
87255
87559
  notification.itemId,
87256
87560
  notification.delta
@@ -87277,7 +87581,10 @@ var CodexProjector = class {
87277
87581
  case "itemCompleted":
87278
87582
  return this.projectItem(notification.item, "completed");
87279
87583
  case "turnCompleted": {
87280
- const outputs = this.endAllReasoningParts();
87584
+ const outputs = [
87585
+ ...this.endAllReasoningParts(),
87586
+ ...this.finishAllSteps()
87587
+ ];
87281
87588
  this.activeResponseMessageId = null;
87282
87589
  this.activeAgentMessages.clear();
87283
87590
  this.agentMessagePhases.clear();
@@ -87360,7 +87667,10 @@ var CodexProjector = class {
87360
87667
  if (delta.length === 0) {
87361
87668
  return [];
87362
87669
  }
87363
- const outputs = this.ensureResponseStarted(itemId);
87670
+ const outputs = [
87671
+ ...this.ensureResponseStarted(itemId),
87672
+ ...this.ensureStepStarted(itemId)
87673
+ ];
87364
87674
  const active = this.activeReasoningParts.get(itemId);
87365
87675
  if (active && active.summaryIndex !== summaryIndex) {
87366
87676
  outputs.push(...this.endReasoningPart(itemId));
@@ -87407,10 +87717,15 @@ var CodexProjector = class {
87407
87717
  }
87408
87718
  return [
87409
87719
  ...this.ensureResponseStarted(item.id),
87720
+ ...this.ensureStepStarted(item.id),
87410
87721
  ...this.projectAgentMessageItem(item, phase)
87411
87722
  ];
87412
87723
  case "reasoning":
87413
- return this.projectReasoningItem(item, phase);
87724
+ return [
87725
+ ...this.ensureResponseStarted(item.id),
87726
+ ...this.ensureStepStarted(item.id),
87727
+ ...this.projectReasoningItem(item, phase)
87728
+ ];
87414
87729
  case "commandExecution":
87415
87730
  return this.projectToolItem({
87416
87731
  phase,
@@ -87440,7 +87755,14 @@ var CodexProjector = class {
87440
87755
  isDenied: isDeclinedStatus(item.status),
87441
87756
  isError: isFailedStatus(item.status),
87442
87757
  title: "apply_patch",
87443
- toolMetadata: statusMetadata(item.status)
87758
+ toolMetadata: statusMetadata(item.status, {
87759
+ activities: [
87760
+ {
87761
+ type: "edit",
87762
+ paths: fileChangePaths(item.changes)
87763
+ }
87764
+ ]
87765
+ })
87444
87766
  });
87445
87767
  case "mcpToolCall":
87446
87768
  if (isAskUserMcpTool(item.server, item.tool)) {
@@ -87460,6 +87782,132 @@ var CodexProjector = class {
87460
87782
  ...item.durationMs != null ? { durationMs: item.durationMs } : {}
87461
87783
  })
87462
87784
  });
87785
+ case "dynamicToolCall": {
87786
+ const name23 = item.namespace ? `${item.namespace}.${item.tool}` : item.tool;
87787
+ return this.projectToolItem({
87788
+ phase,
87789
+ itemId: item.id,
87790
+ name: name23,
87791
+ input: toJsonValue(item.arguments),
87792
+ output: {
87793
+ contentItems: toJsonValue(item.contentItems),
87794
+ success: item.success
87795
+ },
87796
+ isError: isFailedStatus(item.status) || item.success === false,
87797
+ title: name23,
87798
+ toolMetadata: statusMetadata(item.status, {
87799
+ tool: item.tool,
87800
+ ...item.namespace ? { server: item.namespace } : {},
87801
+ activities: [
87802
+ {
87803
+ type: "tool",
87804
+ name: item.tool,
87805
+ ...item.namespace ? { provider: item.namespace } : {}
87806
+ }
87807
+ ],
87808
+ ...item.durationMs != null ? { durationMs: item.durationMs } : {}
87809
+ })
87810
+ });
87811
+ }
87812
+ case "collabAgentToolCall":
87813
+ return this.projectToolItem({
87814
+ phase,
87815
+ itemId: item.id,
87816
+ name: `collaboration.${item.tool}`,
87817
+ input: {
87818
+ prompt: item.prompt,
87819
+ receiverThreadIds: item.receiverThreadIds,
87820
+ model: item.model,
87821
+ reasoningEffort: item.reasoningEffort
87822
+ },
87823
+ output: {
87824
+ status: item.status ?? "unknown",
87825
+ agentsStates: item.agentsStates
87826
+ },
87827
+ isError: isFailedStatus(item.status),
87828
+ title: item.tool,
87829
+ toolMetadata: statusMetadata(item.status, {
87830
+ activities: [{ type: "collaboration", action: item.tool }]
87831
+ })
87832
+ });
87833
+ case "subAgentActivity":
87834
+ return this.projectToolItem({
87835
+ phase,
87836
+ itemId: item.id,
87837
+ name: "collaboration.sub_agent_activity",
87838
+ input: {
87839
+ kind: item.kind,
87840
+ agentThreadId: item.agentThreadId,
87841
+ agentPath: item.agentPath
87842
+ },
87843
+ output: { status: "completed" },
87844
+ isError: false,
87845
+ title: item.kind,
87846
+ toolMetadata: {
87847
+ activities: [{ type: "collaboration", action: item.kind }]
87848
+ }
87849
+ });
87850
+ case "webSearch":
87851
+ return this.projectToolItem({
87852
+ phase,
87853
+ itemId: item.id,
87854
+ name: "web_search",
87855
+ input: { query: item.query, action: toJsonValue(item.action) },
87856
+ output: { status: "completed" },
87857
+ isError: false,
87858
+ title: item.query || "Web search",
87859
+ toolMetadata: {
87860
+ activities: [{ type: "webSearch", query: item.query }]
87861
+ }
87862
+ });
87863
+ case "imageView":
87864
+ return this.projectToolItem({
87865
+ phase,
87866
+ itemId: item.id,
87867
+ name: "view_image",
87868
+ input: { path: item.path },
87869
+ output: { status: "viewed" },
87870
+ isError: false,
87871
+ title: item.path,
87872
+ toolMetadata: {
87873
+ activities: [{ type: "imageView", path: item.path }]
87874
+ }
87875
+ });
87876
+ case "sleep":
87877
+ return this.projectToolItem({
87878
+ phase,
87879
+ itemId: item.id,
87880
+ name: "wait",
87881
+ input: { durationMs: item.durationMs },
87882
+ output: { status: "completed" },
87883
+ isError: false,
87884
+ title: "Wait",
87885
+ toolMetadata: {
87886
+ activities: [{ type: "wait", durationMs: item.durationMs }],
87887
+ durationMs: item.durationMs
87888
+ }
87889
+ });
87890
+ case "imageGeneration":
87891
+ return this.projectToolItem({
87892
+ phase,
87893
+ itemId: item.id,
87894
+ name: "image_generation",
87895
+ input: { prompt: item.revisedPrompt },
87896
+ output: {
87897
+ result: item.result,
87898
+ ...item.savedPath ? { savedPath: item.savedPath } : {}
87899
+ },
87900
+ isError: isFailedStatus(item.status),
87901
+ title: item.revisedPrompt ?? "Generate image",
87902
+ toolMetadata: statusMetadata(item.status, {
87903
+ activities: [
87904
+ {
87905
+ type: "imageGeneration",
87906
+ ...item.savedPath ? { savedPath: item.savedPath } : {}
87907
+ }
87908
+ ]
87909
+ })
87910
+ });
87463
87911
  default:
87464
87912
  return [];
87465
87913
  }
@@ -87467,6 +87915,7 @@ var CodexProjector = class {
87467
87915
  projectToolItem(input) {
87468
87916
  const outputs = [];
87469
87917
  outputs.push(...this.ensureResponseStarted(input.itemId));
87918
+ outputs.push(...this.ensureStepStarted(input.itemId));
87470
87919
  if (input.toolMetadata) {
87471
87920
  this.activeToolMetadata.set(input.itemId, input.toolMetadata);
87472
87921
  }
@@ -87482,7 +87931,7 @@ var CodexProjector = class {
87482
87931
  input.output = this.activeToolOutput.get(input.itemId)?.output ?? "";
87483
87932
  }
87484
87933
  outputs.push(toolOutputChunk(input));
87485
- outputs.push(uiChunk2({ type: "finish-step" }));
87934
+ outputs.push(...this.finishStep(input.itemId));
87486
87935
  this.activeToolCalls.delete(input.itemId);
87487
87936
  this.activeToolMetadata.delete(input.itemId);
87488
87937
  this.activeToolOutput.delete(input.itemId);
@@ -87515,7 +87964,7 @@ var CodexProjector = class {
87515
87964
  }
87516
87965
  outputs.push(
87517
87966
  textBoundaryChunk("text-end", item.id, messagePhase),
87518
- uiChunk2({ type: "finish-step" })
87967
+ ...this.finishStep(item.id)
87519
87968
  );
87520
87969
  this.activeAgentMessages.delete(item.id);
87521
87970
  this.agentMessagePhases.delete(item.id);
@@ -87530,15 +87979,11 @@ var CodexProjector = class {
87530
87979
  this.streamedReasoningIndexes.delete(item.id);
87531
87980
  if (streamedIndexes && streamedIndexes.size > 0) {
87532
87981
  outputs.push(...reasoningItemChunks(item, streamedIndexes));
87533
- outputs.push(uiChunk2({ type: "finish-step" }));
87982
+ outputs.push(...this.finishStep(item.id));
87534
87983
  return outputs;
87535
87984
  }
87536
87985
  const completedChunks = reasoningItemChunks(item);
87537
- return completedChunks.length > 0 ? [
87538
- ...this.ensureResponseStarted(item.id),
87539
- ...completedChunks,
87540
- uiChunk2({ type: "finish-step" })
87541
- ] : [];
87986
+ return [...completedChunks, ...this.finishStep(item.id)];
87542
87987
  }
87543
87988
  endReasoningPart(itemId) {
87544
87989
  const active = this.activeReasoningParts.get(itemId);
@@ -87560,6 +88005,26 @@ var CodexProjector = class {
87560
88005
  this.activeResponseMessageId = messageId;
87561
88006
  return [uiChunk2({ type: "start", messageId })];
87562
88007
  }
88008
+ ensureStepStarted(itemId) {
88009
+ if (this.activeSteps.has(itemId)) {
88010
+ return [];
88011
+ }
88012
+ this.activeSteps.add(itemId);
88013
+ return [uiChunk2({ type: "start-step" })];
88014
+ }
88015
+ finishStep(itemId) {
88016
+ if (!this.activeSteps.delete(itemId)) {
88017
+ return [];
88018
+ }
88019
+ return [uiChunk2({ type: "finish-step" })];
88020
+ }
88021
+ finishAllSteps() {
88022
+ const outputs = [...this.activeSteps].map(
88023
+ () => uiChunk2({ type: "finish-step" })
88024
+ );
88025
+ this.activeSteps.clear();
88026
+ return outputs;
88027
+ }
87563
88028
  };
87564
88029
  function emptyToolOutput() {
87565
88030
  return { bytes: 0, output: "", truncated: false };
@@ -87683,6 +88148,14 @@ function commandActivities(actions) {
87683
88148
  }
87684
88149
  });
87685
88150
  }
88151
+ function fileChangePaths(changes) {
88152
+ return changes.flatMap((change) => {
88153
+ if (typeof change !== "object" || change === null || !("path" in change) || typeof change.path !== "string") {
88154
+ return [];
88155
+ }
88156
+ return [change.path];
88157
+ });
88158
+ }
87686
88159
  function turnCompletionEntry(notification) {
87687
88160
  if (notification.status === "failed") {
87688
88161
  const detail = notification.errorMessage ?? "unknown error";