@agen-ai/acp-transport 0.4.3 → 0.4.4

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
@@ -76,7 +76,7 @@ slow output consumer does not block correlated responses or cancellation. Hosts
76
76
  must reserve bounded queue capacity during handler admission and retain that
77
77
  reservation until processing completes.
78
78
 
79
- Request deadlines and bounded shutdown drains keep Node's event loop alive until
79
+ Finite request deadlines and bounded shutdown drains keep Node's event loop alive until
80
80
  the operation settles, including when the supplied streams have no active I/O
81
81
  handles. Settlement clears the operation's timer. Always await `client.dispose()`
82
82
  when the connection is no longer needed to reject pending requests and complete
@@ -153,6 +153,20 @@ and output backpressure. Notification delivery alone does not provide a durable
153
153
  event journal or a provider-neutral turn state machine.
154
154
 
155
155
  Request cancellation or timeout does not prove that the peer stopped execution.
156
+ Requests default to bounded waiting, using the configured finite timeout and the
157
+ earlier optional `deadlineAt`. Existing numeric `timeoutMs` and `deadlineAt` calls
158
+ retain those limits. `lifetime: 'bounded'` makes that default explicit.
159
+
160
+ Select `{ lifetime: 'until_settled' }` for an execution request that must retain
161
+ its original RPC waiter until a response, explicit abort, disposal or connection
162
+ failure. This choice schedules no request timer and cannot be combined with
163
+ `timeoutMs` or `deadlineAt`, even when either property is explicitly `undefined`.
164
+ Contradictions reject before dispatch. The request still consumes bounded pending
165
+ capacity, retains its exact ID and response validation, and respects signals and
166
+ disposal. The caller must own cancellation, output consumption and cleanup. For a
167
+ long native operation, request abort alone does not establish native cancellation;
168
+ retain the RPC while performing the protocol's cancellation-confirmation flow.
169
+
156
170
  `onRequestDispatch` receives the exact allocated `requestId` at the boundary immediately
157
171
  before the first write, allowing request-scoped reverse traffic to be correlated before
158
172
  the peer can respond. A callback that aborts or rejects admission prevents the request
package/dist/client.js CHANGED
@@ -11,7 +11,7 @@ import {
11
11
  } from "./protocol.js";
12
12
  import { createAcpSchemaValidator } from "./schema.js";
13
13
  import {
14
- boundedTimeout,
14
+ resolveRequestTimeout,
15
15
  cleanupPendingRequest,
16
16
  deferred,
17
17
  isCriticalExtensionMethod
@@ -410,13 +410,13 @@ function createAcpClient(options) {
410
410
  );
411
411
  }
412
412
  const extension = validateOutbound("request", method, params);
