@workerdeck/protocol 2.10.0 → 2.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/index.d.mts CHANGED
@@ -1,10 +1,12 @@
1
1
  //#region src/pricing.d.ts
2
+ type CostBasis = 'list' | 'managed' | 'unknown';
2
3
  type TokenUsage = {
3
4
  input: number;
4
5
  output: number;
5
6
  cacheWrite5m: number;
6
7
  cacheWrite1h: number;
7
8
  cacheRead: number;
9
+ costBasis?: CostBasis;
8
10
  };
9
11
  type ByModel = Record<string, TokenUsage>;
10
12
  type ModelRate = {
@@ -28,18 +30,33 @@ declare const PRICING_AS_OF = "2026-09-19";
28
30
  declare const PRICING_SOURCES = "platform.claude.com and developers.openai.com list prices, bundled";
29
31
  declare const PRICING_NOTE = "List rates as of 2026-09-19. A subscription is a flat fee, so this is what the same tokens would have cost on the pay-as-you-go API, not a bill.";
30
32
  declare const UNPRICED_WARN_SHARE = 0.005;
33
+ declare const PRICING_STALE_DAYS = 90;
31
34
  declare const DEFAULT_PRICING: Record<string, ModelRate>;
35
+ type PricingTable = Record<string, ModelRate>;
36
+ type PricingOverrides = Record<string, ModelRate>;
37
+ type PricingMerge = {
38
+ pricing: PricingTable;
39
+ overrides: PricingOverrides;
40
+ dropped: string[];
41
+ };
42
+ declare function mergePricing(overrides: unknown, base?: PricingTable): PricingMerge;
43
+ declare function activePricing(): PricingTable;
44
+ declare function setPricingOverrides(overrides: unknown): PricingMerge;
45
+ declare function pricingAgeDays(now: number, asOf?: string): number;
46
+ declare function pricingAgeNote(now: number, asOf?: string): string | undefined;
32
47
  declare function canonicalModel(model: string): string;
33
- declare function rateFor(model: string | undefined, pricing?: Record<string, ModelRate>): ModelRate | undefined;
48
+ declare function rateFor(model: string | undefined, pricing?: PricingTable): ModelRate | undefined;
34
49
  declare function emptyTokenUsage(): TokenUsage;
35
50
  declare function totalTokens(usage: TokenUsage): number;
36
51
  declare function addTokenUsage(into: TokenUsage, add: TokenUsage): TokenUsage;
52
+ declare function worseBasis(a: CostBasis | undefined, b: CostBasis | undefined): CostBasis | undefined;
53
+ declare function unknownBasisModels(byModel: ByModel): string[];
37
54
  declare function mergeByModel(into: ByModel, add: ByModel): ByModel;
38
55
  declare function byModelTotalTokens(byModel: ByModel): number;
39
56
  declare function tokenUsageFromWire(usage: unknown): TokenUsage;
40
- declare function costOf(usage: TokenUsage, model: string | undefined, pricing?: Record<string, ModelRate>): CostBreakdown;
41
- declare function costOfByModel(byModel: ByModel, pricing?: Record<string, ModelRate>): CostBreakdown;
42
- declare function unpricedModels(byModel: ByModel, pricing?: Record<string, ModelRate>): string[];
57
+ declare function costOf(usage: TokenUsage, model: string | undefined, pricing?: PricingTable): CostBreakdown;
58
+ declare function costOfByModel(byModel: ByModel, pricing?: PricingTable): CostBreakdown;
59
+ declare function unpricedModels(byModel: ByModel, pricing?: PricingTable): string[];
43
60
  declare function meteredCost(cost: CostBreakdown): number;
44
61
  type SubscriptionComparison = {
45
62
  weeklyUsd: number;
@@ -80,17 +97,35 @@ declare function taskSummary(tasks: readonly SessionTask[]): TaskSummary;
80
97
  declare function taskCountLabel(summary: TaskSummary): string | undefined;
81
98
  declare function visibleTasks(tasks: readonly SessionTask[], showCompleted: boolean): SessionTask[];
82
99
  //#endregion
100
+ //#region src/peer-mentions.d.ts
101
+ declare const PEER_MENTION_SIGIL = "#";
102
+ declare const PEER_MENTION_MAX = 4;
103
+ declare const PEER_MENTION_BODY_MAX = 64;
104
+ declare const PEER_MENTION_SCAN_MAX = 32;
105
+ type PeerMentionToken = {
106
+ start: number;
107
+ end: number;
108
+ body: string;
109
+ };
110
+ declare const PROMPT_SENTENCE_TAIL: ReadonlySet<string>;
111
+ declare function peerMentionSlug(title: string | undefined, id: string): string;
112
+ declare function peerMentionKey(body: string): string;
113
+ declare function isPeerMentionBody(body: string): boolean;
114
+ declare function scanPeerMentions(text: string): PeerMentionToken[];
115
+ //#endregion
83
116
  //#region src/session-list.d.ts
84
117
  type SessionState = 'attention' | 'working' | 'idle' | 'ended';
85
118
  declare const STATE_ORDER: readonly SessionState[];
86
119
  declare const STATE_LABELS: Record<SessionState, string>;
87
120
  declare function sessionState(info: SessionInfo): SessionState;
88
121
  declare function runningSubagents(info: SessionInfo): SubagentInfo[];
122
+ declare function visibleSubagents(info: SessionInfo, show: SubagentDisplay): SubagentInfo[];
89
123
  declare function isAgentRecord(sub: SubagentInfo): boolean;
90
124
  declare function subagentLabel(sub: SubagentInfo): string;
91
125
  type Facet = 'gateway' | 'adapter' | 'state' | 'project';
92
126
  type GroupBy = 'none' | Facet;
93
127
  type SortBy = 'recent' | 'name' | Facet;
128
+ type SubagentDisplay = 'all' | 'active' | 'none';
94
129
  type ViewConfig = {
95
130
  search: string;
96
131
  gateways: string[];
@@ -100,6 +135,7 @@ type ViewConfig = {
100
135
  scoped: boolean;
101
136
  groupBy: GroupBy;
102
137
  sortBy: SortBy;
138
+ subagents: SubagentDisplay;
103
139
  };
104
140
  declare const DEFAULT_VIEW_CONFIG: ViewConfig;
105
141
  type ScopeRoot = {
@@ -132,6 +168,7 @@ declare function projectsOf(rows: readonly SessionRow[]): {
132
168
  declare function sessionLabel(info: SessionInfo): string;
133
169
  declare function projectKey(row: SessionRow): string;
134
170
  declare function projectLabel(row: Pick<SessionRow, 'info'>): string;
171
+ declare function projectName(row: Pick<SessionRow, 'info'>): string;
135
172
  declare function projectSubpath(row: Pick<SessionRow, 'info'>): string | undefined;
136
173
  declare function isJobRun(info: SessionInfo): boolean;
137
174
  declare function inScope(row: SessionRow, scope: WorkspaceScope): boolean;
@@ -152,6 +189,8 @@ declare const TOOL_TITLE_MAX_CHARS = 64;
152
189
  declare const BUILTIN_TOOL_TITLES: Record<string, string>;
153
190
  declare function toolTitle(name: string, titles?: Record<string, string>): string | undefined;
154
191
  declare function sanitizeToolTitle(title: string | undefined, name?: string): string | undefined;
192
+ declare const PEER_SEND_TOOLS: readonly ["peers_send", "mcp__workerdeck__peers_send"];
193
+ declare function isPeerSendTool(name: string): boolean;
155
194
  //#endregion
156
195
  //#region src/usage.d.ts
157
196
  type SessionUsage = {
@@ -443,6 +482,7 @@ type SessionEventBody = {
443
482
  attachments?: MessageAttachment[];
444
483
  patch?: FilePatch;
445
484
  uuid?: string;
485
+ origin?: MessageOrigin;
446
486
  } | {
447
487
  type: 'stream_delta';
448
488
  event: {
@@ -559,6 +599,7 @@ type AttachedFrame = {
559
599
  session: SessionInfo;
560
600
  replayingFrom: number;
561
601
  shell?: boolean;
602
+ pricingOverrides?: PricingOverrides;
562
603
  };
563
604
  type ToolCallRequestFrame = {
564
605
  type: 'tool_call_request';
@@ -744,6 +785,7 @@ type SubagentInfo = {
744
785
  toolUseId: string;
745
786
  agentType?: string;
746
787
  description?: string;
788
+ isAgent?: boolean;
747
789
  status: 'running' | 'done' | 'failed';
748
790
  startedAt: number;
749
791
  toolCount: number;
@@ -767,7 +809,21 @@ type ProjectInfo = {
767
809
  name: string;
768
810
  root: string;
769
811
  icon?: ProjectIcon;
812
+ shortcode?: string;
770
813
  };
814
+ type MessageOrigin = {
815
+ kind: 'peer';
816
+ sessionId: string;
817
+ name?: string;
818
+ engine?: ProfileEngine;
819
+ hostId?: string;
820
+ hops?: string[];
821
+ };
822
+ declare function peerDeliveredPrefix(sessionId: string, name?: string): string;
823
+ declare function peerDeliveredTo(text: string): {
824
+ sessionId: string;
825
+ name?: string;
826
+ } | undefined;
771
827
  type SessionInfo = {
772
828
  id: string;
773
829
  sdkSessionId?: string;
@@ -974,6 +1030,7 @@ type JobUsage = {
974
1030
  tokens: number;
975
1031
  totalCostUsd: number;
976
1032
  numTurns: number;
1033
+ costUsd?: number;
977
1034
  };
978
1035
  type JobResult = {
979
1036
  subtype: string;
@@ -1075,5 +1132,5 @@ type QueueStatsResponse = {
1075
1132
  stats: QueueStats;
1076
1133
  };
1077
1134
  //#endregion
1078
- export { ApiMessage, AttachedFrame, BUILTIN_TOOL_TITLES, ByModel, CHECKLIST_TEXT_MAX, ChecklistItem, ChecklistStatus, ClientFrame, ContentBlock, ContextReading, ContextUsage, ContextUsageCategory, CostBreakdown, CreateJobRequest, CreateJobResponse, CreateProfileRequest, CreateSessionRequest, CreateSessionResponse, DEFAULT_PRICING, DEFAULT_VIEW_CONFIG, ENGINE_CAPABILITIES, EngineCapabilities, ErrorResponse, Facet, FilePatch, FindHostFilesResponse, GetJobResponse, GetProfileResponse, GetSessionResponse, GroupBy, HostDirEntry, HostFileMatch, HostFileRoot, ImageRefPart, JobEvent, JobInfo, JobProgress, JobResult, JobStatus, JobUsage, ListHostDirResponse, ListHostRootsResponse, ListJobsResponse, ListProfilesResponse, ListSdkSessionsResponse, ListSessionFilesResponse, ListSessionsResponse, McpServerActionRequest, McpServerConfigWire, McpServerStatusInfo, McpServerToolInfo, McpServersResponse, MessageAttachment, ModelOption, ModelRate, PRICING_AS_OF, PRICING_NOTE, PRICING_SOURCES, PROTOCOL_VERSION, PatchHunk, PermissionDecisionSource, PermissionMode, PermissionRequest, ProfileConfigSnapshot, ProfileDefaults, ProfileEngine, ProfileInfo, ProfileSessionDefaults, ProfileSpend, ProfileUsage, ProfileUsageWindow, ProjectIcon, ProjectInfo, ProviderConfig, QuestionBehavior, QueueServerFrame, QueueStats, QueueStatsResponse, RateLimitInfo, ReadHostFileResponse, ResolvePermissionRequest, ResolvePermissionResponse, SHELL_COMMAND_MAX, STATE_LABELS, STATE_ORDER, SUBAGENT_HISTORY, SaveProfileResponse, ScopeRoot, SdkSessionSummary, ServerFrame, SessionCapability, SessionCommand, SessionEvent, SessionEventBody, SessionFileInfo, SessionGroup, SessionInfo, SessionNotification, SessionNotificationType, SessionRow, SessionState, SessionStatus, SessionTask, SessionTaskSource, SessionTaskState, SessionUsage, SessionWebhookConfig, SkillInfo, SlashCommandInfo, SortBy, SubagentInfo, SubmitExecutionResultRequest, SubmitExecutionResultResponse, SubscriptionComparison, SubsetSummary, TOOL_RESULT_HEAD_CHARS, TOOL_TITLE_MAX_CHARS, TaskSummary, TextBlock, ThinkingBlock, TokenUsage, ToolCallRequestFrame, ToolExecutionBackend, ToolExecutionOutput, ToolExecutionStatus, ToolResultBlock, ToolUseBlock, UNPRICED_WARN_SHARE, USAGE_STALE_AFTER_MS, UnknownBlock, UpdateProfileRequest, UpdateSessionRequest, UpdateSessionResponse, UploadAttachmentResponse, UsageWindowRow, UserQuestion, UserQuestionOption, ViewConfig, Watermark, WatermarkStore, Watermarks, WebhookConfig, WorkspaceScope, WriteHostFileRequest, WriteHostFileResponse, adaptersOf, addTokenUsage, byModelTotalTokens, canonicalModel, clearFilters, contextReading, costOf, costOfByModel, emptyTokenUsage, filterRows, groupRows, hasFacetFilter, imagePartRef, inScope, isAgentRecord, isJobRun, mergeByModel, mergeUsage, meteredCost, orderUsageWindows, parseTodoWriteInput, parseUserQuestions, projectKey, projectLabel, projectSubpath, projectsOf, rateFor, replayCoalesceKey, replayRetains, runningSubagents, sanitizeToolTitle, scopeActive, sessionLabel, sessionState, sessionTasks, snapshotRetains, subagentLabel, subscriptionComparison, subsetSummary, supportsPermissionMode, taskCountLabel, taskSummary, tokenUsageFromWire, toolTitle, totalTokens, transcriptActivity, transcriptContent, transcriptProse, unpricedModels, unseenCount, usageInfos, usageIsStale, visibleTasks, watermarkKey };
1135
+ export { ApiMessage, AttachedFrame, BUILTIN_TOOL_TITLES, ByModel, CHECKLIST_TEXT_MAX, ChecklistItem, ChecklistStatus, ClientFrame, ContentBlock, ContextReading, ContextUsage, ContextUsageCategory, CostBasis, CostBreakdown, CreateJobRequest, CreateJobResponse, CreateProfileRequest, CreateSessionRequest, CreateSessionResponse, DEFAULT_PRICING, DEFAULT_VIEW_CONFIG, ENGINE_CAPABILITIES, EngineCapabilities, ErrorResponse, Facet, FilePatch, FindHostFilesResponse, GetJobResponse, GetProfileResponse, GetSessionResponse, GroupBy, HostDirEntry, HostFileMatch, HostFileRoot, ImageRefPart, JobEvent, JobInfo, JobProgress, JobResult, JobStatus, JobUsage, ListHostDirResponse, ListHostRootsResponse, ListJobsResponse, ListProfilesResponse, ListSdkSessionsResponse, ListSessionFilesResponse, ListSessionsResponse, McpServerActionRequest, McpServerConfigWire, McpServerStatusInfo, McpServerToolInfo, McpServersResponse, MessageAttachment, MessageOrigin, ModelOption, ModelRate, PEER_MENTION_BODY_MAX, PEER_MENTION_MAX, PEER_MENTION_SCAN_MAX, PEER_MENTION_SIGIL, PEER_SEND_TOOLS, PRICING_AS_OF, PRICING_NOTE, PRICING_SOURCES, PRICING_STALE_DAYS, PROMPT_SENTENCE_TAIL, PROTOCOL_VERSION, PatchHunk, PeerMentionToken, PermissionDecisionSource, PermissionMode, PermissionRequest, PricingMerge, PricingOverrides, PricingTable, ProfileConfigSnapshot, ProfileDefaults, ProfileEngine, ProfileInfo, ProfileSessionDefaults, ProfileSpend, ProfileUsage, ProfileUsageWindow, ProjectIcon, ProjectInfo, ProviderConfig, QuestionBehavior, QueueServerFrame, QueueStats, QueueStatsResponse, RateLimitInfo, ReadHostFileResponse, ResolvePermissionRequest, ResolvePermissionResponse, SHELL_COMMAND_MAX, STATE_LABELS, STATE_ORDER, SUBAGENT_HISTORY, SaveProfileResponse, ScopeRoot, SdkSessionSummary, ServerFrame, SessionCapability, SessionCommand, SessionEvent, SessionEventBody, SessionFileInfo, SessionGroup, SessionInfo, SessionNotification, SessionNotificationType, SessionRow, SessionState, SessionStatus, SessionTask, SessionTaskSource, SessionTaskState, SessionUsage, SessionWebhookConfig, SkillInfo, SlashCommandInfo, SortBy, SubagentDisplay, SubagentInfo, SubmitExecutionResultRequest, SubmitExecutionResultResponse, SubscriptionComparison, SubsetSummary, TOOL_RESULT_HEAD_CHARS, TOOL_TITLE_MAX_CHARS, TaskSummary, TextBlock, ThinkingBlock, TokenUsage, ToolCallRequestFrame, ToolExecutionBackend, ToolExecutionOutput, ToolExecutionStatus, ToolResultBlock, ToolUseBlock, UNPRICED_WARN_SHARE, USAGE_STALE_AFTER_MS, UnknownBlock, UpdateProfileRequest, UpdateSessionRequest, UpdateSessionResponse, UploadAttachmentResponse, UsageWindowRow, UserQuestion, UserQuestionOption, ViewConfig, Watermark, WatermarkStore, Watermarks, WebhookConfig, WorkspaceScope, WriteHostFileRequest, WriteHostFileResponse, activePricing, adaptersOf, addTokenUsage, byModelTotalTokens, canonicalModel, clearFilters, contextReading, costOf, costOfByModel, emptyTokenUsage, filterRows, groupRows, hasFacetFilter, imagePartRef, inScope, isAgentRecord, isJobRun, isPeerMentionBody, isPeerSendTool, mergeByModel, mergePricing, mergeUsage, meteredCost, orderUsageWindows, parseTodoWriteInput, parseUserQuestions, peerDeliveredPrefix, peerDeliveredTo, peerMentionKey, peerMentionSlug, pricingAgeDays, pricingAgeNote, projectKey, projectLabel, projectName, projectSubpath, projectsOf, rateFor, replayCoalesceKey, replayRetains, runningSubagents, sanitizeToolTitle, scanPeerMentions, scopeActive, sessionLabel, sessionState, sessionTasks, setPricingOverrides, snapshotRetains, subagentLabel, subscriptionComparison, subsetSummary, supportsPermissionMode, taskCountLabel, taskSummary, tokenUsageFromWire, toolTitle, totalTokens, transcriptActivity, transcriptContent, transcriptProse, unknownBasisModels, unpricedModels, unseenCount, usageInfos, usageIsStale, visibleSubagents, visibleTasks, watermarkKey, worseBasis };
1079
1136
  //# sourceMappingURL=index.d.mts.map
package/build/index.mjs CHANGED
@@ -21,8 +21,13 @@ function sessionState(info) {
21
21
  function runningSubagents(info) {
22
22
  return (info.subagents ?? []).filter((sub) => sub.status === "running");
23
23
  }
24
+ function visibleSubagents(info, show) {
25
+ if (show === "none") return [];
26
+ const subagents = info.subagents ?? [];
27
+ return show === "all" ? [...subagents] : subagents.filter((sub) => sub.status !== "done");
28
+ }
24
29
  function isAgentRecord(sub) {
25
- return (sub.agentType?.trim() ?? "") !== "";
30
+ return sub.isAgent === true || (sub.agentType?.trim() ?? "") !== "";
26
31
  }
27
32
  function subagentLabel(sub) {
28
33
  const agent = sub.agentType?.trim();
@@ -38,7 +43,8 @@ const DEFAULT_VIEW_CONFIG = {
38
43
  projects: [],
39
44
  scoped: true,
40
45
  groupBy: "state",
41
- sortBy: "recent"
46
+ sortBy: "recent",
47
+ subagents: "active"
42
48
  };
43
49
  function adaptersOf(rows) {
44
50
  return [...new Set(rows.map((r) => r.adapter))].sort();
@@ -58,6 +64,9 @@ function projectKey(row) {
58
64
  return `${row.hostId}:${normalizePath(row.info.project?.root ?? row.info.cwd)}`;
59
65
  }
60
66
  function projectLabel(row) {
67
+ return row.info.project?.shortcode || projectName(row);
68
+ }
69
+ function projectName(row) {
61
70
  const name = row.info.project?.name;
62
71
  if (name) return name;
63
72
  const dir = normalizePath(row.info.cwd);
@@ -77,7 +86,7 @@ function isJobRun(info) {
77
86
  }
78
87
  function matchesSearch(row, needle) {
79
88
  if (!needle) return true;
80
- return sessionLabel(row.info).toLowerCase().includes(needle) || row.info.cwd.toLowerCase().includes(needle) || (row.info.project?.name.toLowerCase().includes(needle) ?? false) || row.hostName.toLowerCase().includes(needle) || row.adapter.toLowerCase().includes(needle) || row.info.id.startsWith(needle);
89
+ return sessionLabel(row.info).toLowerCase().includes(needle) || row.info.cwd.toLowerCase().includes(needle) || (row.info.project?.name.toLowerCase().includes(needle) ?? false) || (row.info.project?.shortcode?.toLowerCase().includes(needle) ?? false) || row.hostName.toLowerCase().includes(needle) || row.adapter.toLowerCase().includes(needle) || row.info.id.startsWith(needle);
81
90
  }
82
91
  function normalizePath(path) {
83
92
  return path.replace(/\\/g, "/").replace(/\/+$/, "");
@@ -158,7 +167,8 @@ function clearFilters(config) {
158
167
  ...DEFAULT_VIEW_CONFIG,
159
168
  scoped: false,
160
169
  groupBy: config.groupBy,
161
- sortBy: config.sortBy
170
+ sortBy: config.sortBy,
171
+ subagents: config.subagents
162
172
  };
163
173
  }
164
174
  //#endregion
@@ -237,7 +247,21 @@ const PRICING_AS_OF = "2026-09-19";
237
247
  const PRICING_SOURCES = "platform.claude.com and developers.openai.com list prices, bundled";
238
248
  const PRICING_NOTE = `List rates as of ${PRICING_AS_OF}. A subscription is a flat fee, so this is what the same tokens would have cost on the pay-as-you-go API, not a bill.`;
239
249
  const UNPRICED_WARN_SHARE = .005;
250
+ const PRICING_STALE_DAYS = 90;
240
251
  const MTOK = 1e6;
252
+ const DAY_MS = 864e5;
253
+ const BASIS_ORDER = {
254
+ list: 0,
255
+ managed: 1,
256
+ unknown: 2
257
+ };
258
+ const RATE_FIELDS = [
259
+ "input",
260
+ "output",
261
+ "cacheWrite5m",
262
+ "cacheWrite1h",
263
+ "cacheRead"
264
+ ];
241
265
  const WEEKS_PER_MONTH = 52 / 12;
242
266
  function anthropicRate(input, output, cacheRead) {
243
267
  return {
@@ -281,11 +305,67 @@ const DEFAULT_PRICING = {
281
305
  "gpt-5.1": openaiRate(1.25, 10, .125),
282
306
  "gpt-5": openaiRate(1.25, 10, .125)
283
307
  };
308
+ let activeTable = DEFAULT_PRICING;
309
+ function rateFromInput(value) {
310
+ if (value === null || typeof value !== "object") return;
311
+ const raw = value;
312
+ const rate = {
313
+ input: 0,
314
+ output: 0,
315
+ cacheWrite5m: 0,
316
+ cacheWrite1h: 0,
317
+ cacheRead: 0
318
+ };
319
+ for (const field of RATE_FIELDS) {
320
+ const rest = raw[field];
321
+ if (typeof rest !== "number" || !Number.isFinite(rest) || rest < 0) return;
322
+ rate[field] = rest;
323
+ }
324
+ return rate;
325
+ }
326
+ function mergePricing(overrides, base = DEFAULT_PRICING) {
327
+ const accepted = {};
328
+ const dropped = [];
329
+ if (overrides !== null && typeof overrides === "object") for (const [model, value] of Object.entries(overrides)) {
330
+ const rate = rateFromInput(value);
331
+ const key = canonicalModel(model);
332
+ if (!rate || key === "") {
333
+ dropped.push(model);
334
+ continue;
335
+ }
336
+ accepted[key] = rate;
337
+ }
338
+ return {
339
+ pricing: {
340
+ ...base,
341
+ ...accepted
342
+ },
343
+ overrides: accepted,
344
+ dropped
345
+ };
346
+ }
347
+ function activePricing() {
348
+ return activeTable;
349
+ }
350
+ function setPricingOverrides(overrides) {
351
+ const merged = mergePricing(overrides);
352
+ activeTable = merged.pricing;
353
+ return merged;
354
+ }
355
+ function pricingAgeDays(now, asOf = PRICING_AS_OF) {
356
+ const dated = Date.parse(asOf);
357
+ return Number.isFinite(dated) ? Math.floor((now - dated) / DAY_MS) : 0;
358
+ }
359
+ function pricingAgeNote(now, asOf = PRICING_AS_OF) {
360
+ const days = pricingAgeDays(now, asOf);
361
+ if (days <= 90) return;
362
+ return `This rate table is ${days} days old, so check the vendor's current list prices before you trust the total.`;
363
+ }
284
364
  function canonicalModel(model) {
285
365
  const slash = model.lastIndexOf("/");
286
366
  return (slash === -1 ? model : model.slice(slash + 1)).toLowerCase().replace(/\[[^\]]*\]$/, "").replace(/^(?:[a-z]+\.)*anthropic\./, "").replace(/[@-]\d{8}$/, "").replace(/-v\d+:\d+$/, "");
287
367
  }
288
- function rateFor(model, pricing = DEFAULT_PRICING) {
368
+ function rateFor(model, pricing = activePricing()) {
289
369
  return model ? pricing[canonicalModel(model)] : void 0;
290
370
  }
291
371
  function emptyTokenUsage() {
@@ -306,9 +386,18 @@ function addTokenUsage(into, add) {
306
386
  output: into.output + add.output,
307
387
  cacheWrite5m: into.cacheWrite5m + add.cacheWrite5m,
308
388
  cacheWrite1h: into.cacheWrite1h + add.cacheWrite1h,
309
- cacheRead: into.cacheRead + add.cacheRead
389
+ cacheRead: into.cacheRead + add.cacheRead,
390
+ costBasis: worseBasis(into.costBasis, add.costBasis)
310
391
  };
311
392
  }
393
+ function worseBasis(a, b) {
394
+ if (a === void 0) return b;
395
+ if (b === void 0) return a;
396
+ return BASIS_ORDER[a] >= BASIS_ORDER[b] ? a : b;
397
+ }
398
+ function unknownBasisModels(byModel) {
399
+ return Object.entries(byModel).filter(([, usage]) => usage.costBasis === "unknown").map(([model]) => canonicalModel(model));
400
+ }
312
401
  function mergeByModel(into, add) {
313
402
  const out = { ...into };
314
403
  for (const [model, usage] of Object.entries(add)) out[model] = addTokenUsage(out[model] ?? emptyTokenUsage(), usage);
@@ -348,7 +437,7 @@ function unpricedBreakdown(tokens) {
348
437
  unpricedShare: tokens > 0 ? 1 : 0
349
438
  };
350
439
  }
351
- function costOf(usage, model, pricing = DEFAULT_PRICING) {
440
+ function costOf(usage, model, pricing = activePricing()) {
352
441
  const rate = rateFor(model, pricing);
353
442
  if (!rate) return unpricedBreakdown(totalTokens(usage));
354
443
  const input = usage.input / MTOK * rate.input;
@@ -366,7 +455,7 @@ function costOf(usage, model, pricing = DEFAULT_PRICING) {
366
455
  unpricedShare: 0
367
456
  };
368
457
  }
369
- function costOfByModel(byModel, pricing = DEFAULT_PRICING) {
458
+ function costOfByModel(byModel, pricing = activePricing()) {
370
459
  const acc = {
371
460
  input: 0,
372
461
  output: 0,
@@ -398,7 +487,7 @@ function costOfByModel(byModel, pricing = DEFAULT_PRICING) {
398
487
  acc.unpricedShare = tokens > 0 ? acc.unpricedTokens / tokens : 0;
399
488
  return acc;
400
489
  }
401
- function unpricedModels(byModel, pricing = DEFAULT_PRICING) {
490
+ function unpricedModels(byModel, pricing = activePricing()) {
402
491
  return Object.keys(byModel).filter((model) => rateFor(model, pricing) === void 0);
403
492
  }
404
493
  function meteredCost(cost) {
@@ -415,6 +504,53 @@ function subscriptionComparison(weeklyUsd, monthlyUsd) {
415
504
  };
416
505
  }
417
506
  //#endregion
507
+ //#region src/peer-mentions.ts
508
+ const PEER_MENTION_SIGIL = "#";
509
+ const PEER_MENTION_MAX = 4;
510
+ const PEER_MENTION_BODY_MAX = 64;
511
+ const PEER_MENTION_SCAN_MAX = 32;
512
+ const PROMPT_SENTENCE_TAIL = /* @__PURE__ */ new Set([
513
+ ".",
514
+ ",",
515
+ ";",
516
+ ":",
517
+ "!",
518
+ "?",
519
+ ")",
520
+ "]",
521
+ "}",
522
+ "\"",
523
+ "'"
524
+ ]);
525
+ const MENTION_BODY = /^[\p{L}\p{N}][\p{L}\p{N}\-_]*$/u;
526
+ function peerMentionSlug(title, id) {
527
+ return (title ?? "").normalize("NFKC").replace(/[^\p{L}\p{N}]+/gu, "-").replace(/^-+|-+$/g, "").slice(0, 64).replace(/^-+|-+$/g, "") || id.slice(0, 8);
528
+ }
529
+ function peerMentionKey(body) {
530
+ return body.normalize("NFKC").toLowerCase().replace(/[_\s]+/g, "-").replace(/-+/g, "-").replace(/^-+|-+$/g, "");
531
+ }
532
+ function isPeerMentionBody(body) {
533
+ return body.length > 0 && body.length <= 64 && MENTION_BODY.test(body);
534
+ }
535
+ function scanPeerMentions(text) {
536
+ const tokens = [];
537
+ const words = /\S+/g;
538
+ let match;
539
+ while ((match = words.exec(text)) !== null && tokens.length < 32) {
540
+ if (match[0][0] !== "#") continue;
541
+ let end = match.index + match[0].length;
542
+ while (end > match.index && PROMPT_SENTENCE_TAIL.has(text[end - 1])) end--;
543
+ const body = text.slice(match.index + 1, end);
544
+ if (!isPeerMentionBody(body)) continue;
545
+ tokens.push({
546
+ start: match.index,
547
+ end,
548
+ body
549
+ });
550
+ }
551
+ return tokens;
552
+ }
553
+ //#endregion
418
554
  //#region src/tool-titles.ts
419
555
  const TOOL_TITLE_MAX_CHARS = 64;
420
556
  const BUILTIN_TOOL_TITLES = {
@@ -430,7 +566,13 @@ const BUILTIN_TOOL_TITLES = {
430
566
  CodexFileChange: "Editing a file",
431
567
  CodexWebSearch: "Searching the web",
432
568
  CodexImageGeneration: "Generating an image",
433
- CodexImageView: "Viewing an image"
569
+ CodexImageView: "Viewing an image",
570
+ peers_list: "Listing peer sessions",
571
+ peers_peek: "Peeking at a peer session",
572
+ peers_send: "Messaging a peer session",
573
+ mcp__workerdeck__peers_list: "Listing peer sessions",
574
+ mcp__workerdeck__peers_peek: "Peeking at a peer session",
575
+ mcp__workerdeck__peers_send: "Messaging a peer session"
434
576
  };
435
577
  function toolTitle(name, titles) {
436
578
  return sanitizeToolTitle(titles?.[name] ?? BUILTIN_TOOL_TITLES[name], name);
@@ -442,6 +584,10 @@ function sanitizeToolTitle(title, name) {
442
584
  const points = [...flat];
443
585
  return points.length > 64 ? points.slice(0, 63).join("") + "…" : flat;
444
586
  }
587
+ const PEER_SEND_TOOLS = ["peers_send", "mcp__workerdeck__peers_send"];
588
+ function isPeerSendTool(name) {
589
+ return PEER_SEND_TOOLS.includes(name);
590
+ }
445
591
  //#endregion
446
592
  //#region src/usage.ts
447
593
  function mergeUsage(session, profile) {
@@ -673,6 +819,18 @@ function supportsPermissionMode(engine, mode) {
673
819
  }
674
820
  const SUBAGENT_HISTORY = 8;
675
821
  const CHECKLIST_TEXT_MAX = 200;
822
+ function peerDeliveredPrefix(sessionId, name) {
823
+ return `Delivered to ${name ? `${name} (${sessionId})` : sessionId}`;
824
+ }
825
+ function peerDeliveredTo(text) {
826
+ const named = /^Delivered to (.+) \(([^()]+)\);/.exec(text);
827
+ if (named) return {
828
+ sessionId: named[2],
829
+ name: named[1]
830
+ };
831
+ const bare = /^Delivered to ([^()\s]+);/.exec(text);
832
+ return bare ? { sessionId: bare[1] } : void 0;
833
+ }
676
834
  function contextReading(body) {
677
835
  if (body.type !== "context_usage") return;
678
836
  const { totalTokens, maxTokens, percentage } = body.usage;
@@ -700,6 +858,7 @@ function transcriptActivity(body) {
700
858
  function transcriptProse(body) {
701
859
  if ("parentToolUseId" in body && body.parentToolUseId != null) return 0;
702
860
  switch (body.type) {
861
+ case "user_message": return body.origin && !body.synthetic ? 1 : 0;
703
862
  case "assistant_message": {
704
863
  const content = body.message.content;
705
864
  if (typeof content === "string") return content.trim() === "" ? 0 : 1;
@@ -749,6 +908,6 @@ function snapshotRetains(body) {
749
908
  return body.type !== "stream_delta";
750
909
  }
751
910
  //#endregion
752
- export { BUILTIN_TOOL_TITLES, CHECKLIST_TEXT_MAX, DEFAULT_PRICING, DEFAULT_VIEW_CONFIG, ENGINE_CAPABILITIES, PRICING_AS_OF, PRICING_NOTE, PRICING_SOURCES, PROTOCOL_VERSION, SHELL_COMMAND_MAX, STATE_LABELS, STATE_ORDER, SUBAGENT_HISTORY, TOOL_RESULT_HEAD_CHARS, TOOL_TITLE_MAX_CHARS, UNPRICED_WARN_SHARE, USAGE_STALE_AFTER_MS, Watermarks, adaptersOf, addTokenUsage, byModelTotalTokens, canonicalModel, clearFilters, contextReading, costOf, costOfByModel, emptyTokenUsage, filterRows, groupRows, hasFacetFilter, imagePartRef, inScope, isAgentRecord, isJobRun, mergeByModel, mergeUsage, meteredCost, orderUsageWindows, parseTodoWriteInput, parseUserQuestions, projectKey, projectLabel, projectSubpath, projectsOf, rateFor, replayCoalesceKey, replayRetains, runningSubagents, sanitizeToolTitle, scopeActive, sessionLabel, sessionState, sessionTasks, snapshotRetains, subagentLabel, subscriptionComparison, subsetSummary, supportsPermissionMode, taskCountLabel, taskSummary, tokenUsageFromWire, toolTitle, totalTokens, transcriptActivity, transcriptContent, transcriptProse, unpricedModels, unseenCount, usageInfos, usageIsStale, visibleTasks, watermarkKey };
911
+ export { BUILTIN_TOOL_TITLES, CHECKLIST_TEXT_MAX, DEFAULT_PRICING, DEFAULT_VIEW_CONFIG, ENGINE_CAPABILITIES, PEER_MENTION_BODY_MAX, PEER_MENTION_MAX, PEER_MENTION_SCAN_MAX, PEER_MENTION_SIGIL, PEER_SEND_TOOLS, PRICING_AS_OF, PRICING_NOTE, PRICING_SOURCES, PRICING_STALE_DAYS, PROMPT_SENTENCE_TAIL, PROTOCOL_VERSION, SHELL_COMMAND_MAX, STATE_LABELS, STATE_ORDER, SUBAGENT_HISTORY, TOOL_RESULT_HEAD_CHARS, TOOL_TITLE_MAX_CHARS, UNPRICED_WARN_SHARE, USAGE_STALE_AFTER_MS, Watermarks, activePricing, adaptersOf, addTokenUsage, byModelTotalTokens, canonicalModel, clearFilters, contextReading, costOf, costOfByModel, emptyTokenUsage, filterRows, groupRows, hasFacetFilter, imagePartRef, inScope, isAgentRecord, isJobRun, isPeerMentionBody, isPeerSendTool, mergeByModel, mergePricing, mergeUsage, meteredCost, orderUsageWindows, parseTodoWriteInput, parseUserQuestions, peerDeliveredPrefix, peerDeliveredTo, peerMentionKey, peerMentionSlug, pricingAgeDays, pricingAgeNote, projectKey, projectLabel, projectName, projectSubpath, projectsOf, rateFor, replayCoalesceKey, replayRetains, runningSubagents, sanitizeToolTitle, scanPeerMentions, scopeActive, sessionLabel, sessionState, sessionTasks, setPricingOverrides, snapshotRetains, subagentLabel, subscriptionComparison, subsetSummary, supportsPermissionMode, taskCountLabel, taskSummary, tokenUsageFromWire, toolTitle, totalTokens, transcriptActivity, transcriptContent, transcriptProse, unknownBasisModels, unpricedModels, unseenCount, usageInfos, usageIsStale, visibleSubagents, visibleTasks, watermarkKey, worseBasis };
753
912
 
754
913
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/session-list.ts","../src/checklist.ts","../src/pricing.ts","../src/tool-titles.ts","../src/usage.ts","../src/watermarks.ts","../src/index.ts"],"sourcesContent":["import type { SessionInfo, SubagentInfo } from './index.ts'\n\nexport type SessionState = 'attention' | 'working' | 'idle' | 'ended'\n\nexport const STATE_ORDER: readonly SessionState[] = ['attention', 'working', 'idle', 'ended']\n\nexport const STATE_LABELS: Record<SessionState, string> = {\n attention: 'Needs attention',\n working: 'Working',\n idle: 'Idle',\n ended: 'Ended',\n}\n\nexport function sessionState(info: SessionInfo): SessionState {\n if (info.pendingPermissionCount > 0 || info.status === 'awaiting_approval') {\n return 'attention'\n }\n if (info.status === 'failed' || info.status === 'closed') {\n return 'ended'\n }\n if (info.status === 'running' || info.status === 'starting') {\n return 'working'\n }\n if (runningSubagents(info).length > 0) {\n return 'working'\n }\n return 'idle'\n}\n\nexport function runningSubagents(info: SessionInfo): SubagentInfo[] {\n return (info.subagents ?? []).filter((sub) => sub.status === 'running')\n}\n\nexport function isAgentRecord(sub: SubagentInfo): boolean {\n return (sub.agentType?.trim() ?? '') !== ''\n}\n\nexport function subagentLabel(sub: SubagentInfo): string {\n const agent = sub.agentType?.trim()\n const description = sub.description?.trim()\n if (agent && description) {\n return `${agent} · ${description}`\n }\n return agent || description || 'Sub-agent'\n}\n\nexport type Facet = 'gateway' | 'adapter' | 'state' | 'project'\nexport type GroupBy = 'none' | Facet\nexport type SortBy = 'recent' | 'name' | Facet\n\nexport type ViewConfig = {\n search: string\n gateways: string[]\n adapters: string[]\n states: SessionState[]\n projects?: string[]\n scoped: boolean\n groupBy: GroupBy\n sortBy: SortBy\n}\n\nexport const DEFAULT_VIEW_CONFIG: ViewConfig = {\n search: '',\n gateways: [],\n adapters: [],\n states: [],\n projects: [],\n scoped: true,\n groupBy: 'state',\n sortBy: 'recent',\n}\n\nexport type ScopeRoot = { hostId?: string; path: string }\n\nexport type WorkspaceScope = { label: string; roots: ScopeRoot[] }\n\nexport type SessionRow = {\n hostId: string\n hostName: string\n local: boolean\n adapter: string\n state: SessionState\n info: SessionInfo\n // Messages this client has not read - `unseenCount` against its watermark, so the\n // unit is prose (`SessionInfo.proseCount`) wherever the gateway reports it. A session\n // that is only running tools contributes 0: the badge answers \"is there something to\n // read\", not \"is anything happening\", which is what `state` is for.\n unseen: number\n}\n\nexport type SessionGroup = { key: string; label?: string; rows: SessionRow[] }\n\nexport function adaptersOf(rows: readonly SessionRow[]): string[] {\n return [...new Set(rows.map((r) => r.adapter))].sort()\n}\n\nexport function projectsOf(rows: readonly SessionRow[]): { key: string; label: string }[] {\n const byKey = new Map<string, string>()\n for (const row of rows) {\n byKey.set(projectKey(row), projectLabel(row))\n }\n return [...byKey].map(([key, label]) => ({ key, label })).sort((a, b) => a.label.toLowerCase().localeCompare(b.label.toLowerCase()))\n}\n\nexport function sessionLabel(info: SessionInfo): string {\n return info.title ?? info.id.slice(0, 8)\n}\n\nexport function projectKey(row: SessionRow): string {\n return `${row.hostId}:${normalizePath(row.info.project?.root ?? row.info.cwd)}`\n}\n\nexport function projectLabel(row: Pick<SessionRow, 'info'>): string {\n const name = row.info.project?.name\n if (name) {\n return name\n }\n const dir = normalizePath(row.info.cwd)\n return dir.slice(dir.lastIndexOf('/') + 1) || 'No project'\n}\n\nexport function projectSubpath(row: Pick<SessionRow, 'info'>): string | undefined {\n const root = row.info.project?.root\n if (root === undefined || !row.info.cwd) {\n return undefined\n }\n const base = normalizePath(root)\n const dir = normalizePath(row.info.cwd)\n if (dir === base) {\n return undefined\n }\n if (!dir.startsWith(`${base}/`)) {\n return undefined\n }\n return dir.slice(base.length + 1) || undefined\n}\n\nexport function isJobRun(info: SessionInfo): boolean {\n return typeof info.meta?.jobId === 'string'\n}\n\nfunction matchesSearch(row: SessionRow, needle: string): boolean {\n if (!needle) {\n return true\n }\n return (\n sessionLabel(row.info).toLowerCase().includes(needle) ||\n row.info.cwd.toLowerCase().includes(needle) ||\n (row.info.project?.name.toLowerCase().includes(needle) ?? false) ||\n row.hostName.toLowerCase().includes(needle) ||\n row.adapter.toLowerCase().includes(needle) ||\n row.info.id.startsWith(needle)\n )\n}\n\nfunction normalizePath(path: string): string {\n return path.replace(/\\\\/g, '/').replace(/\\/+$/, '')\n}\n\nfunction isWithin(root: string, path: string): boolean {\n const base = normalizePath(root)\n const dir = normalizePath(path)\n // The separator matters: /a/project must not swallow /a/project-2.\n return dir === base || dir.startsWith(`${base}/`)\n}\n\nexport function inScope(row: SessionRow, scope: WorkspaceScope): boolean {\n return scope.roots.some(\n (root) => (root.hostId ? root.hostId.toLowerCase() === row.hostId.toLowerCase() : row.local) && isWithin(root.path, row.info.cwd),\n )\n}\n\nexport function scopeActive(config: ViewConfig, scope: WorkspaceScope | undefined): boolean {\n return config.scoped && scope !== undefined\n}\n\nexport function filterRows(rows: readonly SessionRow[], config: ViewConfig, scope?: WorkspaceScope): SessionRow[] {\n const needle = config.search.trim().toLowerCase()\n const scoping = scopeActive(config, scope) ? scope : undefined\n return rows.filter(\n (row) =>\n (config.gateways.length === 0 || config.gateways.includes(row.hostId)) &&\n (config.adapters.length === 0 || config.adapters.includes(row.adapter)) &&\n (config.states.length === 0 || config.states.includes(row.state)) &&\n (!config.projects?.length || config.projects.includes(projectKey(row))) &&\n (!scoping || inScope(row, scoping)) &&\n matchesSearch(row, needle),\n )\n}\n\nfunction facetKey(row: SessionRow, facet: Facet): string {\n return facet === 'gateway' ? row.hostId : facet === 'adapter' ? row.adapter : facet === 'project' ? projectKey(row) : row.state\n}\n\nfunction facetLabel(row: SessionRow, facet: Facet): string {\n return facet === 'gateway'\n ? row.hostName\n : facet === 'adapter'\n ? row.adapter\n : facet === 'project'\n ? projectLabel(row)\n : STATE_LABELS[row.state]\n}\n\nfunction facetRank(row: SessionRow, facet: Facet): string {\n if (facet === 'state') {\n return String(STATE_ORDER.indexOf(row.state))\n }\n return facetLabel(row, facet).toLowerCase()\n}\n\nfunction byRecency(a: SessionRow, b: SessionRow) {\n return (b.info.lastActivityAt ?? b.info.createdAt) - (a.info.lastActivityAt ?? a.info.createdAt)\n}\n\nfunction compare(a: SessionRow, b: SessionRow, sortBy: SortBy): number {\n if (sortBy === 'recent') {\n return byRecency(a, b)\n }\n if (sortBy === 'name') {\n return (\n sessionLabel(a.info).localeCompare(sessionLabel(b.info), undefined, {\n sensitivity: 'base',\n }) || byRecency(a, b)\n )\n }\n return facetRank(a, sortBy).localeCompare(facetRank(b, sortBy)) || byRecency(a, b)\n}\n\nexport function groupRows(rows: readonly SessionRow[], config: ViewConfig): SessionGroup[] {\n const sorted = [...rows].sort((a, b) => compare(a, b, config.sortBy))\n if (config.groupBy === 'none') {\n return sorted.length ? [{ key: 'all', rows: sorted }] : []\n }\n const facet = config.groupBy\n const groups = new Map<string, SessionGroup & { rank: string }>()\n for (const row of sorted) {\n const key = facetKey(row, facet)\n const group = groups.get(key)\n if (group) {\n group.rows.push(row)\n } else {\n groups.set(key, {\n key,\n label: facetLabel(row, facet),\n rank: facetRank(row, facet),\n rows: [row],\n })\n }\n }\n return [...groups.values()].sort((a, b) => a.rank.localeCompare(b.rank))\n}\n\nexport type SubsetSummary = { shown: number; total: number; causes: string[] }\n\nexport function subsetSummary(\n config: ViewConfig,\n scope: WorkspaceScope | undefined,\n shown: number,\n total: number,\n): SubsetSummary | undefined {\n if (shown >= total) {\n return undefined\n }\n const causes: string[] = []\n if (scope && scopeActive(config, scope)) {\n causes.push(scope.label)\n }\n const facets =\n (config.gateways.length ? 1 : 0) + (config.adapters.length ? 1 : 0) + (config.states.length ? 1 : 0) + (config.projects?.length ? 1 : 0)\n if (facets > 0) {\n causes.push(`${facets} filter${facets === 1 ? '' : 's'}`)\n }\n if (config.search.trim()) {\n causes.push('search')\n }\n return { shown, total, causes }\n}\n\nexport function hasFacetFilter(config: ViewConfig): boolean {\n return (\n config.search.trim().length > 0 ||\n config.gateways.length > 0 ||\n config.adapters.length > 0 ||\n config.states.length > 0 ||\n (config.projects?.length ?? 0) > 0\n )\n}\n\nexport function clearFilters(config: ViewConfig): ViewConfig {\n return {\n ...DEFAULT_VIEW_CONFIG,\n scoped: false,\n groupBy: config.groupBy,\n sortBy: config.sortBy,\n }\n}\n","import type { ChecklistItem, ChecklistStatus, SessionInfo } from './index.ts'\nimport { isAgentRecord } from './session-list.ts'\n\nexport type SessionTaskState = 'pending' | 'running' | 'done' | 'failed'\n\nexport type SessionTaskSource = 'checklist' | 'spawn'\n\nexport type SessionTask = {\n key: string\n label: string\n source: SessionTaskSource\n state: SessionTaskState\n detail?: string\n toolUseId?: string\n}\n\nexport type TaskSummary = { total: number; done: number; running: number; failed: number }\n\nfunction checklistEntry(value: unknown): ChecklistItem | undefined {\n if (typeof value !== 'object' || value === null) {\n return undefined\n }\n const raw = value as { content?: unknown; status?: unknown; activeForm?: unknown }\n const status = raw.status\n if (status !== 'pending' && status !== 'in_progress' && status !== 'completed') {\n return undefined\n }\n const content = typeof raw.content === 'string' ? raw.content.trim() : ''\n if (content === '') {\n return undefined\n }\n const active = typeof raw.activeForm === 'string' ? raw.activeForm.trim() : ''\n return { status, text: status === 'in_progress' && active !== '' ? active : content }\n}\n\n// Whole-or-nothing: a malformed entry (streaming, partial input) yields undefined rather than a half-read list.\n// A well-formed empty list is a clear, and answers `[]`.\nexport function parseTodoWriteInput(input: unknown): ChecklistItem[] | undefined {\n const todos = (input as { todos?: unknown } | null)?.todos\n if (!Array.isArray(todos)) {\n return undefined\n }\n const out: ChecklistItem[] = []\n for (const value of todos) {\n const entry = checklistEntry(value)\n if (entry === undefined) {\n return undefined\n }\n out.push(entry)\n }\n return out\n}\n\nfunction checklistState(status: ChecklistStatus): SessionTaskState {\n switch (status) {\n case 'in_progress': {\n return 'running'\n }\n case 'completed': {\n return 'done'\n }\n default: {\n return 'pending'\n }\n }\n}\n\nexport function sessionTasks(info: Pick<SessionInfo, 'checklist' | 'subagents'>): SessionTask[] {\n const checklist = (info.checklist ?? []).map((item, index) => ({\n key: `checklist:${index}`,\n label: item.text,\n source: 'checklist' as const,\n state: checklistState(item.status),\n }))\n const spawns = (info.subagents ?? [])\n .filter((sub) => !isAgentRecord(sub))\n .map((sub) => ({\n key: `spawn:${sub.toolUseId}`,\n label: sub.description?.trim() || 'Task',\n source: 'spawn' as const,\n state: sub.status,\n detail: sub.toolCount > 0 ? String(sub.toolCount) : undefined,\n toolUseId: sub.toolUseId,\n }))\n return [...checklist, ...spawns]\n}\n\nexport function taskSummary(tasks: readonly SessionTask[]): TaskSummary {\n let done = 0\n let running = 0\n let failed = 0\n for (const task of tasks) {\n if (task.state === 'done') {\n done += 1\n } else if (task.state === 'running') {\n running += 1\n } else if (task.state === 'failed') {\n failed += 1\n }\n }\n return { total: tasks.length, done, running, failed }\n}\n\nexport function taskCountLabel(summary: TaskSummary): string | undefined {\n return summary.total === 0 ? undefined : `${summary.done}/${summary.total}`\n}\n\nexport function visibleTasks(tasks: readonly SessionTask[], showCompleted: boolean): SessionTask[] {\n return showCompleted ? [...tasks] : tasks.filter((task) => task.state !== 'done')\n}\n","export type TokenUsage = {\n input: number\n output: number\n cacheWrite5m: number\n cacheWrite1h: number\n cacheRead: number\n}\n\nexport type ByModel = Record<string, TokenUsage>\n\nexport type ModelRate = {\n input: number\n output: number\n cacheWrite5m: number\n cacheWrite1h: number\n cacheRead: number\n}\n\nexport type CostBreakdown = {\n input: number\n output: number\n cacheWrite: number\n cacheRead: number\n total: number\n unpriced: boolean\n unpricedTokens: number\n unpricedShare: number\n}\n\nexport const PRICING_AS_OF = '2026-09-19'\n\nexport const PRICING_SOURCES = 'platform.claude.com and developers.openai.com list prices, bundled'\n\nexport const PRICING_NOTE = `List rates as of ${PRICING_AS_OF}. A subscription is a flat fee, so this is what the same tokens would have cost on the pay-as-you-go API, not a bill.`\n\nexport const UNPRICED_WARN_SHARE = 0.005\n\nconst MTOK = 1_000_000\n\nconst WEEKS_PER_MONTH = 52 / 12\n\nfunction anthropicRate(input: number, output: number, cacheRead?: number): ModelRate {\n return { input, output, cacheWrite5m: input * 1.25, cacheWrite1h: input * 2, cacheRead: cacheRead ?? input * 0.1 }\n}\n\nfunction openaiRate(input: number, output: number, cacheRead: number): ModelRate {\n return { input, output, cacheWrite5m: input, cacheWrite1h: input, cacheRead }\n}\n\nexport const DEFAULT_PRICING: Record<string, ModelRate> = {\n 'claude-fable-5-1': anthropicRate(10, 50, 0.25),\n 'claude-fable-5': anthropicRate(10, 50),\n 'claude-mythos-5-1': anthropicRate(10, 50, 0.25),\n 'claude-mythos-5': anthropicRate(10, 50),\n 'claude-opus-5': anthropicRate(5, 25),\n 'claude-opus-4-8': anthropicRate(5, 25),\n 'claude-opus-4-7': anthropicRate(5, 25),\n 'claude-opus-4-6': anthropicRate(5, 25),\n 'claude-opus-4-5': anthropicRate(5, 25),\n 'claude-sonnet-5': anthropicRate(2, 10),\n 'claude-sonnet-4-6': anthropicRate(3, 15),\n 'claude-sonnet-4-5': anthropicRate(3, 15),\n 'claude-haiku-4-5': anthropicRate(1, 5),\n 'gpt-6-astra': openaiRate(10, 50, 1),\n 'gpt-5.6-sol': openaiRate(4, 20, 0.4),\n 'gpt-5.6-terra': openaiRate(2, 12, 0.2),\n 'gpt-5.6-luna': openaiRate(0.2, 1.2, 0.02),\n 'gpt-5.5': openaiRate(5, 30, 0.5),\n 'gpt-5.4': openaiRate(2.5, 15, 0.25),\n 'gpt-5.2': openaiRate(1.75, 14, 0.175),\n 'gpt-5.1': openaiRate(1.25, 10, 0.125),\n 'gpt-5': openaiRate(1.25, 10, 0.125),\n}\n\nexport function canonicalModel(model: string): string {\n const slash = model.lastIndexOf('/')\n const withoutProvider = slash === -1 ? model : model.slice(slash + 1)\n return withoutProvider\n .toLowerCase()\n .replace(/\\[[^\\]]*\\]$/, '')\n .replace(/^(?:[a-z]+\\.)*anthropic\\./, '')\n .replace(/[@-]\\d{8}$/, '')\n .replace(/-v\\d+:\\d+$/, '')\n}\n\nexport function rateFor(model: string | undefined, pricing: Record<string, ModelRate> = DEFAULT_PRICING): ModelRate | undefined {\n return model ? pricing[canonicalModel(model)] : undefined\n}\n\nexport function emptyTokenUsage(): TokenUsage {\n return { input: 0, output: 0, cacheWrite5m: 0, cacheWrite1h: 0, cacheRead: 0 }\n}\n\nexport function totalTokens(usage: TokenUsage): number {\n return usage.input + usage.output + usage.cacheWrite5m + usage.cacheWrite1h + usage.cacheRead\n}\n\nexport function addTokenUsage(into: TokenUsage, add: TokenUsage): TokenUsage {\n return {\n input: into.input + add.input,\n output: into.output + add.output,\n cacheWrite5m: into.cacheWrite5m + add.cacheWrite5m,\n cacheWrite1h: into.cacheWrite1h + add.cacheWrite1h,\n cacheRead: into.cacheRead + add.cacheRead,\n }\n}\n\nexport function mergeByModel(into: ByModel, add: ByModel): ByModel {\n const out: ByModel = { ...into }\n for (const [model, usage] of Object.entries(add)) {\n out[model] = addTokenUsage(out[model] ?? emptyTokenUsage(), usage)\n }\n return out\n}\n\nexport function byModelTotalTokens(byModel: ByModel): number {\n let total = 0\n for (const usage of Object.values(byModel)) {\n total += totalTokens(usage)\n }\n return total\n}\n\nfunction num(value: unknown): number {\n return typeof value === 'number' && Number.isFinite(value) && value > 0 ? value : 0\n}\n\nexport function tokenUsageFromWire(usage: unknown): TokenUsage {\n if (usage === null || typeof usage !== 'object') {\n return emptyTokenUsage()\n }\n const wire = usage as {\n input_tokens?: unknown\n output_tokens?: unknown\n cache_creation_input_tokens?: unknown\n cache_read_input_tokens?: unknown\n cache_creation?: { ephemeral_5m_input_tokens?: unknown; ephemeral_1h_input_tokens?: unknown } | null\n }\n const split = wire.cache_creation\n const write1h = num(split?.ephemeral_1h_input_tokens)\n const write5m = split ? num(split.ephemeral_5m_input_tokens) : num(wire.cache_creation_input_tokens)\n return {\n input: num(wire.input_tokens),\n output: num(wire.output_tokens),\n cacheWrite5m: write5m,\n cacheWrite1h: write1h,\n cacheRead: num(wire.cache_read_input_tokens),\n }\n}\n\nfunction unpricedBreakdown(tokens: number): CostBreakdown {\n return {\n input: 0,\n output: 0,\n cacheWrite: 0,\n cacheRead: 0,\n total: 0,\n unpriced: true,\n unpricedTokens: tokens,\n unpricedShare: tokens > 0 ? 1 : 0,\n }\n}\n\nexport function costOf(usage: TokenUsage, model: string | undefined, pricing: Record<string, ModelRate> = DEFAULT_PRICING): CostBreakdown {\n const rate = rateFor(model, pricing)\n if (!rate) {\n return unpricedBreakdown(totalTokens(usage))\n }\n const input = (usage.input / MTOK) * rate.input\n const output = (usage.output / MTOK) * rate.output\n const cacheWrite = (usage.cacheWrite5m / MTOK) * rate.cacheWrite5m + (usage.cacheWrite1h / MTOK) * rate.cacheWrite1h\n const cacheRead = (usage.cacheRead / MTOK) * rate.cacheRead\n return {\n input,\n output,\n cacheWrite,\n cacheRead,\n total: input + output + cacheWrite + cacheRead,\n unpriced: false,\n unpricedTokens: 0,\n unpricedShare: 0,\n }\n}\n\nexport function costOfByModel(byModel: ByModel, pricing: Record<string, ModelRate> = DEFAULT_PRICING): CostBreakdown {\n const acc: CostBreakdown = {\n input: 0,\n output: 0,\n cacheWrite: 0,\n cacheRead: 0,\n total: 0,\n unpriced: false,\n unpricedTokens: 0,\n unpricedShare: 0,\n }\n const models = Object.entries(byModel)\n let anyPriced = false\n let tokens = 0\n for (const [model, usage] of models) {\n tokens += totalTokens(usage)\n const cost = costOf(usage, model, pricing)\n if (cost.unpriced) {\n acc.unpricedTokens += cost.unpricedTokens\n continue\n }\n anyPriced = true\n acc.input += cost.input\n acc.output += cost.output\n acc.cacheWrite += cost.cacheWrite\n acc.cacheRead += cost.cacheRead\n acc.total += cost.total\n }\n acc.unpriced = !anyPriced && models.length > 0\n acc.unpricedShare = tokens > 0 ? acc.unpricedTokens / tokens : 0\n return acc\n}\n\nexport function unpricedModels(byModel: ByModel, pricing: Record<string, ModelRate> = DEFAULT_PRICING): string[] {\n return Object.keys(byModel).filter((model) => rateFor(model, pricing) === undefined)\n}\n\n// Rate limits meter fresh input, output and cache writes; a cache read is nearly free to serve and does not\n// count against a plan window, which is why quota burn and API-equivalent cost diverge on an agentic workload.\nexport function meteredCost(cost: CostBreakdown): number {\n return cost.input + cost.output + cost.cacheWrite\n}\n\nexport type SubscriptionComparison = {\n weeklyUsd: number\n monthlyUsd: number\n weeklyShareUsd: number\n ratio: number\n}\n\nexport function subscriptionComparison(weeklyUsd: number, monthlyUsd: number): SubscriptionComparison | undefined {\n if (!(monthlyUsd > 0) || !Number.isFinite(weeklyUsd) || weeklyUsd < 0) {\n return undefined\n }\n const weeklyShareUsd = monthlyUsd / WEEKS_PER_MONTH\n return { weeklyUsd, monthlyUsd, weeklyShareUsd, ratio: weeklyUsd / weeklyShareUsd }\n}\n\nexport type ProfileSpend = {\n weekUsd: number\n monthUsd: number\n weekByModel: ByModel\n unpricedShare: number\n monthlySubscriptionUsd?: number\n subscription?: SubscriptionComparison\n}\n","export const TOOL_TITLE_MAX_CHARS = 64\n\n// Capability tools the sandbox grants and the synthetic names the codex adapter invents: wire\n// names with no public vocabulary behind them. An engine's own tool names (`Bash`, `Read`,\n// `Task`) are deliberately absent - those are the CLI's published names and users read them.\nexport const BUILTIN_TOOL_TITLES: Record<string, string> = {\n fs_read: 'Reading a file',\n fs_write: 'Writing a file',\n fs_list: 'Listing files',\n eval_script: 'Running a script',\n web_fetch: 'Fetching a web page',\n web_search: 'Searching the web',\n deliver_file: 'Delivering a file',\n download: 'Downloading a file',\n CodexCommand: 'Running a command',\n CodexFileChange: 'Editing a file',\n CodexWebSearch: 'Searching the web',\n CodexImageGeneration: 'Generating an image',\n CodexImageView: 'Viewing an image',\n}\n\nexport function toolTitle(name: string, titles?: Record<string, string>): string | undefined {\n return sanitizeToolTitle(titles?.[name] ?? BUILTIN_TOOL_TITLES[name], name)\n}\n\n// Titles reach here from remote MCP servers, so they are untrusted display text: one line,\n// clamped, and never a restatement of the wire name the caller already has.\nexport function sanitizeToolTitle(title: string | undefined, name?: string): string | undefined {\n if (typeof title !== 'string') {\n return undefined\n }\n const flat = [...title]\n .map((char) => (char < ' ' || char === '\\u007f' ? ' ' : char))\n .join('')\n .replace(/\\s+/g, ' ')\n .trim()\n if (flat === '' || flat === name) {\n return undefined\n }\n // By code point, not code unit: a clamp that splits a surrogate pair renders a replacement\n // character, and the clients that mirror this rule do not count in UTF-16.\n const points = [...flat]\n return points.length > TOOL_TITLE_MAX_CHARS ? points.slice(0, TOOL_TITLE_MAX_CHARS - 1).join('') + '…' : flat\n}\n","import type { ProfileUsage, RateLimitInfo } from './index.ts'\n\nexport type SessionUsage = {\n rateLimits?: Record<string, RateLimitInfo>\n updatedAt?: number\n}\n\nexport function mergeUsage(session: SessionUsage, profile: ProfileUsage | undefined): ProfileUsage {\n const out: ProfileUsage = {}\n for (const [key, info] of Object.entries(session.rateLimits ?? {})) {\n out[key] = { info, updatedAt: session.updatedAt ?? 0 }\n }\n for (const [key, window] of Object.entries(profile ?? {})) {\n out[key] = window\n }\n return out\n}\n\n// A rate-limit reading is a poll, not a stream: the engine reports one at a turn boundary, on an attach and on a\n// profiles read, and nothing in between. A window older than this is still the best answer anyone has, and it is\n// no longer a claim about right now, so every surface marks it rather than drawing it as current. Minutes, not\n// hours: the windows move over hours, so a reading from this morning can be wrong by a lot.\nexport const USAGE_STALE_AFTER_MS = 15 * 60_000\n\nexport function usageIsStale(row: Pick<UsageWindowRow, 'updatedAt' | 'inferredReset'>, now: number): boolean {\n // An inferred reset is not stale, it is derived at serve time from the wall clock, and it says so in its own words.\n if (row.inferredReset || row.updatedAt === undefined) {\n return false\n }\n return now - row.updatedAt > USAGE_STALE_AFTER_MS\n}\n\nexport type UsageWindowRow = {\n key: string\n info: RateLimitInfo\n updatedAt?: number\n inferredReset?: boolean\n}\n\nexport function orderUsageWindows(usage: ProfileUsage | undefined): UsageWindowRow[] {\n const all = Object.entries(usage ?? {})\n .filter(([, w]) => w.info.utilization !== undefined)\n .map(([key, w]) => ({ key, info: w.info, updatedAt: w.updatedAt, inferredReset: w.inferredReset }))\n const named = ['five_hour', 'seven_day'].flatMap((key) => all.filter((w) => w.key === key))\n const perModel = all.filter((w) => w.key.startsWith('seven_day_')).sort((a, b) => a.key.localeCompare(b.key))\n return [...named, ...perModel]\n}\n\nexport function usageInfos(usage: ProfileUsage | undefined): Record<string, RateLimitInfo> | undefined {\n if (!usage) {\n return undefined\n }\n const out: Record<string, RateLimitInfo> = {}\n for (const [key, window] of Object.entries(usage)) {\n out[key] = window.info\n }\n return out\n}\n","export type Watermark = {\n itemCount: number\n activity: number\n // Prose rows read (`SessionInfo.proseCount`). Optional because a mark stored before\n // prose counting existed cannot say - see `unseenCount`, which reads that absence as\n // \"caught up\" rather than badging a whole history the operator has already seen.\n prose?: number\n turns: number\n seenAt: number\n}\n\nexport type WatermarkStore = {\n read(): Record<string, Watermark> | undefined\n write(marks: Record<string, Watermark>): void\n}\n\nconst MAX_AGE_MS = 30 * 24 * 60 * 60 * 1000\n\nconst TOUCH_MS = 60_000\n\nexport function watermarkKey(hostId: string, sessionId: string) {\n return `${hostId}:${sessionId}`\n}\n\nexport class Watermarks {\n readonly #store: WatermarkStore\n #cache: Record<string, Watermark>\n\n constructor(store: WatermarkStore) {\n this.#store = store\n this.#cache = { ...store.read() }\n }\n\n get(hostId: string, sessionId: string): Watermark | undefined {\n return this.#cache[watermarkKey(hostId, sessionId)]\n }\n\n all(): Readonly<Record<string, Watermark>> {\n return this.#cache\n }\n\n mark(\n hostId: string,\n sessionId: string,\n seen: { itemCount?: number; activity?: number; prose?: number; turns?: number },\n now = Date.now(),\n ): boolean {\n const id = watermarkKey(hostId, sessionId)\n const previous = this.#cache[id]\n const next: Watermark = {\n itemCount: Math.max(previous?.itemCount ?? 0, seen.itemCount ?? 0),\n activity: Math.max(previous?.activity ?? 0, seen.activity ?? 0),\n // A caller with nothing to say about prose (an older gateway reports no `proseCount`)\n // must not overwrite a real mark with 0, which would re-badge everything already read.\n prose: seen.prose === undefined ? previous?.prose : Math.max(previous?.prose ?? 0, seen.prose),\n turns: Math.max(previous?.turns ?? 0, seen.turns ?? 0),\n seenAt: now,\n }\n if (\n previous &&\n previous.itemCount === next.itemCount &&\n previous.activity === next.activity &&\n previous.prose === next.prose &&\n previous.turns === next.turns &&\n next.seenAt - previous.seenAt < TOUCH_MS\n ) {\n return false\n }\n this.#cache[id] = next\n this.#store.write(this.#prune(now))\n return true\n }\n\n forget(hostId: string, sessionId: string): void {\n const id = watermarkKey(hostId, sessionId)\n if (!(id in this.#cache)) {\n return\n }\n delete this.#cache[id]\n this.#store.write(this.#cache)\n }\n\n #prune(now: number): Record<string, Watermark> {\n const cutoff = now - MAX_AGE_MS\n for (const [id, mark] of Object.entries(this.#cache)) {\n if (mark.seenAt < cutoff) {\n delete this.#cache[id]\n }\n }\n return this.#cache\n }\n}\n\n// The badge's number, in the best unit the pair can agree on: prose the human has not\n// read, else rows, else turns. The ladder is what keeps an older gateway (no `proseCount`\n// on the wire) badging exactly as it did before rather than going silent.\nexport function unseenCount(mark: Watermark | undefined, info: { proseCount?: number; activityCount?: number; turns?: number }): number {\n if (!mark) {\n return 0\n }\n if (info.proseCount !== undefined) {\n // `mark.prose` absent = a mark written before prose counting. Reading it as\n // \"caught up\" costs one missed badge on a session already visited; reading it as 0\n // would badge every such session with its entire history the first time it polls.\n return Math.max(0, info.proseCount - (mark.prose ?? info.proseCount))\n }\n if (info.activityCount !== undefined) {\n return Math.max(0, info.activityCount - mark.activity)\n }\n return Math.max(0, (info.turns ?? 0) - mark.turns)\n}\n","import type { ByModel, ProfileSpend } from './pricing.ts'\n\nexport const PROTOCOL_VERSION = 1\n\nexport type SessionStatus = 'starting' | 'running' | 'awaiting_approval' | 'idle' | 'parked' | 'failed' | 'closed'\n\nexport type PermissionMode = 'default' | 'acceptEdits' | 'bypassPermissions' | 'plan' | 'dontAsk' | 'auto'\n\nexport type TextBlock = { type: 'text'; text: string }\nexport type ThinkingBlock = { type: 'thinking'; thinking: string }\nexport type ToolUseBlock = { type: 'tool_use'; id: string; name: string; input: unknown }\nexport type ToolResultBlock = {\n type: 'tool_result'\n tool_use_id: string\n content?: string | Array<{ type: string; text?: string; [key: string]: unknown }>\n is_error?: boolean\n truncated?: boolean\n total_chars?: number\n}\n\nexport const TOOL_RESULT_HEAD_CHARS = 8_000\n\nexport type ImageRefPart = {\n type: 'image_ref'\n media_type: string\n bytes: number\n part_index: number\n}\n\nfunction base64Bytes(data: string): number {\n const padding = data.endsWith('==') ? 2 : data.endsWith('=') ? 1 : 0\n return Math.max(0, Math.floor((data.length * 3) / 4) - padding)\n}\n\nexport function imagePartRef(part: { type?: string; [key: string]: unknown }, index: number): ImageRefPart | undefined {\n if (part.type !== 'image') {\n return undefined\n }\n const source = part.source as { type?: string; data?: unknown; media_type?: unknown } | undefined\n if (!source || source.type !== 'base64' || typeof source.data !== 'string') {\n return undefined\n }\n return {\n type: 'image_ref',\n media_type: typeof source.media_type === 'string' ? source.media_type : 'application/octet-stream',\n bytes: base64Bytes(source.data),\n part_index: index,\n }\n}\n\nexport type UnknownBlock = { type: string; [key: string]: unknown }\n\nexport type PatchHunk = {\n oldStart: number\n oldLines: number\n newStart: number\n newLines: number\n lines: string[]\n}\n\nexport type FilePatch = {\n path?: string\n kind?: 'create' | 'update'\n hunks: PatchHunk[]\n truncated?: boolean\n}\n\nexport type ContentBlock = TextBlock | ThinkingBlock | ToolUseBlock | ToolResultBlock | UnknownBlock\n\nexport type MessageAttachment = {\n id: string\n name: string\n mediaType: string\n bytes: number\n}\n\nexport type ApiMessage = {\n role: 'user' | 'assistant'\n content: string | ContentBlock[]\n model?: string\n stop_reason?: string | null\n usage?: {\n input_tokens?: number\n output_tokens?: number\n cache_creation_input_tokens?: number\n cache_read_input_tokens?: number\n }\n}\n\nexport type PermissionRequest = {\n id: string\n toolName: string\n input: Record<string, unknown>\n toolUseId: string\n title?: string\n displayName?: string\n description?: string\n decisionReason?: string\n agentId?: string\n expiresAt?: number\n}\n\nexport type PermissionDecisionSource = 'client' | 'timeout' | 'policy'\n\nexport type UserQuestionOption = {\n label: string\n description?: string\n preview?: string\n}\n\nexport type UserQuestion = {\n question: string\n header: string\n options: UserQuestionOption[]\n multiSelect?: boolean\n}\n\nexport type QuestionBehavior = 'ask' | 'auto' | 'deny'\n\nexport function parseUserQuestions(input: Record<string, unknown>): UserQuestion[] {\n const raw = Array.isArray(input.questions) ? input.questions : []\n return raw.flatMap((entry): UserQuestion[] => {\n const q = entry as Partial<UserQuestion>\n if (typeof q.question !== 'string' || !Array.isArray(q.options)) {\n return []\n }\n const options = q.options.filter((o): o is UserQuestionOption => typeof (o as UserQuestionOption | undefined)?.label === 'string')\n if (options.length === 0) {\n return []\n }\n return [\n {\n question: q.question,\n header: typeof q.header === 'string' ? q.header : '',\n options,\n multiSelect: q.multiSelect === true,\n },\n ]\n })\n}\n\nexport type ModelOption = {\n value: string\n resolvedModel?: string\n displayName: string\n description?: string\n primary?: boolean\n reasoningEfforts?: readonly string[]\n}\n\nexport type SkillInfo = {\n name: string\n description?: string\n shortDescription?: string\n displayName?: string\n defaultPrompt?: string\n scope?: string\n enabled: boolean\n}\n\nexport type SlashCommandInfo = {\n name: string\n description?: string\n argumentHint?: string\n aliases?: string[]\n}\n\nexport type ContextUsageCategory = {\n name: string\n tokens: number\n color: string\n}\n\nexport type ContextUsage = {\n categories: ContextUsageCategory[]\n totalTokens: number\n maxTokens: number\n percentage: number\n model?: string\n}\n\nexport type ContextReading = {\n totalTokens: number\n maxTokens: number\n percentage: number\n}\n\nexport type RateLimitInfo = {\n status: string\n rateLimitType?: string\n utilization?: number\n resetsAt?: number\n isUsingOverage?: boolean\n}\n\nexport type ToolExecutionStatus = 'pending' | 'deferred' | 'settled' | 'failed'\n\nexport type ToolExecutionBackend = 'server' | 'browser' | 'managed' | 'remote'\n\nexport type ToolExecutionOutput = { type: 'text'; value: string } | { type: 'json'; value: unknown }\n\nexport type SessionEventBody =\n | {\n type: 'system_init'\n sdkSessionId: string\n model: string\n cwd: string\n apiKeySource: string\n tools: string[]\n skills: string[]\n slashCommands: string[]\n permissionMode: PermissionMode\n claudeCodeVersion: string\n mcpServers: Array<{ name: string; status: string }>\n }\n | { type: 'status_changed'; status: SessionStatus; detail?: string }\n | {\n type: 'capabilities'\n models: ModelOption[]\n commands: SlashCommandInfo[]\n defaultModel?: string\n }\n | { type: 'skills'; skills: SkillInfo[] }\n | { type: 'tool_titles'; titles: Record<string, string> }\n | { type: 'checklist'; items: ChecklistItem[] }\n | {\n type: 'file_produced'\n fileId: string\n path: string\n mediaType?: string\n bytes?: number\n toolUseId?: string\n }\n | { type: 'model_changed'; model?: string }\n | { type: 'permission_mode_changed'; mode: PermissionMode }\n | { type: 'context_usage'; usage: ContextUsage }\n | { type: 'rate_limit'; info: RateLimitInfo }\n | { type: 'plan_info'; subscriptionType: string }\n | {\n type: 'conversation_reset'\n sdkSessionId?: string\n }\n | {\n type: 'context_compacted'\n uuid: string\n parentToolUseId?: string | null\n // The same `uuid` is emitted twice: once with `pending` when the engine starts summarising,\n // once without it when the boundary lands, so one row settles in place. A reader that\n // never sees the first (an older gateway, a replay coalesced to the last) draws the\n // boundary alone, which is what it drew before.\n pending?: boolean\n trigger?: 'manual' | 'auto'\n preTokens?: number\n postTokens?: number\n error?: string\n }\n | {\n type: 'assistant_message'\n message: ApiMessage\n parentToolUseId: string | null\n replay?: boolean\n uuid: string\n }\n | {\n type: 'user_message'\n message: ApiMessage\n parentToolUseId: string | null\n replay?: boolean\n synthetic?: boolean\n attachments?: MessageAttachment[]\n patch?: FilePatch\n uuid?: string\n }\n | {\n type: 'stream_delta'\n event: { type: string; [key: string]: unknown }\n parentToolUseId: string | null\n uuid: string\n }\n | {\n type: 'turn_result'\n subtype: 'success' | 'error_during_execution' | 'error_max_turns' | 'error_max_budget_usd' | 'error_max_structured_output_retries'\n isError: boolean\n durationMs: number\n numTurns: number\n totalCostUsd: number\n result?: string\n errors?: string[]\n usage?: unknown\n usageByModel?: ByModel\n costUsd?: number\n }\n | { type: 'permission_requested'; request: PermissionRequest }\n | {\n type: 'permission_resolved'\n requestId: string\n behavior: 'allow' | 'deny'\n resolvedBy: PermissionDecisionSource\n message?: string\n }\n | {\n type: 'execution_dispatched'\n executionId: string\n toolName: string\n backend: ToolExecutionBackend\n deferred?: boolean\n expiresAt?: number\n }\n | {\n type: 'execution_result'\n executionId: string\n output: ToolExecutionOutput\n logs?: string[]\n durationMs?: number\n }\n | {\n type: 'execution_failed'\n executionId: string\n reason: string\n error: string\n logs?: string[]\n durationMs?: number\n }\n | { type: 'file_delivered'; path: string; bytes: number; description?: string }\n | { type: 'sdk_event'; payload: { type: string; [key: string]: unknown } }\n | { type: 'session_error'; message: string }\n | { type: 'session_closed'; reason: 'client' | 'server' | 'error' }\n\nexport type SessionEvent = SessionEventBody & {\n seq: number\n ts: number\n}\n\nexport type SessionCommand =\n | {\n type: 'user_message'\n text: string\n attachmentIds?: string[]\n }\n | {\n type: 'permission_decision'\n requestId: string\n behavior: 'allow' | 'deny'\n updatedInput?: Record<string, unknown>\n message?: string\n interrupt?: boolean\n }\n | { type: 'interrupt' }\n | { type: 'clear_context' }\n | { type: 'set_permission_mode'; mode: PermissionMode }\n | { type: 'set_model'; model?: string }\n | {\n type: 'tool_call_result'\n executionId: string\n output: ToolExecutionOutput\n logs?: string[]\n }\n | {\n type: 'tool_call_error'\n executionId: string\n reason: string\n error: string\n logs?: string[]\n }\n | { type: 'shell_command'; command: string }\n | { type: 'close' }\n\nexport const SHELL_COMMAND_MAX = 4000\n\nexport type AttachedFrame = {\n type: 'attached'\n protocolVersion: number\n session: SessionInfo\n replayingFrom: number\n // Whether this principal may run `!` commands on this session: server config x operator x hostCwd.\n // Additive, so no PROTOCOL_VERSION bump; an older gateway omits it and the client never offers the mode.\n shell?: boolean\n}\n\nexport type ToolCallRequestFrame = {\n type: 'tool_call_request'\n executionId: string\n toolName: string\n input: unknown\n vfsSeed?: Record<string, string>\n limits?: { timeoutMs?: number; memoryLimitBytes?: number }\n expiresAt?: number\n}\n\nexport type ServerFrame =\n | AttachedFrame\n | { type: 'event'; event: SessionEvent }\n | ToolCallRequestFrame\n | { type: 'tool_call_canceled'; executionId: string; reason: string }\n | { type: 'protocol_error'; message: string }\n\nexport type ClientFrame = SessionCommand\n\nexport type ProfileDefaults = {\n model?: string\n permissionMode?: PermissionMode\n}\n\nexport type ProfileEngine = 'claude' | 'codex' | 'provider'\n\nexport type EngineCapabilities = {\n interactiveApprovals: boolean\n permissionModes: readonly PermissionMode[]\n defaultPermissionMode: PermissionMode\n resume: boolean\n resumeBackfill: boolean\n listSessions: boolean\n contextUsage: boolean\n rateLimits: boolean\n mcpStatus: boolean\n mcpServerActions: boolean\n sessionMcpServers: boolean\n slashCommands: boolean\n clearContext?: boolean\n skillsList: boolean\n settingSources: boolean\n budgets: boolean\n attachments: ReadonlyArray<'image' | 'pdf' | 'text'>\n reasoningEfforts?: readonly string[]\n vfs: boolean\n hostCwd?: boolean\n streaming: 'token' | 'item' | 'none'\n}\n\nexport const ENGINE_CAPABILITIES: Record<ProfileEngine, EngineCapabilities> = {\n claude: {\n interactiveApprovals: true,\n permissionModes: ['default', 'acceptEdits', 'bypassPermissions', 'plan', 'dontAsk', 'auto'],\n defaultPermissionMode: 'default',\n resume: true,\n resumeBackfill: true,\n listSessions: true,\n contextUsage: true,\n rateLimits: true,\n mcpStatus: true,\n mcpServerActions: true,\n sessionMcpServers: true,\n slashCommands: true,\n clearContext: true,\n skillsList: false,\n settingSources: true,\n budgets: true,\n attachments: ['image', 'pdf', 'text'],\n reasoningEfforts: ['low', 'medium', 'high', 'xhigh', 'max'],\n vfs: false,\n hostCwd: true,\n streaming: 'token',\n },\n codex: {\n interactiveApprovals: true,\n permissionModes: ['default', 'acceptEdits', 'bypassPermissions', 'auto'],\n defaultPermissionMode: 'default',\n resume: true,\n resumeBackfill: true,\n listSessions: true,\n contextUsage: true,\n rateLimits: true,\n mcpStatus: true,\n mcpServerActions: false,\n sessionMcpServers: false,\n slashCommands: false,\n clearContext: true,\n skillsList: true,\n settingSources: false,\n budgets: false,\n attachments: ['image', 'text'],\n reasoningEfforts: ['minimal', 'low', 'medium', 'high', 'xhigh'],\n vfs: false,\n hostCwd: true,\n streaming: 'token',\n },\n provider: {\n interactiveApprovals: false,\n permissionModes: ['default', 'bypassPermissions', 'dontAsk'],\n defaultPermissionMode: 'default',\n resume: false,\n resumeBackfill: false,\n listSessions: false,\n contextUsage: false,\n rateLimits: false,\n mcpStatus: true,\n mcpServerActions: false,\n sessionMcpServers: false,\n slashCommands: false,\n clearContext: true,\n skillsList: false,\n settingSources: false,\n budgets: false,\n attachments: ['image', 'pdf', 'text'],\n vfs: true,\n hostCwd: false,\n streaming: 'token',\n },\n}\n\nexport function supportsPermissionMode(engine: ProfileEngine | undefined, mode: PermissionMode): boolean {\n return ENGINE_CAPABILITIES[engine ?? 'claude'].permissionModes.includes(mode)\n}\n\nexport type ProviderConfig = {\n id: string\n model?: string\n models?: string[]\n baseUrl?: string\n apiKeyEnv?: string\n}\n\nexport type SessionCapability = 'web_search' | 'download' | 'web_fetch' | 'deliver_file'\n\nexport type ProfileSessionDefaults = {\n capabilities?: SessionCapability[]\n mcpServers?: string[]\n instructions?: string\n}\n\nexport type ProfileUsageWindow = {\n info: RateLimitInfo\n updatedAt: number\n inferredReset?: boolean\n}\n\nexport type ProfileUsage = Record<string, ProfileUsageWindow>\n\nexport type ProfileInfo = {\n name: string\n engine?: ProfileEngine\n configDir?: string\n codexHome?: string\n provider?: ProviderConfig\n description?: string\n defaults?: ProfileDefaults\n session?: ProfileSessionDefaults\n models?: ModelOption[]\n defaultModel?: string\n capabilities?: EngineCapabilities\n available?: boolean\n unavailableReason?: string\n usage?: ProfileUsage\n spend?: ProfileSpend\n managed?: boolean\n}\n\nexport type ProfileConfigSnapshot = {\n settings?: {\n model?: string\n defaultPermissionMode?: string\n permissionRules?: { allow: number; ask: number; deny: number }\n envKeys?: string[]\n hooks?: string[]\n }\n hasUserMemory: boolean\n skills: string[]\n agents: string[]\n commands: string[]\n}\n\nexport type McpServerConfigWire =\n | { type?: 'stdio'; command: string; args?: string[]; env?: Record<string, string> }\n | { type: 'http'; url: string; headers?: Record<string, string> }\n | { type: 'sse'; url: string; headers?: Record<string, string> }\n\nexport type McpServerToolInfo = {\n name: string\n title?: string\n description?: string\n annotations?: { readOnly?: boolean; destructive?: boolean; openWorld?: boolean }\n inputSchema?: unknown\n}\n\nexport type McpServerStatusInfo = {\n name: string\n status: string\n scope?: string\n error?: string\n serverInfo?: { name: string; version: string }\n transport?: 'stdio' | 'http' | 'sse' | 'sdk'\n command?: string\n args?: string[]\n url?: string\n tools?: McpServerToolInfo[]\n}\n\nexport type McpServersResponse = { servers: McpServerStatusInfo[] }\n\nexport type McpServerActionRequest = { action: 'reconnect' | 'enable' | 'disable' }\n\nexport type UploadAttachmentResponse = { attachment: MessageAttachment }\n\nexport type CreateSessionRequest = {\n cwd?: string\n profile?: string\n prompt?: string\n permissionMode?: PermissionMode\n allowDangerouslySkipPermissions?: boolean\n allowedTools?: string[]\n disallowedTools?: string[]\n mcpServers?: Record<string, McpServerConfigWire>\n settingSources?: Array<'user' | 'project' | 'local'>\n model?: string\n maxTurns?: number\n maxBudgetUsd?: number\n resume?: string\n forkSession?: boolean\n reasoningEffort?: string\n includePartialMessages?: boolean\n // Overrides the gateway's default. null (or 0) means a prompt never expires - it waits as long as the session lives.\n approvalTimeoutMs?: number | null\n questionBehavior?: QuestionBehavior\n capabilities?: SessionCapability[]\n meta?: Record<string, unknown>\n scope?: Record<string, string>\n}\n\nexport type SubagentInfo = {\n toolUseId: string\n agentType?: string\n description?: string\n status: 'running' | 'done' | 'failed'\n startedAt: number\n toolCount: number\n}\n\nexport const SUBAGENT_HISTORY = 8\n\n// Widening this union costs a PROTOCOL_VERSION bump: Swift decodes it strictly.\nexport type ChecklistStatus = 'pending' | 'in_progress' | 'completed'\n\nexport type ChecklistItem = { text: string; status: ChecklistStatus }\n\nexport const CHECKLIST_TEXT_MAX = 200\n\nexport type ProjectIcon = { type: 'glyph'; name: string } | { type: 'image'; mediaType: 'image/png' | 'image/svg+xml'; hash: string }\n\nexport type ProjectInfo = {\n name: string\n root: string\n icon?: ProjectIcon\n}\n\nexport type SessionInfo = {\n id: string\n sdkSessionId?: string\n status: SessionStatus\n cwd: string\n profile?: string\n engine?: ProfileEngine\n capabilities?: EngineCapabilities\n model?: string\n permissionMode?: PermissionMode\n canBypassPermissions?: boolean\n apiKeySource?: string\n createdAt: number\n lastSeq: number\n // Which log the seqs belong to. A dormant wake starts a fresh log and bumps it, so a `seq`\n // that outlived one - a notification sitting on a lock screen - can be told from a live one.\n // Absent from a gateway that predates it, and from a session that has never woken; additive,\n // so no `PROTOCOL_VERSION` bump, and a reader that finds it absent on either side must keep\n // trusting the seq.\n epoch?: number\n pendingPermissionCount: number\n subagents?: SubagentInfo[]\n checklist?: ChecklistItem[]\n meta?: Record<string, unknown>\n title?: string\n totalCostUsd?: number\n costUsd?: number\n usageByModel?: ByModel\n numTurns?: number\n activityCount?: number\n // Rows of the kind a person is actually waiting to read - see `transcriptProse`.\n // Absent from a gateway that predates it - additive, so no `PROTOCOL_VERSION` bump -\n // which is why every reader falls back to `activityCount`. This is the badge's number; `activityCount` stays the \"has\n // anything happened at all\" measure that sorting and dormancy read.\n proseCount?: number\n lastActivityAt?: number\n contextUsage?: ContextReading\n scope?: Record<string, string>\n project?: ProjectInfo\n}\n\nexport function contextReading(body: SessionEventBody): ContextReading | undefined {\n if (body.type !== 'context_usage') {\n return undefined\n }\n const { totalTokens, maxTokens, percentage } = body.usage\n return { totalTokens, maxTokens, percentage }\n}\n\nexport function transcriptActivity(body: SessionEventBody): number {\n if ('parentToolUseId' in body && body.parentToolUseId != null) {\n return 0\n }\n switch (body.type) {\n case 'assistant_message': {\n const content = body.message.content\n if (typeof content === 'string') {\n return content.trim() === '' ? 0 : 1\n }\n const rows = content.filter((block) => block.type === 'text' || block.type === 'thinking' || block.type === 'tool_use').length\n return rows\n }\n case 'user_message': {\n return body.synthetic ? 0 : 1\n }\n case 'turn_result':\n case 'file_delivered':\n case 'session_error': {\n return 1\n }\n default: {\n return 0\n }\n }\n}\n\n// The narrower door beside transcriptActivity: output addressed to the human, not evidence of work.\n// `user_message` is deliberately absent: the human wrote it, so it can never be unread by them, and\n// counting it badged the sender's own prompt whenever they navigated away before the list next polled.\nexport function transcriptProse(body: SessionEventBody): number {\n if ('parentToolUseId' in body && body.parentToolUseId != null) {\n return 0\n }\n switch (body.type) {\n case 'assistant_message': {\n const content = body.message.content\n if (typeof content === 'string') {\n return content.trim() === '' ? 0 : 1\n }\n return content.filter((block) => block.type === 'text' && typeof block.text === 'string' && block.text.trim() !== '').length\n }\n case 'turn_result': {\n return body.isError ? 1 : 0\n }\n case 'file_delivered':\n case 'session_error': {\n return 1\n }\n default: {\n return 0\n }\n }\n}\n\nexport function transcriptContent(body: SessionEventBody): boolean {\n switch (body.type) {\n case 'user_message':\n case 'assistant_message':\n case 'stream_delta':\n case 'turn_result':\n case 'execution_dispatched':\n case 'execution_result':\n case 'execution_failed':\n case 'file_delivered':\n case 'session_error':\n case 'session_closed':\n case 'conversation_reset':\n case 'context_compacted': {\n return true\n }\n default: {\n return false\n }\n }\n}\n\nexport function replayCoalesceKey(body: SessionEventBody): string | undefined {\n switch (body.type) {\n case 'context_usage': {\n return 'context_usage'\n }\n case 'rate_limit': {\n return body.info.rateLimitType ? `rate_limit:${body.info.rateLimitType}` : undefined\n }\n case 'status_changed': {\n return 'status_changed'\n }\n case 'context_compacted': {\n return `context_compacted:${body.uuid}`\n }\n case 'checklist': {\n return 'checklist'\n }\n case 'sdk_event': {\n return body.payload.type === 'system' && body.payload.subtype === 'status' ? 'sdk_event:system:status' : undefined\n }\n default: {\n return undefined\n }\n }\n}\n\nexport function replayRetains(body: SessionEventBody): boolean {\n if (body.type !== 'stream_delta') {\n return true\n }\n const delta = body.event as { type?: string; delta?: { type?: string } }\n if (delta.type !== 'content_block_delta') {\n return false\n }\n return delta.delta?.type === 'text_delta' || delta.delta?.type === 'thinking_delta'\n}\n\nexport function snapshotRetains(body: SessionEventBody): boolean {\n return body.type !== 'stream_delta'\n}\n\nexport type SdkSessionSummary = {\n sessionId: string\n summary: string\n lastModified: number\n createdAt?: number\n customTitle?: string\n firstPrompt?: string\n gitBranch?: string\n cwd?: string\n}\n\nexport type SessionFileInfo = { path: string; bytes: number }\nexport type ListSessionFilesResponse = { files: SessionFileInfo[] }\nexport type ListSessionsResponse = { sessions: SessionInfo[] }\nexport type CreateSessionResponse = { session: SessionInfo }\nexport type GetSessionResponse = { session: SessionInfo }\n\nexport type UpdateSessionRequest = { title?: string | null }\nexport type UpdateSessionResponse = { session: SessionInfo }\n\nexport type ResolvePermissionRequest =\n | { behavior: 'allow'; updatedInput?: Record<string, unknown> }\n | { behavior: 'deny'; message?: string; interrupt?: boolean }\nexport type ResolvePermissionResponse = { resolved: true }\n\nexport type SubmitExecutionResultRequest =\n | { status: 'ok'; output: ToolExecutionOutput; logs?: string[] }\n | { status: 'failed'; reason: string; error: string; logs?: string[] }\nexport type SubmitExecutionResultResponse = {\n applied: boolean\n sessionId: string\n}\n\nexport type ListSdkSessionsResponse = { sdkSessions: SdkSessionSummary[] }\nexport type ListProfilesResponse = {\n profiles: ProfileInfo[]\n canManage?: boolean\n}\n\nexport type CreateProfileRequest = ProfileInfo\n\nexport type UpdateProfileRequest = Omit<Partial<ProfileInfo>, 'name'>\n\nexport type HostFileRoot = {\n path: string\n name: string\n}\n\nexport type ListHostRootsResponse = {\n roots: HostFileRoot[]\n canWrite: boolean\n}\n\nexport type HostDirEntry = {\n name: string\n path: string\n type: 'file' | 'dir' | 'symlink' | 'other'\n bytes?: number\n modifiedAt?: number\n}\n\nexport type ListHostDirResponse = {\n path: string\n entries: HostDirEntry[]\n truncated?: boolean\n}\n\nexport type HostFileMatch = {\n path: string\n relative: string\n}\n\nexport type FindHostFilesResponse = {\n base: string\n matches: HostFileMatch[]\n truncated: boolean\n}\n\nexport type ReadHostFileResponse = {\n path: string\n content: string\n encoding: 'utf8' | 'base64'\n bytes: number\n hash: string\n modifiedAt: number\n}\n\nexport type WriteHostFileRequest = {\n path: string\n content: string\n encoding?: 'utf8' | 'base64'\n expectedHash?: string\n}\n\nexport type WriteHostFileResponse = {\n path: string\n bytes: number\n hash: string\n modifiedAt: number\n}\n\nexport type SaveProfileResponse = { profile: ProfileInfo }\nexport type GetProfileResponse = { profile: ProfileInfo; config: ProfileConfigSnapshot }\nexport type ErrorResponse = { error: string }\n\nexport type SessionNotificationType = 'permission_requested' | 'turn_completed' | 'session_error' | 'session_closed'\n\nexport type SessionNotification = {\n type: SessionNotificationType\n sessionId: string\n session: SessionInfo\n seq: number\n ts: number\n preview?: string\n request?: PermissionRequest\n result?: { isError: boolean; durationMs: number; numTurns: number; totalCostUsd: number }\n reason?: 'client' | 'server' | 'error'\n}\n\nexport type SessionWebhookConfig = {\n url: string\n headers?: Record<string, string>\n events?: SessionNotificationType[]\n}\n\nexport type JobStatus = 'queued' | 'running' | 'parked' | 'succeeded' | 'failed' | 'canceled'\n\nexport type WebhookConfig = {\n url: string\n headers?: Record<string, string>\n progress?: 'messages' | 'completion'\n}\n\nexport type CreateJobRequest = {\n session: CreateSessionRequest & { prompt: string }\n webhook?: WebhookConfig\n maxTokens?: number\n maxDurationMs?: number\n attempts?: number\n retryDelayMs?: number\n meta?: Record<string, unknown>\n}\n\nexport type JobUsage = {\n tokens: number\n totalCostUsd: number\n numTurns: number\n}\n\nexport type JobResult = {\n subtype: string\n isError: boolean\n result?: string\n errors?: string[]\n durationMs: number\n}\n\nexport type JobInfo = {\n id: string\n status: JobStatus\n cwd: string\n profile?: string\n prompt: string\n sessionId?: string\n sdkSessionId?: string\n createdAt: number\n startedAt?: number\n finishedAt?: number\n attempt?: number\n maxAttempts?: number\n nextRunAt?: number\n parkedAt?: number\n parkedExecutionId?: string\n usage: JobUsage\n result?: JobResult\n error?: string\n meta?: Record<string, unknown>\n scope?: Record<string, string>\n}\n\nexport type JobProgress = {\n kind: 'assistant_text' | 'tool_use' | 'permission_requested' | 'permission_resolved'\n preview?: string\n request?: PermissionRequest\n}\n\nexport type JobEvent =\n | { type: 'job_submitted'; job: JobInfo; ts: number }\n | { type: 'job_started'; job: JobInfo; ts: number }\n | { type: 'job_progress'; job: JobInfo; progress: JobProgress; ts: number }\n | { type: 'job_parked'; job: JobInfo; executionId: string; ts: number }\n | { type: 'job_resumed'; job: JobInfo; executionId: string; ts: number }\n | { type: 'job_retrying'; job: JobInfo; ts: number }\n | { type: 'job_completed'; job: JobInfo; ts: number }\n\nexport type QueueStats = {\n maxConcurrency: number\n running: number\n queued: number\n parked: number\n sessionTokenLimit?: number\n dailyTokenLimit?: number\n dailyTokensUsed: number\n paused: boolean\n}\n\nexport type QueueServerFrame =\n | { type: 'queue_attached'; protocolVersion: number; stats: QueueStats }\n | { type: 'job_event'; event: JobEvent }\n | { type: 'queue_stats'; stats: QueueStats }\n\nexport type CreateJobResponse = { job: JobInfo }\nexport type GetJobResponse = { job: JobInfo }\nexport type ListJobsResponse = { jobs: JobInfo[] }\nexport type QueueStatsResponse = { stats: QueueStats }\n\nexport * from './checklist.ts'\nexport * from './pricing.ts'\nexport * from './session-list.ts'\nexport * from './tool-titles.ts'\nexport * from './usage.ts'\nexport * from './watermarks.ts'\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/session-list.ts","../src/checklist.ts","../src/pricing.ts","../src/peer-mentions.ts","../src/tool-titles.ts","../src/usage.ts","../src/watermarks.ts","../src/index.ts"],"sourcesContent":["import type { SessionInfo, SubagentInfo } from './index.ts'\n\nexport type SessionState = 'attention' | 'working' | 'idle' | 'ended'\n\nexport const STATE_ORDER: readonly SessionState[] = ['attention', 'working', 'idle', 'ended']\n\nexport const STATE_LABELS: Record<SessionState, string> = {\n attention: 'Needs attention',\n working: 'Working',\n idle: 'Idle',\n ended: 'Ended',\n}\n\nexport function sessionState(info: SessionInfo): SessionState {\n if (info.pendingPermissionCount > 0 || info.status === 'awaiting_approval') {\n return 'attention'\n }\n if (info.status === 'failed' || info.status === 'closed') {\n return 'ended'\n }\n if (info.status === 'running' || info.status === 'starting') {\n return 'working'\n }\n if (runningSubagents(info).length > 0) {\n return 'working'\n }\n return 'idle'\n}\n\nexport function runningSubagents(info: SessionInfo): SubagentInfo[] {\n return (info.subagents ?? []).filter((sub) => sub.status === 'running')\n}\n\n// A failed sub-agent is not a completed one: 'active' keeps it, because it is the row most worth reading.\nexport function visibleSubagents(info: SessionInfo, show: SubagentDisplay): SubagentInfo[] {\n if (show === 'none') {\n return []\n }\n const subagents = info.subagents ?? []\n return show === 'all' ? [...subagents] : subagents.filter((sub) => sub.status !== 'done')\n}\n\nexport function isAgentRecord(sub: SubagentInfo): boolean {\n return sub.isAgent === true || (sub.agentType?.trim() ?? '') !== ''\n}\n\nexport function subagentLabel(sub: SubagentInfo): string {\n const agent = sub.agentType?.trim()\n const description = sub.description?.trim()\n if (agent && description) {\n return `${agent} · ${description}`\n }\n return agent || description || 'Sub-agent'\n}\n\nexport type Facet = 'gateway' | 'adapter' | 'state' | 'project'\nexport type GroupBy = 'none' | Facet\nexport type SortBy = 'recent' | 'name' | Facet\n\n// How much of a session's sub-agent list its card draws. A layout preference, not a facet filter.\nexport type SubagentDisplay = 'all' | 'active' | 'none'\n\nexport type ViewConfig = {\n search: string\n gateways: string[]\n adapters: string[]\n states: SessionState[]\n projects?: string[]\n scoped: boolean\n groupBy: GroupBy\n sortBy: SortBy\n subagents: SubagentDisplay\n}\n\nexport const DEFAULT_VIEW_CONFIG: ViewConfig = {\n search: '',\n gateways: [],\n adapters: [],\n states: [],\n projects: [],\n scoped: true,\n groupBy: 'state',\n sortBy: 'recent',\n subagents: 'active',\n}\n\nexport type ScopeRoot = { hostId?: string; path: string }\n\nexport type WorkspaceScope = { label: string; roots: ScopeRoot[] }\n\nexport type SessionRow = {\n hostId: string\n hostName: string\n local: boolean\n adapter: string\n state: SessionState\n info: SessionInfo\n // Messages this client has not read - `unseenCount` against its watermark, so the\n // unit is prose (`SessionInfo.proseCount`) wherever the gateway reports it. A session\n // that is only running tools contributes 0: the badge answers \"is there something to\n // read\", not \"is anything happening\", which is what `state` is for.\n unseen: number\n}\n\nexport type SessionGroup = { key: string; label?: string; rows: SessionRow[] }\n\nexport function adaptersOf(rows: readonly SessionRow[]): string[] {\n return [...new Set(rows.map((r) => r.adapter))].sort()\n}\n\nexport function projectsOf(rows: readonly SessionRow[]): { key: string; label: string }[] {\n const byKey = new Map<string, string>()\n for (const row of rows) {\n byKey.set(projectKey(row), projectLabel(row))\n }\n return [...byKey].map(([key, label]) => ({ key, label })).sort((a, b) => a.label.toLowerCase().localeCompare(b.label.toLowerCase()))\n}\n\nexport function sessionLabel(info: SessionInfo): string {\n return info.title ?? info.id.slice(0, 8)\n}\n\nexport function projectKey(row: SessionRow): string {\n return `${row.hostId}:${normalizePath(row.info.project?.root ?? row.info.cwd)}`\n}\n\nexport function projectLabel(row: Pick<SessionRow, 'info'>): string {\n return row.info.project?.shortcode || projectName(row)\n}\n\nexport function projectName(row: Pick<SessionRow, 'info'>): string {\n const name = row.info.project?.name\n if (name) {\n return name\n }\n const dir = normalizePath(row.info.cwd)\n return dir.slice(dir.lastIndexOf('/') + 1) || 'No project'\n}\n\nexport function projectSubpath(row: Pick<SessionRow, 'info'>): string | undefined {\n const root = row.info.project?.root\n if (root === undefined || !row.info.cwd) {\n return undefined\n }\n const base = normalizePath(root)\n const dir = normalizePath(row.info.cwd)\n if (dir === base) {\n return undefined\n }\n if (!dir.startsWith(`${base}/`)) {\n return undefined\n }\n return dir.slice(base.length + 1) || undefined\n}\n\nexport function isJobRun(info: SessionInfo): boolean {\n return typeof info.meta?.jobId === 'string'\n}\n\nfunction matchesSearch(row: SessionRow, needle: string): boolean {\n if (!needle) {\n return true\n }\n return (\n sessionLabel(row.info).toLowerCase().includes(needle) ||\n row.info.cwd.toLowerCase().includes(needle) ||\n (row.info.project?.name.toLowerCase().includes(needle) ?? false) ||\n (row.info.project?.shortcode?.toLowerCase().includes(needle) ?? false) ||\n row.hostName.toLowerCase().includes(needle) ||\n row.adapter.toLowerCase().includes(needle) ||\n row.info.id.startsWith(needle)\n )\n}\n\nfunction normalizePath(path: string): string {\n return path.replace(/\\\\/g, '/').replace(/\\/+$/, '')\n}\n\nfunction isWithin(root: string, path: string): boolean {\n const base = normalizePath(root)\n const dir = normalizePath(path)\n // The separator matters: /a/project must not swallow /a/project-2.\n return dir === base || dir.startsWith(`${base}/`)\n}\n\nexport function inScope(row: SessionRow, scope: WorkspaceScope): boolean {\n return scope.roots.some(\n (root) => (root.hostId ? root.hostId.toLowerCase() === row.hostId.toLowerCase() : row.local) && isWithin(root.path, row.info.cwd),\n )\n}\n\nexport function scopeActive(config: ViewConfig, scope: WorkspaceScope | undefined): boolean {\n return config.scoped && scope !== undefined\n}\n\nexport function filterRows(rows: readonly SessionRow[], config: ViewConfig, scope?: WorkspaceScope): SessionRow[] {\n const needle = config.search.trim().toLowerCase()\n const scoping = scopeActive(config, scope) ? scope : undefined\n return rows.filter(\n (row) =>\n (config.gateways.length === 0 || config.gateways.includes(row.hostId)) &&\n (config.adapters.length === 0 || config.adapters.includes(row.adapter)) &&\n (config.states.length === 0 || config.states.includes(row.state)) &&\n (!config.projects?.length || config.projects.includes(projectKey(row))) &&\n (!scoping || inScope(row, scoping)) &&\n matchesSearch(row, needle),\n )\n}\n\nfunction facetKey(row: SessionRow, facet: Facet): string {\n return facet === 'gateway' ? row.hostId : facet === 'adapter' ? row.adapter : facet === 'project' ? projectKey(row) : row.state\n}\n\nfunction facetLabel(row: SessionRow, facet: Facet): string {\n return facet === 'gateway'\n ? row.hostName\n : facet === 'adapter'\n ? row.adapter\n : facet === 'project'\n ? projectLabel(row)\n : STATE_LABELS[row.state]\n}\n\nfunction facetRank(row: SessionRow, facet: Facet): string {\n if (facet === 'state') {\n return String(STATE_ORDER.indexOf(row.state))\n }\n return facetLabel(row, facet).toLowerCase()\n}\n\nfunction byRecency(a: SessionRow, b: SessionRow) {\n return (b.info.lastActivityAt ?? b.info.createdAt) - (a.info.lastActivityAt ?? a.info.createdAt)\n}\n\nfunction compare(a: SessionRow, b: SessionRow, sortBy: SortBy): number {\n if (sortBy === 'recent') {\n return byRecency(a, b)\n }\n if (sortBy === 'name') {\n return (\n sessionLabel(a.info).localeCompare(sessionLabel(b.info), undefined, {\n sensitivity: 'base',\n }) || byRecency(a, b)\n )\n }\n return facetRank(a, sortBy).localeCompare(facetRank(b, sortBy)) || byRecency(a, b)\n}\n\nexport function groupRows(rows: readonly SessionRow[], config: ViewConfig): SessionGroup[] {\n const sorted = [...rows].sort((a, b) => compare(a, b, config.sortBy))\n if (config.groupBy === 'none') {\n return sorted.length ? [{ key: 'all', rows: sorted }] : []\n }\n const facet = config.groupBy\n const groups = new Map<string, SessionGroup & { rank: string }>()\n for (const row of sorted) {\n const key = facetKey(row, facet)\n const group = groups.get(key)\n if (group) {\n group.rows.push(row)\n } else {\n groups.set(key, {\n key,\n label: facetLabel(row, facet),\n rank: facetRank(row, facet),\n rows: [row],\n })\n }\n }\n return [...groups.values()].sort((a, b) => a.rank.localeCompare(b.rank))\n}\n\nexport type SubsetSummary = { shown: number; total: number; causes: string[] }\n\nexport function subsetSummary(\n config: ViewConfig,\n scope: WorkspaceScope | undefined,\n shown: number,\n total: number,\n): SubsetSummary | undefined {\n if (shown >= total) {\n return undefined\n }\n const causes: string[] = []\n if (scope && scopeActive(config, scope)) {\n causes.push(scope.label)\n }\n const facets =\n (config.gateways.length ? 1 : 0) + (config.adapters.length ? 1 : 0) + (config.states.length ? 1 : 0) + (config.projects?.length ? 1 : 0)\n if (facets > 0) {\n causes.push(`${facets} filter${facets === 1 ? '' : 's'}`)\n }\n if (config.search.trim()) {\n causes.push('search')\n }\n return { shown, total, causes }\n}\n\nexport function hasFacetFilter(config: ViewConfig): boolean {\n return (\n config.search.trim().length > 0 ||\n config.gateways.length > 0 ||\n config.adapters.length > 0 ||\n config.states.length > 0 ||\n (config.projects?.length ?? 0) > 0\n )\n}\n\nexport function clearFilters(config: ViewConfig): ViewConfig {\n return {\n ...DEFAULT_VIEW_CONFIG,\n scoped: false,\n groupBy: config.groupBy,\n sortBy: config.sortBy,\n subagents: config.subagents,\n }\n}\n","import type { ChecklistItem, ChecklistStatus, SessionInfo } from './index.ts'\nimport { isAgentRecord } from './session-list.ts'\n\nexport type SessionTaskState = 'pending' | 'running' | 'done' | 'failed'\n\nexport type SessionTaskSource = 'checklist' | 'spawn'\n\nexport type SessionTask = {\n key: string\n label: string\n source: SessionTaskSource\n state: SessionTaskState\n detail?: string\n toolUseId?: string\n}\n\nexport type TaskSummary = { total: number; done: number; running: number; failed: number }\n\nfunction checklistEntry(value: unknown): ChecklistItem | undefined {\n if (typeof value !== 'object' || value === null) {\n return undefined\n }\n const raw = value as { content?: unknown; status?: unknown; activeForm?: unknown }\n const status = raw.status\n if (status !== 'pending' && status !== 'in_progress' && status !== 'completed') {\n return undefined\n }\n const content = typeof raw.content === 'string' ? raw.content.trim() : ''\n if (content === '') {\n return undefined\n }\n const active = typeof raw.activeForm === 'string' ? raw.activeForm.trim() : ''\n return { status, text: status === 'in_progress' && active !== '' ? active : content }\n}\n\n// Whole-or-nothing: a malformed entry (streaming, partial input) yields undefined rather than a half-read list.\n// A well-formed empty list is a clear, and answers `[]`.\nexport function parseTodoWriteInput(input: unknown): ChecklistItem[] | undefined {\n const todos = (input as { todos?: unknown } | null)?.todos\n if (!Array.isArray(todos)) {\n return undefined\n }\n const out: ChecklistItem[] = []\n for (const value of todos) {\n const entry = checklistEntry(value)\n if (entry === undefined) {\n return undefined\n }\n out.push(entry)\n }\n return out\n}\n\nfunction checklistState(status: ChecklistStatus): SessionTaskState {\n switch (status) {\n case 'in_progress': {\n return 'running'\n }\n case 'completed': {\n return 'done'\n }\n default: {\n return 'pending'\n }\n }\n}\n\nexport function sessionTasks(info: Pick<SessionInfo, 'checklist' | 'subagents'>): SessionTask[] {\n const checklist = (info.checklist ?? []).map((item, index) => ({\n key: `checklist:${index}`,\n label: item.text,\n source: 'checklist' as const,\n state: checklistState(item.status),\n }))\n const spawns = (info.subagents ?? [])\n .filter((sub) => !isAgentRecord(sub))\n .map((sub) => ({\n key: `spawn:${sub.toolUseId}`,\n label: sub.description?.trim() || 'Task',\n source: 'spawn' as const,\n state: sub.status,\n detail: sub.toolCount > 0 ? String(sub.toolCount) : undefined,\n toolUseId: sub.toolUseId,\n }))\n return [...checklist, ...spawns]\n}\n\nexport function taskSummary(tasks: readonly SessionTask[]): TaskSummary {\n let done = 0\n let running = 0\n let failed = 0\n for (const task of tasks) {\n if (task.state === 'done') {\n done += 1\n } else if (task.state === 'running') {\n running += 1\n } else if (task.state === 'failed') {\n failed += 1\n }\n }\n return { total: tasks.length, done, running, failed }\n}\n\nexport function taskCountLabel(summary: TaskSummary): string | undefined {\n return summary.total === 0 ? undefined : `${summary.done}/${summary.total}`\n}\n\nexport function visibleTasks(tasks: readonly SessionTask[], showCompleted: boolean): SessionTask[] {\n return showCompleted ? [...tasks] : tasks.filter((task) => task.state !== 'done')\n}\n","export type CostBasis = 'list' | 'managed' | 'unknown'\n\nexport type TokenUsage = {\n input: number\n output: number\n cacheWrite5m: number\n cacheWrite1h: number\n cacheRead: number\n costBasis?: CostBasis\n}\n\nexport type ByModel = Record<string, TokenUsage>\n\nexport type ModelRate = {\n input: number\n output: number\n cacheWrite5m: number\n cacheWrite1h: number\n cacheRead: number\n}\n\nexport type CostBreakdown = {\n input: number\n output: number\n cacheWrite: number\n cacheRead: number\n total: number\n unpriced: boolean\n unpricedTokens: number\n unpricedShare: number\n}\n\nexport const PRICING_AS_OF = '2026-09-19'\n\nexport const PRICING_SOURCES = 'platform.claude.com and developers.openai.com list prices, bundled'\n\nexport const PRICING_NOTE = `List rates as of ${PRICING_AS_OF}. A subscription is a flat fee, so this is what the same tokens would have cost on the pay-as-you-go API, not a bill.`\n\nexport const UNPRICED_WARN_SHARE = 0.005\n\nexport const PRICING_STALE_DAYS = 90\n\nconst MTOK = 1_000_000\n\nconst DAY_MS = 86_400_000\n\nconst BASIS_ORDER: Record<CostBasis, number> = { list: 0, managed: 1, unknown: 2 }\n\nconst RATE_FIELDS = ['input', 'output', 'cacheWrite5m', 'cacheWrite1h', 'cacheRead'] as const\n\nconst WEEKS_PER_MONTH = 52 / 12\n\nfunction anthropicRate(input: number, output: number, cacheRead?: number): ModelRate {\n return { input, output, cacheWrite5m: input * 1.25, cacheWrite1h: input * 2, cacheRead: cacheRead ?? input * 0.1 }\n}\n\nfunction openaiRate(input: number, output: number, cacheRead: number): ModelRate {\n return { input, output, cacheWrite5m: input, cacheWrite1h: input, cacheRead }\n}\n\nexport const DEFAULT_PRICING: Record<string, ModelRate> = {\n 'claude-fable-5-1': anthropicRate(10, 50, 0.25),\n 'claude-fable-5': anthropicRate(10, 50),\n 'claude-mythos-5-1': anthropicRate(10, 50, 0.25),\n 'claude-mythos-5': anthropicRate(10, 50),\n 'claude-opus-5': anthropicRate(5, 25),\n 'claude-opus-4-8': anthropicRate(5, 25),\n 'claude-opus-4-7': anthropicRate(5, 25),\n 'claude-opus-4-6': anthropicRate(5, 25),\n 'claude-opus-4-5': anthropicRate(5, 25),\n 'claude-sonnet-5': anthropicRate(2, 10),\n 'claude-sonnet-4-6': anthropicRate(3, 15),\n 'claude-sonnet-4-5': anthropicRate(3, 15),\n 'claude-haiku-4-5': anthropicRate(1, 5),\n 'gpt-6-astra': openaiRate(10, 50, 1),\n 'gpt-5.6-sol': openaiRate(4, 20, 0.4),\n 'gpt-5.6-terra': openaiRate(2, 12, 0.2),\n 'gpt-5.6-luna': openaiRate(0.2, 1.2, 0.02),\n 'gpt-5.5': openaiRate(5, 30, 0.5),\n 'gpt-5.4': openaiRate(2.5, 15, 0.25),\n 'gpt-5.2': openaiRate(1.75, 14, 0.175),\n 'gpt-5.1': openaiRate(1.25, 10, 0.125),\n 'gpt-5': openaiRate(1.25, 10, 0.125),\n}\n\nexport type PricingTable = Record<string, ModelRate>\n\nexport type PricingOverrides = Record<string, ModelRate>\n\nexport type PricingMerge = {\n pricing: PricingTable\n overrides: PricingOverrides\n dropped: string[]\n}\n\nlet activeTable: PricingTable = DEFAULT_PRICING\n\nfunction rateFromInput(value: unknown): ModelRate | undefined {\n if (value === null || typeof value !== 'object') {\n return undefined\n }\n const raw = value as Record<string, unknown>\n const rate: ModelRate = { input: 0, output: 0, cacheWrite5m: 0, cacheWrite1h: 0, cacheRead: 0 }\n for (const field of RATE_FIELDS) {\n const rest = raw[field]\n if (typeof rest !== 'number' || !Number.isFinite(rest) || rest < 0) {\n return undefined\n }\n rate[field] = rest\n }\n return rate\n}\n\nexport function mergePricing(overrides: unknown, base: PricingTable = DEFAULT_PRICING): PricingMerge {\n const accepted: PricingOverrides = {}\n const dropped: string[] = []\n if (overrides !== null && typeof overrides === 'object') {\n for (const [model, value] of Object.entries(overrides as Record<string, unknown>)) {\n const rate = rateFromInput(value)\n const key = canonicalModel(model)\n if (!rate || key === '') {\n dropped.push(model)\n continue\n }\n accepted[key] = rate\n }\n }\n return { pricing: { ...base, ...accepted }, overrides: accepted, dropped }\n}\n\nexport function activePricing(): PricingTable {\n return activeTable\n}\n\n// The table is process-wide configuration, like the bundled rates it replaces entries in, so the gateway sets it\n// once at start and every pricing call that names no table of its own reads it.\nexport function setPricingOverrides(overrides: unknown): PricingMerge {\n const merged = mergePricing(overrides)\n activeTable = merged.pricing\n return merged\n}\n\nexport function pricingAgeDays(now: number, asOf: string = PRICING_AS_OF): number {\n const dated = Date.parse(asOf)\n return Number.isFinite(dated) ? Math.floor((now - dated) / DAY_MS) : 0\n}\n\nexport function pricingAgeNote(now: number, asOf: string = PRICING_AS_OF): string | undefined {\n const days = pricingAgeDays(now, asOf)\n if (days <= PRICING_STALE_DAYS) {\n return undefined\n }\n return `This rate table is ${days} days old, so check the vendor's current list prices before you trust the total.`\n}\n\nexport function canonicalModel(model: string): string {\n const slash = model.lastIndexOf('/')\n const withoutProvider = slash === -1 ? model : model.slice(slash + 1)\n return withoutProvider\n .toLowerCase()\n .replace(/\\[[^\\]]*\\]$/, '')\n .replace(/^(?:[a-z]+\\.)*anthropic\\./, '')\n .replace(/[@-]\\d{8}$/, '')\n .replace(/-v\\d+:\\d+$/, '')\n}\n\nexport function rateFor(model: string | undefined, pricing: PricingTable = activePricing()): ModelRate | undefined {\n return model ? pricing[canonicalModel(model)] : undefined\n}\n\nexport function emptyTokenUsage(): TokenUsage {\n return { input: 0, output: 0, cacheWrite5m: 0, cacheWrite1h: 0, cacheRead: 0 }\n}\n\nexport function totalTokens(usage: TokenUsage): number {\n return usage.input + usage.output + usage.cacheWrite5m + usage.cacheWrite1h + usage.cacheRead\n}\n\nexport function addTokenUsage(into: TokenUsage, add: TokenUsage): TokenUsage {\n return {\n input: into.input + add.input,\n output: into.output + add.output,\n cacheWrite5m: into.cacheWrite5m + add.cacheWrite5m,\n cacheWrite1h: into.cacheWrite1h + add.cacheWrite1h,\n cacheRead: into.cacheRead + add.cacheRead,\n costBasis: worseBasis(into.costBasis, add.costBasis),\n }\n}\n\n// A total priced on a basis the engine could not identify stays suspect however little of it there was,\n// so the worse basis wins rather than the newer one.\nexport function worseBasis(a: CostBasis | undefined, b: CostBasis | undefined): CostBasis | undefined {\n if (a === undefined) {\n return b\n }\n if (b === undefined) {\n return a\n }\n return BASIS_ORDER[a] >= BASIS_ORDER[b] ? a : b\n}\n\nexport function unknownBasisModels(byModel: ByModel): string[] {\n return Object.entries(byModel)\n .filter(([, usage]) => usage.costBasis === 'unknown')\n .map(([model]) => canonicalModel(model))\n}\n\nexport function mergeByModel(into: ByModel, add: ByModel): ByModel {\n const out: ByModel = { ...into }\n for (const [model, usage] of Object.entries(add)) {\n out[model] = addTokenUsage(out[model] ?? emptyTokenUsage(), usage)\n }\n return out\n}\n\nexport function byModelTotalTokens(byModel: ByModel): number {\n let total = 0\n for (const usage of Object.values(byModel)) {\n total += totalTokens(usage)\n }\n return total\n}\n\nfunction num(value: unknown): number {\n return typeof value === 'number' && Number.isFinite(value) && value > 0 ? value : 0\n}\n\nexport function tokenUsageFromWire(usage: unknown): TokenUsage {\n if (usage === null || typeof usage !== 'object') {\n return emptyTokenUsage()\n }\n const wire = usage as {\n input_tokens?: unknown\n output_tokens?: unknown\n cache_creation_input_tokens?: unknown\n cache_read_input_tokens?: unknown\n cache_creation?: { ephemeral_5m_input_tokens?: unknown; ephemeral_1h_input_tokens?: unknown } | null\n }\n const split = wire.cache_creation\n const write1h = num(split?.ephemeral_1h_input_tokens)\n const write5m = split ? num(split.ephemeral_5m_input_tokens) : num(wire.cache_creation_input_tokens)\n return {\n input: num(wire.input_tokens),\n output: num(wire.output_tokens),\n cacheWrite5m: write5m,\n cacheWrite1h: write1h,\n cacheRead: num(wire.cache_read_input_tokens),\n }\n}\n\nfunction unpricedBreakdown(tokens: number): CostBreakdown {\n return {\n input: 0,\n output: 0,\n cacheWrite: 0,\n cacheRead: 0,\n total: 0,\n unpriced: true,\n unpricedTokens: tokens,\n unpricedShare: tokens > 0 ? 1 : 0,\n }\n}\n\nexport function costOf(usage: TokenUsage, model: string | undefined, pricing: PricingTable = activePricing()): CostBreakdown {\n const rate = rateFor(model, pricing)\n if (!rate) {\n return unpricedBreakdown(totalTokens(usage))\n }\n const input = (usage.input / MTOK) * rate.input\n const output = (usage.output / MTOK) * rate.output\n const cacheWrite = (usage.cacheWrite5m / MTOK) * rate.cacheWrite5m + (usage.cacheWrite1h / MTOK) * rate.cacheWrite1h\n const cacheRead = (usage.cacheRead / MTOK) * rate.cacheRead\n return {\n input,\n output,\n cacheWrite,\n cacheRead,\n total: input + output + cacheWrite + cacheRead,\n unpriced: false,\n unpricedTokens: 0,\n unpricedShare: 0,\n }\n}\n\nexport function costOfByModel(byModel: ByModel, pricing: PricingTable = activePricing()): CostBreakdown {\n const acc: CostBreakdown = {\n input: 0,\n output: 0,\n cacheWrite: 0,\n cacheRead: 0,\n total: 0,\n unpriced: false,\n unpricedTokens: 0,\n unpricedShare: 0,\n }\n const models = Object.entries(byModel)\n let anyPriced = false\n let tokens = 0\n for (const [model, usage] of models) {\n tokens += totalTokens(usage)\n const cost = costOf(usage, model, pricing)\n if (cost.unpriced) {\n acc.unpricedTokens += cost.unpricedTokens\n continue\n }\n anyPriced = true\n acc.input += cost.input\n acc.output += cost.output\n acc.cacheWrite += cost.cacheWrite\n acc.cacheRead += cost.cacheRead\n acc.total += cost.total\n }\n acc.unpriced = !anyPriced && models.length > 0\n acc.unpricedShare = tokens > 0 ? acc.unpricedTokens / tokens : 0\n return acc\n}\n\nexport function unpricedModels(byModel: ByModel, pricing: PricingTable = activePricing()): string[] {\n return Object.keys(byModel).filter((model) => rateFor(model, pricing) === undefined)\n}\n\n// Rate limits meter fresh input, output and cache writes; a cache read is nearly free to serve and does not\n// count against a plan window, which is why quota burn and API-equivalent cost diverge on an agentic workload.\nexport function meteredCost(cost: CostBreakdown): number {\n return cost.input + cost.output + cost.cacheWrite\n}\n\nexport type SubscriptionComparison = {\n weeklyUsd: number\n monthlyUsd: number\n weeklyShareUsd: number\n ratio: number\n}\n\nexport function subscriptionComparison(weeklyUsd: number, monthlyUsd: number): SubscriptionComparison | undefined {\n if (!(monthlyUsd > 0) || !Number.isFinite(weeklyUsd) || weeklyUsd < 0) {\n return undefined\n }\n const weeklyShareUsd = monthlyUsd / WEEKS_PER_MONTH\n return { weeklyUsd, monthlyUsd, weeklyShareUsd, ratio: weeklyUsd / weeklyShareUsd }\n}\n\nexport type ProfileSpend = {\n weekUsd: number\n monthUsd: number\n weekByModel: ByModel\n unpricedShare: number\n monthlySubscriptionUsd?: number\n subscription?: SubscriptionComparison\n}\n","// `#Name` in a composer names another session on the gateway. The client writes the token, the\n// gateway resolves it, and the two must fold a title the same way or a picked name would not match\n// itself. Everything here is pure, so the same rule runs in a browser, in a webview and on a server.\n\nexport const PEER_MENTION_SIGIL = '#'\n\n// Distinct sessions expanded per message. Four is past any real sentence, and keeps the block a\n// short prompt carries from outweighing the prompt.\nexport const PEER_MENTION_MAX = 4\n\nexport const PEER_MENTION_BODY_MAX = 64\n\n// A scan bound, not a policy: a pasted file of hashes must not cost a resolution pass per line.\nexport const PEER_MENTION_SCAN_MAX = 32\n\nexport type PeerMentionToken = { start: number; end: number; body: string }\n\n// Trailing punctuation belongs to the sentence, not to the name. Shared with `scanPromptTokens`,\n// which scans the same text for `@file` and `/command`, so one boundary answers for all of them.\nexport const PROMPT_SENTENCE_TAIL: ReadonlySet<string> = new Set(['.', ',', ';', ':', '!', '?', ')', ']', '}', '\"', \"'\"])\n\nconst MENTION_BODY = /^[\\p{L}\\p{N}][\\p{L}\\p{N}\\-_]*$/u\n\n// What the composer writes for a session, and the only spelling the resolver is guaranteed to\n// match. An untitled session falls back to the short id `sessionLabel` already draws.\nexport function peerMentionSlug(title: string | undefined, id: string): string {\n const slug = (title ?? '')\n .normalize('NFKC')\n .replace(/[^\\p{L}\\p{N}]+/gu, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, PEER_MENTION_BODY_MAX)\n .replace(/^-+|-+$/g, '')\n return slug || id.slice(0, 8)\n}\n\n// The comparison key. Both sides fold; neither compares raw, so `#astra` finds `Astra` and\n// `#fix_login_bug` finds `Fix login bug`.\nexport function peerMentionKey(body: string): string {\n return body\n .normalize('NFKC')\n .toLowerCase()\n .replace(/[_\\s]+/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-+|-+$/g, '')\n}\n\nexport function isPeerMentionBody(body: string): boolean {\n return body.length > 0 && body.length <= PEER_MENTION_BODY_MAX && MENTION_BODY.test(body)\n}\n\n// The boundary rule, mirroring `scanPromptTokens`: a sigil at the start of a word, a body to the\n// next whitespace, sentence punctuation peeled off the end. `# heading` and `issue#42` are not\n// mentions, and neither is `#-x`.\nexport function scanPeerMentions(text: string): PeerMentionToken[] {\n const tokens: PeerMentionToken[] = []\n const words = /\\S+/g\n let match: RegExpExecArray | null\n while ((match = words.exec(text)) !== null && tokens.length < PEER_MENTION_SCAN_MAX) {\n if (match[0][0] !== PEER_MENTION_SIGIL) {\n continue\n }\n let end = match.index + match[0].length\n while (end > match.index && PROMPT_SENTENCE_TAIL.has(text[end - 1]!)) {\n end--\n }\n const body = text.slice(match.index + 1, end)\n if (!isPeerMentionBody(body)) {\n continue\n }\n tokens.push({ start: match.index, end, body })\n }\n return tokens\n}\n","export const TOOL_TITLE_MAX_CHARS = 64\n\n// Capability tools the sandbox grants and the synthetic names the codex adapter invents: wire\n// names with no public vocabulary behind them. An engine's own tool names (`Bash`, `Read`,\n// `Task`) are deliberately absent - those are the CLI's published names and users read them.\nexport const BUILTIN_TOOL_TITLES: Record<string, string> = {\n fs_read: 'Reading a file',\n fs_write: 'Writing a file',\n fs_list: 'Listing files',\n eval_script: 'Running a script',\n web_fetch: 'Fetching a web page',\n web_search: 'Searching the web',\n deliver_file: 'Delivering a file',\n download: 'Downloading a file',\n CodexCommand: 'Running a command',\n CodexFileChange: 'Editing a file',\n CodexWebSearch: 'Searching the web',\n CodexImageGeneration: 'Generating an image',\n CodexImageView: 'Viewing an image',\n peers_list: 'Listing peer sessions',\n peers_peek: 'Peeking at a peer session',\n peers_send: 'Messaging a peer session',\n mcp__workerdeck__peers_list: 'Listing peer sessions',\n mcp__workerdeck__peers_peek: 'Peeking at a peer session',\n mcp__workerdeck__peers_send: 'Messaging a peer session',\n}\n\nexport function toolTitle(name: string, titles?: Record<string, string>): string | undefined {\n return sanitizeToolTitle(titles?.[name] ?? BUILTIN_TOOL_TITLES[name], name)\n}\n\n// Titles reach here from remote MCP servers, so they are untrusted display text: one line,\n// clamped, and never a restatement of the wire name the caller already has.\nexport function sanitizeToolTitle(title: string | undefined, name?: string): string | undefined {\n if (typeof title !== 'string') {\n return undefined\n }\n const flat = [...title]\n .map((char) => (char < ' ' || char === '\\u007f' ? ' ' : char))\n .join('')\n .replace(/\\s+/g, ' ')\n .trim()\n if (flat === '' || flat === name) {\n return undefined\n }\n // By code point, not code unit: a clamp that splits a surrogate pair renders a replacement\n // character, and the clients that mirror this rule do not count in UTF-16.\n const points = [...flat]\n return points.length > TOOL_TITLE_MAX_CHARS ? points.slice(0, TOOL_TITLE_MAX_CHARS - 1).join('') + '…' : flat\n}\n\n// The peer tools both engines expose, under the bare name and the MCP-prefixed one. A client that\n// draws peer traffic as its own kind of row has to recognise the call by name, so the list lives\n// here rather than in any one client.\nexport const PEER_SEND_TOOLS = ['peers_send', 'mcp__workerdeck__peers_send'] as const\n\nexport function isPeerSendTool(name: string): boolean {\n return (PEER_SEND_TOOLS as readonly string[]).includes(name)\n}\n","import type { ProfileUsage, RateLimitInfo } from './index.ts'\n\nexport type SessionUsage = {\n rateLimits?: Record<string, RateLimitInfo>\n updatedAt?: number\n}\n\nexport function mergeUsage(session: SessionUsage, profile: ProfileUsage | undefined): ProfileUsage {\n const out: ProfileUsage = {}\n for (const [key, info] of Object.entries(session.rateLimits ?? {})) {\n out[key] = { info, updatedAt: session.updatedAt ?? 0 }\n }\n for (const [key, window] of Object.entries(profile ?? {})) {\n out[key] = window\n }\n return out\n}\n\n// A rate-limit reading is a poll, not a stream: the engine reports one at a turn boundary, on an attach and on a\n// profiles read, and nothing in between. A window older than this is still the best answer anyone has, and it is\n// no longer a claim about right now, so every surface marks it rather than drawing it as current. Minutes, not\n// hours: the windows move over hours, so a reading from this morning can be wrong by a lot.\nexport const USAGE_STALE_AFTER_MS = 15 * 60_000\n\nexport function usageIsStale(row: Pick<UsageWindowRow, 'updatedAt' | 'inferredReset'>, now: number): boolean {\n // An inferred reset is not stale, it is derived at serve time from the wall clock, and it says so in its own words.\n if (row.inferredReset || row.updatedAt === undefined) {\n return false\n }\n return now - row.updatedAt > USAGE_STALE_AFTER_MS\n}\n\nexport type UsageWindowRow = {\n key: string\n info: RateLimitInfo\n updatedAt?: number\n inferredReset?: boolean\n}\n\nexport function orderUsageWindows(usage: ProfileUsage | undefined): UsageWindowRow[] {\n const all = Object.entries(usage ?? {})\n .filter(([, w]) => w.info.utilization !== undefined)\n .map(([key, w]) => ({ key, info: w.info, updatedAt: w.updatedAt, inferredReset: w.inferredReset }))\n const named = ['five_hour', 'seven_day'].flatMap((key) => all.filter((w) => w.key === key))\n const perModel = all.filter((w) => w.key.startsWith('seven_day_')).sort((a, b) => a.key.localeCompare(b.key))\n return [...named, ...perModel]\n}\n\nexport function usageInfos(usage: ProfileUsage | undefined): Record<string, RateLimitInfo> | undefined {\n if (!usage) {\n return undefined\n }\n const out: Record<string, RateLimitInfo> = {}\n for (const [key, window] of Object.entries(usage)) {\n out[key] = window.info\n }\n return out\n}\n","export type Watermark = {\n itemCount: number\n activity: number\n // Prose rows read (`SessionInfo.proseCount`). Optional because a mark stored before\n // prose counting existed cannot say - see `unseenCount`, which reads that absence as\n // \"caught up\" rather than badging a whole history the operator has already seen.\n prose?: number\n turns: number\n seenAt: number\n}\n\nexport type WatermarkStore = {\n read(): Record<string, Watermark> | undefined\n write(marks: Record<string, Watermark>): void\n}\n\nconst MAX_AGE_MS = 30 * 24 * 60 * 60 * 1000\n\nconst TOUCH_MS = 60_000\n\nexport function watermarkKey(hostId: string, sessionId: string) {\n return `${hostId}:${sessionId}`\n}\n\nexport class Watermarks {\n readonly #store: WatermarkStore\n #cache: Record<string, Watermark>\n\n constructor(store: WatermarkStore) {\n this.#store = store\n this.#cache = { ...store.read() }\n }\n\n get(hostId: string, sessionId: string): Watermark | undefined {\n return this.#cache[watermarkKey(hostId, sessionId)]\n }\n\n all(): Readonly<Record<string, Watermark>> {\n return this.#cache\n }\n\n mark(\n hostId: string,\n sessionId: string,\n seen: { itemCount?: number; activity?: number; prose?: number; turns?: number },\n now = Date.now(),\n ): boolean {\n const id = watermarkKey(hostId, sessionId)\n const previous = this.#cache[id]\n const next: Watermark = {\n itemCount: Math.max(previous?.itemCount ?? 0, seen.itemCount ?? 0),\n activity: Math.max(previous?.activity ?? 0, seen.activity ?? 0),\n // A caller with nothing to say about prose (an older gateway reports no `proseCount`)\n // must not overwrite a real mark with 0, which would re-badge everything already read.\n prose: seen.prose === undefined ? previous?.prose : Math.max(previous?.prose ?? 0, seen.prose),\n turns: Math.max(previous?.turns ?? 0, seen.turns ?? 0),\n seenAt: now,\n }\n if (\n previous &&\n previous.itemCount === next.itemCount &&\n previous.activity === next.activity &&\n previous.prose === next.prose &&\n previous.turns === next.turns &&\n next.seenAt - previous.seenAt < TOUCH_MS\n ) {\n return false\n }\n this.#cache[id] = next\n this.#store.write(this.#prune(now))\n return true\n }\n\n forget(hostId: string, sessionId: string): void {\n const id = watermarkKey(hostId, sessionId)\n if (!(id in this.#cache)) {\n return\n }\n delete this.#cache[id]\n this.#store.write(this.#cache)\n }\n\n #prune(now: number): Record<string, Watermark> {\n const cutoff = now - MAX_AGE_MS\n for (const [id, mark] of Object.entries(this.#cache)) {\n if (mark.seenAt < cutoff) {\n delete this.#cache[id]\n }\n }\n return this.#cache\n }\n}\n\n// The badge's number, in the best unit the pair can agree on: prose the human has not\n// read, else rows, else turns. The ladder is what keeps an older gateway (no `proseCount`\n// on the wire) badging exactly as it did before rather than going silent.\nexport function unseenCount(mark: Watermark | undefined, info: { proseCount?: number; activityCount?: number; turns?: number }): number {\n if (!mark) {\n return 0\n }\n if (info.proseCount !== undefined) {\n // `mark.prose` absent = a mark written before prose counting. Reading it as\n // \"caught up\" costs one missed badge on a session already visited; reading it as 0\n // would badge every such session with its entire history the first time it polls.\n return Math.max(0, info.proseCount - (mark.prose ?? info.proseCount))\n }\n if (info.activityCount !== undefined) {\n return Math.max(0, info.activityCount - mark.activity)\n }\n return Math.max(0, (info.turns ?? 0) - mark.turns)\n}\n","import type { ByModel, PricingOverrides, ProfileSpend } from './pricing.ts'\n\nexport const PROTOCOL_VERSION = 1\n\nexport type SessionStatus = 'starting' | 'running' | 'awaiting_approval' | 'idle' | 'parked' | 'failed' | 'closed'\n\nexport type PermissionMode = 'default' | 'acceptEdits' | 'bypassPermissions' | 'plan' | 'dontAsk' | 'auto'\n\nexport type TextBlock = { type: 'text'; text: string }\nexport type ThinkingBlock = { type: 'thinking'; thinking: string }\nexport type ToolUseBlock = { type: 'tool_use'; id: string; name: string; input: unknown }\nexport type ToolResultBlock = {\n type: 'tool_result'\n tool_use_id: string\n content?: string | Array<{ type: string; text?: string; [key: string]: unknown }>\n is_error?: boolean\n truncated?: boolean\n total_chars?: number\n}\n\nexport const TOOL_RESULT_HEAD_CHARS = 8_000\n\nexport type ImageRefPart = {\n type: 'image_ref'\n media_type: string\n bytes: number\n part_index: number\n}\n\nfunction base64Bytes(data: string): number {\n const padding = data.endsWith('==') ? 2 : data.endsWith('=') ? 1 : 0\n return Math.max(0, Math.floor((data.length * 3) / 4) - padding)\n}\n\nexport function imagePartRef(part: { type?: string; [key: string]: unknown }, index: number): ImageRefPart | undefined {\n if (part.type !== 'image') {\n return undefined\n }\n const source = part.source as { type?: string; data?: unknown; media_type?: unknown } | undefined\n if (!source || source.type !== 'base64' || typeof source.data !== 'string') {\n return undefined\n }\n return {\n type: 'image_ref',\n media_type: typeof source.media_type === 'string' ? source.media_type : 'application/octet-stream',\n bytes: base64Bytes(source.data),\n part_index: index,\n }\n}\n\nexport type UnknownBlock = { type: string; [key: string]: unknown }\n\nexport type PatchHunk = {\n oldStart: number\n oldLines: number\n newStart: number\n newLines: number\n lines: string[]\n}\n\nexport type FilePatch = {\n path?: string\n kind?: 'create' | 'update'\n hunks: PatchHunk[]\n truncated?: boolean\n}\n\nexport type ContentBlock = TextBlock | ThinkingBlock | ToolUseBlock | ToolResultBlock | UnknownBlock\n\nexport type MessageAttachment = {\n id: string\n name: string\n mediaType: string\n bytes: number\n}\n\nexport type ApiMessage = {\n role: 'user' | 'assistant'\n content: string | ContentBlock[]\n model?: string\n stop_reason?: string | null\n usage?: {\n input_tokens?: number\n output_tokens?: number\n cache_creation_input_tokens?: number\n cache_read_input_tokens?: number\n }\n}\n\nexport type PermissionRequest = {\n id: string\n toolName: string\n input: Record<string, unknown>\n toolUseId: string\n title?: string\n displayName?: string\n description?: string\n decisionReason?: string\n agentId?: string\n expiresAt?: number\n}\n\nexport type PermissionDecisionSource = 'client' | 'timeout' | 'policy'\n\nexport type UserQuestionOption = {\n label: string\n description?: string\n preview?: string\n}\n\nexport type UserQuestion = {\n question: string\n header: string\n options: UserQuestionOption[]\n multiSelect?: boolean\n}\n\nexport type QuestionBehavior = 'ask' | 'auto' | 'deny'\n\nexport function parseUserQuestions(input: Record<string, unknown>): UserQuestion[] {\n const raw = Array.isArray(input.questions) ? input.questions : []\n return raw.flatMap((entry): UserQuestion[] => {\n const q = entry as Partial<UserQuestion>\n if (typeof q.question !== 'string' || !Array.isArray(q.options)) {\n return []\n }\n const options = q.options.filter((o): o is UserQuestionOption => typeof (o as UserQuestionOption | undefined)?.label === 'string')\n if (options.length === 0) {\n return []\n }\n return [\n {\n question: q.question,\n header: typeof q.header === 'string' ? q.header : '',\n options,\n multiSelect: q.multiSelect === true,\n },\n ]\n })\n}\n\nexport type ModelOption = {\n value: string\n resolvedModel?: string\n displayName: string\n description?: string\n primary?: boolean\n reasoningEfforts?: readonly string[]\n}\n\nexport type SkillInfo = {\n name: string\n description?: string\n shortDescription?: string\n displayName?: string\n defaultPrompt?: string\n scope?: string\n enabled: boolean\n}\n\nexport type SlashCommandInfo = {\n name: string\n description?: string\n argumentHint?: string\n aliases?: string[]\n}\n\nexport type ContextUsageCategory = {\n name: string\n tokens: number\n color: string\n}\n\nexport type ContextUsage = {\n categories: ContextUsageCategory[]\n totalTokens: number\n maxTokens: number\n percentage: number\n model?: string\n}\n\nexport type ContextReading = {\n totalTokens: number\n maxTokens: number\n percentage: number\n}\n\nexport type RateLimitInfo = {\n status: string\n rateLimitType?: string\n utilization?: number\n resetsAt?: number\n isUsingOverage?: boolean\n}\n\nexport type ToolExecutionStatus = 'pending' | 'deferred' | 'settled' | 'failed'\n\nexport type ToolExecutionBackend = 'server' | 'browser' | 'managed' | 'remote'\n\nexport type ToolExecutionOutput = { type: 'text'; value: string } | { type: 'json'; value: unknown }\n\nexport type SessionEventBody =\n | {\n type: 'system_init'\n sdkSessionId: string\n model: string\n cwd: string\n apiKeySource: string\n tools: string[]\n skills: string[]\n slashCommands: string[]\n permissionMode: PermissionMode\n claudeCodeVersion: string\n mcpServers: Array<{ name: string; status: string }>\n }\n | { type: 'status_changed'; status: SessionStatus; detail?: string }\n | {\n type: 'capabilities'\n models: ModelOption[]\n commands: SlashCommandInfo[]\n defaultModel?: string\n }\n | { type: 'skills'; skills: SkillInfo[] }\n | { type: 'tool_titles'; titles: Record<string, string> }\n | { type: 'checklist'; items: ChecklistItem[] }\n | {\n type: 'file_produced'\n fileId: string\n path: string\n mediaType?: string\n bytes?: number\n toolUseId?: string\n }\n | { type: 'model_changed'; model?: string }\n | { type: 'permission_mode_changed'; mode: PermissionMode }\n | { type: 'context_usage'; usage: ContextUsage }\n | { type: 'rate_limit'; info: RateLimitInfo }\n | { type: 'plan_info'; subscriptionType: string }\n | {\n type: 'conversation_reset'\n sdkSessionId?: string\n }\n | {\n type: 'context_compacted'\n uuid: string\n parentToolUseId?: string | null\n // The same `uuid` is emitted twice: once with `pending` when the engine starts summarising,\n // once without it when the boundary lands, so one row settles in place. A reader that\n // never sees the first (an older gateway, a replay coalesced to the last) draws the\n // boundary alone, which is what it drew before.\n pending?: boolean\n trigger?: 'manual' | 'auto'\n preTokens?: number\n postTokens?: number\n error?: string\n }\n | {\n type: 'assistant_message'\n message: ApiMessage\n parentToolUseId: string | null\n replay?: boolean\n uuid: string\n }\n | {\n type: 'user_message'\n message: ApiMessage\n parentToolUseId: string | null\n replay?: boolean\n synthetic?: boolean\n attachments?: MessageAttachment[]\n patch?: FilePatch\n uuid?: string\n origin?: MessageOrigin\n }\n | {\n type: 'stream_delta'\n event: { type: string; [key: string]: unknown }\n parentToolUseId: string | null\n uuid: string\n }\n | {\n type: 'turn_result'\n subtype: 'success' | 'error_during_execution' | 'error_max_turns' | 'error_max_budget_usd' | 'error_max_structured_output_retries'\n isError: boolean\n durationMs: number\n numTurns: number\n totalCostUsd: number\n result?: string\n errors?: string[]\n usage?: unknown\n usageByModel?: ByModel\n costUsd?: number\n }\n | { type: 'permission_requested'; request: PermissionRequest }\n | {\n type: 'permission_resolved'\n requestId: string\n behavior: 'allow' | 'deny'\n resolvedBy: PermissionDecisionSource\n message?: string\n }\n | {\n type: 'execution_dispatched'\n executionId: string\n toolName: string\n backend: ToolExecutionBackend\n deferred?: boolean\n expiresAt?: number\n }\n | {\n type: 'execution_result'\n executionId: string\n output: ToolExecutionOutput\n logs?: string[]\n durationMs?: number\n }\n | {\n type: 'execution_failed'\n executionId: string\n reason: string\n error: string\n logs?: string[]\n durationMs?: number\n }\n | { type: 'file_delivered'; path: string; bytes: number; description?: string }\n | { type: 'sdk_event'; payload: { type: string; [key: string]: unknown } }\n | { type: 'session_error'; message: string }\n | { type: 'session_closed'; reason: 'client' | 'server' | 'error' }\n\nexport type SessionEvent = SessionEventBody & {\n seq: number\n ts: number\n}\n\nexport type SessionCommand =\n | {\n type: 'user_message'\n text: string\n attachmentIds?: string[]\n }\n | {\n type: 'permission_decision'\n requestId: string\n behavior: 'allow' | 'deny'\n updatedInput?: Record<string, unknown>\n message?: string\n interrupt?: boolean\n }\n | { type: 'interrupt' }\n | { type: 'clear_context' }\n | { type: 'set_permission_mode'; mode: PermissionMode }\n | { type: 'set_model'; model?: string }\n | {\n type: 'tool_call_result'\n executionId: string\n output: ToolExecutionOutput\n logs?: string[]\n }\n | {\n type: 'tool_call_error'\n executionId: string\n reason: string\n error: string\n logs?: string[]\n }\n | { type: 'shell_command'; command: string }\n | { type: 'close' }\n\nexport const SHELL_COMMAND_MAX = 4000\n\nexport type AttachedFrame = {\n type: 'attached'\n protocolVersion: number\n session: SessionInfo\n replayingFrom: number\n // Whether this principal may run `!` commands on this session: server config x operator x hostCwd.\n // Additive, so no PROTOCOL_VERSION bump; an older gateway omits it and the client never offers the mode.\n shell?: boolean\n // The operator's rate overrides alone, never the bundled table: a client merges them over its own\n // `DEFAULT_PRICING` so what it prices for itself matches what this gateway priced. Additive, and an\n // older gateway omits it, which is the same thing as having no overrides.\n pricingOverrides?: PricingOverrides\n}\n\nexport type ToolCallRequestFrame = {\n type: 'tool_call_request'\n executionId: string\n toolName: string\n input: unknown\n vfsSeed?: Record<string, string>\n limits?: { timeoutMs?: number; memoryLimitBytes?: number }\n expiresAt?: number\n}\n\nexport type ServerFrame =\n | AttachedFrame\n | { type: 'event'; event: SessionEvent }\n | ToolCallRequestFrame\n | { type: 'tool_call_canceled'; executionId: string; reason: string }\n | { type: 'protocol_error'; message: string }\n\nexport type ClientFrame = SessionCommand\n\nexport type ProfileDefaults = {\n model?: string\n permissionMode?: PermissionMode\n}\n\nexport type ProfileEngine = 'claude' | 'codex' | 'provider'\n\nexport type EngineCapabilities = {\n interactiveApprovals: boolean\n permissionModes: readonly PermissionMode[]\n defaultPermissionMode: PermissionMode\n resume: boolean\n resumeBackfill: boolean\n listSessions: boolean\n contextUsage: boolean\n rateLimits: boolean\n mcpStatus: boolean\n mcpServerActions: boolean\n sessionMcpServers: boolean\n slashCommands: boolean\n clearContext?: boolean\n skillsList: boolean\n settingSources: boolean\n budgets: boolean\n attachments: ReadonlyArray<'image' | 'pdf' | 'text'>\n reasoningEfforts?: readonly string[]\n vfs: boolean\n hostCwd?: boolean\n streaming: 'token' | 'item' | 'none'\n}\n\nexport const ENGINE_CAPABILITIES: Record<ProfileEngine, EngineCapabilities> = {\n claude: {\n interactiveApprovals: true,\n permissionModes: ['default', 'acceptEdits', 'bypassPermissions', 'plan', 'dontAsk', 'auto'],\n defaultPermissionMode: 'default',\n resume: true,\n resumeBackfill: true,\n listSessions: true,\n contextUsage: true,\n rateLimits: true,\n mcpStatus: true,\n mcpServerActions: true,\n sessionMcpServers: true,\n slashCommands: true,\n clearContext: true,\n skillsList: false,\n settingSources: true,\n budgets: true,\n attachments: ['image', 'pdf', 'text'],\n reasoningEfforts: ['low', 'medium', 'high', 'xhigh', 'max'],\n vfs: false,\n hostCwd: true,\n streaming: 'token',\n },\n codex: {\n interactiveApprovals: true,\n permissionModes: ['default', 'acceptEdits', 'bypassPermissions', 'auto'],\n defaultPermissionMode: 'default',\n resume: true,\n resumeBackfill: true,\n listSessions: true,\n contextUsage: true,\n rateLimits: true,\n mcpStatus: true,\n mcpServerActions: false,\n sessionMcpServers: false,\n slashCommands: false,\n clearContext: true,\n skillsList: true,\n settingSources: false,\n budgets: false,\n attachments: ['image', 'text'],\n reasoningEfforts: ['minimal', 'low', 'medium', 'high', 'xhigh'],\n vfs: false,\n hostCwd: true,\n streaming: 'token',\n },\n provider: {\n interactiveApprovals: false,\n permissionModes: ['default', 'bypassPermissions', 'dontAsk'],\n defaultPermissionMode: 'default',\n resume: false,\n resumeBackfill: false,\n listSessions: false,\n contextUsage: false,\n rateLimits: false,\n mcpStatus: true,\n mcpServerActions: false,\n sessionMcpServers: false,\n slashCommands: false,\n clearContext: true,\n skillsList: false,\n settingSources: false,\n budgets: false,\n attachments: ['image', 'pdf', 'text'],\n vfs: true,\n hostCwd: false,\n streaming: 'token',\n },\n}\n\nexport function supportsPermissionMode(engine: ProfileEngine | undefined, mode: PermissionMode): boolean {\n return ENGINE_CAPABILITIES[engine ?? 'claude'].permissionModes.includes(mode)\n}\n\nexport type ProviderConfig = {\n id: string\n model?: string\n models?: string[]\n baseUrl?: string\n apiKeyEnv?: string\n}\n\nexport type SessionCapability = 'web_search' | 'download' | 'web_fetch' | 'deliver_file'\n\nexport type ProfileSessionDefaults = {\n capabilities?: SessionCapability[]\n mcpServers?: string[]\n instructions?: string\n}\n\nexport type ProfileUsageWindow = {\n info: RateLimitInfo\n updatedAt: number\n inferredReset?: boolean\n}\n\nexport type ProfileUsage = Record<string, ProfileUsageWindow>\n\nexport type ProfileInfo = {\n name: string\n engine?: ProfileEngine\n configDir?: string\n codexHome?: string\n provider?: ProviderConfig\n description?: string\n defaults?: ProfileDefaults\n session?: ProfileSessionDefaults\n models?: ModelOption[]\n defaultModel?: string\n capabilities?: EngineCapabilities\n available?: boolean\n unavailableReason?: string\n usage?: ProfileUsage\n spend?: ProfileSpend\n managed?: boolean\n}\n\nexport type ProfileConfigSnapshot = {\n settings?: {\n model?: string\n defaultPermissionMode?: string\n permissionRules?: { allow: number; ask: number; deny: number }\n envKeys?: string[]\n hooks?: string[]\n }\n hasUserMemory: boolean\n skills: string[]\n agents: string[]\n commands: string[]\n}\n\nexport type McpServerConfigWire =\n | { type?: 'stdio'; command: string; args?: string[]; env?: Record<string, string> }\n | { type: 'http'; url: string; headers?: Record<string, string> }\n | { type: 'sse'; url: string; headers?: Record<string, string> }\n\nexport type McpServerToolInfo = {\n name: string\n title?: string\n description?: string\n annotations?: { readOnly?: boolean; destructive?: boolean; openWorld?: boolean }\n inputSchema?: unknown\n}\n\nexport type McpServerStatusInfo = {\n name: string\n status: string\n scope?: string\n error?: string\n serverInfo?: { name: string; version: string }\n transport?: 'stdio' | 'http' | 'sse' | 'sdk'\n command?: string\n args?: string[]\n url?: string\n tools?: McpServerToolInfo[]\n}\n\nexport type McpServersResponse = { servers: McpServerStatusInfo[] }\n\nexport type McpServerActionRequest = { action: 'reconnect' | 'enable' | 'disable' }\n\nexport type UploadAttachmentResponse = { attachment: MessageAttachment }\n\nexport type CreateSessionRequest = {\n cwd?: string\n profile?: string\n prompt?: string\n permissionMode?: PermissionMode\n allowDangerouslySkipPermissions?: boolean\n allowedTools?: string[]\n disallowedTools?: string[]\n mcpServers?: Record<string, McpServerConfigWire>\n settingSources?: Array<'user' | 'project' | 'local'>\n model?: string\n maxTurns?: number\n maxBudgetUsd?: number\n resume?: string\n forkSession?: boolean\n reasoningEffort?: string\n includePartialMessages?: boolean\n // Overrides the gateway's default. null (or 0) means a prompt never expires - it waits as long as the session lives.\n approvalTimeoutMs?: number | null\n questionBehavior?: QuestionBehavior\n capabilities?: SessionCapability[]\n meta?: Record<string, unknown>\n scope?: Record<string, string>\n}\n\nexport type SubagentInfo = {\n toolUseId: string\n agentType?: string\n description?: string\n // Set by an engine whose every record is a delegated agent, however it was named. Codex runs\n // each one as its own thread and often has no name for it, so presence of `agentType` cannot\n // be the test. Additive, so no `PROTOCOL_VERSION` bump.\n isAgent?: boolean\n status: 'running' | 'done' | 'failed'\n startedAt: number\n toolCount: number\n}\n\nexport const SUBAGENT_HISTORY = 8\n\n// Widening this union costs a PROTOCOL_VERSION bump: Swift decodes it strictly.\nexport type ChecklistStatus = 'pending' | 'in_progress' | 'completed'\n\nexport type ChecklistItem = { text: string; status: ChecklistStatus }\n\nexport const CHECKLIST_TEXT_MAX = 200\n\nexport type ProjectIcon = { type: 'glyph'; name: string } | { type: 'image'; mediaType: 'image/png' | 'image/svg+xml'; hash: string }\n\nexport type ProjectInfo = {\n name: string\n root: string\n icon?: ProjectIcon\n shortcode?: string\n}\n\n// Who wrote a `user_message` when it was not the person at the keyboard. Absent means the human;\n// `peer` is another session on this or a sibling gateway, delivered through the peer tools.\nexport type MessageOrigin = {\n kind: 'peer'\n sessionId: string\n name?: string\n engine?: ProfileEngine\n hostId?: string\n hops?: string[]\n}\n\n// `peers_send` answers the model in prose, not in a structured result, so the recipient's name only\n// ever reaches a client inside that sentence. Both sides go through this pair rather than each\n// inventing a format: the engine writes the line, the transcript reads the name back out of it.\nexport function peerDeliveredPrefix(sessionId: string, name?: string): string {\n return `Delivered to ${name ? `${name} (${sessionId})` : sessionId}`\n}\n\nexport function peerDeliveredTo(text: string): { sessionId: string; name?: string } | undefined {\n const named = /^Delivered to (.+) \\(([^()]+)\\);/.exec(text)\n if (named) {\n return { sessionId: named[2]!, name: named[1]! }\n }\n const bare = /^Delivered to ([^()\\s]+);/.exec(text)\n return bare ? { sessionId: bare[1]! } : undefined\n}\n\nexport type SessionInfo = {\n id: string\n sdkSessionId?: string\n status: SessionStatus\n cwd: string\n profile?: string\n engine?: ProfileEngine\n capabilities?: EngineCapabilities\n model?: string\n permissionMode?: PermissionMode\n canBypassPermissions?: boolean\n apiKeySource?: string\n createdAt: number\n lastSeq: number\n // Which log the seqs belong to. A dormant wake starts a fresh log and bumps it, so a `seq`\n // that outlived one - a notification sitting on a lock screen - can be told from a live one.\n // Absent from a gateway that predates it, and from a session that has never woken; additive,\n // so no `PROTOCOL_VERSION` bump, and a reader that finds it absent on either side must keep\n // trusting the seq.\n epoch?: number\n pendingPermissionCount: number\n subagents?: SubagentInfo[]\n checklist?: ChecklistItem[]\n meta?: Record<string, unknown>\n title?: string\n totalCostUsd?: number\n costUsd?: number\n usageByModel?: ByModel\n numTurns?: number\n activityCount?: number\n // Rows of the kind a person is actually waiting to read - see `transcriptProse`.\n // Absent from a gateway that predates it - additive, so no `PROTOCOL_VERSION` bump -\n // which is why every reader falls back to `activityCount`. This is the badge's number; `activityCount` stays the \"has\n // anything happened at all\" measure that sorting and dormancy read.\n proseCount?: number\n lastActivityAt?: number\n contextUsage?: ContextReading\n scope?: Record<string, string>\n project?: ProjectInfo\n}\n\nexport function contextReading(body: SessionEventBody): ContextReading | undefined {\n if (body.type !== 'context_usage') {\n return undefined\n }\n const { totalTokens, maxTokens, percentage } = body.usage\n return { totalTokens, maxTokens, percentage }\n}\n\nexport function transcriptActivity(body: SessionEventBody): number {\n if ('parentToolUseId' in body && body.parentToolUseId != null) {\n return 0\n }\n switch (body.type) {\n case 'assistant_message': {\n const content = body.message.content\n if (typeof content === 'string') {\n return content.trim() === '' ? 0 : 1\n }\n const rows = content.filter((block) => block.type === 'text' || block.type === 'thinking' || block.type === 'tool_use').length\n return rows\n }\n case 'user_message': {\n return body.synthetic ? 0 : 1\n }\n case 'turn_result':\n case 'file_delivered':\n case 'session_error': {\n return 1\n }\n default: {\n return 0\n }\n }\n}\n\n// The narrower door beside transcriptActivity: output addressed to the human, not evidence of work.\n// A `user_message` the human typed is deliberately absent: they wrote it, so it can never be unread by\n// them, and counting it badged the sender's own prompt whenever they navigated away before the list next\n// polled. One with an `origin` is the opposite case - a peer wrote it, the human has not seen it.\nexport function transcriptProse(body: SessionEventBody): number {\n if ('parentToolUseId' in body && body.parentToolUseId != null) {\n return 0\n }\n switch (body.type) {\n case 'user_message': {\n return body.origin && !body.synthetic ? 1 : 0\n }\n case 'assistant_message': {\n const content = body.message.content\n if (typeof content === 'string') {\n return content.trim() === '' ? 0 : 1\n }\n return content.filter((block) => block.type === 'text' && typeof block.text === 'string' && block.text.trim() !== '').length\n }\n case 'turn_result': {\n return body.isError ? 1 : 0\n }\n case 'file_delivered':\n case 'session_error': {\n return 1\n }\n default: {\n return 0\n }\n }\n}\n\nexport function transcriptContent(body: SessionEventBody): boolean {\n switch (body.type) {\n case 'user_message':\n case 'assistant_message':\n case 'stream_delta':\n case 'turn_result':\n case 'execution_dispatched':\n case 'execution_result':\n case 'execution_failed':\n case 'file_delivered':\n case 'session_error':\n case 'session_closed':\n case 'conversation_reset':\n case 'context_compacted': {\n return true\n }\n default: {\n return false\n }\n }\n}\n\nexport function replayCoalesceKey(body: SessionEventBody): string | undefined {\n switch (body.type) {\n case 'context_usage': {\n return 'context_usage'\n }\n case 'rate_limit': {\n return body.info.rateLimitType ? `rate_limit:${body.info.rateLimitType}` : undefined\n }\n case 'status_changed': {\n return 'status_changed'\n }\n case 'context_compacted': {\n return `context_compacted:${body.uuid}`\n }\n case 'checklist': {\n return 'checklist'\n }\n case 'sdk_event': {\n return body.payload.type === 'system' && body.payload.subtype === 'status' ? 'sdk_event:system:status' : undefined\n }\n default: {\n return undefined\n }\n }\n}\n\nexport function replayRetains(body: SessionEventBody): boolean {\n if (body.type !== 'stream_delta') {\n return true\n }\n const delta = body.event as { type?: string; delta?: { type?: string } }\n if (delta.type !== 'content_block_delta') {\n return false\n }\n return delta.delta?.type === 'text_delta' || delta.delta?.type === 'thinking_delta'\n}\n\nexport function snapshotRetains(body: SessionEventBody): boolean {\n return body.type !== 'stream_delta'\n}\n\nexport type SdkSessionSummary = {\n sessionId: string\n summary: string\n lastModified: number\n createdAt?: number\n customTitle?: string\n firstPrompt?: string\n gitBranch?: string\n cwd?: string\n}\n\nexport type SessionFileInfo = { path: string; bytes: number }\nexport type ListSessionFilesResponse = { files: SessionFileInfo[] }\nexport type ListSessionsResponse = { sessions: SessionInfo[] }\nexport type CreateSessionResponse = { session: SessionInfo }\nexport type GetSessionResponse = { session: SessionInfo }\n\nexport type UpdateSessionRequest = { title?: string | null }\nexport type UpdateSessionResponse = { session: SessionInfo }\n\nexport type ResolvePermissionRequest =\n | { behavior: 'allow'; updatedInput?: Record<string, unknown> }\n | { behavior: 'deny'; message?: string; interrupt?: boolean }\nexport type ResolvePermissionResponse = { resolved: true }\n\nexport type SubmitExecutionResultRequest =\n | { status: 'ok'; output: ToolExecutionOutput; logs?: string[] }\n | { status: 'failed'; reason: string; error: string; logs?: string[] }\nexport type SubmitExecutionResultResponse = {\n applied: boolean\n sessionId: string\n}\n\nexport type ListSdkSessionsResponse = { sdkSessions: SdkSessionSummary[] }\nexport type ListProfilesResponse = {\n profiles: ProfileInfo[]\n canManage?: boolean\n}\n\nexport type CreateProfileRequest = ProfileInfo\n\nexport type UpdateProfileRequest = Omit<Partial<ProfileInfo>, 'name'>\n\nexport type HostFileRoot = {\n path: string\n name: string\n}\n\nexport type ListHostRootsResponse = {\n roots: HostFileRoot[]\n canWrite: boolean\n}\n\nexport type HostDirEntry = {\n name: string\n path: string\n type: 'file' | 'dir' | 'symlink' | 'other'\n bytes?: number\n modifiedAt?: number\n}\n\nexport type ListHostDirResponse = {\n path: string\n entries: HostDirEntry[]\n truncated?: boolean\n}\n\nexport type HostFileMatch = {\n path: string\n relative: string\n}\n\nexport type FindHostFilesResponse = {\n base: string\n matches: HostFileMatch[]\n truncated: boolean\n}\n\nexport type ReadHostFileResponse = {\n path: string\n content: string\n encoding: 'utf8' | 'base64'\n bytes: number\n hash: string\n modifiedAt: number\n}\n\nexport type WriteHostFileRequest = {\n path: string\n content: string\n encoding?: 'utf8' | 'base64'\n expectedHash?: string\n}\n\nexport type WriteHostFileResponse = {\n path: string\n bytes: number\n hash: string\n modifiedAt: number\n}\n\nexport type SaveProfileResponse = { profile: ProfileInfo }\nexport type GetProfileResponse = { profile: ProfileInfo; config: ProfileConfigSnapshot }\nexport type ErrorResponse = { error: string }\n\nexport type SessionNotificationType = 'permission_requested' | 'turn_completed' | 'session_error' | 'session_closed'\n\nexport type SessionNotification = {\n type: SessionNotificationType\n sessionId: string\n session: SessionInfo\n seq: number\n ts: number\n preview?: string\n request?: PermissionRequest\n result?: { isError: boolean; durationMs: number; numTurns: number; totalCostUsd: number }\n reason?: 'client' | 'server' | 'error'\n}\n\nexport type SessionWebhookConfig = {\n url: string\n headers?: Record<string, string>\n events?: SessionNotificationType[]\n}\n\nexport type JobStatus = 'queued' | 'running' | 'parked' | 'succeeded' | 'failed' | 'canceled'\n\nexport type WebhookConfig = {\n url: string\n headers?: Record<string, string>\n progress?: 'messages' | 'completion'\n}\n\nexport type CreateJobRequest = {\n session: CreateSessionRequest & { prompt: string }\n webhook?: WebhookConfig\n maxTokens?: number\n maxDurationMs?: number\n attempts?: number\n retryDelayMs?: number\n meta?: Record<string, unknown>\n}\n\nexport type JobUsage = {\n tokens: number\n totalCostUsd: number\n numTurns: number\n costUsd?: number\n}\n\nexport type JobResult = {\n subtype: string\n isError: boolean\n result?: string\n errors?: string[]\n durationMs: number\n}\n\nexport type JobInfo = {\n id: string\n status: JobStatus\n cwd: string\n profile?: string\n prompt: string\n sessionId?: string\n sdkSessionId?: string\n createdAt: number\n startedAt?: number\n finishedAt?: number\n attempt?: number\n maxAttempts?: number\n nextRunAt?: number\n parkedAt?: number\n parkedExecutionId?: string\n usage: JobUsage\n result?: JobResult\n error?: string\n meta?: Record<string, unknown>\n scope?: Record<string, string>\n}\n\nexport type JobProgress = {\n kind: 'assistant_text' | 'tool_use' | 'permission_requested' | 'permission_resolved'\n preview?: string\n request?: PermissionRequest\n}\n\nexport type JobEvent =\n | { type: 'job_submitted'; job: JobInfo; ts: number }\n | { type: 'job_started'; job: JobInfo; ts: number }\n | { type: 'job_progress'; job: JobInfo; progress: JobProgress; ts: number }\n | { type: 'job_parked'; job: JobInfo; executionId: string; ts: number }\n | { type: 'job_resumed'; job: JobInfo; executionId: string; ts: number }\n | { type: 'job_retrying'; job: JobInfo; ts: number }\n | { type: 'job_completed'; job: JobInfo; ts: number }\n\nexport type QueueStats = {\n maxConcurrency: number\n running: number\n queued: number\n parked: number\n sessionTokenLimit?: number\n dailyTokenLimit?: number\n dailyTokensUsed: number\n paused: boolean\n}\n\nexport type QueueServerFrame =\n | { type: 'queue_attached'; protocolVersion: number; stats: QueueStats }\n | { type: 'job_event'; event: JobEvent }\n | { type: 'queue_stats'; stats: QueueStats }\n\nexport type CreateJobResponse = { job: JobInfo }\nexport type GetJobResponse = { job: JobInfo }\nexport type ListJobsResponse = { jobs: JobInfo[] }\nexport type QueueStatsResponse = { stats: QueueStats }\n\nexport * from './checklist.ts'\nexport * from './pricing.ts'\nexport * from './peer-mentions.ts'\nexport * from './session-list.ts'\nexport * from './tool-titles.ts'\nexport * from './usage.ts'\nexport * from './watermarks.ts'\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@workerdeck/protocol",
3
- "version": "2.10.0",
3
+ "version": "2.12.0",
4
4
  "type": "module",
5
5
  "description": "The WorkerDeck wire protocol: typed session events, commands, and REST shapes shared by server and clients. Dependency-free, browser-safe. This protocol is the product boundary - versioned from day one.",
6
6
  "license": "MIT",