@automatalabs/acp-agents 0.21.2 → 0.22.1
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/dist/acp-client.d.ts +51 -0
- package/dist/acp-client.d.ts.map +1 -1
- package/dist/acp-client.js +127 -2
- package/dist/auth/auth-profiles.d.ts +63 -0
- package/dist/auth/auth-profiles.d.ts.map +1 -0
- package/dist/auth/auth-profiles.js +45 -0
- package/dist/auth/auth-store.d.ts +112 -0
- package/dist/auth/auth-store.d.ts.map +1 -0
- package/dist/auth/auth-store.js +186 -0
- package/dist/auth/auth-types.d.ts +93 -0
- package/dist/auth/auth-types.d.ts.map +1 -0
- package/dist/auth/auth-types.js +108 -0
- package/dist/backend.d.ts +7 -0
- package/dist/backend.d.ts.map +1 -1
- package/dist/backends/claude.d.ts +2 -0
- package/dist/backends/claude.d.ts.map +1 -1
- package/dist/backends/claude.js +3 -0
- package/dist/backends/codex.d.ts +3 -0
- package/dist/backends/codex.d.ts.map +1 -1
- package/dist/backends/codex.js +4 -0
- package/dist/backends/opencode.d.ts +2 -0
- package/dist/backends/opencode.d.ts.map +1 -1
- package/dist/backends/opencode.js +3 -0
- package/dist/capabilities.d.ts +7 -1
- package/dist/capabilities.d.ts.map +1 -1
- package/dist/capabilities.js +17 -0
- package/dist/client-handlers.d.ts +9 -0
- package/dist/client-handlers.d.ts.map +1 -1
- package/dist/client-handlers.js +17 -0
- package/dist/errors-map.d.ts.map +1 -1
- package/dist/errors-map.js +26 -2
- package/dist/index.d.ts +11 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -2
- package/dist/permissions.d.ts +27 -0
- package/dist/permissions.d.ts.map +1 -1
- package/dist/permissions.js +23 -1
- package/dist/pool.d.ts +20 -0
- package/dist/pool.d.ts.map +1 -1
- package/dist/pool.js +58 -16
- package/dist/protocol-coverage.d.ts +75 -0
- package/dist/protocol-coverage.d.ts.map +1 -1
- package/dist/protocol-coverage.js +58 -0
- package/dist/runner.d.ts +120 -3
- package/dist/runner.d.ts.map +1 -1
- package/dist/runner.js +307 -20
- package/package.json +3 -3
package/dist/acp-client.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ import { type AcpEventSink } from "./events.js";
|
|
|
7
7
|
import { type ElicitationResolver, type PermissionResolver, type ToolPolicy } from "./permissions.js";
|
|
8
8
|
import { UsageAccumulator } from "./usage.js";
|
|
9
9
|
import { type ClientHandlers } from "./client-handlers.js";
|
|
10
|
+
import { type AuthStore, type BackendAuthMachine, type ConnectionAuthStamp } from "./auth/auth-store.js";
|
|
10
11
|
interface RawResultSuccess {
|
|
11
12
|
type: string;
|
|
12
13
|
subtype: string;
|
|
@@ -99,6 +100,17 @@ export interface PooledConnectionDeps {
|
|
|
99
100
|
/** Initialize-time elicitation advertisement; fixed per connection, so it is driven by the
|
|
100
101
|
* runner-wide resolver rather than session-scoped responders attached later. */
|
|
101
102
|
advertiseElicitation?: boolean;
|
|
103
|
+
/** Initialize-time client auth advertisement (§1.2); fixed per connection like elicitation.
|
|
104
|
+
* Undefined (the default) omits the `auth` capability entirely — the default-OFF baseline. */
|
|
105
|
+
authCapabilities?: {
|
|
106
|
+
terminal?: boolean;
|
|
107
|
+
gateway?: boolean;
|
|
108
|
+
};
|
|
109
|
+
/** The runner's single auth store (§2). When present, this connection reconciles to the current
|
|
110
|
+
* intent at the end of `initialize` (replay for in-process creds), overlays the spawn env with
|
|
111
|
+
* collected `env_var` values, and carries a generation stamp the pool gates selection on.
|
|
112
|
+
* Undefined => no auth wiring, byte-identical to the pre-auth baseline (default-OFF). */
|
|
113
|
+
authStore?: AuthStore;
|
|
102
114
|
/** Client-side ACP fs/terminal handlers advertised once and routed by sessionId. */
|
|
103
115
|
clientHandlers?: ClientHandlers;
|
|
104
116
|
}
|
|
@@ -109,6 +121,8 @@ export interface PooledConnectionDeps {
|
|
|
109
121
|
*/
|
|
110
122
|
export declare class PooledConnection {
|
|
111
123
|
readonly backendId: BackendId;
|
|
124
|
+
/** Process-unique connection id, used only to tag `BackendAuthMachine` events (§2.3). */
|
|
125
|
+
readonly id: string;
|
|
112
126
|
/** The held ACP connection (fluent client() app); session/* calls go through its
|
|
113
127
|
* `agent` ClientContext via the typed wrappers below. */
|
|
114
128
|
private readonly connection;
|
|
@@ -119,6 +133,14 @@ export declare class PooledConnection {
|
|
|
119
133
|
private readonly onEvent;
|
|
120
134
|
private readonly clientHandlers;
|
|
121
135
|
private readonly advertiseElicitation;
|
|
136
|
+
private readonly authCapabilities;
|
|
137
|
+
private readonly authStore;
|
|
138
|
+
/** Which intent-generation THIS process reflects (§2.4). Starts at -1/false so a connection with
|
|
139
|
+
* no applied intent is stale against a machine that has ever advanced past generation 0. */
|
|
140
|
+
authStamp: ConnectionAuthStamp;
|
|
141
|
+
/** Set by the pool when a busy stale connection must be recycled once it drains (§2.6). While set,
|
|
142
|
+
* the connection is never handed a new session and is disposed-and-dropped on release. */
|
|
143
|
+
recyclePending: boolean;
|
|
122
144
|
/** Set true at the start of dispose() so the graceful-shutdown death is NOT reported as a crash. */
|
|
123
145
|
private disposing;
|
|
124
146
|
/** Resolves once `initialize` completed (or rejects if the process died first). */
|
|
@@ -151,6 +173,35 @@ export declare class PooledConnection {
|
|
|
151
173
|
/** Mark this connection dead exactly once, then ask the pool to evict it. Idempotent. */
|
|
152
174
|
private die;
|
|
153
175
|
private stderrSuffix;
|
|
176
|
+
/** Resolve this connection's `BackendAuthMachine` from the runner's store, or undefined when no
|
|
177
|
+
* store is wired (default-OFF) — the machine is keyed by the backend's poolKey (§2.3). */
|
|
178
|
+
private authMachine;
|
|
179
|
+
/** The client `auth` advertisement for THIS connection (§1.2), refined per-backend by the pure-data
|
|
180
|
+
* `AuthProfile.clientAuthCapabilities` (§3.1). When the host advertised nothing (default-OFF) the
|
|
181
|
+
* key is omitted verbatim — no profile is consulted, so behavior stays byte-identical. When the
|
|
182
|
+
* host opted in, the backend's profile maps the host affordances (`onAuth` ⇐ gateway desired,
|
|
183
|
+
* `terminal` ⇐ host TTY) onto the method TYPES this backend can actually service (e.g. codex never
|
|
184
|
+
* advertises terminal; opencode never advertises gateway). A custom backend has NO profile → the
|
|
185
|
+
* host's advertisement passes through unchanged (conformance-by-absence, §3.5). */
|
|
186
|
+
private effectiveAuthCapabilities;
|
|
187
|
+
/** Mark this connection current against `generation` (nothing more to apply). */
|
|
188
|
+
private stampApplied;
|
|
189
|
+
/** true iff the current intent is an in-process (gateway) cred, so an idle connection can be
|
|
190
|
+
* re-primed with an authenticate RPC replay instead of being recycled (§2.6). */
|
|
191
|
+
canLiveReapply(machine: BackendAuthMachine): boolean;
|
|
192
|
+
/** Reconcile this connection to the current intent at the end of `initialize` (§2.5). For an
|
|
193
|
+
* in-process cred, replay `authenticate({methodId,_meta})`; for disk/spawn-env a fresh process
|
|
194
|
+
* already carries the credential, so only stamp it current. */
|
|
195
|
+
private applyAuthIntent;
|
|
196
|
+
/** Idle in-process connection: re-send `authenticate` and re-stamp so the next session opens under
|
|
197
|
+
* the current gateway cred without a process recycle (§2.6). Returns true iff a re-apply ran. */
|
|
198
|
+
reapplyAuthIfStale(machine: BackendAuthMachine): Promise<boolean>;
|
|
199
|
+
/** Fire-and-forget idle live re-apply (§2.6). Any failure disposes the connection so the pool
|
|
200
|
+
* respawns a fresh process rather than serving a session under a failed replay. */
|
|
201
|
+
scheduleReapply(machine: BackendAuthMachine): void;
|
|
202
|
+
/** Mark a BUSY stale connection for recycle once it drains (§2.6): finish in-flight prompts under
|
|
203
|
+
* the auth they started with, then dispose-and-drop on release. */
|
|
204
|
+
markForRecycleWhenIdle(_machine: BackendAuthMachine): void;
|
|
154
205
|
/** Race a wire call against process death so a crash surfaces a clear error instead of hanging
|
|
155
206
|
* on a JSON-RPC response that will never come. */
|
|
156
207
|
race<T>(op: Promise<T>): Promise<T>;
|
package/dist/acp-client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"acp-client.d.ts","sourceRoot":"","sources":["../src/acp-client.ts"],"names":[],"mappings":"AAwBA,OAAO,EAOL,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,UAAU,EAQf,KAAK,yBAAyB,EAC9B,KAAK,YAAY,EACjB,KAAK,uBAAuB,EAC5B,KAAK,+BAA+B,EACpC,KAAK,kBAAkB,EACvB,KAAK,0BAA0B,EAC/B,KAAK,6BAA6B,EAGlC,KAAK,oBAAoB,EAEzB,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,EAG5B,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAG1B,KAAK,aAAa,EAClB,KAAK,cAAc,EAMnB,KAAK,aAAa,EAClB,KAAK,cAAc,EAMnB,KAAK,yBAAyB,EAG9B,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EAGxB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,6BAA6B,EAClC,KAAK,8BAA8B,EACnC,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAO5B,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAIL,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACrB,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACzE,OAAO,EAQL,KAAK,sBAAsB,EAC5B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAA2C,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AACzF,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,UAAU,EAChB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAIL,KAAK,cAAc,EAEpB,MAAM,sBAAsB,CAAC;AA0B9B,UAAU,gBAAgB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;
|
|
1
|
+
{"version":3,"file":"acp-client.d.ts","sourceRoot":"","sources":["../src/acp-client.ts"],"names":[],"mappings":"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"}
|
package/dist/acp-client.js
CHANGED
|
@@ -29,6 +29,7 @@ import { emitSessionUpdate } from "./events.js";
|
|
|
29
29
|
import { decidePermission, } from "./permissions.js";
|
|
30
30
|
import { UsageAccumulator } from "./usage.js";
|
|
31
31
|
import { clientCapabilitiesFor, hasFullMcpHandlers, } from "./client-handlers.js";
|
|
32
|
+
import { redactSecrets, } from "./auth/auth-store.js";
|
|
32
33
|
/** A benign client identity. NOT JetBrains/IntelliJ 2026.1 — that exact identity makes
|
|
33
34
|
* codex-acp disable session config options (our model/effort routing channel). */
|
|
34
35
|
const CLIENT_INFO = {
|
|
@@ -51,6 +52,8 @@ const GUARDED_STATEFUL_REQUESTS = new Map([
|
|
|
51
52
|
"no driven wrapper yet; raw forked sessions cannot be routed (permissions auto-cancel)",
|
|
52
53
|
],
|
|
53
54
|
]);
|
|
55
|
+
/** Monotonic seq for process-unique PooledConnection ids (auth-machine event tagging, §2.3). */
|
|
56
|
+
let nextConnectionSeq = 0;
|
|
54
57
|
const parseConnectMcpRequest = (params) => params;
|
|
55
58
|
const parseMessageMcpRequest = (params) => params;
|
|
56
59
|
const parseMessageMcpNotification = (params) => params;
|
|
@@ -633,6 +636,8 @@ function toolNameFromMeta(meta) {
|
|
|
633
636
|
*/
|
|
634
637
|
export class PooledConnection {
|
|
635
638
|
backendId;
|
|
639
|
+
/** Process-unique connection id, used only to tag `BackendAuthMachine` events (§2.3). */
|
|
640
|
+
id = `conn-${(nextConnectionSeq += 1)}`;
|
|
636
641
|
/** The held ACP connection (fluent client() app); session/* calls go through its
|
|
637
642
|
* `agent` ClientContext via the typed wrappers below. */
|
|
638
643
|
connection;
|
|
@@ -643,6 +648,14 @@ export class PooledConnection {
|
|
|
643
648
|
onEvent;
|
|
644
649
|
clientHandlers;
|
|
645
650
|
advertiseElicitation;
|
|
651
|
+
authCapabilities;
|
|
652
|
+
authStore;
|
|
653
|
+
/** Which intent-generation THIS process reflects (§2.4). Starts at -1/false so a connection with
|
|
654
|
+
* no applied intent is stale against a machine that has ever advanced past generation 0. */
|
|
655
|
+
authStamp = { appliedGeneration: -1, applied: false, trippedAuthRequired: false };
|
|
656
|
+
/** Set by the pool when a busy stale connection must be recycled once it drains (§2.6). While set,
|
|
657
|
+
* the connection is never handed a new session and is disposed-and-dropped on release. */
|
|
658
|
+
recyclePending = false;
|
|
646
659
|
/** Set true at the start of dispose() so the graceful-shutdown death is NOT reported as a crash. */
|
|
647
660
|
disposing = false;
|
|
648
661
|
/** Resolves once `initialize` completed (or rejects if the process died first). */
|
|
@@ -663,11 +676,20 @@ export class PooledConnection {
|
|
|
663
676
|
this.onEvent = deps.onEvent;
|
|
664
677
|
this.clientHandlers = deps.clientHandlers;
|
|
665
678
|
this.advertiseElicitation = deps.advertiseElicitation ?? Boolean(deps.elicitationResolver);
|
|
679
|
+
this.authCapabilities = deps.authCapabilities;
|
|
680
|
+
this.authStore = deps.authStore;
|
|
666
681
|
this.client = new MultiplexClient(this.backendId, this.onEvent, deps.clientHandlers, deps.permissionResolver, deps.elicitationResolver);
|
|
667
682
|
const { command, args, env } = backend.spawnConfig();
|
|
683
|
+
// Spawn-env auth overlay (§2.8): host-collected `env_var` values (and, for a profiled backend,
|
|
684
|
+
// its `spawnAuthEnv` contribution) stacked ABOVE the backend's own env. Undefined when nothing is
|
|
685
|
+
// held — byte-identical to today. Passed straight to spawn; never logged (§2.14, Principle 9).
|
|
686
|
+
const authOverlay = this.authStore?.spawnEnvFor(backend.poolKey ?? backend.id);
|
|
668
687
|
// NOTE: deliberately NO `cwd` here. cwd is per-SESSION (session/new), so one pooled process
|
|
669
688
|
// serves runs in different worktrees without losing isolation.
|
|
670
|
-
const child = spawn(command, args, {
|
|
689
|
+
const child = spawn(command, args, {
|
|
690
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
691
|
+
env: authOverlay ? { ...env, ...authOverlay } : env,
|
|
692
|
+
});
|
|
671
693
|
this.child = child;
|
|
672
694
|
if (!child.stdin || !child.stdout) {
|
|
673
695
|
throw new Error(`Failed to spawn ACP agent (${backend.id}): missing stdio pipes`);
|
|
@@ -809,6 +831,8 @@ export class PooledConnection {
|
|
|
809
831
|
this.client.settleAllPendingPermissions();
|
|
810
832
|
this.client.settleAllPendingElicitations();
|
|
811
833
|
this.client.disconnectAllMcpConnections();
|
|
834
|
+
// The dying connection's stamp is dropped with it; the machine's auth state is unchanged (§2.3).
|
|
835
|
+
this.authStore?.existing(this.backend.poolKey ?? this.backend.id)?.send({ t: "process_death", connectionId: this.id });
|
|
812
836
|
// A crash (not a graceful dispose) is worth surfacing for observability; the engine still
|
|
813
837
|
// handles it by retrying the run on a fresh process. Best-effort, after death is recorded.
|
|
814
838
|
if (this.onEvent && !this.disposing) {
|
|
@@ -817,9 +841,91 @@ export class PooledConnection {
|
|
|
817
841
|
this.onDead(this);
|
|
818
842
|
}
|
|
819
843
|
stderrSuffix() {
|
|
820
|
-
|
|
844
|
+
// Redact credential-shaped substrings before the tail can appear in any error suffix (§2.14):
|
|
845
|
+
// a spawned agent that echoes an injected env var to stderr must not leak it into an error.
|
|
846
|
+
const tail = redactSecrets(this.stderrTail).trim();
|
|
821
847
|
return tail ? `\n${tail}` : "";
|
|
822
848
|
}
|
|
849
|
+
/** Resolve this connection's `BackendAuthMachine` from the runner's store, or undefined when no
|
|
850
|
+
* store is wired (default-OFF) — the machine is keyed by the backend's poolKey (§2.3). */
|
|
851
|
+
authMachine() {
|
|
852
|
+
return this.authStore?.machineFor(this.backend.poolKey ?? this.backend.id, this.backend.authProfile);
|
|
853
|
+
}
|
|
854
|
+
/** The client `auth` advertisement for THIS connection (§1.2), refined per-backend by the pure-data
|
|
855
|
+
* `AuthProfile.clientAuthCapabilities` (§3.1). When the host advertised nothing (default-OFF) the
|
|
856
|
+
* key is omitted verbatim — no profile is consulted, so behavior stays byte-identical. When the
|
|
857
|
+
* host opted in, the backend's profile maps the host affordances (`onAuth` ⇐ gateway desired,
|
|
858
|
+
* `terminal` ⇐ host TTY) onto the method TYPES this backend can actually service (e.g. codex never
|
|
859
|
+
* advertises terminal; opencode never advertises gateway). A custom backend has NO profile → the
|
|
860
|
+
* host's advertisement passes through unchanged (conformance-by-absence, §3.5). */
|
|
861
|
+
effectiveAuthCapabilities() {
|
|
862
|
+
const base = this.authCapabilities;
|
|
863
|
+
if (!base)
|
|
864
|
+
return undefined; // default-OFF: omit `auth` entirely (byte-identical baseline)
|
|
865
|
+
const profile = this.backend.authProfile;
|
|
866
|
+
if (!profile)
|
|
867
|
+
return base;
|
|
868
|
+
return profile.clientAuthCapabilities({ onAuth: Boolean(base.gateway), terminal: Boolean(base.terminal) });
|
|
869
|
+
}
|
|
870
|
+
/** Mark this connection current against `generation` (nothing more to apply). */
|
|
871
|
+
stampApplied(generation) {
|
|
872
|
+
this.authStamp = { appliedGeneration: generation, applied: true, trippedAuthRequired: false };
|
|
873
|
+
}
|
|
874
|
+
/** true iff the current intent is an in-process (gateway) cred, so an idle connection can be
|
|
875
|
+
* re-primed with an authenticate RPC replay instead of being recycled (§2.6). */
|
|
876
|
+
canLiveReapply(machine) {
|
|
877
|
+
return machine.currentKlassIsInProcess();
|
|
878
|
+
}
|
|
879
|
+
/** Reconcile this connection to the current intent at the end of `initialize` (§2.5). For an
|
|
880
|
+
* in-process cred, replay `authenticate({methodId,_meta})`; for disk/spawn-env a fresh process
|
|
881
|
+
* already carries the credential, so only stamp it current. */
|
|
882
|
+
async applyAuthIntent(machine) {
|
|
883
|
+
if (machine.state !== "credentials_held" && machine.state !== "authenticated") {
|
|
884
|
+
this.stampApplied(machine.generation); // nothing to apply; mark current
|
|
885
|
+
return;
|
|
886
|
+
}
|
|
887
|
+
const intent = machine.intentView();
|
|
888
|
+
if (intent?.klass !== "in-process") {
|
|
889
|
+
// disk (native store) + spawn-env (env at spawn) need no RPC — a fresh process already has them.
|
|
890
|
+
this.stampApplied(machine.generation);
|
|
891
|
+
return;
|
|
892
|
+
}
|
|
893
|
+
const meta = machine.applyMeta();
|
|
894
|
+
try {
|
|
895
|
+
await this.rawAgentRequest(AGENT_METHODS.authenticate, {
|
|
896
|
+
methodId: intent.methodId,
|
|
897
|
+
...(meta ? { _meta: meta } : {}),
|
|
898
|
+
});
|
|
899
|
+
this.stampApplied(machine.generation);
|
|
900
|
+
machine.send({ t: "apply_ok", connectionId: this.id, generation: machine.generation });
|
|
901
|
+
}
|
|
902
|
+
catch (err) {
|
|
903
|
+
machine.send({ t: "apply_failed", connectionId: this.id, generation: machine.generation, error: err });
|
|
904
|
+
throw err; // -> AUTH_REQUIRED via §1.5; connection unusable
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
/** Idle in-process connection: re-send `authenticate` and re-stamp so the next session opens under
|
|
908
|
+
* the current gateway cred without a process recycle (§2.6). Returns true iff a re-apply ran. */
|
|
909
|
+
async reapplyAuthIfStale(machine) {
|
|
910
|
+
if (!machine.isStale(this.authStamp) || !this.canLiveReapply(machine))
|
|
911
|
+
return false;
|
|
912
|
+
await this.ready;
|
|
913
|
+
await this.applyAuthIntent(machine);
|
|
914
|
+
return true;
|
|
915
|
+
}
|
|
916
|
+
/** Fire-and-forget idle live re-apply (§2.6). Any failure disposes the connection so the pool
|
|
917
|
+
* respawns a fresh process rather than serving a session under a failed replay. */
|
|
918
|
+
scheduleReapply(machine) {
|
|
919
|
+
void this.reapplyAuthIfStale(machine).catch(() => {
|
|
920
|
+
this.recyclePending = true;
|
|
921
|
+
void this.dispose();
|
|
922
|
+
});
|
|
923
|
+
}
|
|
924
|
+
/** Mark a BUSY stale connection for recycle once it drains (§2.6): finish in-flight prompts under
|
|
925
|
+
* the auth they started with, then dispose-and-drop on release. */
|
|
926
|
+
markForRecycleWhenIdle(_machine) {
|
|
927
|
+
this.recyclePending = true;
|
|
928
|
+
}
|
|
823
929
|
/** Race a wire call against process death so a crash surfaces a clear error instead of hanging
|
|
824
930
|
* on a JSON-RPC response that will never come. */
|
|
825
931
|
async race(op) {
|
|
@@ -854,6 +960,8 @@ export class PooledConnection {
|
|
|
854
960
|
// this runner. Omitted flags are unsupported; false flags are never sent deliberately.
|
|
855
961
|
clientCapabilities: clientCapabilitiesFor(this.clientHandlers, {
|
|
856
962
|
elicitation: this.advertiseElicitation,
|
|
963
|
+
// Per-backend profile refinement (§1.2/§3.1); undefined => no `auth` key emitted (default-OFF).
|
|
964
|
+
auth: this.effectiveAuthCapabilities(),
|
|
857
965
|
}),
|
|
858
966
|
clientInfo: { ...CLIENT_INFO },
|
|
859
967
|
})),
|
|
@@ -872,6 +980,15 @@ export class PooledConnection {
|
|
|
872
980
|
`this client (protocol v${PROTOCOL_VERSION}) does not support — closing the connection.${this.stderrSuffix()}`, WorkflowErrorCode.SCRIPT_VALIDATION_ERROR, { recoverable: false });
|
|
873
981
|
}
|
|
874
982
|
this.negotiated = negotiated;
|
|
983
|
+
// Reconcile this connection to the current auth intent (§2.5). Runs identically on pooled,
|
|
984
|
+
// dedicated, and interactive connections — the intent is durable in the AuthStore, so a fresh
|
|
985
|
+
// process always re-primes an in-process (gateway) credential here, which is the direct fix
|
|
986
|
+
// for the dispose-after-authenticate bug (gap 3). Disk/spawn-env intents are only stamped.
|
|
987
|
+
const machine = this.authMachine();
|
|
988
|
+
if (machine) {
|
|
989
|
+
machine.send({ t: "initialize_ok", connectionId: this.id, advertised: negotiated.authMethods });
|
|
990
|
+
await this.applyAuthIntent(machine);
|
|
991
|
+
}
|
|
875
992
|
}
|
|
876
993
|
finally {
|
|
877
994
|
clearTimeout(timer);
|
|
@@ -1108,6 +1225,14 @@ export class PooledConnection {
|
|
|
1108
1225
|
this.client.unregister(sessionId);
|
|
1109
1226
|
if (this._activeSessions > 0)
|
|
1110
1227
|
this._activeSessions -= 1;
|
|
1228
|
+
// Generation-gated recycle (§2.6): a stale connection marked for recycle while busy is
|
|
1229
|
+
// disposed-and-dropped the moment it drains, instead of returning to the pool, so the next
|
|
1230
|
+
// acquire lands on a fresh process that primes the current intent at initialize. dispose()
|
|
1231
|
+
// drops it via the onDead path.
|
|
1232
|
+
if (this.recyclePending && this._activeSessions === 0 && this._alive) {
|
|
1233
|
+
void this.dispose();
|
|
1234
|
+
return;
|
|
1235
|
+
}
|
|
1111
1236
|
// keepOpen: the caller intends to re-open this session later (session/load|resume), so the
|
|
1112
1237
|
// agent-persisted session must be left untouched — skip the best-effort close entirely.
|
|
1113
1238
|
if (keepOpen || !this.negotiated?.supportsClose || !this._alive)
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { AuthMethod } from "@agentclientprotocol/sdk";
|
|
2
|
+
import type { ClientCapabilityOptions } from "../client-handlers.js";
|
|
3
|
+
import type { AuthMethodDescriptor, AuthResolution } from "./auth-types.js";
|
|
4
|
+
import type { AuthIntent } from "./auth-store.js";
|
|
5
|
+
/** The spawnable interactive login a host runs in a TTY. Identical to the `launch` member of the
|
|
6
|
+
* `terminal` `AuthMethodDescriptor` (§1.3). */
|
|
7
|
+
export interface TerminalLaunch {
|
|
8
|
+
command: string;
|
|
9
|
+
args: string[];
|
|
10
|
+
env?: Record<string, string>;
|
|
11
|
+
label?: string;
|
|
12
|
+
}
|
|
13
|
+
/** Per-agent adapter (§3.1). Every field is DATA/ENRICHMENT only — none gates the base flow. A backend
|
|
14
|
+
* with NO profile runs the base flow verbatim (conformance-by-absence). Built-in profiles are wired
|
|
15
|
+
* onto their backend in PR7; `custom.ts` leaves `Backend.authProfile` undefined. */
|
|
16
|
+
export interface AuthProfile {
|
|
17
|
+
readonly backendId: string;
|
|
18
|
+
/** Which auth method TYPES to advertise for this backend, given host affordances. Refines the
|
|
19
|
+
* runner default derivation in §1.2; still connection-lifetime-fixed. `host.onAuth` = the host can
|
|
20
|
+
* complete an in-process (gateway) auth; `host.terminal` = the host has a real TTY. */
|
|
21
|
+
clientAuthCapabilities(host: {
|
|
22
|
+
onAuth: boolean;
|
|
23
|
+
terminal: boolean;
|
|
24
|
+
}): ClientCapabilityOptions["auth"];
|
|
25
|
+
/** Enrich/label the base descriptor for one advertised method. MUST delegate type dispatch to the
|
|
26
|
+
* §1.3 `buildAuthDescriptors` dispatcher (it receives the already-dispatched `base`); may only
|
|
27
|
+
* override name/description/label. */
|
|
28
|
+
describe(method: AuthMethod, base: AuthMethodDescriptor): AuthMethodDescriptor;
|
|
29
|
+
/** Terminal launch override; base falls back to §1.3's launch-resolution order. */
|
|
30
|
+
terminalLaunch?(method: Extract<AuthMethod, {
|
|
31
|
+
type: "terminal";
|
|
32
|
+
}>): TerminalLaunch;
|
|
33
|
+
/** Wrap a `{outcome:"meta"}` resolution into the agent's expected authenticate `_meta`. */
|
|
34
|
+
buildMeta?(method: AuthMethod, resolution: Extract<AuthResolution, {
|
|
35
|
+
outcome: "meta";
|
|
36
|
+
}>): Record<string, unknown>;
|
|
37
|
+
/** OPTIONAL spawn-env overlay contributed regardless of `klass` (§2.8, Principle 9). Codex only —
|
|
38
|
+
* the `DEFAULT_AUTH_REQUEST` lever channel. Secret; consumed inside `AuthStore.spawnEnvFor`, never
|
|
39
|
+
* logged. */
|
|
40
|
+
spawnAuthEnv?(intent: AuthIntent): Record<string, string> | undefined;
|
|
41
|
+
}
|
|
42
|
+
/** Claude Code — `@agentclientprotocol/claude-agent-acp` 0.57.0 (§3.2). Reveals its `terminal` login
|
|
43
|
+
* methods on `auth.terminal===true` OR `_meta["terminal-auth"]===true`, and its `gateway`/
|
|
44
|
+
* `gateway-bedrock` `agent`-type methods on `auth._meta.gateway===true`, so terminal follows the
|
|
45
|
+
* host TTY and gateway follows an `onAuth` resolver. `describe`/`buildMeta` are client-side identity:
|
|
46
|
+
* the base dispatcher already produces the correct descriptor and the gateway payload passes through
|
|
47
|
+
* unchanged. No `spawnAuthEnv` — Claude has no `DEFAULT_AUTH_REQUEST`-style pre-auth channel and is
|
|
48
|
+
* consumed client-side only (§3.2 spawn-time). */
|
|
49
|
+
export declare const claudeAuthProfile: AuthProfile;
|
|
50
|
+
/** Codex — `@automatalabs/codex-acp` 1.4.x, our fork (§3.3). Advertises no `terminal` method (its
|
|
51
|
+
* `api-key` reads env internally and `chat-gpt`/`gateway` are `agent`-type), so terminal is always
|
|
52
|
+
* false; `gateway` follows an `onAuth` resolver. The `spawnAuthEnv` lever emits `DEFAULT_AUTH_REQUEST`
|
|
53
|
+
* for `api-key`/`gateway` intents so a freshly recycled process pre-authenticates before its first
|
|
54
|
+
* gated request — layered on top of the universal replay (§2.5), never replacing it and never
|
|
55
|
+
* required for correctness (§2.8/§3.3). */
|
|
56
|
+
export declare const codexAuthProfile: AuthProfile;
|
|
57
|
+
/** OpenCode — `opencode-ai` 1.17.14 (§3.4). Advertises exactly one `opencode-login` method that is
|
|
58
|
+
* semantically terminal (it carries a `_meta["terminal-auth"]` launch hint when the host has a TTY),
|
|
59
|
+
* and no gateway/`env_var`/logout auth surface. So terminal follows the host TTY and gateway is
|
|
60
|
+
* always false. `describe` is client-side identity; no `buildMeta` (no meta method) and no
|
|
61
|
+
* `spawnAuthEnv` (no `DEFAULT_AUTH_REQUEST` analog; §3.4 spawn-time). */
|
|
62
|
+
export declare const opencodeAuthProfile: AuthProfile;
|
|
63
|
+
//# sourceMappingURL=auth-profiles.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-profiles.d.ts","sourceRoot":"","sources":["../../src/auth/auth-profiles.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,KAAK,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAC5E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD;gDACgD;AAChD,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;qFAEqF;AACrF,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;4FAEwF;IACxF,sBAAsB,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,GAAG,uBAAuB,CAAC,MAAM,CAAC,CAAC;IACtG;;2CAEuC;IACvC,QAAQ,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,oBAAoB,GAAG,oBAAoB,CAAC;IAC/E,mFAAmF;IACnF,cAAc,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,UAAU,EAAE;QAAE,IAAI,EAAE,UAAU,CAAA;KAAE,CAAC,GAAG,cAAc,CAAC;IACnF,2FAA2F;IAC3F,SAAS,CAAC,CAAC,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,CAAC,cAAc,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClH;;kBAEc;IACd,YAAY,CAAC,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC;CACvE;AAED;;;;;;mDAMmD;AACnD,eAAO,MAAM,iBAAiB,EAAE,WAK/B,CAAC;AAEF;;;;;4CAK4C;AAC5C,eAAO,MAAM,gBAAgB,EAAE,WAc9B,CAAC;AAEF;;;;0EAI0E;AAC1E,eAAO,MAAM,mBAAmB,EAAE,WAIjC,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/** Claude Code — `@agentclientprotocol/claude-agent-acp` 0.57.0 (§3.2). Reveals its `terminal` login
|
|
2
|
+
* methods on `auth.terminal===true` OR `_meta["terminal-auth"]===true`, and its `gateway`/
|
|
3
|
+
* `gateway-bedrock` `agent`-type methods on `auth._meta.gateway===true`, so terminal follows the
|
|
4
|
+
* host TTY and gateway follows an `onAuth` resolver. `describe`/`buildMeta` are client-side identity:
|
|
5
|
+
* the base dispatcher already produces the correct descriptor and the gateway payload passes through
|
|
6
|
+
* unchanged. No `spawnAuthEnv` — Claude has no `DEFAULT_AUTH_REQUEST`-style pre-auth channel and is
|
|
7
|
+
* consumed client-side only (§3.2 spawn-time). */
|
|
8
|
+
export const claudeAuthProfile = {
|
|
9
|
+
backendId: "claude",
|
|
10
|
+
clientAuthCapabilities: ({ onAuth, terminal }) => ({ terminal, gateway: onAuth }),
|
|
11
|
+
describe: (_method, base) => base,
|
|
12
|
+
buildMeta: (_method, resolution) => resolution.meta,
|
|
13
|
+
};
|
|
14
|
+
/** Codex — `@automatalabs/codex-acp` 1.4.x, our fork (§3.3). Advertises no `terminal` method (its
|
|
15
|
+
* `api-key` reads env internally and `chat-gpt`/`gateway` are `agent`-type), so terminal is always
|
|
16
|
+
* false; `gateway` follows an `onAuth` resolver. The `spawnAuthEnv` lever emits `DEFAULT_AUTH_REQUEST`
|
|
17
|
+
* for `api-key`/`gateway` intents so a freshly recycled process pre-authenticates before its first
|
|
18
|
+
* gated request — layered on top of the universal replay (§2.5), never replacing it and never
|
|
19
|
+
* required for correctness (§2.8/§3.3). */
|
|
20
|
+
export const codexAuthProfile = {
|
|
21
|
+
backendId: "codex",
|
|
22
|
+
clientAuthCapabilities: ({ onAuth }) => ({ terminal: false, gateway: onAuth }),
|
|
23
|
+
describe: (_method, base) => base,
|
|
24
|
+
buildMeta: (_method, resolution) => resolution.meta,
|
|
25
|
+
spawnAuthEnv(intent) {
|
|
26
|
+
// Only api-key and gateway intents drive the codex pre-auth channel (§3.3). `authenticateMeta` is
|
|
27
|
+
// SECRET and undefined for the env-only api-key path — the base overlay injects that key's env.
|
|
28
|
+
if (intent.methodId !== "api-key" && intent.methodId !== "gateway")
|
|
29
|
+
return undefined;
|
|
30
|
+
const meta = intent.authenticateMeta;
|
|
31
|
+
return {
|
|
32
|
+
DEFAULT_AUTH_REQUEST: JSON.stringify({ methodId: intent.methodId, ...(meta ? { _meta: meta } : {}) }),
|
|
33
|
+
};
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
/** OpenCode — `opencode-ai` 1.17.14 (§3.4). Advertises exactly one `opencode-login` method that is
|
|
37
|
+
* semantically terminal (it carries a `_meta["terminal-auth"]` launch hint when the host has a TTY),
|
|
38
|
+
* and no gateway/`env_var`/logout auth surface. So terminal follows the host TTY and gateway is
|
|
39
|
+
* always false. `describe` is client-side identity; no `buildMeta` (no meta method) and no
|
|
40
|
+
* `spawnAuthEnv` (no `DEFAULT_AUTH_REQUEST` analog; §3.4 spawn-time). */
|
|
41
|
+
export const opencodeAuthProfile = {
|
|
42
|
+
backendId: "opencode",
|
|
43
|
+
clientAuthCapabilities: ({ terminal }) => ({ terminal, gateway: false }),
|
|
44
|
+
describe: (_method, base) => base,
|
|
45
|
+
};
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import type { AuthMethod } from "@agentclientprotocol/sdk";
|
|
2
|
+
import type { AuthProfile } from "./auth-profiles.js";
|
|
3
|
+
export type AuthMethodType = "agent" | "terminal" | "env_var";
|
|
4
|
+
/** The three-value strategy that collapses onto the two credential classes (§2.1):
|
|
5
|
+
* "disk" -> disk-persisted; apply on a fresh connection = NOTHING.
|
|
6
|
+
* "in-process" -> per-spawn via authenticate RPC replay (§2.5).
|
|
7
|
+
* "spawn-env" -> per-spawn via env injection + recycle (§2.8). */
|
|
8
|
+
export type CredentialClass = "disk" | "in-process" | "spawn-env";
|
|
9
|
+
/** Type-driven, agent-agnostic classification (§2.1). Keys ONLY on the method type + whether the
|
|
10
|
+
* advertised `_meta` is gateway-shaped — never on an agent id. */
|
|
11
|
+
export declare function classifyCredential(methodType: AuthMethodType, advertisedMeta: Record<string, unknown> | null | undefined): {
|
|
12
|
+
klass: CredentialClass;
|
|
13
|
+
diskBacked: boolean;
|
|
14
|
+
};
|
|
15
|
+
/** The host's completed auth choice, recorded as ONE immutable intent. This is the only place
|
|
16
|
+
* credential material lives in the library — never written to a journal, emitted in an event, or
|
|
17
|
+
* logged (§2.14). */
|
|
18
|
+
export interface AuthIntent {
|
|
19
|
+
readonly backendId: string;
|
|
20
|
+
readonly poolKey: string;
|
|
21
|
+
readonly methodId: string;
|
|
22
|
+
readonly methodType: AuthMethodType;
|
|
23
|
+
readonly klass: CredentialClass;
|
|
24
|
+
/** SECRET. The `_meta` payload for the chosen method (e.g. claude `{ gateway: { baseUrl, headers } }`
|
|
25
|
+
* or codex `{ "api-key": { apiKey } }`). Populated for BOTH in-process and disk intents; how it is
|
|
26
|
+
* consumed depends on `klass`, not on whether it is set. */
|
|
27
|
+
readonly authenticateMeta?: Record<string, unknown>;
|
|
28
|
+
/** SECRET; spawn-env only. Env values injected at agent spawn. */
|
|
29
|
+
readonly envValues?: Record<string, string>;
|
|
30
|
+
/** klass === "disk": a fresh process re-reads the native store; survives cold resume (§2.13). */
|
|
31
|
+
readonly diskBacked: boolean;
|
|
32
|
+
}
|
|
33
|
+
/** The connection-level record of which intent-generation THIS process reflects (§2.4). */
|
|
34
|
+
export interface ConnectionAuthStamp {
|
|
35
|
+
appliedGeneration: number;
|
|
36
|
+
applied: boolean;
|
|
37
|
+
trippedAuthRequired: boolean;
|
|
38
|
+
}
|
|
39
|
+
export type BackendAuthState = "unauthenticated" | "credentials_held" | "authenticated" | "auth_required";
|
|
40
|
+
export type AuthEvent = {
|
|
41
|
+
t: "initialize_ok";
|
|
42
|
+
connectionId: string;
|
|
43
|
+
advertised: readonly AuthMethod[];
|
|
44
|
+
} | {
|
|
45
|
+
t: "host_authenticate";
|
|
46
|
+
intent: AuthIntent;
|
|
47
|
+
} | {
|
|
48
|
+
t: "apply_ok";
|
|
49
|
+
connectionId: string;
|
|
50
|
+
generation: number;
|
|
51
|
+
} | {
|
|
52
|
+
t: "apply_failed";
|
|
53
|
+
connectionId: string;
|
|
54
|
+
generation: number;
|
|
55
|
+
error: unknown;
|
|
56
|
+
} | {
|
|
57
|
+
t: "auth_required_tripped";
|
|
58
|
+
connectionId: string;
|
|
59
|
+
error: unknown;
|
|
60
|
+
} | {
|
|
61
|
+
t: "logout";
|
|
62
|
+
} | {
|
|
63
|
+
t: "process_death";
|
|
64
|
+
connectionId: string;
|
|
65
|
+
};
|
|
66
|
+
/** Redacted, secret-free projection of an intent — ids/types/klass only (§2.14). */
|
|
67
|
+
export type RedactedIntent = Readonly<Omit<AuthIntent, "authenticateMeta" | "envValues">>;
|
|
68
|
+
/** One state machine per `poolKey`, owned by the `AuthStore`. The single source of auth truth. */
|
|
69
|
+
export declare class BackendAuthMachine {
|
|
70
|
+
private _state;
|
|
71
|
+
private _generation;
|
|
72
|
+
private _intent;
|
|
73
|
+
private _advertised;
|
|
74
|
+
get state(): BackendAuthState;
|
|
75
|
+
get generation(): number;
|
|
76
|
+
/** The advertised methods most recently observed at `initialize` (redaction source for status). */
|
|
77
|
+
get advertised(): readonly AuthMethod[];
|
|
78
|
+
get authenticated(): boolean;
|
|
79
|
+
/** Redacted view — ids/types/klass only, NEVER authenticateMeta/envValues. */
|
|
80
|
+
intentView(): RedactedIntent | undefined;
|
|
81
|
+
/** SECRET accessor — connection-internal only (used by applyAuthIntent, §2.5). */
|
|
82
|
+
applyMeta(): Record<string, unknown> | undefined;
|
|
83
|
+
/** SECRET accessor — pool/connection-internal only (used by spawnEnvFor, §2.8). */
|
|
84
|
+
spawnEnv(): Record<string, string> | undefined;
|
|
85
|
+
/** SECRET accessor — module-internal only (AuthStore.spawnEnvFor passes it to a profile). */
|
|
86
|
+
rawIntent(): AuthIntent | undefined;
|
|
87
|
+
/** Cold-resume re-arm predicate (§2.13): resumable iff creds are held/applied OR disk-backed. */
|
|
88
|
+
canResume(): boolean;
|
|
89
|
+
isStale(stamp: ConnectionAuthStamp): boolean;
|
|
90
|
+
/** true iff the current intent is an in-process (gateway) cred that can be live-re-applied on an
|
|
91
|
+
* idle connection via an authenticate RPC replay, rather than requiring a process recycle. */
|
|
92
|
+
currentKlassIsInProcess(): boolean;
|
|
93
|
+
send(ev: AuthEvent): void;
|
|
94
|
+
}
|
|
95
|
+
/** The single per-runner auth store. Owns one `BackendAuthMachine` per `poolKey` and records the
|
|
96
|
+
* (optional) per-backend `AuthProfile` so `spawnEnvFor` can consult it. */
|
|
97
|
+
export declare class AuthStore {
|
|
98
|
+
private readonly machines;
|
|
99
|
+
private readonly profiles;
|
|
100
|
+
/** Get/create the machine for a `poolKey`, recording the backend's profile the first time. */
|
|
101
|
+
machineFor(poolKey: string, profile?: AuthProfile): BackendAuthMachine;
|
|
102
|
+
/** The machine for a `poolKey`, or undefined if none has been created yet (read-only lookup). */
|
|
103
|
+
existing(poolKey: string): BackendAuthMachine | undefined;
|
|
104
|
+
/** Every `poolKey` that has a machine (the touched backends). */
|
|
105
|
+
poolKeys(): string[];
|
|
106
|
+
/** The spawn-env overlay (§2.8): the machine's `env_var` collected values merged with the backend
|
|
107
|
+
* profile's `spawnAuthEnv(intent)` contribution. Undefined when neither applies. Secret — passed
|
|
108
|
+
* straight to `spawn`, never logged. */
|
|
109
|
+
spawnEnvFor(poolKey: string): Record<string, string> | undefined;
|
|
110
|
+
}
|
|
111
|
+
export declare function redactSecrets(text: string): string;
|
|
112
|
+
//# sourceMappingURL=auth-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-store.d.ts","sourceRoot":"","sources":["../../src/auth/auth-store.ts"],"names":[],"mappings":"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"}
|