@ellipsis-dev/sdk 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { A as AgentSessionWire, L as ListSessionRecordsResponse, a as ListSessionTurnsResponse, S as SessionMessageWire } from './types-BRE4NMnS.js';
2
- export { b as AgentSessionExitStatus, c as AgentSessionPr, d as AgentSessionSource, e as AgentSessionStatus, f as AgentTurn, g as AgentTurnStatus, h as AttributionType, B as BudgetSource, D as DefaultResolution, i as DeltaFrame, j as DoneFrame, E as ErrorFrame, G as GithubAccountSnippet, k as GithubAccountType, H as Harness, l as HeartbeatFrame, M as MessagesFrame, m as ModelTokensInfo, P as ParentKind, R as RecordsAppendFrame, n as SendSessionMessageRequest, o as SessionFrame, p as SessionLiveness, q as SessionMessageStatus, r as SessionRecordWire, s as SessionState, t as SessionStreamFrame, u as SessionSurface, v as SnapshotFrame, w as StreamFrame, T as TokensInfo, x as TurnTokensInfo, y as components, z as paths } from './types-BRE4NMnS.js';
1
+ import { A as AgentSessionWire, L as ListSessionRecordsResponse, a as ListSessionTurnsResponse, b as ListSessionExecutionsResponse, S as SessionMessageWire } from './types-CtvSTnzA.js';
2
+ export { c as AgentSessionExitStatus, d as AgentSessionPr, e as AgentSessionSource, f as AgentSessionStatus, g as AgentTurn, h as AgentTurnStatus, i as AttributionType, B as BudgetSource, D as DefaultResolution, j as DeltaFrame, k as DoneFrame, E as ErrorFrame, G as GithubAccountSnippet, l as GithubAccountType, H as Harness, m as HeartbeatFrame, M as ModelTokensInfo, P as ParentKind, R as RecordsAppendFrame, n as SendSessionMessageRequest, o as SessionExecutionWire, p as SessionFrame, q as SessionLiveness, r as SessionMessageStatus, s as SessionRecordWire, t as SessionState, u as SessionStreamFrame, v as SessionSurface, w as SnapshotFrame, x as StreamFrame, T as TokensInfo, y as TurnTokensInfo, z as components, C as paths } from './types-CtvSTnzA.js';
3
3
 
4
4
  type FetchJson = (path: string, init?: {
5
5
  method?: string;
@@ -14,9 +14,10 @@ declare class EllipsisClient {
14
14
  limit?: number;
15
15
  }): Promise<ListSessionRecordsResponse>;
16
16
  getSessionTurns(sessionId: string): Promise<ListSessionTurnsResponse>;
17
+ getSessionExecutions(sessionId: string): Promise<ListSessionExecutionsResponse>;
17
18
  sendSessionMessage(sessionId: string, message: string, options?: {
18
19
  idempotencyKey?: string;
19
20
  }): Promise<SessionMessageWire>;
20
21
  }
21
22
 
22
- export { AgentSessionWire, EllipsisClient, type FetchJson, ListSessionRecordsResponse, ListSessionTurnsResponse, SessionMessageWire };
23
+ export { AgentSessionWire, EllipsisClient, type FetchJson, ListSessionExecutionsResponse, ListSessionRecordsResponse, ListSessionTurnsResponse, SessionMessageWire };
package/dist/index.js CHANGED
@@ -30,6 +30,16 @@ var EllipsisClient = class {
30
30
  `/v1/sessions/${encodeURIComponent(sessionId)}/turns`
31
31
  );
32
32
  }
33
+ // The session's executions (initial start, cold wakes, infra retries) with
34
+ // their launch context: `system_prompt_append` is the text Ellipsis appends
35
+ // to Claude Code's default system prompt, alongside the initial query and
36
+ // model. Per execution because each cold wake persists its own launch
37
+ // config.
38
+ async getSessionExecutions(sessionId) {
39
+ return await this.fetchJson(
40
+ `/v1/sessions/${encodeURIComponent(sessionId)}/executions`
41
+ );
42
+ }
33
43
  // Send a message into the session's inbox (§4.2). Returns the created (or,
