dsh-loop-engine 1.0.0-rc10

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.
Files changed (63) hide show
  1. package/README.md +121 -0
  2. package/README.zh.md +38 -0
  3. package/cordis.patch.yml +3 -0
  4. package/lib/client.js +37506 -0
  5. package/lib/index.js +6412 -0
  6. package/lib/invariant.js +108 -0
  7. package/lib/types/client/LoopEngineBadge.d.ts +34 -0
  8. package/lib/types/client/LoopEngineComposerSelect.d.ts +40 -0
  9. package/lib/types/client/LoopEngineSection.d.ts +34 -0
  10. package/lib/types/client/index.d.ts +29 -0
  11. package/lib/types/client/locales.d.ts +46 -0
  12. package/lib/types/client/store.d.ts +58 -0
  13. package/lib/types/commands.d.ts +69 -0
  14. package/lib/types/driver-core/context-files.d.ts +62 -0
  15. package/lib/types/driver-core/ownership.d.ts +40 -0
  16. package/lib/types/driver-core/permission-knobs.d.ts +26 -0
  17. package/lib/types/driver-core/prompt.d.ts +23 -0
  18. package/lib/types/driver-core/skill-inject.d.ts +59 -0
  19. package/lib/types/engine-claude/agent.d.ts +104 -0
  20. package/lib/types/engine-claude/loop.d.ts +111 -0
  21. package/lib/types/engine-claude/mapping.d.ts +83 -0
  22. package/lib/types/engine-claude/permission.d.ts +41 -0
  23. package/lib/types/engine-claude/process.d.ts +59 -0
  24. package/lib/types/engine-claude/sdk.d.ts +57 -0
  25. package/lib/types/engine-claude/types.d.ts +18 -0
  26. package/lib/types/engine-codex/agent.d.ts +111 -0
  27. package/lib/types/engine-codex/appserver/client.d.ts +49 -0
  28. package/lib/types/engine-codex/appserver/mapping.d.ts +67 -0
  29. package/lib/types/engine-codex/appserver/thread.d.ts +66 -0
  30. package/lib/types/engine-codex/appserver/types.d.ts +215 -0
  31. package/lib/types/engine-codex/loop.d.ts +114 -0
  32. package/lib/types/engine-codex/permission.d.ts +32 -0
  33. package/lib/types/engine-codex/skills.d.ts +29 -0
  34. package/lib/types/engine-codex/types.d.ts +19 -0
  35. package/lib/types/engine-kimi/acp/client.d.ts +76 -0
  36. package/lib/types/engine-kimi/acp/mapping.d.ts +44 -0
  37. package/lib/types/engine-kimi/acp/types.d.ts +95 -0
  38. package/lib/types/engine-kimi/agent.d.ts +123 -0
  39. package/lib/types/engine-kimi/commands.d.ts +40 -0
  40. package/lib/types/engine-kimi/loop.d.ts +108 -0
  41. package/lib/types/engine-kimi/mapping.d.ts +71 -0
  42. package/lib/types/engine-kimi/permission.d.ts +28 -0
  43. package/lib/types/engine-kimi/process.d.ts +61 -0
  44. package/lib/types/engine-kimi/skills.d.ts +57 -0
  45. package/lib/types/engine-kimi/types.d.ts +23 -0
  46. package/lib/types/engine-pi/agent.d.ts +135 -0
  47. package/lib/types/engine-pi/loop.d.ts +123 -0
  48. package/lib/types/engine-pi/permission.d.ts +43 -0
  49. package/lib/types/engine-pi/probe.d.ts +23 -0
  50. package/lib/types/engine-pi/rpc/client.d.ts +105 -0
  51. package/lib/types/engine-pi/rpc/mapping.d.ts +37 -0
  52. package/lib/types/engine-pi/rpc/types.d.ts +235 -0
  53. package/lib/types/engine-pi/skills.d.ts +55 -0
  54. package/lib/types/engine-pi/types.d.ts +27 -0
  55. package/lib/types/index.d.ts +114 -0
  56. package/lib/types/invariant.d.ts +23 -0
  57. package/lib/types/namespace.d.ts +9 -0
  58. package/lib/types/patch-manager.d.ts +59 -0
  59. package/lib/types/preset.d.ts +73 -0
  60. package/lib/types/provider-route.d.ts +49 -0
  61. package/lib/types/settings.d.ts +31 -0
  62. package/lib/types/skills.d.ts +93 -0
  63. package/package.json +103 -0
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Pi loop Agent: drives one session through turn and step boundaries by
3
+ * spawning a `pi --mode rpc` child process and speaking strict-LF JSONL over
4
+ * stdio. The dsh session log is the sole source of truth and each step runs one
5
+ * stateless Pi session (a fresh `new_session` + a single `prompt`), so the
6
+ * prompt is a pure serialization of the durable history plus the assembled dsh
7
+ * system prompt. Pi owns its tools natively but has no permission system, so
8
+ * the whole child is sandboxed by the dsh subprocess seam and its `--tools`
9
+ * are pruned to the resolved stance.
10
+ *
11
+ * @module dsh-loop-engine/engine-pi/agent
12
+ */
13
+ import type { Agent, AgentCancelCause, AgentOptions, AgentStatus, CancelOptions, InboxTarget } from '@deepseek-ai/dsh-agent';
14
+ import { Inbox } from '@deepseek-ai/dsh-agent';
15
+ import type { Scope } from '@deepseek-ai/dsh-scope';
16
+ import type { Session, SessionId, UserMessage } from '@deepseek-ai/dsh-session';
17
+ import type { Context } from '@deepseek-ai/cordis';
18
+ import type { ResolvedConfig } from './types.ts';
19
+ import { type PiSpawnCapability } from './rpc/client.ts';
20
+ /** Provider route label used for logged header snapshots and message provenance. */
21
+ export declare const PROVIDER = "pi";
22
+ /** Drives one session through turn and step boundaries on Pi. */
23
+ export declare class PiAgent implements Agent {
24
+ private loopCtx;
25
+ readonly id: SessionId;
26
+ readonly options: AgentOptions;
27
+ readonly session: Session;
28
+ private readonly config;
29
+ private readonly spawn;
30
+ private readonly bin;
31
+ readonly inbox: Inbox;
32
+ private phase;
33
+ private activityDone;
34
+ /** The agent-scoped registration boundary; the lifecycle owner unwinds it after the driver exits. */
35
+ readonly scope: Scope;
36
+ readonly ctx: Context;
37
+ /** Fused dispatcher, built once in the constructor so hot-path dispatches never allocate. */
38
+ private readonly dispatch;
39
+ /** Whether this loop instance has appended its initial/resume request anchor. */
40
+ private requestHeaderLogged;
41
+ /** Lazily created RPC client, reused across steps and released on scope teardown. */
42
+ private rpc;
43
+ /** The spawn spec the cached client was built from; a change forces a respawn. */
44
+ private lastSpec;
45
+ constructor(loopCtx: Context, id: SessionId, options: AgentOptions, session: Session, config: ResolvedConfig, spawn: PiSpawnCapability, bin: string);
46
+ /** Return the cached RPC client, respawning when the spec or process changed. */
47
+ private rpcClient;
48
+ get status(): AgentStatus;
49
+ /** Commit a phase and publish its externally visible status transition. */
50
+ private setPhase;
51
+ send(message: UserMessage, target: InboxTarget, wakeup: boolean): void;
52
+ /**
53
+ * Queue a message for the next turn and wake the driver.
54
+ * @param input - the user message to deliver.
55
+ */
56
+ followup(input: UserMessage): void;
57
+ /**
58
+ * Queue a message for the running step and wake the driver.
59
+ * @param input - the user message to deliver.
60
+ */
61
+ steer(input: UserMessage): void;
62
+ /**
63
+ * Queue a message for the running step without waking the driver.
64
+ * @param input - the user message to deliver.
65
+ */
66
+ inject(input: UserMessage): void;
67
+ cancel(cause: AgentCancelCause, options?: CancelOptions): void;
68
+ /**
69
+ * Run a maintenance job while the agent is idle.
70
+ * @param job - the maintenance operation, receiving the phase abort signal.
71
+ * @returns the maintenance result.
72
+ */
73
+ runMaintenance<T>(job: (signal: AbortSignal) => Promise<T>): Promise<T>;
74
+ /**
75
+ * Start one driver, or latch its wake behind maintenance or an aborted
76
+ * activity. A wake sent while idle always opens its turn boundary, even
77
+ * when its message was cleared; only a latched replay is suppressed when
78
+ * the queue no longer holds the wake.
79
+ * @param wakeAfterAbort - the {@link send} classification, captured before
80
+ * the inbox insertion so a reentrant cancel cannot reclassify it.
81
+ */
82
+ private wakeDriver;
83
+ whenIdle(): Promise<void>;
84
+ /** Report one failure at its live boundary, then preserve it for driver containment. */
85
+ private throwError;
86
+ private kick;
87
+ private preStep;
88
+ /**
89
+ * Scan the step's user messages for `/name` skill gestures, load each
90
+ * matching skill, and inject the rendered skill content into the message
91
+ * batch. This mirrors what dsh-tool-skill does for the in-process engine.
92
+ * @param messages - the current step's message batch.
93
+ * @param signal - cancellation signal (aborted loads are silently dropped).
94
+ * @returns the original batch when no skill was invoked, or an extended
95
+ * batch with injected skill-content messages appended.
96
+ */
97
+ private injectSkills;
98
+ /**
99
+ * Resolve the runtime permission stance for one query. Deployment-pinned
100
+ * fields win; anything unpinned follows the session's durable dsh permission
101
+ * knobs, re-folded per query so mid-session preset switches take effect on the
102
+ * next step.
103
+ * @returns the permission fields of the query spec.
104
+ */
105
+ private queryPermission;
106
+ /** Open one turn before claiming its first proposed step. */
107
+ private turn;
108
+ /** Model label recorded in the request header for one lifecycle. */
109
+ private modelLabel;
110
+ /** Append the request header snapshot once per loop instance. */
111
+ private assertRequestHeader;
112
+ /**
113
+ * The harness Session's web-side model selection, if any was stored. The
114
+ * durable `model/selection` event carries `{ provider, model, ... }`; when a
115
+ * user picked a model via `/model`, this is the newest pick, and it overrides
116
+ * the deployment config (which stays the fallback). Returns `undefined` when
117
+ * no selection was stored, so the deployment config governs.
118
+ */
119
+ private dynamicModel;
120
+ /** Build the `pi --mode rpc` argv/cwd/env for one step's child process. */
121
+ private spawnSpec;
122
+ /**
123
+ * Run one Pi RPC query for the current step and map its event stream into the
124
+ * session log. The step opens a fresh Pi session (`new_session`) and sends the
125
+ * serialized session history as one prompt, then consumes events until the
126
+ * agent settles. Like the Codex/Claude drivers, Pi owns its own system prompt
127
+ * natively, so the dsh system-prompt assembly (which pulls dsh tool schemas
128
+ * and `agent.ctx.tools`) is deliberately not run — the durable session log is
129
+ * the sole source of model context.
130
+ */
131
+ private step;
132
+ /** Append one Pi tool result to the durable log as a `tool/result` message. */
133
+ private appendToolResult;
134
+ }
135
+ //# sourceMappingURL=agent.d.ts.map
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Pi loop engine module: hosts the AgentFactory that drives every session
3
+ * through the Pi CLI (`@earendil-works/pi-coding-agent`) over its JSONL RPC
4
+ * mode, one stateless session per dsh step, with the durable session log as the
5
+ * sole source of model context. dsh-loop-engine constructs this factory when
6
+ * the Pi engine is selected; this module is a library, not a Cordis plugin
7
+ * entry. Pi has no permission system, so the entire `pi --mode rpc` child is
8
+ * spawned through the dsh subprocess seam — the only available privilege
9
+ * boundary — and its `--tools` are pruned to the resolved sandbox stance.
10
+ *
11
+ * @module dsh-loop-engine/engine-pi
12
+ */
13
+ import { Service } from '@deepseek-ai/cordis';
14
+ import type { Context } from '@deepseek-ai/cordis';
15
+ import z from '@deepseek-ai/schemastery';
16
+ import type { AgentFactory, AgentHandle, CreateAgentOptions, ResumeAgentOptions } from '@deepseek-ai/dsh-agent';
17
+ import type { PiModelEntry } from './probe.ts';
18
+ import type { PiProcess, PiSpawnSpec } from './rpc/client.ts';
19
+ import type { PiSandboxMode, ResolvedConfig } from './types.ts';
20
+ /** Pi CLI sandbox modes a deployment may pin. */
21
+ export declare const PI_SANDBOX_MODES: readonly PiSandboxMode[];
22
+ /** Grace in milliseconds for Pi process-tree termination. */
23
+ export declare const PI_DISPOSE_GRACE_MS = 3000;
24
+ /** Deployment-owned configuration for the Pi loop plugin. */
25
+ export interface Config {
26
+ /**
27
+ * Pinned sandbox stance for every RPC child. When omitted, each query follows
28
+ * the session's dsh permission knobs (`sandbox/mode` and `approval/policy`):
29
+ * full access runs native, `workspace-write` wraps the child in the dsh
30
+ * sandbox with a write-capable tool set, an `ask` policy degrades to a
31
+ * read-only denial, and anything else fails closed with `read-only`.
32
+ */
33
+ sandboxMode?: PiSandboxMode;
34
+ /** LLM provider for the `pi` child (`--provider`), when the deployment pins one. */
35
+ provider?: string;
36
+ /** Model pattern for the `pi` child (`--model`); Pi native settings own the model when omitted. */
37
+ model?: string;
38
+ /** Thinking/reasoning level, appended to the `--model` pattern when pinned. */
39
+ thinkingLevel?: string;
40
+ /** Explicit environment entries passed to the `pi` child. */
41
+ env?: Record<string, string>;
42
+ /** Shared Pi model catalog holder; the loop writes its `pi --list-models` probe result here. */
43
+ piCatalogHolder?: {
44
+ entries: readonly PiModelEntry[];
45
+ };
46
+ }
47
+ /** Schema of the Pi loop plugin configuration. */
48
+ export declare const Config: z<Config>;
49
+ /** Host-face ctx key for the Pi loop service. */
50
+ declare module '@deepseek-ai/cordis' {
51
+ interface Context {
52
+ agentLoopPi: PiLoop;
53
+ }
54
+ }
55
+ /**
56
+ * Concrete AgentFactory and driver service of the Pi loop. Creation and resume
57
+ * follow the registry factory contract and the shared publication transaction:
58
+ * prepare, run setup, then publish through both registries, announce, and emit
59
+ * `agent/session-start`.
60
+ */
61
+ export declare class PiLoop extends Service implements AgentFactory {
62
+ /** Services the loop resolves through its own fiber; blessed identically to the package-level entry inject. */
63
+ static inject: string[];
64
+ /** Validated configuration owned by the loop plugin. */
65
+ readonly config: ResolvedConfig;
66
+ private readonly ownership;
67
+ /** Plain holder prevents Cordis from re-tracing the factory's dependency context through a caller shadow. */
68
+ private readonly runtime;
69
+ /** Process-tree spawn capability handed to every agent, sandboxed by the subprocess seam. */
70
+ readonly spawn: (spec: PiSpawnSpec) => PiProcess;
71
+ /** Resolved Pi CLI entrypoint; `argv[0]` of every Pi RPC child. */
72
+ readonly bin: string;
73
+ constructor(ctx: Context, config: Config);
74
+ /**
75
+ * Construct the driver, scope, and one memoized reverse teardown for a new
76
+ * agent. The teardown is registered with the factory and the owner fiber
77
+ * BEFORE publication, so a mid-setup unload rolls everything back; `signal`
78
+ * fuses caller cancellation with lifecycle teardown for setup awaits.
79
+ */
80
+ private prepare;
81
+ /** Prepare one Agent around an acquired Session, run setup, and publish it. */
82
+ private setupAndPublish;
83
+ /**
84
+ * Create an agent and session under one caller-supplied identity, owned by
85
+ * the accessing fiber. When a persistence backend is mounted, the session's
86
+ * durable identity is stored before publication.
87
+ * @param ownerCtx - caller context that structurally owns the lifecycle.
88
+ * @param options - identities, session seed/metadata, loop options, setup, and cancellation.
89
+ * @returns the published handle.
90
+ */
91
+ createAgent(ownerCtx: Context, options: CreateAgentOptions): Promise<AgentHandle>;
92
+ /**
93
+ * Take a fresh session's write ownership when persistence is mounted.
94
+ * Nothing is appended here: the constructor seed (which never re-emits
95
+ * through `session/event`) is stored by {@link appendUnstoredSuffix} at the
96
+ * publication commit point, so a failed or cancelled setup closes an
97
+ * unmaterialized handle and leaves no stored residue — the same id can be
98
+ * created again.
99
+ * @param session - the unpublished session to store.
100
+ * @param signal - optional cancellation forwarded to the backend create.
101
+ * @returns the owned handle and stored cursor, or `undefined` without a backend.
102
+ */
103
+ private createStoredSession;
104
+ /**
105
+ * Durably store the session events appended since the last stored cursor.
106
+ * Pre-publication appends (constructor seed markers, setup-window events)
107
+ * never re-emit through `session/event`, so publication must flush them
108
+ * through the handle before live events start routing into it.
109
+ * @param stored - the session's owned handle and stored cursor, if any.
110
+ * @param session - the unpublished session whose suffix is stored.
111
+ */
112
+ private appendUnstoredSuffix;
113
+ /**
114
+ * Resume an owned agent from the configured persistence service.
115
+ * @param ownerCtx - caller context that owns load, setup, and the live lifecycle.
116
+ * @param options - persisted identity, loop options, setup, and cancellation.
117
+ * @returns the published handle.
118
+ */
119
+ resume(ownerCtx: Context, options: ResumeAgentOptions): Promise<AgentHandle>;
120
+ /** Resume through an explicit persistence service. */
121
+ private resumeWith;
122
+ }
123
+ //# sourceMappingURL=loop.d.ts.map
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Mapping from the dsh session's durable permission knobs to one Pi RPC
3
+ * process's runtime stance. Pi carries no native permission system — "runs
4
+ * with the permissions of the user" — so the driver cannot ask it to sandbox or
5
+ * approve. The only available boundary is the process environment: the driver
6
+ * either wraps the whole `pi --mode rpc` child in the dsh subprocess sandbox
7
+ * and prunes its `--tools`, or (full access) lets it run under the dsh user.
8
+ * The fold mirrors the codex bridge, mapping the session's `sandbox/mode` and
9
+ * `approval/policy` events directly:
10
+ * - full access → `danger-full-access`, no tool pruning (native tools);
11
+ * - `workspace-write` → sandbox wrap with a write-capable tool set;
12
+ * - an `ask` policy → degraded to a read-only denial (Pi has no request
13
+ * callback, so interactive approval can only become a rejection);
14
+ * - anything else fails closed → `read-only`.
15
+ *
16
+ * @module dsh-loop-engine/engine-pi/permission
17
+ */
18
+ import type { PermissionEvent } from '../driver-core/permission-knobs.ts';
19
+ import type { PiSandboxMode } from './types.ts';
20
+ /** The runtime stance one Pi RPC process should run under. */
21
+ export interface PiPermission {
22
+ /** Sandbox mode driving whether the child is wrapped in the dsh sandbox. */
23
+ readonly sandboxMode: PiSandboxMode;
24
+ /** The `--tools` allowlist; empty means "use Pi's native tools" (no pruning). */
25
+ readonly tools: readonly string[];
26
+ }
27
+ /** Conservative unattended default: read-only sandbox, no write/exec tools. */
28
+ export declare const DEFAULT_PI_PERMISSION: PiPermission;
29
+ /**
30
+ * Derive the `--tools` allowlist for a given sandbox stance. Full access prunes
31
+ * nothing; `workspace-write` allows a write-capable set; `read-only` allows read
32
+ * and search only.
33
+ * @param mode - the resolved sandbox stance.
34
+ * @returns the tool set to pass as `--tools`.
35
+ */
36
+ export declare function toolsForSandbox(mode: PiSandboxMode): readonly string[];
37
+ /**
38
+ * Resolve the session's effective Pi runtime stance.
39
+ * @param events - the durable session log.
40
+ * @returns the stance one Pi RPC process should run under.
41
+ */
42
+ export declare function resolveSessionPermission(events: readonly PermissionEvent[]): PiPermission;
43
+ //# sourceMappingURL=permission.d.ts.map
@@ -0,0 +1,23 @@
1
+ import type { PiProcess, PiSpawnSpec } from './rpc/client.ts';
2
+ /** One discoverable Pi model: the raw two-part identity `pi` exposes. */
3
+ export interface PiModelEntry {
4
+ readonly provider: string;
5
+ readonly model: string;
6
+ }
7
+ /**
8
+ * Parse the output of `pi --list-models`: a column-aligned table whose first
9
+ * two columns are `provider` and `model`. The header row and blank lines are
10
+ * skipped; long model ids simply occupy more columns. Splitting on 2+ spaces
11
+ * yields provider and model in the first two fields regardless of alignment.
12
+ */
13
+ export declare function parsePiModelList(output: string): PiModelEntry[];
14
+ /**
15
+ * Spawn `pi --list-models` and return the parsed model entries. Failures
16
+ * (non-zero exit, no stdout, spawn throw) resolve to an empty array so the
17
+ * catalog stays advisory and a probe glitch never breaks the engine mount.
18
+ * @param bin - the Pi CLI entrypoint (from `piCliEntrypoint()`); becomes spec.argv[0].
19
+ * @param spawn - the process-spawn adapter; `piSubprocessSpec` prepends the node
20
+ * prefix, so spec.argv must NOT carry it.
21
+ */
22
+ export declare function probePiModels(bin: string, spawn: (spec: PiSpawnSpec) => PiProcess): Promise<readonly PiModelEntry[]>;
23
+ //# sourceMappingURL=probe.d.ts.map
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Strict-LF JSONL client for the Pi RPC subprocess (`pi --mode rpc`).
3
+ *
4
+ * The driver hands the client a process handle carrying its stdin/stdout/stderr
5
+ * (projected from the dsh subprocess seam, so the whole `pi` child is sandboxed
6
+ * by the harness). The client frames records on a bare `\n` only — not on
7
+ * Unicode separators — using a byte decoder, tolerates a trailing `\r`, and
8
+ * correlates command responses by the optional `id` field while dispatching
9
+ * every non-response line to a buffered event stream.
10
+ *
11
+ * @module dsh-loop-engine/engine-pi/rpc/client
12
+ */
13
+ import type { ChildProcess } from 'node:child_process';
14
+ import type { Readable, Writable } from 'node:stream';
15
+ import type { PiCommand, PiEvent, PiResponse } from './types.ts';
16
+ /** A spawned Pi RPC process as the protocol transport needs it. */
17
+ export interface PiProcess {
18
+ /** Child stdin (command JSON lines). */
19
+ readonly stdin: Writable;
20
+ /** Child stdout (response + event JSON lines). */
21
+ readonly stdout: Readable;
22
+ /** Child stderr (diagnostics; buffered and dropped). */
23
+ readonly stderr: Readable;
24
+ /** Register a single human-readable termination callback. */
25
+ onExit(handler: () => void): void;
26
+ /** Request process-tree termination. */
27
+ terminate(): void;
28
+ }
29
+ /** The exact argv/cwd/env the driver requests for one `pi --mode rpc` child. */
30
+ export interface PiSpawnSpec {
31
+ /** The program plus its flags; `argv[0]` is the Pi CLI entrypoint. */
32
+ readonly argv: readonly string[];
33
+ readonly cwd: string;
34
+ readonly env: Record<string, string>;
35
+ }
36
+ /** Spawns one Pi RPC process over the given spec (the driver's spawn capability). */
37
+ export type PiSpawnCapability = (spec: PiSpawnSpec) => PiProcess;
38
+ /** Callback receiving every non-response event line. */
39
+ export type PiEventHandler = (event: PiEvent) => void;
40
+ /** Options for one `prompt` command. */
41
+ export interface PiPromptOptions {
42
+ readonly streamingBehavior?: 'steer' | 'followUp';
43
+ }
44
+ /** Project a `node:child_process` child onto the Pi protocol transport. */
45
+ export declare function fromChildProcess(child: ChildProcess): PiProcess;
46
+ /** Prompt the agent and stream its events. */
47
+ export declare class PiRpcClient {
48
+ private readonly process;
49
+ private reqId;
50
+ private pending;
51
+ private readonly eventBuffer;
52
+ private eventWake;
53
+ private eventHandler;
54
+ private disposed;
55
+ private readonly decoder;
56
+ private buffer;
57
+ private readonly onStderr;
58
+ /** Whether this client was disposed or its process exited. */
59
+ get closed(): boolean;
60
+ /** Mount a client over an already-spawned Pi RPC process. */
61
+ constructor(process: PiProcess);
62
+ /**
63
+ * Create a client, spawning the Pi RPC child through the supplied capability
64
+ * (or the default node-runtime spawn when none is given).
65
+ * @param spec - the Pi CLI argv/cwd/env the child should run with.
66
+ * @param spawn - optional process-spawn capability (the subprocess seam);
67
+ * absent falls back to the plain node child spawn.
68
+ * @returns the connected client.
69
+ */
70
+ static create(spec: PiSpawnSpec, spawn?: PiSpawnCapability): PiRpcClient;
71
+ /** Register the event dispatch handler. */
72
+ onEvent(handler: PiEventHandler): void;
73
+ /** Drop any events still buffered from a previous step (stateless per-step sessions). */
74
+ clearEvents(): void;
75
+ /** Start a fresh Pi session. */
76
+ newSession(): Promise<PiResponse>;
77
+ /** Prompt the agent and await the acceptance response. */
78
+ prompt(message: string, options?: PiPromptOptions): Promise<PiResponse>;
79
+ /** Abort the current agent operation. */
80
+ abort(): Promise<PiResponse>;
81
+ /** Query session stats. */
82
+ getSessionStats(): Promise<PiResponse>;
83
+ /** Send a command without awaiting its response (fire-and-forget). */
84
+ send(command: PiCommand): void;
85
+ /**
86
+ * Send a command and await the correlated response. Assigns a fresh `id`
87
+ * when the command carries none, so responses always round-trip.
88
+ */
89
+ request(command: PiCommand): Promise<PiResponse>;
90
+ /**
91
+ * Consume every buffered event as an async generator, waking as fresh lines
92
+ * arrive. The caller bounds the iteration by a terminal event; unmatched
93
+ * lines stay buffered for a later iteration.
94
+ */
95
+ events(): AsyncGenerator<PiEvent, void, void>;
96
+ /** Dispose the client and request child termination. */
97
+ dispose(): void;
98
+ /** Feed one chunk of stdout into the framing state machine. */
99
+ private feed;
100
+ /** Dispatch one parsed line to the pending map or the event queue. */
101
+ private dispatch;
102
+ /** Drain decoded stderr bytes (no-op consumer keeps the pipe flowing). */
103
+ private consumeStderr;
104
+ }
105
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Maps Pi RPC messages and end-of-execution events to dsh session-log events.
3
+ * Token-level streaming deltas are folded inline by the driver's step loop
4
+ * (they carry live progress); this module projects the end-state items — a
5
+ * completed tool call, a completed tool execution, and a finished turn's usage
6
+ * — into the durable `tool/call`, `tool/result`, and usage events.
7
+ *
8
+ * @module dsh-loop-engine/engine-pi/rpc/mapping
9
+ */
10
+ import type { TokenUsage, ToolResultMessage } from '@deepseek-ai/dsh-llm';
11
+ import type { PiUsage } from './types.ts';
12
+ /** Map one Pi usage snapshot to dsh TokenUsage. */
13
+ export declare function mapUsage(usage: PiUsage): TokenUsage;
14
+ /**
15
+ * Derive the compact transcript text of a Pi content block, joining nested
16
+ * text segments so the durable tool-result block carries the read model text.
17
+ * @param content - the result payload (e.g. `{ content: [{ type, text }, ...] }`).
18
+ * @returns the joined text.
19
+ */
20
+ export declare function resultText(content: unknown): string;
21
+ /** Map a completed Pi tool-execution end event to the durable tool/result message. */
22
+ export declare function mapToolResult(ev: {
23
+ toolCallId: string;
24
+ result: unknown;
25
+ isError: boolean;
26
+ }): ToolResultMessage;
27
+ /** Map the identity of a Pi message tool call or execution start to a durable tool/call. */
28
+ export declare function mapToolCall(ev: {
29
+ callId: string;
30
+ name: string;
31
+ arguments: unknown;
32
+ }): {
33
+ callId: string;
34
+ name: string;
35
+ arguments: string;
36
+ };
37
+ //# sourceMappingURL=mapping.d.ts.map