@automatalabs/acp-agents 0.21.1 → 0.22.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.
- 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/errors-map.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors-map.d.ts","sourceRoot":"","sources":["../src/errors-map.ts"],"names":[],"mappings":"AAYA,OAAO,EAA0C,aAAa,EAAqB,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"errors-map.d.ts","sourceRoot":"","sources":["../src/errors-map.ts"],"names":[],"mappings":"AAYA,OAAO,EAA0C,aAAa,EAAqB,MAAM,4BAA4B,CAAC;AAEtH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAE3D,eAAO,MAAM,4BAA4B,SAAS,CAAC;AAQnD,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;CACrC;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAahD;AAED,8EAA8E;AAC9E,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,eAAe,GAAG,aAAa,CAsCvG"}
|
package/dist/errors-map.js
CHANGED
|
@@ -12,6 +12,11 @@
|
|
|
12
12
|
// AGENT_EMPTY_OUTPUT) pass through unchanged.
|
|
13
13
|
import { classifyProviderLimit, isWorkflowError, WorkflowError, WorkflowErrorCode } from "@automatalabs/shared-types";
|
|
14
14
|
export const ACP_AUTH_REQUIRED_ERROR_CODE = -32000;
|
|
15
|
+
// JSON-RPC codes the SDK reserves for NON-auth failures (jsonrpc.js:764-829). A different reserved
|
|
16
|
+
// code that merely mentions the auth phrase must NEVER mis-route to pause-for-auth. -32000 is
|
|
17
|
+
// deliberately EXCLUDED — it is the primary auth code (reserved exclusively for authRequired,
|
|
18
|
+
// jsonrpc.js:818-823) and is matched code-only above the fallback.
|
|
19
|
+
const OTHER_RESERVED = new Set([-32700, -32600, -32601, -32602, -32603, -32800, -32002]);
|
|
15
20
|
export function errorText(error) {
|
|
16
21
|
if (error instanceof Error)
|
|
17
22
|
return error.message;
|
|
@@ -38,9 +43,19 @@ export function mapThrownError(error, labelOrContext) {
|
|
|
38
43
|
const context = typeof labelOrContext === "string" ? { label: labelOrContext } : (labelOrContext ?? {});
|
|
39
44
|
const message = errorText(error);
|
|
40
45
|
if (isAcpAuthRequired(error, message)) {
|
|
46
|
+
// authContext sources ONLY agent-advertised AuthMethod fields (ids/types/names) — never our
|
|
47
|
+
// sent _meta/env values (Principle 9). This is the machine-readable contract every downstream
|
|
48
|
+
// host reads; the enriched message is human-readable only.
|
|
49
|
+
const methods = (context.authMethods ?? []).map((m) => ({
|
|
50
|
+
id: m.id,
|
|
51
|
+
// AuthMethodAgent carries no `type` field (the SDK treats a missing discriminant as "agent").
|
|
52
|
+
type: ("type" in m ? m.type : undefined) ?? "agent",
|
|
53
|
+
name: m.name,
|
|
54
|
+
}));
|
|
41
55
|
return new WorkflowError(authRequiredMessage(message, context), WorkflowErrorCode.AUTH_REQUIRED, {
|
|
42
56
|
recoverable: false,
|
|
43
57
|
agentLabel: context.label,
|
|
58
|
+
authContext: { backendId: context.backendId, methods },
|
|
44
59
|
details: error,
|
|
45
60
|
});
|
|
46
61
|
}
|
|
@@ -55,8 +70,17 @@ export function mapThrownError(error, labelOrContext) {
|
|
|
55
70
|
});
|
|
56
71
|
}
|
|
57
72
|
function isAcpAuthRequired(error, message) {
|
|
58
|
-
|
|
59
|
-
|
|
73
|
+
const code = error?.code;
|
|
74
|
+
// PRIMARY (spec-faithful): -32000 is reserved EXCLUSIVELY for authRequired (jsonrpc.js:818-823;
|
|
75
|
+
// no other constructor in jsonrpc.js:764-829 emits it). Code alone, ANY message — this unblocks
|
|
76
|
+
// conformant agents that localize or rephrase the text.
|
|
77
|
+
if (code === ACP_AUTH_REQUIRED_ERROR_CODE)
|
|
78
|
+
return true;
|
|
79
|
+
// FALLBACK: a non-conformant agent that signals auth in prose without the reserved code. A
|
|
80
|
+
// DIFFERENT reserved code that merely mentions the phrase must NEVER mis-route to pause-for-auth.
|
|
81
|
+
return typeof code === "number"
|
|
82
|
+
? !OTHER_RESERVED.has(code) && /\bauthentication required\b/i.test(message)
|
|
83
|
+
: /\bauthentication required\b/i.test(message);
|
|
60
84
|
}
|
|
61
85
|
function authRequiredMessage(message, context) {
|
|
62
86
|
const backend = context.backendId ? ` (${context.backendId})` : "";
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
export { AcpAgentRunner, createAcpRunner, selectBackend } from "./runner.js";
|
|
2
|
-
export type { AcpRunnerOptions, AuthenticateOptions, AuthMethodsOptions, DisableProviderOptions, DeleteSessionOptions, ListProvidersOptions, ListSessionsOptions, LogoutOptions, ReattachSessionOptions, SetProviderOptions, } from "./runner.js";
|
|
2
|
+
export type { AcpRunnerOptions, AuthenticateOptions, AuthMethodsOptions, AuthCapableRunner, AuthController, AuthOutcome, AuthStatusSnapshot, CompleteAuthOptions, DisableProviderOptions, DeleteSessionOptions, ListProvidersOptions, ListSessionsOptions, LogoutOptions, ReattachSessionOptions, SetProviderOptions, } from "./runner.js";
|
|
3
|
+
export { buildAuthDescriptor, buildAuthDescriptors, isGatewayShapedMeta } from "./auth/auth-types.js";
|
|
4
|
+
export type { AuthContext, AuthMethodDescriptor, AuthResolution, AuthResolver } from "./auth/auth-types.js";
|
|
5
|
+
export { AuthStore, BackendAuthMachine, classifyCredential, redactSecrets, } from "./auth/auth-store.js";
|
|
6
|
+
export type { AuthEvent, AuthIntent, AuthMethodType, BackendAuthState, ConnectionAuthStamp, CredentialClass, RedactedIntent, } from "./auth/auth-store.js";
|
|
7
|
+
export { claudeAuthProfile, codexAuthProfile, opencodeAuthProfile } from "./auth/auth-profiles.js";
|
|
8
|
+
export type { AuthProfile, TerminalLaunch } from "./auth/auth-profiles.js";
|
|
3
9
|
export { InteractiveSession } from "./interactive.js";
|
|
4
10
|
export type { InteractiveSessionOptions, InteractiveTurn } from "./interactive.js";
|
|
5
11
|
export { AGENT_METHODS, CLIENT_METHODS } from "@agentclientprotocol/sdk";
|
|
@@ -8,8 +14,8 @@ export { BACKENDS_ENV, registryWithRunBackends, resolveBackendRegistry } from ".
|
|
|
8
14
|
export type { BackendRegistry, CustomBackendConfig, RegisteredBackend } from "./registry.js";
|
|
9
15
|
export { PooledConnection, SessionHandle } from "./acp-client.js";
|
|
10
16
|
export type { AcpSessionOptions, PooledConnectionDeps } from "./acp-client.js";
|
|
11
|
-
export { AGENT_METHOD_COVERAGE, CLIENT_METHOD_COVERAGE } from "./protocol-coverage.js";
|
|
12
|
-
export type { AgentMethodCoverage, ClientMethodCoverage } from "./protocol-coverage.js";
|
|
17
|
+
export { AGENT_METHOD_COVERAGE, ACP_AUTH_REQUIRED_CODE_EXCLUSIVE, AUTH_CAPABILITY_KEYS, AUTH_META_CONVENTION_KEYS, AUTH_META_MATRIX, CLIENT_METHOD_COVERAGE, CODEX_SPAWN_AUTH_ENV, HANDLED_AUTH_METHOD_TYPES, assertAuthCapabilityShape, } from "./protocol-coverage.js";
|
|
18
|
+
export type { AgentMethodCoverage, AuthMetaMatrixRow, ClientMethodCoverage } from "./protocol-coverage.js";
|
|
13
19
|
export { GATED_CUSTOM_META_KEYS, adaptPromptContent, gateCustomMeta, isSupportedProtocolVersion, negotiateCapabilities, unsupportedMcpServer, } from "./capabilities.js";
|
|
14
20
|
export type { NegotiatedCapabilities } from "./capabilities.js";
|
|
15
21
|
export { AcpAgentPool, resolvePoolSize } from "./pool.js";
|
|
@@ -23,8 +29,8 @@ export { ClaudeBackend } from "./backends/claude.js";
|
|
|
23
29
|
export { CodexBackend } from "./backends/codex.js";
|
|
24
30
|
export { OpenCodeBackend } from "./backends/opencode.js";
|
|
25
31
|
export { CustomAcpBackend } from "./backends/custom.js";
|
|
26
|
-
export { decidePermission } from "./permissions.js";
|
|
27
|
-
export type { ElicitationResolver, PermissionResolver, ToolPolicy } from "./permissions.js";
|
|
32
|
+
export { decidePermission, resolvePermission, withPersist } from "./permissions.js";
|
|
33
|
+
export type { ElicitationResolver, PermissionPersist, PermissionResolution, PermissionResolver, ToolPolicy, } from "./permissions.js";
|
|
28
34
|
export { UsageAccumulator } from "./usage.js";
|
|
29
35
|
export type { AgentSessionRef, McpAcpServerConfig, McpServerConfig } from "@automatalabs/shared-types";
|
|
30
36
|
export { toAnthropicJsonSchema, toJsonSchema, toStrictJsonSchema } from "./schema-strict.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC7E,YAAY,EACV,gBAAgB,EAChB,mBAAmB,EACnB,kBAAkB,EAClB,sBAAsB,EACtB,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,EACnB,aAAa,EACb,sBAAsB,EACtB,kBAAkB,GACnB,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -5,12 +5,18 @@
|
|
|
5
5
|
// @automatalabs/workflow-engine; the two siblings meet ONLY at AgentRunner, injected by the
|
|
6
6
|
// @automatalabs/workflows facade (which mcp-server builds on) via createAcpRunner().
|
|
7
7
|
export { AcpAgentRunner, createAcpRunner, selectBackend } from "./runner.js";
|
|
8
|
+
// Type-driven auth contracts (§1.3) and the AuthStore lifecycle spine (§2).
|
|
9
|
+
export { buildAuthDescriptor, buildAuthDescriptors, isGatewayShapedMeta } from "./auth/auth-types.js";
|
|
10
|
+
export { AuthStore, BackendAuthMachine, classifyCredential, redactSecrets, } from "./auth/auth-store.js";
|
|
11
|
+
// Per-agent auth profiles (§3): the pure-data adapters wired onto the built-in backends. Custom
|
|
12
|
+
// backends supply none (conformance-by-absence, §3.5).
|
|
13
|
+
export { claudeAuthProfile, codexAuthProfile, opencodeAuthProfile } from "./auth/auth-profiles.js";
|
|
8
14
|
export { InteractiveSession } from "./interactive.js";
|
|
9
15
|
export { AGENT_METHODS, CLIENT_METHODS } from "@agentclientprotocol/sdk";
|
|
10
16
|
// The custom-backend registry: run ANY ACP agent as an agent() target.
|
|
11
17
|
export { BACKENDS_ENV, registryWithRunBackends, resolveBackendRegistry } from "./registry.js";
|
|
12
18
|
export { PooledConnection, SessionHandle } from "./acp-client.js";
|
|
13
|
-
export { AGENT_METHOD_COVERAGE, CLIENT_METHOD_COVERAGE } from "./protocol-coverage.js";
|
|
19
|
+
export { AGENT_METHOD_COVERAGE, ACP_AUTH_REQUIRED_CODE_EXCLUSIVE, AUTH_CAPABILITY_KEYS, AUTH_META_CONVENTION_KEYS, AUTH_META_MATRIX, CLIENT_METHOD_COVERAGE, CODEX_SPAWN_AUTH_ENV, HANDLED_AUTH_METHOD_TYPES, assertAuthCapabilityShape, } from "./protocol-coverage.js";
|
|
14
20
|
// ACP capability negotiation: parse/validate the initialize response and gate what the client
|
|
15
21
|
// sends (custom `_meta` keys, MCP transports) on what the connected agent advertised.
|
|
16
22
|
export { GATED_CUSTOM_META_KEYS, adaptPromptContent, gateCustomMeta, isSupportedProtocolVersion, negotiateCapabilities, unsupportedMcpServer, } from "./capabilities.js";
|
|
@@ -24,7 +30,7 @@ export { ClaudeBackend } from "./backends/claude.js";
|
|
|
24
30
|
export { CodexBackend } from "./backends/codex.js";
|
|
25
31
|
export { OpenCodeBackend } from "./backends/opencode.js";
|
|
26
32
|
export { CustomAcpBackend } from "./backends/custom.js";
|
|
27
|
-
export { decidePermission } from "./permissions.js";
|
|
33
|
+
export { decidePermission, resolvePermission, withPersist } from "./permissions.js";
|
|
28
34
|
export { UsageAccumulator } from "./usage.js";
|
|
29
35
|
export { toAnthropicJsonSchema, toJsonSchema, toStrictJsonSchema } from "./schema-strict.js";
|
|
30
36
|
export { extractValidated, findJsonBlock, parseFinalJson, resolveStructuredOutput, validateValue, } from "./structured-output.js";
|
package/dist/permissions.d.ts
CHANGED
|
@@ -12,6 +12,20 @@ export type PermissionResolver = (params: RequestPermissionRequest, ctx: AcpEven
|
|
|
12
12
|
* UNSTABLE/@experimental; this library deliberately exposes the SDK request/response types
|
|
13
13
|
* directly so regular SDK bumps and wire tests catch drift instead of freezing a local copy. */
|
|
14
14
|
export type ElicitationResolver = (request: CreateElicitationRequest, context: AcpEventContext) => Promise<CreateElicitationResponse> | CreateElicitationResponse;
|
|
15
|
+
/** Codex tool-approval persistence directive (codex-acp `dist/index.js:23952-23975`, §3.6). A
|
|
16
|
+
* permission decision may ask the agent to REMEMBER the approval for the rest of the session
|
|
17
|
+
* ("session") or permanently ("always"). It is echoed as `_meta.persist` on the RequestPermission
|
|
18
|
+
* response; an agent WITHOUT the capability ignores the extra `_meta` (Principle 3 — no silent
|
|
19
|
+
* unsupported surface). */
|
|
20
|
+
export type PermissionPersist = "session" | "always";
|
|
21
|
+
/** High-level permission decision (§3.6). Mirrors the spec's `PermissionResolution`: a host says
|
|
22
|
+
* allow/deny and, on allow, MAY request persistence. `resolvePermission` maps it onto a concrete ACP
|
|
23
|
+
* `RequestPermissionResponse` (option selection + the `_meta.persist` echo), so a host can drive
|
|
24
|
+
* `onPermissionRequest` at this altitude instead of hand-building the SDK response. */
|
|
25
|
+
export interface PermissionResolution {
|
|
26
|
+
outcome: "allow" | "deny";
|
|
27
|
+
persist?: PermissionPersist;
|
|
28
|
+
}
|
|
15
29
|
export interface ToolPolicy {
|
|
16
30
|
/** Allow-list (agentType `tools`). When non-empty, a tool that matches NOTHING is denied. */
|
|
17
31
|
allow?: string[];
|
|
@@ -21,7 +35,20 @@ export interface ToolPolicy {
|
|
|
21
35
|
* behavior. Explicit ACP session modes set this to "deny" unless a permission resolver is
|
|
22
36
|
* present, otherwise read-only/plan confinement can be bypassed by auto-approved escalations. */
|
|
23
37
|
defaultOutcome?: "allow" | "deny";
|
|
38
|
+
/** Codex tool-approval persistence (§3.6): when the auto-responder ALLOWS a tool, echo this as
|
|
39
|
+
* `_meta.persist` on the response so a capable agent remembers the approval. Ignored on deny and by
|
|
40
|
+
* agents without the capability. */
|
|
41
|
+
persist?: PermissionPersist;
|
|
24
42
|
}
|
|
25
43
|
/** Decide the auto-response for one permission request given the tool policy. */
|
|
26
44
|
export declare function decidePermission(request: RequestPermissionRequest, policy: ToolPolicy): RequestPermissionResponse;
|
|
45
|
+
/** Stamp a persistence directive onto a permission response's top-level `_meta.persist` (§3.6). A
|
|
46
|
+
* cancelled response, or an absent directive, is returned unchanged. Never mutates the input; a
|
|
47
|
+
* non-secret structural echo, so it is safe to emit in events. */
|
|
48
|
+
export declare function withPersist(response: RequestPermissionResponse, persist: PermissionPersist | undefined): RequestPermissionResponse;
|
|
49
|
+
/** Map a high-level `PermissionResolution` (§3.6) onto a concrete ACP `RequestPermissionResponse` for
|
|
50
|
+
* `request`: pick an allow/reject option of the requested polarity and, on allow, echo `_meta.persist`.
|
|
51
|
+
* Falls back to CANCELLING when the agent offers no option of the requested polarity (the only way to
|
|
52
|
+
* refuse a tool with no reject option) — identical to the auto-responder's contract. */
|
|
53
|
+
export declare function resolvePermission(request: RequestPermissionRequest, resolution: PermissionResolution): RequestPermissionResponse;
|
|
27
54
|
//# sourceMappingURL=permissions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../src/permissions.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EACV,wBAAwB,EACxB,yBAAyB,EAGzB,wBAAwB,EACxB,yBAAyB,EAC1B,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD;;;;;;wDAMwD;AACxD,MAAM,MAAM,kBAAkB,GAAG,CAC/B,MAAM,EAAE,wBAAwB,EAChC,GAAG,EAAE,eAAe,KACjB,OAAO,CAAC,yBAAyB,CAAC,GAAG,yBAAyB,CAAC;AAEpE;;iGAEiG;AACjG,MAAM,MAAM,mBAAmB,GAAG,CAChC,OAAO,EAAE,wBAAwB,EACjC,OAAO,EAAE,eAAe,KACrB,OAAO,CAAC,yBAAyB,CAAC,GAAG,yBAAyB,CAAC;AAEpE,MAAM,WAAW,UAAU;IACzB,6FAA6F;IAC7F,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,6EAA6E;IAC7E,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB;;sGAEkG;IAClG,cAAc,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../src/permissions.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EACV,wBAAwB,EACxB,yBAAyB,EAGzB,wBAAwB,EACxB,yBAAyB,EAC1B,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD;;;;;;wDAMwD;AACxD,MAAM,MAAM,kBAAkB,GAAG,CAC/B,MAAM,EAAE,wBAAwB,EAChC,GAAG,EAAE,eAAe,KACjB,OAAO,CAAC,yBAAyB,CAAC,GAAG,yBAAyB,CAAC;AAEpE;;iGAEiG;AACjG,MAAM,MAAM,mBAAmB,GAAG,CAChC,OAAO,EAAE,wBAAwB,EACjC,OAAO,EAAE,eAAe,KACrB,OAAO,CAAC,yBAAyB,CAAC,GAAG,yBAAyB,CAAC;AAEpE;;;;4BAI4B;AAC5B,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,QAAQ,CAAC;AAErD;;;wFAGwF;AACxF,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,GAAG,MAAM,CAAC;IAC1B,OAAO,CAAC,EAAE,iBAAiB,CAAC;CAC7B;AAED,MAAM,WAAW,UAAU;IACzB,6FAA6F;IAC7F,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,6EAA6E;IAC7E,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB;;sGAEkG;IAClG,cAAc,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAClC;;yCAEqC;IACrC,OAAO,CAAC,EAAE,iBAAiB,CAAC;CAC7B;AAKD,iFAAiF;AACjF,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,wBAAwB,EACjC,MAAM,EAAE,UAAU,GACjB,yBAAyB,CAwC3B;AAED;;mEAEmE;AACnE,wBAAgB,WAAW,CACzB,QAAQ,EAAE,yBAAyB,EACnC,OAAO,EAAE,iBAAiB,GAAG,SAAS,GACrC,yBAAyB,CAG3B;AAED;;;yFAGyF;AACzF,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,wBAAwB,EACjC,UAAU,EAAE,oBAAoB,GAC/B,yBAAyB,CAM3B"}
|
package/dist/permissions.js
CHANGED
|
@@ -35,7 +35,29 @@ export function decidePermission(request, policy) {
|
|
|
35
35
|
// remaining way to refuse a tool the server offers no reject option for.
|
|
36
36
|
return { outcome: { outcome: "cancelled" } };
|
|
37
37
|
}
|
|
38
|
-
|
|
38
|
+
const response = { outcome: { outcome: "selected", optionId: option.optionId } };
|
|
39
|
+
// Echo the persistence directive (§3.6) only when the auto-responder ALLOWS; a denial persists nothing.
|
|
40
|
+
return wantAllow ? withPersist(response, policy.persist) : response;
|
|
41
|
+
}
|
|
42
|
+
/** Stamp a persistence directive onto a permission response's top-level `_meta.persist` (§3.6). A
|
|
43
|
+
* cancelled response, or an absent directive, is returned unchanged. Never mutates the input; a
|
|
44
|
+
* non-secret structural echo, so it is safe to emit in events. */
|
|
45
|
+
export function withPersist(response, persist) {
|
|
46
|
+
if (!persist || response.outcome.outcome !== "selected")
|
|
47
|
+
return response;
|
|
48
|
+
return { ...response, _meta: { ...(response._meta ?? {}), persist } };
|
|
49
|
+
}
|
|
50
|
+
/** Map a high-level `PermissionResolution` (§3.6) onto a concrete ACP `RequestPermissionResponse` for
|
|
51
|
+
* `request`: pick an allow/reject option of the requested polarity and, on allow, echo `_meta.persist`.
|
|
52
|
+
* Falls back to CANCELLING when the agent offers no option of the requested polarity (the only way to
|
|
53
|
+
* refuse a tool with no reject option) — identical to the auto-responder's contract. */
|
|
54
|
+
export function resolvePermission(request, resolution) {
|
|
55
|
+
const wantAllow = resolution.outcome === "allow";
|
|
56
|
+
const option = pickOption(request.options, wantAllow);
|
|
57
|
+
if (!option)
|
|
58
|
+
return { outcome: { outcome: "cancelled" } };
|
|
59
|
+
const response = { outcome: { outcome: "selected", optionId: option.optionId } };
|
|
60
|
+
return wantAllow ? withPersist(response, resolution.persist) : response;
|
|
39
61
|
}
|
|
40
62
|
function candidateNames(request) {
|
|
41
63
|
const decoration = [];
|
package/dist/pool.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { PooledConnection, SessionHandle, type AcpSessionOptions } from "./acp-c
|
|
|
3
3
|
import { type ClientHandlers } from "./client-handlers.js";
|
|
4
4
|
import type { AcpEventSink } from "./events.js";
|
|
5
5
|
import type { ElicitationResolver, PermissionResolver } from "./permissions.js";
|
|
6
|
+
import type { AuthStore } from "./auth/auth-store.js";
|
|
6
7
|
export interface AcpPoolOptions {
|
|
7
8
|
/** Long-lived processes to keep PER backend. Default 1; falls back to AGENTPRISM_ACP_POOL_SIZE. */
|
|
8
9
|
size?: number;
|
|
@@ -16,6 +17,16 @@ export interface AcpPoolDeps {
|
|
|
16
17
|
permissionResolver?: PermissionResolver;
|
|
17
18
|
elicitationResolver?: ElicitationResolver;
|
|
18
19
|
advertiseElicitation?: boolean;
|
|
20
|
+
/** Initialize-time client auth advertisement (§1.2), forwarded to every PooledConnection.
|
|
21
|
+
* Undefined omits the `auth` capability — the default-OFF baseline. */
|
|
22
|
+
authCapabilities?: {
|
|
23
|
+
terminal?: boolean;
|
|
24
|
+
gateway?: boolean;
|
|
25
|
+
};
|
|
26
|
+
/** The runner's single auth store (§2). When present, connection selection is generation-gated:
|
|
27
|
+
* no session is ever opened on a connection whose applied intent-generation is stale. Undefined
|
|
28
|
+
* => no gating, byte-identical to the pre-auth baseline. */
|
|
29
|
+
authStore?: AuthStore;
|
|
19
30
|
}
|
|
20
31
|
/** Resolve the per-backend pool size: explicit option wins, else env, else 1. Clamped to >= 1. */
|
|
21
32
|
export declare function resolvePoolSize(option?: number): number;
|
|
@@ -41,6 +52,15 @@ export declare class AcpAgentPool {
|
|
|
41
52
|
* double-book a connection.
|
|
42
53
|
*/
|
|
43
54
|
private selectConnection;
|
|
55
|
+
/** Reconcile every live connection for a key to the current generation (§2.6). Stale-but-busy
|
|
56
|
+
* connections are DRAINED (recycled on release), not disposed synchronously, so in-flight prompts
|
|
57
|
+
* finish under the auth they started with. Never blocks. */
|
|
58
|
+
private reconcileStale;
|
|
59
|
+
/** Public: reconcile every live connection for a backend to the current generation (§2.6). Called
|
|
60
|
+
* by the runner immediately after a host-completed auth so a subsequent run() lands current. */
|
|
61
|
+
recycle(poolKey: string): void;
|
|
62
|
+
/** Spawn a fresh pooled connection (a fresh process primes the current intent at initialize). */
|
|
63
|
+
private spawn;
|
|
44
64
|
private connectionsFor;
|
|
45
65
|
/** Evict a dead connection so it is never handed out again. */
|
|
46
66
|
private drop;
|
package/dist/pool.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pool.d.ts","sourceRoot":"","sources":["../src/pool.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,OAAO,EAAa,MAAM,cAAc,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAC1F,OAAO,EAA0B,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEnF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"pool.d.ts","sourceRoot":"","sources":["../src/pool.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,OAAO,EAAa,MAAM,cAAc,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAC1F,OAAO,EAA0B,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEnF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAChF,OAAO,KAAK,EAAE,SAAS,EAAsB,MAAM,sBAAsB,CAAC;AAK1E,MAAM,WAAW,cAAc;IAC7B,mGAAmG;IACnG,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,4FAA4F;IAC5F,cAAc,CAAC,EAAE,cAAc,CAAC;CACjC;AAED;6FAC6F;AAC7F,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACxC,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B;4EACwE;IACxE,gBAAgB,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAC7D;;iEAE6D;IAC7D,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAED,kGAAkG;AAClG,wBAAgB,eAAe,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAUvD;AAED,qBAAa,YAAY;IAUrB,OAAO,CAAC,QAAQ,CAAC,IAAI;IATvB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA6B;IAC5D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA4C;IACtE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA4B;IAC1D,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAS;gBAGvB,OAAO,GAAE,cAAmB,EACX,IAAI,GAAE,WAAgB;IAOzC,8FAA8F;IACxF,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,aAAa,CAAC;IAehF,2FAA2F;IACrF,eAAe,CACnB,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,CAAC,UAAU,EAAE,gBAAgB,KAAK,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC,EACzF,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAO,GACrD,OAAO,CAAC,aAAa,CAAC;IAezB;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IAyBxB;;iEAE6D;IAC7D,OAAO,CAAC,cAAc;IActB;qGACiG;IACjG,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAM9B,iGAAiG;IACjG,OAAO,CAAC,KAAK;IAgBb,OAAO,CAAC,cAAc;IAStB,+DAA+D;IAC/D,OAAO,CAAC,IAAI;IAOZ,iEAAiE;IAC3D,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ9B,OAAO,CAAC,cAAc;IAMtB,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,cAAc;IAMtB,gGAAgG;IAChG,OAAO,CAAC,WAAW;CAGpB"}
|
package/dist/pool.js
CHANGED
|
@@ -75,26 +75,68 @@ export class AcpAgentPool {
|
|
|
75
75
|
// Pool identity: poolKey (id + spawn-config hash for custom backends) over bare id, so two
|
|
76
76
|
// runs declaring the same NAME with different COMMANDS never share a process.
|
|
77
77
|
const key = backend.poolKey ?? backend.id;
|
|
78
|
+
// Generation-gated selection (§2.6): reuse any idle live connection that is NOT stale,
|
|
79
|
+
// reconciling stale ones first. This is the mechanical proof that no session is served under
|
|
80
|
+
// stale auth. `existing` (not `machineFor`) so the default-OFF path never lazily creates a
|
|
81
|
+
// machine — undefined machine ⇒ nothing is ever stale, byte-identical to the pre-auth baseline.
|
|
82
|
+
const machine = this.deps.authStore?.existing(key);
|
|
78
83
|
const connections = this.connectionsFor(key);
|
|
79
|
-
|
|
80
|
-
|
|
84
|
+
if (machine)
|
|
85
|
+
this.reconcileStale(key, machine);
|
|
86
|
+
const usable = connections.filter((c) => c.alive && !c.recyclePending && !machine?.isStale(c.authStamp));
|
|
87
|
+
const idle = usable.find((c) => c.activeSessions === 0);
|
|
81
88
|
if (idle)
|
|
82
89
|
return idle;
|
|
83
|
-
if (
|
|
84
|
-
this.
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
90
|
+
if (usable.length < this.size)
|
|
91
|
+
return this.spawn(key, backend);
|
|
92
|
+
// At capacity with every usable connection busy: multiplex onto the least-loaded one.
|
|
93
|
+
return usable.length > 0
|
|
94
|
+
? usable.reduce((least, c) => (c.activeSessions < least.activeSessions ? c : least))
|
|
95
|
+
: this.spawn(key, backend);
|
|
96
|
+
}
|
|
97
|
+
/** Reconcile every live connection for a key to the current generation (§2.6). Stale-but-busy
|
|
98
|
+
* connections are DRAINED (recycled on release), not disposed synchronously, so in-flight prompts
|
|
99
|
+
* finish under the auth they started with. Never blocks. */
|
|
100
|
+
reconcileStale(key, machine) {
|
|
101
|
+
for (const c of this.connectionsFor(key).filter((c) => c.alive)) {
|
|
102
|
+
if (!machine.isStale(c.authStamp))
|
|
103
|
+
continue;
|
|
104
|
+
if (c.canLiveReapply(machine) && c.activeSessions === 0) {
|
|
105
|
+
c.scheduleReapply(machine); // in-process: re-auth the idle connection live
|
|
106
|
+
}
|
|
107
|
+
else if (c.activeSessions === 0) {
|
|
108
|
+
void c.dispose(); // disk/spawn-env: recycle the idle process now
|
|
109
|
+
this.drop(key, c);
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
c.markForRecycleWhenIdle(machine); // BUSY: drain, then recycle on release
|
|
113
|
+
}
|
|
95
114
|
}
|
|
96
|
-
|
|
97
|
-
|
|
115
|
+
}
|
|
116
|
+
/** Public: reconcile every live connection for a backend to the current generation (§2.6). Called
|
|
117
|
+
* by the runner immediately after a host-completed auth so a subsequent run() lands current. */
|
|
118
|
+
recycle(poolKey) {
|
|
119
|
+
if (this.disposed)
|
|
120
|
+
return;
|
|
121
|
+
const machine = this.deps.authStore?.existing(poolKey);
|
|
122
|
+
if (machine)
|
|
123
|
+
this.reconcileStale(poolKey, machine);
|
|
124
|
+
}
|
|
125
|
+
/** Spawn a fresh pooled connection (a fresh process primes the current intent at initialize). */
|
|
126
|
+
spawn(key, backend) {
|
|
127
|
+
this.installExitHook();
|
|
128
|
+
const connection = PooledConnection.create(backend, {
|
|
129
|
+
onDead: (dead) => this.drop(key, dead),
|
|
130
|
+
onEvent: this.deps.onEvent,
|
|
131
|
+
permissionResolver: this.deps.permissionResolver,
|
|
132
|
+
elicitationResolver: this.deps.elicitationResolver,
|
|
133
|
+
advertiseElicitation: this.deps.advertiseElicitation,
|
|
134
|
+
authCapabilities: this.deps.authCapabilities,
|
|
135
|
+
authStore: this.deps.authStore,
|
|
136
|
+
clientHandlers: this.clientHandlers,
|
|
137
|
+
});
|
|
138
|
+
this.connectionsFor(key).push(connection);
|
|
139
|
+
return connection;
|
|
98
140
|
}
|
|
99
141
|
connectionsFor(key) {
|
|
100
142
|
let arr = this.byBackend.get(key);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AGENT_METHODS, CLIENT_METHODS } from "@agentclientprotocol/sdk";
|
|
2
|
+
import type { AuthCapabilities, AuthMethod, AuthMethodAgent, AuthMethodEnvVar, AuthMethodTerminal, ClientCapabilities } from "@agentclientprotocol/sdk";
|
|
2
3
|
type ValueOf<T> = T[keyof T];
|
|
3
4
|
type ClientMethod = ValueOf<typeof CLIENT_METHODS>;
|
|
4
5
|
type AgentMethod = ValueOf<typeof AGENT_METHODS>;
|
|
@@ -12,5 +13,79 @@ export type AgentMethodCoverage = "driven" | "passthrough" | "guarded";
|
|
|
12
13
|
* and the passthrough remainder is nes/*, document/*, and mcp/message. */
|
|
13
14
|
export declare const CLIENT_METHOD_COVERAGE: Record<ClientMethod, ClientMethodCoverage>;
|
|
14
15
|
export declare const AGENT_METHOD_COVERAGE: Record<AgentMethod, AgentMethodCoverage>;
|
|
16
|
+
/** Compile-time assertion primitive: `Expect<T>` only accepts `true`, so a `false` (drifted) SDK
|
|
17
|
+
* shape is a type error at build time. */
|
|
18
|
+
type Expect<T extends true> = T;
|
|
19
|
+
/** `ClientCapabilities.auth` still exists and is typed as `AuthCapabilities` (§1.2 UNSTABLE pin). */
|
|
20
|
+
export type _AuthKeyExists = Expect<"auth" extends keyof ClientCapabilities ? true : false>;
|
|
21
|
+
/** `AuthCapabilities.terminal` is still the typed boolean gate §1.2 assigns to (no `as` cast). */
|
|
22
|
+
export type _AuthTerminalIsBoolean = Expect<AuthCapabilities["terminal"] extends boolean | undefined ? true : false>;
|
|
23
|
+
/** The exact property set SDK 1.2.1 types on `AuthCapabilities` (§1.2). The runtime tripwire below
|
|
24
|
+
* asserts `clientCapabilitiesFor({ auth })` emits ONLY these keys, so a bump that widens/renames
|
|
25
|
+
* the shape trips the coverage suite. */
|
|
26
|
+
export declare const AUTH_CAPABILITY_KEYS: readonly string[];
|
|
27
|
+
/** Runtime drift assertion (§4.6.4 item 1): every key on the advertised `ClientCapabilities.auth`
|
|
28
|
+
* block is a pinned SDK-1.2.1 `AuthCapabilities` key. Throws on drift, tripping the build. A
|
|
29
|
+
* `null`/absent `auth` (the default-OFF baseline) is vacuously conformant. Reads only structural
|
|
30
|
+
* keys — never any advertised value — so it is secret-free. */
|
|
31
|
+
export declare function assertAuthCapabilityShape(auth: ClientCapabilities["auth"]): void;
|
|
32
|
+
/** The three `AuthMethod` variants the base dispatcher handles (`agent`/`terminal`/`env_var`, §1.3).
|
|
33
|
+
* `agent` is the default when `type` is absent (`AuthMethodAgent` carries no `type`). */
|
|
34
|
+
export declare const HANDLED_AUTH_METHOD_TYPES: readonly ["agent", "terminal", "env_var"];
|
|
35
|
+
/** §4.6.4 item 3 — the SDK `AuthMethod` union is EXACTLY the three variants the dispatcher handles;
|
|
36
|
+
* a fourth variant (a widened union) makes this `false` and fails `tsc`. */
|
|
37
|
+
export type _AuthMethodUnionPinned = Expect<[
|
|
38
|
+
AuthMethod
|
|
39
|
+
] extends [AuthMethodAgent | AuthMethodTerminal | AuthMethodEnvVar] ? true : false>;
|
|
40
|
+
/** The `terminal`/`env_var` discriminants are still the literals the dispatcher branches on: the SDK
|
|
41
|
+
* intersects the bare method type with `{ type: "…" }` in the `AuthMethod` union, so a dropped
|
|
42
|
+
* discriminant makes `Extract` collapse to `never` and fails `tsc`. */
|
|
43
|
+
export type _AuthMethodTerminalDiscriminant = Expect<[
|
|
44
|
+
Extract<AuthMethod, {
|
|
45
|
+
type: "terminal";
|
|
46
|
+
}>
|
|
47
|
+
] extends [never] ? false : true>;
|
|
48
|
+
export type _AuthMethodEnvVarDiscriminant = Expect<[
|
|
49
|
+
Extract<AuthMethod, {
|
|
50
|
+
type: "env_var";
|
|
51
|
+
}>
|
|
52
|
+
] extends [never] ? false : true>;
|
|
53
|
+
/** The cross-agent `_meta` key conventions the base layer keys on (§1 intro; recognized by literal
|
|
54
|
+
* name, NOT SDK schema fields). `gateway` ⇒ in-process classification; `terminal-auth` ⇒ terminal
|
|
55
|
+
* launch hint; `api-key` ⇒ codex's disk api-key `_meta`. */
|
|
56
|
+
export declare const AUTH_META_CONVENTION_KEYS: {
|
|
57
|
+
readonly gateway: "gateway";
|
|
58
|
+
readonly terminalAuth: "terminal-auth";
|
|
59
|
+
readonly apiKey: "api-key";
|
|
60
|
+
};
|
|
61
|
+
/** The codex startup pre-auth env channel delivered by `codexAuthProfile.spawnAuthEnv` (§2.8/§3.3). */
|
|
62
|
+
export declare const CODEX_SPAWN_AUTH_ENV: "DEFAULT_AUTH_REQUEST";
|
|
63
|
+
/** JSON-RPC `-32000` is reserved EXCLUSIVELY for `authRequired` (SDK `jsonrpc.js:818-823`) — the
|
|
64
|
+
* guarantee the code-only §1.5 matcher relies on (§4.6.4 item 5). */
|
|
65
|
+
export declare const ACP_AUTH_REQUIRED_CODE_EXCLUSIVE: -32000;
|
|
66
|
+
/** One row of the §3.6 full `_meta` support matrix, landed as executable data (not prose) so an
|
|
67
|
+
* SDK/agent bump that changes a `_meta` surface trips the drift suite (§4.6.4 item 4). */
|
|
68
|
+
export interface AuthMetaMatrixRow {
|
|
69
|
+
readonly agent: "claude" | "codex" | "opencode" | "all";
|
|
70
|
+
/** A stable literal that MUST still be present in the cited artifact/spec — the drift anchor. */
|
|
71
|
+
readonly capability: string;
|
|
72
|
+
/** Wire direction: A→C agent→client, C→A client→agent, C↔A both, — none, agent-internal. */
|
|
73
|
+
readonly direction: "A→C" | "C→A" | "C↔A" | "—" | "agent-internal";
|
|
74
|
+
readonly status: "supported-today" | "work-item";
|
|
75
|
+
/** Owning §/PR for a work item; omitted for supported-today rows. */
|
|
76
|
+
readonly owner?: string;
|
|
77
|
+
/** When set, the literal is asserted present in this backend's INSTALLED dist (claude/codex only;
|
|
78
|
+
* opencode ships a compiled binary with no consumable source — §3.4, grounded by live-e2e). */
|
|
79
|
+
readonly distProbe?: "claude" | "codex";
|
|
80
|
+
}
|
|
81
|
+
/** The §3.6 auth `_meta` matrix as executable rows — the exact surfaces §4.6.4 item 4 enumerates
|
|
82
|
+
* (claude gateway/terminal-auth, codex api-key/gateway/DEFAULT_AUTH_REQUEST, opencode terminal-auth),
|
|
83
|
+
* plus the codex tool-approval `persist` and the cross-agent provider-env passthrough. Each
|
|
84
|
+
* `capability` is a literal that MUST appear in spec §3.6; `docs-drift.test.ts` asserts that lockstep,
|
|
85
|
+
* and (where `distProbe` is set) `protocol-coverage.test.ts` asserts the literal is still present in
|
|
86
|
+
* the installed agent dist — so neither the spec nor an agent bump can silently drift a `_meta`
|
|
87
|
+
* surface. OpenCode ships a compiled binary with no consumable source (§3.4), so its row has no dist
|
|
88
|
+
* probe (grounded instead by the §4.6.3 live-e2e). */
|
|
89
|
+
export declare const AUTH_META_MATRIX: readonly AuthMetaMatrixRow[];
|
|
15
90
|
export {};
|
|
16
91
|
//# sourceMappingURL=protocol-coverage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol-coverage.d.ts","sourceRoot":"","sources":["../src/protocol-coverage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"protocol-coverage.d.ts","sourceRoot":"","sources":["../src/protocol-coverage.ts"],"names":[],"mappings":"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"}
|
|
@@ -49,3 +49,61 @@ export const AGENT_METHOD_COVERAGE = {
|
|
|
49
49
|
[AGENT_METHODS.document_did_save]: "passthrough",
|
|
50
50
|
[AGENT_METHODS.document_did_focus]: "passthrough",
|
|
51
51
|
};
|
|
52
|
+
/** The exact property set SDK 1.2.1 types on `AuthCapabilities` (§1.2). The runtime tripwire below
|
|
53
|
+
* asserts `clientCapabilitiesFor({ auth })` emits ONLY these keys, so a bump that widens/renames
|
|
54
|
+
* the shape trips the coverage suite. */
|
|
55
|
+
export const AUTH_CAPABILITY_KEYS = ["terminal", "_meta"];
|
|
56
|
+
/** Runtime drift assertion (§4.6.4 item 1): every key on the advertised `ClientCapabilities.auth`
|
|
57
|
+
* block is a pinned SDK-1.2.1 `AuthCapabilities` key. Throws on drift, tripping the build. A
|
|
58
|
+
* `null`/absent `auth` (the default-OFF baseline) is vacuously conformant. Reads only structural
|
|
59
|
+
* keys — never any advertised value — so it is secret-free. */
|
|
60
|
+
export function assertAuthCapabilityShape(auth) {
|
|
61
|
+
if (auth == null)
|
|
62
|
+
return;
|
|
63
|
+
for (const key of Object.keys(auth)) {
|
|
64
|
+
if (!AUTH_CAPABILITY_KEYS.includes(key)) {
|
|
65
|
+
throw new Error(`ClientCapabilities.auth carries unpinned key "${key}" — the SDK AuthCapabilities shape drifted (§1.2/§4.6.4).`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// ---------------------------------------------------------------------------------------------
|
|
70
|
+
// Auth `AuthMethod.type` discriminant + cross-agent `_meta` convention drift tripwires
|
|
71
|
+
// (§3.6 / §4.6.4 items 3–5). The base auth flow (§1) dispatches on `AuthMethod.type` plus a small,
|
|
72
|
+
// fixed set of literal cross-agent `_meta` key names — NOT SDK schema fields. Pin both so a
|
|
73
|
+
// `@agentclientprotocol/sdk` bump that widens the method union, or an agent bump that moves a `_meta`
|
|
74
|
+
// surface, fails the build BEFORE release (bump-ACP-deps-every-release), never silently.
|
|
75
|
+
// ---------------------------------------------------------------------------------------------
|
|
76
|
+
/** The three `AuthMethod` variants the base dispatcher handles (`agent`/`terminal`/`env_var`, §1.3).
|
|
77
|
+
* `agent` is the default when `type` is absent (`AuthMethodAgent` carries no `type`). */
|
|
78
|
+
export const HANDLED_AUTH_METHOD_TYPES = ["agent", "terminal", "env_var"];
|
|
79
|
+
/** The cross-agent `_meta` key conventions the base layer keys on (§1 intro; recognized by literal
|
|
80
|
+
* name, NOT SDK schema fields). `gateway` ⇒ in-process classification; `terminal-auth` ⇒ terminal
|
|
81
|
+
* launch hint; `api-key` ⇒ codex's disk api-key `_meta`. */
|
|
82
|
+
export const AUTH_META_CONVENTION_KEYS = {
|
|
83
|
+
gateway: "gateway",
|
|
84
|
+
terminalAuth: "terminal-auth",
|
|
85
|
+
apiKey: "api-key",
|
|
86
|
+
};
|
|
87
|
+
/** The codex startup pre-auth env channel delivered by `codexAuthProfile.spawnAuthEnv` (§2.8/§3.3). */
|
|
88
|
+
export const CODEX_SPAWN_AUTH_ENV = "DEFAULT_AUTH_REQUEST";
|
|
89
|
+
/** JSON-RPC `-32000` is reserved EXCLUSIVELY for `authRequired` (SDK `jsonrpc.js:818-823`) — the
|
|
90
|
+
* guarantee the code-only §1.5 matcher relies on (§4.6.4 item 5). */
|
|
91
|
+
export const ACP_AUTH_REQUIRED_CODE_EXCLUSIVE = -32000;
|
|
92
|
+
/** The §3.6 auth `_meta` matrix as executable rows — the exact surfaces §4.6.4 item 4 enumerates
|
|
93
|
+
* (claude gateway/terminal-auth, codex api-key/gateway/DEFAULT_AUTH_REQUEST, opencode terminal-auth),
|
|
94
|
+
* plus the codex tool-approval `persist` and the cross-agent provider-env passthrough. Each
|
|
95
|
+
* `capability` is a literal that MUST appear in spec §3.6; `docs-drift.test.ts` asserts that lockstep,
|
|
96
|
+
* and (where `distProbe` is set) `protocol-coverage.test.ts` asserts the literal is still present in
|
|
97
|
+
* the installed agent dist — so neither the spec nor an agent bump can silently drift a `_meta`
|
|
98
|
+
* surface. OpenCode ships a compiled binary with no consumable source (§3.4), so its row has no dist
|
|
99
|
+
* probe (grounded instead by the §4.6.3 live-e2e). */
|
|
100
|
+
export const AUTH_META_MATRIX = [
|
|
101
|
+
{ agent: "claude", capability: "gateway", direction: "C↔A", status: "work-item", owner: "§1.2-§1.3/PR2-PR3", distProbe: "claude" },
|
|
102
|
+
{ agent: "claude", capability: "terminal-auth", direction: "C↔A", status: "work-item", owner: "§1.2-§1.3/PR2-PR3", distProbe: "claude" },
|
|
103
|
+
{ agent: "codex", capability: "api-key", direction: "A→C", status: "work-item", owner: "§1.3/PR3", distProbe: "codex" },
|
|
104
|
+
{ agent: "codex", capability: "gateway", direction: "C↔A", status: "work-item", owner: "§1.2-§1.3/PR2-PR3", distProbe: "codex" },
|
|
105
|
+
{ agent: "codex", capability: "DEFAULT_AUTH_REQUEST", direction: "C→A", status: "work-item", owner: "§3.3/PR7", distProbe: "codex" },
|
|
106
|
+
{ agent: "codex", capability: "persist", direction: "C→A", status: "work-item", owner: "§3.6/PR7", distProbe: "codex" },
|
|
107
|
+
{ agent: "opencode", capability: "terminal-auth", direction: "C↔A", status: "work-item", owner: "§1.2-§1.3/PR2-PR3" },
|
|
108
|
+
{ agent: "all", capability: "provider env keys", direction: "C→A", status: "work-item", owner: "§2.8/§3.4/PR3" },
|
|
109
|
+
];
|