@deepseek-ai/dsh-api-session-controller 0.2.1-alpha.1 → 0.2.1-alpha.3

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.
@@ -91,9 +91,11 @@ import z from '@deepseek-ai/schemastery';
91
91
  import { errorChain, ReasoningEffortId } from '@deepseek-ai/dsh-llm';
92
92
  import { canOpenNativePath, nativeFileManager, nativeFileApplications, openNativeFileApplication, openNativeAssociatedPath, revealNativePath } from '@deepseek-ai/dsh-native-command';
93
93
  import { SessionQueryError } from '@deepseek-ai/dsh-session-query';
94
- import { Remote, RemoteError, TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol';
94
+ import { Remote, RemoteError, TypertRemoteService, principalOf } from '@deepseek-ai/dsh-typert-protocol';
95
+ import { canonicalClientTimeZone } from '@deepseek-ai/dsh-util-time';
96
+ import { assertNever } from '@deepseek-ai/dsh-util-values';
95
97
  import { ApiSessionAgentController, inspectApiSession, } from "./agent.js";
96
- import { SessionCommandController } from "./commands.js";
98
+ import { SessionCommandController, hasPromptContent } from "./commands.js";
97
99
  import { SessionControlController } from "./control.js";
98
100
  import { SessionHistoryController } from "./history.js";
99
101
  import { SessionFileReferences } from "./file-references.js";
@@ -106,6 +108,15 @@ import { ArchivedSessionGate } from "./archived-session-gate.js";
106
108
  export { ApiSessionNotFound } from "./agent.js";
107
109
  export { SessionFileReferences } from "./file-references.js";
108
110
  export { SessionSkillCatalog } from "./skill-catalog.js";
111
+ /**
112
+ * Read the Session resource a history address names: the Session itself, or
113
+ * the child Session whose transcript a subagent address reads.
114
+ * @param request - history request carrying the durable address.
115
+ * @returns the Session whose access the read requires.
116
+ */
117
+ function addressedSession(request) {
118
+ return request.address.kind === 'session' ? request.address.sessionId : request.address.childSessionId;
119
+ }
109
120
  /** Host service backing the generated `ctx.remote.session` namespace. */
110
121
  let SessionController = (() => {
111
122
  let _classSuper = TypertRemoteService;
@@ -147,8 +158,8 @@ let SessionController = (() => {
147
158
  _attachment_decorators = [Remote('attachment')];
148
159
  _updateQueue_decorators = [Remote('updateQueue')];
149
160
  _cancel_decorators = [Remote('cancel')];
150
- _page_decorators = [Remote('page')];
151
- _follow_decorators = [Remote({ mode: 'stream' })];
161
+ _page_decorators = [Remote({ name: 'page', resources: { session: addressedSession } })];
162
+ _follow_decorators = [Remote({ mode: 'stream', resources: { session: addressedSession } })];
152
163
  _projections_decorators = [Remote('projections')];
153
164
  _control_decorators = [Remote({ mode: 'stream' })];
154
165
  __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);
@@ -179,6 +190,7 @@ let SessionController = (() => {
179
190
  'fileUploads',
180
191
  'fs',
181
192
  'llm',
193
+ 'remoteAccess',
182
194
  'sessions',
183
195
  'sessionProjections',
184
196
  'sessionQuery',
@@ -207,6 +219,7 @@ let SessionController = (() => {
207
219
  */
208
220
  constructor(ctx, config, internals = {}) {
209
221
  super(ctx, 'sessionController', { namespace: 'session' });
222
+ ctx.typert.resources.register('session', { field: 'sessionId' });
210
223
  const resolved = SessionController.Config(config);
211
224
  installModelSelectionProjection(ctx);
212
225
  this.agents = new ApiSessionAgentController(ctx);
@@ -324,21 +337,25 @@ let SessionController = (() => {
324
337
  * @returns visible Session summaries ordered by activity.
325
338
  */
326
339
  async list(_request, signal) {
327
- return { items: await this.listState.list(signal) };
340
+ const items = await this.listState.list(signal);
341
+ return { items: items.filter(item => this.ctx.remoteAccess.allows({ kind: 'session', id: item.sessionId })) };
328
342
  }
329
343
  /**
330
- * Search visible Session content without resuming an Agent.
344
+ * Search visible Session content without resuming an Agent. A non-owner
345
+ * receives only the hits whose Session `allows()` admits; `hasMore`
346
+ * describes the bounded result before that filtering.
331
347
  * @param request - literal message-content query.
332
348
  * @param signal - cancellation for list and search reads.
333
349
  * @returns authorized bounded Session search results.
334
350
  */
335
- search(request, signal) {
336
- return this.listState.search(request.query, signal);
351
+ async search(request, signal) {
352
+ const result = await this.listState.search(request.query, signal);
353
+ return { ...result, items: result.items.filter(item => this.ctx.remoteAccess.allows({ kind: 'session', id: item.sessionId })) };
337
354
  }
338
355
  /**
339
- * Create or idempotently adopt one ordinary Session.
340
- * @param request - requested identity, location, and Agent preset.
341
- * @returns the Session identity and resolved preset when configured.
356
+ * Create one ordinary Session for a new conversation, reusing the named blank Session while it is reusable.
357
+ * @param request - optional blank Session to reuse, location, and Agent preset.
358
+ * @returns the created or reused Session identity and its preset when configured.
342
359
  */
343
360
  create(request) {
344
361
  return this.commands.create(request);
@@ -463,10 +480,18 @@ let SessionController = (() => {
463
480
  * Fork one cold-readable exact event prefix into a new Session. An omitted
464
481
  * boundary selects the latest completed-turn prefix; an open cut receives
465
482
  * synthetic fork closers.
466
- * @param request - source Session and optional exact inclusive event boundary.
483
+ * @param request - source Session, optional exact inclusive event boundary, and migration preflight choice.
467
484
  * @returns the new Session identity.
468
485
  */
469
- fork(request) {
486
+ async fork(request) {
487
+ if (request.allowMigration === false && this.ctx.sessions.get(request.sessionId) === undefined) {
488
+ const stored = await this.ctx.get('sessionPersistence')?.stat(request.sessionId);
489
+ if (stored?.formatStatus === 'migration-required' && this.ctx.sessions.get(request.sessionId) === undefined) {
490
+ throw new RemoteError('session/migration-required', 'Open the source Session to complete migration before forking', {
491
+ sessionId: request.sessionId,
492
+ });
493
+ }
494
+ }
470
495
  return this.commands.fork(request);
471
496
  }
472
497
  /**
@@ -475,9 +500,26 @@ let SessionController = (() => {
475
500
  * @param signal - caller cancellation before prompt admission begins.
476
501
  * @returns acknowledgement that the Agent accepted the prompt.
477
502
  */
478
- prompt(request, signal) {
503
+ async prompt(request, signal) {
479
504
  signal.throwIfAborted();
480
- return this.commands.prompt(request);
505
+ if (!hasPromptContent(request.content)) {
506
+ throw new RemoteError('gateway/bad-request', 'prompt content must include non-whitespace text or an attachment', {});
507
+ }
508
+ const clientTimeZone = request.clientTimeZone === undefined
509
+ ? undefined
510
+ : canonicalClientTimeZone(request.clientTimeZone);
511
+ if (request.clientTimeZone !== undefined && clientTimeZone === undefined) {
512
+ throw new RemoteError('session/invalid-time-zone', 'clientTimeZone must be UTC or a valid IANA Area/Location name', { value: request.clientTimeZone });
513
+ }
514
+ // The caller is recorded only when it is not the owner, so owner messages keep their exact source.
515
+ const principal = principalOf(this.ctx.invocation);
516
+ const source = {
517
+ kind: 'user',
518
+ rpcId: request.requestId,
519
+ ...(clientTimeZone === undefined ? {} : { clientTimeZone }),
520
+ ...(principal === undefined ? {} : { principal }),
521
+ };
522
+ return this.commands.prompt(request, source);
481
523
  }
482
524
  /**
483
525
  * Read one image proven reachable from the addressed Session log.
@@ -523,10 +565,10 @@ let SessionController = (() => {
523
565
  return this.history.follow(request, signal);
524
566
  }
525
567
  /**
526
- * Read all registered projections without activating an Agent.
568
+ * Read exact projections, returning cached hints only when migration is required.
527
569
  * @param request - Session whose current values are required.
528
- * @param signal - cancellation for the Session observation.
529
- * @returns complete baseline, or null when the Session does not exist.
570
+ * @param signal - cancellation for the Session read.
571
+ * @returns a sequenced baseline, cached hints when migration is deferred, or null when absent.
530
572
  */
531
573
  async projections(request, signal) {
532
574
  const { sessionId } = request;
@@ -536,12 +578,27 @@ let SessionController = (() => {
536
578
  try {
537
579
  const env_2 = { stack: [], error: void 0, hasError: false };
538
580
  try {
581
+ signal.throwIfAborted();
582
+ const live = this.liveProjections(sessionId);
583
+ if (live !== undefined)
584
+ return live;
585
+ const stored = await this.ctx.get('sessionPersistence')?.stat(sessionId, { signal });
586
+ signal.throwIfAborted();
587
+ const attached = this.liveProjections(sessionId);
588
+ if (attached !== undefined)
589
+ return attached;
590
+ if (stored === undefined)
591
+ return null;
592
+ if (stored.formatStatus === 'migration-required') {
593
+ const cached = this.ctx.get('sessionProjectionCache')?.cachedSnapshot(stored.header);
594
+ return { kind: 'migration-required', values: { ...cached?.values } };
595
+ }
539
596
  const observation = __addDisposableResource(env_2, await this.ctx.sessionQuery.observeSession(sessionId, { signal }), false);
540
597
  const projections = observation.projections;
541
598
  if (projections === undefined) {
542
599
  throw new RemoteError('session/projections-unavailable', 'Session projections are unavailable', {});
543
600
  }
544
- return { asOfSeq: projections.asOfSeq, values: projections.values };
601
+ return { kind: 'sequenced', asOfSeq: projections.asOfSeq, values: projections.values };
545
602
  }
546
603
  catch (e_2) {
547
604
  env_2.error = e_2;
@@ -552,10 +609,10 @@ let SessionController = (() => {
552
609
  }
553
610
  }
554
611
  catch (error) {
555
- if (error instanceof SessionQueryError && error.code === 'SESSION_QUERY_SESSION_NOT_FOUND')
556
- return null;
557
- if (signal.aborted
558
- || (error instanceof SessionQueryError && error.code === 'SESSION_QUERY_ABORTED')) {
612
+ if (error instanceof SessionQueryError && error.code === 'SESSION_QUERY_SESSION_NOT_FOUND') {
613
+ return this.liveProjections(sessionId) ?? null;
614
+ }
615
+ if (signal.aborted || (error instanceof SessionQueryError && error.code === 'SESSION_QUERY_ABORTED')) {
559
616
  throw new RemoteError('gateway/cancelled', 'Session projection read was cancelled', {}, { cause: error });
560
617
  }
561
618
  if (error instanceof RemoteError)
@@ -563,13 +620,36 @@ let SessionController = (() => {
563
620
  throw new RemoteError('gateway/internal', 'Session projection read failed', {}, { cause: error });
564
621
  }
565
622
  }
623
+ liveProjections(sessionId) {
624
+ const session = this.ctx.sessions.get(sessionId);
625
+ if (session === undefined)
626
+ return undefined;
627
+ const snapshot = this.ctx.sessionProjections.snapshot(session);
628
+ return { kind: 'sequenced', asOfSeq: snapshot.asOfSeq, values: snapshot.values };
629
+ }
566
630
  /**
567
631
  * Stream a complete live-control baseline followed by replacement frames.
568
632
  * @param signal - cancellation owned by the Remote stream carrier.
569
633
  * @returns one complete baseline followed by live replacement frames.
570
634
  */
571
- control(signal) {
572
- return this.controlState.control(signal);
635
+ async *control(signal) {
636
+ for await (const frame of this.controlState.control(signal)) {
637
+ switch (frame.type) {
638
+ case 'baseline': {
639
+ const projections = Object.fromEntries(Object.entries(frame.value.projections)
640
+ .filter(([sessionId]) => this.ctx.remoteAccess.allows({ kind: 'session', id: sessionId })));
641
+ yield { type: 'baseline', value: { ...frame.value, projections } };
642
+ break;
643
+ }
644
+ case 'projection':
645
+ if (this.ctx.remoteAccess.allows({ kind: 'session', id: frame.sessionId }))
646
+ yield frame;
647
+ break;
648
+ /* v8 ignore next -- closed control-frame union. */
649
+ default:
650
+ assertNever(frame);
651
+ }
652
+ }
573
653
  }
574
654
  };
575
655
  })();
package/lib/types/list.js CHANGED
@@ -97,6 +97,7 @@ export class ApiSessionList {
97
97
  sessionId: session.id,
98
98
  updatedAt: updatedAt(session.header, metadata),
99
99
  agentAvailable: this.ctx.agents.get(session.id)?.session === session,
100
+ formatStatus: 'current',
100
101
  running: this.ctx.agents.get(session.id)?.status === 'running',
101
102
  blank: metadata?.blank ?? session.seq === 0,
102
103
  ...listFields(session.header),
@@ -122,7 +123,7 @@ export class ApiSessionList {
122
123
  items.push(this.summaryFor(live));
123
124
  }
124
125
  else if (record.header.cwd !== undefined) {
125
- cold.push(record.header);
126
+ cold.push(record);
126
127
  }
127
128
  if (performance.now() >= yieldDeadline) {
128
129
  await scheduler.yield();
@@ -130,9 +131,9 @@ export class ApiSessionList {
130
131
  yieldDeadline = performance.now() + this.workSliceMs;
131
132
  }
132
133
  }
133
- for (const header of cold) {
134
+ for (const record of cold) {
134
135
  signal?.throwIfAborted();
135
- items.push(this.summarizeCold(header));
136
+ items.push(this.summarizeCold(record));
136
137
  if (performance.now() >= yieldDeadline) {
137
138
  await scheduler.yield();
138
139
  signal?.throwIfAborted();
@@ -143,13 +144,14 @@ export class ApiSessionList {
143
144
  items.sort((left, right) => right.updatedAt - left.updatedAt);
144
145
  return items;
145
146
  }
146
- summarizeCold(header) {
147
+ summarizeCold({ header, formatStatus }) {
147
148
  const projections = this.projectionsFor(header, undefined);
148
149
  const metadata = projections?.values.sessionListMetadata;
149
150
  return {
150
151
  sessionId: header.id,
151
152
  updatedAt: updatedAt(header, metadata),
152
153
  agentAvailable: false,
154
+ ...(formatStatus === undefined ? {} : { formatStatus }),
153
155
  running: false,
154
156
  // A large, metadata-less, or inaccessible cache miss remains unknown and visible.
155
157
  blank: metadata?.blank ?? false,
@@ -100,7 +100,7 @@ let SessionSkillCatalog = (() => {
100
100
  __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);
101
101
  if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
102
102
  }
103
- static inject = ['agents', 'sessionQuery', 'typert'];
103
+ static inject = ['agents', 'sessionQuery', 'typert', 'workingDirectory'];
104
104
  /** @param ctx - Host context carrying Session reads and optional skill/preset services. */
105
105
  constructor(ctx) {
106
106
  super(ctx, 'sessionSkillCatalog', { namespace: 'skills' });
@@ -116,7 +116,6 @@ let SessionSkillCatalog = (() => {
116
116
  async list(request, signal) {
117
117
  const env_1 = { stack: [], error: void 0, hasError: false };
118
118
  try {
119
- void signal;
120
119
  const { sessionId } = request;
121
120
  let cwd;
122
121
  let agentPreset;
@@ -127,8 +126,13 @@ let SessionSkillCatalog = (() => {
127
126
  if (observation.projections === undefined) {
128
127
  throw new Error('skill catalog requires a projected Session observation');
129
128
  }
130
- cwd = observation.header.cwd;
129
+ cwd = observation.projections.values.workingDirectory
130
+ ?? observation.header.cwd
131
+ ?? this.ctx.workingDirectory.defaultDirectory;
131
132
  agentPreset = observation.projections.values.agentPreset ?? undefined;
133
+ const live = this.ctx.agents.get(sessionId);
134
+ if (live !== undefined)
135
+ cwd = await this.ctx.workingDirectory.ensure(live, signal);
132
136
  }
133
137
  catch (e_1) {
134
138
  env_2.error = e_1;
@@ -145,9 +149,6 @@ let SessionSkillCatalog = (() => {
145
149
  }
146
150
  throw new RemoteError('gateway/internal', `session "${sessionId}" could not be inspected: ${String(error)}`, {});
147
151
  }
148
- if (cwd === undefined) {
149
- throw new RemoteError('gateway/internal', `session "${sessionId}" has no project cwd`, {});
150
- }
151
152
  const live = this.ctx.agents.get(sessionId);
152
153
  const presets = this.ctx.get('agentPresets');
153
154
  const scoped = live === undefined ? undefined : presets?.serviceFor(live, 'skills');
@@ -6,6 +6,7 @@ import type { LlmAttemptId, MessageId } from '@deepseek-ai/dsh-llm/brand';
6
6
  import type { TextBlock } from '@deepseek-ai/dsh-llm';
7
7
  import type { SessionId, SessionSeqCursor } from '@deepseek-ai/dsh-session/types';
8
8
  import type { SessionProjectionMap } from '@deepseek-ai/dsh-session-projection/types';
9
+ import type { Principal } from '@deepseek-ai/dsh-typert-protocol';
9
10
  import type { JsonValue } from '@deepseek-ai/dsh-util-values';
10
11
  import type { WorkspaceId } from '@deepseek-ai/dsh-workspace/types';
11
12
  declare module '@deepseek-ai/dsh-session-projection/types' {
@@ -159,6 +160,8 @@ export type QueueAction = {
159
160
  export interface SessionSummary {
160
161
  /** Whether this Session currently owns a live Agent. */
161
162
  readonly agentAvailable: boolean;
163
+ /** Current for attached Sessions; otherwise the persistence format status when reported. */
164
+ readonly formatStatus?: 'current' | 'migration-required';
162
165
  readonly sessionId: SessionId;
163
166
  readonly updatedAt: number;
164
167
  readonly running: boolean;
@@ -209,7 +212,6 @@ declare module '@deepseek-ai/dsh-typert-protocol' {
209
212
  'agent-preset/conflict': {
210
213
  readonly sessionId: SessionId;
211
214
  readonly requestedPreset: string;
212
- readonly existingPreset?: string;
213
215
  };
214
216
  'session/attachment-invalid': {
215
217
  readonly reason: string;
@@ -226,6 +228,9 @@ declare module '@deepseek-ai/dsh-typert-protocol' {
226
228
  'session/fork-unavailable': {
227
229
  readonly sessionId: SessionId;
228
230
  };
231
+ 'session/migration-required': {
232
+ readonly sessionId: SessionId;
233
+ };
229
234
  'subagent/not-found': {
230
235
  readonly parentSessionId: SessionId;
231
236
  readonly childSessionId: SessionId;
@@ -275,16 +280,22 @@ export interface SessionSearchValue {
275
280
  readonly items: readonly SessionSearchItem[];
276
281
  readonly hasMore: boolean;
277
282
  }
278
- /** Session creation or explicit-id adoption request. */
283
+ /** Request for a Session for a new conversation. */
279
284
  export interface SessionCreateRequest {
285
+ /** Workspace the Session joins; exclusive with `cwd`. */
280
286
  readonly workspaceId?: WorkspaceId;
287
+ /** Directory the Session owns when no Workspace is named. */
281
288
  readonly cwd?: string;
289
+ /** Blank Session to reuse while it is reusable, or the identity of a new Session when none is stored under it. */
282
290
  readonly sessionId?: SessionId;
291
+ /** Preset the Session runs, replacing a reused Session's recorded preset; the configured default when omitted. */
283
292
  readonly agentPreset?: string;
284
293
  }
285
294
  /** Session creation response value. */
286
295
  export interface SessionCreateValue {
296
+ /** The created or reused Session, which may differ from the requested `sessionId`. */
287
297
  readonly sessionId: SessionId;
298
+ /** Preset the Session runs, when the deployment composes a preset roster. */
288
299
  readonly agentPreset?: string;
289
300
  }
290
301
  /** Session model-selection request. */
@@ -310,6 +321,8 @@ export interface SessionForkRequest {
310
321
  readonly sessionId: SessionId;
311
322
  /** Exact inclusive source event seq; omission selects the latest completed-turn prefix. */
312
323
  readonly atSeq?: number;
324
+ /** False asks the Host to check for required migration before forking. Defaults to true. */
325
+ readonly allowMigration?: boolean;
313
326
  }
314
327
  /** Identity of a newly forked Session. */
315
328
  export interface SessionForkValue {
@@ -374,11 +387,16 @@ export interface SessionOpenWorkspacePathValue {
374
387
  export type SessionRequestId = Branded<'session-request-id'>;
375
388
  declare module '@deepseek-ai/dsh-llm' {
376
389
  interface MessageSourceMap {
377
- /** Browser prompt correlation and optional Host-validated time zone. */
390
+ /**
391
+ * Browser prompt correlation, optional Host-validated time zone, and the
392
+ * caller that submitted the prompt. `principal` is written only for a
393
+ * caller other than the owner, so an absent `principal` means the owner.
394
+ */
378
395
  'user-rpc': {
379
396
  kind: 'user';
380
397
  rpcId: SessionRequestId;
381
398
  clientTimeZone?: string;
399
+ principal?: Principal;
382
400
  };
383
401
  }
384
402
  }
@@ -396,8 +414,13 @@ export type SessionAddress = {
396
414
  export interface SessionProjectionsRequest {
397
415
  readonly sessionId: SessionId;
398
416
  }
399
- /** Complete Session projection baseline; null when the Session does not exist. */
400
- export type SessionProjectionsValue = SessionProjectionBaseline | null;
417
+ /** Exact projections carry their event cut; required migration returns sequence-free cache hints. Null means absent. */
418
+ export type SessionProjectionsValue = (SessionProjectionBaseline & {
419
+ readonly kind: 'sequenced';
420
+ }) | {
421
+ readonly kind: 'migration-required';
422
+ readonly values: SessionProjectionValues;
423
+ } | null;
401
424
  /** One raw Session event in the Remote journal. */
402
425
  export interface SessionEventEntry {
403
426
  readonly type: 'event';
package/locale/en.json ADDED
@@ -0,0 +1,5 @@
1
+ {
2
+ "meta": {
3
+ "title": "api-session-controller"
4
+ }
5
+ }
package/locale/zh.json ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "meta": {
3
+ "title": "会话控制接口",
4
+ "description": "向客户端提供会话读取、运行控制和状态更新能力。"
5
+ }
6
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@deepseek-ai/dsh-api-session-controller",
3
3
  "description": "Session Remote commands, cold reads, and live control transport",
4
- "version": "0.2.1-alpha.1",
4
+ "version": "0.2.1-alpha.3",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -39,7 +39,8 @@
39
39
  "default": "./lib/typert.remote-client.js"
40
40
  },
41
41
  "./src/*": "./src/*",
42
- "./package.json": "./package.json"
42
+ "./package.json": "./package.json",
43
+ "./locale/*.json": "./locale/*.json"
43
44
  },
44
45
  "dsh": {
45
46
  "client": {
@@ -54,6 +55,7 @@
54
55
  }
55
56
  },
56
57
  "files": [
58
+ "locale/*.json",
57
59
  "lib/index.js",
58
60
  "lib/client.js",
59
61
  "lib/types/**/*.js",
@@ -65,43 +67,44 @@
65
67
  ],
66
68
  "license": "MIT",
67
69
  "dependencies": {
70
+ "@deepseek-ai/dsh-brand": "0.2.1-alpha.3",
71
+ "@deepseek-ai/dsh-deque": "0.2.1-alpha.3",
72
+ "@deepseek-ai/schemastery": "~3.18.5-alpha.2",
68
73
  "mime-types": "^3.0.2",
69
- "zod": "^4.4.3",
70
- "@deepseek-ai/dsh-deque": "0.2.1-alpha.1",
71
- "@deepseek-ai/dsh-brand": "0.2.1-alpha.1",
72
- "@deepseek-ai/schemastery": "~3.18.5-alpha.1"
74
+ "zod": "4.4.3"
73
75
  },
74
76
  "peerDependencies": {
75
- "@deepseek-ai/cordis": "~4.0.5-alpha.1",
76
- "@deepseek-ai/dsh-agent": "0.2.1-alpha.1",
77
- "@deepseek-ai/dsh-agent-default-model": "0.2.1-alpha.1",
78
- "@deepseek-ai/dsh-agent-preset-registry": "0.2.1-alpha.1",
79
- "@deepseek-ai/dsh-api-gateway": "0.2.1-alpha.1",
80
- "@deepseek-ai/dsh-attachment": "0.2.1-alpha.1",
81
- "@deepseek-ai/dsh-client-connection": "0.2.1-alpha.1",
82
- "@deepseek-ai/dsh-client-file-upload": "0.2.1-alpha.1",
83
- "@deepseek-ai/dsh-commands": "0.2.1-alpha.1",
84
- "@deepseek-ai/dsh-fs": "0.2.1-alpha.1",
85
- "@deepseek-ai/dsh-llm": "0.2.1-alpha.1",
86
- "@deepseek-ai/dsh-native-command": "0.2.1-alpha.1",
87
- "@deepseek-ai/dsh-scope": "0.2.1-alpha.1",
88
- "@deepseek-ai/dsh-session-persistence": "0.2.1-alpha.1",
89
- "@deepseek-ai/dsh-session-projection": "0.2.1-alpha.1",
90
- "@deepseek-ai/dsh-session-projection-cache": "0.2.1-alpha.1",
91
- "@deepseek-ai/dsh-session": "0.2.1-alpha.1",
92
- "@deepseek-ai/dsh-file-reference": "0.2.1-alpha.1",
93
- "@deepseek-ai/dsh-session-query": "0.2.1-alpha.1",
94
- "@deepseek-ai/dsh-credentials": "0.2.1-alpha.1",
95
- "@deepseek-ai/dsh-session-title": "0.2.1-alpha.1",
96
- "@deepseek-ai/dsh-settings": "0.2.1-alpha.1",
97
- "@deepseek-ai/dsh-skill": "0.2.1-alpha.1",
98
- "@deepseek-ai/dsh-subagent": "0.2.1-alpha.1",
99
- "@deepseek-ai/dsh-util-time": "0.2.1-alpha.1",
100
- "@deepseek-ai/dsh-util-values": "0.2.1-alpha.1",
101
- "@deepseek-ai/dsh-typert-registry": "0.2.1-alpha.1",
102
- "@deepseek-ai/dsh-util-workspace-path": "0.2.1-alpha.1",
103
- "@deepseek-ai/dsh-typert-protocol": "0.2.1-alpha.1",
104
- "@deepseek-ai/dsh-workspace": "0.2.1-alpha.1"
77
+ "@deepseek-ai/cordis": "~4.0.5-alpha.2",
78
+ "@deepseek-ai/dsh-agent": "0.2.1-alpha.3",
79
+ "@deepseek-ai/dsh-agent-default-model": "0.2.1-alpha.3",
80
+ "@deepseek-ai/dsh-agent-preset-registry": "0.2.1-alpha.3",
81
+ "@deepseek-ai/dsh-api-gateway": "0.2.1-alpha.3",
82
+ "@deepseek-ai/dsh-attachment": "0.2.1-alpha.3",
83
+ "@deepseek-ai/dsh-client-connection": "0.2.1-alpha.3",
84
+ "@deepseek-ai/dsh-client-file-upload": "0.2.1-alpha.3",
85
+ "@deepseek-ai/dsh-commands": "0.2.1-alpha.3",
86
+ "@deepseek-ai/dsh-credentials": "0.2.1-alpha.3",
87
+ "@deepseek-ai/dsh-file-reference": "0.2.1-alpha.3",
88
+ "@deepseek-ai/dsh-fs": "0.2.1-alpha.3",
89
+ "@deepseek-ai/dsh-llm": "0.2.1-alpha.3",
90
+ "@deepseek-ai/dsh-native-command": "0.2.1-alpha.3",
91
+ "@deepseek-ai/dsh-scope": "0.2.1-alpha.3",
92
+ "@deepseek-ai/dsh-session": "0.2.1-alpha.3",
93
+ "@deepseek-ai/dsh-session-persistence": "0.2.1-alpha.3",
94
+ "@deepseek-ai/dsh-session-projection": "0.2.1-alpha.3",
95
+ "@deepseek-ai/dsh-session-projection-cache": "0.2.1-alpha.3",
96
+ "@deepseek-ai/dsh-session-query": "0.2.1-alpha.3",
97
+ "@deepseek-ai/dsh-session-title": "0.2.1-alpha.3",
98
+ "@deepseek-ai/dsh-settings": "0.2.1-alpha.3",
99
+ "@deepseek-ai/dsh-skill": "0.2.1-alpha.3",
100
+ "@deepseek-ai/dsh-subagent": "0.2.1-alpha.3",
101
+ "@deepseek-ai/dsh-typert-protocol": "0.2.1-alpha.3",
102
+ "@deepseek-ai/dsh-typert-registry": "0.2.1-alpha.3",
103
+ "@deepseek-ai/dsh-util-time": "0.2.1-alpha.3",
104
+ "@deepseek-ai/dsh-util-values": "0.2.1-alpha.3",
105
+ "@deepseek-ai/dsh-util-workspace-path": "0.2.1-alpha.3",
106
+ "@deepseek-ai/dsh-workspace": "0.2.1-alpha.3",
107
+ "@deepseek-ai/dsh-working-directory": "0.2.1-alpha.3"
105
108
  },
106
109
  "peerDependenciesMeta": {
107
110
  "@deepseek-ai/dsh-session-persistence": {
@@ -115,48 +118,51 @@
115
118
  }
116
119
  },
117
120
  "devDependencies": {
121
+ "@deepseek-ai/dsh-api-remote-access": "0.2.1-alpha.3",
122
+ "@deepseek-ai/cordis": "~4.0.5-alpha.2",
123
+ "@deepseek-ai/dsh-agent": "0.2.1-alpha.3",
124
+ "@deepseek-ai/dsh-agent-default-model": "0.2.1-alpha.3",
125
+ "@deepseek-ai/dsh-agent-loop": "0.2.1-alpha.3",
126
+ "@deepseek-ai/dsh-agent-loop-testkit": "0.2.1-alpha.3",
127
+ "@deepseek-ai/dsh-agent-preset-registry": "0.2.1-alpha.3",
128
+ "@deepseek-ai/dsh-api-gateway": "0.2.1-alpha.3",
129
+ "@deepseek-ai/dsh-attachment": "0.2.1-alpha.3",
130
+ "@deepseek-ai/dsh-client-connection": "0.2.1-alpha.3",
131
+ "@deepseek-ai/dsh-client-file-upload": "0.2.1-alpha.3",
132
+ "@deepseek-ai/dsh-client-store": "0.2.1-alpha.3",
133
+ "@deepseek-ai/dsh-client-test-runtime": "0.2.1-alpha.3",
134
+ "@deepseek-ai/dsh-commands": "0.2.1-alpha.3",
135
+ "@deepseek-ai/dsh-credentials": "0.2.1-alpha.3",
136
+ "@deepseek-ai/dsh-file-reference": "0.2.1-alpha.3",
137
+ "@deepseek-ai/dsh-fs": "0.2.1-alpha.3",
138
+ "@deepseek-ai/dsh-fs-local": "0.2.1-alpha.3",
139
+ "@deepseek-ai/dsh-llm": "0.2.1-alpha.3",
140
+ "@deepseek-ai/dsh-native-command": "0.2.1-alpha.3",
141
+ "@deepseek-ai/dsh-permission-presets": "0.2.1-alpha.3",
142
+ "@deepseek-ai/dsh-remote-mock": "0.2.1-alpha.3",
143
+ "@deepseek-ai/dsh-scope": "0.2.1-alpha.3",
144
+ "@deepseek-ai/dsh-session": "0.2.1-alpha.3",
145
+ "@deepseek-ai/dsh-session-persistence": "0.2.1-alpha.3",
146
+ "@deepseek-ai/dsh-session-persistence-jsonl": "0.2.1-alpha.3",
147
+ "@deepseek-ai/dsh-session-projection": "0.2.1-alpha.3",
148
+ "@deepseek-ai/dsh-session-projection-cache": "0.2.1-alpha.3",
149
+ "@deepseek-ai/dsh-session-query": "0.2.1-alpha.3",
150
+ "@deepseek-ai/dsh-session-title": "0.2.1-alpha.3",
151
+ "@deepseek-ai/dsh-settings": "0.2.1-alpha.3",
152
+ "@deepseek-ai/dsh-skill": "0.2.1-alpha.3",
153
+ "@deepseek-ai/dsh-storage": "0.2.1-alpha.3",
154
+ "@deepseek-ai/dsh-storage-domain": "0.2.1-alpha.3",
155
+ "@deepseek-ai/dsh-storage-json": "0.2.1-alpha.3",
156
+ "@deepseek-ai/dsh-subagent": "0.2.1-alpha.3",
157
+ "@deepseek-ai/dsh-typert-protocol": "0.2.1-alpha.3",
158
+ "@deepseek-ai/dsh-typert-registry": "0.2.1-alpha.3",
159
+ "@deepseek-ai/dsh-util-crypto": "0.2.1-alpha.3",
160
+ "@deepseek-ai/dsh-util-time": "0.2.1-alpha.3",
161
+ "@deepseek-ai/dsh-util-values": "0.2.1-alpha.3",
162
+ "@deepseek-ai/dsh-util-workspace-path": "0.2.1-alpha.3",
163
+ "@deepseek-ai/dsh-workspace": "0.2.1-alpha.3",
118
164
  "@types/mime-types": "^3.0.1",
119
- "@deepseek-ai/dsh-agent": "0.2.1-alpha.1",
120
- "@deepseek-ai/dsh-agent-default-model": "0.2.1-alpha.1",
121
- "@deepseek-ai/cordis": "~4.0.5-alpha.1",
122
- "@deepseek-ai/dsh-agent-loop": "0.2.1-alpha.1",
123
- "@deepseek-ai/dsh-agent-loop-testkit": "0.2.1-alpha.1",
124
- "@deepseek-ai/dsh-agent-preset-registry": "0.2.1-alpha.1",
125
- "@deepseek-ai/dsh-api-gateway": "0.2.1-alpha.1",
126
- "@deepseek-ai/dsh-attachment": "0.2.1-alpha.1",
127
- "@deepseek-ai/dsh-client-connection": "0.2.1-alpha.1",
128
- "@deepseek-ai/dsh-client-file-upload": "0.2.1-alpha.1",
129
- "@deepseek-ai/dsh-client-store": "0.2.1-alpha.1",
130
- "@deepseek-ai/dsh-commands": "0.2.1-alpha.1",
131
- "@deepseek-ai/dsh-credentials": "0.2.1-alpha.1",
132
- "@deepseek-ai/dsh-fs": "0.2.1-alpha.1",
133
- "@deepseek-ai/dsh-fs-local": "0.2.1-alpha.1",
134
- "@deepseek-ai/dsh-file-reference": "0.2.1-alpha.1",
135
- "@deepseek-ai/dsh-llm": "0.2.1-alpha.1",
136
- "@deepseek-ai/dsh-client-test-runtime": "0.2.1-alpha.1",
137
- "@deepseek-ai/dsh-permission-presets": "0.2.1-alpha.1",
138
- "@deepseek-ai/dsh-native-command": "0.2.1-alpha.1",
139
- "@deepseek-ai/dsh-scope": "0.2.1-alpha.1",
140
- "@deepseek-ai/dsh-remote-mock": "0.2.1-alpha.1",
141
- "@deepseek-ai/dsh-session": "0.2.1-alpha.1",
142
- "@deepseek-ai/dsh-session-persistence": "0.2.1-alpha.1",
143
- "@deepseek-ai/dsh-session-projection": "0.2.1-alpha.1",
144
- "@deepseek-ai/dsh-session-projection-cache": "0.2.1-alpha.1",
145
- "@deepseek-ai/dsh-session-query": "0.2.1-alpha.1",
146
- "@deepseek-ai/dsh-session-title": "0.2.1-alpha.1",
147
- "@deepseek-ai/dsh-skill": "0.2.1-alpha.1",
148
- "@deepseek-ai/dsh-storage": "0.2.1-alpha.1",
149
- "@deepseek-ai/dsh-storage-domain": "0.2.1-alpha.1",
150
- "@deepseek-ai/dsh-storage-json": "0.2.1-alpha.1",
151
- "@deepseek-ai/dsh-typert-protocol": "0.2.1-alpha.1",
152
- "@deepseek-ai/dsh-subagent": "0.2.1-alpha.1",
153
- "@deepseek-ai/dsh-typert-registry": "0.2.1-alpha.1",
154
- "@deepseek-ai/dsh-util-crypto": "0.2.1-alpha.1",
155
- "@deepseek-ai/dsh-util-time": "0.2.1-alpha.1",
156
- "@deepseek-ai/dsh-util-values": "0.2.1-alpha.1",
157
- "@deepseek-ai/dsh-util-workspace-path": "0.2.1-alpha.1",
158
- "@deepseek-ai/dsh-workspace": "0.2.1-alpha.1",
159
- "@deepseek-ai/dsh-settings": "0.2.1-alpha.1"
165
+ "@deepseek-ai/dsh-working-directory": "0.2.1-alpha.3"
160
166
  },
161
167
  "scripts": {
162
168
  "bundle": "tsdown",