@khorsheed/dsh-file-preview 0.1.1 → 0.3.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 +26 -0
- package/README.en.md +20 -13
- package/README.i18n.yaml +2 -2
- package/README.md +34 -27
- package/lib/index.js +238 -86
- package/lib/typert.host.js +249 -49
- package/lib/typert.remote-client.d.ts +6 -1
- package/lib/typert.remote-client.js +83 -5
- package/lib/types/bash-writes.js +1 -1
- package/lib/types/fold.d.ts +12 -9
- package/lib/types/fold.js +26 -15
- package/lib/types/index.d.ts +51 -10
- package/lib/types/index.js +131 -68
- package/lib/types/open-external.d.ts +37 -0
- package/lib/types/open-external.js +61 -0
- package/lib/types/types.d.ts +11 -1
- package/package.json +14 -14
- package/lib/tsconfig.tsbuildinfo +0 -1
- package/lib/typert.remote-client.d.ts.map +0 -1
- package/lib/types/bash-writes.d.ts.map +0 -1
- package/lib/types/fold.d.ts.map +0 -1
- package/lib/types/index.d.ts.map +0 -1
- package/lib/types/invariant.d.ts.map +0 -1
- package/lib/types/reveal.d.ts.map +0 -1
- package/lib/types/types.d.ts.map +0 -1
- package/skills/3d-artifact/SKILL.md +0 -52
|
@@ -1,6 +1,9 @@
|
|
|
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_capabilities_result$schema = z.object({
|
|
5
|
+
'protocolVersion': z.literal(1),
|
|
6
|
+
})
|
|
4
7
|
const _khorsheed_dsh_file_preview_filePreview_list_parameter_0$schema = z.intersection(z.string(), z.unknown())
|
|
5
8
|
const _khorsheed_dsh_file_preview_filePreview_list_result$schema = z.object({
|
|
6
9
|
'entries': z.array(z.object({
|
|
@@ -24,11 +27,20 @@ const _khorsheed_dsh_file_preview_filePreview_list_result$schema = z.object({
|
|
|
24
27
|
'asOfSeq': z.number().readonly(),
|
|
25
28
|
'truncated': z.boolean().readonly(),
|
|
26
29
|
})
|
|
30
|
+
const _khorsheed_dsh_file_preview_filePreview_openExternal_parameter_0$schema = z.intersection(z.string(), z.unknown())
|
|
31
|
+
const _khorsheed_dsh_file_preview_filePreview_openExternal_parameter_1$schema = z.string()
|
|
32
|
+
const _khorsheed_dsh_file_preview_filePreview_openExternal_parameter_2$schema = z.string()
|
|
33
|
+
const _khorsheed_dsh_file_preview_filePreview_openExternal_result$schema = z.union([z.object({
|
|
34
|
+
'opened': z.literal(true).readonly(),
|
|
35
|
+
}), z.object({
|
|
36
|
+
'opened': z.literal(false).readonly(),
|
|
37
|
+
'reason': z.union([z.literal("missing"), z.literal("unknown-app"), z.literal("unsupported-platform"), z.literal("launch-failed")]).readonly(),
|
|
38
|
+
})])
|
|
27
39
|
const _khorsheed_dsh_file_preview_filePreview_read_parameter_0$schema = z.intersection(z.string(), z.unknown())
|
|
28
40
|
const _khorsheed_dsh_file_preview_filePreview_read_parameter_1$schema = z.string()
|
|
29
41
|
const _khorsheed_dsh_file_preview_filePreview_read_result$schema = z.object({
|
|
30
42
|
'path': z.string().readonly(),
|
|
31
|
-
'kind': z.union([z.literal("
|
|
43
|
+
'kind': z.union([z.literal("missing"), z.literal("error"), z.literal("text"), z.literal("image"), z.literal("binary"), z.literal("too-large")]).readonly(),
|
|
32
44
|
'content': z.string().readonly().optional(),
|
|
33
45
|
'url': z.string().readonly().optional(),
|
|
34
46
|
'truncated': z.boolean().readonly().optional(),
|
|
@@ -62,6 +74,21 @@ const _khorsheed_dsh_file_preview_filePreview_turnFiles_result$schema = z.object
|
|
|
62
74
|
export const TYPERT_REMOTE = {
|
|
63
75
|
package: '@khorsheed/dsh-file-preview',
|
|
64
76
|
descriptors: [
|
|
77
|
+
{
|
|
78
|
+
id: '@khorsheed/dsh-file-preview#filePreview/capabilities',
|
|
79
|
+
service: 'filePreview',
|
|
80
|
+
namespace: 'filePreview',
|
|
81
|
+
method: 'capabilities',
|
|
82
|
+
invocation: { kind: 'direct' },
|
|
83
|
+
parameters: [
|
|
84
|
+
],
|
|
85
|
+
result: {
|
|
86
|
+
mode: 'strict',
|
|
87
|
+
typeSymbol: '@khorsheed/dsh-file-preview#filePreview/capabilities:result',
|
|
88
|
+
schema: _khorsheed_dsh_file_preview_filePreview_capabilities_result$schema,
|
|
89
|
+
},
|
|
90
|
+
sourceLocation: {"file":"packages/file-preview/src/index.ts","line":191,"column":3},
|
|
91
|
+
},
|
|
65
92
|
{
|
|
66
93
|
id: '@khorsheed/dsh-file-preview#filePreview/list',
|
|
67
94
|
service: 'filePreview',
|
|
@@ -90,7 +117,58 @@ export const TYPERT_REMOTE = {
|
|
|
90
117
|
typeSymbol: '@khorsheed/dsh-file-preview/types#FilePreviewList',
|
|
91
118
|
schema: _khorsheed_dsh_file_preview_filePreview_list_result$schema,
|
|
92
119
|
},
|
|
93
|
-
sourceLocation: {"file":"packages/file-preview/src/index.ts","line":
|
|
120
|
+
sourceLocation: {"file":"packages/file-preview/src/index.ts","line":311,"column":9},
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
id: '@khorsheed/dsh-file-preview#filePreview/openExternal',
|
|
124
|
+
service: 'filePreview',
|
|
125
|
+
namespace: 'filePreview',
|
|
126
|
+
method: 'openExternal',
|
|
127
|
+
invocation: { kind: 'direct' },
|
|
128
|
+
scope: {
|
|
129
|
+
context: 'agent',
|
|
130
|
+
wire: 'agentId',
|
|
131
|
+
},
|
|
132
|
+
parameters: [
|
|
133
|
+
{
|
|
134
|
+
name: 'agent',
|
|
135
|
+
wire: 'agentId',
|
|
136
|
+
source: 'lookup',
|
|
137
|
+
lookup: 'agent',
|
|
138
|
+
codec: {
|
|
139
|
+
mode: 'strict',
|
|
140
|
+
typeSymbol: '@deepseek-ai/dsh-session/types#SessionId',
|
|
141
|
+
schema: _khorsheed_dsh_file_preview_filePreview_openExternal_parameter_0$schema,
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
name: 'path',
|
|
146
|
+
wire: 'path',
|
|
147
|
+
source: 'json',
|
|
148
|
+
codec: {
|
|
149
|
+
mode: 'strict',
|
|
150
|
+
typeSymbol: '@khorsheed/dsh-file-preview#filePreview/openExternal:path',
|
|
151
|
+
schema: _khorsheed_dsh_file_preview_filePreview_openExternal_parameter_1$schema,
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
name: 'app',
|
|
156
|
+
wire: 'app',
|
|
157
|
+
source: 'json',
|
|
158
|
+
codec: {
|
|
159
|
+
mode: 'strict',
|
|
160
|
+
typeSymbol: '@khorsheed/dsh-file-preview#filePreview/openExternal:app',
|
|
161
|
+
schema: _khorsheed_dsh_file_preview_filePreview_openExternal_parameter_2$schema,
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
],
|
|
165
|
+
cancellation: { parameter: 'signal' },
|
|
166
|
+
result: {
|
|
167
|
+
mode: 'strict',
|
|
168
|
+
typeSymbol: '@khorsheed/dsh-file-preview/types#FilePreviewOpenExternal',
|
|
169
|
+
schema: _khorsheed_dsh_file_preview_filePreview_openExternal_result$schema,
|
|
170
|
+
},
|
|
171
|
+
sourceLocation: {"file":"packages/file-preview/src/index.ts","line":528,"column":9},
|
|
94
172
|
},
|
|
95
173
|
{
|
|
96
174
|
id: '@khorsheed/dsh-file-preview#filePreview/read',
|
|
@@ -131,7 +209,7 @@ export const TYPERT_REMOTE = {
|
|
|
131
209
|
typeSymbol: '@khorsheed/dsh-file-preview/types#FilePreviewRead',
|
|
132
210
|
schema: _khorsheed_dsh_file_preview_filePreview_read_result$schema,
|
|
133
211
|
},
|
|
134
|
-
sourceLocation: {"file":"packages/file-preview/src/index.ts","line":
|
|
212
|
+
sourceLocation: {"file":"packages/file-preview/src/index.ts","line":401,"column":9},
|
|
135
213
|
},
|
|
136
214
|
{
|
|
137
215
|
id: '@khorsheed/dsh-file-preview#filePreview/reveal',
|
|
@@ -172,7 +250,7 @@ export const TYPERT_REMOTE = {
|
|
|
172
250
|
typeSymbol: '@khorsheed/dsh-file-preview/types#FilePreviewReveal',
|
|
173
251
|
schema: _khorsheed_dsh_file_preview_filePreview_reveal_result$schema,
|
|
174
252
|
},
|
|
175
|
-
sourceLocation: {"file":"packages/file-preview/src/index.ts","line":
|
|
253
|
+
sourceLocation: {"file":"packages/file-preview/src/index.ts","line":478,"column":9},
|
|
176
254
|
},
|
|
177
255
|
{
|
|
178
256
|
id: '@khorsheed/dsh-file-preview#filePreview/turnFiles',
|
|
@@ -202,7 +280,7 @@ export const TYPERT_REMOTE = {
|
|
|
202
280
|
typeSymbol: '@khorsheed/dsh-file-preview/types#FilePreviewTurnMap',
|
|
203
281
|
schema: _khorsheed_dsh_file_preview_filePreview_turnFiles_result$schema,
|
|
204
282
|
},
|
|
205
|
-
sourceLocation: {"file":"packages/file-preview/src/index.ts","line":
|
|
283
|
+
sourceLocation: {"file":"packages/file-preview/src/index.ts","line":348,"column":9},
|
|
206
284
|
},
|
|
207
285
|
],
|
|
208
286
|
}
|
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,9 +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
|
|
30
|
-
*
|
|
31
|
-
*
|
|
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.
|
|
32
34
|
* @param events - the session's events in ascending seq order.
|
|
33
35
|
* @param maxFiles - cap on returned entries; excess files are dropped in
|
|
34
36
|
* first-seen order after the cap is reached.
|
|
@@ -55,11 +57,12 @@ export type TurnFilesByTurn = ReadonlyMap<number, ReadonlyMap<string, TurnFileFa
|
|
|
55
57
|
* single source of truth. Unlike {@link foldFilePreview}, this does NOT dedupe
|
|
56
58
|
* a path to its last occurrence: a file touched in two turns appears in BOTH
|
|
57
59
|
* turn maps, so each turn's card lists exactly what that turn mutated.
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
60
|
+
* Reads leave no card entry (the card is the mutation vocabulary — write/edit
|
|
61
|
+
* only), so a pure-read call never registers; write/edit calls register with
|
|
62
|
+
* their own turn; nested PTC dispatches borrow the enclosing root call's
|
|
63
|
+
* turn (dispatch events carry none); a `tool/result` whose presentation meta
|
|
64
|
+
* carries diffs registers its paths (the render-intent vocabulary) with the
|
|
65
|
+
* result's turn, and per-turn line deltas are summed from the diffs. A `write` whose result carries no diffs is a
|
|
63
66
|
* create (the write tool records no diffs when the file had no prior content):
|
|
64
67
|
* its full written content — read from the call arguments, which the log keeps
|
|
65
68
|
* — is the added-line count, once per file per turn.
|
|
@@ -67,7 +70,7 @@ export type TurnFilesByTurn = ReadonlyMap<number, ReadonlyMap<string, TurnFileFa
|
|
|
67
70
|
* Count discipline: a write/edit tool/call only registers the path's location
|
|
68
71
|
* and never touches counts (its counted result follows); the first count
|
|
69
72
|
* contribution for a turn+path is adopted verbatim, later ones accumulate per
|
|
70
|
-
* field with unknown-wins — an uncounted mutation (a
|
|
73
|
+
* field with unknown-wins — an uncounted mutation (a PTC dispatch, or a
|
|
71
74
|
* diff whose side reports no prior content) poisons that field to undefined
|
|
72
75
|
* rather than reporting a misleading partial.
|
|
73
76
|
* @param events - the session's events in ascending seq order.
|
package/lib/types/fold.js
CHANGED
|
@@ -57,9 +57,11 @@ export function diffsFromResultMeta(meta) {
|
|
|
57
57
|
* first-seen order and deduplicated by display path; a later occurrence
|
|
58
58
|
* refreshes the entry's op and location without moving it, and each write/edit
|
|
59
59
|
* tool result appends its change's diff to the entry's `diffs` in event order.
|
|
60
|
-
* Nested
|
|
61
|
-
*
|
|
62
|
-
*
|
|
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.
|
|
63
65
|
* @param events - the session's events in ascending seq order.
|
|
64
66
|
* @param maxFiles - cap on returned entries; excess files are dropped in
|
|
65
67
|
* first-seen order after the cap is reached.
|
|
@@ -67,7 +69,7 @@ export function diffsFromResultMeta(meta) {
|
|
|
67
69
|
*/
|
|
68
70
|
export function foldFilePreview(events, maxFiles) {
|
|
69
71
|
const entries = new Map();
|
|
70
|
-
/** Root tool/call locations, so nested
|
|
72
|
+
/** Root tool/call locations, so nested dispatches borrow their turn/step. */
|
|
71
73
|
const callSites = new Map();
|
|
72
74
|
let asOfSeq = -1;
|
|
73
75
|
/** Upsert one touched path, refreshing a repeat in place and keeping its diffs. */
|
|
@@ -88,7 +90,7 @@ export function foldFilePreview(events, maxFiles) {
|
|
|
88
90
|
record(target, event.seq, event.data.turn, event.data.step);
|
|
89
91
|
continue;
|
|
90
92
|
}
|
|
91
|
-
if (event.type === 'tool/
|
|
93
|
+
if (event.type === 'tool/ptc-dispatch') {
|
|
92
94
|
// The dispatch event IS the settled outcome: a failed sub-call changed
|
|
93
95
|
// nothing, so only successful file touches record.
|
|
94
96
|
if (event.data.isError)
|
|
@@ -172,11 +174,12 @@ function resultCallFacts(message) {
|
|
|
172
174
|
* single source of truth. Unlike {@link foldFilePreview}, this does NOT dedupe
|
|
173
175
|
* a path to its last occurrence: a file touched in two turns appears in BOTH
|
|
174
176
|
* turn maps, so each turn's card lists exactly what that turn mutated.
|
|
175
|
-
*
|
|
176
|
-
*
|
|
177
|
-
*
|
|
178
|
-
*
|
|
179
|
-
*
|
|
177
|
+
* Reads leave no card entry (the card is the mutation vocabulary — write/edit
|
|
178
|
+
* only), so a pure-read call never registers; write/edit calls register with
|
|
179
|
+
* their own turn; nested PTC dispatches borrow the enclosing root call's
|
|
180
|
+
* turn (dispatch events carry none); a `tool/result` whose presentation meta
|
|
181
|
+
* carries diffs registers its paths (the render-intent vocabulary) with the
|
|
182
|
+
* result's turn, and per-turn line deltas are summed from the diffs. A `write` whose result carries no diffs is a
|
|
180
183
|
* create (the write tool records no diffs when the file had no prior content):
|
|
181
184
|
* its full written content — read from the call arguments, which the log keeps
|
|
182
185
|
* — is the added-line count, once per file per turn.
|
|
@@ -184,7 +187,7 @@ function resultCallFacts(message) {
|
|
|
184
187
|
* Count discipline: a write/edit tool/call only registers the path's location
|
|
185
188
|
* and never touches counts (its counted result follows); the first count
|
|
186
189
|
* contribution for a turn+path is adopted verbatim, later ones accumulate per
|
|
187
|
-
* field with unknown-wins — an uncounted mutation (a
|
|
190
|
+
* field with unknown-wins — an uncounted mutation (a PTC dispatch, or a
|
|
188
191
|
* diff whose side reports no prior content) poisons that field to undefined
|
|
189
192
|
* rather than reporting a misleading partial.
|
|
190
193
|
* @param events - the session's events in ascending seq order.
|
|
@@ -192,7 +195,7 @@ function resultCallFacts(message) {
|
|
|
192
195
|
*/
|
|
193
196
|
export function foldFilePreviewByTurn(events) {
|
|
194
197
|
const byTurn = new Map();
|
|
195
|
-
/** Root tool/call locations, so nested
|
|
198
|
+
/** Root tool/call locations, so nested dispatches borrow their turn/step. */
|
|
196
199
|
const callSites = new Map();
|
|
197
200
|
/** Write-tool calls keyed by callId (create fallback; see {@link WriteCallFacts}). */
|
|
198
201
|
const writeCalls = new Map();
|
|
@@ -222,7 +225,7 @@ export function foldFilePreviewByTurn(events) {
|
|
|
222
225
|
* a turn+path is adopted verbatim (a count-less placeholder from a
|
|
223
226
|
* preceding tool/call must not poison it); later contributions accumulate
|
|
224
227
|
* per field with unknown-wins. `unknown` marks an uncountable mutation (a
|
|
225
|
-
*
|
|
228
|
+
* PTC dispatch): it poisons both fields. */
|
|
226
229
|
const recordContribution = (path, turn, seq, step, added, removed, unknown) => {
|
|
227
230
|
const map = turnMap(turn);
|
|
228
231
|
const key = countKey(turn, path);
|
|
@@ -257,6 +260,11 @@ export function foldFilePreviewByTurn(events) {
|
|
|
257
260
|
const target = pathFromToolCall(event.data.name, event.data.arguments);
|
|
258
261
|
if (target === undefined)
|
|
259
262
|
continue;
|
|
263
|
+
// The card's vocabulary is mutations only: a read call registers
|
|
264
|
+
// nothing (it may still anchor a nested dispatch's location via
|
|
265
|
+
// callSites above).
|
|
266
|
+
if (target.op === 'read')
|
|
267
|
+
continue;
|
|
260
268
|
if (target.op === 'write') {
|
|
261
269
|
const content = contentFromWriteCall(event.data.arguments);
|
|
262
270
|
if (content !== undefined) {
|
|
@@ -268,9 +276,9 @@ export function foldFilePreviewByTurn(events) {
|
|
|
268
276
|
recordLocation(target.path, event.data.turn, event.seq, event.data.step);
|
|
269
277
|
continue;
|
|
270
278
|
}
|
|
271
|
-
if (event.type === 'tool/
|
|
279
|
+
if (event.type === 'tool/ptc-dispatch') {
|
|
272
280
|
// The dispatch event IS the settled outcome: a failed sub-call changed
|
|
273
|
-
// nothing, so only successful file touches record.
|
|
281
|
+
// nothing, so only successful file touches record. PTC writes are
|
|
274
282
|
// uncountable (no result diffs reach the session), so they register the
|
|
275
283
|
// path and poison the line-count totals (unknown wins).
|
|
276
284
|
if (event.data.isError)
|
|
@@ -278,6 +286,9 @@ export function foldFilePreviewByTurn(events) {
|
|
|
278
286
|
const target = targetFromArguments(event.data.name, event.data.arguments);
|
|
279
287
|
if (target === undefined)
|
|
280
288
|
continue;
|
|
289
|
+
// Reads leave no card entry here too — only mutations register.
|
|
290
|
+
if (target.op === 'read')
|
|
291
|
+
continue;
|
|
281
292
|
const site = callSites.get(String(event.data.rootCallId)) ?? { turn: 0, step: 0 };
|
|
282
293
|
sessionSeen.add(target.path);
|
|
283
294
|
recordContribution(target.path, site.turn, event.seq, site.step, undefined, undefined, true);
|
package/lib/types/index.d.ts
CHANGED
|
@@ -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;
|
|
@@ -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.
|
|
@@ -32,6 +33,8 @@ export declare class FilePreviewService extends TypertRemoteService {
|
|
|
32
33
|
private readonly agents;
|
|
33
34
|
/** Native reveal runner; a constructor seam for deterministic tests. */
|
|
34
35
|
private readonly revealNative;
|
|
36
|
+
/** Native open-in-app runner; a constructor seam for deterministic tests. */
|
|
37
|
+
private readonly openExternalNative;
|
|
35
38
|
/** Bash-write collector (S2 seam), or undefined when disabled in config. */
|
|
36
39
|
private readonly collector;
|
|
37
40
|
/** Per-session by-turn fold cache, invalidated by the log watermark. */
|
|
@@ -45,7 +48,12 @@ export declare class FilePreviewService extends TypertRemoteService {
|
|
|
45
48
|
*/
|
|
46
49
|
constructor(ctx: Context, config?: FilePreviewConfig, deps?: {
|
|
47
50
|
revealNative?: (path: string, signal: AbortSignal) => Promise<void>;
|
|
51
|
+
openExternalNative?: (path: string, app: string, signal: AbortSignal) => Promise<void>;
|
|
48
52
|
});
|
|
53
|
+
/** Zero-session availability handshake for browser companions. */
|
|
54
|
+
capabilities(): {
|
|
55
|
+
protocolVersion: 1;
|
|
56
|
+
};
|
|
49
57
|
private get fs();
|
|
50
58
|
/**
|
|
51
59
|
* Serve one image file's bytes for a browser `<img>` request. The URL is
|
|
@@ -55,27 +63,44 @@ export declare class FilePreviewService extends TypertRemoteService {
|
|
|
55
63
|
* @param res - the response to fill with bytes or an error status.
|
|
56
64
|
*/
|
|
57
65
|
private serveImage;
|
|
66
|
+
/** Resolve the session's recorded display paths against its cwd and keep only
|
|
67
|
+
* those that currently exist as a regular file. The products surfaces fold
|
|
68
|
+
* the session log (which is history, not disk state): a path the log wrote
|
|
69
|
+
* may have been cleaned up since (a temp script the turn deleted), and such
|
|
70
|
+
* a path is not a product to list. Existence is checked fresh on every call
|
|
71
|
+
* (never cached), so a deletion that lands after a fold is visible on the
|
|
72
|
+
* next fetch. Unresolvable/unstat-able paths are treated as absent.
|
|
73
|
+
* @param agent - owning live agent; its session cwd anchors relative paths.
|
|
74
|
+
* @param paths - the display paths to probe.
|
|
75
|
+
* @returns the subset that resolves to an existing regular file.
|
|
76
|
+
*/
|
|
77
|
+
private retainExisting;
|
|
58
78
|
/**
|
|
59
79
|
* List the files one session wrote or edited: the log fold plus any
|
|
60
80
|
* bash-written files the collector verified (the S2 seam), merged so a
|
|
61
|
-
* captured path the fold already knows keeps its log-derived entry.
|
|
81
|
+
* captured path the fold already knows keeps its log-derived entry. Only
|
|
82
|
+
* paths that currently exist on disk are returned — a file the session
|
|
83
|
+
* wrote and later deleted is history, not a product.
|
|
62
84
|
* @param agent - owning live agent; its session log is the data source.
|
|
63
|
-
* @returns first-seen files capped by `maxFiles`, with the log watermark.
|
|
85
|
+
* @returns existing first-seen files capped by `maxFiles`, with the log watermark.
|
|
64
86
|
*/
|
|
65
|
-
list(agent: Agent): FilePreviewList
|
|
87
|
+
list(agent: Agent): Promise<FilePreviewList>;
|
|
66
88
|
/**
|
|
67
89
|
* Every turn's file mutations for the turn-tail card — the single source of
|
|
68
90
|
* truth the card renders (the client's old write/edit-only fold retired).
|
|
69
|
-
* Built by folding the session log per turn (write/edit calls,
|
|
91
|
+
* Built by folding the session log per turn (write/edit calls, PTC
|
|
70
92
|
* dispatches borrowing the root call's turn, and render-intent paths from
|
|
71
93
|
* result diff meta) and merging the collector's bash-written captures by
|
|
72
94
|
* their own turn. The fold is cached per session and invalidated by the log
|
|
73
95
|
* 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.
|
|
96
|
+
* turns appears in BOTH turn groups — per-turn attribution is exact. Only
|
|
97
|
+
* paths that currently exist on disk are returned (a deleted temp script is
|
|
98
|
+
* history, not a product); existence is probed fresh on every call, so the
|
|
99
|
+
* cached fold is filtered per request rather than cached.
|
|
75
100
|
* @param agent - owning live agent; its session log is the data source.
|
|
76
|
-
* @returns per-turn file groups plus the scanned watermark.
|
|
101
|
+
* @returns existing per-turn file groups plus the scanned watermark.
|
|
77
102
|
*/
|
|
78
|
-
turnFiles(agent: Agent): FilePreviewTurnMap
|
|
103
|
+
turnFiles(agent: Agent): Promise<FilePreviewTurnMap>;
|
|
79
104
|
/**
|
|
80
105
|
* Read the current content of one recorded file, resolved against the
|
|
81
106
|
* session cwd and capped by `maxReadBytes`.
|
|
@@ -100,6 +125,22 @@ export declare class FilePreviewService extends TypertRemoteService {
|
|
|
100
125
|
* @returns whether the file manager selected the file, or why not.
|
|
101
126
|
*/
|
|
102
127
|
reveal(agent: Agent, path: string, signal: AbortSignal): Promise<FilePreviewReveal>;
|
|
128
|
+
/**
|
|
129
|
+
* Open one recorded file in a specific host application (the "open in IDE"
|
|
130
|
+
* gesture). The official open-in-app route only accepts directories — a
|
|
131
|
+
* file path 404s — so file-exact opens go through this method: macOS
|
|
132
|
+
* `open -a <App> <path>` via the same native-command runner reveal uses.
|
|
133
|
+
* The browser names the application by official open-in-app catalog id
|
|
134
|
+
* (probed from `/open-in-app/apps`); the id → app-name map lives in
|
|
135
|
+
* open-external.ts. Non-macOS hosts and unknown ids answer without
|
|
136
|
+
* launching, and the client hides the gesture.
|
|
137
|
+
* @param agent - owning live agent; its session cwd anchors relative paths.
|
|
138
|
+
* @param path - the display path recorded by the read/write/edit tool call.
|
|
139
|
+
* @param app - official open-in-app catalog id (e.g. `cursor`).
|
|
140
|
+
* @param signal - cooperative cancellation from the calling UI request.
|
|
141
|
+
* @returns whether the application launched, or why not.
|
|
142
|
+
*/
|
|
143
|
+
openExternal(agent: Agent, path: string, app: string, signal: AbortSignal): Promise<FilePreviewOpenExternal>;
|
|
103
144
|
}
|
|
104
145
|
export default FilePreviewService;
|
|
105
146
|
//# sourceMappingURL=index.d.ts.map
|