@linxiraos/pi-utils 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (244) hide show
  1. package/CHANGELOG.md +449 -0
  2. package/README.md +36 -0
  3. package/dist/types/abortable.d.ts +32 -0
  4. package/dist/types/acp/connection.d.ts +118 -0
  5. package/dist/types/acp/protocol.d.ts +526 -0
  6. package/dist/types/acp/schema.d.ts +41 -0
  7. package/dist/types/acp/stream.d.ts +8 -0
  8. package/dist/types/acp/transport.d.ts +81 -0
  9. package/dist/types/acp.d.ts +6 -0
  10. package/dist/types/async.d.ts +20 -0
  11. package/dist/types/binary.d.ts +17 -0
  12. package/dist/types/browsers.d.ts +68 -0
  13. package/dist/types/chalk.d.ts +125 -0
  14. package/dist/types/cli.d.ts +134 -0
  15. package/dist/types/color.d.ts +102 -0
  16. package/dist/types/dates.d.ts +7 -0
  17. package/dist/types/dirs.d.ts +282 -0
  18. package/dist/types/docx/converter.d.ts +46 -0
  19. package/dist/types/docx/xml.d.ts +26 -0
  20. package/dist/types/docx/zip.d.ts +6 -0
  21. package/dist/types/docx.d.ts +11 -0
  22. package/dist/types/dom/core.d.ts +431 -0
  23. package/dist/types/dom/parser.d.ts +7 -0
  24. package/dist/types/dom/selector.d.ts +5 -0
  25. package/dist/types/dom.d.ts +5 -0
  26. package/dist/types/env.d.ts +124 -0
  27. package/dist/types/fetch-retry.d.ts +96 -0
  28. package/dist/types/file-lock.d.ts +23 -0
  29. package/dist/types/format.d.ts +37 -0
  30. package/dist/types/frontmatter.d.ts +46 -0
  31. package/dist/types/fs-error.d.ts +31 -0
  32. package/dist/types/glob.d.ts +28 -0
  33. package/dist/types/headers.d.ts +34 -0
  34. package/dist/types/index.d.ts +39 -0
  35. package/dist/types/json-parse.d.ts +74 -0
  36. package/dist/types/json.d.ts +14 -0
  37. package/dist/types/logger/rotating-file.d.ts +18 -0
  38. package/dist/types/logger.d.ts +96 -0
  39. package/dist/types/loop-phase.d.ts +10 -0
  40. package/dist/types/lru.d.ts +46 -0
  41. package/dist/types/marked/core.d.ts +445 -0
  42. package/dist/types/marked.d.ts +2 -0
  43. package/dist/types/mermaid-ascii.d.ts +11 -0
  44. package/dist/types/mime.d.ts +29 -0
  45. package/dist/types/module-timer.d.ts +1 -0
  46. package/dist/types/path-tree.d.ts +76 -0
  47. package/dist/types/path.d.ts +2 -0
  48. package/dist/types/peek-file.d.ts +29 -0
  49. package/dist/types/postmortem.d.ts +104 -0
  50. package/dist/types/process-name.d.ts +7 -0
  51. package/dist/types/procmgr.d.ts +74 -0
  52. package/dist/types/prompt.d.ts +18 -0
  53. package/dist/types/ptree.d.ts +110 -0
  54. package/dist/types/readability/readability.d.ts +9 -0
  55. package/dist/types/readability/readerable.d.ts +10 -0
  56. package/dist/types/readability/types.d.ts +70 -0
  57. package/dist/types/readability.d.ts +4 -0
  58. package/dist/types/ring.d.ts +93 -0
  59. package/dist/types/runtime-install.d.ts +78 -0
  60. package/dist/types/sanitize-text.d.ts +29 -0
  61. package/dist/types/snowflake.d.ts +25 -0
  62. package/dist/types/stderr-guard.d.ts +22 -0
  63. package/dist/types/stream.d.ts +67 -0
  64. package/dist/types/tab-spacing.d.ts +24 -0
  65. package/dist/types/temp.d.ts +17 -0
  66. package/dist/types/template.d.ts +62 -0
  67. package/dist/types/timing-buffer.d.ts +22 -0
  68. package/dist/types/tls-fetch.d.ts +37 -0
  69. package/dist/types/turndown/gfm.d.ts +11 -0
  70. package/dist/types/turndown/html.d.ts +5 -0
  71. package/dist/types/turndown/service.d.ts +21 -0
  72. package/dist/types/turndown/types.d.ts +70 -0
  73. package/dist/types/turndown.d.ts +4 -0
  74. package/dist/types/type-guards.d.ts +5 -0
  75. package/dist/types/vendor/mermaid-ascii/ascii/ansi.d.ts +41 -0
  76. package/dist/types/vendor/mermaid-ascii/ascii/canvas.d.ts +89 -0
  77. package/dist/types/vendor/mermaid-ascii/ascii/class-diagram.d.ts +7 -0
  78. package/dist/types/vendor/mermaid-ascii/ascii/converter.d.ts +12 -0
  79. package/dist/types/vendor/mermaid-ascii/ascii/draw.d.ts +66 -0
  80. package/dist/types/vendor/mermaid-ascii/ascii/edge-bundling.d.ts +48 -0
  81. package/dist/types/vendor/mermaid-ascii/ascii/edge-routing.d.ts +43 -0
  82. package/dist/types/vendor/mermaid-ascii/ascii/er-diagram.d.ts +7 -0
  83. package/dist/types/vendor/mermaid-ascii/ascii/grid.d.ts +56 -0
  84. package/dist/types/vendor/mermaid-ascii/ascii/index.d.ts +65 -0
  85. package/dist/types/vendor/mermaid-ascii/ascii/multiline-utils.d.ts +27 -0
  86. package/dist/types/vendor/mermaid-ascii/ascii/pathfinder.d.ts +17 -0
  87. package/dist/types/vendor/mermaid-ascii/ascii/sequence.d.ts +7 -0
  88. package/dist/types/vendor/mermaid-ascii/ascii/shapes/circle.d.ts +11 -0
  89. package/dist/types/vendor/mermaid-ascii/ascii/shapes/corners.d.ts +34 -0
  90. package/dist/types/vendor/mermaid-ascii/ascii/shapes/diamond.d.ts +11 -0
  91. package/dist/types/vendor/mermaid-ascii/ascii/shapes/hexagon.d.ts +11 -0
  92. package/dist/types/vendor/mermaid-ascii/ascii/shapes/index.d.ts +26 -0
  93. package/dist/types/vendor/mermaid-ascii/ascii/shapes/rectangle.d.ts +31 -0
  94. package/dist/types/vendor/mermaid-ascii/ascii/shapes/rounded.d.ts +11 -0
  95. package/dist/types/vendor/mermaid-ascii/ascii/shapes/special.d.ts +59 -0
  96. package/dist/types/vendor/mermaid-ascii/ascii/shapes/stadium.d.ts +17 -0
  97. package/dist/types/vendor/mermaid-ascii/ascii/shapes/state.d.ts +30 -0
  98. package/dist/types/vendor/mermaid-ascii/ascii/shapes/types.d.ts +55 -0
  99. package/dist/types/vendor/mermaid-ascii/ascii/types.d.ts +206 -0
  100. package/dist/types/vendor/mermaid-ascii/ascii/validate.d.ts +51 -0
  101. package/dist/types/vendor/mermaid-ascii/ascii/xychart.d.ts +2 -0
  102. package/dist/types/vendor/mermaid-ascii/class/parser.d.ts +6 -0
  103. package/dist/types/vendor/mermaid-ascii/class/types.d.ts +102 -0
  104. package/dist/types/vendor/mermaid-ascii/er/parser.d.ts +6 -0
  105. package/dist/types/vendor/mermaid-ascii/er/types.d.ts +76 -0
  106. package/dist/types/vendor/mermaid-ascii/index.d.ts +1 -0
  107. package/dist/types/vendor/mermaid-ascii/multiline-utils.d.ts +9 -0
  108. package/dist/types/vendor/mermaid-ascii/parser.d.ts +7 -0
  109. package/dist/types/vendor/mermaid-ascii/sequence/parser.d.ts +6 -0
  110. package/dist/types/vendor/mermaid-ascii/sequence/types.d.ts +130 -0
  111. package/dist/types/vendor/mermaid-ascii/text-metrics.d.ts +21 -0
  112. package/dist/types/vendor/mermaid-ascii/types.d.ts +114 -0
  113. package/dist/types/vendor/mermaid-ascii/xychart/colors.d.ts +25 -0
  114. package/dist/types/vendor/mermaid-ascii/xychart/parser.d.ts +6 -0
  115. package/dist/types/vendor/mermaid-ascii/xychart/types.d.ts +145 -0
  116. package/dist/types/version.d.ts +18 -0
  117. package/dist/types/vterm/buffer.d.ts +99 -0
  118. package/dist/types/vterm/terminal.d.ts +44 -0
  119. package/dist/types/vterm.d.ts +8 -0
  120. package/dist/types/which.d.ts +37 -0
  121. package/dist/types/worker-host.d.ts +51 -0
  122. package/dist/types/xml.d.ts +31 -0
  123. package/package.json +59 -0
  124. package/src/abortable.ts +109 -0
  125. package/src/acp/connection.ts +344 -0
  126. package/src/acp/protocol.ts +466 -0
  127. package/src/acp/schema.ts +160 -0
  128. package/src/acp/stream.ts +82 -0
  129. package/src/acp/transport.ts +213 -0
  130. package/src/acp.ts +6 -0
  131. package/src/async.ts +91 -0
  132. package/src/binary.ts +50 -0
  133. package/src/browsers.ts +501 -0
  134. package/src/chalk.ts +312 -0
  135. package/src/cli.ts +529 -0
  136. package/src/color.ts +302 -0
  137. package/src/dates.ts +194 -0
  138. package/src/dirs.ts +1026 -0
  139. package/src/docx/converter.ts +681 -0
  140. package/src/docx/xml.ts +166 -0
  141. package/src/docx/zip.ts +87 -0
  142. package/src/docx.ts +20 -0
  143. package/src/dom/core.ts +1254 -0
  144. package/src/dom/parser.ts +370 -0
  145. package/src/dom/selector.ts +290 -0
  146. package/src/dom.ts +33 -0
  147. package/src/env.ts +400 -0
  148. package/src/fetch-retry.ts +379 -0
  149. package/src/file-lock.ts +69 -0
  150. package/src/format.ts +113 -0
  151. package/src/frontmatter.ts +205 -0
  152. package/src/fs-error.ts +56 -0
  153. package/src/glob.ts +189 -0
  154. package/src/headers.ts +167 -0
  155. package/src/index.ts +59 -0
  156. package/src/json-parse.ts +821 -0
  157. package/src/json.ts +23 -0
  158. package/src/logger/rotating-file.ts +149 -0
  159. package/src/logger.ts +798 -0
  160. package/src/loop-phase.ts +49 -0
  161. package/src/lru.ts +185 -0
  162. package/src/marked/core.ts +1576 -0
  163. package/src/marked.ts +2 -0
  164. package/src/mermaid-ascii.ts +31 -0
  165. package/src/mime.ts +159 -0
  166. package/src/module-timer.ts +148 -0
  167. package/src/path-tree.ts +147 -0
  168. package/src/path.ts +28 -0
  169. package/src/peek-file.ts +188 -0
  170. package/src/postmortem.ts +433 -0
  171. package/src/process-name.ts +57 -0
  172. package/src/procmgr.ts +247 -0
  173. package/src/prompt.ts +545 -0
  174. package/src/ptree.ts +412 -0
  175. package/src/readability/readability.ts +533 -0
  176. package/src/readability/readerable.ts +51 -0
  177. package/src/readability/types.ts +72 -0
  178. package/src/readability.ts +11 -0
  179. package/src/ring.ts +169 -0
  180. package/src/runtime-install.ts +393 -0
  181. package/src/sanitize-text.ts +96 -0
  182. package/src/snowflake.ts +121 -0
  183. package/src/stderr-guard.ts +155 -0
  184. package/src/stream.ts +454 -0
  185. package/src/tab-spacing.ts +336 -0
  186. package/src/temp.ts +134 -0
  187. package/src/template.ts +586 -0
  188. package/src/timing-buffer.ts +47 -0
  189. package/src/tls-fetch.ts +178 -0
  190. package/src/turndown/gfm.ts +106 -0
  191. package/src/turndown/html.ts +257 -0
  192. package/src/turndown/service.ts +334 -0
  193. package/src/turndown/types.ts +81 -0
  194. package/src/turndown.ts +5 -0
  195. package/src/type-guards.ts +17 -0
  196. package/src/vendor/mermaid-ascii/NOTICE +33 -0
  197. package/src/vendor/mermaid-ascii/ascii/ansi.ts +409 -0
  198. package/src/vendor/mermaid-ascii/ascii/canvas.ts +476 -0
  199. package/src/vendor/mermaid-ascii/ascii/class-diagram.ts +699 -0
  200. package/src/vendor/mermaid-ascii/ascii/converter.ts +271 -0
  201. package/src/vendor/mermaid-ascii/ascii/draw.ts +1382 -0
  202. package/src/vendor/mermaid-ascii/ascii/edge-bundling.ts +328 -0
  203. package/src/vendor/mermaid-ascii/ascii/edge-routing.ts +297 -0
  204. package/src/vendor/mermaid-ascii/ascii/er-diagram.ts +441 -0
  205. package/src/vendor/mermaid-ascii/ascii/grid.ts +578 -0
  206. package/src/vendor/mermaid-ascii/ascii/index.ts +187 -0
  207. package/src/vendor/mermaid-ascii/ascii/multiline-utils.ts +78 -0
  208. package/src/vendor/mermaid-ascii/ascii/pathfinder.ts +277 -0
  209. package/src/vendor/mermaid-ascii/ascii/sequence.ts +460 -0
  210. package/src/vendor/mermaid-ascii/ascii/shapes/circle.ts +27 -0
  211. package/src/vendor/mermaid-ascii/ascii/shapes/corners.ts +127 -0
  212. package/src/vendor/mermaid-ascii/ascii/shapes/diamond.ts +27 -0
  213. package/src/vendor/mermaid-ascii/ascii/shapes/hexagon.ts +27 -0
  214. package/src/vendor/mermaid-ascii/ascii/shapes/index.ts +101 -0
  215. package/src/vendor/mermaid-ascii/ascii/shapes/rectangle.ts +175 -0
  216. package/src/vendor/mermaid-ascii/ascii/shapes/rounded.ts +27 -0
  217. package/src/vendor/mermaid-ascii/ascii/shapes/special.ts +296 -0
  218. package/src/vendor/mermaid-ascii/ascii/shapes/stadium.ts +114 -0
  219. package/src/vendor/mermaid-ascii/ascii/shapes/state.ts +192 -0
  220. package/src/vendor/mermaid-ascii/ascii/shapes/types.ts +73 -0
  221. package/src/vendor/mermaid-ascii/ascii/types.ts +273 -0
  222. package/src/vendor/mermaid-ascii/ascii/validate.ts +120 -0
  223. package/src/vendor/mermaid-ascii/ascii/xychart.ts +875 -0
  224. package/src/vendor/mermaid-ascii/class/parser.ts +290 -0
  225. package/src/vendor/mermaid-ascii/class/types.ts +121 -0
  226. package/src/vendor/mermaid-ascii/er/parser.ts +181 -0
  227. package/src/vendor/mermaid-ascii/er/types.ts +91 -0
  228. package/src/vendor/mermaid-ascii/index.ts +14 -0
  229. package/src/vendor/mermaid-ascii/multiline-utils.ts +30 -0
  230. package/src/vendor/mermaid-ascii/parser.ts +645 -0
  231. package/src/vendor/mermaid-ascii/sequence/parser.ts +207 -0
  232. package/src/vendor/mermaid-ascii/sequence/types.ts +146 -0
  233. package/src/vendor/mermaid-ascii/text-metrics.ts +71 -0
  234. package/src/vendor/mermaid-ascii/types.ts +164 -0
  235. package/src/vendor/mermaid-ascii/xychart/colors.ts +140 -0
  236. package/src/vendor/mermaid-ascii/xychart/parser.ts +115 -0
  237. package/src/vendor/mermaid-ascii/xychart/types.ts +150 -0
  238. package/src/version.ts +99 -0
  239. package/src/vterm/buffer.ts +218 -0
  240. package/src/vterm/terminal.ts +773 -0
  241. package/src/vterm.ts +8 -0
  242. package/src/which.ts +234 -0
  243. package/src/worker-host.ts +100 -0
  244. package/src/xml.ts +313 -0
