@khorsheed/dsh-file-preview 0.1.1 → 0.2.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/CHANGELOG.md +8 -0
- package/README.en.md +15 -11
- package/README.i18n.yaml +2 -2
- package/README.md +31 -27
- package/lib/index.js +99 -46
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/typert.host.js +124 -44
- package/lib/typert.remote-client.d.ts.map +1 -1
- package/lib/typert.remote-client.js +4 -4
- package/lib/types/bash-writes.js +1 -1
- package/lib/types/fold.d.ts +8 -6
- package/lib/types/fold.d.ts.map +1 -1
- package/lib/types/fold.js +41 -18
- package/lib/types/index.d.ts +26 -8
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/index.js +81 -25
- package/package.json +14 -13
package/lib/typert.host.js
CHANGED
|
@@ -93,7 +93,7 @@ export const TYPERT = {
|
|
|
93
93
|
typeSymbol: '@khorsheed/dsh-file-preview/types#FilePreviewList',
|
|
94
94
|
schema: _khorsheed_dsh_file_preview_filePreview_list_result$schema,
|
|
95
95
|
},
|
|
96
|
-
sourceLocation: {"file":"packages/file-preview/src/index.ts","line":
|
|
96
|
+
sourceLocation: {"file":"packages/file-preview/src/index.ts","line":368,"column":9},
|
|
97
97
|
},
|
|
98
98
|
{
|
|
99
99
|
id: '@khorsheed/dsh-file-preview#filePreview/read',
|
|
@@ -134,7 +134,7 @@ export const TYPERT = {
|
|
|
134
134
|
typeSymbol: '@khorsheed/dsh-file-preview/types#FilePreviewRead',
|
|
135
135
|
schema: _khorsheed_dsh_file_preview_filePreview_read_result$schema,
|
|
136
136
|
},
|
|
137
|
-
sourceLocation: {"file":"packages/file-preview/src/index.ts","line":
|
|
137
|
+
sourceLocation: {"file":"packages/file-preview/src/index.ts","line":458,"column":9},
|
|
138
138
|
},
|
|
139
139
|
{
|
|
140
140
|
id: '@khorsheed/dsh-file-preview#filePreview/reveal',
|
|
@@ -175,7 +175,7 @@ export const TYPERT = {
|
|
|
175
175
|
typeSymbol: '@khorsheed/dsh-file-preview/types#FilePreviewReveal',
|
|
176
176
|
schema: _khorsheed_dsh_file_preview_filePreview_reveal_result$schema,
|
|
177
177
|
},
|
|
178
|
-
sourceLocation: {"file":"packages/file-preview/src/index.ts","line":
|
|
178
|
+
sourceLocation: {"file":"packages/file-preview/src/index.ts","line":535,"column":9},
|
|
179
179
|
},
|
|
180
180
|
{
|
|
181
181
|
id: '@khorsheed/dsh-file-preview#filePreview/turnFiles',
|
|
@@ -205,32 +205,32 @@ export const TYPERT = {
|
|
|
205
205
|
typeSymbol: '@khorsheed/dsh-file-preview/types#FilePreviewTurnMap',
|
|
206
206
|
schema: _khorsheed_dsh_file_preview_filePreview_turnFiles_result$schema,
|
|
207
207
|
},
|
|
208
|
-
sourceLocation: {"file":"packages/file-preview/src/index.ts","line":
|
|
208
|
+
sourceLocation: {"file":"packages/file-preview/src/index.ts","line":405,"column":9},
|
|
209
209
|
},
|
|
210
210
|
],
|
|
211
211
|
model: {
|
|
212
212
|
"services": [
|
|
213
213
|
{
|
|
214
|
-
"description": "The `filePreview` Remote service: session-scoped read-only file inspection for web surfaces. `list` is a
|
|
214
|
+
"description": "The `filePreview` Remote service: session-scoped read-only file inspection for web surfaces. `list` is a fold over the session log, then filtered to the paths that still exist on disk (resolved against the session cwd and stat-ed per call); `read` resolves the path against the session cwd and serves current text content through `ctx.fs` (or a browser URL for images), capped by config. Image bytes ride a dedicated host route so the browser loads them natively without bloating the RPC channel.",
|
|
215
215
|
"summary": "The `filePreview` Remote service: session-scoped read-only file inspection for web surfaces.",
|
|
216
216
|
"tags": [],
|
|
217
|
-
"jsDoc": "/**\n * The `filePreview` Remote service: session-scoped read-only file inspection\n * for web surfaces. `list` is a
|
|
217
|
+
"jsDoc": "/**\n * The `filePreview` Remote service: session-scoped read-only file inspection\n * for web surfaces. `list` is a fold over the session log, then filtered to the\n * paths that still exist on disk (resolved against the session cwd and stat-ed\n * per call); `read` resolves the path against the session cwd and serves current\n * text content through `ctx.fs` (or a browser URL for images), capped by\n * config. Image bytes ride a dedicated host route so the browser loads them\n * natively without bloating the RPC channel.\n */",
|
|
218
218
|
"key": "filePreview",
|
|
219
219
|
"exportName": "FilePreviewService",
|
|
220
220
|
"members": [
|
|
221
221
|
{
|
|
222
222
|
"kind": "method",
|
|
223
223
|
"name": "list",
|
|
224
|
-
"signature": "@Remote('list') list(agent: Agent): FilePreviewList",
|
|
224
|
+
"signature": "@Remote('list') async list(agent: Agent): Promise<FilePreviewList>",
|
|
225
225
|
"summary": "List the files one session wrote or edited: the log fold plus any bash-written files the collector verified (the S2 seam), merged so a captured path the fold already knows keeps its log-derived entry.",
|
|
226
|
-
"jsDoc": "/**\n * List the files one session wrote or edited: the log fold plus any\n * bash-written files the collector verified (the S2 seam), merged so a\n * captured path the fold already knows keeps its log-derived entry.\n * @param agent - owning live agent; its session log is the data source.\n * @returns first-seen files capped by `maxFiles`, with the log watermark.\n */"
|
|
226
|
+
"jsDoc": "/**\n * List the files one session wrote or edited: the log fold plus any\n * bash-written files the collector verified (the S2 seam), merged so a\n * captured path the fold already knows keeps its log-derived entry. Only\n * paths that currently exist on disk are returned — a file the session\n * wrote and later deleted is history, not a product.\n * @param agent - owning live agent; its session log is the data source.\n * @returns existing first-seen files capped by `maxFiles`, with the log watermark.\n */"
|
|
227
227
|
},
|
|
228
228
|
{
|
|
229
229
|
"kind": "method",
|
|
230
230
|
"name": "turnFiles",
|
|
231
|
-
"signature": "@Remote('turnFiles') turnFiles(agent: Agent): FilePreviewTurnMap",
|
|
231
|
+
"signature": "@Remote('turnFiles') async turnFiles(agent: Agent): Promise<FilePreviewTurnMap>",
|
|
232
232
|
"summary": "Every turn's file mutations for the turn-tail card — the single source of truth the card renders (the client's old write/edit-only fold retired).",
|
|
233
|
-
"jsDoc": "/**\n * Every turn's file mutations for the turn-tail card — the single source of\n * truth the card renders (the client's old write/edit-only fold retired).\n * Built by folding the session log per turn (write/edit calls, Code Mode\n * dispatches borrowing the root call's turn, and render-intent paths from\n * result diff meta) and merging the collector's bash-written captures by\n * their own turn. The fold is cached per session and invalidated by the log\n * watermark, so repeated card fetches do not refold. A path touched in two\n * turns appears in BOTH turn groups — per-turn attribution is exact.\n * @param agent - owning live agent; its session log is the data source.\n * @returns per-turn file groups plus the scanned watermark.\n */"
|
|
233
|
+
"jsDoc": "/**\n * Every turn's file mutations for the turn-tail card — the single source of\n * truth the card renders (the client's old write/edit-only fold retired).\n * Built by folding the session log per turn (write/edit calls, Code Mode\n * dispatches borrowing the root call's turn, and render-intent paths from\n * result diff meta) and merging the collector's bash-written captures by\n * their own turn. The fold is cached per session and invalidated by the log\n * watermark, so repeated card fetches do not refold. A path touched in two\n * turns appears in BOTH turn groups — per-turn attribution is exact. Only\n * paths that currently exist on disk are returned (a deleted temp script is\n * history, not a product); existence is probed fresh on every call, so the\n * cached fold is filtered per request rather than cached.\n * @param agent - owning live agent; its session log is the data source.\n * @returns existing per-turn file groups plus the scanned watermark.\n */"
|
|
234
234
|
},
|
|
235
235
|
{
|
|
236
236
|
"kind": "method",
|
|
@@ -256,9 +256,13 @@ export const TYPERT = {
|
|
|
256
256
|
"name": "AgentCancelCause",
|
|
257
257
|
"declaration": "export type AgentCancelCause = { readonly kind: 'user'; } | { readonly kind: 'parent'; } | { readonly kind: 'hook'; readonly reason: string; } | { readonly kind: 'disposed'; };"
|
|
258
258
|
},
|
|
259
|
+
{
|
|
260
|
+
"name": "AgentMessageSource",
|
|
261
|
+
"declaration": "export interface AgentMessageSource {\n readonly kind: 'agent-message';\n readonly form: 'relay';\n readonly senderSessionId: SessionId;\n}"
|
|
262
|
+
},
|
|
259
263
|
{
|
|
260
264
|
"name": "AgentOptions",
|
|
261
|
-
"declaration": "export interface AgentOptions {\n provider?: string;\n model?: string;\n maxTokens?: number;\n subagentDepth?: number;\n}"
|
|
265
|
+
"declaration": "export interface AgentOptions {\n provider?: string;\n model?: string;\n reasoningEffort?: ReasoningEffortId;\n maxTokens?: number;\n subagentDepth?: number;\n}"
|
|
262
266
|
},
|
|
263
267
|
{
|
|
264
268
|
"name": "AgentStatus",
|
|
@@ -293,21 +297,13 @@ export const TYPERT = {
|
|
|
293
297
|
"declaration": "export type Branded<B extends string> = string & { readonly [BRAND]: B; };"
|
|
294
298
|
},
|
|
295
299
|
{
|
|
296
|
-
"name": "
|
|
297
|
-
"declaration": "export type
|
|
300
|
+
"name": "BrandedNumber",
|
|
301
|
+
"declaration": "export type BrandedNumber<B extends string> = number & { readonly [BRAND]: B; };"
|
|
298
302
|
},
|
|
299
303
|
{
|
|
300
304
|
"name": "CancelOptions",
|
|
301
305
|
"declaration": "export interface CancelOptions {\n keepInbox?: boolean | undefined;\n}"
|
|
302
306
|
},
|
|
303
|
-
{
|
|
304
|
-
"name": "CodeDispatchEventData",
|
|
305
|
-
"declaration": "export interface CodeDispatchEventData extends CodeDispatchStartEventData {\n isError: boolean;\n content: ContentBlock[];\n}"
|
|
306
|
-
},
|
|
307
|
-
{
|
|
308
|
-
"name": "CodeDispatchStartEventData",
|
|
309
|
-
"declaration": "export interface CodeDispatchStartEventData {\n rootCallId: CallId;\n parentCallId: CallId;\n subCallId: CallId;\n name: string;\n arguments: unknown;\n}"
|
|
310
|
-
},
|
|
311
307
|
{
|
|
312
308
|
"name": "CommandId",
|
|
313
309
|
"declaration": "export type CommandId = Branded<'CommandId'>;"
|
|
@@ -342,11 +338,7 @@ export const TYPERT = {
|
|
|
342
338
|
},
|
|
343
339
|
{
|
|
344
340
|
"name": "ContinuableSubagentDescriptorData",
|
|
345
|
-
"declaration": "export interface ContinuableSubagentDescriptorData extends SubagentDescriptorBase {\n readonly mode: 'continuable';\n readonly label: string;\n readonly agentProvider?: string;\n readonly agentModel?: string;\n readonly persona?: string;\n readonly toolFilter?: ToolRestriction;\n}"
|
|
346
|
-
},
|
|
347
|
-
{
|
|
348
|
-
"name": "CoordinatorMessageSource",
|
|
349
|
-
"declaration": "export interface CoordinatorMessageSource {\n readonly kind: 'coordinator';\n readonly form: 'relay';\n readonly senderSessionId: SessionId;\n}"
|
|
341
|
+
"declaration": "export interface ContinuableSubagentDescriptorData extends SubagentDescriptorBase {\n readonly mode: 'continuable';\n readonly label: string;\n readonly agentProvider?: string;\n readonly agentModel?: string;\n readonly agentReasoningEffort?: ReasoningEffortId;\n readonly persona?: string;\n readonly toolFilter?: ToolRestriction;\n}"
|
|
350
342
|
},
|
|
351
343
|
{
|
|
352
344
|
"name": "EpochHeader",
|
|
@@ -450,7 +442,7 @@ export const TYPERT = {
|
|
|
450
442
|
},
|
|
451
443
|
{
|
|
452
444
|
"name": "MessageSourceMap",
|
|
453
|
-
"declaration": "export interface MessageSourceMap {\n user: { kind: 'user'; };\n plugin: { kind: 'plugin'; plugin: string; } & ContextFormed;\n model: ModelMessageSource;\n tool: ToolMessageSource;\n
|
|
445
|
+
"declaration": "export interface MessageSourceMap {\n user: { kind: 'user'; };\n plugin: { kind: 'plugin'; plugin: string; } & ContextFormed;\n model: ModelMessageSource;\n tool: ToolMessageSource;\n 'agent-message': AgentMessageSource;\n 'subagent-settled': SubagentSettledMessageSource;\n}"
|
|
454
446
|
},
|
|
455
447
|
{
|
|
456
448
|
"name": "ModelMessageSource",
|
|
@@ -464,6 +456,14 @@ export const TYPERT = {
|
|
|
464
456
|
"name": "ProviderRequestId",
|
|
465
457
|
"declaration": "export type ProviderRequestId = Branded<'ProviderRequestId'>;"
|
|
466
458
|
},
|
|
459
|
+
{
|
|
460
|
+
"name": "PtcDispatchEventData",
|
|
461
|
+
"declaration": "export interface PtcDispatchEventData extends PtcDispatchStartEventData {\n isError: boolean;\n content: ContentBlock[];\n}"
|
|
462
|
+
},
|
|
463
|
+
{
|
|
464
|
+
"name": "PtcDispatchStartEventData",
|
|
465
|
+
"declaration": "export interface PtcDispatchStartEventData {\n rootCallId: ToolCallId;\n parentCallId: ToolCallId;\n subCallId: ToolCallId;\n name: string;\n arguments: unknown;\n}"
|
|
466
|
+
},
|
|
467
467
|
{
|
|
468
468
|
"name": "ReasoningBlock",
|
|
469
469
|
"declaration": "export interface ReasoningBlock {\n type: 'reasoning';\n text: string;\n}"
|
|
@@ -482,7 +482,63 @@ export const TYPERT = {
|
|
|
482
482
|
},
|
|
483
483
|
{
|
|
484
484
|
"name": "RequestHeaderReason",
|
|
485
|
-
"declaration": "export type RequestHeaderReason = 'initial' | 'resume' | 'change';"
|
|
485
|
+
"declaration": "export type RequestHeaderReason = 'initial' | 'resume' | 'change' | 'series';"
|
|
486
|
+
},
|
|
487
|
+
{
|
|
488
|
+
"name": "RoomCreatedEvent",
|
|
489
|
+
"declaration": "export interface RoomCreatedEvent {\n readonly version: 1;\n}"
|
|
490
|
+
},
|
|
491
|
+
{
|
|
492
|
+
"name": "RoomDispatchEvent",
|
|
493
|
+
"declaration": "export interface RoomDispatchEvent {\n readonly targets: readonly string[];\n readonly text: string;\n}"
|
|
494
|
+
},
|
|
495
|
+
{
|
|
496
|
+
"name": "RoomGoalEvent",
|
|
497
|
+
"declaration": "export interface RoomGoalEvent {\n readonly text: string;\n}"
|
|
498
|
+
},
|
|
499
|
+
{
|
|
500
|
+
"name": "RoomJsonValue",
|
|
501
|
+
"declaration": "export type RoomJsonValue = null | boolean | number | string | RoomJsonValue[] | { [key: string]: RoomJsonValue; };"
|
|
502
|
+
},
|
|
503
|
+
{
|
|
504
|
+
"name": "RoomMemberAddedEvent",
|
|
505
|
+
"declaration": "export interface RoomMemberAddedEvent {\n readonly name: string;\n readonly kind: 'main-agent' | 'cli';\n readonly provider?: string;\n readonly instructions?: string;\n readonly invitedBy: 'human' | 'agent';\n readonly cwd?: string;\n readonly childSessionId?: SessionId;\n}"
|
|
506
|
+
},
|
|
507
|
+
{
|
|
508
|
+
"name": "RoomMemberRemovedEvent",
|
|
509
|
+
"declaration": "export interface RoomMemberRemovedEvent {\n readonly name: string;\n}"
|
|
510
|
+
},
|
|
511
|
+
{
|
|
512
|
+
"name": "RoomMemberUpdatedEvent",
|
|
513
|
+
"declaration": "export interface RoomMemberUpdatedEvent {\n readonly name: string;\n readonly rename?: string;\n readonly instructions?: string | null;\n readonly cwd?: string | null;\n readonly childSessionId?: SessionId;\n}"
|
|
514
|
+
},
|
|
515
|
+
{
|
|
516
|
+
"name": "RoomRelayEvent",
|
|
517
|
+
"declaration": "export interface RoomRelayEvent {\n readonly id: string;\n readonly from: string;\n readonly to: string;\n readonly content: string;\n readonly provenance?: Record<string, RoomJsonValue>;\n}"
|
|
518
|
+
},
|
|
519
|
+
{
|
|
520
|
+
"name": "RoomRelayResolvedEvent",
|
|
521
|
+
"declaration": "export interface RoomRelayResolvedEvent {\n readonly id: string;\n readonly state: 'confirmed' | 'dismissed' | 'sent';\n}"
|
|
522
|
+
},
|
|
523
|
+
{
|
|
524
|
+
"name": "RoomRunStateEvent",
|
|
525
|
+
"declaration": "export interface RoomRunStateEvent {\n readonly member: string;\n readonly state: 'running' | 'done' | 'cancelled' | 'failed';\n readonly startedAt: number;\n readonly elapsedMs?: number;\n readonly error?: string;\n}"
|
|
526
|
+
},
|
|
527
|
+
{
|
|
528
|
+
"name": "RoomSpeechEvent",
|
|
529
|
+
"declaration": "export interface RoomSpeechEvent {\n readonly member: string;\n readonly text: string;\n readonly childSessionId?: SessionId;\n readonly durationMs?: number;\n}"
|
|
530
|
+
},
|
|
531
|
+
{
|
|
532
|
+
"name": "RoomTaskAddedEvent",
|
|
533
|
+
"declaration": "export interface RoomTaskAddedEvent {\n readonly id: string;\n readonly member: string;\n readonly title: string;\n readonly status: 'pending' | 'in_progress';\n readonly blockedBy?: string;\n}"
|
|
534
|
+
},
|
|
535
|
+
{
|
|
536
|
+
"name": "RoomTaskEditedEvent",
|
|
537
|
+
"declaration": "export interface RoomTaskEditedEvent {\n readonly id: string;\n readonly title?: string;\n readonly blockedBy?: string | null;\n}"
|
|
538
|
+
},
|
|
539
|
+
{
|
|
540
|
+
"name": "RoomTaskUpdatedEvent",
|
|
541
|
+
"declaration": "export interface RoomTaskUpdatedEvent {\n readonly id: string;\n readonly status: 'in_progress' | 'done' | 'cancelled' | 'failed';\n}"
|
|
486
542
|
},
|
|
487
543
|
{
|
|
488
544
|
"name": "SandboxMode",
|
|
@@ -490,15 +546,15 @@ export const TYPERT = {
|
|
|
490
546
|
},
|
|
491
547
|
{
|
|
492
548
|
"name": "Session",
|
|
493
|
-
"declaration": "export class Session {\n get surface(): SessionSurface;\n readonly header: SessionHeader;\n get id(): SessionId;\n readonly firstLiveSeq:
|
|
549
|
+
"declaration": "export class Session {\n get surface(): SessionSurface;\n readonly header: SessionHeader;\n readonly inheritedEventCount: SessionLogOffset;\n get id(): SessionId;\n readonly firstLiveSeq: SessionLogOffset;\n eventAt(seq: SessionSeq): SessionEvent | undefined;\n snapshotEvents(fromSeq: SessionLogOffset = SessionLogOffset(0), toSeqExclusive: SessionLogOffset = this.seq): readonly SessionEvent[];\n ownEvents(): readonly SessionEvent[];\n isOwnSeq(seq: SessionSeq): boolean;\n get seq(): SessionLogOffset;\n append<T extends SessionEventType>(type: T, data: SessionEventMap[T], ...opts: T extends SurfaceEventType ? [opts: SurfaceIntent] : []): SessionEvent<T>;\n requestHeader(): EpochHeader | undefined;\n requestContext(): RequestContext | undefined;\n deriveMessages(): Message[];\n deriveEventMessage(event: SessionEvent): Message | null;\n}"
|
|
494
550
|
},
|
|
495
551
|
{
|
|
496
552
|
"name": "SessionEvent",
|
|
497
|
-
"declaration": "export type SessionEvent<T extends SessionEventType = SessionEventType> = { [K in SessionEventType]: { type: K; seq:
|
|
553
|
+
"declaration": "export type SessionEvent<T extends SessionEventType = SessionEventType> = { [K in SessionEventType]: { type: K; seq: SessionSeq; time: number; data: SessionEventMap[K]; ignorable?: true; } & (K extends SurfaceEventType ? { sourceEventSeqs?: SessionSeq[]; surfaceOp?: SurfaceOp; } : object) }[T];"
|
|
498
554
|
},
|
|
499
555
|
{
|
|
500
556
|
"name": "SessionEventMap",
|
|
501
|
-
"declaration": "export interface SessionEventMap {\n 'turn/start': { turn: number; };\n 'turn/end': { turn: number; reason: TurnEndReason; };\n 'step/start': { turn: number; step: number; };\n 'step/end': { turn: number; step: number; };\n 'user/message': UserMessage;\n 'assistant/chunk': { turn: number; step: number; chunk: StreamChunk; };\n 'assistant/message': { turn: number; step: number; message: AssistantMessage; usage?: TokenUsage; interrupted?: true; };\n 'tool/call': { turn: number; step: number; callId:
|
|
557
|
+
"declaration": "export interface SessionEventMap {\n 'turn/start': { turn: number; };\n 'turn/end': { turn: number; reason: TurnEndReason; };\n 'step/start': { turn: number; step: number; };\n 'step/end': { turn: number; step: number; };\n 'user/message': UserMessage;\n 'assistant/chunk': { turn: number; step: number; chunk: StreamChunk; };\n 'assistant/message': { turn: number; step: number; message: AssistantMessage; usage?: TokenUsage; interrupted?: true; };\n 'tool/call': { turn: number; step: number; callId: ToolCallId; name: string; arguments: string; };\n 'tool/result': { turn: number; step: number; message: ToolResultMessage; error?: { name: string; code: string; }; meta?: JsonValue; };\n 'request/header': { header: EpochHeader; reason: RequestHeaderReason; startsSeries?: true; };\n 'request/context': RequestContext;\n 'session/end-seed': Record<string, never>;\n 'agent/inbox/spliced': { target: InboxTarget; start: number; removedCount?: number; inserted: UserMessage[]; outcome?: 'canceled'; };\n 'approval/asked': { id: ApprovalRequestId; toolName: string; callId?: ToolCallId; reason?: string; };\n 'approval/decided': { id: ApprovalRequestId; outcome: ApprovalOutcome; };\n 'approval/policy': { policy: ApprovalPolicy; source?: 'delegation'; };\n 'tool/code-dispatch-start': PtcDispatchStartEventData;\n 'tool/code-dispatch': PtcDispatchEventData;\n 'command/run': { commandId: CommandId; name: string; args?: string; source: CommandSource; };\n 'command/done': { commandId: CommandId; kind: 'success' | 'error'; text?: string; sourceEventSeq?: import('@deepseek-ai/dsh-session/types').SessionSeq; };\n 'subagent/descriptor': SubagentDescriptorData;\n 'session/title': SessionTitleEventData;\n 'todo/write': { todos: TodoItem[]; };\n 'sandbox/mode': { mode: SandboxMode; source?: 'delegation'; };\n 'agent-preset/selected': { agentPreset: string; };\n 'room/created': RoomCreatedEvent;\n 'room/member-added': RoomMemberAddedEvent;\n 'room/member-updated': RoomMemberUpdatedEvent;\n 'room/member-removed': RoomMemberRemovedEvent;\n 'room/dispatch': RoomDispatchEvent;\n 'room/speech': RoomSpeechEvent;\n 'room/run-state': RoomRunStateEvent;\n 'room/relay': RoomRelayEvent;\n 'room/relay-resolved': RoomRelayResolvedEvent;\n 'room/task-added': RoomTaskAddedEvent;\n 'room/task-updated': RoomTaskUpdatedEvent;\n 'room/task-edited': RoomTaskEditedEvent;\n 'room/goal': RoomGoalEvent;\n}"
|
|
502
558
|
},
|
|
503
559
|
{
|
|
504
560
|
"name": "SessionEventType",
|
|
@@ -506,19 +562,43 @@ export const TYPERT = {
|
|
|
506
562
|
},
|
|
507
563
|
{
|
|
508
564
|
"name": "SessionHeader",
|
|
509
|
-
"declaration": "export interface SessionHeader {\n readonly version: number;\n readonly id: SessionId;\n readonly createdAt: number;\n readonly cwd?: string;\n readonly parentSession?: SessionId;\n readonly
|
|
565
|
+
"declaration": "export interface SessionHeader {\n readonly version: number;\n readonly id: SessionId;\n readonly createdAt: number;\n readonly cwd?: string;\n readonly parentSession?: SessionId;\n readonly isSeeded: boolean;\n readonly origin?: 'subagent';\n readonly delegationDepth?: number;\n readonly agentPreset?: string;\n}"
|
|
510
566
|
},
|
|
511
567
|
{
|
|
512
568
|
"name": "SessionId",
|
|
513
569
|
"declaration": "export type SessionId = Branded<'SessionId'>;"
|
|
514
570
|
},
|
|
571
|
+
{
|
|
572
|
+
"name": "SessionLogOffset",
|
|
573
|
+
"declaration": "export type SessionLogOffset = BrandedNumber<'SessionLogOffset'>;"
|
|
574
|
+
},
|
|
575
|
+
{
|
|
576
|
+
"name": "SessionSeq",
|
|
577
|
+
"declaration": "export type SessionSeq = BrandedNumber<'SessionSeq'>;"
|
|
578
|
+
},
|
|
515
579
|
{
|
|
516
580
|
"name": "SessionSurface",
|
|
517
|
-
"declaration": "export interface SessionSurface {\n readonly nodes: readonly
|
|
581
|
+
"declaration": "export interface SessionSurface {\n readonly nodes: readonly SessionSeq[];\n readonly replaceGeneration: number;\n}"
|
|
582
|
+
},
|
|
583
|
+
{
|
|
584
|
+
"name": "SessionTitleEventData",
|
|
585
|
+
"declaration": "export interface SessionTitleEventData {\n readonly title: string;\n readonly messageSeqs: SessionSeq[];\n readonly source: SessionTitleSource;\n}"
|
|
586
|
+
},
|
|
587
|
+
{
|
|
588
|
+
"name": "SessionTitleModelProvenance",
|
|
589
|
+
"declaration": "export interface SessionTitleModelProvenance {\n readonly provider: string;\n readonly model: string;\n}"
|
|
590
|
+
},
|
|
591
|
+
{
|
|
592
|
+
"name": "SessionTitleProviderId",
|
|
593
|
+
"declaration": "export type SessionTitleProviderId = Branded<'SessionTitleProviderId'>;"
|
|
594
|
+
},
|
|
595
|
+
{
|
|
596
|
+
"name": "SessionTitleSource",
|
|
597
|
+
"declaration": "export type SessionTitleSource = { readonly kind: 'fallback'; } | { readonly kind: 'provider'; readonly provider: SessionTitleProviderId; readonly model?: SessionTitleModelProvenance; } | { readonly kind: 'user'; };"
|
|
518
598
|
},
|
|
519
599
|
{
|
|
520
600
|
"name": "StreamChunk",
|
|
521
|
-
"declaration": "export type StreamChunk = { type: 'block-start'; index: number; blockType: ContentBlockType; } | { type: 'text-delta'; index: number; text: string; } | { type: 'reasoning-delta'; index: number; text: string; } | { type: 'tool-call-delta'; index: number; id:
|
|
601
|
+
"declaration": "export type StreamChunk = { type: 'block-start'; index: number; blockType: ContentBlockType; } | { type: 'text-delta'; index: number; text: string; } | { type: 'reasoning-delta'; index: number; text: string; } | { type: 'tool-call-delta'; index: number; id: ToolCallId; name?: string; argumentsDelta: string; } | { type: 'block-end'; index: number; block: ContentBlock; } | { type: 'usage'; usage: TokenUsage; } | { type: 'finish'; reason: FinishReason; replayState?: ReplayEnvelope; };"
|
|
522
602
|
},
|
|
523
603
|
{
|
|
524
604
|
"name": "SubagentDescriptorBase",
|
|
@@ -528,10 +608,6 @@ export const TYPERT = {
|
|
|
528
608
|
"name": "SubagentDescriptorData",
|
|
529
609
|
"declaration": "export type SubagentDescriptorData = OneShotSubagentDescriptorData | ContinuableSubagentDescriptorData;"
|
|
530
610
|
},
|
|
531
|
-
{
|
|
532
|
-
"name": "SubagentReportMessageSource",
|
|
533
|
-
"declaration": "export interface SubagentReportMessageSource {\n readonly kind: 'subagent-report';\n readonly form: 'relay';\n readonly senderSessionId: SessionId;\n}"
|
|
534
|
-
},
|
|
535
611
|
{
|
|
536
612
|
"name": "SubagentSettledMessageSource",
|
|
537
613
|
"declaration": "export interface SubagentSettledMessageSource {\n readonly kind: 'subagent-settled';\n readonly form: 'notice';\n readonly summary: string;\n readonly senderSessionId: SessionId;\n}"
|
|
@@ -542,11 +618,11 @@ export const TYPERT = {
|
|
|
542
618
|
},
|
|
543
619
|
{
|
|
544
620
|
"name": "SurfaceIntent",
|
|
545
|
-
"declaration": "export interface SurfaceIntent {\n surfaceOp: SurfaceOp;\n sourceEventSeqs?:
|
|
621
|
+
"declaration": "export interface SurfaceIntent {\n surfaceOp: SurfaceOp;\n sourceEventSeqs?: SessionSeq[];\n}"
|
|
546
622
|
},
|
|
547
623
|
{
|
|
548
624
|
"name": "SurfaceOp",
|
|
549
|
-
"declaration": "export type SurfaceOp = 'append' | { op: 'replace'; start:
|
|
625
|
+
"declaration": "export type SurfaceOp = 'append' | { op: 'replace'; start: SessionSeq; end: SessionSeq; };"
|
|
550
626
|
},
|
|
551
627
|
{
|
|
552
628
|
"name": "TextBlock",
|
|
@@ -558,15 +634,19 @@ export const TYPERT = {
|
|
|
558
634
|
},
|
|
559
635
|
{
|
|
560
636
|
"name": "TokenUsage",
|
|
561
|
-
"declaration": "export interface TokenUsage {\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens?: number;\n cacheWriteTokens?: number;\n reasoningTokens?: number;\n}"
|
|
637
|
+
"declaration": "export interface TokenUsage {\n inputTokens: number;\n outputTokens: number;\n totalTokens?: number;\n cacheReadTokens?: number;\n cacheWriteTokens?: number;\n reasoningTokens?: number;\n}"
|
|
562
638
|
},
|
|
563
639
|
{
|
|
564
640
|
"name": "ToolCallBlock",
|
|
565
|
-
"declaration": "export interface ToolCallBlock {\n type: 'tool-call';\n id:
|
|
641
|
+
"declaration": "export interface ToolCallBlock {\n type: 'tool-call';\n id: ToolCallId;\n name: string;\n arguments: string;\n}"
|
|
642
|
+
},
|
|
643
|
+
{
|
|
644
|
+
"name": "ToolCallId",
|
|
645
|
+
"declaration": "export type ToolCallId = Branded<'ToolCallId'>;"
|
|
566
646
|
},
|
|
567
647
|
{
|
|
568
648
|
"name": "ToolMessageSource",
|
|
569
|
-
"declaration": "export interface ToolMessageSource {\n kind: 'tool';\n callId:
|
|
649
|
+
"declaration": "export interface ToolMessageSource {\n kind: 'tool';\n callId: ToolCallId;\n}"
|
|
570
650
|
},
|
|
571
651
|
{
|
|
572
652
|
"name": "ToolRestriction",
|
|
@@ -574,7 +654,7 @@ export const TYPERT = {
|
|
|
574
654
|
},
|
|
575
655
|
{
|
|
576
656
|
"name": "ToolResultBlock",
|
|
577
|
-
"declaration": "export interface ToolResultBlock {\n type: 'tool-result';\n toolCallId:
|
|
657
|
+
"declaration": "export interface ToolResultBlock {\n type: 'tool-result';\n toolCallId: ToolCallId;\n content: ContentBlock[];\n isError?: boolean;\n}"
|
|
578
658
|
},
|
|
579
659
|
{
|
|
580
660
|
"name": "ToolResultMessage",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"typert.remote-client.d.ts","names":["list","read","reveal","turnFiles"],"sources":["../src/index.ts"],"sourcesContent":[null],"mappings":";;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"typert.remote-client.d.ts","names":["list","read","reveal","turnFiles"],"sources":["../src/index.ts"],"sourcesContent":[null],"mappings":";;;;;;;;;;IA+WQA,I;IA0FAC,I;IA6EAC,M;IAlIAC,S;;;IArCAH,kB;IA0FAC,kB;IA6EAC,oB;IAlIAC,uB;;;;;;IArCAH,wB;IA0FAC,wB;IA6EAC,0B;IAlIAC,6B","ignoreList":[]}
|
|
@@ -90,7 +90,7 @@ export const TYPERT_REMOTE = {
|
|
|
90
90
|
typeSymbol: '@khorsheed/dsh-file-preview/types#FilePreviewList',
|
|
91
91
|
schema: _khorsheed_dsh_file_preview_filePreview_list_result$schema,
|
|
92
92
|
},
|
|
93
|
-
sourceLocation: {"file":"packages/file-preview/src/index.ts","line":
|
|
93
|
+
sourceLocation: {"file":"packages/file-preview/src/index.ts","line":368,"column":9},
|
|
94
94
|
},
|
|
95
95
|
{
|
|
96
96
|
id: '@khorsheed/dsh-file-preview#filePreview/read',
|
|
@@ -131,7 +131,7 @@ export const TYPERT_REMOTE = {
|
|
|
131
131
|
typeSymbol: '@khorsheed/dsh-file-preview/types#FilePreviewRead',
|
|
132
132
|
schema: _khorsheed_dsh_file_preview_filePreview_read_result$schema,
|
|
133
133
|
},
|
|
134
|
-
sourceLocation: {"file":"packages/file-preview/src/index.ts","line":
|
|
134
|
+
sourceLocation: {"file":"packages/file-preview/src/index.ts","line":458,"column":9},
|
|
135
135
|
},
|
|
136
136
|
{
|
|
137
137
|
id: '@khorsheed/dsh-file-preview#filePreview/reveal',
|
|
@@ -172,7 +172,7 @@ export const TYPERT_REMOTE = {
|
|
|
172
172
|
typeSymbol: '@khorsheed/dsh-file-preview/types#FilePreviewReveal',
|
|
173
173
|
schema: _khorsheed_dsh_file_preview_filePreview_reveal_result$schema,
|
|
174
174
|
},
|
|
175
|
-
sourceLocation: {"file":"packages/file-preview/src/index.ts","line":
|
|
175
|
+
sourceLocation: {"file":"packages/file-preview/src/index.ts","line":535,"column":9},
|
|
176
176
|
},
|
|
177
177
|
{
|
|
178
178
|
id: '@khorsheed/dsh-file-preview#filePreview/turnFiles',
|
|
@@ -202,7 +202,7 @@ export const TYPERT_REMOTE = {
|
|
|
202
202
|
typeSymbol: '@khorsheed/dsh-file-preview/types#FilePreviewTurnMap',
|
|
203
203
|
schema: _khorsheed_dsh_file_preview_filePreview_turnFiles_result$schema,
|
|
204
204
|
},
|
|
205
|
-
sourceLocation: {"file":"packages/file-preview/src/index.ts","line":
|
|
205
|
+
sourceLocation: {"file":"packages/file-preview/src/index.ts","line":405,"column":9},
|
|
206
206
|
},
|
|
207
207
|
],
|
|
208
208
|
}
|
package/lib/types/bash-writes.js
CHANGED
|
@@ -305,7 +305,7 @@ export class BashWriteCollector {
|
|
|
305
305
|
#replay(session) {
|
|
306
306
|
this.#pending.set(session.id, new Map());
|
|
307
307
|
this.#captured.set(session.id, new Map());
|
|
308
|
-
for (const event of session.
|
|
308
|
+
for (const event of session.snapshotEvents())
|
|
309
309
|
this.#onEvent(session, event);
|
|
310
310
|
}
|
|
311
311
|
#onEvent(session, event) {
|
package/lib/types/fold.d.ts
CHANGED
|
@@ -26,7 +26,8 @@ export declare function diffsFromResultMeta(meta: unknown): readonly FilePreview
|
|
|
26
26
|
* first-seen order and deduplicated by display path; a later occurrence
|
|
27
27
|
* refreshes the entry's op and location without moving it, and each write/edit
|
|
28
28
|
* tool result appends its change's diff to the entry's `diffs` in event order.
|
|
29
|
-
* Nested Code Mode file dispatches (`tool/code-dispatch` events
|
|
29
|
+
* Nested Code Mode file dispatches (`tool/code-dispatch` events, or
|
|
30
|
+
* `tool/ptc-dispatch` on seats running the PTC rename) count too —
|
|
30
31
|
* they carry no turn/step of their own, so the entry borrows the enclosing
|
|
31
32
|
* root call's location.
|
|
32
33
|
* @param events - the session's events in ascending seq order.
|
|
@@ -55,11 +56,12 @@ export type TurnFilesByTurn = ReadonlyMap<number, ReadonlyMap<string, TurnFileFa
|
|
|
55
56
|
* single source of truth. Unlike {@link foldFilePreview}, this does NOT dedupe
|
|
56
57
|
* a path to its last occurrence: a file touched in two turns appears in BOTH
|
|
57
58
|
* turn maps, so each turn's card lists exactly what that turn mutated.
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
59
|
+
* Reads leave no card entry (the card is the mutation vocabulary — write/edit
|
|
60
|
+
* only), so a pure-read call never registers; write/edit calls register with
|
|
61
|
+
* their own turn; nested Code Mode dispatches borrow the enclosing root call's
|
|
62
|
+
* turn (dispatch events carry none); a `tool/result` whose presentation meta
|
|
63
|
+
* carries diffs registers its paths (the render-intent vocabulary) with the
|
|
64
|
+
* result's turn, and per-turn line deltas are summed from the diffs. A `write` whose result carries no diffs is a
|
|
63
65
|
* create (the write tool records no diffs when the file had no prior content):
|
|
64
66
|
* its full written content — read from the call arguments, which the log keeps
|
|
65
67
|
* — is the added-line count, once per file per turn.
|
package/lib/types/fold.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fold.d.ts","sourceRoot":"","sources":["../../src/fold.ts"],"names":[],"mappings":"AAAA,8GAA8G;AAE9G,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAG5D,OAAO,KAAK,EAAqC,eAAe,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"fold.d.ts","sourceRoot":"","sources":["../../src/fold.ts"],"names":[],"mappings":"AAAA,8GAA8G;AAE9G,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAG5D,OAAO,KAAK,EAAqC,eAAe,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAiBnG,uEAAuE;AACvE,MAAM,WAAW,qBAAqB;IACpC,uCAAuC;IACvC,QAAQ,CAAC,EAAE,EAAE,aAAa,CAAA;IAC1B,uDAAuD;IACvD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACtB;AAED,2EAA2E;AAC3E,MAAM,MAAM,qBAAqB,GAAG;IAClC,yEAAyE;IACzE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,4DAA4D;IAC5D,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,gCAAgC;IAChC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACzB,CAAA;AAmBD,sFAAsF;AACtF,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,qBAAqB,GAAG,SAAS,CAOvG;AAED,8EAA8E;AAC9E,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,OAAO,GAAG,SAAS,qBAAqB,EAAE,GAAG,SAAS,CAc/F;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,eAAe,CAiElG;AAED,kGAAkG;AAClG,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAI9C;AAED,8EAA8E;AAC9E,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,uFAAuF;IACvF,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,4DAA4D;IAC5D,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,4FAA4F;IAC5F,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAC1B;AAED,4FAA4F;AAC5F,MAAM,MAAM,eAAe,GAAG,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAA;AAuCpF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,GAAG,eAAe,CAiItF"}
|
package/lib/types/fold.js
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
/** Pure log fold over the files a session read, wrote, or edited. @module @khorsheed/dsh-file-preview/fold */
|
|
2
2
|
/** Tool names whose calls record a touched file path. */
|
|
3
3
|
const FILE_TOOL_NAMES = new Set(['read', 'write', 'edit']);
|
|
4
|
+
/**
|
|
5
|
+
* Settled nested-dispatch event names, matched by name (feature detection,
|
|
6
|
+
* never a version check): `tool/code-dispatch` is the Code Mode name every
|
|
7
|
+
* host through 0.1.2-rc.1 emits; `tool/ptc-dispatch` is the PTC rename later
|
|
8
|
+
* 0.1.2 seats move to. Both carry the same settled-dispatch payload, so one
|
|
9
|
+
* branch serves either.
|
|
10
|
+
*/
|
|
11
|
+
const DISPATCH_EVENT_NAMES = new Set(['tool/code-dispatch', 'tool/ptc-dispatch']);
|
|
4
12
|
/** The argument key carrying the touched path (shared by all three file tools). */
|
|
5
13
|
const FILE_PATH_ARGUMENT = 'file_path';
|
|
6
14
|
/**
|
|
@@ -57,7 +65,8 @@ export function diffsFromResultMeta(meta) {
|
|
|
57
65
|
* first-seen order and deduplicated by display path; a later occurrence
|
|
58
66
|
* refreshes the entry's op and location without moving it, and each write/edit
|
|
59
67
|
* tool result appends its change's diff to the entry's `diffs` in event order.
|
|
60
|
-
* Nested Code Mode file dispatches (`tool/code-dispatch` events
|
|
68
|
+
* Nested Code Mode file dispatches (`tool/code-dispatch` events, or
|
|
69
|
+
* `tool/ptc-dispatch` on seats running the PTC rename) count too —
|
|
61
70
|
* they carry no turn/step of their own, so the entry borrows the enclosing
|
|
62
71
|
* root call's location.
|
|
63
72
|
* @param events - the session's events in ascending seq order.
|
|
@@ -88,16 +97,19 @@ export function foldFilePreview(events, maxFiles) {
|
|
|
88
97
|
record(target, event.seq, event.data.turn, event.data.step);
|
|
89
98
|
continue;
|
|
90
99
|
}
|
|
91
|
-
if (event.type
|
|
100
|
+
if (DISPATCH_EVENT_NAMES.has(event.type)) {
|
|
92
101
|
// The dispatch event IS the settled outcome: a failed sub-call changed
|
|
93
|
-
// nothing, so only successful file touches record.
|
|
94
|
-
|
|
102
|
+
// nothing, so only successful file touches record. The PTC rename keeps
|
|
103
|
+
// the code-dispatch payload shape (the ptc name has no SessionEventMap
|
|
104
|
+
// row yet), so the data reads through the declared constituent.
|
|
105
|
+
const dispatch = event;
|
|
106
|
+
if (dispatch.data.isError)
|
|
95
107
|
continue;
|
|
96
|
-
const target = targetFromArguments(
|
|
108
|
+
const target = targetFromArguments(dispatch.data.name, dispatch.data.arguments);
|
|
97
109
|
if (target === undefined)
|
|
98
110
|
continue;
|
|
99
|
-
const site = callSites.get(String(
|
|
100
|
-
record(target,
|
|
111
|
+
const site = callSites.get(String(dispatch.data.rootCallId)) ?? { turn: 0, step: 0 };
|
|
112
|
+
record(target, dispatch.seq, site.turn, site.step);
|
|
101
113
|
continue;
|
|
102
114
|
}
|
|
103
115
|
if (event.type === 'tool/result') {
|
|
@@ -172,11 +184,12 @@ function resultCallFacts(message) {
|
|
|
172
184
|
* single source of truth. Unlike {@link foldFilePreview}, this does NOT dedupe
|
|
173
185
|
* a path to its last occurrence: a file touched in two turns appears in BOTH
|
|
174
186
|
* turn maps, so each turn's card lists exactly what that turn mutated.
|
|
175
|
-
*
|
|
176
|
-
*
|
|
177
|
-
*
|
|
178
|
-
*
|
|
179
|
-
*
|
|
187
|
+
* Reads leave no card entry (the card is the mutation vocabulary — write/edit
|
|
188
|
+
* only), so a pure-read call never registers; write/edit calls register with
|
|
189
|
+
* their own turn; nested Code Mode dispatches borrow the enclosing root call's
|
|
190
|
+
* turn (dispatch events carry none); a `tool/result` whose presentation meta
|
|
191
|
+
* carries diffs registers its paths (the render-intent vocabulary) with the
|
|
192
|
+
* result's turn, and per-turn line deltas are summed from the diffs. A `write` whose result carries no diffs is a
|
|
180
193
|
* create (the write tool records no diffs when the file had no prior content):
|
|
181
194
|
* its full written content — read from the call arguments, which the log keeps
|
|
182
195
|
* — is the added-line count, once per file per turn.
|
|
@@ -257,6 +270,11 @@ export function foldFilePreviewByTurn(events) {
|
|
|
257
270
|
const target = pathFromToolCall(event.data.name, event.data.arguments);
|
|
258
271
|
if (target === undefined)
|
|
259
272
|
continue;
|
|
273
|
+
// The card's vocabulary is mutations only: a read call registers
|
|
274
|
+
// nothing (it may still anchor a nested code dispatch's location via
|
|
275
|
+
// callSites above).
|
|
276
|
+
if (target.op === 'read')
|
|
277
|
+
continue;
|
|
260
278
|
if (target.op === 'write') {
|
|
261
279
|
const content = contentFromWriteCall(event.data.arguments);
|
|
262
280
|
if (content !== undefined) {
|
|
@@ -268,19 +286,24 @@ export function foldFilePreviewByTurn(events) {
|
|
|
268
286
|
recordLocation(target.path, event.data.turn, event.seq, event.data.step);
|
|
269
287
|
continue;
|
|
270
288
|
}
|
|
271
|
-
if (event.type
|
|
289
|
+
if (DISPATCH_EVENT_NAMES.has(event.type)) {
|
|
272
290
|
// The dispatch event IS the settled outcome: a failed sub-call changed
|
|
273
291
|
// nothing, so only successful file touches record. Code Mode writes are
|
|
274
292
|
// uncountable (no result diffs reach the session), so they register the
|
|
275
|
-
// path and poison the line-count totals (unknown wins).
|
|
276
|
-
|
|
293
|
+
// path and poison the line-count totals (unknown wins). Same payload
|
|
294
|
+
// shape caveat as foldFilePreview above.
|
|
295
|
+
const dispatch = event;
|
|
296
|
+
if (dispatch.data.isError)
|
|
277
297
|
continue;
|
|
278
|
-
const target = targetFromArguments(
|
|
298
|
+
const target = targetFromArguments(dispatch.data.name, dispatch.data.arguments);
|
|
279
299
|
if (target === undefined)
|
|
280
300
|
continue;
|
|
281
|
-
|
|
301
|
+
// Reads leave no card entry here too — only mutations register.
|
|
302
|
+
if (target.op === 'read')
|
|
303
|
+
continue;
|
|
304
|
+
const site = callSites.get(String(dispatch.data.rootCallId)) ?? { turn: 0, step: 0 };
|
|
282
305
|
sessionSeen.add(target.path);
|
|
283
|
-
recordContribution(target.path, site.turn,
|
|
306
|
+
recordContribution(target.path, site.turn, dispatch.seq, site.step, undefined, undefined, true);
|
|
284
307
|
continue;
|
|
285
308
|
}
|
|
286
309
|
if (event.type === 'tool/result') {
|
package/lib/types/index.d.ts
CHANGED
|
@@ -13,8 +13,9 @@ declare module '@deepseek-ai/cordis' {
|
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
15
15
|
* The `filePreview` Remote service: session-scoped read-only file inspection
|
|
16
|
-
* for web surfaces. `list` is a
|
|
17
|
-
*
|
|
16
|
+
* for web surfaces. `list` is a fold over the session log, then filtered to the
|
|
17
|
+
* paths that still exist on disk (resolved against the session cwd and stat-ed
|
|
18
|
+
* per call); `read` resolves the path against the session cwd and serves current
|
|
18
19
|
* text content through `ctx.fs` (or a browser URL for images), capped by
|
|
19
20
|
* config. Image bytes ride a dedicated host route so the browser loads them
|
|
20
21
|
* natively without bloating the RPC channel.
|
|
@@ -55,14 +56,28 @@ export declare class FilePreviewService extends TypertRemoteService {
|
|
|
55
56
|
* @param res - the response to fill with bytes or an error status.
|
|
56
57
|
*/
|
|
57
58
|
private serveImage;
|
|
59
|
+
/** Resolve the session's recorded display paths against its cwd and keep only
|
|
60
|
+
* those that currently exist as a regular file. The products surfaces fold
|
|
61
|
+
* the session log (which is history, not disk state): a path the log wrote
|
|
62
|
+
* may have been cleaned up since (a temp script the turn deleted), and such
|
|
63
|
+
* a path is not a product to list. Existence is checked fresh on every call
|
|
64
|
+
* (never cached), so a deletion that lands after a fold is visible on the
|
|
65
|
+
* next fetch. Unresolvable/unstat-able paths are treated as absent.
|
|
66
|
+
* @param agent - owning live agent; its session cwd anchors relative paths.
|
|
67
|
+
* @param paths - the display paths to probe.
|
|
68
|
+
* @returns the subset that resolves to an existing regular file.
|
|
69
|
+
*/
|
|
70
|
+
private retainExisting;
|
|
58
71
|
/**
|
|
59
72
|
* List the files one session wrote or edited: the log fold plus any
|
|
60
73
|
* bash-written files the collector verified (the S2 seam), merged so a
|
|
61
|
-
* captured path the fold already knows keeps its log-derived entry.
|
|
74
|
+
* captured path the fold already knows keeps its log-derived entry. Only
|
|
75
|
+
* paths that currently exist on disk are returned — a file the session
|
|
76
|
+
* wrote and later deleted is history, not a product.
|
|
62
77
|
* @param agent - owning live agent; its session log is the data source.
|
|
63
|
-
* @returns first-seen files capped by `maxFiles`, with the log watermark.
|
|
78
|
+
* @returns existing first-seen files capped by `maxFiles`, with the log watermark.
|
|
64
79
|
*/
|
|
65
|
-
list(agent: Agent): FilePreviewList
|
|
80
|
+
list(agent: Agent): Promise<FilePreviewList>;
|
|
66
81
|
/**
|
|
67
82
|
* Every turn's file mutations for the turn-tail card — the single source of
|
|
68
83
|
* truth the card renders (the client's old write/edit-only fold retired).
|
|
@@ -71,11 +86,14 @@ export declare class FilePreviewService extends TypertRemoteService {
|
|
|
71
86
|
* result diff meta) and merging the collector's bash-written captures by
|
|
72
87
|
* their own turn. The fold is cached per session and invalidated by the log
|
|
73
88
|
* watermark, so repeated card fetches do not refold. A path touched in two
|
|
74
|
-
* turns appears in BOTH turn groups — per-turn attribution is exact.
|
|
89
|
+
* turns appears in BOTH turn groups — per-turn attribution is exact. Only
|
|
90
|
+
* paths that currently exist on disk are returned (a deleted temp script is
|
|
91
|
+
* history, not a product); existence is probed fresh on every call, so the
|
|
92
|
+
* cached fold is filtered per request rather than cached.
|
|
75
93
|
* @param agent - owning live agent; its session log is the data source.
|
|
76
|
-
* @returns per-turn file groups plus the scanned watermark.
|
|
94
|
+
* @returns existing per-turn file groups plus the scanned watermark.
|
|
77
95
|
*/
|
|
78
|
-
turnFiles(agent: Agent): FilePreviewTurnMap
|
|
96
|
+
turnFiles(agent: Agent): Promise<FilePreviewTurnMap>;
|
|
79
97
|
/**
|
|
80
98
|
* Read the current content of one recorded file, resolved against the
|
|
81
99
|
* session cwd and capped by `maxReadBytes`.
|