@deepseek-ai/dsh-sdk-client 0.2.0-rc.2 → 0.2.1-alpha.2

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/README.i18n.yaml CHANGED
@@ -15,14 +15,14 @@
15
15
  en: d152484eb41ac6b4
16
16
  zh: 09388d293f9be9cb
17
17
  /deepseek-ai-dsh-sdk-client/use-this-package:
18
- en: 3c21c7ec64d17346
19
- zh: c6ba1b632b8a4d72
18
+ en: 316b142489dd050f
19
+ zh: 2b37ae57b2a52b5e
20
20
  /deepseek-ai-dsh-sdk-client/use-this-package/running-agent-turns-with-deepseekharness:
21
21
  en: 01c58dddd7e62de2
22
22
  zh: 6dbd46e244f3f135
23
23
  /deepseek-ai-dsh-sdk-client/use-this-package/lower-level-control-with-harnessclient:
24
- en: 8e7eb3a9b3f91404
25
- zh: 277a722586dcb549
24
+ en: 8778901987da6e59
25
+ zh: 3d09fe4b0b393a15
26
26
  /deepseek-ai-dsh-sdk-client/understand-the-implementation:
27
27
  en: 8773f50c51da85f0
28
28
  zh: 4649ebc69357deb0
@@ -30,8 +30,8 @@
30
30
  en: 6632c06d819233cc
31
31
  zh: 207d55d8217ec6b1
32
32
  /deepseek-ai-dsh-sdk-client/understand-the-implementation/source-map:
33
- en: f8a986c22b7a2953
34
- zh: 35937eb44e1ee909
33
+ en: a3c7978a80f5aba3
34
+ zh: fdc4dfdafd2eccfa
35
35
  /deepseek-ai-dsh-sdk-client/understand-the-implementation/owned-activity-flow:
36
36
  en: 94a42babac5f1c7d
37
37
  zh: df9e42ed02f7d002
package/README.md CHANGED
@@ -25,6 +25,8 @@ English | [中文](README.zh.md)
25
25
  <a id="use-this-package"></a>
26
26
  ## Use this package
27
27
 
28
+ `HarnessSession.getWorkingDirectory()` reads the effective directory; `setWorkingDirectory(path)` changes it and returns the validated absolute path. Either method creates an unknown Session without starting a model turn. Relative paths use the Session's current directory. Origin metadata, permissions, and existing processes remain unchanged. `HarnessClient` exposes the same methods with a leading `sessionId` argument.
29
+
28
30
  Use this client when TypeScript code must drive a complete Harness runtime from another process and you can name the runtime executable explicitly. The common path is minimal: construct a `DeepSeekHarness` with a launch spec, run prompts, and close it so the child process is always reaped.
29
31
 
30
32
  ### Running agent turns with DeepSeekHarness
@@ -51,6 +53,8 @@ The subprocess starts lazily on first use and stays owned by the instance across
51
53
 
52
54
  `HarnessClient` is the protocol client under the run API: explicit `start()`, `initialize()`, `prompt()`, `request()`, and `close()`, plus notification subscriptions. `prompt()` returns the queued message id as soon as the runtime accepts it and never waits for agent activity. `subscribe(filter?)` returns a `NotificationSubscription` (awaitable `next()`, non-blocking `tryNext()`, async iteration); `subscribeSessionTree(id)` scopes to one session and the descendants discovered from `subagent.started` lineage edges — the runtime notifies for every session in its context, and scoping is client-side, exactly like the Python SDK.
53
55
 
