@elpapi42/pi-fleet-sdk 0.2.0-beta.0 → 0.2.0-beta.14

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.md CHANGED
@@ -1,3 +1,269 @@
1
1
  # @elpapi42/pi-fleet-sdk
2
2
 
3
- This version only reserves the official package name for pi-fleet trusted publishing. It contains no SDK implementation. Use `0.2.0-beta.1` or later.
3
+ `@elpapi42/pi-fleet-sdk` is the TypeScript client for one installed per-user `pi-fleet-daemon`.
4
+
5
+ The SDK controls agents through the daemon's private Unix socket. It does not install, start, stop, repair, or upgrade the daemon. It does not resolve Pi, open the pi-fleet database, or select a state root. Importing the package has no filesystem, socket, or process side effects.
6
+
7
+ ## Requirements
8
+
9
+ - Node.js `^22.19.0 || ^24.0.0`
10
+ - A compatible `pi-fleet-daemon` installed and active for the current OS user
11
+
12
+ Install the SDK separately from the daemon:
13
+
14
+ ```sh
15
+ npm install @elpapi42/pi-fleet-sdk
16
+ ```
17
+
18
+ ## Connect and create an agent
19
+
20
+ ```ts
21
+ import { connectPiFleet, PiFleetError } from "@elpapi42/pi-fleet-sdk";
22
+
23
+ let client;
24
+ try {
25
+ client = await connectPiFleet();
26
+ } catch (error) {
27
+ if (error instanceof PiFleetError) {
28
+ switch (error.code) {
29
+ case "daemon_unavailable":
30
+ // The daemon endpoint is absent or unavailable.
31
+ break;
32
+ case "endpoint_unsafe":
33
+ // The endpoint failed ownership, mode, type, or identity checks.
34
+ break;
35
+ case "daemon_rejected":
36
+ case "protocol_incompatible":
37
+ // The installed daemon cannot accept this SDK connection.
38
+ break;
39
+ }
40
+ }
41
+ throw error;
42
+ }
43
+
44
+ try {
45
+ const reviewer = await client.create({
46
+ name: "reviewer",
47
+ cwd: "/workspace/project",
48
+ instructions: "Review the current changes.",
49
+ piArgs: ["--model", "provider/model"],
50
+ });
51
+
52
+ console.log(reviewer.name, reviewer.id);
53
+ } finally {
54
+ await client.close();
55
+ }
56
+ ```
57
+
58
+ `connectPiFleet()` performs a passive daemon handshake. It sends no agent operation and never starts a missing daemon.
59
+
60
+ `piArgs` are exact Pi passthrough tokens. They can contain secrets. The SDK sends them unchanged and does not log them. The daemon stores them in private local state for session restoration. Do not copy them into application logs or diagnostics.
61
+
62
+ ## Get and list agents
63
+
64
+ ```ts
65
+ const reviewer = await client.get("reviewer");
66
+ const summaries = await client.list();
67
+
68
+ for (const summary of summaries) {
69
+ console.log(summary.name, summary.id, summary.state, summary.process.state);
70
+ }
71
+
72
+ const current = await reviewer.status();
73
+ console.log(current.state);
74
+ ```
75
+
76
+ `create()` and `get()` return remote `Agent` handles. `list()` returns summaries, not handles.
77
+
78
+ Each handle binds the agent's immutable UUID and reusable name. If an agent is destroyed and another agent later uses the same name, the old handle fails. It never targets the replacement.
79
+
80
+ `get()` throws `PiFleetError` with code `agent_not_found` when the name does not exist.
81
+
82
+ ## Send instructions
83
+
84
+ Steering is the default delivery mode:
85
+
86
+ ```ts
87
+ const receipt = await reviewer.send("Check the public error boundary.");
88
+ console.log(receipt.acceptedAt);
89
+ ```
90
+
91
+ Use `followUp` when Pi must process the instruction after its current work:
92
+
93
+ ```ts
94
+ await reviewer.send("Run the focused tests next.", {
95
+ delivery: "followUp",
96
+ });
97
+ ```
98
+
99
+ `send()` reports acceptance only. It does not return an assistant response or correlate a later response with one send. Use `receive()` to observe agent activity.
100
+
101
+ ## Receive semantic events
102
+
103
+ `receive()` is a passive continuous stream. It does not start or restore Pi. The default stream begins at its live attachment boundary. The stream remains open across idle periods, Pi restoration, and recoverable daemon restarts.
104
+
105
+ ```ts
106
+ const stream = await reviewer.receive();
107
+
108
+ // The initial cursor is available before the first event.
109
+ await saveCursor(stream.cursor);
110
+
111
+ for await (const event of stream) {
112
+ console.log(event.observedAt, event.type, event.id);
113
+
114
+ if (event.type === "assistant.message.finished") {
115
+ console.log(event.text);
116
+ }
117
+ }
118
+ ```
119
+
120
+ The SDK emits these six event types:
121
+
122
+ - `assistant.thinking.started`
123
+ - `assistant.thinking.finished`
124
+ - `assistant.message.started`
125
+ - `assistant.message.finished`
126
+ - `tool.execution.started`
127
+ - `tool.execution.finished`
128
+
129
+ The stream emits semantic lifecycle start and finish events, not raw Pi RPC records or text deltas. An observed start can remain unmatched after interruption. Each event includes an event ID, activity ID, agent ID, cursor, observation epoch, raw-record position, and observation time.
130
+
131
+ Each stream permits one consumer. Call `receive()` again to create an independent subscription.
132
+
133
+ ### Start modes
134
+
135
+ ```ts
136
+ // Live events from this attachment boundary.
137
+ const live = await reviewer.receive();
138
+
139
+ // All retained events from the start.
140
+ const history = await reviewer.receive({ fromStart: true });
141
+
142
+ // Events after an opaque cursor previously returned by this agent's stream.
143
+ const resumed = await reviewer.receive({ after: savedCursor });
144
+ ```
145
+
146
+ `after` and `fromStart` are mutually exclusive. Treat cursors as opaque values. Store and restore only exact cursors returned by the SDK for the same agent generation.
147
+
148
+ ### Checkpoint and deduplicate
149
+
150
+ Receive reconnection is at least once. A resumed stream can emit an event ID that the application already processed.
151
+
152
+ For durable consumers:
153
+
154
+ 1. Save `stream.cursor` after attachment and before reading the first event.
155
+ 2. Deduplicate events by `event.id`.
156
+ 3. Process an event and save `event.cursor` in one application transaction when possible.
157
+ 4. Resume with `receive({ after: savedCursor })`.
158
+
159
+ ```ts
160
+ for await (const event of stream) {
161
+ if (await hasProcessedEvent(event.id)) {
162
+ await saveCursor(event.cursor);
163
+ continue;
164
+ }
165
+
166
+ await processAndCheckpoint(event, event.cursor);
167
+ }
168
+ ```
169
+
170
+ ## Handle observation uncertainty
171
+
172
+ The SDK reconnects after recoverable daemon loss from the last safe cursor. It never crosses a known observation gap automatically.
173
+
174
+ If continuity is uncertain, the stream throws `PiFleetError` with code `observation_uncertain`. The error includes `lastSafeCursor` and can include `continuationCursor`. Continue only after the application explicitly accepts the gap.
175
+
176
+ ```ts
177
+ import { PiFleetError, type Agent, type ReceiveStream } from "@elpapi42/pi-fleet-sdk";
178
+
179
+ async function consume(agent: Agent, initial: ReceiveStream): Promise<void> {
180
+ let stream = initial;
181
+
182
+ while (true) {
183
+ try {
184
+ await saveCursor(stream.cursor);
185
+ for await (const event of stream) {
186
+ await processAndCheckpoint(event, event.cursor);
187
+ }
188
+ return;
189
+ } catch (error) {
190
+ if (!(error instanceof PiFleetError) || error.code !== "observation_uncertain") {
191
+ throw error;
192
+ }
193
+
194
+ const continuation = error.details?.continuationCursor;
195
+ if (continuation === undefined) throw error;
196
+
197
+ await acceptObservationGap({
198
+ lastSafeCursor: error.details?.lastSafeCursor,
199
+ continuationCursor: continuation,
200
+ });
201
+
202
+ stream = await agent.receive({ after: continuation });
203
+ }
204
+ }
205
+ }
206
+ ```
207
+
208
+ The application owns the gap decision. Do not use `continuationCursor` as an automatic retry cursor.
209
+
210
+ ## Cancellation and close
211
+
212
+ Pass an `AbortSignal` to connection, finite operations, sends, or receive streams:
213
+
214
+ ```ts
215
+ const controller = new AbortController();
216
+
217
+ const stream = await reviewer.receive({ signal: controller.signal });
218
+ const consuming = (async () => {
219
+ for await (const event of stream) {
220
+ await processEvent(event);
221
+ }
222
+ })();
223
+
224
+ controller.abort();
225
+
226
+ try {
227
+ await consuming;
228
+ } catch (error) {
229
+ if (!(error instanceof PiFleetError) || error.code !== "cancelled") throw error;
230
+ }
231
+ ```
232
+
233
+ Caller cancellation uses the `cancelled` code. Work cancelled by `client.close()` uses `client_closed`.
234
+
235
+ `client.close()` is idempotent and local. It cancels this client's pending requests, receive streams, connection attempts, and reconnect delays. It does not stop the daemon, destroy agents, stop Pi, or change shared state.
236
+
237
+ ```ts
238
+ try {
239
+ // Use the client.
240
+ } finally {
241
+ await client.close();
242
+ }
243
+ ```
244
+
245
+ ## Error boundary
246
+
247
+ All public SDK failures are `PiFleetError` instances with a closed `code` union and fixed content-safe messages. The SDK does not expose daemon messages, filesystem paths, Pi arguments, prompts, raw protocol records, or nested internal errors.
248
+
249
+ Useful connection and lifecycle codes include:
250
+
251
+ - `daemon_unavailable`: the canonical daemon endpoint is unavailable
252
+ - `endpoint_unsafe`: endpoint trust checks failed
253
+ - `daemon_rejected`: the daemon rejected the SDK handshake
254
+ - `protocol_incompatible`: protocol or required capabilities are incompatible
255
+ - `timeout`: connection or handshake timed out
256
+ - `runtime_unavailable`: an established daemon connection was lost
257
+ - `cancelled`: the caller cancelled the operation
258
+ - `client_closed`: `client.close()` cancelled local work
259
+ - `observation_uncertain`: receive continuity has a known gap
260
+
261
+ ## SDK boundary
262
+
263
+ The SDK has no public daemon-management API. Install and manage `pi-fleet-daemon` separately.
264
+
265
+ Neither the current SDK nor the proposed CLI exposes `untilIdle`. The SDK uses continuous receive streams with explicit cursors. Callers decide when to stop consuming events without treating that choice as agent task completion.
266
+
267
+ ## License
268
+
269
+ MIT
@@ -0,0 +1,174 @@
1
+ export declare type ActivityId = string & {
2
+ readonly __brand: "ActivityId";
3
+ };
4
+
5
+ export declare interface Agent {
6
+ readonly id: AgentId;
7
+ readonly name: string;
8
+ status(options?: SdkRequestOptions): Promise<AgentSummary>;
9
+ send(message: string, options?: {
10
+ readonly delivery?: SendDelivery;
11
+ readonly signal?: AbortSignal;
12
+ }): Promise<InputReceipt>;
13
+ receive(options?: AgentReceiveOptions): Promise<ReceiveStream>;
14
+ compact(options?: SdkRequestOptions): Promise<CompactionSummary>;
15
+ destroy(options?: SdkRequestOptions): Promise<void>;
16
+ }
17
+
18
+ export declare type AgentEventId = string & {
19
+ readonly __brand: "AgentEventId";
20
+ };
21
+
22
+ export declare type AgentId = string & {
23
+ readonly __brand: "AgentId";
24
+ };
25
+
26
+ export declare type AgentReceiveOptions = {
27
+ readonly signal?: AbortSignal;
28
+ } & ({
29
+ readonly after?: never;
30
+ readonly fromStart?: false;
31
+ } | {
32
+ readonly after: ReceiveCursor;
33
+ readonly fromStart?: never;
34
+ } | {
35
+ readonly after?: never;
36
+ readonly fromStart: true;
37
+ });
38
+
39
+ export declare type AgentState = "restoring" | "working" | "idle" | "failed" | "destroying";
40
+
41
+ export declare interface AgentSummary {
42
+ readonly id: string;
43
+ readonly name: string;
44
+ readonly state: AgentState;
45
+ readonly process: {
46
+ readonly state: ProcessState;
47
+ };
48
+ readonly session: {
49
+ readonly path: string | null;
50
+ readonly id: string | null;
51
+ };
52
+ readonly error?: {
53
+ readonly code: string;
54
+ } | undefined;
55
+ }
56
+
57
+ export declare interface AssistantMessageFinishedEvent extends SemanticEventBase {
58
+ readonly type: "assistant.message.finished";
59
+ readonly text: string;
60
+ }
61
+
62
+ export declare interface AssistantMessageStartedEvent extends SemanticEventBase {
63
+ readonly type: "assistant.message.started";
64
+ }
65
+
66
+ export declare interface AssistantThinkingFinishedEvent extends SemanticEventBase {
67
+ readonly type: "assistant.thinking.finished";
68
+ readonly text: string;
69
+ }
70
+
71
+ export declare interface AssistantThinkingStartedEvent extends SemanticEventBase {
72
+ readonly type: "assistant.thinking.started";
73
+ }
74
+
75
+ export declare interface CompactionSummary {
76
+ readonly tokensBefore: number;
77
+ readonly estimatedTokensAfter?: number;
78
+ }
79
+
80
+ declare type ConnectPiFleet = (options?: ConnectPiFleetOptions) => Promise<PiFleetClient>;
81
+
82
+ /** Connects to the explicitly installed per-user pi-fleet daemon. */
83
+ export declare const connectPiFleet: ConnectPiFleet;
84
+
85
+ export declare interface ConnectPiFleetOptions {
86
+ readonly signal?: AbortSignal;
87
+ }
88
+
89
+ declare type ContinuityEpoch = number & {
90
+ readonly __brand: "ContinuityEpoch";
91
+ };
92
+
93
+ export declare interface CreateAgentInput {
94
+ readonly name: string;
95
+ readonly cwd: string;
96
+ readonly piArgs?: readonly string[];
97
+ readonly instructions?: string;
98
+ }
99
+
100
+ export declare interface InputReceipt {
101
+ readonly acceptedAt: string;
102
+ }
103
+
104
+ export declare interface PiFleetClient {
105
+ create(input: CreateAgentInput, options?: SdkRequestOptions): Promise<Agent>;
106
+ get(name: string, options?: SdkRequestOptions): Promise<Agent>;
107
+ list(options?: SdkRequestOptions): Promise<readonly AgentSummary[]>;
108
+ close(): Promise<void>;
109
+ }
110
+
111
+ export declare class PiFleetError extends Error {
112
+ readonly code: PiFleetErrorCode;
113
+ readonly details: Readonly<PiFleetErrorDetails> | undefined;
114
+ constructor(code: PiFleetErrorCode, details?: Readonly<PiFleetErrorDetails>);
115
+ }
116
+
117
+ export declare type PiFleetErrorCode = (typeof SDK_PUBLIC_ERROR_CODES)[number];
118
+
119
+ export declare interface PiFleetErrorDetails {
120
+ readonly lastSafeCursor?: ReceiveCursor;
121
+ readonly continuationCursor?: ReceiveCursor;
122
+ }
123
+
124
+ export declare type ProcessState = "resident" | "starting" | "absent" | "cleanup_uncertain";
125
+
126
+ export declare type ReceiveCursor = string & {
127
+ readonly __brand: "ReceiveCursor";
128
+ };
129
+
130
+ export declare interface ReceiveStream extends AsyncIterable<SemanticEvent> {
131
+ readonly cursor: ReceiveCursor;
132
+ }
133
+
134
+ declare const SDK_PUBLIC_ERROR_CODES: readonly ["agent_busy", "agent_destroyed", "agent_destroying", "agent_not_found", "capacity_exceeded", "cancelled", "compaction_failed", "compaction_uncertain", "cursor_expired", "cursor_invalid", "cursor_wrong_agent", "delivery_uncertain", "destroy_incomplete", "incarnation_cleanup_uncertain", "internal_error", "invalid_arguments", "invalid_request", "name_taken", "nothing_to_compact", "observation_uncertain", "operation_conflict", "operation_in_progress", "pi_installation_changed", "pi_not_executable", "pi_not_found", "pi_start_failed", "pi_version_unavailable", "protocol_error", "protocol_incompatible", "receive_resource_exhausted", "runtime_interrupted", "runtime_unavailable", "semantic_event_too_large", "stale_agent", "state_corrupt", "storage_unavailable", "timeout", "client_closed", "daemon_rejected", "daemon_unavailable", "endpoint_unsafe"];
135
+
136
+ export declare interface SdkRequestOptions {
137
+ readonly signal?: AbortSignal;
138
+ }
139
+
140
+ export declare type SemanticEvent = AssistantThinkingStartedEvent | AssistantThinkingFinishedEvent | AssistantMessageStartedEvent | AssistantMessageFinishedEvent | ToolExecutionStartedEvent | ToolExecutionFinishedEvent;
141
+
142
+ declare interface SemanticEventBase {
143
+ readonly id: AgentEventId;
144
+ readonly activityId: ActivityId;
145
+ readonly agentId: AgentId;
146
+ readonly cursor: ReceiveCursor;
147
+ readonly epoch: ContinuityEpoch;
148
+ readonly sourceRawPosition: number;
149
+ readonly observedAt: string;
150
+ }
151
+
152
+ export declare type SendDelivery = "steer" | "followUp";
153
+
154
+ export declare interface ToolExecutionFinishedEvent extends SemanticEventBase {
155
+ readonly type: "tool.execution.finished";
156
+ readonly tool: {
157
+ readonly callId: string;
158
+ readonly name: string;
159
+ readonly input: unknown;
160
+ readonly output: unknown;
161
+ readonly isError: boolean;
162
+ };
163
+ }
164
+
165
+ export declare interface ToolExecutionStartedEvent extends SemanticEventBase {
166
+ readonly type: "tool.execution.started";
167
+ readonly tool: {
168
+ readonly callId: string;
169
+ readonly name: string;
170
+ readonly input: unknown;
171
+ };
172
+ }
173
+
174
+ export { }
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ var DAEMON_PROTOCOL_IDENTITY_VALUE=Object.freeze({major:4,minor:0});var DAEMON_INCOMPATIBLE_MINOR_REVISIONS=Object.freeze([]);var DAEMON_JOURNAL_SCHEMA_VERSION=3;var DAEMON_PLATFORM_IDENTITY=Object.freeze({os:"linux",cpu:"x64"});var DAEMON_SUPPORTED_CAPABILITY_NAMES=Object.freeze(["agent.compact.v1","agent.create.v1","agent.destroy.v1","agent.list.v1","agent.receive.v1","agent.send.v1","agent.status.v1","receive.continuation.v1","receive.cursor.v1","receive.replay.v1","receive.semantic-events.v1"]);var DAEMON_DEFAULT_HANDSHAKE_LIMITS=Object.freeze({maxFrameBytes:1024*1024,maxEventBytes:1024*1024,maxSegments:4096});var DAEMON_CAPABILITY_DECLARATION=Object.freeze({protocol:DAEMON_PROTOCOL_IDENTITY_VALUE,incompatibleMinorRevisions:DAEMON_INCOMPATIBLE_MINOR_REVISIONS,journalSchemaVersion:DAEMON_JOURNAL_SCHEMA_VERSION,platform:DAEMON_PLATFORM_IDENTITY,supportedCapabilities:DAEMON_SUPPORTED_CAPABILITY_NAMES,defaultLimits:DAEMON_DEFAULT_HANDSHAKE_LIMITS});import{createConnection}from"node:net";var CLIENT_TRANSPORT_CONNECT_TIMEOUT_MS=5e3;var CLIENT_TRANSPORT_PRE_READY_FRAME_BYTES=64*1024;var CLIENT_TRANSPORT_MAX_QUEUED_FRAMES=64;var CLIENT_TRANSPORT_MAX_FRAME_BYTES=64*1024*1024;var ERROR_MESSAGES={cancelled:"The daemon operation was cancelled.",connection_closed:"The daemon connection closed.",connection_failed:"The daemon connection failed.",connection_timeout:"The daemon connection timed out.",protocol_error:"The daemon protocol frame is invalid."};var ClientTransportError=class extends Error{constructor(code){super(ERROR_MESSAGES[code]);this.code=code;this.name="ClientTransportError"}};var defaultTimers={set:(callback,delayMs)=>setTimeout(callback,delayMs),clear:handle=>clearTimeout(handle)};var JsonLineConnection=class _JsonLineConnection{#socket;#timers;#waiters=[];#queue=[];#terminalListeners=new Set;#closePromise;#connectionSignal;#onConnectionAbort;#resolveClose;#buffer=Buffer.alloc(0);#failure=null;#socketClosed=false;#frameLimit=CLIENT_TRANSPORT_PRE_READY_FRAME_BYTES;constructor(socket,timers,signal){this.#socket=socket;this.#timers=timers;this.#connectionSignal=signal;this.#closePromise=new Promise(resolve2=>{this.#resolveClose=resolve2});this.#onConnectionAbort=signal===void 0?void 0:()=>this.#terminate(transportError("cancelled"),true,false);socket.on("data",this.#onData);socket.on("error",this.#onSocketError);socket.on("end",this.#onSocketEnd);socket.on("close",this.#onSocketClose);signal?.addEventListener("abort",this.#onConnectionAbort,{once:true});if(signal?.aborted)this.#onConnectionAbort?.()}static async connect(path,options={}){if(options.signal?.aborted)throw transportError("cancelled");const timeoutMs=options.connectTimeoutMs??CLIENT_TRANSPORT_CONNECT_TIMEOUT_MS;assertTimeout(timeoutMs);const timers=options.timers??defaultTimers;const socketFactory=options.socketFactory??createConnection;return new Promise((resolve2,reject)=>{let socket;try{socket=socketFactory(path)}catch{reject(transportError("connection_failed"));return}let settled=false;const timerCancellation={};const cleanup=()=>{timerCancellation.cancel?.();options.signal?.removeEventListener("abort",onAbort);socket.off("connect",onConnect);socket.off("error",onError);socket.off("close",onClose)};const finish=(callback,destroy)=>{if(settled)return;settled=true;cleanup();if(destroy&&!socket.destroyed)socket.destroy();callback()};const onAbort=()=>finish(()=>reject(transportError("cancelled")),true);const onConnect=()=>{const connection=new _JsonLineConnection(socket,timers,options.signal);finish(()=>resolve2(connection),false)};const onError=()=>finish(()=>reject(transportError("connection_failed")),true);const onClose=()=>finish(()=>reject(transportError("connection_failed")),false);options.signal?.addEventListener("abort",onAbort,{once:true});socket.once("connect",onConnect);socket.once("error",onError);socket.once("close",onClose);timerCancellation.cancel=scheduleTimer(timers,()=>finish(()=>reject(transportError("connection_timeout")),true),timeoutMs);if(options.signal?.aborted)onAbort()})}setFrameLimit(limit){if(!Number.isSafeInteger(limit)||limit<=0||limit>CLIENT_TRANSPORT_MAX_FRAME_BYTES){throw transportError("protocol_error")}this.#frameLimit=limit;if(this.#buffer.byteLength>limit||this.#queue.some(frame=>frame.frameBytes>limit)){const error=transportError("protocol_error");this.#terminate(error,true,false);throw error}}assertUsable(){if(this.#failure!==null)throw this.#failure}hasQueuedFrames(){return this.#queue.length>0}async write(value,options={}){this.#throwIfUnavailable(options.signal);let serialized;try{serialized=JSON.stringify(value)}catch{throw transportError("protocol_error")}if(serialized===void 0)throw transportError("protocol_error");const frame=Buffer.from(serialized,"utf8");if(frame.byteLength>this.#frameLimit)throw transportError("protocol_error");const bytes=Buffer.allocUnsafe(frame.byteLength+1);frame.copy(bytes);bytes[bytes.byteLength-1]=10;await new Promise((resolve2,reject)=>{let settled=false;let cancelTimer;const timeoutMs=options.timeoutMs;if(timeoutMs!==void 0)assertTimeout(timeoutMs);const cleanup=()=>{options.signal?.removeEventListener("abort",onAbort);this.#terminalListeners.delete(onTerminal);cancelTimer?.()};const finish=callback=>{if(settled)return;settled=true;cleanup();callback()};const onTerminal=error=>finish(()=>reject(error));const onAbort=()=>this.#terminate(transportError("cancelled"),true,false);const onTimeout=()=>this.#terminate(transportError("connection_timeout"),true,false);options.signal?.addEventListener("abort",onAbort,{once:true});this.#terminalListeners.add(onTerminal);if(timeoutMs!==void 0){cancelTimer=scheduleTimer(this.#timers,onTimeout,timeoutMs)}if(settled)return;try{this.#socket.write(bytes,error=>{if(error!==void 0&&error!==null){this.#terminate(transportError("connection_failed"),true,true);return}finish(resolve2)})}catch{this.#terminate(transportError("connection_failed"),true,true)}if(options.signal?.aborted)onAbort()})}next(options={}){if(options.signal?.aborted){this.#terminate(transportError("cancelled"),true,false);return Promise.reject(transportError("cancelled"))}const queued=this.#queue.shift();if(queued!==void 0)return Promise.resolve(queued.value);if(this.#failure!==null)return Promise.reject(this.#failure);if(options.timeoutMs!==void 0)assertTimeout(options.timeoutMs);return new Promise((resolve2,reject)=>{let cancelTimer;const waiter={resolve:value=>finish(()=>resolve2(value)),reject:error=>finish(()=>reject(error))};const cleanup=()=>{options.signal?.removeEventListener("abort",onAbort);cancelTimer?.();const index=this.#waiters.indexOf(waiter);if(index>=0)this.#waiters.splice(index,1)};let settled=false;const finish=callback=>{if(settled)return;settled=true;cleanup();callback()};const onAbort=()=>this.#terminate(transportError("cancelled"),true,false);const onTimeout=()=>this.#terminate(transportError("connection_timeout"),true,false);this.#waiters.push(waiter);options.signal?.addEventListener("abort",onAbort,{once:true});if(options.timeoutMs!==void 0){cancelTimer=scheduleTimer(this.#timers,onTimeout,options.timeoutMs)}if(options.signal?.aborted)onAbort()})}async close(){if(this.#failure===null){this.#terminate(transportError("connection_closed"),true,false)}else if(!this.#socket.destroyed){this.#socket.destroy()}if(!this.#socketClosed)await this.#closePromise}#onData=chunk=>{if(this.#failure!==null)return;let offset=0;while(offset<chunk.byteLength){const newline=chunk.indexOf(10,offset);const end=newline<0?chunk.byteLength:newline;const segment=chunk.subarray(offset,end);if(this.#buffer.byteLength+segment.byteLength>this.#frameLimit){this.#terminate(transportError("protocol_error"),true,false);return}if(segment.byteLength>0){this.#buffer=appendBounded(this.#buffer,segment)}if(newline<0)return;let lineBytes=this.#buffer;const frameBytes=lineBytes.byteLength;this.#buffer=Buffer.alloc(0);if(lineBytes.at(-1)===13)lineBytes=lineBytes.subarray(0,-1);offset=newline+1;if(lineBytes.byteLength===0)continue;let line;try{line=new TextDecoder("utf-8",{fatal:true}).decode(lineBytes)}catch{this.#terminate(transportError("protocol_error"),true,false);return}let value;try{value=JSON.parse(line)}catch{this.#terminate(transportError("protocol_error"),true,false);return}const waiter=this.#waiters.shift();if(waiter!==void 0){waiter.resolve(value)}else if(this.#queue.length>=CLIENT_TRANSPORT_MAX_QUEUED_FRAMES){this.#terminate(transportError("protocol_error"),true,false);return}else{this.#queue.push({value,frameBytes})}}};#onSocketError=()=>{this.#terminate(transportError("connection_failed"),true,true)};#onSocketEnd=()=>{this.#terminate(transportError(this.#buffer.byteLength===0?"connection_closed":"protocol_error"),true,this.#buffer.byteLength===0)};#onSocketClose=()=>{this.#socketClosed=true;this.#resolveClose();if(this.#failure===null){this.#terminate(transportError(this.#buffer.byteLength===0?"connection_closed":"protocol_error"),false,this.#buffer.byteLength===0)}this.#socket.off("error",this.#onSocketError);this.#socket.off("close",this.#onSocketClose)};#throwIfUnavailable(signal){if(signal?.aborted){this.#terminate(transportError("cancelled"),true,false);throw transportError("cancelled")}if(this.#failure!==null)throw this.#failure}#terminate(error,destroy,preserveQueuedFrames){if(this.#failure!==null)return;this.#failure=error;this.#connectionSignal?.removeEventListener("abort",this.#onConnectionAbort);this.#socket.off("data",this.#onData);this.#socket.off("end",this.#onSocketEnd);this.#buffer=Buffer.alloc(0);if(!preserveQueuedFrames)this.#queue.length=0;while(this.#waiters.length>0)this.#waiters.shift().reject(error);for(const listener of[...this.#terminalListeners])listener(error);if(destroy&&!this.#socket.destroyed)this.#socket.destroy()}};function appendBounded(existing,segment){if(existing.byteLength===0)return Buffer.from(segment);return Buffer.concat([existing,segment],existing.byteLength+segment.byteLength)}function scheduleTimer(timers,callback,delayMs){let fired=false;const handle=timers.set(()=>{fired=true;callback()},delayMs);if(fired)timers.clear(handle);return()=>timers.clear(handle)}function assertTimeout(timeoutMs){if(!Number.isSafeInteger(timeoutMs)||timeoutMs<0)throw transportError("protocol_error")}function transportError(code){return new ClientTransportError(code)}var MAX_CAPABILITIES=32;var MAX_CAPABILITY_BYTES=128;var MAX_INCOMPATIBLE_MINOR_REVISIONS=16;var MAX_RELEASE_VERSION_BYTES=128;var MAX_EVENT_BYTES=64*1024*1024;var MAX_SEGMENTS=1e6;var releaseVersionPattern=/^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/;var capabilityPattern=/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/;var CLIENT_HANDSHAKE_TIMEOUT_MS=CLIENT_TRANSPORT_CONNECT_TIMEOUT_MS;var HANDSHAKE_ERROR_MESSAGES=Object.freeze({invalid_handshake:"The daemon handshake is invalid.",invalid_hello:"The daemon rejected the client handshake.",protocol_incompatible:"The client and daemon protocol versions are incompatible.",minor_incompatible:"The client and daemon protocol minor versions are incompatible.",capability_unsupported:"The daemon does not support a required capability.",limits_invalid:"The client and daemon limits are incompatible."});var ClientHandshakeError=class extends Error{constructor(code){super(HANDSHAKE_ERROR_MESSAGES[code]);this.code=code;this.name="ClientHandshakeError"}};var rejectionCodes=new Set(["invalid_hello","protocol_incompatible","minor_incompatible","capability_unsupported","limits_invalid"]);async function performClientHandshake(connection,configuration,options={}){try{const hello=createClientHello(configuration);const timeoutMs=options.timeoutMs??CLIENT_HANDSHAKE_TIMEOUT_MS;assertBoundedInteger(timeoutMs,0,Number.MAX_SAFE_INTEGER,"invalid_handshake");const deadline=new HandshakeDeadline(timeoutMs,options.now??monotonicNow);await connection.write(hello,operationOptions(connection,deadline,options.signal));const frame=await connection.next(operationOptions(connection,deadline,options.signal));assertHandshakeActive(connection,deadline,options.signal);const ready=validateDaemonHandshake(frame,hello.requiredCapabilities,hello.incompatibleMinorRevisions,hello.requestedLimits);assertHandshakeActive(connection,deadline,options.signal);connection.setFrameLimit(ready.limits.maxFrameBytes);assertHandshakeActive(connection,deadline,options.signal);return ready}catch(error){closeAfterHandshakeFailure(connection);if(error instanceof ClientHandshakeError||isTransportError(error))throw error;throw handshakeError("invalid_handshake")}}function createClientHello(configuration){if(!isClientType(configuration.clientType))throw handshakeError("invalid_handshake");assertReleaseVersion(configuration.releaseVersion);assertCanonicalCapabilities(configuration.requiredCapabilities);const incompatibleMinorRevisions=configuration.incompatibleMinorRevisions??[];assertCanonicalMinorRevisions(incompatibleMinorRevisions);assertLimits(configuration.requestedLimits);return deepFreeze({v:DAEMON_PROTOCOL_IDENTITY_VALUE.major,type:"client.hello",protocol:{major:DAEMON_PROTOCOL_IDENTITY_VALUE.major,minor:DAEMON_PROTOCOL_IDENTITY_VALUE.minor},client:{type:configuration.clientType,releaseVersion:configuration.releaseVersion},requiredCapabilities:[...configuration.requiredCapabilities],incompatibleMinorRevisions:[...incompatibleMinorRevisions],requestedLimits:{maxFrameBytes:configuration.requestedLimits.maxFrameBytes,maxEventBytes:configuration.requestedLimits.maxEventBytes,maxSegments:configuration.requestedLimits.maxSegments}})}function validateDaemonHandshake(value,requiredCapabilities,clientIncompatibleMinorRevisions,requestedLimits){if(!isRecord(value)||value.v!==DAEMON_PROTOCOL_IDENTITY_VALUE.major){throw handshakeError("invalid_handshake")}if(value.type==="daemon.rejected")return rejectDaemonHandshake(value);if(value.type!=="daemon.ready")throw handshakeError("invalid_handshake");const protocol=requiredRecord(value.protocol);assertBoundedInteger(protocol.major,0,255,"invalid_handshake");assertBoundedInteger(protocol.minor,0,255,"invalid_handshake");if(protocol.major!==DAEMON_PROTOCOL_IDENTITY_VALUE.major){throw handshakeError("protocol_incompatible")}const daemon=requiredRecord(value.daemon);assertReleaseVersion(daemon.releaseVersion);const platform=requiredRecord(daemon.platform);if(platform.os!==DAEMON_PLATFORM_IDENTITY.os||platform.cpu!==DAEMON_PLATFORM_IDENTITY.cpu||daemon.journalSchemaVersion!==DAEMON_JOURNAL_SCHEMA_VERSION){throw handshakeError("invalid_handshake")}assertCanonicalCapabilities(value.supportedCapabilities);const supportedCapabilities=value.supportedCapabilities;const supported=new Set(supportedCapabilities);if(requiredCapabilities.some(capability=>!supported.has(capability))){throw handshakeError("capability_unsupported")}if(clientIncompatibleMinorRevisions.includes(protocol.minor)){throw handshakeError("minor_incompatible")}assertCanonicalMinorRevisions(value.incompatibleMinorRevisions);const incompatibleMinorRevisions=value.incompatibleMinorRevisions;if(incompatibleMinorRevisions.includes(DAEMON_PROTOCOL_IDENTITY_VALUE.minor)){throw handshakeError("minor_incompatible")}assertLimits(value.limits);const limits=value.limits;for(const key of["maxFrameBytes","maxEventBytes","maxSegments"]){if(limits[key]>requestedLimits[key]){throw handshakeError("limits_invalid")}}return deepFreeze({protocol:{major:protocol.major,minor:protocol.minor},daemon:{releaseVersion:daemon.releaseVersion,platform:{os:DAEMON_PLATFORM_IDENTITY.os,cpu:DAEMON_PLATFORM_IDENTITY.cpu},journalSchemaVersion:DAEMON_JOURNAL_SCHEMA_VERSION},supportedCapabilities:[...supportedCapabilities],incompatibleMinorRevisions:[...incompatibleMinorRevisions],limits:{maxFrameBytes:limits.maxFrameBytes,maxEventBytes:limits.maxEventBytes,maxSegments:limits.maxSegments}})}function rejectDaemonHandshake(value){if(typeof value.code!=="string"||!rejectionCodes.has(value.code)||value.message!==HANDSHAKE_ERROR_MESSAGES[value.code]){throw handshakeError("invalid_handshake")}throw handshakeError(value.code)}function isClientType(value){return value==="cli"||value==="private"||value==="sdk"}function assertReleaseVersion(value){if(typeof value!=="string"||Buffer.byteLength(value,"utf8")>MAX_RELEASE_VERSION_BYTES||!isStrictSemVer(value)){throw handshakeError("invalid_handshake")}}function isStrictSemVer(value){const match=releaseVersionPattern.exec(value);if(match===null)return false;const prerelease=match[4];if(prerelease===void 0)return true;return prerelease.split(".").every(identifier=>!/^[0-9]+$/.test(identifier)||identifier==="0"||identifier[0]!=="0")}function assertCanonicalCapabilities(value){if(!Array.isArray(value)||value.length>MAX_CAPABILITIES){throw handshakeError("invalid_handshake")}for(let index=0;index<value.length;index+=1){const capability=value[index];if(typeof capability!=="string"||Buffer.byteLength(capability,"utf8")>MAX_CAPABILITY_BYTES||!capabilityPattern.test(capability)||index>0&&value[index-1]>=capability){throw handshakeError("invalid_handshake")}}}function assertCanonicalMinorRevisions(value){if(!Array.isArray(value)||value.length>MAX_INCOMPATIBLE_MINOR_REVISIONS){throw handshakeError("invalid_handshake")}for(let index=0;index<value.length;index+=1){assertBoundedInteger(value[index],0,255,"invalid_handshake");if(index>0&&value[index-1]>=value[index]){throw handshakeError("invalid_handshake")}}}function assertLimits(value){if(!isRecord(value))throw handshakeError("limits_invalid");assertBoundedInteger(value.maxFrameBytes,1,CLIENT_TRANSPORT_MAX_FRAME_BYTES,"limits_invalid");assertBoundedInteger(value.maxEventBytes,1,MAX_EVENT_BYTES,"limits_invalid");assertBoundedInteger(value.maxSegments,1,MAX_SEGMENTS,"limits_invalid");if(value.maxEventBytes>value.maxFrameBytes)throw handshakeError("limits_invalid")}function assertBoundedInteger(value,minimum,maximum,code){if(!Number.isSafeInteger(value)||value<minimum||value>maximum){throw handshakeError(code)}}function requiredRecord(value){if(!isRecord(value))throw handshakeError("invalid_handshake");return value}function isRecord(value){return typeof value==="object"&&value!==null&&!Array.isArray(value)}function isTransportError(error){return error instanceof ClientTransportError}function operationOptions(connection,deadline,signal){return{...signal===void 0?{}:{signal},timeoutMs:remainingHandshakeMs(connection,deadline,signal)}}function assertHandshakeActive(connection,deadline,signal){void remainingHandshakeMs(connection,deadline,signal)}function remainingHandshakeMs(connection,deadline,signal){if(signal?.aborted)throw new ClientTransportError("cancelled");connection.assertUsable();return deadline.remainingMs()}var HandshakeDeadline=class{#timeoutMs;#now;#startedAt;#lastObservedAt;constructor(timeoutMs,now){this.#timeoutMs=timeoutMs;this.#now=now;this.#startedAt=this.#readNow();this.#lastObservedAt=this.#startedAt}remainingMs(){const current=this.#readNow();if(current<this.#lastObservedAt)throw handshakeError("invalid_handshake");this.#lastObservedAt=current;const remaining=Math.floor(this.#timeoutMs-(current-this.#startedAt));if(remaining<=0)throw new ClientTransportError("connection_timeout");return remaining}#readNow(){const value=this.#now();if(!Number.isFinite(value))throw handshakeError("invalid_handshake");return value}};function monotonicNow(){return performance.now()}function closeAfterHandshakeFailure(connection){try{void connection.close().catch(()=>void 0)}catch{}}function handshakeError(code){return new ClientHandshakeError(code)}function deepFreeze(value){if(typeof value!=="object"||value===null||Object.isFrozen(value))return value;Object.freeze(value);for(const child of Object.values(value))deepFreeze(child);return value}function awaitWithCancellation(promise,signal){if(signal===void 0)return promise;if(signal.aborted){void promise.catch(()=>void 0);return Promise.reject(new ClientTransportError("cancelled"))}return new Promise((resolve2,reject)=>{let settled=false;const finish=callback=>{if(settled)return;settled=true;signal.removeEventListener("abort",onAbort);callback()};const onAbort=()=>finish(()=>reject(new ClientTransportError("cancelled")));signal.addEventListener("abort",onAbort,{once:true});promise.then(value=>finish(()=>resolve2(value)),error=>finish(()=>reject(error)));if(signal.aborted)onAbort()})}import{lstat as nodeLstat}from"node:fs/promises";import{dirname,isAbsolute,join,parse,relative,resolve,sep}from"node:path";var DAEMON_PARENT_DIRECTORY="pi-fleet";var DAEMON_SOCKET_NAME="control.sock";var SdkDaemonEndpointTrustError=class extends Error{constructor(code){super(code==="daemon_unavailable"?"The pi-fleet daemon is unavailable.":"The pi-fleet daemon endpoint is unsafe.");this.code=code;this.name="SdkDaemonEndpointTrustError"}};async function inspectSdkDaemonEndpoint(dependencies={}){const paths=endpointPaths(dependencies);const numericUid=dependencies.currentUid??process.getuid?.();if(!Number.isSafeInteger(numericUid)||numericUid===void 0||numericUid<0){throw unsafeEndpoint()}const uid=BigInt(numericUid);const inspect=cancellableInspector(dependencies.lstat??lstatBigInt,dependencies.signal);const first=await observeEndpoint(paths,uid,inspect,"daemon_unavailable");const second=await observeEndpoint(paths,uid,inspect,"endpoint_unsafe");if(!sameEvidence(first,second))throw unsafeEndpoint();return second}async function recheckSdkDaemonEndpoint(evidence,dependencies={}){const inspect=cancellableInspector(dependencies.lstat??lstatBigInt,dependencies.signal);const paths={socketPath:evidence.socketPath,runtimeDirectory:evidence.runtimeDirectory,parentDirectory:evidence.parentDirectory,trustedAncestors:evidence.ancestorIdentities.map(({path})=>path)};const observed=await observeEndpoint(paths,evidence.runtimeIdentity.uid,inspect,"endpoint_unsafe");if(!sameEvidence(evidence,observed))throw unsafeEndpoint()}function endpointPaths(dependencies){const env=dependencies.env??process.env;if(env.PIFLEET_SOCKET_PATH!==void 0)throw unsafeEndpoint();let socketPath;let runtimeDirectory;if(dependencies.testSocketPath!==void 0){socketPath=validateAbsolutePath(dependencies.testSocketPath);runtimeDirectory=dirname(dirname(socketPath))}else{if(dependencies.testTrustRoot!==void 0)throw unsafeEndpoint();const configuredRuntimeDirectory=env.XDG_RUNTIME_DIR;if(configuredRuntimeDirectory===void 0)throw unavailableDaemon();runtimeDirectory=validateAbsolutePath(configuredRuntimeDirectory);socketPath=join(runtimeDirectory,DAEMON_PARENT_DIRECTORY,DAEMON_SOCKET_NAME)}const parentDirectory=dirname(socketPath);const trustRoot=validateAbsolutePath(dependencies.testTrustRoot??parse(runtimeDirectory).root);if(!isWithin(runtimeDirectory,trustRoot))throw unsafeEndpoint();return{socketPath,runtimeDirectory,parentDirectory,trustedAncestors:ancestorPaths(runtimeDirectory,trustRoot)}}function ancestorPaths(runtimeDirectory,trustRoot){const child=relative(trustRoot,runtimeDirectory);if(child==="")return[];const parts=child.split(sep);parts.pop();const ancestors=[trustRoot];let current=trustRoot;for(const part of parts){current=resolve(current,part);ancestors.push(current)}return ancestors}async function observeEndpoint(paths,uid,inspect,absentCode){const ancestorIdentities=[];for(const path of paths.trustedAncestors){const stats=await requiredStats(path,inspect,"endpoint_unsafe");if(stats.isSymbolicLink()||!stats.isDirectory()||stats.uid!==0n&&stats.uid!==uid||(permissions(stats.mode)&0o022n)!==0n){throw unsafeEndpoint()}ancestorIdentities.push({path,...identity(stats,"directory")})}const runtimeIdentity=await privateIdentity(paths.runtimeDirectory,"directory",uid,0o700n,inspect,absentCode);const parentIdentity=await privateIdentity(paths.parentDirectory,"directory",uid,0o700n,inspect,absentCode);const socketIdentity=await privateIdentity(paths.socketPath,"socket",uid,0o600n,inspect,absentCode);return{socketPath:paths.socketPath,runtimeDirectory:paths.runtimeDirectory,parentDirectory:paths.parentDirectory,runtimeIdentity,parentIdentity,socketIdentity,ancestorIdentities}}async function privateIdentity(path,kind,uid,mode,inspect,absentCode){const stats=await requiredStats(path,inspect,absentCode);const expectedType=kind==="directory"?stats.isDirectory():stats.isSocket();if(stats.isSymbolicLink()||!expectedType||stats.uid!==uid||permissions(stats.mode)!==mode){throw unsafeEndpoint()}return identity(stats,kind)}async function requiredStats(path,inspect,absentCode){try{return await inspect(path)}catch(error){if(error instanceof ClientTransportError&&error.code==="cancelled")throw error;if(isMissing(error)&&absentCode==="daemon_unavailable")throw unavailableDaemon();throw unsafeEndpoint()}}function cancellableInspector(inspect,signal){if(signal===void 0)return inspect;return path=>awaitWithCancellation(inspect(path),signal)}function identity(stats,kind){const common={dev:stats.dev,ino:stats.ino,uid:stats.uid,mode:permissions(stats.mode)};return kind==="socket"?{...common,kind,ctimeNs:stats.ctimeNs}:{...common,kind}}function sameEvidence(left,right){return left.socketPath===right.socketPath&&left.runtimeDirectory===right.runtimeDirectory&&left.parentDirectory===right.parentDirectory&&sameIdentity(left.runtimeIdentity,right.runtimeIdentity)&&sameIdentity(left.parentIdentity,right.parentIdentity)&&sameIdentity(left.socketIdentity,right.socketIdentity)&&left.ancestorIdentities.length===right.ancestorIdentities.length&&left.ancestorIdentities.every((identity2,index)=>{const other=right.ancestorIdentities[index];return other!==void 0&&identity2.path===other.path&&sameIdentity(identity2,other)})}function sameIdentity(left,right){return left.dev===right.dev&&left.ino===right.ino&&left.kind===right.kind&&left.uid===right.uid&&left.mode===right.mode&&(left.kind!=="socket"||right.kind==="socket"&&left.ctimeNs===right.ctimeNs)}function permissions(mode){return mode&0o7777n}async function lstatBigInt(path){return nodeLstat(path,{bigint:true})}function isMissing(error){return typeof error==="object"&&error!==null&&"code"in error&&error.code==="ENOENT"}function validateAbsolutePath(path){if(path.length===0||!isAbsolute(path)||hasControlCharacter(path)){throw unsafeEndpoint()}return path}function hasControlCharacter(value){for(let index=0;index<value.length;index+=1){const code=value.charCodeAt(index);if(code<=31||code===127)return true}return false}function isWithin(path,root){const child=relative(root,path);return child===""||!child.startsWith("..")&&!isAbsolute(child)}function unavailableDaemon(){return new SdkDaemonEndpointTrustError("daemon_unavailable")}function unsafeEndpoint(){return new SdkDaemonEndpointTrustError("endpoint_unsafe")}var SDK_RELEASE_VERSION="0.2.0-beta.14";var SDK_REQUIRED_CAPABILITIES=DAEMON_SUPPORTED_CAPABILITY_NAMES;var SDK_REQUESTED_LIMITS=DAEMON_DEFAULT_HANDSHAKE_LIMITS;var SDK_INCOMPATIBLE_DAEMON_MINOR_REVISIONS=Object.freeze([]);function performSdkHandshake(connection,options={}){return performClientHandshake(connection,{clientType:"sdk",releaseVersion:SDK_RELEASE_VERSION,requiredCapabilities:SDK_REQUIRED_CAPABILITIES,incompatibleMinorRevisions:SDK_INCOMPATIBLE_DAEMON_MINOR_REVISIONS,requestedLimits:SDK_REQUESTED_LIMITS},options)}var SdkDaemonConnectionError=class extends Error{code="connection_failed";constructor(){super("The pi-fleet daemon connection failed.");this.name="SdkDaemonConnectionError"}};var SdkEstablishedConnectionTransportError=class extends ClientTransportError{constructor(code){super(code);this.name="SdkEstablishedConnectionTransportError"}};async function openSdkDaemonConnection(options={},dependencies={}){assertNotCancelled(options.signal);let connection;try{const endpointDependencies={...dependencies.endpoint,...options.signal===void 0?{}:{signal:options.signal}};const endpoint=await awaitWithCancellation(inspectSdkDaemonEndpoint(endpointDependencies),options.signal);assertNotCancelled(options.signal);const connect=dependencies.connect??connectJsonLine;connection=new IdempotentProbeConnection(await connect(endpoint.socketPath,{connectTimeoutMs:dependencies.connectTimeoutMs??CLIENT_TRANSPORT_CONNECT_TIMEOUT_MS,...options.signal===void 0?{}:{signal:options.signal},...dependencies.socketFactory===void 0?{}:{socketFactory:dependencies.socketFactory},...dependencies.timers===void 0?{}:{timers:dependencies.timers}}));assertNotCancelled(options.signal);await awaitWithCancellation(recheckSdkDaemonEndpoint(endpoint,{...dependencies.endpoint?.lstat===void 0?{}:{lstat:dependencies.endpoint.lstat},...options.signal===void 0?{}:{signal:options.signal}}),options.signal);assertNotCancelled(options.signal);const readiness=await performSdkHandshake(connection,{...options.signal===void 0?{}:{signal:options.signal},...dependencies.handshakeTimeoutMs===void 0?{}:{timeoutMs:dependencies.handshakeTimeoutMs},...dependencies.handshakeNow===void 0?{}:{now:dependencies.handshakeNow}});return Object.freeze({connection,readiness})}catch(error){if(connection!==void 0)closeAfterProbeFailure(connection);const normalized=normalizeProbeError(error);if(connection!==void 0&&isConnectionLoss(normalized)){throw new SdkEstablishedConnectionTransportError(normalized.code)}throw normalized}}async function probeSdkDaemonHandshake(options={},dependencies={}){const opened=await openSdkDaemonConnection(options,dependencies);try{await opened.connection.close()}catch{throw new ClientTransportError("connection_failed")}assertNotCancelled(options.signal);return opened.readiness}function connectJsonLine(path,options){return JsonLineConnection.connect(path,options)}var IdempotentProbeConnection=class{#connection;#closePromise;constructor(connection){this.#connection=connection}write(...args){return this.#connection.write(...args)}next(...args){return this.#connection.next(...args)}assertUsable(){this.#connection.assertUsable()}setFrameLimit(limit){this.#connection.setFrameLimit(limit)}close(){if(this.#closePromise!==void 0)return this.#closePromise;try{this.#closePromise=this.#connection.close()}catch(error){this.#closePromise=Promise.reject(error)}return this.#closePromise}};function assertNotCancelled(signal){if(signal?.aborted)throw new ClientTransportError("cancelled")}function closeAfterProbeFailure(connection){try{void connection.close().catch(()=>void 0)}catch{}}function isConnectionLoss(error){return error instanceof ClientTransportError&&(error.code==="connection_failed"||error.code==="connection_closed"||error.code==="connection_timeout")}function normalizeProbeError(error){if(error instanceof SdkDaemonEndpointTrustError||error instanceof ClientTransportError||error instanceof ClientHandshakeError){return error}return new SdkDaemonConnectionError}function createDeferred(){let resolve2;let reject;const promise=new Promise((resolvePromise,rejectPromise)=>{resolve2=resolvePromise;reject=rejectPromise});return{promise,resolve:resolve2,reject}}import{randomUUID}from"node:crypto";var STANDALONE_PROTOCOL_VERSION=DAEMON_PROTOCOL_IDENTITY_VALUE.major;var MAX_PROTOCOL_FRAME_BYTES=1024*1024;var SDK_DAEMON_ERROR_CODES=Object.freeze(["agent_busy","agent_destroyed","agent_destroying","agent_not_found","capacity_exceeded","cancelled","compaction_failed","compaction_uncertain","cursor_expired","cursor_invalid","cursor_wrong_agent","delivery_uncertain","destroy_incomplete","incarnation_cleanup_uncertain","internal_error","invalid_arguments","invalid_request","name_taken","nothing_to_compact","observation_uncertain","operation_conflict","operation_in_progress","pi_installation_changed","pi_not_executable","pi_not_found","pi_start_failed","pi_version_unavailable","protocol_error","protocol_incompatible","receive_resource_exhausted","runtime_interrupted","runtime_unavailable","semantic_event_too_large","stale_agent","state_corrupt","storage_unavailable","timeout"]);var SDK_PUBLIC_ERROR_CODES=Object.freeze([...SDK_DAEMON_ERROR_CODES,"client_closed","daemon_rejected","daemon_unavailable","endpoint_unsafe"]);var SDK_PUBLIC_ERROR_CURSOR_MAX_BYTES=4*1024;var daemonErrorCodes=new Set(SDK_DAEMON_ERROR_CODES);var publicErrorCodes=new Set(SDK_PUBLIC_ERROR_CODES);function isSdkDaemonErrorCode(value){return typeof value==="string"&&daemonErrorCodes.has(value)}function isSdkPublicErrorCode(value){return typeof value==="string"&&publicErrorCodes.has(value)}var SDK_PUBLIC_ERROR_MESSAGES=Object.freeze({agent_busy:"The agent is busy.",agent_destroyed:"The agent was destroyed.",agent_destroying:"The agent is being destroyed.",agent_not_found:"The agent was not found.",capacity_exceeded:"The agent process capacity is full.",cancelled:"The operation was cancelled.",compaction_failed:"The agent compaction failed.",compaction_uncertain:"The agent compaction result is uncertain.",cursor_expired:"The receive cursor has expired.",cursor_invalid:"The receive cursor is invalid.",cursor_wrong_agent:"The receive cursor belongs to a different agent.",delivery_uncertain:"The input delivery result is uncertain.",destroy_incomplete:"The agent destroy operation is incomplete.",incarnation_cleanup_uncertain:"The agent process cleanup result is uncertain.",internal_error:"The pi-fleet SDK failed.",invalid_arguments:"The operation arguments are invalid.",invalid_request:"The operation request is invalid.",name_taken:"The agent name is already in use.",nothing_to_compact:"The agent session has nothing to compact.",observation_uncertain:"The receive observation continuity is uncertain.",operation_conflict:"The operation conflicts with an existing operation.",operation_in_progress:"The operation is still in progress.",pi_installation_changed:"The Pi installation changed before startup completed.",pi_not_executable:"Pi is not executable.",pi_not_found:"The Pi command was not found.",pi_start_failed:"Pi failed to start.",pi_version_unavailable:"The Pi version is unavailable.",protocol_error:"The daemon protocol data is invalid.",protocol_incompatible:"The SDK and daemon protocols are incompatible.",receive_resource_exhausted:"The receive stream resource limit was reached.",runtime_interrupted:"The agent runtime was interrupted.",runtime_unavailable:"The pi-fleet daemon became unavailable.",semantic_event_too_large:"The receive event exceeds the supported size.",stale_agent:"The agent handle is stale.",state_corrupt:"The pi-fleet state is corrupt.",storage_unavailable:"The pi-fleet storage is unavailable.",timeout:"The operation timed out.",client_closed:"The pi-fleet client is closed.",daemon_rejected:"The pi-fleet daemon rejected the SDK connection.",daemon_unavailable:"The pi-fleet daemon is unavailable.",endpoint_unsafe:"The pi-fleet daemon endpoint is unsafe."});var SdkInvalidArgumentsError=class extends Error{constructor(){super("The SDK operation arguments are invalid.");this.name="SdkInvalidArgumentsError"}};var SdkInternalError=class extends Error{constructor(){super("The SDK operation failed.");this.name="SdkInternalError"}};var AGENT_NAME_PATTERN=/^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;var UUID_PATTERN=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;var ERROR_CODE_PATTERN=/^[a-z][a-z0-9_]{0,127}$/;var MAX_DAEMON_ERROR_MESSAGE_BYTES=4*1024;var finiteContextBrand=Symbol("SdkFiniteRequestContext");var SdkDaemonRequestError=class extends Error{constructor(code){super("The daemon rejected the agent request.");this.code=code;this.name="SdkDaemonRequestError"}};var RetryableFiniteTransportError=class extends ClientTransportError{};function createSdkFiniteRequestContext(input,dependencies={}){let method;let params;try{const request=requiredRecord2(input);assertOnlyKeys(request,["method","params"]);if(!isFiniteMethod(request.method))throw protocolError();method=request.method;params=normalizeParams(method,request.params)}catch{throw new SdkInvalidArgumentsError}try{const operation=isMutation(method)?createOperationIdentity(dependencies.randomUuid??randomUUID,dependencies.now??systemNow):void 0;return deepFreeze2({[finiteContextBrand]:true,method,params,...operation===void 0?{}:{operation}})}catch{throw new SdkInternalError}}async function performSdkFiniteRequest(input,options={},dependencies={}){const context=createSdkFiniteRequestContext(input,dependencies);for(let attempt=0;attempt<2;attempt+=1){try{return await executeSdkFiniteRequestAttempt(context,options,dependencies)}catch(error){if(!(error instanceof RetryableFiniteTransportError))throw error;if(options.signal?.aborted)throw new ClientTransportError("cancelled");if(attempt===1)throw new ClientTransportError(error.code)}}throw new ClientTransportError("connection_failed")}async function executeSdkFiniteRequestAttempt(context,options={},dependencies={}){let connection;let completeResponseObserved=false;try{assertFiniteContext(context);const requestId=createRequestId(dependencies.randomUuid??randomUUID);const open=dependencies.openConnection??openSdkDaemonConnection;const opened=await open(options);connection=opened.connection;const request=finiteWireRequest(context,requestId);await connection.write(request,options.signal===void 0?{}:{signal:options.signal});const response=await connection.next(options.signal===void 0?{}:{signal:options.signal});completeResponseObserved=true;const result=validateFiniteResponse(context,requestId,response);closeAfterFiniteAttempt(connection);return result}catch(error){if(connection!==void 0)closeAfterFiniteAttempt(connection);const retryablePhase=connection!==void 0||error instanceof SdkEstablishedConnectionTransportError;if(!completeResponseObserved&&retryablePhase&&isRetryableTransportLoss(error)){throw new RetryableFiniteTransportError(error.code)}throw normalizeFiniteError(error)}}function finiteWireRequest(context,requestId){return deepFreeze2({v:STANDALONE_PROTOCOL_VERSION,requestId,method:context.method,params:copyParamsForWire(context.method,context.params),...context.operation===void 0?{}:{operation:{...context.operation}}})}function validateFiniteResponse(context,requestId,value){const response=requiredRecord2(value);if(response.v!==STANDALONE_PROTOCOL_VERSION||response.requestId!==requestId||typeof response.ok!=="boolean"){throw protocolError()}if(response.ok){if(!("result"in response)||"error"in response)throw protocolError();return validateMethodResult(context,response.result)}if("result"in response)throw protocolError();throwDaemonFailure(response.error)}function validateMethodResult(context,value){let result;switch(context.method){case"agent.create":result=validateCreateResult(value,context.params.name);break;case"agent.send":result=validateSendResult(value,context.params.name,context.params.expectedAgentId);break;case"agent.status":result=validateStatusResult(value,context.params.name,context.params.expectedAgentId);break;case"agent.list":result=validateListResult(value);break;case"agent.compact":result=validateCompactResult(value,context.params.name,context.params.expectedAgentId);break;case"agent.destroy":result=validateDestroyResult(value,context.params.name,context.params.expectedAgentId);break}return deepFreeze2(result)}function validateCreateResult(value,name){const result=resultRecord(value,"agent.created");const agent=copyAgentSummary(result.agent);assertTarget(agent,name);return{schemaVersion:1,type:"agent.created",agent}}function validateSendResult(value,name,agentId){const result=resultRecord(value,"message.accepted");const agent=copyAgentIdentity(result.agent);assertTarget(agent,name,agentId);assertCanonicalTimestamp(result.acceptedAt);return{schemaVersion:1,type:"message.accepted",agent,acceptedAt:result.acceptedAt}}function validateStatusResult(value,name,agentId){const result=resultRecord(value,"agent.status");const agent=copyAgentSummary(result.agent);assertTarget(agent,name,agentId);return{schemaVersion:1,type:"agent.status",agent}}function validateListResult(value){const result=resultRecord(value,"agent.list");if(!Array.isArray(result.agents))throw protocolError();const agents=result.agents.map(copyAgentSummary);const ids=new Set(agents.map(({id})=>id));const names=new Set(agents.map(({name})=>name));if(ids.size!==agents.length||names.size!==agents.length)throw protocolError();return{schemaVersion:1,type:"agent.list",agents}}function validateCompactResult(value,name,agentId){const result=resultRecord(value,"agent.compacted");const agent=copyAgentIdentity(result.agent);assertTarget(agent,name,agentId);const compaction=requiredRecord2(result.compaction);assertNonnegativeInteger(compaction.tokensBefore);if(compaction.estimatedTokensAfter!==void 0){assertNonnegativeInteger(compaction.estimatedTokensAfter)}return{schemaVersion:1,type:"agent.compacted",agent,compaction:{tokensBefore:compaction.tokensBefore,...compaction.estimatedTokensAfter===void 0?{}:{estimatedTokensAfter:compaction.estimatedTokensAfter}}}}function validateDestroyResult(value,name,agentId){const result=resultRecord(value,"agent.destroyed");const agent=copyAgentIdentity(result.agent);assertTarget(agent,name,agentId);return{schemaVersion:1,type:"agent.destroyed",agent}}function resultRecord(value,type){const result=requiredRecord2(value);if(result.schemaVersion!==1||result.type!==type)throw protocolError();return result}function copyAgentSummary(value){const agent=requiredRecord2(value);const id=checkedUuid(agent.id);const name=checkedAgentName(agent.name);if(!isAgentState(agent.state))throw protocolError();const process2=requiredRecord2(agent.process);if(!isProcessState(process2.state))throw protocolError();const session=requiredRecord2(agent.session);assertNullableNonemptyString(session.path);assertNullableNonemptyString(session.id);let error;if(agent.error!==void 0){const observedError=requiredRecord2(agent.error);if(!isErrorCodeIdentifier(observedError.code))throw protocolError();error={code:observedError.code}}return{id,name,state:agent.state,process:{state:process2.state},session:{path:session.path,id:session.id},...error===void 0?{}:{error}}}function copyAgentIdentity(value){const agent=requiredRecord2(value);return{id:checkedUuid(agent.id),name:checkedAgentName(agent.name)}}function assertTarget(actual,name,expectedAgentId){if(actual.name!==name||expectedAgentId!==void 0&&actual.id!==expectedAgentId){throw protocolError()}}function throwDaemonFailure(value){const error=requiredRecord2(value);if(!isSdkDaemonErrorCode(error.code)||typeof error.message!=="string"||error.message.length===0||Buffer.byteLength(error.message,"utf8")>MAX_DAEMON_ERROR_MESSAGE_BYTES||error.details!==void 0&&!isRecord2(error.details)){throw protocolError()}throw new SdkDaemonRequestError(error.code)}function normalizeParams(method,value){const params=requiredRecord2(value);switch(method){case"agent.create":{assertOnlyKeys(params,["name","cwd","instructions","piArgv"]);const nameValue=params.name;const cwdValue=params.cwd;const instructionsValue=params.instructions;const piArgvValue=params.piArgv;const name=checkedAgentName(nameValue);const cwd=checkedNonemptyString(cwdValue);if(instructionsValue!==void 0&&typeof instructionsValue!=="string"){throw protocolError()}const piArgv=copyStringArray(piArgvValue);return deepFreeze2({name,cwd,...instructionsValue===void 0?{}:{instructions:instructionsValue},piArgv})}case"agent.send":{assertOnlyKeys(params,["name","expectedAgentId","message","delivery"]);const delivery=params.delivery;if(delivery!==void 0&&delivery!=="steer"&&delivery!=="followUp"){throw protocolError()}return deepFreeze2({name:checkedAgentName(params.name),expectedAgentId:checkedUuid(params.expectedAgentId),message:checkedNonemptyString(params.message),...delivery===void 0?{}:{delivery}})}case"agent.status":assertOnlyKeys(params,["name","expectedAgentId"]);return deepFreeze2({name:checkedAgentName(params.name),...params.expectedAgentId===void 0?{}:{expectedAgentId:checkedUuid(params.expectedAgentId)}});case"agent.compact":case"agent.destroy":assertOnlyKeys(params,["name","expectedAgentId"]);return deepFreeze2({name:checkedAgentName(params.name),expectedAgentId:checkedUuid(params.expectedAgentId)});case"agent.list":assertOnlyKeys(params,[]);return deepFreeze2({})}}function copyParamsForWire(method,params){if(method==="agent.create"){const create=params;return{name:create.name,cwd:create.cwd,...create.instructions===void 0?{}:{instructions:create.instructions},piArgv:[...create.piArgv]}}return{...params}}function createRequestId(uuid){try{return checkedUuid(uuid())}catch{throw new SdkInternalError}}function createOperationIdentity(uuid,now){const operationId=checkedUuid(uuid());const observed=now();if(!(observed instanceof Date)||!Number.isFinite(observed.getTime()))throw protocolError();const createdAt=observed.toISOString();assertCanonicalTimestamp(createdAt);return deepFreeze2({operationId,createdAt})}function isFiniteMethod(value){return value==="agent.create"||value==="agent.send"||value==="agent.status"||value==="agent.list"||value==="agent.compact"||value==="agent.destroy"}function isMutation(method){return method==="agent.create"||method==="agent.send"||method==="agent.compact"||method==="agent.destroy"}function assertFiniteContext(value){if(!isRecord2(value)||value[finiteContextBrand]!==true||!Object.isFrozen(value)){throw protocolError()}}function checkedUuid(value){if(typeof value!=="string"||!UUID_PATTERN.test(value))throw protocolError();return value}function checkedAgentName(value){if(typeof value!=="string"||!AGENT_NAME_PATTERN.test(value))throw protocolError();return value}function checkedNonemptyString(value){if(typeof value!=="string"||value.length===0)throw protocolError();return value}function copyStringArray(value){if(!Array.isArray(value))throw protocolError();const length=value.length;const copy=new Array(length);for(let index=0;index<length;index+=1){const item=value[index];if(typeof item!=="string")throw protocolError();copy[index]=item}return copy}function assertCanonicalTimestamp(value){if(typeof value!=="string"||value.length!==24||!value.endsWith("Z")||!Number.isFinite(Date.parse(value))||new Date(value).toISOString()!==value){throw protocolError()}}function assertNonnegativeInteger(value){if(!Number.isSafeInteger(value)||value<0)throw protocolError()}function assertNullableNonemptyString(value){if(value!==null&&(typeof value!=="string"||value.length===0))throw protocolError()}function isAgentState(value){return value==="restoring"||value==="working"||value==="idle"||value==="failed"||value==="destroying"}function isProcessState(value){return value==="resident"||value==="starting"||value==="absent"||value==="cleanup_uncertain"}function isErrorCodeIdentifier(value){return typeof value==="string"&&ERROR_CODE_PATTERN.test(value)}function assertOnlyKeys(value,keys){const allowed=new Set(keys);if(Object.keys(value).some(key=>!allowed.has(key)))throw protocolError()}function requiredRecord2(value){if(!isRecord2(value))throw protocolError();return value}function isRecord2(value){return typeof value==="object"&&value!==null&&!Array.isArray(value)}function protocolError(){return new ClientTransportError("protocol_error")}function normalizeFiniteError(error){if(error instanceof SdkDaemonEndpointTrustError||error instanceof SdkDaemonConnectionError||error instanceof ClientTransportError||error instanceof ClientHandshakeError||error instanceof SdkDaemonRequestError||error instanceof SdkInvalidArgumentsError||error instanceof SdkInternalError){return error}return new SdkInternalError}function isRetryableTransportLoss(error){return error instanceof ClientTransportError&&(error.code==="connection_closed"||error.code==="connection_failed"||error.code==="connection_timeout")}function closeAfterFiniteAttempt(connection){try{void connection.close().catch(()=>void 0)}catch{}}function systemNow(){return new Date}function deepFreeze2(value){if(typeof value!=="object"||value===null||Object.isFrozen(value))return value;Object.freeze(value);for(const child of Object.values(value))deepFreeze2(child);return value}import{randomUUID as randomUUID2}from"node:crypto";var AGENT_NAME_PATTERN2=/^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;var UUID_PATTERN2=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;var MAX_DAEMON_ERROR_MESSAGE_BYTES2=4*1024;var SdkReceiveStreamError=class extends Error{constructor(code,details){super("The receive stream failed.");this.code=code;this.details=details;this.name="SdkReceiveStreamError"}};async function openSdkReceiveStream(input,options={},dependencies={}){let connection;try{const normalized=normalizeSdkReceiveStreamInput(input);const requestId=createRequestId2(dependencies.randomUuid??randomUUID2);const open=dependencies.openConnection??openSdkDaemonConnection;const opened=await open(options);connection=opened.connection;await connection.write(receiveRequest(normalized,requestId),options.signal===void 0?{}:{signal:options.signal});const first=await connection.next(options.signal===void 0?{}:{signal:options.signal});const initial=parseInitialFrame(first,requestId,opened.readiness.limits);if(initial.kind==="error"){await requireTerminalClosure(connection,options.signal);throw initial.error}return new AttachedSdkReceiveStream(connection,requestId,normalized.expectedAgentId,initial.cursor,initial.limits.maxEventBytes,initial.limits.maxSegments,options.signal)}catch(error){if(connection!==void 0)closeAfterReceive(connection);throw normalizeReceiveError(error)}}function normalizeSdkReceiveStreamInput(value){try{const input=requiredRecord3(value);assertOnlyKeys2(input,["name","expectedAgentId","start"]);const name=checkedAgentName2(input.name);const expectedAgentId=checkedUuid2(input.expectedAgentId);const suppliedStart=input.start;const startValue=suppliedStart===void 0?{kind:"live"}:suppliedStart;const start=requiredRecord3(startValue);const kind=start.kind;if(kind==="live"||kind==="start"){assertOnlyKeys2(start,["kind"]);return deepFreeze3({name,expectedAgentId,start:{kind}})}if(kind==="after"){assertOnlyKeys2(start,["kind","cursor"]);const cursor=checkedOpaqueString(start.cursor);return deepFreeze3({name,expectedAgentId,start:{kind,cursor}})}throw protocolError2()}catch(error){if(error instanceof SdkInvalidArgumentsError)throw error;throw new SdkInvalidArgumentsError}}function receiveRequest(input,requestId){return deepFreeze3({v:STANDALONE_PROTOCOL_VERSION,requestId,method:"agent.receive",params:{name:input.name,expectedAgentId:input.expectedAgentId,...input.start.kind==="start"?{fromStart:true}:{},...input.start.kind==="after"?{after:input.start.cursor}:{}}})}function parseInitialFrame(value,requestId,negotiated){const frame=checkedEnvelope(value,requestId);if("ok"in frame){if(frame.ok!==false||"result"in frame||"stream"in frame||"cursor"in frame||"limits"in frame||"segment"in frame){throw protocolError2()}return{kind:"error",error:parseReceiveError(frame.error)}}if(frame.stream==="error"){assertNoKnownFields(frame,["cursor","limits","segment","ok","result"]);return{kind:"error",error:parseReceiveError(frame.error)}}if(frame.stream!=="ready")throw protocolError2();assertNoKnownFields(frame,["segment","error","ok","result"]);const cursor=checkedOpaqueString(frame.cursor);const limits=requiredRecord3(frame.limits);assertPositiveSafeInteger(limits.maxEventBytes);assertPositiveSafeInteger(limits.maxSegments);if(limits.maxEventBytes>negotiated.maxEventBytes||limits.maxSegments>negotiated.maxSegments){throw protocolError2()}return{kind:"ready",cursor,limits:{maxEventBytes:limits.maxEventBytes,maxSegments:limits.maxSegments}}}var AttachedSdkReceiveStream=class{constructor(connection,requestId,expectedAgentId,cursor,maxEventBytes,maxSegments,signal){this.connection=connection;this.requestId=requestId;this.expectedAgentId=expectedAgentId;this.maxEventBytes=maxEventBytes;this.maxSegments=maxSegments;this.signal=signal;this.cursor=cursor;Object.freeze(this)}cursor;#iterated=false;[Symbol.asyncIterator](){if(this.#iterated)throw new SdkReceiveStreamError("invalid_request");this.#iterated=true;return new SdkReceiveIterator(this.connection,this.requestId,this.expectedAgentId,this.cursor,this.maxEventBytes,this.maxSegments,this.signal)}};var SdkReceiveIterator=class{constructor(connection,requestId,expectedAgentId,cursor,maxEventBytes,maxSegments,signal){this.connection=connection;this.requestId=requestId;this.signal=signal;this.#cursor=cursor;this.#assembler=new StrictSemanticEventAssembler(expectedAgentId,maxEventBytes,maxSegments)}#assembler;#cursor;#done=false;#returned=false;#tail=Promise.resolve();next(){const operation=this.#tail.then(()=>this.#next());this.#tail=operation.then(()=>void 0,()=>void 0);return operation}return(){this.#returned=true;this.#done=true;closeAfterReceive(this.connection);return Promise.resolve({done:true,value:void 0})}async#next(){if(this.#done)return{done:true,value:void 0};try{while(true){const value=await this.connection.next(this.signal===void 0?{}:{signal:this.signal});const frame=checkedEnvelope(value,this.requestId);if("ok"in frame||frame.stream==="ready")throw protocolError2();if(frame.stream==="semantic.segment"){assertNoKnownFields(frame,["cursor","limits","error","ok","result"]);const complete=this.#assembler.push(frame.segment,this.#cursor);if(complete!==null){this.#cursor=complete.cursor;return{done:false,value:complete}}continue}if(frame.stream==="end"){assertNoKnownFields(frame,["cursor","limits","segment","error","ok","result"]);if(this.#assembler.pending)throw protocolError2();await requireTerminalClosure(this.connection,this.signal);this.#finish();return{done:true,value:void 0}}if(frame.stream==="error"){assertNoKnownFields(frame,["cursor","limits","segment","ok","result"]);if(this.#assembler.pending)throw protocolError2();const error=parseReceiveError(frame.error,this.#cursor);await requireTerminalClosure(this.connection,this.signal);this.#finish();throw error}throw protocolError2()}}catch(error){if(this.#returned)return{done:true,value:void 0};this.#finish();if(error instanceof ClientTransportError){if(error.code==="cancelled"||error.code==="protocol_error")throw error;if(this.#assembler.pending)throw protocolError2();if(isConnectionLoss2(error.code)){throw new SdkReceiveStreamError("runtime_unavailable",deepFreeze3({lastSafeCursor:this.#cursor}))}}throw normalizeReceiveError(error)}}#finish(){if(this.#done)return;this.#done=true;closeAfterReceive(this.connection)}};var StrictSemanticEventAssembler=class{constructor(expectedAgentId,maxEventBytes,maxSegments){this.expectedAgentId=expectedAgentId;this.maxEventBytes=maxEventBytes;this.maxSegments=maxSegments}#current;get pending(){return this.#current!==void 0}push(value,expectedCursor){const frame=requiredRecord3(value);if(frame.type!=="semantic.segment")throw protocolError2();const eventId=checkedOpaqueString(frame.eventId);const precedingCursor=checkedOpaqueString(frame.precedingCursor);const eventCursor=checkedOpaqueString(frame.eventCursor);assertNonnegativeSafeInteger(frame.index);assertPositiveSafeInteger(frame.count);if(frame.index>=frame.count||frame.count>this.maxSegments)throw protocolError2();if(typeof frame.data!=="string"||frame.data.length===0)throw protocolError2();if(frame.index===0){if(this.#current!==void 0||precedingCursor!==expectedCursor)throw protocolError2();if(eventCursor===precedingCursor)throw protocolError2();this.#current={eventId,precedingCursor,eventCursor,count:frame.count,chunks:[],bytes:0}}const current=this.#current;if(current===void 0||current.eventId!==eventId||current.precedingCursor!==precedingCursor||current.eventCursor!==eventCursor||current.count!==frame.count||frame.index!==current.chunks.length){throw protocolError2()}const chunk=decodeCanonicalBase64(frame.data);if(current.bytes+chunk.byteLength>this.maxEventBytes)throw protocolError2();current.chunks.push(chunk);current.bytes+=chunk.byteLength;if(current.chunks.length<current.count)return null;const bytes=Buffer.concat(current.chunks,current.bytes);this.#current=void 0;let text;try{text=new TextDecoder("utf-8",{fatal:true}).decode(bytes)}catch{throw protocolError2()}let decoded;try{decoded=JSON.parse(text)}catch{throw protocolError2()}const event=copySemanticEvent(decoded,this.expectedAgentId);if(event.id!==eventId||event.cursor!==eventCursor)throw protocolError2();return event}};function copySemanticEvent(value,expectedAgentId){const event=requiredRecord3(value);const id=checkedOpaqueString(event.id);const activityId=checkedOpaqueString(event.activityId);const agentId=checkedUuid2(event.agentId);if(agentId!==expectedAgentId)throw protocolError2();const cursor=checkedOpaqueString(event.cursor);assertNonnegativeSafeInteger(event.epoch);assertPositiveSafeInteger(event.sourceRawPosition);assertCanonicalTimestamp2(event.observedAt);const base={id,activityId,agentId,cursor,epoch:event.epoch,sourceRawPosition:event.sourceRawPosition,observedAt:event.observedAt};let copied;switch(event.type){case"assistant.thinking.started":case"assistant.message.started":if("text"in event||"tool"in event)throw protocolError2();copied={...base,type:event.type};break;case"assistant.thinking.finished":case"assistant.message.finished":if("tool"in event||!isMeaningfulString(event.text))throw protocolError2();copied={...base,type:event.type,text:event.text};break;case"tool.execution.started":{if("text"in event)throw protocolError2();const tool=requiredRecord3(event.tool);if(!("input"in tool)||"output"in tool||"isError"in tool)throw protocolError2();copied={...base,type:event.type,tool:{callId:checkedNonemptyString2(tool.callId),name:checkedNonemptyString2(tool.name),input:tool.input}};break}case"tool.execution.finished":{if("text"in event)throw protocolError2();const tool=requiredRecord3(event.tool);if(!("input"in tool)||!("output"in tool)||typeof tool.isError!=="boolean"){throw protocolError2()}copied={...base,type:event.type,tool:{callId:checkedNonemptyString2(tool.callId),name:checkedNonemptyString2(tool.name),input:tool.input,output:tool.output,isError:tool.isError}};break}default:throw protocolError2()}return deepFreeze3(copied)}function checkedEnvelope(value,requestId){const frame=requiredRecord3(value);if(frame.v!==STANDALONE_PROTOCOL_VERSION||frame.requestId!==requestId){throw protocolError2()}if(!("ok"in frame)&&typeof frame.stream!=="string")throw protocolError2();return frame}function parseReceiveError(value,expectedCursor){const error=requiredRecord3(value);if(!isSdkDaemonErrorCode(error.code)||typeof error.message!=="string"||error.message.length===0||Buffer.byteLength(error.message,"utf8")>MAX_DAEMON_ERROR_MESSAGE_BYTES2||error.details!==void 0&&!isRecord3(error.details)){throw protocolError2()}const details=error.details===void 0?void 0:requiredRecord3(error.details);let lastSafeCursor;if(details!==void 0&&details.lastSafeCursor!==void 0){lastSafeCursor=checkedOpaqueString(details.lastSafeCursor);if(expectedCursor!==void 0&&lastSafeCursor!==expectedCursor)throw protocolError2()}let continuationCursor;if(error.code==="observation_uncertain"){if(details===void 0||lastSafeCursor===void 0||!("continuationCursor"in details)){throw protocolError2()}if(details.continuationCursor!==null){continuationCursor=checkedOpaqueString(details.continuationCursor)}}else if(details!==void 0&&"continuationCursor"in details){throw protocolError2()}const retained=lastSafeCursor===void 0&&continuationCursor===void 0?void 0:deepFreeze3({...lastSafeCursor===void 0?{}:{lastSafeCursor},...continuationCursor===void 0?{}:{continuationCursor}});return new SdkReceiveStreamError(error.code,retained)}async function requireTerminalClosure(connection,signal){try{await connection.next(signal===void 0?{}:{signal});throw protocolError2()}catch(error){if(error instanceof ClientTransportError&&(error.code==="connection_closed"||error.code==="connection_failed")){return}throw error}}function decodeCanonicalBase64(value){const bytes=Buffer.from(value,"base64");if(bytes.byteLength===0||bytes.toString("base64")!==value)throw protocolError2();return bytes}function normalizeReceiveError(error){if(error instanceof SdkDaemonEndpointTrustError||error instanceof SdkDaemonConnectionError||error instanceof ClientTransportError||error instanceof ClientHandshakeError||error instanceof SdkReceiveStreamError||error instanceof SdkInvalidArgumentsError||error instanceof SdkInternalError){return error}return new SdkInternalError}function closeAfterReceive(connection){try{void connection.close().catch(()=>void 0)}catch{}}function isConnectionLoss2(code){return code==="connection_closed"||code==="connection_failed"||code==="connection_timeout"}function createRequestId2(uuid){try{return checkedUuid2(uuid())}catch{throw new SdkInternalError}}function checkedAgentName2(value){if(typeof value!=="string"||!AGENT_NAME_PATTERN2.test(value))throw protocolError2();return value}function checkedUuid2(value){if(typeof value!=="string"||!UUID_PATTERN2.test(value))throw protocolError2();return value}function checkedOpaqueString(value){if(typeof value!=="string"||value.length===0)throw protocolError2();return value}function checkedNonemptyString2(value){if(typeof value!=="string"||value.length===0)throw protocolError2();return value}function isMeaningfulString(value){return typeof value==="string"&&/\S/u.test(value)}function assertCanonicalTimestamp2(value){if(typeof value!=="string"||value.length!==24||!value.endsWith("Z")||!Number.isFinite(Date.parse(value))||new Date(value).toISOString()!==value){throw protocolError2()}}function assertNonnegativeSafeInteger(value){if(!Number.isSafeInteger(value)||value<0)throw protocolError2()}function assertPositiveSafeInteger(value){if(!Number.isSafeInteger(value)||value<=0)throw protocolError2()}function assertOnlyKeys2(value,keys){const allowed=new Set(keys);if(Object.keys(value).some(key=>!allowed.has(key)))throw protocolError2()}function assertNoKnownFields(value,keys){if(keys.some(key=>key in value))throw protocolError2()}function requiredRecord3(value){if(!isRecord3(value))throw protocolError2();return value}function isRecord3(value){return typeof value==="object"&&value!==null&&!Array.isArray(value)}function protocolError2(){return new ClientTransportError("protocol_error")}function deepFreeze3(value){if(typeof value!=="object"||value===null)return value;const pending=[value];const seen=new Set;while(pending.length>0){const current=pending.pop();if(seen.has(current))continue;seen.add(current);Object.freeze(current);for(const child of Object.values(current)){if(typeof child==="object"&&child!==null)pending.push(child)}}return value}var RECONNECT_DELAYS_MS=Object.freeze([100,250,500,1e3]);async function openReconnectingSdkReceiveStream(input,options={},dependencies={}){const controller=new AbortController;const signal=options.signal===void 0?controller.signal:AbortSignal.any([options.signal,controller.signal]);const attemptOptions=Object.freeze({signal});const openStream=dependencies.openStream??openSdkReceiveStream;const normalizedInput=normalizeSdkReceiveStreamInput(input);const target=Object.freeze({name:normalizedInput.name,expectedAgentId:normalizedInput.expectedAgentId});const initial=await openStream(normalizedInput,attemptOptions);if(signal.aborted){closePhysicalStream(initial);throw new ClientTransportError("cancelled")}return new ReconnectingSdkReceiveStream(initial,target,attemptOptions,openStream,dependencies.delay??abortableReconnectDelay,controller)}var ReconnectingSdkReceiveStream=class{constructor(initial,target,options,openStream,delay,controller){this.initial=initial;this.target=target;this.options=options;this.openStream=openStream;this.delay=delay;this.controller=controller;this.cursor=initial.cursor;Object.freeze(this)}cursor;#iterated=false;[Symbol.asyncIterator](){if(this.#iterated)throw new SdkReceiveStreamError("invalid_request");this.#iterated=true;return new ReconnectingSdkReceiveIterator(this.initial,this.target,this.options,this.openStream,this.delay,this.controller)}};var ReconnectingSdkReceiveIterator=class{constructor(initial,target,options,openStream,delay,controller){this.target=target;this.options=options;this.openStream=openStream;this.delay=delay;this.controller=controller;this.#cursor=initial.cursor;this.#current=initial[Symbol.asyncIterator]()}#current;#cursor;#done=false;#returned=false;#tail=Promise.resolve();next(){const operation=this.#tail.then(()=>this.#next());this.#tail=operation.then(()=>void 0,()=>void 0);return operation}return(){this.#returned=true;this.#done=true;this.controller.abort();closePhysicalIterator(this.#current);this.#current=void 0;return Promise.resolve({done:true,value:void 0})}async#next(){if(this.#done)return{done:true,value:void 0};try{while(true){const current=this.#current;if(current===void 0)throw protocolError3();let result;try{result=await current.next()}catch(error){closePhysicalIterator(current);this.#current=void 0;if(!isAttachedRuntimeLoss(error,this.#cursor))throw error;const replacement=await this.#recover();if(replacement===null)return{done:true,value:void 0};this.#current=replacement[Symbol.asyncIterator]();continue}if(result.done){this.#finish();return{done:true,value:void 0}}this.#cursor=result.value.cursor;return{done:false,value:result.value}}}catch(error){if(this.#returned)return{done:true,value:void 0};this.#finish();throw error}}async#recover(){let delayIndex=0;while(true){await this.delay(RECONNECT_DELAYS_MS[Math.min(delayIndex,RECONNECT_DELAYS_MS.length-1)],this.options.signal);if(this.#returned)return null;assertNotCancelled2(this.options.signal);delayIndex+=1;let replacement;try{replacement=await this.openStream({name:this.target.name,expectedAgentId:this.target.expectedAgentId,start:{kind:"after",cursor:this.#cursor}},this.options)}catch(error){if(this.#returned)return null;if(isRecoverableReattachmentFailure(error,this.#cursor))continue;throw error}if(this.#returned){closePhysicalStream(replacement);return null}if(this.options.signal.aborted){closePhysicalStream(replacement);throw new ClientTransportError("cancelled")}if(replacement.cursor!==this.#cursor){closePhysicalStream(replacement);throw protocolError3()}return replacement}}#finish(){if(this.#done)return;this.#done=true;this.controller.abort();closePhysicalIterator(this.#current);this.#current=void 0}};function isAttachedRuntimeLoss(error,cursor){if(!(error instanceof SdkReceiveStreamError))return false;assertRecoveryCursorDetails(error,cursor);return error.code==="runtime_unavailable"}function isRecoverableReattachmentFailure(error,cursor){if(error instanceof SdkReceiveStreamError){assertRecoveryCursorDetails(error,cursor);return error.code==="runtime_unavailable"}if(error instanceof SdkDaemonEndpointTrustError){return error.code==="daemon_unavailable"}return error instanceof ClientTransportError&&(error.code==="connection_closed"||error.code==="connection_failed"||error.code==="connection_timeout")}function assertRecoveryCursorDetails(error,cursor){if(error.details?.continuationCursor!==void 0&&error.code!=="observation_uncertain"||error.details?.lastSafeCursor!==void 0&&error.details.lastSafeCursor!==cursor){throw protocolError3()}}function closePhysicalStream(stream){let iterator;try{iterator=stream[Symbol.asyncIterator]()}catch{return}closePhysicalIterator(iterator)}function closePhysicalIterator(iterator){if(iterator===void 0)return;try{void iterator.return?.().catch(()=>void 0)}catch{}}function abortableReconnectDelay(milliseconds,signal){if(signal.aborted)return Promise.reject(new ClientTransportError("cancelled"));return new Promise((resolve2,reject)=>{let settled=false;const finish=callback=>{if(settled)return;settled=true;clearTimeout(timer);signal.removeEventListener("abort",onAbort);callback()};const onAbort=()=>finish(()=>reject(new ClientTransportError("cancelled")));const timer=setTimeout(()=>finish(resolve2),milliseconds);signal.addEventListener("abort",onAbort,{once:true});if(signal.aborted)onAbort()})}function assertNotCancelled2(signal){if(signal.aborted)throw new ClientTransportError("cancelled")}function protocolError3(){return new ClientTransportError("protocol_error")}function createProtocolSdkTransport(dependencies={}){return new ProtocolSdkTransport(dependencies)}var ProtocolSdkTransport=class{#finiteRequest;#openReceive;#closeController=new AbortController;#activeOperations=new Set;#closed=false;#closePromise;constructor(dependencies){this.#finiteRequest=dependencies.finiteRequest??performSdkFiniteRequest;this.#openReceive=dependencies.openReceive??openReconnectingSdkReceiveStream}async create(input,signal){const name=input.name;const cwd=input.cwd;const piArgs=input.piArgs;const instructions=input.instructions;const result=await this.run(signal,operationSignal=>this.#finiteRequest({method:"agent.create",params:{name,cwd,piArgv:piArgs??[],...instructions===void 0?{}:{instructions}}},{signal:operationSignal}));return result.agent}async get(name,signal){try{const result=await this.run(signal,operationSignal=>this.#finiteRequest({method:"agent.status",params:{name}},{signal:operationSignal}));return result.agent}catch(error){if(error instanceof SdkDaemonRequestError&&error.code==="agent_not_found")return null;throw error}}async list(signal){const result=await this.run(signal,operationSignal=>this.#finiteRequest({method:"agent.list",params:{}},{signal:operationSignal}));return result.agents}async status(target,signal){const result=await this.run(signal,operationSignal=>this.#finiteRequest({method:"agent.status",params:{name:target.name,expectedAgentId:target.expectedAgentId}},{signal:operationSignal}));return result.agent}async send(target,message,delivery,signal){const result=await this.run(signal,operationSignal=>this.#finiteRequest({method:"agent.send",params:{name:target.name,expectedAgentId:target.expectedAgentId,message,delivery}},{signal:operationSignal}));return{acceptedAt:result.acceptedAt}}receive(target,start,signal){return this.run(signal,async operationSignal=>{const stream=await this.#openReceive({name:target.name,expectedAgentId:target.expectedAgentId,start},{signal:operationSignal});return new TrackedReceiveStream(stream,operationSignal,operation=>this.track(operation))})}async compact(target,signal){const result=await this.run(signal,operationSignal=>this.#finiteRequest({method:"agent.compact",params:{name:target.name,expectedAgentId:target.expectedAgentId}},{signal:operationSignal}));return result.compaction}async destroy(target,signal){await this.run(signal,operationSignal=>this.#finiteRequest({method:"agent.destroy",params:{name:target.name,expectedAgentId:target.expectedAgentId}},{signal:operationSignal}))}close(){if(this.#closePromise!==void 0)return this.#closePromise;const deferred=createDeferred();this.#closePromise=deferred.promise;this.#closed=true;this.#closeController.abort();void this.waitForActiveOperations().then(deferred.resolve,deferred.reject);return this.#closePromise}run(signal,operation){if(this.#closed)return Promise.reject(new SdkDaemonRequestError("runtime_unavailable"));const operationSignal=AbortSignal.any([signal,this.#closeController.signal]);let pending;try{pending=Promise.resolve(operation(operationSignal))}catch(error){pending=Promise.reject(error)}return this.track(pending)}track(operation){this.#activeOperations.add(operation);void operation.then(()=>this.#activeOperations.delete(operation),()=>this.#activeOperations.delete(operation));return operation}async waitForActiveOperations(){while(this.#activeOperations.size>0){await Promise.allSettled([...this.#activeOperations])}}};var TrackedReceiveStream=class{cursor;#stream;#signal;#track;constructor(stream,signal,track){this.cursor=stream.cursor;this.#stream=stream;this.#signal=signal;this.#track=track;Object.freeze(this)}[Symbol.asyncIterator](){if(this.#signal.aborted)throw new ClientTransportError("cancelled");return new TrackedReceiveIterator(this.#stream[Symbol.asyncIterator](),this.#signal,this.#track)}};var TrackedReceiveIterator=class{#iterator;#signal;#track;constructor(iterator,signal,track){this.#iterator=iterator;this.#signal=signal;this.#track=track;Object.freeze(this)}next(){if(this.#signal.aborted)return Promise.reject(new ClientTransportError("cancelled"));return this.trackCall(()=>this.#iterator.next())}return(value){return this.trackCall(async()=>this.#iterator.return===void 0?{done:true,value:void 0}:this.#iterator.return(value))}throw(error){return this.trackCall(async()=>{if(this.#iterator.throw===void 0){await this.#iterator.return?.();throw error}return this.#iterator.throw(error)})}trackCall(operation){let pending;try{pending=Promise.resolve(operation()).then(result=>{if(this.#signal.aborted)throw new ClientTransportError("cancelled");return result})}catch(error){pending=Promise.reject(error)}return this.#track(pending)}};var TRANSPORT_PUBLIC_CODES=Object.freeze({cancelled:"cancelled",connection_closed:"runtime_unavailable",connection_failed:"runtime_unavailable",connection_timeout:"timeout",protocol_error:"protocol_error"});var HANDSHAKE_PUBLIC_CODES=Object.freeze({invalid_handshake:"protocol_error",invalid_hello:"daemon_rejected",protocol_incompatible:"protocol_incompatible",minor_incompatible:"protocol_incompatible",capability_unsupported:"protocol_incompatible",limits_invalid:"protocol_incompatible"});var PiFleetError=class extends Error{code;details;constructor(code,details){const codeAccepted=isSdkPublicErrorCode(code);const acceptedCode=codeAccepted?code:"internal_error";const projection=codeAccepted?projectDetails(acceptedCode,details):{valid:true};const safeCode=projection.valid?acceptedCode:"protocol_error";super(SDK_PUBLIC_ERROR_MESSAGES[safeCode]);this.name="PiFleetError";this.code=safeCode;this.details=projection.valid?projection.details:void 0;this.stack=`${this.name}: ${this.message}`;Object.freeze(this)}};function toPiFleetError(error,clientCloseCausedFailure=false){try{if(clientCloseCausedFailure&&error instanceof ClientTransportError&&error.code==="cancelled"){return new PiFleetError("client_closed")}return projectError(error)}catch{return new PiFleetError("internal_error")}}function projectError(error){if(error instanceof PiFleetError){return new PiFleetError(error.code,error.details)}if(error instanceof SdkDaemonEndpointTrustError){return new PiFleetError(error.code)}if(error instanceof SdkDaemonConnectionError){return new PiFleetError("runtime_unavailable")}if(error instanceof SdkInvalidArgumentsError){return new PiFleetError("invalid_arguments")}if(error instanceof SdkInternalError){return new PiFleetError("internal_error")}if(error instanceof ClientTransportError){return new PiFleetError(TRANSPORT_PUBLIC_CODES[error.code])}if(error instanceof ClientHandshakeError){return new PiFleetError(HANDSHAKE_PUBLIC_CODES[error.code])}if(error instanceof SdkDaemonRequestError){return isSdkPublicErrorCode(error.code)?new PiFleetError(error.code):new PiFleetError("protocol_error")}if(error instanceof SdkReceiveStreamError){if(!isSdkPublicErrorCode(error.code))return new PiFleetError("protocol_error");return new PiFleetError(error.code,error.details)}return new PiFleetError("internal_error")}function projectDetails(code,value){if(value===void 0){return code==="observation_uncertain"?{valid:false}:{valid:true}}if(!isRecord4(value))return{valid:false};try{const lastSafeValue=value.lastSafeCursor;const continuationValue=value.continuationCursor;const lastSafeCursor=lastSafeValue===void 0?void 0:checkedCursor(lastSafeValue);const continuationCursor=continuationValue===void 0?void 0:checkedCursor(continuationValue);if(code==="observation_uncertain"){if(lastSafeCursor===void 0)return{valid:false}}else if(continuationValue!==void 0){return{valid:false}}if(lastSafeCursor===void 0&&continuationCursor===void 0){return{valid:true}}return{valid:true,details:Object.freeze({...lastSafeCursor===void 0?{}:{lastSafeCursor},...continuationCursor===void 0?{}:{continuationCursor}})}}catch{return{valid:false}}}function checkedCursor(value){if(typeof value!=="string"||value.length===0||Buffer.byteLength(value,"utf8")>SDK_PUBLIC_ERROR_CURSOR_MAX_BYTES){throw new Error("invalid cursor")}return value}function isRecord4(value){return typeof value==="object"&&value!==null&&!Array.isArray(value)}function createSdkConnector(dependencies={}){const probe=dependencies.probe??probeSdkDaemonHandshake;const createTransport=dependencies.createTransport??createProtocolSdkTransport;return{async connect(value){let options;try{options=captureConnectOptions(value)}catch(error){throw toPiFleetError(error)}try{throwIfConnectionAborted(options.signal);await probe(options);throwIfConnectionAborted(options.signal);return createTransport()}catch(error){throw toPiFleetError(error)}}}}function captureConnectOptions(value){try{if(typeof value!=="object"||value===null||Array.isArray(value)){throw new SdkInvalidArgumentsError}const options=value;if(Object.keys(options).some(key=>key!=="signal")){throw new SdkInvalidArgumentsError}const signal=options.signal;if(signal!==void 0&&!(signal instanceof AbortSignal)){throw new SdkInvalidArgumentsError}return Object.freeze(signal===void 0?{}:{signal})}catch(error){if(error instanceof SdkInvalidArgumentsError)throw error;throw new SdkInvalidArgumentsError}}function throwIfConnectionAborted(signal){if(signal?.aborted)throw cancelledConnection()}function cancelledConnection(){return new PiFleetError("cancelled")}var CLIENT_CLOSE_ABORT_REASON=Symbol("pi-fleet-sdk-client-close");function createConnectPiFleet(connector){return async(options={})=>createPiFleetClient(await connector.connect(options))}function createPiFleetClient(transport){return new PiFleetClientImpl(transport)}var PiFleetClientImpl=class{#closed=false;#closedController=new AbortController;#closePromise;#transport;constructor(transport){this.#transport=transport;Object.freeze(this)}async create(input,options={}){return this.agent(await this.callAgent(options,signal=>this.#transport.create(input,signal)))}async get(name,options={}){const summary=await this.callAgent(options,signal=>this.#transport.get(name,signal));if(summary===null){throw new PiFleetError("agent_not_found")}return this.agent(summary)}async list(options={}){return this.callAgent(options,signal=>this.#transport.list(signal))}close(){if(this.#closePromise!==void 0)return this.#closePromise;const deferred=createDeferred();this.#closePromise=deferred.promise;this.#closed=true;this.#closedController.abort(CLIENT_CLOSE_ABORT_REASON);void this.closeTransport().then(deferred.resolve,deferred.reject);return this.#closePromise}async closeTransport(){try{await this.#transport.close()}catch(error){throw toPiFleetError(error)}}agent(summary){return new AgentImpl(this,this.#transport,summary)}async callAgent(options,operation){this.assertOpen();let operationSignal;try{operationSignal=this.operationSignal(options);return await operation(operationSignal)}catch(error){throw this.publicError(error,operationSignal)}}publicError(error,operationSignal){return toPiFleetError(error,operationSignal?.aborted===true&&operationSignal.reason===CLIENT_CLOSE_ABORT_REASON)}operationSignal(value){if(typeof value!=="object"||value===null||Array.isArray(value)){throw new SdkInvalidArgumentsError}let signal;try{signal=value.signal}catch{throw new SdkInvalidArgumentsError}if(signal!==void 0&&!(signal instanceof AbortSignal)){throw new SdkInvalidArgumentsError}return signal===void 0?this.#closedController.signal:AbortSignal.any([signal,this.#closedController.signal])}assertOpen(){if(this.#closed)throw new PiFleetError("client_closed")}};var AgentImpl=class{#client;#transport;#id;#name;constructor(client,transport,initialSummary){this.#client=client;this.#transport=transport;this.#id=initialSummary.id;this.#name=initialSummary.name;Object.freeze(this)}get id(){return this.#id}get name(){return this.#name}status(options={}){return this.#client.callAgent(options,signal=>this.#transport.status(this.target(),signal))}send(message,options={}){return this.#client.callAgent(options,signal=>this.#transport.send(this.target(),message,options.delivery??"steer",signal))}receive(options={}){return this.#client.callAgent(options,async signal=>{const stream=await this.#transport.receive(this.target(),receiveStart(options),signal);return new PublicReceiveStream(stream,error=>this.#client.publicError(error,signal))})}compact(options={}){return this.#client.callAgent(options,signal=>this.#transport.compact(this.target(),signal))}destroy(options={}){return this.#client.callAgent(options,signal=>this.#transport.destroy(this.target(),signal))}target(){return{name:this.#name,expectedAgentId:this.#id}}};function receiveStart(value){try{if(typeof value!=="object"||value===null||Array.isArray(value)){throw new SdkInvalidArgumentsError}const options=value;const allowed=new Set(["after","fromStart","signal"]);if(Object.keys(options).some(key=>!allowed.has(key))){throw new SdkInvalidArgumentsError}const afterValue=options.after;const fromStartValue=options.fromStart;const hasAfter=afterValue!==void 0;const hasFromStart=fromStartValue!==void 0;if(hasAfter){if(hasFromStart||typeof afterValue!=="string"||afterValue.length===0){throw new SdkInvalidArgumentsError}return{kind:"after",cursor:afterValue}}if(hasFromStart&&fromStartValue!==true&&fromStartValue!==false){throw new SdkInvalidArgumentsError}return fromStartValue===true?{kind:"start"}:{kind:"live"}}catch(error){if(error instanceof SdkInvalidArgumentsError)throw error;throw new SdkInvalidArgumentsError}}var PublicReceiveStream=class{cursor;#stream;#projectError;constructor(stream,projectError2){this.cursor=stream.cursor;this.#stream=stream;this.#projectError=projectError2;Object.freeze(this)}[Symbol.asyncIterator](){let iterator;try{iterator=this.#stream[Symbol.asyncIterator]()}catch(error){throw this.#projectError(error)}return new PublicReceiveIterator(iterator,this.#projectError)}};var PublicReceiveIterator=class{#iterator;#projectError;constructor(iterator,projectError2){this.#iterator=iterator;this.#projectError=projectError2;Object.freeze(this)}async next(){try{return await this.#iterator.next()}catch(error){throw this.#projectError(error)}}async return(value){try{return await this.#iterator.return?.(value)??{done:true,value:void 0}}catch(error){throw this.#projectError(error)}}async throw(error){try{if(this.#iterator.throw===void 0){await this.#iterator.return?.();throw error}return await this.#iterator.throw(error)}catch(failure){throw this.#projectError(failure)}}};var connectPiFleet=createConnectPiFleet(createSdkConnector());export{PiFleetError,connectPiFleet};
package/package.json CHANGED
@@ -1,17 +1,50 @@
1
1
  {
2
2
  "name": "@elpapi42/pi-fleet-sdk",
3
- "version": "0.2.0-beta.0",
4
- "description": "Reserved bootstrap version for the official pi-fleet SDK package",
3
+ "version": "0.2.0-beta.14",
4
+ "description": "Client-only TypeScript SDK for an installed pi-fleet daemon",
5
5
  "license": "MIT",
6
- "private": false,
6
+ "type": "module",
7
+ "sideEffects": false,
8
+ "engines": {
9
+ "node": "^22.19.0 || ^24.0.0"
10
+ },
11
+ "scripts": {
12
+ "build": "node ../../scripts/build-sdk.mjs",
13
+ "build:declarations": "node ../../scripts/build-sdk-declarations.mjs",
14
+ "check:boundary": "node ../../scripts/check-sdk-build.mjs",
15
+ "prepack": "npm run build && npm run check:boundary",
16
+ "pack:artifact": "npm pack"
17
+ },
18
+ "exports": {
19
+ ".": {
20
+ "types": "./dist/index.d.ts",
21
+ "import": "./dist/index.js"
22
+ }
23
+ },
24
+ "types": "./dist/index.d.ts",
25
+ "files": [
26
+ "dist/",
27
+ "README.md",
28
+ "LICENSE"
29
+ ],
30
+ "publishConfig": {
31
+ "access": "public",
32
+ "tag": "beta"
33
+ },
34
+ "keywords": [
35
+ "pi",
36
+ "agents",
37
+ "sdk",
38
+ "automation",
39
+ "orchestration"
40
+ ],
7
41
  "repository": {
8
42
  "type": "git",
9
43
  "url": "git+https://github.com/elpapi42/pi-fleet.git",
10
44
  "directory": "packages/sdk"
11
45
  },
12
- "publishConfig": {
13
- "access": "public",
14
- "tag": "bootstrap"
15
- },
16
- "files": ["README.md", "LICENSE"]
46
+ "homepage": "https://github.com/elpapi42/pi-fleet#readme",
47
+ "bugs": {
48
+ "url": "https://github.com/elpapi42/pi-fleet/issues"
49
+ }
17
50
  }