413
- const timeoutMs = boundedTimeout({
413
+ const timeoutMs = resolveRequestTimeout({
414
414
  options: requestOptions,
415
415
  now: now(),
416
416
  defaultMs: limits.defaultRequestTimeoutMs,
417
417
  maximumMs: limits.maxRequestTimeoutMs
418
418
  });
419
- if (timeoutMs <= 0 || requestOptions.signal?.aborted) {
419
+ if (timeoutMs !== void 0 && timeoutMs <= 0 || requestOptions.signal?.aborted) {
420
420
  throw new AcpRequestError("acp_request_aborted", 0);
421
421
  }
422
422
  const id = allocateRequestId();
@@ -430,7 +430,7 @@ function createAcpClient(options) {
430
430
  sendCancellation(id);
431
431
  };
432
432
  requestOptions.signal?.addEventListener("abort", abort, { once: true });
433
- const timer = setTimeout(() => {
433
+ const timer = timeoutMs === void 0 ? void 0 : setTimeout(() => {
434
434
  const entry2 = pending.get(key);
435
435
  if (!entry2) return;
436
436
  cleanupPending(entry2);
@@ -47,15 +47,22 @@ export interface CreateAcpClientOptions {
47
47
  readonly onFatalError?: (error: Error) => void;
48
48
  readonly disposeTransport?: () => void | Promise<void>;
49
49
  }
50
- export interface AcpRequestOptions {
51
- readonly timeoutMs?: number;
52
- readonly deadlineAt?: number | Date;
50
+ interface AcpRequestContextOptions {
53
51
  readonly signal?: AbortSignal;
54
52
  /** Runs synchronously after local admission and immediately before the transport write. */
55
53
  readonly onRequestDispatch?: (context: AcpRequestDispatchContext) => void;
56
54
  /** Runs synchronously after response validation, before promise settlement and the next frame. */
57
55
  readonly onResponseReceived?: (response: AcpResponseReceived) => void;
58
56
  }
57
+ export type AcpRequestOptions = AcpRequestContextOptions & (Readonly<{
58
+ lifetime?: 'bounded';
59
+ timeoutMs?: number;
60
+ deadlineAt?: number | Date;
61
+ }> | Readonly<{
62
+ lifetime: 'until_settled';
63
+ timeoutMs?: never;
64
+ deadlineAt?: never;
65
+ }>);
59
66
  export interface AcpClientCloseResult {
60
67
  readonly kind: 'disposed' | 'peer_closed' | 'fatal';
61
68
  readonly error?: Error;
@@ -67,4 +74,5 @@ export interface AcpClient {
67
74
  readonly closed: Promise<AcpClientCloseResult>;
68
75
  readonly dispose: () => Promise<void>;
69
76
  }
77
+ export {};
70
78
  //# sourceMappingURL=clientContracts.d.ts.map
@@ -7,7 +7,7 @@ export interface PendingRequest {
7
7
  readonly extension: boolean;
8
8
  readonly resolve: (value: AcpJsonValue) => void;
9
9
  readonly reject: (error: Error) => void;
10
- readonly timer: ReturnType<typeof setTimeout>;
10
+ readonly timer: ReturnType<typeof setTimeout> | undefined;
11
11
  readonly removeAbortListener: () => void;
12
12
  readonly onResponseReceived?: AcpRequestOptions['onResponseReceived'];
13
13
  }
@@ -21,11 +21,11 @@ export declare function deferred<T>(): {
21
21
  reject: (error: unknown) => void;
22
22
  };
23
23
  export declare function isCriticalExtensionMethod(method: string): boolean;
24
- export declare function boundedTimeout(input: {
24
+ export declare function resolveRequestTimeout(input: {
25
25
  readonly options: AcpRequestOptions;
26
26
  readonly now: number;
27
27
  readonly defaultMs: number;
28
28
  readonly maximumMs: number;
29
- }): number;
29
+ }): number | undefined;
30
30
  export declare function cleanupPendingRequest(pending: Map<string, PendingRequest>, entry: PendingRequest): void;
31
31
  //# sourceMappingURL=clientState.d.ts.map
@@ -11,12 +11,21 @@ function deferred() {
11
11
  function isCriticalExtensionMethod(method) {
12
12
  return method.startsWith("_") || method.startsWith("$/");
13
13
  }
14
- function boundedTimeout(input) {
14
+ function resolveRequestTimeout(input) {
15
+ if (input.options.lifetime === "until_settled") {
16
+ if (Reflect.has(input.options, "timeoutMs") || Reflect.has(input.options, "deadlineAt")) {
17
+ throw new TypeError("Until-settled ACP requests cannot select finite timing.");
18
+ }
19
+ return void 0;
20
+ }
21
+ if (input.options.lifetime !== void 0 && input.options.lifetime !== "bounded") {
22
+ throw new TypeError("ACP request lifetime is invalid.");
23
+ }
15
24
  const requested = input.options.timeoutMs ?? input.defaultMs;
16
25
  if (!Number.isSafeInteger(requested) || requested <= 0 || requested > input.maximumMs) {
17
26
  throw new TypeError("ACP request timeout is outside the supported range.");
18
27
  }
19
- if (!input.options.deadlineAt) return requested;
28
+ if (input.options.deadlineAt === void 0) return requested;
20
29
  const deadline = input.options.deadlineAt instanceof Date ? input.options.deadlineAt.getTime() : input.options.deadlineAt;
21
30
  if (!Number.isFinite(deadline)) throw new TypeError("ACP request deadline is invalid.");
22
31
  return Math.min(requested, Math.floor(deadline - input.now));
@@ -27,8 +36,8 @@ function cleanupPendingRequest(pending, entry) {
27
36
  pending.delete(acpRequestIdKey(entry.id));
28
37
  }
29
38
  export {
30
- boundedTimeout,
31
39
  cleanupPendingRequest,
32
40
  deferred,
33
- isCriticalExtensionMethod
41
+ isCriticalExtensionMethod,
42
+ resolveRequestTimeout
34
43
  };
@@ -127,10 +127,21 @@ export type AcpStandardCancelParams = AcpStandardObject<{
127
127
  sessionId: string;
128
128
  _meta?: AcpStandardMeta;
129
129
  }>;
130
+ export type AcpStandardListSessionsParams = AcpStandardObject<{
131
+ cwd?: string | null;
132
+ cursor?: string | null;
133
+ _meta?: AcpStandardMeta;
134
+ }>;
135
+ export type AcpStandardDeleteSessionParams = AcpStandardObject<{
136
+ sessionId: string;
137
+ _meta?: AcpStandardMeta;
138
+ }>;
130
139
  export interface AcpStandardSessionOperations {
131
140
  readonly initialize: (params: AcpStandardInitializeParams, options?: AcpRequestOptions) => Promise<AcpJsonValue>;
132
141
  readonly newSession: (params: AcpStandardNewSessionParams, options?: AcpRequestOptions) => Promise<AcpJsonValue>;
133
142
  readonly loadSession: (params: AcpStandardLoadSessionParams, options?: AcpRequestOptions) => Promise<AcpJsonValue>;
143
+ readonly listSessions: (params: AcpStandardListSessionsParams, options?: AcpRequestOptions) => Promise<AcpJsonValue>;
144
+ readonly deleteSession: (params: AcpStandardDeleteSessionParams, options?: AcpRequestOptions) => Promise<AcpJsonValue>;
134
145
  readonly prompt: (params: AcpStandardPromptParams, options?: AcpRequestOptions) => Promise<AcpJsonValue>;
135
146
  readonly cancel: (params: AcpStandardCancelParams) => Promise<void>;
136
147
  }
@@ -2,6 +2,8 @@ const STANDARD_METHODS = Object.freeze({
2
2
  initialize: "initialize",
3
3
  newSession: "session/new",
4
4
  loadSession: "session/load",
5
+ listSessions: "session/list",
6
+ deleteSession: "session/delete",
5
7
  prompt: "session/prompt",
6
8
  cancel: "session/cancel"
7
9
  });
@@ -22,6 +24,16 @@ function createAcpStandardSessionOperations(client) {
22
24
  params,
23
25
  options
24
26
  ),
27
+ listSessions: (params, options) => client.request(
28
+ STANDARD_METHODS.listSessions,
29
+ params,
30
+ options
31
+ ),
32
+ deleteSession: (params, options) => client.request(
33
+ STANDARD_METHODS.deleteSession,
34
+ params,
35
+ options
36
+ ),
25
37
  prompt: (params, options) => client.request(
26
38
  STANDARD_METHODS.prompt,
27
39
  params,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agen-ai/acp-transport",
3
- "version": "0.4.3",
3
+ "version": "0.4.4",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "sideEffects": false,