@khorsheed/dsh-file-preview 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,17 +4,21 @@ import type {
4
4
  TypertRemoteContribution,
5
5
  } from '@deepseek-ai/dsh-typert-protocol'
6
6
  import type { SessionId } from '@deepseek-ai/dsh-session/types'
7
- import type { FilePreviewList, FilePreviewRead, FilePreviewReveal, FilePreviewTurnMap } from '@khorsheed/dsh-file-preview/types'
7
+ import type { FilePreviewList, FilePreviewOpenExternal, FilePreviewRead, FilePreviewReveal, FilePreviewTurnMap } from '@khorsheed/dsh-file-preview/types'
8
8
 
9
9
  declare module '@deepseek-ai/dsh-typert-protocol' {
10
10
  interface TypertRemoteNamespace$66696c6550726576696577 {
11
+ capabilities: () => Promise<RemoteResult<{ protocolVersion: 1; }>>
11
12
  list: (agentId: SessionId) => Promise<RemoteResult<FilePreviewList>>
13
+ openExternal: (agentId: SessionId, path: string, app: string, signal?: AbortSignal) => Promise<RemoteResult<FilePreviewOpenExternal>>
12
14
  read: (agentId: SessionId, path: string, signal?: AbortSignal) => Promise<RemoteResult<FilePreviewRead>>
13
15
  reveal: (agentId: SessionId, path: string, signal?: AbortSignal) => Promise<RemoteResult<FilePreviewReveal>>
14
16
  turnFiles: (agentId: SessionId) => Promise<RemoteResult<FilePreviewTurnMap>>
15
17
  }
16
18
  interface TypertRemoteMap {
19
+ 'filePreview/capabilities': () => Promise<RemoteResult<{ protocolVersion: 1; }>>
17
20
  'filePreview/list': (agentId: SessionId) => Promise<RemoteResult<FilePreviewList>>
21
+ 'filePreview/openExternal': (agentId: SessionId, path: string, app: string, signal?: AbortSignal) => Promise<RemoteResult<FilePreviewOpenExternal>>
18
22
  'filePreview/read': (agentId: SessionId, path: string, signal?: AbortSignal) => Promise<RemoteResult<FilePreviewRead>>
19
23
  'filePreview/reveal': (agentId: SessionId, path: string, signal?: AbortSignal) => Promise<RemoteResult<FilePreviewReveal>>
20
24
  'filePreview/turnFiles': (agentId: SessionId) => Promise<RemoteResult<FilePreviewTurnMap>>
@@ -24,6 +28,7 @@ declare module '@deepseek-ai/dsh-typert-protocol' {
24
28
  }
25
29
  interface TypertRemoteScopeMap {
26
30
  'agent:filePreview/list': () => Promise<RemoteResult<FilePreviewList>>
31
+ 'agent:filePreview/openExternal': (path: string, app: string, signal?: AbortSignal) => Promise<RemoteResult<FilePreviewOpenExternal>>
27
32
  'agent:filePreview/read': (path: string, signal?: AbortSignal) => Promise<RemoteResult<FilePreviewRead>>
28
33
  'agent:filePreview/reveal': (path: string, signal?: AbortSignal) => Promise<RemoteResult<FilePreviewReveal>>
29
34
  'agent:filePreview/turnFiles': () => Promise<RemoteResult<FilePreviewTurnMap>>
@@ -1,8 +1,14 @@
1
1
  /* Generated by @deepseek-ai/dsh-typert-generator from the Host FaceModel — do not edit. */
2
2
  import { z } from 'zod'
3
3
 
4
- const _khorsheed_dsh_file_preview_filePreview_list_parameter_0$schema = z.intersection(z.string(), z.unknown())
5
- const _khorsheed_dsh_file_preview_filePreview_list_result$schema = z.object({
4
+ let _khorsheed_dsh_file_preview_filePreview_capabilities_result$schema$value
5
+ const _khorsheed_dsh_file_preview_filePreview_capabilities_result$schema = () => (_khorsheed_dsh_file_preview_filePreview_capabilities_result$schema$value ??= z.object({
6
+ 'protocolVersion': z.literal(1),
7
+ }))
8
+ let _khorsheed_dsh_file_preview_filePreview_list_parameter_0$schema$value
9
+ const _khorsheed_dsh_file_preview_filePreview_list_parameter_0$schema = () => (_khorsheed_dsh_file_preview_filePreview_list_parameter_0$schema$value ??= z.intersection(z.string(), z.unknown()))
10
+ let _khorsheed_dsh_file_preview_filePreview_list_result$schema$value
11
+ const _khorsheed_dsh_file_preview_filePreview_list_result$schema = () => (_khorsheed_dsh_file_preview_filePreview_list_result$schema$value ??= z.object({
6
12
  'entries': z.array(z.object({
7
13
  'path': z.string().readonly(),
8
14
  'op': z.union([z.literal("read"), z.literal("write"), z.literal("edit")]).readonly(),
@@ -23,29 +29,50 @@ const _khorsheed_dsh_file_preview_filePreview_list_result$schema = z.object({
23
29
  })).readonly(),
24
30
  'asOfSeq': z.number().readonly(),
25
31
  'truncated': z.boolean().readonly(),
26
- })
27
- const _khorsheed_dsh_file_preview_filePreview_read_parameter_0$schema = z.intersection(z.string(), z.unknown())
28
- const _khorsheed_dsh_file_preview_filePreview_read_parameter_1$schema = z.string()
29
- const _khorsheed_dsh_file_preview_filePreview_read_result$schema = z.object({
32
+ }))
33
+ let _khorsheed_dsh_file_preview_filePreview_openExternal_parameter_0$schema$value
34
+ const _khorsheed_dsh_file_preview_filePreview_openExternal_parameter_0$schema = () => (_khorsheed_dsh_file_preview_filePreview_openExternal_parameter_0$schema$value ??= z.intersection(z.string(), z.unknown()))
35
+ let _khorsheed_dsh_file_preview_filePreview_openExternal_parameter_1$schema$value
36
+ const _khorsheed_dsh_file_preview_filePreview_openExternal_parameter_1$schema = () => (_khorsheed_dsh_file_preview_filePreview_openExternal_parameter_1$schema$value ??= z.string())
37
+ let _khorsheed_dsh_file_preview_filePreview_openExternal_parameter_2$schema$value
38
+ const _khorsheed_dsh_file_preview_filePreview_openExternal_parameter_2$schema = () => (_khorsheed_dsh_file_preview_filePreview_openExternal_parameter_2$schema$value ??= z.string())
39
+ let _khorsheed_dsh_file_preview_filePreview_openExternal_result$schema$value
40
+ const _khorsheed_dsh_file_preview_filePreview_openExternal_result$schema = () => (_khorsheed_dsh_file_preview_filePreview_openExternal_result$schema$value ??= z.union([z.object({
41
+ 'opened': z.literal(true).readonly(),
42
+ }), z.object({
43
+ 'opened': z.literal(false).readonly(),
44
+ 'reason': z.union([z.literal("missing"), z.literal("unknown-app"), z.literal("unsupported-platform"), z.literal("launch-failed")]).readonly(),
45
+ })]))
46
+ let _khorsheed_dsh_file_preview_filePreview_read_parameter_0$schema$value
47
+ const _khorsheed_dsh_file_preview_filePreview_read_parameter_0$schema = () => (_khorsheed_dsh_file_preview_filePreview_read_parameter_0$schema$value ??= z.intersection(z.string(), z.unknown()))
48
+ let _khorsheed_dsh_file_preview_filePreview_read_parameter_1$schema$value
49
+ const _khorsheed_dsh_file_preview_filePreview_read_parameter_1$schema = () => (_khorsheed_dsh_file_preview_filePreview_read_parameter_1$schema$value ??= z.string())
50
+ let _khorsheed_dsh_file_preview_filePreview_read_result$schema$value
51
+ const _khorsheed_dsh_file_preview_filePreview_read_result$schema = () => (_khorsheed_dsh_file_preview_filePreview_read_result$schema$value ??= z.object({
30
52
  'path': z.string().readonly(),
31
- 'kind': z.union([z.literal("text"), z.literal("image"), z.literal("binary"), z.literal("missing"), z.literal("too-large"), z.literal("error")]).readonly(),
53
+ 'kind': z.union([z.literal("missing"), z.literal("too-large"), z.literal("error"), z.literal("text"), z.literal("binary"), z.literal("image")]).readonly(),
32
54
  'content': z.string().readonly().optional(),
33
55
  'url': z.string().readonly().optional(),
34
56
  'truncated': z.boolean().readonly().optional(),
35
57
  'htmlScripted': z.boolean().readonly().optional(),
36
58
  'size': z.number().readonly().optional(),
37
59
  'message': z.string().readonly().optional(),
38
- })
39
- const _khorsheed_dsh_file_preview_filePreview_reveal_parameter_0$schema = z.intersection(z.string(), z.unknown())
40
- const _khorsheed_dsh_file_preview_filePreview_reveal_parameter_1$schema = z.string()
41
- const _khorsheed_dsh_file_preview_filePreview_reveal_result$schema = z.union([z.object({
60
+ }))
61
+ let _khorsheed_dsh_file_preview_filePreview_reveal_parameter_0$schema$value
62
+ const _khorsheed_dsh_file_preview_filePreview_reveal_parameter_0$schema = () => (_khorsheed_dsh_file_preview_filePreview_reveal_parameter_0$schema$value ??= z.intersection(z.string(), z.unknown()))
63
+ let _khorsheed_dsh_file_preview_filePreview_reveal_parameter_1$schema$value
64
+ const _khorsheed_dsh_file_preview_filePreview_reveal_parameter_1$schema = () => (_khorsheed_dsh_file_preview_filePreview_reveal_parameter_1$schema$value ??= z.string())
65
+ let _khorsheed_dsh_file_preview_filePreview_reveal_result$schema$value
66
+ const _khorsheed_dsh_file_preview_filePreview_reveal_result$schema = () => (_khorsheed_dsh_file_preview_filePreview_reveal_result$schema$value ??= z.union([z.object({
42
67
  'revealed': z.literal(true).readonly(),
43
68
  }), z.object({
44
69
  'revealed': z.literal(false).readonly(),
45
70
  'reason': z.union([z.literal("missing"), z.literal("select-failed")]).readonly(),
46
- })])
47
- const _khorsheed_dsh_file_preview_filePreview_turnFiles_parameter_0$schema = z.intersection(z.string(), z.unknown())
48
- const _khorsheed_dsh_file_preview_filePreview_turnFiles_result$schema = z.object({
71
+ })]))
72
+ let _khorsheed_dsh_file_preview_filePreview_turnFiles_parameter_0$schema$value
73
+ const _khorsheed_dsh_file_preview_filePreview_turnFiles_parameter_0$schema = () => (_khorsheed_dsh_file_preview_filePreview_turnFiles_parameter_0$schema$value ??= z.intersection(z.string(), z.unknown()))
74
+ let _khorsheed_dsh_file_preview_filePreview_turnFiles_result$schema$value
75
+ const _khorsheed_dsh_file_preview_filePreview_turnFiles_result$schema = () => (_khorsheed_dsh_file_preview_filePreview_turnFiles_result$schema$value ??= z.object({
49
76
  'turns': z.array(z.object({
50
77
  'turn': z.number().readonly(),
51
78
  'files': z.array(z.object({
@@ -57,11 +84,27 @@ const _khorsheed_dsh_file_preview_filePreview_turnFiles_result$schema = z.object
57
84
  })).readonly(),
58
85
  })).readonly(),
59
86
  'asOfSeq': z.number().readonly(),
60
- })
87
+ }))
61
88
 
62
89
  export const TYPERT_REMOTE = {
63
90
  package: '@khorsheed/dsh-file-preview',
64
91
  descriptors: [
92
+ {
93
+ id: '@khorsheed/dsh-file-preview#filePreview/capabilities',
94
+ service: 'filePreview',
95
+ namespace: 'filePreview',
96
+ method: 'capabilities',
97
+ invocation: { kind: 'direct' },
98
+ parameters: [
99
+ ],
100
+ result: {
101
+ mode: 'strict',
102
+ typeSymbol: '@khorsheed/dsh-file-preview#filePreview/capabilities:result',
103
+ create: _khorsheed_dsh_file_preview_filePreview_capabilities_result$schema,
104
+ schema: _khorsheed_dsh_file_preview_filePreview_capabilities_result$schema(),
105
+ },
106
+ sourceLocation: {"file":"packages/file-preview/src/index.ts","line":196,"column":3},
107
+ },
65
108
  {
66
109
  id: '@khorsheed/dsh-file-preview#filePreview/list',
67
110
  service: 'filePreview',
@@ -81,16 +124,73 @@ export const TYPERT_REMOTE = {
81
124
  codec: {
82
125
  mode: 'strict',
83
126
  typeSymbol: '@deepseek-ai/dsh-session/types#SessionId',
84
- schema: _khorsheed_dsh_file_preview_filePreview_list_parameter_0$schema,
127
+ create: _khorsheed_dsh_file_preview_filePreview_list_parameter_0$schema,
128
+ schema: _khorsheed_dsh_file_preview_filePreview_list_parameter_0$schema(),
85
129
  },
86
130
  },
87
131
  ],
88
132
  result: {
89
133
  mode: 'strict',
90
134
  typeSymbol: '@khorsheed/dsh-file-preview/types#FilePreviewList',
91
- schema: _khorsheed_dsh_file_preview_filePreview_list_result$schema,
135
+ create: _khorsheed_dsh_file_preview_filePreview_list_result$schema,
136
+ schema: _khorsheed_dsh_file_preview_filePreview_list_result$schema(),
137
+ },
138
+ sourceLocation: {"file":"packages/file-preview/src/index.ts","line":316,"column":9},
139
+ },
140
+ {
141
+ id: '@khorsheed/dsh-file-preview#filePreview/openExternal',
142
+ service: 'filePreview',
143
+ namespace: 'filePreview',
144
+ method: 'openExternal',
145
+ invocation: { kind: 'direct' },
146
+ scope: {
147
+ context: 'agent',
148
+ wire: 'agentId',
149
+ },
150
+ parameters: [
151
+ {
152
+ name: 'agent',
153
+ wire: 'agentId',
154
+ source: 'lookup',
155
+ lookup: 'agent',
156
+ codec: {
157
+ mode: 'strict',
158
+ typeSymbol: '@deepseek-ai/dsh-session/types#SessionId',
159
+ create: _khorsheed_dsh_file_preview_filePreview_openExternal_parameter_0$schema,
160
+ schema: _khorsheed_dsh_file_preview_filePreview_openExternal_parameter_0$schema(),
161
+ },
162
+ },
163
+ {
164
+ name: 'path',
165
+ wire: 'path',
166
+ source: 'json',
167
+ codec: {
168
+ mode: 'strict',
169
+ typeSymbol: '@khorsheed/dsh-file-preview#filePreview/openExternal:path',
170
+ create: _khorsheed_dsh_file_preview_filePreview_openExternal_parameter_1$schema,
171
+ schema: _khorsheed_dsh_file_preview_filePreview_openExternal_parameter_1$schema(),
172
+ },
173
+ },
174
+ {
175
+ name: 'app',
176
+ wire: 'app',
177
+ source: 'json',
178
+ codec: {
179
+ mode: 'strict',
180
+ typeSymbol: '@khorsheed/dsh-file-preview#filePreview/openExternal:app',
181
+ create: _khorsheed_dsh_file_preview_filePreview_openExternal_parameter_2$schema,
182
+ schema: _khorsheed_dsh_file_preview_filePreview_openExternal_parameter_2$schema(),
183
+ },
184
+ },
185
+ ],
186
+ cancellation: { parameter: 'signal' },
187
+ result: {
188
+ mode: 'strict',
189
+ typeSymbol: '@khorsheed/dsh-file-preview/types#FilePreviewOpenExternal',
190
+ create: _khorsheed_dsh_file_preview_filePreview_openExternal_result$schema,
191
+ schema: _khorsheed_dsh_file_preview_filePreview_openExternal_result$schema(),
92
192
  },
93
- sourceLocation: {"file":"packages/file-preview/src/index.ts","line":368,"column":9},
193
+ sourceLocation: {"file":"packages/file-preview/src/index.ts","line":539,"column":9},
94
194
  },
95
195
  {
96
196
  id: '@khorsheed/dsh-file-preview#filePreview/read',
@@ -111,7 +211,8 @@ export const TYPERT_REMOTE = {
111
211
  codec: {
112
212
  mode: 'strict',
113
213
  typeSymbol: '@deepseek-ai/dsh-session/types#SessionId',
114
- schema: _khorsheed_dsh_file_preview_filePreview_read_parameter_0$schema,
214
+ create: _khorsheed_dsh_file_preview_filePreview_read_parameter_0$schema,
215
+ schema: _khorsheed_dsh_file_preview_filePreview_read_parameter_0$schema(),
115
216
  },
116
217
  },
117
218
  {
@@ -121,7 +222,8 @@ export const TYPERT_REMOTE = {
121
222
  codec: {
122
223
  mode: 'strict',
123
224
  typeSymbol: '@khorsheed/dsh-file-preview#filePreview/read:path',
124
- schema: _khorsheed_dsh_file_preview_filePreview_read_parameter_1$schema,
225
+ create: _khorsheed_dsh_file_preview_filePreview_read_parameter_1$schema,
226
+ schema: _khorsheed_dsh_file_preview_filePreview_read_parameter_1$schema(),
125
227
  },
126
228
  },
127
229
  ],
@@ -129,9 +231,10 @@ export const TYPERT_REMOTE = {
129
231
  result: {
130
232
  mode: 'strict',
131
233
  typeSymbol: '@khorsheed/dsh-file-preview/types#FilePreviewRead',
132
- schema: _khorsheed_dsh_file_preview_filePreview_read_result$schema,
234
+ create: _khorsheed_dsh_file_preview_filePreview_read_result$schema,
235
+ schema: _khorsheed_dsh_file_preview_filePreview_read_result$schema(),
133
236
  },
134
- sourceLocation: {"file":"packages/file-preview/src/index.ts","line":458,"column":9},
237
+ sourceLocation: {"file":"packages/file-preview/src/index.ts","line":409,"column":9},
135
238
  },
136
239
  {
137
240
  id: '@khorsheed/dsh-file-preview#filePreview/reveal',
@@ -152,7 +255,8 @@ export const TYPERT_REMOTE = {
152
255
  codec: {
153
256
  mode: 'strict',
154
257
  typeSymbol: '@deepseek-ai/dsh-session/types#SessionId',
155
- schema: _khorsheed_dsh_file_preview_filePreview_reveal_parameter_0$schema,
258
+ create: _khorsheed_dsh_file_preview_filePreview_reveal_parameter_0$schema,
259
+ schema: _khorsheed_dsh_file_preview_filePreview_reveal_parameter_0$schema(),
156
260
  },
157
261
  },
158
262
  {
@@ -162,7 +266,8 @@ export const TYPERT_REMOTE = {
162
266
  codec: {
163
267
  mode: 'strict',
164
268
  typeSymbol: '@khorsheed/dsh-file-preview#filePreview/reveal:path',
165
- schema: _khorsheed_dsh_file_preview_filePreview_reveal_parameter_1$schema,
269
+ create: _khorsheed_dsh_file_preview_filePreview_reveal_parameter_1$schema,
270
+ schema: _khorsheed_dsh_file_preview_filePreview_reveal_parameter_1$schema(),
166
271
  },
167
272
  },
168
273
  ],
@@ -170,9 +275,10 @@ export const TYPERT_REMOTE = {
170
275
  result: {
171
276
  mode: 'strict',
172
277
  typeSymbol: '@khorsheed/dsh-file-preview/types#FilePreviewReveal',
173
- schema: _khorsheed_dsh_file_preview_filePreview_reveal_result$schema,
278
+ create: _khorsheed_dsh_file_preview_filePreview_reveal_result$schema,
279
+ schema: _khorsheed_dsh_file_preview_filePreview_reveal_result$schema(),
174
280
  },
175
- sourceLocation: {"file":"packages/file-preview/src/index.ts","line":535,"column":9},
281
+ sourceLocation: {"file":"packages/file-preview/src/index.ts","line":489,"column":9},
176
282
  },
177
283
  {
178
284
  id: '@khorsheed/dsh-file-preview#filePreview/turnFiles',
@@ -193,16 +299,18 @@ export const TYPERT_REMOTE = {
193
299
  codec: {
194
300
  mode: 'strict',
195
301
  typeSymbol: '@deepseek-ai/dsh-session/types#SessionId',
196
- schema: _khorsheed_dsh_file_preview_filePreview_turnFiles_parameter_0$schema,
302
+ create: _khorsheed_dsh_file_preview_filePreview_turnFiles_parameter_0$schema,
303
+ schema: _khorsheed_dsh_file_preview_filePreview_turnFiles_parameter_0$schema(),
197
304
  },
198
305
  },
199
306
  ],
200
307
  result: {
201
308
  mode: 'strict',
202
309
  typeSymbol: '@khorsheed/dsh-file-preview/types#FilePreviewTurnMap',
203
- schema: _khorsheed_dsh_file_preview_filePreview_turnFiles_result$schema,
310
+ create: _khorsheed_dsh_file_preview_filePreview_turnFiles_result$schema,
311
+ schema: _khorsheed_dsh_file_preview_filePreview_turnFiles_result$schema(),
204
312
  },
205
- sourceLocation: {"file":"packages/file-preview/src/index.ts","line":405,"column":9},
313
+ sourceLocation: {"file":"packages/file-preview/src/index.ts","line":353,"column":9},
206
314
  },
207
315
  ],
208
316
  }
@@ -26,10 +26,11 @@ 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, or
30
- * `tool/ptc-dispatch` on seats running the PTC rename) count too —
31
- * they carry no turn/step of their own, so the entry borrows the enclosing
32
- * root call's location.
29
+ * Nested PTC file dispatches (`tool/ptc-dispatch` events — the host's Code
30
+ * Mode name through 0.1.2, renamed with the 0.1.5 format; the v2→v3 log
31
+ * migration renames persisted rows, so only the ptc name is matched) count
32
+ * too — they carry no turn/step of their own, so the entry borrows the
33
+ * enclosing root call's location.
33
34
  * @param events - the session's events in ascending seq order.
34
35
  * @param maxFiles - cap on returned entries; excess files are dropped in
35
36
  * first-seen order after the cap is reached.
@@ -58,7 +59,7 @@ export type TurnFilesByTurn = ReadonlyMap<number, ReadonlyMap<string, TurnFileFa
58
59
  * turn maps, so each turn's card lists exactly what that turn mutated.
59
60
  * Reads leave no card entry (the card is the mutation vocabulary — write/edit
60
61
  * 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
+ * their own turn; nested PTC dispatches borrow the enclosing root call's
62
63
  * turn (dispatch events carry none); a `tool/result` whose presentation meta
63
64
  * carries diffs registers its paths (the render-intent vocabulary) with the
64
65
  * result's turn, and per-turn line deltas are summed from the diffs. A `write` whose result carries no diffs is a
@@ -69,7 +70,7 @@ export type TurnFilesByTurn = ReadonlyMap<number, ReadonlyMap<string, TurnFileFa
69
70
  * Count discipline: a write/edit tool/call only registers the path's location
70
71
  * and never touches counts (its counted result follows); the first count
71
72
  * contribution for a turn+path is adopted verbatim, later ones accumulate per
72
- * field with unknown-wins — an uncounted mutation (a Code Mode dispatch, or a
73
+ * field with unknown-wins — an uncounted mutation (a PTC dispatch, or a
73
74
  * diff whose side reports no prior content) poisons that field to undefined
74
75
  * rather than reporting a misleading partial.
75
76
  * @param events - the session's events in ascending seq order.
package/lib/types/fold.js CHANGED
@@ -1,14 +1,6 @@
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']);
12
4
  /** The argument key carrying the touched path (shared by all three file tools). */
13
5
  const FILE_PATH_ARGUMENT = 'file_path';
14
6
  /**
@@ -65,10 +57,11 @@ export function diffsFromResultMeta(meta) {
65
57
  * first-seen order and deduplicated by display path; a later occurrence
66
58
  * refreshes the entry's op and location without moving it, and each write/edit
67
59
  * tool result appends its change's diff to the entry's `diffs` in event order.
68
- * Nested Code Mode file dispatches (`tool/code-dispatch` events, or
69
- * `tool/ptc-dispatch` on seats running the PTC rename) count too —
70
- * they carry no turn/step of their own, so the entry borrows the enclosing
71
- * root call's location.
60
+ * Nested PTC file dispatches (`tool/ptc-dispatch` events — the host's Code
61
+ * Mode name through 0.1.2, renamed with the 0.1.5 format; the v2→v3 log
62
+ * migration renames persisted rows, so only the ptc name is matched) count
63
+ * too — they carry no turn/step of their own, so the entry borrows the
64
+ * enclosing root call's location.
72
65
  * @param events - the session's events in ascending seq order.
73
66
  * @param maxFiles - cap on returned entries; excess files are dropped in
74
67
  * first-seen order after the cap is reached.
@@ -76,7 +69,7 @@ export function diffsFromResultMeta(meta) {
76
69
  */
77
70
  export function foldFilePreview(events, maxFiles) {
78
71
  const entries = new Map();
79
- /** Root tool/call locations, so nested code dispatches borrow their turn/step. */
72
+ /** Root tool/call locations, so nested dispatches borrow their turn/step. */
80
73
  const callSites = new Map();
81
74
  let asOfSeq = -1;
82
75
  /** Upsert one touched path, refreshing a repeat in place and keeping its diffs. */
@@ -97,19 +90,16 @@ export function foldFilePreview(events, maxFiles) {
97
90
  record(target, event.seq, event.data.turn, event.data.step);
98
91
  continue;
99
92
  }
100
- if (DISPATCH_EVENT_NAMES.has(event.type)) {
93
+ if (event.type === 'tool/ptc-dispatch') {
101
94
  // The dispatch event IS the settled outcome: a failed sub-call changed
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
+ // nothing, so only successful file touches record.
96
+ if (event.data.isError)
107
97
  continue;
108
- const target = targetFromArguments(dispatch.data.name, dispatch.data.arguments);
98
+ const target = targetFromArguments(event.data.name, event.data.arguments);
109
99
  if (target === undefined)
110
100
  continue;
111
- const site = callSites.get(String(dispatch.data.rootCallId)) ?? { turn: 0, step: 0 };
112
- record(target, dispatch.seq, site.turn, site.step);
101
+ const site = callSites.get(String(event.data.rootCallId)) ?? { turn: 0, step: 0 };
102
+ record(target, event.seq, site.turn, site.step);
113
103
  continue;
114
104
  }
115
105
  if (event.type === 'tool/result') {
@@ -172,8 +162,13 @@ function contentFromWriteCall(argumentsJson) {
172
162
  }
173
163
  return undefined;
174
164
  }
175
- /** Read the tool-result block's call identity and failure flag off a result message. */
165
+ /** Read the result message's call identity and failure flag. V4's first-class
166
+ * tool role puts both on the message itself; V3 wrapped them in the leading
167
+ * `tool-result` content block — read the message level first, then the block. */
176
168
  function resultCallFacts(message) {
169
+ if (typeof message.toolCallId === 'string') {
170
+ return { callId: message.toolCallId, isError: message.isError === true };
171
+ }
177
172
  const block = message.content[0];
178
173
  if (block?.type !== 'tool-result' || typeof block.toolCallId !== 'string')
179
174
  return undefined;
@@ -186,7 +181,7 @@ function resultCallFacts(message) {
186
181
  * turn maps, so each turn's card lists exactly what that turn mutated.
187
182
  * Reads leave no card entry (the card is the mutation vocabulary — write/edit
188
183
  * 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
184
+ * their own turn; nested PTC dispatches borrow the enclosing root call's
190
185
  * turn (dispatch events carry none); a `tool/result` whose presentation meta
191
186
  * carries diffs registers its paths (the render-intent vocabulary) with the
192
187
  * result's turn, and per-turn line deltas are summed from the diffs. A `write` whose result carries no diffs is a
@@ -197,7 +192,7 @@ function resultCallFacts(message) {
197
192
  * Count discipline: a write/edit tool/call only registers the path's location
198
193
  * and never touches counts (its counted result follows); the first count
199
194
  * contribution for a turn+path is adopted verbatim, later ones accumulate per
200
- * field with unknown-wins — an uncounted mutation (a Code Mode dispatch, or a
195
+ * field with unknown-wins — an uncounted mutation (a PTC dispatch, or a
201
196
  * diff whose side reports no prior content) poisons that field to undefined
202
197
  * rather than reporting a misleading partial.
203
198
  * @param events - the session's events in ascending seq order.
@@ -205,7 +200,7 @@ function resultCallFacts(message) {
205
200
  */
206
201
  export function foldFilePreviewByTurn(events) {
207
202
  const byTurn = new Map();
208
- /** Root tool/call locations, so nested code dispatches borrow their turn/step. */
203
+ /** Root tool/call locations, so nested dispatches borrow their turn/step. */
209
204
  const callSites = new Map();
210
205
  /** Write-tool calls keyed by callId (create fallback; see {@link WriteCallFacts}). */
211
206
  const writeCalls = new Map();
@@ -235,7 +230,7 @@ export function foldFilePreviewByTurn(events) {
235
230
  * a turn+path is adopted verbatim (a count-less placeholder from a
236
231
  * preceding tool/call must not poison it); later contributions accumulate
237
232
  * per field with unknown-wins. `unknown` marks an uncountable mutation (a
238
- * Code Mode dispatch): it poisons both fields. */
233
+ * PTC dispatch): it poisons both fields. */
239
234
  const recordContribution = (path, turn, seq, step, added, removed, unknown) => {
240
235
  const map = turnMap(turn);
241
236
  const key = countKey(turn, path);
@@ -271,7 +266,7 @@ export function foldFilePreviewByTurn(events) {
271
266
  if (target === undefined)
272
267
  continue;
273
268
  // The card's vocabulary is mutations only: a read call registers
274
- // nothing (it may still anchor a nested code dispatch's location via
269
+ // nothing (it may still anchor a nested dispatch's location via
275
270
  // callSites above).
276
271
  if (target.op === 'read')
277
272
  continue;
@@ -286,24 +281,22 @@ export function foldFilePreviewByTurn(events) {
286
281
  recordLocation(target.path, event.data.turn, event.seq, event.data.step);
287
282
  continue;
288
283
  }
289
- if (DISPATCH_EVENT_NAMES.has(event.type)) {
284
+ if (event.type === 'tool/ptc-dispatch') {
290
285
  // The dispatch event IS the settled outcome: a failed sub-call changed
291
- // nothing, so only successful file touches record. Code Mode writes are
286
+ // nothing, so only successful file touches record. PTC writes are
292
287
  // uncountable (no result diffs reach the session), so they register the
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)
288
+ // path and poison the line-count totals (unknown wins).
289
+ if (event.data.isError)
297
290
  continue;
298
- const target = targetFromArguments(dispatch.data.name, dispatch.data.arguments);
291
+ const target = targetFromArguments(event.data.name, event.data.arguments);
299
292
  if (target === undefined)
300
293
  continue;
301
294
  // Reads leave no card entry here too — only mutations register.
302
295
  if (target.op === 'read')
303
296
  continue;
304
- const site = callSites.get(String(dispatch.data.rootCallId)) ?? { turn: 0, step: 0 };
297
+ const site = callSites.get(String(event.data.rootCallId)) ?? { turn: 0, step: 0 };
305
298
  sessionSeen.add(target.path);
306
- recordContribution(target.path, site.turn, dispatch.seq, site.step, undefined, undefined, true);
299
+ recordContribution(target.path, site.turn, event.seq, site.step, undefined, undefined, true);
307
300
  continue;
308
301
  }
309
302
  if (event.type === 'tool/result') {
@@ -5,7 +5,7 @@ import type { Context } from '@deepseek-ai/cordis';
5
5
  import type { Agent } from '@deepseek-ai/dsh-agent';
6
6
  import { TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol';
7
7
  import z from '@deepseek-ai/schemastery';
8
- import type { FilePreviewConfig, FilePreviewList, FilePreviewRead, FilePreviewReveal, FilePreviewTurnMap } from './types.ts';
8
+ import type { FilePreviewConfig, FilePreviewList, FilePreviewOpenExternal, FilePreviewRead, FilePreviewReveal, FilePreviewTurnMap } from './types.ts';
9
9
  declare module '@deepseek-ai/cordis' {
10
10
  interface Context {
11
11
  filePreview: FilePreviewService;
@@ -33,6 +33,8 @@ export declare class FilePreviewService extends TypertRemoteService {
33
33
  private readonly agents;
34
34
  /** Native reveal runner; a constructor seam for deterministic tests. */
35
35
  private readonly revealNative;
36
+ /** Native open-in-app runner; a constructor seam for deterministic tests. */
37
+ private readonly openExternalNative;
36
38
  /** Bash-write collector (S2 seam), or undefined when disabled in config. */
37
39
  private readonly collector;
38
40
  /** Per-session by-turn fold cache, invalidated by the log watermark. */
@@ -46,7 +48,12 @@ export declare class FilePreviewService extends TypertRemoteService {
46
48
  */
47
49
  constructor(ctx: Context, config?: FilePreviewConfig, deps?: {
48
50
  revealNative?: (path: string, signal: AbortSignal) => Promise<void>;
51
+ openExternalNative?: (path: string, app: string, signal: AbortSignal) => Promise<void>;
49
52
  });
53
+ /** Zero-session availability handshake for browser companions. */
54
+ capabilities(): {
55
+ protocolVersion: 1;
56
+ };
50
57
  private get fs();
51
58
  /**
52
59
  * Serve one image file's bytes for a browser `<img>` request. The URL is
@@ -81,7 +88,7 @@ export declare class FilePreviewService extends TypertRemoteService {
81
88
  /**
82
89
  * Every turn's file mutations for the turn-tail card — the single source of
83
90
  * truth the card renders (the client's old write/edit-only fold retired).
84
- * Built by folding the session log per turn (write/edit calls, Code Mode
91
+ * Built by folding the session log per turn (write/edit calls, PTC
85
92
  * dispatches borrowing the root call's turn, and render-intent paths from
86
93
  * result diff meta) and merging the collector's bash-written captures by
87
94
  * their own turn. The fold is cached per session and invalidated by the log
@@ -96,7 +103,10 @@ export declare class FilePreviewService extends TypertRemoteService {
96
103
  turnFiles(agent: Agent): Promise<FilePreviewTurnMap>;
97
104
  /**
98
105
  * Read the current content of one recorded file, resolved against the
99
- * session cwd and capped by `maxReadBytes`.
106
+ * session cwd and capped by `maxReadBytes`. The text read is a bounded byte
107
+ * window (`readByteRange` of cap + 1 bytes), so an oversized file costs the
108
+ * cap, never its full size; a known oversized stat still short-circuits to
109
+ * `too-large` before any bytes move.
100
110
  * @param agent - owning live agent; its session cwd anchors relative paths.
101
111
  * @param path - the display path recorded by the write/edit tool call.
102
112
  * @param signal - cooperative cancellation from the calling UI request.
@@ -118,6 +128,22 @@ export declare class FilePreviewService extends TypertRemoteService {
118
128
  * @returns whether the file manager selected the file, or why not.
119
129
  */
120
130
  reveal(agent: Agent, path: string, signal: AbortSignal): Promise<FilePreviewReveal>;
131
+ /**
132
+ * Open one recorded file in a specific host application (the "open in IDE"
133
+ * gesture). The official open-in-app route only accepts directories — a
134
+ * file path 404s — so file-exact opens go through this method: macOS
135
+ * `open -a <App> <path>` via the same native-command runner reveal uses.
136
+ * The browser names the application by official open-in-app catalog id
137
+ * (probed from `/open-in-app/apps`); the id → app-name map lives in
138
+ * open-external.ts. Non-macOS hosts and unknown ids answer without
139
+ * launching, and the client hides the gesture.
140
+ * @param agent - owning live agent; its session cwd anchors relative paths.
141
+ * @param path - the display path recorded by the read/write/edit tool call.
142
+ * @param app - official open-in-app catalog id (e.g. `cursor`).
143
+ * @param signal - cooperative cancellation from the calling UI request.
144
+ * @returns whether the application launched, or why not.
145
+ */
146
+ openExternal(agent: Agent, path: string, app: string, signal: AbortSignal): Promise<FilePreviewOpenExternal>;
121
147
  }
122
148
  export default FilePreviewService;
123
149
  //# sourceMappingURL=index.d.ts.map