@automatalabs/acp-agents 0.17.0 → 0.19.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/README.md +7 -3
- package/dist/acp-client.d.ts +4 -0
- package/dist/acp-client.d.ts.map +1 -1
- package/dist/acp-client.js +39 -22
- package/dist/backend.d.ts +4 -0
- package/dist/backend.d.ts.map +1 -1
- package/dist/backends/claude.d.ts.map +1 -1
- package/dist/backends/claude.js +3 -2
- package/dist/backends/custom.d.ts +1 -0
- package/dist/backends/custom.d.ts.map +1 -1
- package/dist/backends/custom.js +6 -2
- package/dist/pool.d.ts +6 -1
- package/dist/pool.d.ts.map +1 -1
- package/dist/pool.js +18 -0
- package/dist/prompt.d.ts +1 -1
- package/dist/prompt.d.ts.map +1 -1
- package/dist/prompt.js +23 -12
- package/dist/registry.d.ts +3 -0
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +4 -0
- package/dist/runner.d.ts +7 -0
- package/dist/runner.d.ts.map +1 -1
- package/dist/runner.js +59 -3
- package/dist/structured-output.d.ts +3 -0
- package/dist/structured-output.d.ts.map +1 -1
- package/dist/structured-output.js +8 -1
- package/dist/structured-tool.d.ts +26 -0
- package/dist/structured-tool.d.ts.map +1 -0
- package/dist/structured-tool.js +208 -0
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ npm install @automatalabs/acp-agents
|
|
|
14
14
|
|
|
15
15
|
## Standalone use: drive one agent
|
|
16
16
|
|
|
17
|
-
`createAcpRunner().run(prompt, options)` runs a single agent to completion. Pass a [typebox](https://github.com/sinclairzx81/typebox) `schema` to get a validated object back (typed as `Static<typeof schema>`); omit it to get the final assistant text as a `string`. The backend (Claude vs Codex) is selected from `model` / `tier`.
|
|
17
|
+
`createAcpRunner().run(prompt, options)` runs a single agent to completion. Pass a [typebox](https://github.com/sinclairzx81/typebox) `schema` to get a validated object back (typed as `Static<typeof schema>`); omit it to get the final assistant text as a `string`. The backend (Claude vs Codex) is selected from `model` / `tier`. Whoever constructs the runner owns it: call `dispose()` (or use `await using`) when you're done to tear down the pooled child processes.
|
|
18
18
|
|
|
19
19
|
```ts
|
|
20
20
|
import { createAcpRunner } from "@automatalabs/acp-agents";
|
|
@@ -133,7 +133,7 @@ try {
|
|
|
133
133
|
|
|
134
134
|
## Listening in: live ACP events
|
|
135
135
|
|
|
136
|
-
`AcpAgentRunner` is also a typed event bus — `runner.on(name, listener)` bubbles up the live ACP stream of every run (streaming text, tool calls, usage, permissions). Event names are the ACP `sessionUpdate` discriminants (`agent_message_chunk`, `tool_call`, `usage_update`, …) plus the cross-cutting `session_update` (catch-all), `permission_pending`, `permission_request`, `raw_message`, `session_open` / `session_close`, and `backend_error`. Each payload carries a `{ sessionId, backendId, label?, runId? }` context envelope (a pooled runner multiplexes many runs at once). `permission_pending`
|
|
136
|
+
`AcpAgentRunner` is also a typed event bus — `runner.on(name, listener)` bubbles up the live ACP stream of every run (streaming text, tool calls, usage, permissions, elicitations). Event names are the ACP `sessionUpdate` discriminants (`agent_message_chunk`, `tool_call`, `usage_update`, …) plus the cross-cutting `session_update` (catch-all), `permission_pending`, `permission_request`, `elicitation_pending`, `elicitation_request`, `elicitation_complete`, `raw_message`, `session_open` / `session_close`, and `backend_error`. Each payload carries a `{ sessionId, backendId, label?, runId? }` context envelope (a pooled runner multiplexes many runs at once). `permission_pending` / `elicitation_pending` are resolver-only and carry `{ request }` before the host resolver is invoked; `permission_request` / `elicitation_request` fire exactly once with the final `{ request, outcome }` returned to the agent; `elicitation_complete` carries `{ notification }` for URL completions. `on()` / `once()` return an unsubscribe thunk; `off()` and `removeAllListeners()` round it out. Listeners are best-effort observers — a throwing listener never affects the run.
|
|
137
137
|
|
|
138
138
|
```ts
|
|
139
139
|
const off = runner.on("agent_message_chunk", (e) => {
|
|
@@ -151,14 +151,18 @@ The full event map (`AcpRunnerEventMap`) and helpers (`TypedEventEmitter`) are e
|
|
|
151
151
|
From [`src/index.ts`](./src/index.ts):
|
|
152
152
|
|
|
153
153
|
- **`createAcpRunner(options?)`** — factory returning an `AcpAgentRunner` (this is what `@automatalabs/workflows` injects into the engine).
|
|
154
|
-
- **`AcpAgentRunner`** — the `AgentRunner` implementation; `run(prompt, options)`, `openSession(options)`, and `
|
|
154
|
+
- **`AcpAgentRunner`** — the `AgentRunner` implementation; `run(prompt, options)`, `openSession(options)`, `dispose()`, and `[Symbol.asyncDispose]()` for `await using`. The caller that constructs a runner owns its lifecycle.
|
|
155
|
+
- **Auth/provider lifecycle methods** — `authMethods()`, `authenticate()`, `listProviders()`, `setProvider()`, `disableProvider()`, and `logout()`; see [docs/api.md](../../docs/api.md) for capability gating and installed adapter support.
|
|
156
|
+
- **Session lifecycle methods** — `listSessions()`, `deleteSession()`, `loadSession()`, and `resumeSession()` for backends that advertise session persistence; see [docs/api.md](../../docs/api.md).
|
|
155
157
|
- **`InteractiveSession` / `InteractiveSessionOptions` / `InteractiveTurn`** — the held-open multi-turn session surface returned by `openSession()`.
|
|
158
|
+
- **`AcpRunnerOptions.onElicitation`** — runner-wide ACP elicitation responder; sessions can override with `InteractiveSessionOptions.onElicitation`.
|
|
156
159
|
- **`selectBackend({ model, tier }, registry?)`** — the cross-provider routing rule: which backend a spec maps to (registered custom names match first, exact or `name/<inner-model>`).
|
|
157
160
|
- **`ClaudeBackend` / `CodexBackend`** — the two built-in backend strategies (spawn config + per-backend schema wiring).
|
|
158
161
|
- **`CustomAcpBackend` / `resolveBackendRegistry` / `BACKENDS_ENV`** — the custom-backend registry: run **any** ACP agent as a named backend via `createAcpRunner({ backends: { name: { command, args?, env?, sessionMeta?, customCapabilities? } } })` or the `AGENTPRISM_BACKENDS` env var (JSON, same shape; the option wins per name; `claude`/`codex` reserved). Custom backends carry a `schema` as turn-level `_meta.outputSchema` and read the result off the final message as JSON. `customCapabilities: { namespace, gatedKeys }` declares the agent's `agentCapabilities._meta` negotiation contract: once the agent advertises that namespace, each declared bare `_meta` key is sent only when its same-named flag is `true` (no declaration = never gated).
|
|
159
162
|
- **`PermissionResolver`** — async human-in-the-loop permission resolution for runner-wide or interactive sessions.
|
|
160
163
|
- **`clientCapabilitiesFor` + the `ClientHandlers` / `FsHandlers` / `TerminalHandlers` / `AcpSessionContext` types** — the client-side fs/terminal interposition surface (see above).
|
|
161
164
|
- **`negotiateCapabilities` / `adaptPromptContent` / `gateCustomMeta` / `unsupportedMcpServer` + `NegotiatedCapabilities`** — the `initialize` capability-negotiation primitives; the negotiated record for a live connection is exposed on `PooledConnection.capabilities`.
|
|
165
|
+
- **`AGENT_METHOD_COVERAGE` / `CLIENT_METHOD_COVERAGE`** — manifests classifying the installed ACP SDK method surface; enforced by tests so SDK bumps cannot silently drift.
|
|
162
166
|
- **`toJsonSchema(schema)` / `toStrictJsonSchema(schema)`** — turn a typebox schema into the on-the-wire shapes: a plain JSON Schema for Claude `outputFormat`, and an OpenAI-strict-normalized schema for Codex `outputSchema`.
|
|
163
167
|
|
|
164
168
|
Also exported: `AcpAgentPool` / `resolvePoolSize`, `PooledConnection` / `SessionHandle`, `decidePermission`, `UsageAccumulator`, `resolveStructuredOutput` / `extractValidated` / `findJsonBlock` / `validateValue`, `errorText` / `mapThrownError`, and the event surface `TypedEventEmitter` / `AcpRunnerEventMap` / `AcpEventName` / `AcpEventListener` / `AcpEventContext` / `AcpSessionUpdate` (+ the per-event payload types, including `AcpPermissionPendingEvent`), plus their associated types.
|
package/dist/acp-client.d.ts
CHANGED
|
@@ -161,6 +161,10 @@ export declare class PooledConnection {
|
|
|
161
161
|
* synchronously (before the first await) so the pool's load accounting is race-free.
|
|
162
162
|
*/
|
|
163
163
|
openSession(opts: AcpSessionOptions): Promise<SessionHandle>;
|
|
164
|
+
/** Reserve a session slot before initialize, then let the caller shape session/new with
|
|
165
|
+
* negotiated capabilities in hand. */
|
|
166
|
+
openPreparedSession(prepare: (connection: PooledConnection) => AcpSessionOptions | Promise<AcpSessionOptions>): Promise<SessionHandle>;
|
|
167
|
+
private openReadySession;
|
|
164
168
|
/** Reopen an existing session and replay its transcript through the router before resolving. */
|
|
165
169
|
loadSession(sessionId: string, opts: AcpSessionOptions): Promise<SessionHandle>;
|
|
166
170
|
/** Reopen an existing session without transcript replay. */
|
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":"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
|
|
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
|
@@ -875,34 +875,51 @@ export class PooledConnection {
|
|
|
875
875
|
this._activeSessions += 1;
|
|
876
876
|
try {
|
|
877
877
|
await this.ready;
|
|
878
|
-
|
|
879
|
-
// does not advertise (http/sse gated on mcpCapabilities; stdio is always serviceable).
|
|
880
|
-
// Fail-fast and non-recoverable — re-running the same incompatible transport can never
|
|
881
|
-
// succeed. Lenient for agents that advertise no mcpCapabilities (the legacy passthrough).
|
|
882
|
-
this.assertSupportedMcpServers(opts);
|
|
883
|
-
// session/new `_meta`, layered lowest-to-highest precedence: the backend's static
|
|
884
|
-
// defaults (a custom registry entry's `sessionMeta`), then the generic user passthrough
|
|
885
|
-
// (opts.meta), then the backend's protocol-critical `_meta` (Claude schema channel;
|
|
886
|
-
// Codex base/developer instructions), then the engine runId correlation stamp. The result
|
|
887
|
-
// is gated against the agent's advertised custom capabilities (a declared key the agent
|
|
888
|
-
// said it does not honor is dropped). When no layer survives, no `_meta` is sent.
|
|
889
|
-
const meta = this.sessionRequestMeta(opts);
|
|
890
|
-
const request = {
|
|
891
|
-
cwd: opts.cwd,
|
|
892
|
-
// Client-provided MCP servers (additive run input), else the default empty list.
|
|
893
|
-
mcpServers: opts.mcpServers ?? [],
|
|
894
|
-
...(meta ? { _meta: meta } : {}),
|
|
895
|
-
};
|
|
896
|
-
const response = await this.race(this.connection.agent.request(AGENT_METHODS.session_new, request));
|
|
897
|
-
const state = new SessionState(opts.cwd, opts.policy, opts.permissionResolver, opts.elicitationResolver, opts.label, opts.runId, response.modes, acpMcpServerIds(opts.mcpServers), opts.retainSessionLog ?? true);
|
|
898
|
-
this.client.register(response.sessionId, state);
|
|
899
|
-
return new SessionHandle(this, response.sessionId, state, response.configOptions ?? [], opts);
|
|
878
|
+
return await this.openReadySession(opts);
|
|
900
879
|
}
|
|
901
880
|
catch (error) {
|
|
902
881
|
this._activeSessions -= 1;
|
|
903
882
|
throw error;
|
|
904
883
|
}
|
|
905
884
|
}
|
|
885
|
+
/** Reserve a session slot before initialize, then let the caller shape session/new with
|
|
886
|
+
* negotiated capabilities in hand. */
|
|
887
|
+
async openPreparedSession(prepare) {
|
|
888
|
+
this._activeSessions += 1;
|
|
889
|
+
try {
|
|
890
|
+
await this.ready;
|
|
891
|
+
const opts = await prepare(this);
|
|
892
|
+
return await this.openReadySession(opts);
|
|
893
|
+
}
|
|
894
|
+
catch (error) {
|
|
895
|
+
this._activeSessions -= 1;
|
|
896
|
+
throw error;
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
async openReadySession(opts) {
|
|
900
|
+
// Capability gate: reject a client-provided MCP server whose transport the connected agent
|
|
901
|
+
// does not advertise (http/sse gated on mcpCapabilities; stdio is always serviceable).
|
|
902
|
+
// Fail-fast and non-recoverable — re-running the same incompatible transport can never
|
|
903
|
+
// succeed. Lenient for agents that advertise no mcpCapabilities (the legacy passthrough).
|
|
904
|
+
this.assertSupportedMcpServers(opts);
|
|
905
|
+
// session/new `_meta`, layered lowest-to-highest precedence: the backend's static
|
|
906
|
+
// defaults (a custom registry entry's `sessionMeta`), then the generic user passthrough
|
|
907
|
+
// (opts.meta), then the backend's protocol-critical `_meta` (Claude schema channel;
|
|
908
|
+
// Codex base/developer instructions), then the engine runId correlation stamp. The result
|
|
909
|
+
// is gated against the agent's advertised custom capabilities (a declared key the agent
|
|
910
|
+
// said it does not honor is dropped). When no layer survives, no `_meta` is sent.
|
|
911
|
+
const meta = this.sessionRequestMeta(opts);
|
|
912
|
+
const request = {
|
|
913
|
+
cwd: opts.cwd,
|
|
914
|
+
// Client-provided MCP servers (additive run input), else the default empty list.
|
|
915
|
+
mcpServers: opts.mcpServers ?? [],
|
|
916
|
+
...(meta ? { _meta: meta } : {}),
|
|
917
|
+
};
|
|
918
|
+
const response = await this.race(this.connection.agent.request(AGENT_METHODS.session_new, request));
|
|
919
|
+
const state = new SessionState(opts.cwd, opts.policy, opts.permissionResolver, opts.elicitationResolver, opts.label, opts.runId, response.modes, acpMcpServerIds(opts.mcpServers), opts.retainSessionLog ?? true);
|
|
920
|
+
this.client.register(response.sessionId, state);
|
|
921
|
+
return new SessionHandle(this, response.sessionId, state, response.configOptions ?? [], opts);
|
|
922
|
+
}
|
|
906
923
|
/** Reopen an existing session and replay its transcript through the router before resolving. */
|
|
907
924
|
loadSession(sessionId, opts) {
|
|
908
925
|
return this.reattachSession(AGENT_METHODS.session_load, sessionId, opts);
|
package/dist/backend.d.ts
CHANGED
|
@@ -37,6 +37,10 @@ export interface Backend {
|
|
|
37
37
|
* without the schema in the prompt, such an agent returns well-formed JSON with the WRONG
|
|
38
38
|
* KEYS and the repair ladder can never converge (it can fix prose, not unseen contracts). */
|
|
39
39
|
readonly embedSchemaInPrompt?: boolean;
|
|
40
|
+
/** When true, schema runs may inject a client-hosted MCP StructuredOutput tool if the
|
|
41
|
+
* initialized agent strictly advertises HTTP MCP support. Native schema channels leave this
|
|
42
|
+
* unset; custom ACP backends opt in unless their registry entry disables it. */
|
|
43
|
+
readonly injectStructuredOutputTool?: boolean;
|
|
40
44
|
/** The agentCapabilities._meta namespace this backend's agent advertises under, and the bare
|
|
41
45
|
* `_meta` keys gated by same-named boolean flags in that block; undefined = this backend has
|
|
42
46
|
* no custom-capability contract (its custom `_meta`, if any, is never gated). */
|
package/dist/backend.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEvC,4FAA4F;AAC5F,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,OAAO,CAAC;AAClD;sFACsF;AACtF,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC;AAE/B,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;CACxB;AAED,8FAA8F;AAC9F,MAAM,WAAW,gBAAgB;IAC/B,oDAAoD;IACpD,eAAe,IAAI,MAAM,CAAC;IAC1B,uGAAuG;IACvG,mBAAmB,IAAI,OAAO,CAAC;CAChC;AAED;+EAC+E;AAC/E,MAAM,WAAW,iBAAiB;IAChC,yFAAyF;IACzF,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,sFAAsF;IACtF,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,EAAE,EAAE,SAAS,CAAC;IACvB;;;0EAGsE;IACtE,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;kGAI8F;IAC9F,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IACvC;;sFAEkF;IAClF,QAAQ,CAAC,kBAAkB,CAAC,EAAE;QAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,CAAC;IACpG,0DAA0D;IAC1D,WAAW,IAAI,WAAW,CAAC;IAC3B;;sEAEkE;IAClE,mBAAmB,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IAC5D;;;mGAG+F;IAC/F,WAAW,CAAC,MAAM,EAAE,OAAO,GAAG,SAAS,EAAE,MAAM,CAAC,EAAE,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IAC1G,kGAAkG;IAClG,UAAU,CAAC,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IAC7E,oGAAoG;IACpG,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC;CACrD;AAED,6FAA6F;AAC7F,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,CAE7D"}
|
|
1
|
+
{"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEvC,4FAA4F;AAC5F,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,OAAO,CAAC;AAClD;sFACsF;AACtF,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC;AAE/B,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;CACxB;AAED,8FAA8F;AAC9F,MAAM,WAAW,gBAAgB;IAC/B,oDAAoD;IACpD,eAAe,IAAI,MAAM,CAAC;IAC1B,uGAAuG;IACvG,mBAAmB,IAAI,OAAO,CAAC;CAChC;AAED;+EAC+E;AAC/E,MAAM,WAAW,iBAAiB;IAChC,yFAAyF;IACzF,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,sFAAsF;IACtF,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,EAAE,EAAE,SAAS,CAAC;IACvB;;;0EAGsE;IACtE,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;kGAI8F;IAC9F,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IACvC;;qFAEiF;IACjF,QAAQ,CAAC,0BAA0B,CAAC,EAAE,OAAO,CAAC;IAC9C;;sFAEkF;IAClF,QAAQ,CAAC,kBAAkB,CAAC,EAAE;QAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,CAAC;IACpG,0DAA0D;IAC1D,WAAW,IAAI,WAAW,CAAC;IAC3B;;sEAEkE;IAClE,mBAAmB,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IAC5D;;;mGAG+F;IAC/F,WAAW,CAAC,MAAM,EAAE,OAAO,GAAG,SAAS,EAAE,MAAM,CAAC,EAAE,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IAC1G,kGAAkG;IAClG,UAAU,CAAC,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IAC7E,oGAAoG;IACpG,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC;CACrD;AAED,6FAA6F;AAC7F,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,CAE7D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../src/backends/claude.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../src/backends/claude.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEvC,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAM5E,qBAAa,aAAc,YAAW,OAAO;IAC3C,QAAQ,CAAC,EAAE,EAAG,QAAQ,CAAU;IAEhC,WAAW,IAAI,WAAW;IAgB1B,WAAW,CAAC,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS;IAe7E,UAAU,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS;IAKjD,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO;CAGpD"}
|
package/dist/backends/claude.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// ClaudeBackend — drives @agentclientprotocol/claude-agent-acp@0.
|
|
1
|
+
// ClaudeBackend — drives @agentclientprotocol/claude-agent-acp@0.56.0 (over the Claude
|
|
2
2
|
// Agent SDK). Structured output rides the vendor `_meta.claudeCode` channel at session/new:
|
|
3
3
|
// options.outputFormat = { type:"json_schema", schema } // the SDK's native constraint
|
|
4
4
|
// emitRawSDKMessages = true // MANDATORY to READ the result
|
|
@@ -31,7 +31,7 @@ export class ClaudeBackend {
|
|
|
31
31
|
// optional SessionMetaInputs (the seam still accepts them via the Backend interface).
|
|
32
32
|
if (!schema)
|
|
33
33
|
return undefined;
|
|
34
|
-
|
|
34
|
+
const meta = {
|
|
35
35
|
claudeCode: {
|
|
36
36
|
options: {
|
|
37
37
|
outputFormat: { type: "json_schema", schema: toJsonSchema(schema) },
|
|
@@ -39,6 +39,7 @@ export class ClaudeBackend {
|
|
|
39
39
|
emitRawSDKMessages: true,
|
|
40
40
|
},
|
|
41
41
|
};
|
|
42
|
+
return meta;
|
|
42
43
|
}
|
|
43
44
|
promptMeta() {
|
|
44
45
|
// Claude's schema is session-scoped (read at session/new); nothing on the turn.
|
|
@@ -11,6 +11,7 @@ export declare class CustomAcpBackend implements Backend {
|
|
|
11
11
|
* schema in the prompt — otherwise the model returns JSON with keys it invented and the
|
|
12
12
|
* repair ladder can never converge on a contract the model was never shown. */
|
|
13
13
|
readonly embedSchemaInPrompt = true;
|
|
14
|
+
readonly injectStructuredOutputTool: boolean;
|
|
14
15
|
readonly customCapabilities?: NonNullable<Backend["customCapabilities"]>;
|
|
15
16
|
constructor(config: RegisteredBackend);
|
|
16
17
|
spawnConfig(): SpawnConfig;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"custom.d.ts","sourceRoot":"","sources":["../../src/backends/custom.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"custom.d.ts","sourceRoot":"","sources":["../../src/backends/custom.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEvC,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAC5E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAIxD,qBAAa,gBAAiB,YAAW,OAAO;IAYlC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAXnC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB;mGAC+F;IAC/F,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB;;oFAEgF;IAChF,QAAQ,CAAC,mBAAmB,QAAQ;IACpC,QAAQ,CAAC,0BAA0B,EAAE,OAAO,CAAC;IAC7C,QAAQ,CAAC,kBAAkB,CAAC,EAAE,WAAW,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAC;gBAE5C,MAAM,EAAE,iBAAiB;IAYtD,WAAW,IAAI,WAAW;IAS1B,mBAAmB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS;IAQ1D,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS;IAM9E,UAAU,CAAC,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS;IAQ5E,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO;CAGpD"}
|
package/dist/backends/custom.js
CHANGED
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
// Claude/Codex pair. The generic dialect it speaks is the one this repo already publishes:
|
|
3
3
|
// - schema IN: the bare turn-level `_meta.outputSchema` (same key the @automatalabs/codex-acp
|
|
4
4
|
// fork reads), as a plain JSON Schema. An agent that honors it constrains its
|
|
5
|
-
// final message natively
|
|
6
|
-
//
|
|
5
|
+
// final message natively. When the negotiated agent advertises HTTP MCP support,
|
|
6
|
+
// the runner also injects a client-hosted StructuredOutput tool whose inputSchema
|
|
7
|
+
// carries the schema; agents that ignore both channels still work via the
|
|
8
|
+
// validate/re-prompt ladder over final text.
|
|
7
9
|
// - result OUT: JSON.parse of the final assistant message (with a balanced-block fallback),
|
|
8
10
|
// exactly like Codex — no vendor extension notification required.
|
|
9
11
|
// - config-level `_meta`: the registry entry's static `sessionMeta` rides every session/new
|
|
@@ -25,10 +27,12 @@ export class CustomAcpBackend {
|
|
|
25
27
|
* schema in the prompt — otherwise the model returns JSON with keys it invented and the
|
|
26
28
|
* repair ladder can never converge on a contract the model was never shown. */
|
|
27
29
|
embedSchemaInPrompt = true;
|
|
30
|
+
injectStructuredOutputTool;
|
|
28
31
|
customCapabilities;
|
|
29
32
|
constructor(config) {
|
|
30
33
|
this.config = config;
|
|
31
34
|
this.id = config.name;
|
|
35
|
+
this.injectStructuredOutputTool = config.structuredOutputTool ?? true;
|
|
32
36
|
if (config.customCapabilities)
|
|
33
37
|
this.customCapabilities = config.customCapabilities;
|
|
34
38
|
const spawnIdentity = JSON.stringify({
|
package/dist/pool.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Backend } from "./backend.js";
|
|
2
|
-
import { SessionHandle, type AcpSessionOptions } from "./acp-client.js";
|
|
2
|
+
import { PooledConnection, SessionHandle, type AcpSessionOptions } from "./acp-client.js";
|
|
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";
|
|
@@ -30,6 +30,11 @@ export declare class AcpAgentPool {
|
|
|
30
30
|
constructor(options?: AcpPoolOptions, deps?: AcpPoolDeps);
|
|
31
31
|
/** Acquire a session for one agent() run: get/grow a pooled connection and open a session. */
|
|
32
32
|
acquire(backend: Backend, opts: AcpSessionOptions): Promise<SessionHandle>;
|
|
33
|
+
/** Acquire a connection slot, then let the caller prepare session/new after initialize. */
|
|
34
|
+
acquirePrepared(backend: Backend, prepare: (connection: PooledConnection) => AcpSessionOptions | Promise<AcpSessionOptions>, context?: {
|
|
35
|
+
signal?: AbortSignal;
|
|
36
|
+
label?: string;
|
|
37
|
+
}): Promise<SessionHandle>;
|
|
33
38
|
/**
|
|
34
39
|
* Pick the connection to host the next session. Runs SYNCHRONOUSLY (no await) through to the
|
|
35
40
|
* synchronous load-reservation in openSession(), so concurrent acquires never over-spawn or
|
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,
|
|
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;AAKhF,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;CAChC;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;IA4BxB,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
|
@@ -48,6 +48,24 @@ export class AcpAgentPool {
|
|
|
48
48
|
});
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
|
+
/** Acquire a connection slot, then let the caller prepare session/new after initialize. */
|
|
52
|
+
async acquirePrepared(backend, prepare, context = {}) {
|
|
53
|
+
if (this.disposed)
|
|
54
|
+
throw new Error("ACP agent pool is disposed");
|
|
55
|
+
const connection = this.selectConnection(backend);
|
|
56
|
+
try {
|
|
57
|
+
return await connection.openPreparedSession(prepare);
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
if (context.signal?.aborted)
|
|
61
|
+
throw error;
|
|
62
|
+
throw mapThrownError(error, {
|
|
63
|
+
label: context.label,
|
|
64
|
+
backendId: connection.backendId,
|
|
65
|
+
authMethods: connection.capabilities?.authMethods,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
51
69
|
/**
|
|
52
70
|
* Pick the connection to host the next session. Runs SYNCHRONOUSLY (no await) through to the
|
|
53
71
|
* synchronous load-reservation in openSession(), so concurrent acquires never over-spawn or
|
package/dist/prompt.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ import type { Backend } from "./backend.js";
|
|
|
7
7
|
export declare function buildRunPrompt(prompt: string, opts: {
|
|
8
8
|
instructions?: string;
|
|
9
9
|
label?: string;
|
|
10
|
-
}, schema: TSchema | undefined, backend: Backend): string;
|
|
10
|
+
}, schema: TSchema | undefined, backend: Backend, structuredToolActive?: boolean): string;
|
|
11
11
|
/** Validate prompt images before spawning/sending. Invalid images are deterministic script
|
|
12
12
|
* errors, never provider failures, and the bad index is part of the contract for callers. */
|
|
13
13
|
export declare function validatePromptImages(images: readonly PromptImage[] | undefined, label?: string): void;
|
package/dist/prompt.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAGL,KAAK,WAAW,EACjB,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAG5C;4FAC4F;AAC5F,wBAAgB,cAAc,CAC5B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE;IAAE,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,EAC/C,MAAM,EAAE,OAAO,GAAG,SAAS,EAC3B,OAAO,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAGL,KAAK,WAAW,EACjB,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAG5C;4FAC4F;AAC5F,wBAAgB,cAAc,CAC5B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE;IAAE,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,EAC/C,MAAM,EAAE,OAAO,GAAG,SAAS,EAC3B,OAAO,EAAE,OAAO,EAChB,oBAAoB,UAAQ,GAC3B,MAAM,CAgCR;AAED;8FAC8F;AAC9F,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,GAAG,SAAS,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CA0BrG;AAgBD,qFAAqF;AACrF,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,WAAW,EAAE,GAAG,YAAY,EAAE,CAE7F;AAED;gEACgE;AAChE,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,GAAG,YAAY,EAAE,EAChC,MAAM,EAAE,SAAS,WAAW,EAAE,GAAG,SAAS,GACzC,MAAM,GAAG,YAAY,EAAE,CAIzB;AAED,8EAA8E;AAC9E,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EACzC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAC3C,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAGrC"}
|
package/dist/prompt.js
CHANGED
|
@@ -2,7 +2,7 @@ import { WorkflowError, WorkflowErrorCode, } from "@automatalabs/shared-types";
|
|
|
2
2
|
import { toJsonSchema } from "./schema-strict.js";
|
|
3
3
|
/** Build the exact one-shot run() prompt text: optional engine instructions, a diagnostic label,
|
|
4
4
|
* the user prompt, and (for schema runs) the backend-appropriate final-output contract. */
|
|
5
|
-
export function buildRunPrompt(prompt, opts, schema, backend) {
|
|
5
|
+
export function buildRunPrompt(prompt, opts, schema, backend, structuredToolActive = false) {
|
|
6
6
|
const parts = [];
|
|
7
7
|
if (opts.instructions)
|
|
8
8
|
parts.push(opts.instructions);
|
|
@@ -10,18 +10,29 @@ export function buildRunPrompt(prompt, opts, schema, backend) {
|
|
|
10
10
|
parts.push(`Task label: ${opts.label}`);
|
|
11
11
|
parts.push(prompt);
|
|
12
12
|
if (schema) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
13
|
+
if (structuredToolActive) {
|
|
14
|
+
parts.push([
|
|
15
|
+
"Final output contract:",
|
|
16
|
+
"- You have been provided an MCP tool named StructuredOutput (it may appear namespaced by its server, e.g. structured_output_StructuredOutput).",
|
|
17
|
+
"- You MUST call it exactly once with your final answer as its arguments; its parameter schema defines the required output shape.",
|
|
18
|
+
"- Complete all necessary research and tool calls BEFORE calling it.",
|
|
19
|
+
"- Do NOT emit your final answer as plain text.",
|
|
20
|
+
].join("\n"));
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
const contract = [
|
|
24
|
+
"Final output contract:",
|
|
25
|
+
"- Your FINAL message MUST be a single JSON object that conforms to the required output schema.",
|
|
26
|
+
"- Output ONLY that JSON object — no prose, no explanation, and no markdown code fences.",
|
|
27
|
+
"- If you need to inspect files or run commands first, do so, then emit the JSON object as your final message.",
|
|
28
|
+
];
|
|
29
|
+
if (backend.embedSchemaInPrompt) {
|
|
30
|
+
// Custom ACP agents may ignore `_meta.outputSchema`; state the schema in-band so the
|
|
31
|
+
// repair ladder is correcting against a visible contract, not an unseen extension key.
|
|
32
|
+
contract.push(`- The required output schema (JSON Schema):\n${JSON.stringify(toJsonSchema(schema))}`);
|
|
33
|
+
}
|
|
34
|
+
parts.push(contract.join("\n"));
|
|
23
35
|
}
|
|
24
|
-
parts.push(contract.join("\n"));
|
|
25
36
|
}
|
|
26
37
|
return parts.join("\n\n");
|
|
27
38
|
}
|
package/dist/registry.d.ts
CHANGED
|
@@ -16,6 +16,9 @@ export interface CustomBackendConfig {
|
|
|
16
16
|
readonly namespace: string;
|
|
17
17
|
readonly gatedKeys: readonly string[];
|
|
18
18
|
};
|
|
19
|
+
/** Enable client-hosted StructuredOutput MCP tool injection when schema runs negotiate HTTP MCP.
|
|
20
|
+
* Default true; set false for custom agents that should use only the generic prompt/_meta path. */
|
|
21
|
+
structuredOutputTool?: boolean;
|
|
19
22
|
}
|
|
20
23
|
/** A validated registry entry: the (lowercased) name plus its config. */
|
|
21
24
|
export interface RegisteredBackend extends CustomBackendConfig {
|
package/dist/registry.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,YAAY,wBAAwB,CAAC;AAKlD,0EAA0E;AAC1E,MAAM,WAAW,mBAAmB;IAClC,4DAA4D;IAC5D,OAAO,EAAE,MAAM,CAAC;IAChB,6CAA6C;IAC7C,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,mFAAmF;IACnF,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B;2FACuF;IACvF,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC;gFAC4E;IAC5E,kBAAkB,CAAC,EAAE;QAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,YAAY,wBAAwB,CAAC;AAKlD,0EAA0E;AAC1E,MAAM,WAAW,mBAAmB;IAClC,4DAA4D;IAC5D,OAAO,EAAE,MAAM,CAAC;IAChB,6CAA6C;IAC7C,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,mFAAmF;IACnF,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B;2FACuF;IACvF,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC;gFAC4E;IAC5E,kBAAkB,CAAC,EAAE;QAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,CAAC;IAC3F;wGACoG;IACpG,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED,yEAAyE;AACzE,MAAM,WAAW,iBAAkB,SAAQ,mBAAmB;IAC5D,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,eAAe,GAAG,WAAW,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;AAErE;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,EAC5C,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,eAAe,CAwBjB;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,eAAe,EACrB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,GACxC,eAAe,CAQjB"}
|
package/dist/registry.js
CHANGED
|
@@ -81,6 +81,9 @@ function validateEntry(rawName, config, source) {
|
|
|
81
81
|
if (c.sessionMeta !== undefined && (c.sessionMeta === null || typeof c.sessionMeta !== "object" || Array.isArray(c.sessionMeta))) {
|
|
82
82
|
throw new Error(`${source}: backend "${rawName}" "sessionMeta" must be an object`);
|
|
83
83
|
}
|
|
84
|
+
if (c.structuredOutputTool !== undefined && typeof c.structuredOutputTool !== "boolean") {
|
|
85
|
+
throw new Error(`${source}: backend "${rawName}" "structuredOutputTool" must be a boolean`);
|
|
86
|
+
}
|
|
84
87
|
const customCapabilities = validateCustomCapabilities(c.customCapabilities, source, rawName);
|
|
85
88
|
return [
|
|
86
89
|
name,
|
|
@@ -90,6 +93,7 @@ function validateEntry(rawName, config, source) {
|
|
|
90
93
|
...(c.args !== undefined ? { args: c.args } : {}),
|
|
91
94
|
...(c.env !== undefined ? { env: c.env } : {}),
|
|
92
95
|
...(c.sessionMeta !== undefined ? { sessionMeta: c.sessionMeta } : {}),
|
|
96
|
+
...(c.structuredOutputTool !== undefined ? { structuredOutputTool: c.structuredOutputTool } : {}),
|
|
93
97
|
...(customCapabilities !== undefined ? { customCapabilities } : {}),
|
|
94
98
|
},
|
|
95
99
|
];
|
package/dist/runner.d.ts
CHANGED
|
@@ -86,6 +86,11 @@ export interface AcpRunnerOptions extends AcpPoolOptions {
|
|
|
86
86
|
* elicitation form/url support on every connection; sessions may override the resolver. */
|
|
87
87
|
onElicitation?: ElicitationResolver;
|
|
88
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* ACP-backed AgentRunner implementation. The caller that constructs an AcpAgentRunner owns it:
|
|
91
|
+
* pass it into managers/runs as needed, then call dispose() (or use `await using`) when that
|
|
92
|
+
* owner is done with the pooled and dedicated backend processes.
|
|
93
|
+
*/
|
|
89
94
|
export declare class AcpAgentRunner implements AgentRunner {
|
|
90
95
|
private readonly pool;
|
|
91
96
|
/** The resolved custom-backend registry (env + option, validated at construction). */
|
|
@@ -100,6 +105,7 @@ export declare class AcpAgentRunner implements AgentRunner {
|
|
|
100
105
|
private readonly clientHandlers;
|
|
101
106
|
private readonly permissionResolver;
|
|
102
107
|
private readonly elicitationResolver;
|
|
108
|
+
private readonly structuredOutputTools;
|
|
103
109
|
/** Held-open interactive sessions own dedicated ACP processes outside the pool. The runner
|
|
104
110
|
* tracks their connections so dispose() can release them and the process-exit hook can
|
|
105
111
|
* synchronously kill any dedicated children if the host exits without release(). */
|
|
@@ -156,6 +162,7 @@ export declare class AcpAgentRunner implements AgentRunner {
|
|
|
156
162
|
/** Tear down the whole pool (close every long-lived process). Call when the run ends / the
|
|
157
163
|
* runner is disposed. Beyond the AgentRunner seam (additive) — never enters the resume hash. */
|
|
158
164
|
dispose(): Promise<void>;
|
|
165
|
+
[Symbol.asyncDispose](): Promise<void>;
|
|
159
166
|
private createInteractiveSession;
|
|
160
167
|
private createDedicatedConnection;
|
|
161
168
|
/** Build the backend choice, model-selection spec, tool policy, and session/new options in one
|
package/dist/runner.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAmBA,OAAO,EAGL,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,UAAU,EAChB,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EACV,mBAAmB,EACnB,oBAAoB,EACpB,UAAU,EAEV,sBAAsB,EACtB,uBAAuB,EAEvB,qBAAqB,EAErB,oBAAoB,EAEpB,cAAc,EACd,kBAAkB,EAClB,mBAAmB,EAEpB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEvC,OAAO,EAAgB,KAAK,cAAc,EAAE,MAAM,WAAW,CAAC;AAC9D,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,YAAY,EAGlB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,kBAAkB,EAAE,KAAK,yBAAyB,EAAE,MAAM,kBAAkB,CAAC;AAItF,OAAO,EAGL,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACzB,MAAM,eAAe,CAAC;AAEvB,OAAO,KAAK,EAAE,mBAAmB,EAAE,kBAAkB,EAAc,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"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"}
|
package/dist/runner.js
CHANGED
|
@@ -28,7 +28,14 @@ import { CustomAcpBackend } from "./backends/custom.js";
|
|
|
28
28
|
import { registryWithRunBackends, resolveBackendRegistry, } from "./registry.js";
|
|
29
29
|
import { mapThrownError } from "./errors-map.js";
|
|
30
30
|
import { resolveStructuredOutput } from "./structured-output.js";
|
|
31
|
+
import { STRUCTURED_OUTPUT_SERVER_NAME, StructuredOutputToolHost, } from "./structured-tool.js";
|
|
31
32
|
import { buildRunPrompt, mergeTurnMeta, promptWithImages, validatePromptImages, } from "./prompt.js";
|
|
33
|
+
const STRUCTURED_TOOL_REPROMPT_TEXT = "You did not call the StructuredOutput tool. Call the StructuredOutput tool now, exactly once, with your final answer as its arguments conforming to its parameter schema. Do not reply with plain text.";
|
|
34
|
+
/**
|
|
35
|
+
* ACP-backed AgentRunner implementation. The caller that constructs an AcpAgentRunner owns it:
|
|
36
|
+
* pass it into managers/runs as needed, then call dispose() (or use `await using`) when that
|
|
37
|
+
* owner is done with the pooled and dedicated backend processes.
|
|
38
|
+
*/
|
|
32
39
|
export class AcpAgentRunner {
|
|
33
40
|
pool;
|
|
34
41
|
/** The resolved custom-backend registry (env + option, validated at construction). */
|
|
@@ -43,6 +50,7 @@ export class AcpAgentRunner {
|
|
|
43
50
|
clientHandlers;
|
|
44
51
|
permissionResolver;
|
|
45
52
|
elicitationResolver;
|
|
53
|
+
structuredOutputTools = new StructuredOutputToolHost();
|
|
46
54
|
/** Held-open interactive sessions own dedicated ACP processes outside the pool. The runner
|
|
47
55
|
* tracks their connections so dispose() can release them and the process-exit hook can
|
|
48
56
|
* synchronously kill any dedicated children if the host exits without release(). */
|
|
@@ -312,8 +320,29 @@ export class AcpAgentRunner {
|
|
|
312
320
|
signal: opts.signal,
|
|
313
321
|
});
|
|
314
322
|
let session;
|
|
323
|
+
let structuredTool;
|
|
324
|
+
let structuredToolActive = false;
|
|
315
325
|
try {
|
|
316
|
-
session = await this.pool.
|
|
326
|
+
session = await this.pool.acquirePrepared(prepared.backend, async (connection) => {
|
|
327
|
+
let sessionOptions = prepared.sessionOptions;
|
|
328
|
+
if (shouldInjectStructuredOutputTool(schema, prepared.backend, connection.capabilities)) {
|
|
329
|
+
structuredTool = await this.structuredOutputTools.register(schema);
|
|
330
|
+
structuredToolActive = true;
|
|
331
|
+
sessionOptions = {
|
|
332
|
+
...sessionOptions,
|
|
333
|
+
mcpServers: [
|
|
334
|
+
...(sessionOptions.mcpServers ?? []),
|
|
335
|
+
{
|
|
336
|
+
type: "http",
|
|
337
|
+
name: nextStructuredOutputServerName(sessionOptions.mcpServers),
|
|
338
|
+
url: structuredTool.url,
|
|
339
|
+
headers: [],
|
|
340
|
+
},
|
|
341
|
+
],
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
return sessionOptions;
|
|
345
|
+
}, { signal: opts.signal, label: opts.label });
|
|
317
346
|
const activeSession = session;
|
|
318
347
|
opts.signal?.throwIfAborted();
|
|
319
348
|
// For a CUSTOM backend chosen by its registered name, the name itself is routing, not a
|
|
@@ -323,7 +352,7 @@ export class AcpAgentRunner {
|
|
|
323
352
|
opts.signal?.throwIfAborted();
|
|
324
353
|
if (opts.mode)
|
|
325
354
|
await activeSession.setMode(opts.mode);
|
|
326
|
-
const text = buildRunPrompt(prompt, opts, schema, prepared.backend);
|
|
355
|
+
const text = buildRunPrompt(prompt, opts, schema, prepared.backend, structuredToolActive);
|
|
327
356
|
const initialPrompt = opts.images && opts.images.length > 0 ? promptWithImages(text, opts.images) : text;
|
|
328
357
|
// Generic turn-scoped _meta passthrough merged UNDER the backend-computed keys (e.g. the
|
|
329
358
|
// outputSchema forward when a schema is set) — user meta never clobbers the schema channel.
|
|
@@ -343,12 +372,14 @@ export class AcpAgentRunner {
|
|
|
343
372
|
assertNormalStopReason(repromptResponse.stopReason, opts.label);
|
|
344
373
|
},
|
|
345
374
|
lastText: () => activeSession.currentTurnText(),
|
|
375
|
+
tryCaptured: structuredTool ? () => structuredTool?.tryCaptured() : undefined,
|
|
346
376
|
tryNative: () => prepared.backend.nativeStructured(activeSession),
|
|
347
377
|
};
|
|
348
378
|
const result = await resolveStructuredOutput(structuredSession, schema, {
|
|
349
379
|
maxSchemaRetries: opts.maxSchemaRetries,
|
|
350
380
|
signal: opts.signal,
|
|
351
381
|
label: opts.label,
|
|
382
|
+
...(structuredToolActive ? { repromptText: STRUCTURED_TOOL_REPROMPT_TEXT } : {}),
|
|
352
383
|
});
|
|
353
384
|
return result;
|
|
354
385
|
}
|
|
@@ -372,6 +403,7 @@ export class AcpAgentRunner {
|
|
|
372
403
|
});
|
|
373
404
|
}
|
|
374
405
|
finally {
|
|
406
|
+
structuredTool?.release();
|
|
375
407
|
if (session) {
|
|
376
408
|
// Read real usage on BOTH success and error so partial usage is never lost.
|
|
377
409
|
try {
|
|
@@ -403,9 +435,17 @@ export class AcpAgentRunner {
|
|
|
403
435
|
this.removeExitHook();
|
|
404
436
|
const sessions = [...this.interactiveSessions.keys()];
|
|
405
437
|
await Promise.all(sessions.map((session) => session.release()));
|
|
406
|
-
|
|
438
|
+
try {
|
|
439
|
+
await this.pool.dispose();
|
|
440
|
+
}
|
|
441
|
+
finally {
|
|
442
|
+
await this.structuredOutputTools.dispose();
|
|
443
|
+
}
|
|
407
444
|
this.events.removeAllListeners();
|
|
408
445
|
}
|
|
446
|
+
async [Symbol.asyncDispose]() {
|
|
447
|
+
await this.dispose();
|
|
448
|
+
}
|
|
409
449
|
async createInteractiveSession(opts, methodName, open) {
|
|
410
450
|
if (this.disposed)
|
|
411
451
|
throw new Error("ACP agent runner is disposed");
|
|
@@ -569,6 +609,22 @@ function assertNormalStopReason(stopReason, label) {
|
|
|
569
609
|
return;
|
|
570
610
|
}
|
|
571
611
|
}
|
|
612
|
+
function shouldInjectStructuredOutputTool(schema, backend, capabilities) {
|
|
613
|
+
return Boolean(schema && backend.injectStructuredOutputTool && supportsStructuredOutputToolTransport(capabilities));
|
|
614
|
+
}
|
|
615
|
+
function supportsStructuredOutputToolTransport(capabilities) {
|
|
616
|
+
return capabilities?.agent.mcpCapabilities?.http === true;
|
|
617
|
+
}
|
|
618
|
+
function nextStructuredOutputServerName(servers) {
|
|
619
|
+
const used = new Set((servers ?? []).map((server) => server.name));
|
|
620
|
+
let candidate = STRUCTURED_OUTPUT_SERVER_NAME;
|
|
621
|
+
let suffix = 2;
|
|
622
|
+
while (used.has(candidate)) {
|
|
623
|
+
candidate = `${STRUCTURED_OUTPUT_SERVER_NAME}_${suffix}`;
|
|
624
|
+
suffix += 1;
|
|
625
|
+
}
|
|
626
|
+
return candidate;
|
|
627
|
+
}
|
|
572
628
|
async function applyModelSelection(session, spec, opts) {
|
|
573
629
|
// `spec` is opts.model ?? opts.tier (`model` wins — frozen contract), with a custom
|
|
574
630
|
// backend's routing name already stripped by innerModelSpec.
|
|
@@ -29,12 +29,15 @@ export interface StructuredSession {
|
|
|
29
29
|
lastText(): string;
|
|
30
30
|
/** The backend's native structured result for the latest turn (unvalidated), or undefined. */
|
|
31
31
|
tryNative(): unknown;
|
|
32
|
+
/** Captured StructuredOutput MCP tool arguments, when client-hosted injection is active. */
|
|
33
|
+
tryCaptured?(): unknown | undefined;
|
|
32
34
|
}
|
|
33
35
|
export interface ResolveOptions {
|
|
34
36
|
/** Extra repair turns before giving up. Leaf default 2 (matches pi). */
|
|
35
37
|
maxSchemaRetries?: number;
|
|
36
38
|
signal?: AbortSignal;
|
|
37
39
|
label?: string;
|
|
40
|
+
repromptText?: string;
|
|
38
41
|
}
|
|
39
42
|
/**
|
|
40
43
|
* Resolve a schema agent's result via the ladder above. Returns the validated value (typed
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"structured-output.d.ts","sourceRoot":"","sources":["../src/structured-output.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"structured-output.d.ts","sourceRoot":"","sources":["../src/structured-output.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAIvC;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAa9D;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAiBpD;AAED,gGAAgG;AAChG,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAQtE;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAUvE;AAED,sGAAsG;AACtG,MAAM,WAAW,iBAAiB;IAChC,mDAAmD;IACnD,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,+DAA+D;IAC/D,QAAQ,IAAI,MAAM,CAAC;IACnB,8FAA8F;IAC9F,SAAS,IAAI,OAAO,CAAC;IACrB,4FAA4F;IAC5F,WAAW,CAAC,IAAI,OAAO,GAAG,SAAS,CAAC;CACrC;AAED,MAAM,WAAW,cAAc;IAC7B,wEAAwE;IACxE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAQD;;;;GAIG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,iBAAiB,EAC1B,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,OAAO,CAAC,CAgClB"}
|
|
@@ -93,6 +93,12 @@ const REPROMPT_TEXT = [
|
|
|
93
93
|
*/
|
|
94
94
|
export async function resolveStructuredOutput(session, schema, options) {
|
|
95
95
|
const tryResolve = () => {
|
|
96
|
+
const captured = session.tryCaptured?.();
|
|
97
|
+
if (captured !== undefined) {
|
|
98
|
+
const validated = validateValue(captured, schema);
|
|
99
|
+
if (validated !== undefined)
|
|
100
|
+
return validated;
|
|
101
|
+
}
|
|
96
102
|
const native = session.tryNative();
|
|
97
103
|
if (native !== undefined && native !== null) {
|
|
98
104
|
const validated = validateValue(native, schema);
|
|
@@ -105,9 +111,10 @@ export async function resolveStructuredOutput(session, schema, options) {
|
|
|
105
111
|
if (resolved !== undefined)
|
|
106
112
|
return resolved;
|
|
107
113
|
const maxRetries = Math.max(0, options.maxSchemaRetries ?? 2);
|
|
114
|
+
const repromptText = options.repromptText ?? REPROMPT_TEXT;
|
|
108
115
|
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
109
116
|
options.signal?.throwIfAborted();
|
|
110
|
-
await session.prompt(
|
|
117
|
+
await session.prompt(repromptText);
|
|
111
118
|
resolved = tryResolve();
|
|
112
119
|
if (resolved !== undefined)
|
|
113
120
|
return resolved;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type Tool } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
import type { TSchema } from "typebox";
|
|
3
|
+
export declare const STRUCTURED_OUTPUT_TOOL_NAME = "StructuredOutput";
|
|
4
|
+
export declare const STRUCTURED_OUTPUT_SERVER_NAME = "structured_output";
|
|
5
|
+
export declare const STRUCTURED_OUTPUT_TOOL_DESCRIPTION: string;
|
|
6
|
+
export interface StructuredOutputToolRegistration {
|
|
7
|
+
readonly url: string;
|
|
8
|
+
tryCaptured(): unknown | undefined;
|
|
9
|
+
release(): void;
|
|
10
|
+
}
|
|
11
|
+
/** Runner-scoped localhost MCP host. It binds only once a schema run actually needs injection. */
|
|
12
|
+
export declare class StructuredOutputToolHost {
|
|
13
|
+
private readonly slots;
|
|
14
|
+
private server;
|
|
15
|
+
private listenPromise;
|
|
16
|
+
private port;
|
|
17
|
+
isListening(): boolean;
|
|
18
|
+
listeningPort(): number | undefined;
|
|
19
|
+
register(schema: TSchema): Promise<StructuredOutputToolRegistration>;
|
|
20
|
+
dispose(): Promise<void>;
|
|
21
|
+
private ensureListening;
|
|
22
|
+
private handleRequest;
|
|
23
|
+
private slotFor;
|
|
24
|
+
}
|
|
25
|
+
export declare function structuredToolInputSchema(schema: TSchema): Tool["inputSchema"];
|
|
26
|
+
//# sourceMappingURL=structured-tool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"structured-tool.d.ts","sourceRoot":"","sources":["../src/structured-tool.ts"],"names":[],"mappings":"AASA,OAAO,EAOL,KAAK,IAAI,EACV,MAAM,oCAAoC,CAAC;AAC5C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAKvC,eAAO,MAAM,2BAA2B,qBAAqB,CAAC;AAC9D,eAAO,MAAM,6BAA6B,sBAAsB,CAAC;AAEjE,eAAO,MAAM,kCAAkC,QAM2C,CAAC;AAW3F,MAAM,WAAW,gCAAgC;IAC/C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,WAAW,IAAI,OAAO,GAAG,SAAS,CAAC;IACnC,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,kGAAkG;AAClG,qBAAa,wBAAwB;IACnC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA2B;IACjD,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,CAAC,aAAa,CAA4B;IACjD,OAAO,CAAC,IAAI,CAAqB;IAEjC,WAAW,IAAI,OAAO;IAItB,aAAa,IAAI,MAAM,GAAG,SAAS;IAI7B,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,gCAAgC,CAAC;IAwBpE,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;YAYhB,eAAe;YAoCf,aAAa;IAyB3B,OAAO,CAAC,OAAO;CAahB;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,CAI9E"}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
import http from "node:http";
|
|
3
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
4
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
5
|
+
import { CallToolRequestSchema, ErrorCode, ListToolsRequestSchema, McpError, } from "@modelcontextprotocol/sdk/types.js";
|
|
6
|
+
import { Convert, Errors } from "typebox/value";
|
|
7
|
+
import { toJsonSchema } from "./schema-strict.js";
|
|
8
|
+
import { validateValue } from "./structured-output.js";
|
|
9
|
+
export const STRUCTURED_OUTPUT_TOOL_NAME = "StructuredOutput";
|
|
10
|
+
export const STRUCTURED_OUTPUT_SERVER_NAME = "structured_output";
|
|
11
|
+
export const STRUCTURED_OUTPUT_TOOL_DESCRIPTION = "Use this tool to return your final response in the requested structured format.\n\n" +
|
|
12
|
+
"IMPORTANT:\n" +
|
|
13
|
+
"- You MUST call this tool exactly once at the end of your response\n" +
|
|
14
|
+
"- The input must be valid JSON matching the required schema\n" +
|
|
15
|
+
"- Complete all necessary research and tool calls BEFORE calling this tool\n" +
|
|
16
|
+
"- This tool provides your final answer - no further actions are taken after calling it";
|
|
17
|
+
const HOST = "127.0.0.1";
|
|
18
|
+
/** Runner-scoped localhost MCP host. It binds only once a schema run actually needs injection. */
|
|
19
|
+
export class StructuredOutputToolHost {
|
|
20
|
+
slots = new Map();
|
|
21
|
+
server;
|
|
22
|
+
listenPromise;
|
|
23
|
+
port;
|
|
24
|
+
isListening() {
|
|
25
|
+
return this.server?.listening === true;
|
|
26
|
+
}
|
|
27
|
+
listeningPort() {
|
|
28
|
+
return this.port;
|
|
29
|
+
}
|
|
30
|
+
async register(schema) {
|
|
31
|
+
const token = randomBytes(16).toString("hex");
|
|
32
|
+
const slot = {
|
|
33
|
+
token,
|
|
34
|
+
schema,
|
|
35
|
+
inputSchema: structuredToolInputSchema(schema),
|
|
36
|
+
captured: undefined,
|
|
37
|
+
};
|
|
38
|
+
this.slots.set(token, slot);
|
|
39
|
+
try {
|
|
40
|
+
const port = await this.ensureListening();
|
|
41
|
+
return {
|
|
42
|
+
url: `http://${HOST}:${port}/${token}`,
|
|
43
|
+
tryCaptured: () => slot.captured,
|
|
44
|
+
release: once(() => {
|
|
45
|
+
this.slots.delete(token);
|
|
46
|
+
}),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
this.slots.delete(token);
|
|
51
|
+
throw error;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
async dispose() {
|
|
55
|
+
this.slots.clear();
|
|
56
|
+
const server = this.server;
|
|
57
|
+
this.server = undefined;
|
|
58
|
+
this.listenPromise = undefined;
|
|
59
|
+
this.port = undefined;
|
|
60
|
+
if (!server || !server.listening)
|
|
61
|
+
return;
|
|
62
|
+
await new Promise((resolve, reject) => {
|
|
63
|
+
server.close((error) => (error ? reject(error) : resolve()));
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
async ensureListening() {
|
|
67
|
+
if (!this.server) {
|
|
68
|
+
this.server = http.createServer((req, res) => {
|
|
69
|
+
void this.handleRequest(req, res);
|
|
70
|
+
});
|
|
71
|
+
this.server.unref();
|
|
72
|
+
}
|
|
73
|
+
if (!this.listenPromise) {
|
|
74
|
+
this.listenPromise = new Promise((resolve, reject) => {
|
|
75
|
+
const server = this.server;
|
|
76
|
+
const onError = (error) => {
|
|
77
|
+
server.off("listening", onListening);
|
|
78
|
+
reject(error);
|
|
79
|
+
};
|
|
80
|
+
const onListening = () => {
|
|
81
|
+
server.off("error", onError);
|
|
82
|
+
const address = server.address();
|
|
83
|
+
if (!address || typeof address === "string") {
|
|
84
|
+
reject(new Error("StructuredOutput MCP server did not bind to a TCP port"));
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
this.port = address.port;
|
|
88
|
+
resolve();
|
|
89
|
+
};
|
|
90
|
+
server.once("error", onError);
|
|
91
|
+
server.once("listening", onListening);
|
|
92
|
+
server.listen(0, HOST);
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
await this.listenPromise;
|
|
96
|
+
if (this.port === undefined) {
|
|
97
|
+
throw new Error("StructuredOutput MCP server has no listening port");
|
|
98
|
+
}
|
|
99
|
+
return this.port;
|
|
100
|
+
}
|
|
101
|
+
async handleRequest(req, res) {
|
|
102
|
+
const slot = this.slotFor(req);
|
|
103
|
+
if (!slot) {
|
|
104
|
+
res.writeHead(404, { "content-type": "text/plain; charset=utf-8" });
|
|
105
|
+
res.end("not found");
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined });
|
|
109
|
+
const server = createMcpServer(slot);
|
|
110
|
+
try {
|
|
111
|
+
await server.connect(transport);
|
|
112
|
+
await transport.handleRequest(req, res);
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
if (!res.headersSent) {
|
|
116
|
+
res.writeHead(500, { "content-type": "text/plain; charset=utf-8" });
|
|
117
|
+
res.end(error instanceof Error ? error.message : String(error));
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
res.destroy(error instanceof Error ? error : undefined);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
finally {
|
|
124
|
+
await Promise.allSettled([server.close(), transport.close()]);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
slotFor(req) {
|
|
128
|
+
const rawUrl = req.url ?? "/";
|
|
129
|
+
let pathname;
|
|
130
|
+
try {
|
|
131
|
+
pathname = new URL(rawUrl, `http://${HOST}`).pathname;
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
return undefined;
|
|
135
|
+
}
|
|
136
|
+
if (!pathname.startsWith("/") || pathname.slice(1).includes("/"))
|
|
137
|
+
return undefined;
|
|
138
|
+
const token = pathname.slice(1);
|
|
139
|
+
if (!token)
|
|
140
|
+
return undefined;
|
|
141
|
+
return this.slots.get(token);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
export function structuredToolInputSchema(schema) {
|
|
145
|
+
const json = toJsonSchema(schema);
|
|
146
|
+
delete json.$schema;
|
|
147
|
+
return json;
|
|
148
|
+
}
|
|
149
|
+
function createMcpServer(slot) {
|
|
150
|
+
const server = new Server({ name: "agentprism-structured-output", version: "0.1.0" }, { capabilities: { tools: {} } });
|
|
151
|
+
server.setRequestHandler(ListToolsRequestSchema, () => ({
|
|
152
|
+
tools: [
|
|
153
|
+
{
|
|
154
|
+
name: STRUCTURED_OUTPUT_TOOL_NAME,
|
|
155
|
+
description: STRUCTURED_OUTPUT_TOOL_DESCRIPTION,
|
|
156
|
+
inputSchema: slot.inputSchema,
|
|
157
|
+
},
|
|
158
|
+
],
|
|
159
|
+
}));
|
|
160
|
+
server.setRequestHandler(CallToolRequestSchema, (request) => {
|
|
161
|
+
if (request.params.name !== STRUCTURED_OUTPUT_TOOL_NAME) {
|
|
162
|
+
throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${request.params.name}`);
|
|
163
|
+
}
|
|
164
|
+
const args = request.params.arguments ?? {};
|
|
165
|
+
const validated = validateValue(args, slot.schema);
|
|
166
|
+
if (validated !== undefined) {
|
|
167
|
+
slot.captured = validated;
|
|
168
|
+
return textResult("Structured output captured successfully.");
|
|
169
|
+
}
|
|
170
|
+
return textResult(rejectionText(args, slot.schema), true);
|
|
171
|
+
});
|
|
172
|
+
return server;
|
|
173
|
+
}
|
|
174
|
+
function textResult(text, isError) {
|
|
175
|
+
return {
|
|
176
|
+
content: [{ type: "text", text }],
|
|
177
|
+
...(isError ? { isError: true } : {}),
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
function rejectionText(value, schema) {
|
|
181
|
+
let converted;
|
|
182
|
+
try {
|
|
183
|
+
converted = Convert(schema, value);
|
|
184
|
+
}
|
|
185
|
+
catch {
|
|
186
|
+
converted = value;
|
|
187
|
+
}
|
|
188
|
+
const details = Errors(schema, converted)
|
|
189
|
+
.slice(0, 3)
|
|
190
|
+
.map((error) => `${error.instancePath || "/"} ${error.message}`)
|
|
191
|
+
.join("; ");
|
|
192
|
+
return [
|
|
193
|
+
"Structured output rejected: arguments do not match the required schema.",
|
|
194
|
+
details,
|
|
195
|
+
"Fix the arguments and call StructuredOutput again.",
|
|
196
|
+
]
|
|
197
|
+
.filter(Boolean)
|
|
198
|
+
.join(" ");
|
|
199
|
+
}
|
|
200
|
+
function once(fn) {
|
|
201
|
+
let called = false;
|
|
202
|
+
return () => {
|
|
203
|
+
if (called)
|
|
204
|
+
return;
|
|
205
|
+
called = true;
|
|
206
|
+
fn();
|
|
207
|
+
};
|
|
208
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@automatalabs/acp-agents",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=22"
|
|
@@ -30,8 +30,9 @@
|
|
|
30
30
|
"@agentclientprotocol/sdk": "^1.2.0",
|
|
31
31
|
"@agentclientprotocol/claude-agent-acp": "0.56.0",
|
|
32
32
|
"@automatalabs/codex-acp": "1.4.0",
|
|
33
|
+
"@modelcontextprotocol/sdk": "^1.29",
|
|
33
34
|
"typebox": "1.3.2",
|
|
34
|
-
"@automatalabs/shared-types": "0.
|
|
35
|
+
"@automatalabs/shared-types": "0.12.0"
|
|
35
36
|
},
|
|
36
37
|
"scripts": {
|
|
37
38
|
"build": "tsc -b",
|