56
+ Task-owning consumers can subscribe before `prompt()`, then call `request('session/wait', { sessionId })` and drain queued notifications with `tryNext()`. This waits for managed descendants and their root summary turns; `HarnessSession.run()` retains its next-idle interval. `validatedSessionEvent()` validates the event envelope and the assistant/turn fields consumed by SDK readers before they enter an output fold.
57
+
54
58
  The client exports typed errors for every failure mode: `JsonRpcResponseError` (a wire error response, code and data preserved), `RequestTimeoutError` (a configured bound elapsed), `SdkProtocolError` (a response outside the documented protocol), and `TransportClosedError` (the runtime is gone — the message carries the exit code and a bounded stderr tail). `close()` requests protocol `shutdown` (bounded by `shutdownTimeoutMs`, default 1000 ms), then walks a stdin-EOF → SIGTERM → SIGKILL ladder until the process has exited; it is idempotent, and a closed client refuses reuse. `HarnessClientOptions.env` replaces the child environment entirely when given (`undefined` inherits the parent's); callers own credential policy — `scrubbedParentEnv` from `dsh-subprocess` is the shared scrub base for isolation-minded launches.
55
59
 
56
60
  -----
@@ -76,7 +80,6 @@ The client is two layers over one wire: `DeepSeekHarness` (owned runs) over `Har
76
80
  | [`src/dispose.ts`](src/dispose.ts) | Private teardown ladder: stdin EOF → SIGTERM → SIGKILL to actual exit |
77
81
  | [`src/types.ts`](src/types.ts) | Launch and timeout options, notification shapes, `RunResult` |
78
82
  | [`src/index.ts`](src/index.ts) | Consumer interface: the two client layers and caller-facing types |
79
- | — | No runtime invariant companion is published; this client library runs outside any harness context (its peer is a separate runtime process); the runtime's own packages own the event-stream relations. |
80
83
 
81
84
  ### Owned activity flow
82
85
 
package/README.zh.md CHANGED
@@ -25,6 +25,8 @@ kind: "package-library"
25
25
  <a id="use-this-package"></a>
26
26
  ## 使用本包
27
27
 
28
+ `HarnessSession.getWorkingDirectory()` 读取有效目录;`setWorkingDirectory(path)` 修改目录并返回校验后的绝对路径。两个方法都可创建未知 Session,而不启动模型轮次。相对路径以 Session 当前目录解析。起始目录元数据、权限与已有进程保持不变。`HarnessClient` 提供同名方法,并以 `sessionId` 作为首个参数。
29
+
28
30
  当 TypeScript 代码需要从另一进程驱动完整 Harness 运行时、且你能显式指名运行时可执行文件时,使用本客户端。常用路径极简:用启动规格构造 `DeepSeekHarness`,运行提示词,然后关闭它,使子进程总能被回收。
29
31
 
30
32
  ### 用 DeepSeekHarness 运行 agent 轮次
@@ -51,6 +53,8 @@ console.log(result.finalResponse)
51
53
 
52
54
  `HarnessClient` 是运行 API 之下的协议客户端:显式 `start()`、`initialize()`、`prompt()`、`request()` 与 `close()`,外加通知订阅。`prompt()` 在运行时接受排队消息后立即返回该消息的 id,绝不等待 agent 活动。`subscribe(filter?)` 返回 `NotificationSubscription`(可等待的 `next()`、非阻塞 `tryNext()`、异步迭代);`subscribeSessionTree(id)` 把范围限定到一个会话及从 `subagent.started` 血缘边发现的后代——运行时对上下文内每个会话都发通知,范围限定在客户端完成,与 Python SDK 完全一致。
53
55
 
56
+ 拥有完整任务的消费者可以先订阅,再调用 `prompt()`,随后调用 `request('session/wait', { sessionId })`,并通过 `tryNext()` 取完已排队的通知。这会等待受管理后代及其触发的根 Agent 摘要轮次;`HarnessSession.run()` 仍以首次空闲作为活动区间终点。`validatedSessionEvent()` 在事件进入输出折叠前,校验事件封装及 SDK 读取方使用的 assistant/turn 字段。
57
+
54
58
  本客户端为每种失败模式导出类型化错误:`JsonRpcResponseError`(协议错误响应,保留 code 与 data)、`RequestTimeoutError`(配置的时限已到)、`SdkProtocolError`(响应超出文档化协议)、`TransportClosedError`(运行时已消失——消息携带退出码与有界 stderr 尾部)。`close()` 先请求协议 `shutdown`(受 `shutdownTimeoutMs` 约束,默认 1000 毫秒),然后走 stdin-EOF → SIGTERM → SIGKILL 阶梯直到进程退出;幂等,已关闭的客户端拒绝复用。`HarnessClientOptions.env` 给定时整体替换子进程环境(`undefined` 原样继承父进程环境);凭据策略归调用方——`dsh-subprocess` 的 `scrubbedParentEnv` 是面向隔离启动的共享擦除基底。
55
59
 
56
60
  -----
@@ -76,7 +80,6 @@ console.log(result.finalResponse)
76
80
  | [`src/dispose.ts`](src/dispose.ts) | 私有关闭阶梯:stdin EOF → SIGTERM → SIGKILL 直到真正退出 |
77
81
  | [`src/types.ts`](src/types.ts) | 启动与超时选项、通知结构、`RunResult` |
78
82
  | [`src/index.ts`](src/index.ts) | 消费方接口:两层客户端与面向调用方的类型 |
79
- | — | 不发布运行时不变式伴生入口;本客户端库运行在任何 harness 上下文之外(其对端是独立运行时进程);运行时自身的包负责维护事件流关系。 |
80
83
 
81
84
  ### 自有活动流程
82
85
 
package/lib/index.js CHANGED
@@ -441,6 +441,31 @@ var HarnessClient = class {
441
441
  return result.messageId;
442
442
  }
443
443
  /**
444
+ * Read a Session's effective working directory, recovering it if missing.
445
+ * @param sessionId - target Session; an unknown id creates it.
446
+ * @returns the absolute effective directory.
447
+ */
448
+ getWorkingDirectory(sessionId) {
449
+ return this.workingDirectoryRequest("session/working-directory/get", { sessionId });
450
+ }
451
+ /**
452
+ * Change a Session's effective directory without changing origin or permissions.
453
+ * @param sessionId - target Session; an unknown id creates it.
454
+ * @param path - absolute or Session-current-directory-relative path.
455
+ * @returns the validated absolute directory.
456
+ */
457
+ setWorkingDirectory(sessionId, path) {
458
+ return this.workingDirectoryRequest("session/working-directory/set", {
459
+ sessionId,
460
+ path
461
+ });
462
+ }
463
+ async workingDirectoryRequest(method, params) {
464
+ const result = await this.request(method, params);
465
+ if (!isRecord(result) || typeof result.cwd !== "string") throw new SdkProtocolError(`${method} returned no working directory: ${JSON.stringify(result)}`);
466
+ return result.cwd;
467
+ }
468
+ /**
444
469
  * Send one JSON-RPC request and await its result.
445
470
  * @param method - the wire method name.
446
471
  * @param params - the params object; omitted params send `{}`.
@@ -682,7 +707,7 @@ var DeepSeekHarness = class {
682
707
  }
683
708
  /**
684
709
  * Open a session handle (no wire traffic; the runtime creates the session
685
- * on its first prompt).
710
+ * on its first prompt or working-directory operation).
686
711
  * @param sessionId - explicit id to reuse; omitted mints a fresh one.
687
712
  * @returns the session handle.
688
713
  */
@@ -730,6 +755,23 @@ var HarnessSession = class {
730
755
  this.id = id;
731
756
  }
732
757
  /**
758
+ * Read the effective directory and recover a missing directory to the Session origin.
759
+ * @returns the absolute directory used by new independent operations.
760
+ */
761
+ async getWorkingDirectory() {
762
+ await this.harness.start();
763
+ return this.harness.client.getWorkingDirectory(this.id);
764
+ }
765
+ /**
766
+ * Change the effective directory without moving existing processes or changing permissions.
767
+ * @param path - absolute or Session-current-directory-relative directory.
768
+ * @returns the validated absolute directory.
769
+ */
770
+ async setWorkingDirectory(path) {
771
+ await this.harness.start();
772
+ return this.harness.client.setWorkingDirectory(this.id, path);
773
+ }
774
+ /**
733
775
  * Queue one prompt, then observe the whole session through its next idle.
734
776
  * @param input - prompt text, or content blocks sent verbatim.
735
777
  * @param options - optional per-notification observer.
@@ -806,7 +848,11 @@ function validatedTurnEndReason(value) {
806
848
  }
807
849
  return value;
808
850
  }
809
- /** Validate the fields in a wire `session.event` envelope before returning the typed result. */
851
+ /**
852
+ * Validate the event envelope and assistant/turn fields consumed by SDK readers.
853
+ * @param value - the raw `session.event` event payload.
854
+ * @returns the event, or throws a protocol error for malformed consumed fields.
855
+ */
810
856
  function validatedSessionEvent(value) {
811
857
  if (!isRecord(value) || typeof value.type !== "string") throw new SdkProtocolError(`session.event carried no event envelope: ${JSON.stringify(value)}`);
812
858
  if (value.type === "assistant/message") {
@@ -841,4 +887,4 @@ function finalResponse(events) {
841
887
  return "";
842
888
  }
843
889
  //#endregion
844
- export { DeepSeekHarness, HarnessClient, HarnessSession, JsonRpcResponseError, RequestTimeoutError, SdkProtocolError, TransportClosedError };
890
+ export { DeepSeekHarness, HarnessClient, HarnessSession, JsonRpcResponseError, RequestTimeoutError, SdkProtocolError, TransportClosedError, validatedSessionEvent };
@@ -48,7 +48,7 @@ export declare class DeepSeekHarness implements AsyncDisposable {
48
48
  start(): Promise<void>;
49
49
  /**
50
50
  * Open a session handle (no wire traffic; the runtime creates the session
51
- * on its first prompt).
51
+ * on its first prompt or working-directory operation).
52
52
  * @param sessionId - explicit id to reuse; omitted mints a fresh one.
53
53
  * @returns the session handle.
54
54
  */
@@ -92,6 +92,17 @@ export declare class HarnessSession {
92
92
  * @param id - the wire session id this handle runs on.
93
93
  */
94
94
  constructor(harness: DeepSeekHarness, id: string);
95
+ /**
96
+ * Read the effective directory and recover a missing directory to the Session origin.
97
+ * @returns the absolute directory used by new independent operations.
98
+ */
99
+ getWorkingDirectory(): Promise<string>;
100
+ /**
101
+ * Change the effective directory without moving existing processes or changing permissions.
102
+ * @param path - absolute or Session-current-directory-relative directory.
103
+ * @returns the validated absolute directory.
104
+ */
105
+ setWorkingDirectory(path: string): Promise<string>;
95
106
  /**
96
107
  * Queue one prompt, then observe the whole session through its next idle.
97
108
  * @param input - prompt text, or content blocks sent verbatim.
@@ -107,6 +118,12 @@ export declare class HarnessSession {
107
118
  * @returns the content blocks to send.
108
119
  */
109
120
  export declare function normalizeInput(input: string | SdkPromptContentBlock[]): SdkPromptContentBlock[];
121
+ /**
122
+ * Validate the event envelope and assistant/turn fields consumed by SDK readers.
123
+ * @param value - the raw `session.event` event payload.
124
+ * @returns the event, or throws a protocol error for malformed consumed fields.
125
+ */
126
+ export declare function validatedSessionEvent(value: unknown): SessionEvent;
110
127
  /**
111
128
  * Extract the concatenated text of the last assistant message.
112
129
  * @param events - the activity interval's `session.event` payloads in wire order.
@@ -96,6 +96,20 @@ export declare class HarnessClient {
96
96
  * @returns the queued message id.
97
97
  */
98
98
  prompt(sessionId: string, contentBlocks: SdkPromptContentBlock[]): Promise<string>;
99
+ /**
100
+ * Read a Session's effective working directory, recovering it if missing.
101
+ * @param sessionId - target Session; an unknown id creates it.
102
+ * @returns the absolute effective directory.
103
+ */
104
+ getWorkingDirectory(sessionId: string): Promise<string>;
105
+ /**
106
+ * Change a Session's effective directory without changing origin or permissions.
107
+ * @param sessionId - target Session; an unknown id creates it.
108
+ * @param path - absolute or Session-current-directory-relative path.
109
+ * @returns the validated absolute directory.
110
+ */
111
+ setWorkingDirectory(sessionId: string, path: string): Promise<string>;
112
+ private workingDirectoryRequest;
99
113
  /**
100
114
  * Send one JSON-RPC request and await its result.
101
115
  * @param method - the wire method name.
@@ -8,7 +8,7 @@
8
8
  *
9
9
  * @module @deepseek-ai/dsh-sdk-client
10
10
  */
11
- export { DeepSeekHarness, HarnessSession } from './api.ts';
11
+ export { DeepSeekHarness, HarnessSession, validatedSessionEvent } from './api.ts';
12
12
  export type { RunOptions } from './api.ts';
13
13
  export { HarnessClient, RequestTimeoutError, SdkProtocolError, TransportClosedError, } from './client.ts';
14
14
  export type { NotificationSubscription } from './client.ts';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@deepseek-ai/dsh-sdk-client",
3
3
  "description": "TypeScript client SDK for driving a DeepSeek Harness runtime subprocess over stdio JSON-RPC: the DeepSeekHarness high-level turns API and the lower-level HarnessClient",
4
- "version": "0.2.0-rc.2",
4
+ "version": "0.2.1-alpha.2",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -26,18 +26,19 @@
26
26
  ],
27
27
  "license": "MIT",
28
28
  "dependencies": {
29
- "@deepseek-ai/dsh": "0.2.0-rc.2"
29
+ "@deepseek-ai/dsh": "0.2.1-alpha.2"
30
30
  },
31
31
  "peerDependencies": {
32
- "@deepseek-ai/dsh-llm": "0.2.0-rc.2",
33
- "@deepseek-ai/dsh-sdk-protocol": "0.2.0-rc.2",
34
- "@deepseek-ai/dsh-session": "0.2.0-rc.2",
35
- "@deepseek-ai/cordis": "~4.0.4"
32
+ "@deepseek-ai/dsh-llm": "0.2.1-alpha.2",
33
+ "@deepseek-ai/dsh-sdk-protocol": "0.2.1-alpha.2",
34
+ "@deepseek-ai/dsh-session": "0.2.1-alpha.2",
35
+ "@deepseek-ai/cordis": "~4.0.5-alpha.1"
36
36
  },
37
37
  "devDependencies": {
38
- "@deepseek-ai/dsh-llm": "0.2.0-rc.2",
39
- "@deepseek-ai/dsh-sdk-protocol": "0.2.0-rc.2",
40
- "@deepseek-ai/dsh-session": "0.2.0-rc.2",
41
- "@deepseek-ai/cordis": "~4.0.4"
38
+ "@deepseek-ai/dsh-llm": "0.2.1-alpha.2",
39
+ "@deepseek-ai/dsh-sdk-protocol": "0.2.1-alpha.2",
40
+ "@deepseek-ai/dsh-session": "0.2.1-alpha.2",
41
+ "@deepseek-ai/cordis": "~4.0.5-alpha.1",
42
+ "@deepseek-ai/dsh-experimental-translator": "0.2.1-alpha.2"
42
43
  }
43
44
  }