@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 +4 -3
- package/dist/index.js +10 -0
- package/dist/store/index.d.ts +15 -5
- package/dist/store/index.js +226 -51
- package/dist/stream/index.d.ts +2 -2
- package/dist/stream/index.js +1 -1
- package/dist/{types-BRE4NMnS.d.ts → types-CtvSTnzA.d.ts} +97 -14
- package/package.json +1 -1
- package/schema/frames.schema.json +2 -29
- package/schema/lifecycle.schema.json +505 -0
- package/schema/openapi.v1.json +181 -0
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-
|
|
2
|
-
export {
|
|
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
|
package/dist/store/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
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
|
-
|
|
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
|
|
45
|
-
declare function
|
|
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,
|
|
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 };
|
package/dist/store/index.js
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
// src/store/lifecycle.ts
|
|
2
|
-
function
|
|
3
|
-
|
|
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
|
|
6
|
-
|
|
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 "
|
|
28
|
-
|
|
29
|
-
|
|
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 "
|
|
44
|
-
return "
|
|
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
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
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 =
|
|
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
|
-
|
|
567
|
-
|
|
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
|
-
|
|
640
|
-
|
|
812
|
+
sandboxOutputLine,
|
|
813
|
+
sandboxOutputLines,
|
|
814
|
+
sandboxOutputStep,
|
|
815
|
+
sandboxPhaseLabel,
|
|
641
816
|
statusActivityText,
|
|
642
817
|
summarizeToolInput
|
|
643
818
|
};
|
package/dist/stream/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { x as StreamFrame, A as AgentSessionWire } from '../types-CtvSTnzA.js';
|
|
2
2
|
|
|
3
|
-
declare const SESSION_STREAM_PROTOCOL_VERSION =
|
|
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;
|
package/dist/stream/index.js
CHANGED