34
44
  // on an idempotent retry, the original) inbox row — clients key optimistic
35
45
  // echo chips on its id. `idempotencyKey` makes retries safe per
@@ -1,4 +1,4 @@
1
- import { r as SessionRecordWire, A as AgentSessionWire, S as SessionMessageWire, w as StreamFrame } from '../types-BRE4NMnS.js';
1
+ import { s as SessionRecordWire, A as AgentSessionWire, S as SessionMessageWire, x as StreamFrame } from '../types-CtvSTnzA.js';
2
2
 
3
3
  interface ChatToolNode {
4
4
  key: string;
@@ -8,6 +8,8 @@ interface ChatToolNode {
8
8
  summary: string;
9
9
  result: string | null;
10
10
  isError: boolean;
11
+ startedAt: string | null;
12
+ completedAt: string | null;
11
13
  }
12
14
  type ChatNode = {
13
15
  key: string;
@@ -26,7 +28,9 @@ type ChatNode = {
26
28
  kind: 'lifecycle';
27
29
  text: string;
28
30
  recordType: string;
29
- hook?: string;
31
+ step?: string;
32
+ lines?: string[];
33
+ payload?: Record<string, unknown>;
30
34
  } | ChatToolNode;
31
35
  interface ChatTurn {
32
36
  key: string;
@@ -41,8 +45,11 @@ interface ChatTurn {
41
45
  }
42
46
  declare function groupRecordsToChatTurns(records: readonly SessionRecordWire[]): ChatTurn[];
43
47
 
44
- declare function setupOutputHook(payload: Record<string, unknown>): string;
45
- declare function setupOutputLine(payload: Record<string, unknown>): string | null;
48
+ declare function sandboxOutputStep(payload: Record<string, unknown>): string;
49
+ declare function sandboxOutputLines(payload: Record<string, unknown>): string[];
50
+ declare function sandboxOutputLine(payload: Record<string, unknown>): string | null;
51
+ declare function cacheTierLabel(tier: unknown): string | null;
52
+ declare function sandboxPhaseLabel(phase: unknown): string;
46
53
  declare function lifecycleText(recordType: string, payload: Record<string, unknown>): string | null;
47
54
 
48
55
  interface CCContentBlock {
@@ -132,6 +139,7 @@ declare class SessionTranscriptStore {
132
139
  private snapshot;
133
140
  private listeners;
134
141
  private acknowledged;
142
+ private inbox;
135
143
  private cursorSeq;
136
144
  private turnsFor;
137
145
  private turnsCache;
@@ -139,7 +147,9 @@ declare class SessionTranscriptStore {
139
147
  subscribe: (listener: () => void) => (() => void);
140
148
  getSnapshot: () => SessionTranscriptSnapshot;
141
149
  chatTurns: () => ChatTurn[];
150
+ private pendingMessages;
151
+ private applyMessageRecord;
142
152
  ingest: (rawFrame: StreamFrame) => void;
143
153
  }
144
154
 
145
- export { type CCContentBlock, type CCEvent, type ChatNode, type ChatToolNode, type ChatTurn, type EventToItemsOptions, type ItemKind, LineBuffer, type SessionTranscriptSnapshot, SessionTranscriptStore, StreamFrame, type TranscriptItem, clampLines, collapseToolRuns, emptySessionTranscriptSnapshot, eventToItems, foldCosts, formatDuration, groupRecordsToChatTurns, isConnectVisibleRecord, isConversationOver, lifecycleText, oneLine, parseEventLine, pendingToolCalls, recordToItems, resultCostUsd, setupOutputHook, setupOutputLine, statusActivityText, summarizeToolInput };
155
+ export { type CCContentBlock, type CCEvent, type ChatNode, type ChatToolNode, type ChatTurn, type EventToItemsOptions, type ItemKind, LineBuffer, type SessionTranscriptSnapshot, SessionTranscriptStore, StreamFrame, type TranscriptItem, cacheTierLabel, clampLines, collapseToolRuns, emptySessionTranscriptSnapshot, eventToItems, foldCosts, formatDuration, groupRecordsToChatTurns, isConnectVisibleRecord, isConversationOver, lifecycleText, oneLine, parseEventLine, pendingToolCalls, recordToItems, resultCostUsd, sandboxOutputLine, sandboxOutputLines, sandboxOutputStep, sandboxPhaseLabel, statusActivityText, summarizeToolInput };
@@ -1,11 +1,15 @@
1
1
  // src/store/lifecycle.ts
2
- function setupOutputHook(payload) {
3
- return typeof payload.hook === "string" ? payload.hook : "setup";
2
+ function sandboxOutputStep(payload) {
3
+ if (typeof payload.step === "string" && payload.step) return payload.step;
4
+ return typeof payload.phase === "string" ? payload.phase : "setup";
4
5
  }
5
- function setupOutputLine(payload) {
6
- const lines = Array.isArray(payload.lines) ? payload.lines.filter(
6
+ function sandboxOutputLines(payload) {
7
+ return Array.isArray(payload.lines) ? payload.lines.filter(
7
8
  (l) => typeof l === "string" && l.trim().length > 0
8
9
  ) : [];
10
+ }
11
+ function sandboxOutputLine(payload) {
12
+ const lines = sandboxOutputLines(payload);
9
13
  return lines.length ? lines[lines.length - 1].trim() : null;
10
14
  }
11
15
  function cacheTierLabel(tier) {
@@ -20,13 +24,71 @@ function cacheTierLabel(tier) {
20
24
  return null;
21
25
  }
22
26
  }
27
+ function sandboxPhaseLabel(phase) {
28
+ switch (phase) {
29
+ case "image":
30
+ return "Preparing image";
31
+ case "clone":
32
+ return "Fetching repositories";
33
+ case "setup":
34
+ return "Running setup";
35
+ case "snapshot":
36
+ return "Snapshotting";
37
+ case "hooks":
38
+ return "Running hooks";
39
+ case "restore":
40
+ return "Restoring workspace";
41
+ default:
42
+ return typeof phase === "string" && phase ? phase.charAt(0).toUpperCase() + phase.slice(1) : "Working";
43
+ }
44
+ }
45
+ function durationLabel(ms) {
46
+ if (typeof ms !== "number" || !isFinite(ms) || ms < 0) return null;
47
+ return ms >= 1e3 ? `${(ms / 1e3).toFixed(1)}s` : `${Math.round(ms)}ms`;
48
+ }
49
+ function sandboxPhaseText(payload) {
50
+ const label = sandboxPhaseLabel(payload.phase);
51
+ const detail = payload.detail && typeof payload.detail === "object" ? payload.detail : {};
52
+ switch (payload.status) {
53
+ case "started":
54
+ return `${label}\u2026`;
55
+ case "completed": {
56
+ const parts = [label];
57
+ const tier = cacheTierLabel(detail.cache_tier);
58
+ if (tier) parts.push(tier);
59
+ const duration = durationLabel(payload.duration_ms);
60
+ if (duration) parts.push(duration);
61
+ return parts.join(" \xB7 ");
62
+ }
63
+ case "failed": {
64
+ const duration = durationLabel(payload.duration_ms);
65
+ return duration ? `${label} failed \xB7 ${duration}` : `${label} failed`;
66
+ }
67
+ default:
68
+ return label;
69
+ }
70
+ }
23
71
  function lifecycleText(recordType, payload) {
24
72
  switch (recordType) {
73
+ case "session_scheduled": {
74
+ const config = typeof payload.config_name === "string" ? payload.config_name : null;
75
+ return config ? `Session scheduled \xB7 ${config}` : "Session scheduled";
76
+ }
77
+ case "session_starting": {
78
+ const attempt = typeof payload.attempt === "number" ? payload.attempt : 0;
79
+ if (attempt > 0) return "Retrying\u2026";
80
+ const wakeIndex = typeof payload.wake_index === "number" ? payload.wake_index : 0;
81
+ return wakeIndex > 0 ? "Waking the session\u2026" : "Session starting\u2026";
82
+ }
83
+ case "session_retrying":
84
+ return typeof payload.reason === "string" && payload.reason ? `Retrying \xB7 ${payload.reason}` : "Retrying after a transient error\u2026";
25
85
  case "sandbox_starting":
26
86
  return "Starting sandbox\u2026";
27
- case "sandbox_setup_output": {
28
- const last = setupOutputLine(payload);
29
- return last ? `${setupOutputHook(payload)} \xB7 ${last}` : null;
87
+ case "sandbox_phase":
88
+ return sandboxPhaseText(payload);
89
+ case "sandbox_output": {
90
+ const last = sandboxOutputLine(payload);
91
+ return last ? `${sandboxOutputStep(payload)} \xB7 ${last}` : null;
30
92
  }
31
93
  case "sandbox_ready": {
32
94
  const repos = Array.isArray(payload.repositories) ? payload.repositories.filter(
@@ -40,8 +102,8 @@ function lifecycleText(recordType, payload) {
40
102
  }
41
103
  case "session_resumed":
42
104
  return "Resumed the conversation";
43
- case "session_paused":
44
- return "Sleeping \u2014 your next message wakes it";
105
+ case "session_idle":
106
+ return "Idle \u2014 your next message wakes it";
45
107
  case "session_closed":
46
108
  return "Conversation closed";
47
109
  case "session_cancelled": {
@@ -314,6 +376,12 @@ var TOOL_USE_BLOCK_TYPES = /* @__PURE__ */ new Set([
314
376
  "server_tool_use",
315
377
  "mcp_tool_use"
316
378
  ]);
379
+ var SANDBOX_RECORD_TYPES = /* @__PURE__ */ new Set([
380
+ "sandbox_starting",
381
+ "sandbox_phase",
382
+ "sandbox_output",
383
+ "sandbox_ready"
384
+ ]);
317
385
  function toolResultText2(block) {
318
386
  const c = block.content;
319
387
  if (typeof c === "string") return c.trim();
@@ -331,6 +399,7 @@ function groupRecordsToChatTurns(records) {
331
399
  let seq = 0;
332
400
  const nextKey = (base) => `${base}:${seq++}`;
333
401
  let openIdx = -1;
402
+ let prevCumulativeCostUsd = 0;
334
403
  let initCount = 0;
335
404
  let pendingResume = false;
336
405
  const openAgentTurn = (record) => {
@@ -354,36 +423,64 @@ function groupRecordsToChatTurns(records) {
354
423
  for (const record of records) {
355
424
  if (record.source === "lifecycle") {
356
425
  const text = lifecycleText(record.record_type, record.payload);
357
- if (text) {
358
- const isSetupOutput = record.record_type === "sandbox_setup_output";
359
- const hook = isSetupOutput ? setupOutputHook(record.payload) : void 0;
360
- const prev = turns.length > 0 ? turns[turns.length - 1] : null;
361
- const prevNode = prev?.nodes[0];
362
- if (isSetupOutput && prev && prevNode && prevNode.kind === "lifecycle" && prevNode.hook === hook) {
363
- prevNode.text = text;
364
- prev.completedAt = record.created_at;
365
- continue;
426
+ if (!text) continue;
427
+ const isSandbox = SANDBOX_RECORD_TYPES.has(record.record_type);
428
+ const isSandboxOutput = record.record_type === "sandbox_output";
429
+ const step = isSandboxOutput ? sandboxOutputStep(record.payload) : void 0;
430
+ const lines = isSandboxOutput ? sandboxOutputLines(record.payload) : void 0;
431
+ let foldTarget = null;
432
+ if (isSandbox && record.record_type !== "sandbox_starting") {
433
+ for (let i = turns.length - 1; i >= 0; i--) {
434
+ const candidate = turns[i];
435
+ if (candidate.role !== "lifecycle") break;
436
+ if (candidate.nodes.some(
437
+ (n) => n.kind === "lifecycle" && SANDBOX_RECORD_TYPES.has(n.recordType)
438
+ )) {
439
+ foldTarget = candidate;
440
+ break;
441
+ }
366
442
  }
367
- turns.push({
368
- key: nextKey(record.id),
369
- role: "lifecycle",
370
- nodes: [
371
- {
372
- key: nextKey(record.id),
373
- kind: "lifecycle",
374
- text,
375
- recordType: record.record_type,
376
- hook
377
- }
378
- ],
379
- startedAt: record.created_at,
380
- completedAt: record.created_at,
381
- durationMs: null,
382
- costUsd: null,
383
- tokens: null,
384
- resumed: false
385
- });
386
443
  }
444
+ if (foldTarget) {
445
+ const last = foldTarget.nodes[foldTarget.nodes.length - 1];
446
+ if (isSandboxOutput && last && last.kind === "lifecycle" && last.recordType === "sandbox_output" && last.step === step) {
447
+ last.text = text;
448
+ last.lines = [...last.lines ?? [], ...lines ?? []];
449
+ } else {
450
+ foldTarget.nodes.push({
451
+ key: nextKey(record.id),
452
+ kind: "lifecycle",
453
+ text,
454
+ recordType: record.record_type,
455
+ step,
456
+ lines,
457
+ payload: record.payload
458
+ });
459
+ }
460
+ foldTarget.completedAt = record.created_at;
461
+ continue;
462
+ }
463
+ turns.push({
464
+ key: nextKey(record.id),
465
+ role: "lifecycle",
466
+ nodes: [
467
+ {
468
+ key: nextKey(record.id),
469
+ kind: "lifecycle",
470
+ text,
471
+ recordType: record.record_type,
472
+ step,
473
+ lines,
474
+ payload: record.payload
475
+ }
476
+ ],
477
+ startedAt: record.created_at,
478
+ completedAt: record.created_at,
479
+ durationMs: null,
480
+ costUsd: null,
481
+ tokens: null,
482
+ resumed: false
483
+ });
387
484
  continue;
388
485
  }
389
486
  if (record.source !== "claude_code") continue;
@@ -399,8 +496,13 @@ function groupRecordsToChatTurns(records) {
399
496
  if (openIdx >= 0) {
400
497
  turns[openIdx].completedAt = record.created_at;
401
498
  turns[openIdx].durationMs = typeof data.duration_ms === "number" ? data.duration_ms : null;
402
- if (typeof data.total_cost_usd === "number")
403
- turns[openIdx].costUsd = data.total_cost_usd;
499
+ if (typeof data.total_cost_usd === "number") {
500
+ turns[openIdx].costUsd = Math.max(
501
+ 0,
502
+ data.total_cost_usd - prevCumulativeCostUsd
503
+ );
504
+ prevCumulativeCostUsd = data.total_cost_usd;
505
+ }
404
506
  openIdx = -1;
405
507
  }
406
508
  continue;
@@ -437,6 +539,7 @@ function groupRecordsToChatTurns(records) {
437
539
  if (node) {
438
540
  node.result = body;
439
541
  node.isError = !!block.is_error;
542
+ node.completedAt = record.created_at;
440
543
  } else {
441
544
  const orphan = {
442
545
  key: nextKey(record.id),
@@ -445,7 +548,9 @@ function groupRecordsToChatTurns(records) {
445
548
  input: null,
446
549
  summary: "",
447
550
  result: body,
448
- isError: !!block.is_error
551
+ isError: !!block.is_error,
552
+ startedAt: null,
553
+ completedAt: record.created_at
449
554
  };
450
555
  openAgentTurn(record).nodes.push(orphan);
451
556
  if (useId != null) toolNodeByUseId.set(useId, orphan);
@@ -476,7 +581,9 @@ function groupRecordsToChatTurns(records) {
476
581
  input: block.input ?? null,
477
582
  summary: summarizeToolInput(name, block.input ?? void 0),
478
583
  result: null,
479
- isError: false
584
+ isError: false,
585
+ startedAt: record.created_at,
586
+ completedAt: null
480
587
  };
481
588
  turn.nodes.push(node);
482
589
  if (block.id) toolNodeByUseId.set(block.id, node);
@@ -523,6 +630,11 @@ var SessionTranscriptStore = class {
523
630
  snapshot = EMPTY_SNAPSHOT;
524
631
  listeners = /* @__PURE__ */ new Set();
525
632
  acknowledged = /* @__PURE__ */ new Set();
633
+ // The inbox projection (protocol v3): message_received/delivered/requeued
634
+ // RECORDS drive it; the snapshot seeds the pending set at connect. Keyed by
635
+ // message id so a requeue can restore a message the delivered record
636
+ // removed from the pending view.
637
+ inbox = /* @__PURE__ */ new Map();
526
638
  // The resume cursor: the highest feed_seq received via records_append. Only
527
639
  // records advance it (§3.4) — never messages/session frames. streamSession
528
640
  // tracks its own copy; this one seeds a NEW streamSession call (e.g. a
@@ -551,6 +663,57 @@ var SessionTranscriptStore = class {
551
663
  }
552
664
  return this.turnsCache;
553
665
  };
666
+ // The current pending set, in feed order — what queued chips render.
667
+ pendingMessages = () => [...this.inbox.values()].filter((m) => m.status === "pending").sort((a, b) => (a.feed_seq ?? 0) - (b.feed_seq ?? 0));
668
+ // Fold one lifecycle record into the inbox projection; returns whether the
669
+ // pending view changed. Unknown fields/types are ignored (§3.6).
670
+ applyMessageRecord = (record) => {
671
+ const payload = record.payload;
672
+ const messageId = typeof payload.message_id === "string" ? payload.message_id : null;
673
+ switch (record.record_type) {
674
+ case "message_received": {
675
+ if (messageId == null || this.inbox.has(messageId)) return false;
676
+ this.inbox.set(messageId, {
677
+ id: messageId,
678
+ agent_session_id: record.agent_session_id,
679
+ feed_seq: record.feed_seq,
680
+ status: "pending",
681
+ body: typeof payload.body === "string" ? payload.body : "",
682
+ author: typeof payload.author === "string" ? payload.author : null,
683
+ sender_attribution_type: typeof payload.sender_attribution_type === "string" ? payload.sender_attribution_type : null,
684
+ sender_attribution_id: typeof payload.sender_attribution_id === "string" ? payload.sender_attribution_id : null,
685
+ created_at: record.created_at,
686
+ delivered_at: null,
687
+ delivered_turn_id: null
688
+ });
689
+ return true;
690
+ }
691
+ case "message_delivered": {
692
+ const existing = messageId != null ? this.inbox.get(messageId) : null;
693
+ if (!existing || existing.status !== "pending") return false;
694
+ this.inbox.set(messageId, {
695
+ ...existing,
696
+ status: "delivered",
697
+ delivered_at: record.created_at,
698
+ delivered_turn_id: typeof payload.turn_id === "string" ? payload.turn_id : null
699
+ });
700
+ return true;
701
+ }
702
+ case "message_requeued": {
703
+ const existing = messageId != null ? this.inbox.get(messageId) : null;
704
+ if (!existing || existing.status === "pending") return false;
705
+ this.inbox.set(messageId, {
706
+ ...existing,
707
+ status: "pending",
708
+ delivered_at: null,
709
+ delivered_turn_id: null
710
+ });
711
+ return true;
712
+ }
713
+ default:
714
+ return false;
715
+ }
716
+ };
554
717
  // Ingest one frame from the stream client. Unknown frame types stamp
555
718
  // liveness and change nothing else (§3.6).
556
719
  ingest = (rawFrame) => {
@@ -563,8 +726,11 @@ var SessionTranscriptStore = class {
563
726
  switch (frame.type) {
564
727
  case "snapshot": {
565
728
  next.session = frame.session;
566
- next.messages = frame.messages;
567
- for (const message of frame.messages) this.acknowledged.add(message.id);
729
+ for (const message of frame.messages) {
730
+ this.inbox.set(message.id, message);
731
+ this.acknowledged.add(message.id);
732
+ }
733
+ next.messages = this.pendingMessages();
568
734
  next.acknowledgedMessageIds = new Set(this.acknowledged);
569
735
  next.conversationOver = isConversationOver(frame.session);
570
736
  next.historyTruncated = frame.earliest_feed_seq != null && this.cursorSeq < frame.earliest_feed_seq - 1;
@@ -576,12 +742,24 @@ var SessionTranscriptStore = class {
576
742
  this.cursorSeq = fresh[fresh.length - 1].feed_seq;
577
743
  next.records = [...prev.records, ...fresh];
578
744
  let acknowledgedNew = false;
745
+ let inboxChanged = false;
579
746
  for (const record of fresh) {
580
747
  if (record.session_message_id != null) {
581
748
  this.acknowledged.add(record.session_message_id);
582
749
  acknowledgedNew = true;
583
750
  }
751
+ if (record.source === "lifecycle") {
752
+ inboxChanged = this.applyMessageRecord(record) || inboxChanged;
753
+ if (record.record_type === "message_received" || record.record_type === "message_delivered") {
754
+ const payload = record.payload;
755
+ if (typeof payload.message_id === "string") {
756
+ this.acknowledged.add(payload.message_id);
757
+ acknowledgedNew = true;
758
+ }
759
+ }
760
+ }
584
761
  }
762
+ if (inboxChanged) next.messages = this.pendingMessages();
585
763
  if (acknowledgedNew) {
586
764
  next.acknowledgedMessageIds = new Set(this.acknowledged);
587
765
  }
@@ -589,12 +767,6 @@ var SessionTranscriptStore = class {
589
767
  next.liveOutputTokens = null;
590
768
  break;
591
769
  }
592
- case "messages": {
593
- next.messages = frame.messages;
594
- for (const message of frame.messages) this.acknowledged.add(message.id);
595
- next.acknowledgedMessageIds = new Set(this.acknowledged);
596
- break;
597
- }
598
770
  case "session": {
599
771
  next.session = frame.session;
600
772
  next.conversationOver = isConversationOver(frame.session);
@@ -621,6 +793,7 @@ var SessionTranscriptStore = class {
621
793
  export {
622
794
  LineBuffer,
623
795
  SessionTranscriptStore,
796
+ cacheTierLabel,
624
797
  clampLines,
625
798
  collapseToolRuns,
626
799
  emptySessionTranscriptSnapshot,
@@ -636,8 +809,10 @@ export {
636
809
  pendingToolCalls,
637
810
  recordToItems,
638
811
  resultCostUsd,
639
- setupOutputHook,
640
- setupOutputLine,
812
+ sandboxOutputLine,
813
+ sandboxOutputLines,
814
+ sandboxOutputStep,
815
+ sandboxPhaseLabel,
641
816
  statusActivityText,
642
817
  summarizeToolInput
643
818
  };
@@ -1,6 +1,6 @@
1
- import { w as StreamFrame, A as AgentSessionWire } from '../types-BRE4NMnS.js';
1
+ import { x as StreamFrame, A as AgentSessionWire } from '../types-CtvSTnzA.js';
2
2
 
3
- declare const SESSION_STREAM_PROTOCOL_VERSION = 2;
3
+ declare const SESSION_STREAM_PROTOCOL_VERSION = 3;
4
4
  declare const WS_CLOSE_NORMAL = 1000;
5
5
  declare const WS_CLOSE_GOING_AWAY = 1001;
6
6
  declare const WS_CLOSE_UNSUPPORTED_PROTOCOL_VERSION = 1002;
@@ -1,5 +1,5 @@
1
1
  // src/stream/index.ts
2
- var SESSION_STREAM_PROTOCOL_VERSION = 2;
2
+ var SESSION_STREAM_PROTOCOL_VERSION = 3;
3
3
  var WS_CLOSE_NORMAL = 1e3;
4
4
  var WS_CLOSE_GOING_AWAY = 1001;
5
5
  var WS_CLOSE_UNSUPPORTED_PROTOCOL_VERSION = 1002;