@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.
@@ -35,54 +35,12 @@ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn,
35
35
  if (target) Object.defineProperty(target, contextIn.name, descriptor);
36
36
  done = true;
37
37
  };
38
- import { readFileSync } from 'node:fs';
39
- import { dirname, join } from 'node:path';
40
- import { fileURLToPath } from 'node:url';
41
38
  import { Remote, TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol';
42
39
  import z from '@deepseek-ai/schemastery';
43
40
  import { BashWriteCollector } from './bash-writes.js';
44
41
  import { foldFilePreview, foldFilePreviewByTurn } from './fold.js';
42
+ import { openExternalNative, macAppName } from './open-external.js';
45
43
  import { revealNativePath } from './reveal.js';
46
- /**
47
- * Register the 3d-artifact skill — the generation-side contract for
48
- * sandbox-runnable interactive 3D / digital-twin single-file HTML (self-
49
- * contained, zero runtime network, GLB-inline zero-fetch models). Pull-based
50
- * discovery: an agent whose task involves generating such an HTML page finds
51
- * the contract through the skill catalog — no per-session push notice.
52
- * Optional: compositions without the skill capability skip the registration.
53
- * A missing/malformed shipped SKILL.md degrades to a warning — a discovery
54
- * aid must never take a boot down; the pack-smoke test owns the file's
55
- * presence in the tarball.
56
- * @param ctx - plugin context.
57
- */
58
- function registerArtifactSkill(ctx) {
59
- const skills = ctx.get('skills');
60
- if (skills === undefined) {
61
- // Not a crash: file preview degrades without the skill (and a minimal
62
- // composition may legitimately lack the capability). The line exists so a
63
- // host-API migration that drops or renames the skills service shows up in
64
- // boot logs instead of failing silently — same diagnostic as ankh-guard's
65
- // restart-skill registration; grep "skill .* not registered".
66
- ctx.logger.warn('file-preview: skills capability absent — the 3d-artifact skill is not registered');
67
- return;
68
- }
69
- try {
70
- const skillFile = join(dirname(fileURLToPath(import.meta.url)), '..', 'skills', '3d-artifact', 'SKILL.md');
71
- const raw = readFileSync(skillFile, 'utf8');
72
- const match = /^---\n([\s\S]*?)\n---\n([\s\S]*)$/.exec(raw);
73
- const name = /^name: (.+)$/m.exec(match?.[1] ?? '')?.[1]?.trim();
74
- const description = /^description: (.+)$/m.exec(match?.[1] ?? '')?.[1]?.trim();
75
- const content = match?.[2];
76
- if (match === null || name === undefined || description === undefined || content === undefined) {
77
- ctx.logger.warn('file-preview: shipped SKILL.md is malformed — the 3d-artifact skill is not registered');
78
- return;
79
- }
80
- ctx.effect(() => skills.register({ name, description, content, source: 'runtime' }));
81
- }
82
- catch (error) {
83
- ctx.logger.warn(`file-preview: shipped SKILL.md unreadable (${String(error)}) — the 3d-artifact skill is not registered`);
84
- }
85
- }
86
44
  /** Extensions treated as binary without reading (their text decode is meaningless). */
87
45
  const BINARY_EXTENSIONS = new Set([
88
46
  '.pdf', '.zip', '.gz', '.tar', '.7z', '.zstd', '.br',
@@ -145,8 +103,9 @@ function readErrorMessage(error) {
145
103
  }
146
104
  /**
147
105
  * The `filePreview` Remote service: session-scoped read-only file inspection
148
- * for web surfaces. `list` is a pure fold over the session log (no filesystem
149
- * access); `read` resolves the path against the session cwd and serves current
106
+ * for web surfaces. `list` is a fold over the session log, then filtered to the
107
+ * paths that still exist on disk (resolved against the session cwd and stat-ed
108
+ * per call); `read` resolves the path against the session cwd and serves current
150
109
  * text content through `ctx.fs` (or a browser URL for images), capped by
151
110
  * config. Image bytes ride a dedicated host route so the browser loads them
152
111
  * natively without bloating the RPC channel.
@@ -154,21 +113,27 @@ function readErrorMessage(error) {
154
113
  let FilePreviewService = (() => {
155
114
  let _classSuper = TypertRemoteService;
156
115
  let _instanceExtraInitializers = [];
116
+ let _capabilities_decorators;
157
117
  let _list_decorators;
158
118
  let _turnFiles_decorators;
159
119
  let _read_decorators;
160
120
  let _reveal_decorators;
121
+ let _openExternal_decorators;
161
122
  return class FilePreviewService extends _classSuper {
162
123
  static {
163
124
  const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
125
+ _capabilities_decorators = [Remote('capabilities')];
164
126
  _list_decorators = [Remote('list')];
165
127
  _turnFiles_decorators = [Remote('turnFiles')];
166
128
  _read_decorators = [Remote('read')];
167
129
  _reveal_decorators = [Remote('reveal')];
130
+ _openExternal_decorators = [Remote('openExternal')];
131
+ __esDecorate(this, null, _capabilities_decorators, { kind: "method", name: "capabilities", static: false, private: false, access: { has: obj => "capabilities" in obj, get: obj => obj.capabilities }, metadata: _metadata }, null, _instanceExtraInitializers);
168
132
  __esDecorate(this, null, _list_decorators, { kind: "method", name: "list", static: false, private: false, access: { has: obj => "list" in obj, get: obj => obj.list }, metadata: _metadata }, null, _instanceExtraInitializers);
169
133
  __esDecorate(this, null, _turnFiles_decorators, { kind: "method", name: "turnFiles", static: false, private: false, access: { has: obj => "turnFiles" in obj, get: obj => obj.turnFiles }, metadata: _metadata }, null, _instanceExtraInitializers);
170
134
  __esDecorate(this, null, _read_decorators, { kind: "method", name: "read", static: false, private: false, access: { has: obj => "read" in obj, get: obj => obj.read }, metadata: _metadata }, null, _instanceExtraInitializers);
171
135
  __esDecorate(this, null, _reveal_decorators, { kind: "method", name: "reveal", static: false, private: false, access: { has: obj => "reveal" in obj, get: obj => obj.reveal }, metadata: _metadata }, null, _instanceExtraInitializers);
136
+ __esDecorate(this, null, _openExternal_decorators, { kind: "method", name: "openExternal", static: false, private: false, access: { has: obj => "openExternal" in obj, get: obj => obj.openExternal }, metadata: _metadata }, null, _instanceExtraInitializers);
172
137
  if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
173
138
  }
174
139
  static inject = ['fs'];
@@ -188,6 +153,8 @@ let FilePreviewService = (() => {
188
153
  agents;
189
154
  /** Native reveal runner; a constructor seam for deterministic tests. */
190
155
  revealNative;
156
+ /** Native open-in-app runner; a constructor seam for deterministic tests. */
157
+ openExternalNative;
191
158
  /** Bash-write collector (S2 seam), or undefined when disabled in config. */
192
159
  collector;
193
160
  /** Per-session by-turn fold cache, invalidated by the log watermark. */
@@ -208,6 +175,7 @@ let FilePreviewService = (() => {
208
175
  captureBashWrites: config.captureBashWrites ?? true,
209
176
  };
210
177
  this.revealNative = deps.revealNative ?? revealNativePath;
178
+ this.openExternalNative = deps.openExternalNative ?? openExternalNative;
211
179
  if (config.captureBashWrites !== false) {
212
180
  this.collector = new BashWriteCollector({ fs: this.fs, maxFiles: this.resolved.maxFiles });
213
181
  ctx.effect(() => this.collector.attach(ctx), 'file-preview: bash-write capture');
@@ -228,7 +196,10 @@ let FilePreviewService = (() => {
228
196
  handler: (req, res) => { void this.serveImage(req, res); },
229
197
  }), 'file-preview: image route');
230
198
  }
231
- registerArtifactSkill(ctx);
199
+ }
200
+ /** Zero-session availability handshake for browser companions. */
201
+ capabilities() {
202
+ return { protocolVersion: 1 };
232
203
  }
233
204
  get fs() {
234
205
  return this.ctx.fs;
@@ -310,48 +281,85 @@ let FilePreviewService = (() => {
310
281
  });
311
282
  res.end(Buffer.from(bytes));
312
283
  }
284
+ /** Resolve the session's recorded display paths against its cwd and keep only
285
+ * those that currently exist as a regular file. The products surfaces fold
286
+ * the session log (which is history, not disk state): a path the log wrote
287
+ * may have been cleaned up since (a temp script the turn deleted), and such
288
+ * a path is not a product to list. Existence is checked fresh on every call
289
+ * (never cached), so a deletion that lands after a fold is visible on the
290
+ * next fetch. Unresolvable/unstat-able paths are treated as absent.
291
+ * @param agent - owning live agent; its session cwd anchors relative paths.
292
+ * @param paths - the display paths to probe.
293
+ * @returns the subset that resolves to an existing regular file.
294
+ */
295
+ async retainExisting(agent, paths) {
296
+ if (paths.length === 0)
297
+ return new Set();
298
+ const cwd = agent.session.header.cwd;
299
+ const existing = new Set();
300
+ for (const path of paths) {
301
+ if (existing.has(path))
302
+ continue;
303
+ try {
304
+ const target = await this.fs.resolve(path, cwd === undefined ? {} : { cwd });
305
+ const info = await this.fs.stat(target);
306
+ if (info?.type === 'file')
307
+ existing.add(path);
308
+ }
309
+ catch {
310
+ // Unresolvable or stat failed: the path is not present to list.
311
+ }
312
+ }
313
+ return existing;
314
+ }
313
315
  /**
314
316
  * List the files one session wrote or edited: the log fold plus any
315
317
  * bash-written files the collector verified (the S2 seam), merged so a
316
- * captured path the fold already knows keeps its log-derived entry.
318
+ * captured path the fold already knows keeps its log-derived entry. Only
319
+ * paths that currently exist on disk are returned — a file the session
320
+ * wrote and later deleted is history, not a product.
317
321
  * @param agent - owning live agent; its session log is the data source.
318
- * @returns first-seen files capped by `maxFiles`, with the log watermark.
322
+ * @returns existing first-seen files capped by `maxFiles`, with the log watermark.
319
323
  */
320
- list(agent) {
321
- const folded = foldFilePreview(agent.session.events, this.resolved.maxFiles);
324
+ async list(agent) {
325
+ const folded = foldFilePreview(agent.session.snapshotEvents(), this.resolved.maxFiles);
322
326
  const captured = this.collector?.captured(agent.session.id);
323
- if (captured === undefined || captured.size === 0)
324
- return folded;
325
- const seen = new Set(folded.entries.map(entry => entry.path));
326
- const extra = [];
327
- for (const [path, write] of captured) {
328
- if (seen.has(path) || folded.entries.length + extra.length >= this.resolved.maxFiles)
329
- continue;
330
- extra.push({ path, op: 'write', seq: write.seq, turn: write.turn, step: write.step, diffs: [] });
327
+ let entries = folded.entries;
328
+ if (captured !== undefined && captured.size > 0) {
329
+ const seen = new Set(entries.map(entry => entry.path));
330
+ const extra = [];
331
+ for (const [path, write] of captured) {
332
+ if (seen.has(path) || entries.length + extra.length >= this.resolved.maxFiles)
333
+ continue;
334
+ extra.push({ path, op: 'write', seq: write.seq, turn: write.turn, step: write.step, diffs: [] });
335
+ }
336
+ entries = [...entries, ...extra];
331
337
  }
332
- if (extra.length === 0)
333
- return folded;
338
+ const existing = await this.retainExisting(agent, entries.map(entry => entry.path));
334
339
  return {
335
- entries: [...folded.entries, ...extra],
340
+ entries: entries.filter(entry => existing.has(entry.path)),
336
341
  asOfSeq: folded.asOfSeq,
337
- truncated: folded.truncated || folded.entries.length + extra.length >= this.resolved.maxFiles,
342
+ truncated: folded.truncated || entries.length >= this.resolved.maxFiles,
338
343
  };
339
344
  }
340
345
  /**
341
346
  * Every turn's file mutations for the turn-tail card — the single source of
342
347
  * truth the card renders (the client's old write/edit-only fold retired).
343
- * Built by folding the session log per turn (write/edit calls, Code Mode
348
+ * Built by folding the session log per turn (write/edit calls, PTC
344
349
  * dispatches borrowing the root call's turn, and render-intent paths from
345
350
  * result diff meta) and merging the collector's bash-written captures by
346
351
  * their own turn. The fold is cached per session and invalidated by the log
347
352
  * watermark, so repeated card fetches do not refold. A path touched in two
348
- * turns appears in BOTH turn groups — per-turn attribution is exact.
353
+ * turns appears in BOTH turn groups — per-turn attribution is exact. Only
354
+ * paths that currently exist on disk are returned (a deleted temp script is
355
+ * history, not a product); existence is probed fresh on every call, so the
356
+ * cached fold is filtered per request rather than cached.
349
357
  * @param agent - owning live agent; its session log is the data source.
350
- * @returns per-turn file groups plus the scanned watermark.
358
+ * @returns existing per-turn file groups plus the scanned watermark.
351
359
  */
352
- turnFiles(agent) {
360
+ async turnFiles(agent) {
353
361
  const session = agent.session;
354
- const events = session.events;
362
+ const events = session.snapshotEvents();
355
363
  const asOfSeq = events.length === 0 ? -1 : events[events.length - 1].seq;
356
364
  const cached = this.turnCache.get(session.id);
357
365
  let byTurn;
@@ -386,7 +394,15 @@ let FilePreviewService = (() => {
386
394
  continue;
387
395
  turns.push({ turn, files: files.sort((a, b) => a.seq - b.seq) });
388
396
  }
389
- return { turns, asOfSeq };
397
+ // Filter the assembled groups to paths that still exist on disk (fresh per
398
+ // call — the fold cache is by log watermark, existence moves independently).
399
+ const existing = await this.retainExisting(agent, turns.flatMap(group => group.files.map(file => file.path)));
400
+ return {
401
+ turns: turns
402
+ .map(group => ({ turn: group.turn, files: group.files.filter(file => existing.has(file.path)) }))
403
+ .filter(group => group.files.length > 0),
404
+ asOfSeq,
405
+ };
390
406
  }
391
407
  /**
392
408
  * Read the current content of one recorded file, resolved against the
@@ -511,6 +527,53 @@ let FilePreviewService = (() => {
511
527
  return { revealed: false, reason: 'select-failed' };
512
528
  }
513
529
  }
530
+ /**
531
+ * Open one recorded file in a specific host application (the "open in IDE"
532
+ * gesture). The official open-in-app route only accepts directories — a
533
+ * file path 404s — so file-exact opens go through this method: macOS
534
+ * `open -a <App> <path>` via the same native-command runner reveal uses.
535
+ * The browser names the application by official open-in-app catalog id
536
+ * (probed from `/open-in-app/apps`); the id → app-name map lives in
537
+ * open-external.ts. Non-macOS hosts and unknown ids answer without
538
+ * launching, and the client hides the gesture.
539
+ * @param agent - owning live agent; its session cwd anchors relative paths.
540
+ * @param path - the display path recorded by the read/write/edit tool call.
541
+ * @param app - official open-in-app catalog id (e.g. `cursor`).
542
+ * @param signal - cooperative cancellation from the calling UI request.
543
+ * @returns whether the application launched, or why not.
544
+ */
545
+ async openExternal(agent, path, app, signal) {
546
+ if (typeof path !== 'string' || path.length === 0 || typeof app !== 'string' || app.length === 0) {
547
+ return { opened: false, reason: 'missing' };
548
+ }
549
+ if (macAppName(app) === undefined)
550
+ return { opened: false, reason: 'unknown-app' };
551
+ const cwd = agent.session.header.cwd;
552
+ let target;
553
+ try {
554
+ target = await this.fs.resolve(path, cwd === undefined ? { signal } : { cwd, signal });
555
+ }
556
+ catch {
557
+ return { opened: false, reason: 'missing' };
558
+ }
559
+ let info;
560
+ try {
561
+ info = await this.fs.stat(target, signal);
562
+ }
563
+ catch {
564
+ info = undefined;
565
+ }
566
+ if (info === undefined)
567
+ return { opened: false, reason: 'missing' };
568
+ try {
569
+ await this.openExternalNative(this.fs.processPath(target), app, signal);
570
+ return { opened: true };
571
+ }
572
+ catch (error) {
573
+ const message = error instanceof Error ? error.message : String(error);
574
+ return { opened: false, reason: message.startsWith('open-in-app is unsupported on ') ? 'unsupported-platform' : 'launch-failed' };
575
+ }
576
+ }
514
577
  };
515
578
  })();
516
579
  export { FilePreviewService };
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Native "open this file in a specific application" dispatch used by the
3
+ * file-preview Remote's `openExternal` method (the "open in IDE" gesture).
4
+ *
5
+ * The official open-in-app route (`POST /open-in-app/open`) only accepts
6
+ * directories — a file path 404s — so file-exact opens carry their own
7
+ * dispatch here. macOS only: `open -a <App> <path>` through the official
8
+ * `@deepseek-ai/dsh-native-command` runner (no shell, abort propagation),
9
+ * mirroring `reveal.ts`'s discipline. The browser picks the application by
10
+ * official open-in-app catalog id (probed from `/open-in-app/apps`); the
11
+ * id → `.app` name map below mirrors the official catalog's darwin entries
12
+ * (packages/host/open-in-app/src/catalog.ts at 0.1.5-rc.1 — re-check on every
13
+ * host upgrade). Other platforms and unknown ids answer unsupported, and the
14
+ * client hides the gesture.
15
+ * @module @khorsheed/dsh-file-preview
16
+ */
17
+ import { type NativeCommandRunner } from '@deepseek-ai/dsh-native-command';
18
+ /** Injectable platform facts for deterministic adapter tests. */
19
+ export interface OpenExternalInternals {
20
+ platform?: NodeJS.Platform;
21
+ run?: NativeCommandRunner;
22
+ }
23
+ /** The application name one catalog id maps to, or undefined when unknown. */
24
+ export declare function macAppName(appId: string): string | undefined;
25
+ /**
26
+ * Open one file in the named application. Throws when the platform is not
27
+ * macOS or the catalog id is unknown — the caller maps both to an
28
+ * `unsupported`/`unknown-app` answer and the client hides the gesture. A
29
+ * launch failure propagates as the runner's rejection.
30
+ * @param path - absolute path in the host's execution world (caller owns
31
+ * resolution, typically `FileSystem.processPath`).
32
+ * @param appId - official open-in-app catalog id (e.g. `cursor`).
33
+ * @param signal - caller/connection lifetime; abort terminates the native command.
34
+ * @param internals - platform seam for deterministic tests.
35
+ */
36
+ export declare function openExternalNative(path: string, appId: string, signal: AbortSignal, internals?: OpenExternalInternals): Promise<void>;
37
+ //# sourceMappingURL=open-external.d.ts.map
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Native "open this file in a specific application" dispatch used by the
3
+ * file-preview Remote's `openExternal` method (the "open in IDE" gesture).
4
+ *
5
+ * The official open-in-app route (`POST /open-in-app/open`) only accepts
6
+ * directories — a file path 404s — so file-exact opens carry their own
7
+ * dispatch here. macOS only: `open -a <App> <path>` through the official
8
+ * `@deepseek-ai/dsh-native-command` runner (no shell, abort propagation),
9
+ * mirroring `reveal.ts`'s discipline. The browser picks the application by
10
+ * official open-in-app catalog id (probed from `/open-in-app/apps`); the
11
+ * id → `.app` name map below mirrors the official catalog's darwin entries
12
+ * (packages/host/open-in-app/src/catalog.ts at 0.1.5-rc.1 — re-check on every
13
+ * host upgrade). Other platforms and unknown ids answer unsupported, and the
14
+ * client hides the gesture.
15
+ * @module @khorsheed/dsh-file-preview
16
+ */
17
+ import { runNativeCommand } from '@deepseek-ai/dsh-native-command';
18
+ /** Official catalog id → macOS application name (darwin entries of the official catalog). */
19
+ const MAC_APP_NAMES = {
20
+ cursor: 'Cursor',
21
+ vscode: 'Visual Studio Code',
22
+ vscodeinsiders: 'Visual Studio Code - Insiders',
23
+ windsurf: 'Windsurf',
24
+ zed: 'Zed',
25
+ sublimetext: 'Sublime Text',
26
+ xcode: 'Xcode',
27
+ androidstudio: 'Android Studio',
28
+ intellij: 'IntelliJ IDEA',
29
+ pycharm: 'PyCharm',
30
+ webstorm: 'WebStorm',
31
+ phpstorm: 'PhpStorm',
32
+ goland: 'GoLand',
33
+ rider: 'Rider',
34
+ rustrover: 'RustRover',
35
+ };
36
+ /** The application name one catalog id maps to, or undefined when unknown. */
37
+ export function macAppName(appId) {
38
+ return MAC_APP_NAMES[appId];
39
+ }
40
+ /**
41
+ * Open one file in the named application. Throws when the platform is not
42
+ * macOS or the catalog id is unknown — the caller maps both to an
43
+ * `unsupported`/`unknown-app` answer and the client hides the gesture. A
44
+ * launch failure propagates as the runner's rejection.
45
+ * @param path - absolute path in the host's execution world (caller owns
46
+ * resolution, typically `FileSystem.processPath`).
47
+ * @param appId - official open-in-app catalog id (e.g. `cursor`).
48
+ * @param signal - caller/connection lifetime; abort terminates the native command.
49
+ * @param internals - platform seam for deterministic tests.
50
+ */
51
+ export async function openExternalNative(path, appId, signal, internals = {}) {
52
+ const platform = internals.platform ?? process.platform;
53
+ if (platform !== 'darwin') {
54
+ throw new Error(`open-in-app is unsupported on ${platform}`);
55
+ }
56
+ const app = macAppName(appId);
57
+ if (app === undefined)
58
+ throw new Error(`unknown application id "${appId}"`);
59
+ const run = internals.run ?? runNativeCommand;
60
+ await run('open', ['-a', app, path], signal);
61
+ }
@@ -95,6 +95,16 @@ export type FilePreviewReveal = {
95
95
  /** Why: `missing` = the recorded path does not resolve to an existing target; `select-failed` = the host could not select the file. */
96
96
  readonly reason: 'missing' | 'select-failed';
97
97
  };
98
+ /** Outcome of a `filePreview.openExternal` call (the "open in IDE" gesture). */
99
+ export type FilePreviewOpenExternal = {
100
+ /** The application launched on the file. */
101
+ readonly opened: true;
102
+ } | {
103
+ /** The file could not be opened in the named application. */
104
+ readonly opened: false;
105
+ /** Why: `missing` = the recorded path does not resolve to an existing target; `unknown-app` = the catalog id is not mapped; `unsupported-platform` = the host is not macOS; `launch-failed` = the native launch rejected. */
106
+ readonly reason: 'missing' | 'unknown-app' | 'unsupported-platform' | 'launch-failed';
107
+ };
98
108
  /** One file's mutation facts within one turn — the turn card's vocabulary. */
99
109
  export interface FilePreviewTurnFile {
100
110
  /** The display path (absolute for bash-captured writes; as-recorded otherwise). */
@@ -105,7 +115,7 @@ export interface FilePreviewTurnFile {
105
115
  /** Lines added across the turn's mutations of this path. */
106
116
  readonly added?: number;
107
117
  /** Lines removed; 0 for a create; absent when an uncounted mutation (a write
108
- * whose prior content was not diffable, a Code Mode dispatch) reported no
118
+ * whose prior content was not diffable, a PTC dispatch) reported no
109
119
  * total. */
110
120
  readonly removed?: number;
111
121
  }
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  "cordis",
8
8
  "file-preview"
9
9
  ],
10
- "version": "0.1.1",
10
+ "version": "0.3.0",
11
11
  "type": "module",
12
12
  "main": "lib/index.js",
13
13
  "types": "lib/types/index.d.ts",
@@ -42,7 +42,6 @@
42
42
  "lib/typert.remote-client.d.ts",
43
43
  "lib/typert.remote-client.js",
44
44
  "cordis.patch.yml",
45
- "skills/**/*.md",
46
45
  "LICENSE",
47
46
  "CHANGELOG.md"
48
47
  ],
@@ -59,24 +58,25 @@
59
58
  },
60
59
  "devDependencies": {
61
60
  "@deepseek-ai/cordis": "^4.0.1",
62
- "@deepseek-ai/dsh-agent": "^0.1.1-rc.1",
63
- "@deepseek-ai/dsh-fs": "^0.1.1-rc.1",
64
- "@deepseek-ai/dsh-invariants": "^0.1.1-rc.1",
65
- "@deepseek-ai/dsh-llm": "^0.1.1-rc.1",
66
- "@deepseek-ai/dsh-loader-smoke": "^0.1.1-rc.1",
67
- "@deepseek-ai/dsh-native-command": "^0.1.1-rc.1",
68
- "@deepseek-ai/dsh-session": "^0.1.1-rc.1",
69
- "@deepseek-ai/dsh-skill": "^0.1.1-rc.1",
70
- "@deepseek-ai/dsh-tools": "^0.1.1-rc.1",
71
- "@deepseek-ai/dsh-typert-protocol": "^0.1.1-rc.1"
61
+ "@deepseek-ai/dsh-agent": "^0.1.5-rc.1",
62
+ "@deepseek-ai/dsh-fs": "^0.1.5-rc.1",
63
+ "@deepseek-ai/dsh-invariants": "^0.1.5-rc.1",
64
+ "@deepseek-ai/dsh-llm": "^0.1.5-rc.1",
65
+ "@deepseek-ai/dsh-loader-smoke": "^0.1.5-rc.1",
66
+ "@deepseek-ai/dsh-native-command": "^0.1.5-rc.1",
67
+ "@deepseek-ai/dsh-session": "^0.1.5-rc.1",
68
+ "@deepseek-ai/dsh-skill": "^0.1.5-rc.1",
69
+ "@deepseek-ai/dsh-tools": "^0.1.5-rc.1",
70
+ "@deepseek-ai/dsh-typert-protocol": "^0.1.5-rc.1",
71
+ "@deepseek-ai/dsh-util-values": "^0.1.5-rc.1"
72
72
  },
73
73
  "dsh": {
74
74
  "bundle": {
75
75
  "patch": "./cordis.patch.yml"
76
76
  },
77
77
  "compat": {
78
- "minHost": "0.1.0-rc.6",
79
- "verifiedHost": "0.1.1-rc.2"
78
+ "minHost": "0.1.5-rc.1",
79
+ "verifiedHost": "0.1.5-rc.1"
80
80
  }
81
81
  }
82
82
  }