@@ -0,0 +1,109 @@
1
+ import assert from "node:assert/strict";
2
+
3
+ export class AbortError extends Error {
4
+ constructor(signal: AbortSignal) {
5
+ assert(signal.aborted, "Abort signal must be aborted");
6
+
7
+ const message = signal.reason instanceof Error ? signal.reason.message : "Cancelled";
8
+ super(`Aborted: ${message}`, { cause: signal.reason });
9
+ this.name = "AbortError";
10
+ }
11
+ }
12
+
13
+ /**
14
+ * Abortable async iteration over a {@link ReadableStream}. Reads the source
15
+ * reader directly and yields each chunk, so the consumer's `for await` drives a
16
+ * single read loop with no intermediate stream or per-chunk enqueue.
17
+ *
18
+ * Unlike `stream.pipeThrough(..., { signal })`, this explicitly cancels the
19
+ * source reader on abort or early `break`, propagating HTTP-client disconnects
20
+ * and watchdog timeouts to the backend request instead of only stopping the
21
+ * local consumer. On abort it throws {@link AbortError}; the lock is released
22
+ * on completion, abort, throw, or early exit. The source is cancelled only on
23
+ * abort or early exit — never on natural EOF.
24
+ */
25
+ export async function* abortableSource<T>(stream: ReadableStream<T>, signal?: AbortSignal): AsyncGenerator<T> {
26
+ if (signal?.aborted) throw new AbortError(signal);
27
+ const reader = stream.getReader();
28
+ let onAbort: (() => void) | undefined;
29
+ if (signal) {
30
+ onAbort = () => {
31
+ void reader.cancel(signal.reason).catch(() => {});
32
+ };
33
+ signal.addEventListener("abort", onAbort, { once: true });
34
+ }
35
+ let completed = false;
36
+ try {
37
+ for (;;) {
38
+ const result = await reader.read();
39
+ if (signal?.aborted) throw new AbortError(signal);
40
+ if (result.done) {
41
+ completed = true;
42
+ return;
43
+ }
44
+ yield result.value;
45
+ }
46
+ } finally {
47
+ if (signal && onAbort) signal.removeEventListener("abort", onAbort);
48
+ // Propagate early-exit (`break`/`return`) and abort to the backend; skip
49
+ // on natural EOF where the stream already closed itself.
50
+ if (!completed) {
51
+ try {
52
+ await reader.cancel();
53
+ } catch {}
54
+ }
55
+ try {
56
+ reader.releaseLock();
57
+ } catch {}
58
+ }
59
+ }
60
+
61
+ /**
62
+ * Runs a promise-returning function (`pr`). If the given AbortSignal is aborted before or during
63
+ * execution, the promise is rejected with a standard error.
64
+ *
65
+ * @param signal - Optional AbortSignal to cancel the operation
66
+ * @param pr - Function returning a promise to run
67
+ * @returns Promise resolving as `pr` would, or rejecting on abort
68
+ */
69
+ export function untilAborted<T>(
70
+ signal: AbortSignal | undefined | null,
71
+ pr: Promise<T> | (() => Promise<T>),
72
+ ): Promise<T> {
73
+ if (!signal) return typeof pr === "function" ? pr() : pr;
74
+ if (signal.aborted) return Promise.reject(new AbortError(signal));
75
+
76
+ const { promise, resolve, reject } = Promise.withResolvers<T>();
77
+ const onAbort = () => reject(new AbortError(signal));
78
+ signal.addEventListener("abort", onAbort, { once: true });
79
+
80
+ void (async () => {
81
+ try {
82
+ resolve(await (typeof pr === "function" ? pr() : pr));
83
+ } catch (err) {
84
+ reject(err);
85
+ } finally {
86
+ signal.removeEventListener("abort", onAbort);
87
+ }
88
+ })();
89
+
90
+ return promise;
91
+ }
92
+
93
+ /**
94
+ * Memoizes a function with no arguments, calling it once and caching the result.
95
+ *
96
+ * @param fn - Function to be called once
97
+ * @returns A function that returns the cached result of `fn`
98
+ */
99
+ export function once<T>(fn: () => T): () => T {
100
+ let store = undefined as { value: T } | undefined;
101
+ return () => {
102
+ if (store) {
103
+ return store.value;
104
+ }
105
+ const value = fn();
106
+ store = { value };
107
+ return value;
108
+ };
109
+ }
@@ -0,0 +1,344 @@
1
+ import type {
2
+ Agent,
3
+ AuthenticateRequest,
4
+ AuthenticateResponse,
5
+ CloseSessionRequest,
6
+ CloseSessionResponse,
7
+ CompleteElicitationNotification,
8
+ CreateElicitationRequest,
9
+ CreateElicitationResponse,
10
+ CreateTerminalRequest,
11
+ ForkSessionRequest,
12
+ ForkSessionResponse,
13
+ InitializeRequest,
14
+ InitializeResponse,
15
+ ListSessionsRequest,
16
+ ListSessionsResponse,
17
+ LoadSessionRequest,
18
+ LoadSessionResponse,
19
+ MaybePromise,
20
+ NewSessionRequest,
21
+ NewSessionResponse,
22
+ PromptRequest,
23
+ PromptResponse,
24
+ ReadTextFileRequest,
25
+ ReadTextFileResponse,
26
+ RequestPermissionRequest,
27
+ RequestPermissionResponse,
28
+ ResumeSessionRequest,
29
+ ResumeSessionResponse,
30
+ SessionNotification,
31
+ SetSessionConfigOptionRequest,
32
+ SetSessionConfigOptionResponse,
33
+ SetSessionModeRequest,
34
+ SetSessionModeResponse,
35
+ TerminalActionResponse,
36
+ TerminalOutputResponse,
37
+ WaitForTerminalExitResponse,
38
+ WriteTextFileRequest,
39
+ WriteTextFileResponse,
40
+ } from "./protocol";
41
+ import type { Stream } from "./stream";
42
+ import { RequestError, RpcConnection } from "./transport";
43
+
44
+ /** Terminal creation response returned by a client. */
45
+ export interface CreateTerminalResponse {
46
+ terminalId: string;
47
+ }
48
+ /** Client callbacks handled by a client-side connection. */
49
+ export interface Client {
50
+ requestPermission(params: RequestPermissionRequest): MaybePromise<RequestPermissionResponse>;
51
+ sessionUpdate(params: SessionNotification): MaybePromise<void>;
52
+ readTextFile?(params: ReadTextFileRequest): MaybePromise<ReadTextFileResponse>;
53
+ writeTextFile?(params: WriteTextFileRequest): MaybePromise<WriteTextFileResponse | void>;
54
+ createTerminal?(params: CreateTerminalRequest): MaybePromise<CreateTerminalResponse>;
55
+ terminalOutput?(params: { sessionId: string; terminalId: string }): MaybePromise<TerminalOutputResponse>;
56
+ waitForTerminalExit?(params: { sessionId: string; terminalId: string }): MaybePromise<WaitForTerminalExitResponse>;
57
+ killTerminal?(params: { sessionId: string; terminalId: string }): MaybePromise<TerminalActionResponse | void>;
58
+ releaseTerminal?(params: { sessionId: string; terminalId: string }): MaybePromise<TerminalActionResponse | void>;
59
+ unstable_createElicitation?(params: CreateElicitationRequest): MaybePromise<CreateElicitationResponse>;
60
+ unstable_completeElicitation?(params: CompleteElicitationNotification): MaybePromise<void>;
61
+ extMethod?(method: string, params: Record<string, unknown>): MaybePromise<Record<string, unknown>>;
62
+ extNotification?(method: string, params: Record<string, unknown>): MaybePromise<void>;
63
+ }
64
+
65
+ /** Agent-side ACP connection. */
66
+ export class AgentSideConnection {
67
+ #connection: RpcConnection;
68
+
69
+ constructor(toAgent: (connection: AgentSideConnection) => Agent, stream: Stream) {
70
+ let agent: Agent | undefined;
71
+ this.#connection = new RpcConnection(stream, async (method, params, notification) => {
72
+ const target = agent;
73
+ if (!target) throw RequestError.internalError(undefined, "Agent is not initialized");
74
+ return dispatchAgent(target, method, params, notification);
75
+ });
76
+ agent = toAgent(this);
77
+ }
78
+
79
+ /** Signal aborted when the transport closes. */
80
+ get signal(): AbortSignal {
81
+ return this.#connection.signal;
82
+ }
83
+ /** Promise resolved when the transport closes. */
84
+ get closed(): Promise<void> {
85
+ return this.#connection.closed;
86
+ }
87
+ /** Sends a session update notification. */
88
+ sessionUpdate(params: SessionNotification): Promise<void> {
89
+ return this.#connection.notify("session/update", params);
90
+ }
91
+ /** Requests permission from the client. */
92
+ requestPermission(params: RequestPermissionRequest): Promise<RequestPermissionResponse> {
93
+ return this.#connection.request("session/request_permission", params);
94
+ }
95
+ /** Reads a client-side text file. */
96
+ readTextFile(params: ReadTextFileRequest): Promise<ReadTextFileResponse> {
97
+ return this.#connection.request("fs/read_text_file", params);
98
+ }
99
+ /** Writes a client-side text file. */
100
+ writeTextFile(params: WriteTextFileRequest): Promise<WriteTextFileResponse> {
101
+ return this.#connection.request("fs/write_text_file", params);
102
+ }
103
+ /** Creates a client terminal and returns its control handle. */
104
+ async createTerminal(params: CreateTerminalRequest): Promise<TerminalHandle> {
105
+ const response = await this.#connection.request<CreateTerminalResponse>("terminal/create", params);
106
+ return new TerminalHandle(response.terminalId, params.sessionId, this.#connection);
107
+ }
108
+ /** Creates an interactive elicitation on the client. */
109
+ unstable_createElicitation(params: CreateElicitationRequest): Promise<CreateElicitationResponse> {
110
+ return this.#connection.request("elicitation/create", params);
111
+ }
112
+ /** Notifies a client that URL elicitation completed. */
113
+ unstable_completeElicitation(params: CompleteElicitationNotification): Promise<void> {
114
+ return this.#connection.notify("elicitation/complete", params);
115
+ }
116
+ /** Sends a custom request. */
117
+ request<Response = unknown, Params = unknown>(method: string, params?: Params): Promise<Response> {
118
+ return this.#connection.request(method, params);
119
+ }
120
+ /** Sends a custom notification. */
121
+ notify<Params = unknown>(method: string, params?: Params): Promise<void> {
122
+ return this.#connection.notify(method, params);
123
+ }
124
+ /** Sends a legacy extension request. */
125
+ extMethod(method: string, params: Record<string, unknown>): Promise<Record<string, unknown>> {
126
+ return this.request(method, params);
127
+ }
128
+ /** Sends a legacy extension notification. */
129
+ extNotification(method: string, params: Record<string, unknown>): Promise<void> {
130
+ return this.notify(method, params);
131
+ }
132
+ }
133
+
134
+ /** Handle for controlling a client-owned terminal. */
135
+ export class TerminalHandle {
136
+ /** Client terminal identifier. */
137
+ readonly id: string;
138
+ #sessionId: string;
139
+ #connection: RpcConnection;
140
+
141
+ constructor(id: string, sessionId: string, connection: RpcConnection) {
142
+ this.id = id;
143
+ this.#sessionId = sessionId;
144
+ this.#connection = connection;
145
+ }
146
+ /** Gets current terminal output. */
147
+ currentOutput(): Promise<TerminalOutputResponse> {
148
+ return this.#connection.request("terminal/output", { sessionId: this.#sessionId, terminalId: this.id });
149
+ }
150
+ /** Waits for terminal exit. */
151
+ waitForExit(): Promise<WaitForTerminalExitResponse> {
152
+ return this.#connection.request("terminal/wait_for_exit", { sessionId: this.#sessionId, terminalId: this.id });
153
+ }
154
+ /** Kills the terminal. */
155
+ kill(): Promise<TerminalActionResponse> {
156
+ return this.#connection.request("terminal/kill", { sessionId: this.#sessionId, terminalId: this.id });
157
+ }
158
+ /** Releases the terminal. */
159
+ release(): Promise<TerminalActionResponse | void> {
160
+ return this.#connection.request("terminal/release", { sessionId: this.#sessionId, terminalId: this.id });
161
+ }
162
+ /** Releases the terminal during async disposal. */
163
+ async [Symbol.asyncDispose](): Promise<void> {
164
+ await this.release();
165
+ }
166
+ }
167
+
168
+ /** Client-side ACP connection used to call an agent. */
169
+ export class ClientSideConnection {
170
+ #connection: RpcConnection;
171
+
172
+ constructor(toClient: (connection: ClientSideConnection) => Client, stream: Stream) {
173
+ let client: Client | undefined;
174
+ this.#connection = new RpcConnection(stream, async (method, params, notification) => {
175
+ const target = client;
176
+ if (!target) throw RequestError.internalError(undefined, "Client is not initialized");
177
+ return dispatchClient(target, method, params, notification);
178
+ });
179
+ client = toClient(this);
180
+ }
181
+ /** Signal aborted when the transport closes. */
182
+ get signal(): AbortSignal {
183
+ return this.#connection.signal;
184
+ }
185
+ /** Promise resolved when the transport closes. */
186
+ get closed(): Promise<void> {
187
+ return this.#connection.closed;
188
+ }
189
+ /** Initializes protocol capabilities. */
190
+ initialize(params: InitializeRequest): Promise<InitializeResponse> {
191
+ return this.#connection.request("initialize", params);
192
+ }
193
+ /** Authenticates with an agent. */
194
+ authenticate(params: AuthenticateRequest): Promise<AuthenticateResponse> {
195
+ return this.#connection.request("authenticate", params);
196
+ }
197
+ /** Creates a session. */
198
+ newSession(params: NewSessionRequest): Promise<NewSessionResponse> {
199
+ return this.#connection.request("session/new", params);
200
+ }
201
+ /** Loads a session. */
202
+ loadSession(params: LoadSessionRequest): Promise<LoadSessionResponse> {
203
+ return this.#connection.request("session/load", params);
204
+ }
205
+ /** Lists sessions. */
206
+ listSessions(params: ListSessionsRequest): Promise<ListSessionsResponse> {
207
+ return this.#connection.request("session/list", params);
208
+ }
209
+ /** Resumes a session. */
210
+ resumeSession(params: ResumeSessionRequest): Promise<ResumeSessionResponse> {
211
+ return this.#connection.request("session/resume", params);
212
+ }
213
+ /** Forks a session. */
214
+ unstable_forkSession(params: ForkSessionRequest): Promise<ForkSessionResponse> {
215
+ return this.#connection.request("session/fork", params);
216
+ }
217
+ /** Closes a session. */
218
+ closeSession(params: CloseSessionRequest): Promise<CloseSessionResponse> {
219
+ return this.#connection.request("session/close", params);
220
+ }
221
+ /** Sets a session mode. */
222
+ setSessionMode(params: SetSessionModeRequest): Promise<SetSessionModeResponse> {
223
+ return this.#connection.request("session/set_mode", params);
224
+ }
225
+ /** Sets a session config option. */
226
+ setSessionConfigOption(params: SetSessionConfigOptionRequest): Promise<SetSessionConfigOptionResponse> {
227
+ return this.#connection.request("session/set_config_option", params);
228
+ }
229
+ /** Sends a prompt. */
230
+ prompt(params: PromptRequest): Promise<PromptResponse> {
231
+ return this.#connection.request("session/prompt", params);
232
+ }
233
+ /** Cancels an active prompt. */
234
+ cancel(params: { sessionId: string }): Promise<void> {
235
+ return this.#connection.notify("session/cancel", params);
236
+ }
237
+ }
238
+
239
+ async function dispatchAgent(agent: Agent, method: string, params: unknown, notification: boolean): Promise<unknown> {
240
+ switch (method) {
241
+ case "initialize":
242
+ return agent.initialize(params as InitializeRequest);
243
+ case "authenticate":
244
+ return invokeRequired(agent, agent.authenticate, method, params as AuthenticateRequest);
245
+ case "session/new":
246
+ return agent.newSession(params as NewSessionRequest);
247
+ case "session/load":
248
+ return invokeRequired(agent, agent.loadSession, method, params as LoadSessionRequest);
249
+ case "session/list":
250
+ return invokeRequired(agent, agent.listSessions, method, params as ListSessionsRequest);
251
+ case "session/resume":
252
+ return invokeRequired(agent, agent.resumeSession, method, params as ResumeSessionRequest);
253
+ case "session/fork":
254
+ return invokeRequired(agent, agent.unstable_forkSession, method, params as ForkSessionRequest);
255
+ case "session/close":
256
+ return invokeRequired(agent, agent.closeSession, method, params as CloseSessionRequest);
257
+ case "session/set_mode":
258
+ return invokeRequired(agent, agent.setSessionMode, method, params as SetSessionModeRequest);
259
+ case "session/set_config_option":
260
+ return invokeRequired(agent, agent.setSessionConfigOption, method, params as SetSessionConfigOptionRequest);
261
+ case "session/prompt":
262
+ return agent.prompt(params as PromptRequest);
263
+ case "session/cancel":
264
+ return agent.cancel(params as { sessionId: string });
265
+ default:
266
+ if (method === "$/cancel_request") return;
267
+ if (notification && agent.extNotification)
268
+ return agent.extNotification(method, params as Record<string, unknown>);
269
+ if (!notification && agent.extMethod) return agent.extMethod(method, params as Record<string, unknown>);
270
+ throw RequestError.methodNotFound(method);
271
+ }
272
+ }
273
+
274
+ async function dispatchClient(
275
+ client: Client,
276
+ method: string,
277
+ params: unknown,
278
+ notification: boolean,
279
+ ): Promise<unknown> {
280
+ switch (method) {
281
+ case "session/request_permission":
282
+ return client.requestPermission(params as RequestPermissionRequest);
283
+ case "session/update":
284
+ return client.sessionUpdate(params as SessionNotification);
285
+ case "fs/read_text_file":
286
+ return invokeRequired(client, client.readTextFile, method, params as ReadTextFileRequest);
287
+ case "fs/write_text_file":
288
+ return invokeRequired(client, client.writeTextFile, method, params as WriteTextFileRequest);
289
+ case "terminal/create":
290
+ return invokeRequired(client, client.createTerminal, method, params as CreateTerminalRequest);
291
+ case "terminal/output":
292
+ return invokeRequired(
293
+ client,
294
+ client.terminalOutput,
295
+ method,
296
+ params as { sessionId: string; terminalId: string },
297
+ );
298
+ case "terminal/wait_for_exit":
299
+ return invokeRequired(
300
+ client,
301
+ client.waitForTerminalExit,
302
+ method,
303
+ params as { sessionId: string; terminalId: string },
304
+ );
305
+ case "terminal/kill":
306
+ return invokeRequired(
307
+ client,
308
+ client.killTerminal,
309
+ method,
310
+ params as { sessionId: string; terminalId: string },
311
+ );
312
+ case "terminal/release":
313
+ return invokeRequired(
314
+ client,
315
+ client.releaseTerminal,
316
+ method,
317
+ params as { sessionId: string; terminalId: string },
318
+ );
319
+ case "elicitation/create":
320
+ return invokeRequired(client, client.unstable_createElicitation, method, params as CreateElicitationRequest);
321
+ case "elicitation/complete":
322
+ return invokeRequired(
323
+ client,
324
+ client.unstable_completeElicitation,
325
+ method,
326
+ params as CompleteElicitationNotification,
327
+ );
328
+ default:
329
+ if (notification && client.extNotification)
330
+ return client.extNotification(method, params as Record<string, unknown>);
331
+ if (!notification && client.extMethod) return client.extMethod(method, params as Record<string, unknown>);
332
+ throw RequestError.methodNotFound(method);
333
+ }
334
+ }
335
+
336
+ function invokeRequired<Params, Response>(
337
+ receiver: Agent | Client,
338
+ handler: ((params: Params) => MaybePromise<Response>) | undefined,
339
+ method: string,
340
+ params: Params,
341
+ ): MaybePromise<Response> {
342
+ if (!handler) throw RequestError.methodNotFound(method);
343
+ return handler.call(receiver, params);
344
+ }