@asap-protocol/openai-agents 2.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/README.md +53 -0
  2. package/dist/commonjs/asap-as-remote-agent.d.ts +44 -0
  3. package/dist/commonjs/asap-as-remote-agent.d.ts.map +1 -0
  4. package/dist/commonjs/asap-as-remote-agent.js +119 -0
  5. package/dist/commonjs/asap-to-openai-tool.d.ts +34 -0
  6. package/dist/commonjs/asap-to-openai-tool.d.ts.map +1 -0
  7. package/dist/commonjs/asap-to-openai-tool.js +172 -0
  8. package/dist/commonjs/errors.d.ts +27 -0
  9. package/dist/commonjs/errors.d.ts.map +1 -0
  10. package/dist/commonjs/errors.js +53 -0
  11. package/dist/commonjs/index.d.ts +12 -0
  12. package/dist/commonjs/index.d.ts.map +1 -0
  13. package/dist/commonjs/index.js +37 -0
  14. package/dist/commonjs/package.json +3 -0
  15. package/dist/commonjs/schema-bridge.d.ts +8 -0
  16. package/dist/commonjs/schema-bridge.d.ts.map +1 -0
  17. package/dist/commonjs/schema-bridge.js +106 -0
  18. package/dist/commonjs/send-asap-envelope.d.ts +16 -0
  19. package/dist/commonjs/send-asap-envelope.d.ts.map +1 -0
  20. package/dist/commonjs/send-asap-envelope.js +100 -0
  21. package/dist/commonjs/streaming.d.ts +16 -0
  22. package/dist/commonjs/streaming.d.ts.map +1 -0
  23. package/dist/commonjs/streaming.js +45 -0
  24. package/dist/esm/asap-as-remote-agent.d.ts +44 -0
  25. package/dist/esm/asap-as-remote-agent.d.ts.map +1 -0
  26. package/dist/esm/asap-as-remote-agent.js +114 -0
  27. package/dist/esm/asap-to-openai-tool.d.ts +34 -0
  28. package/dist/esm/asap-to-openai-tool.d.ts.map +1 -0
  29. package/dist/esm/asap-to-openai-tool.js +168 -0
  30. package/dist/esm/errors.d.ts +27 -0
  31. package/dist/esm/errors.d.ts.map +1 -0
  32. package/dist/esm/errors.js +44 -0
  33. package/dist/esm/index.d.ts +12 -0
  34. package/dist/esm/index.d.ts.map +1 -0
  35. package/dist/esm/index.js +11 -0
  36. package/dist/esm/package.json +3 -0
  37. package/dist/esm/schema-bridge.d.ts +8 -0
  38. package/dist/esm/schema-bridge.d.ts.map +1 -0
  39. package/dist/esm/schema-bridge.js +103 -0
  40. package/dist/esm/send-asap-envelope.d.ts +16 -0
  41. package/dist/esm/send-asap-envelope.d.ts.map +1 -0
  42. package/dist/esm/send-asap-envelope.js +97 -0
  43. package/dist/esm/streaming.d.ts +16 -0
  44. package/dist/esm/streaming.d.ts.map +1 -0
  45. package/dist/esm/streaming.js +41 -0
  46. package/package.json +69 -0
package/README.md ADDED
@@ -0,0 +1,53 @@
1
+ # `@asap-protocol/openai-agents`
2
+
3
+ ## ⚠️ This is **not** `@asap-protocol/client/adapters/openai`
4
+
5
+ [`@asap-protocol/client/adapters/openai`](https://github.com/adriannoes/asap-protocol/tree/main/packages/typescript/client/src/adapters/openai.ts) exposes **`asapToolsForOpenAI`**, producing **static `ChatCompletionTool[]`** for the **OpenAI Chat Completions API** (`openai` npm package, no Agents runtime).
6
+
7
+ **`@asap-protocol/openai-agents`** integrates with the **`@openai/agents` SDK** (`Agent`, `tool()`, handoffs, `run()`). Different consumer and lifecycle — **both packages coexist**.
8
+
9
+ ## Overview
10
+
11
+ Maps ASAP **capabilities** to OpenAI Agents **`tool()`** definitions (using **`executeCapability`** from **`@asap-protocol/client`**), optionally wraps an **`Agent`** intended as a **handoff** target against an ASAP gateway, and bridges ASAP **`task_stream`** payloads into incremental **text deltas**.
12
+
13
+ ## Peer dependencies
14
+
15
+ | Package | Range |
16
+ |---------|-------|
17
+ | `@asap-protocol/client` | `^2.3.0` |
18
+ | `@openai/agents` | `^0.11.0` (patch drift tolerated; CI pins **`0.11.4`** + **`latest`**) |
19
+ | `zod` | `^4.1.8` (aligned with `@openai/agents`; Zod 3 is not supported) |
20
+
21
+ Node **≥ 18**.
22
+
23
+ !!! warning "Pre-1.0 `@openai/agents` API drift"
24
+
25
+ **`@openai/agents` is pre-1.0.** Minor/patch releases may change `Agent` constructor options, `tool()` parameter shapes, or default tool error handling. Pin your dependency and re-run tests after upgrades; CI exercises **`latest`** and **`0.11.4`**.
26
+
27
+ ## Usage
28
+
29
+ See [`docs/integrations/openai-agents.md`](../../../docs/integrations/openai-agents.md) and [`apps/example-openai-agents/`](../../../apps/example-openai-agents/).
30
+
31
+ ```typescript
32
+ import { Agent, run, setDefaultOpenAIKey } from "@openai/agents";
33
+ import type { AsapExecuteClient } from "@asap-protocol/client";
34
+ import { asapToolsForOpenAIAgents } from "@asap-protocol/openai-agents";
35
+
36
+ declare const client: AsapExecuteClient;
37
+
38
+ setDefaultOpenAIKey(process.env.OPENAI_API_KEY ?? "");
39
+
40
+ const tools = await asapToolsForOpenAIAgents(client);
41
+ const agent = new Agent({
42
+ name: "demo",
43
+ instructions: "Use ASAP tools when helpful.",
44
+ model: "gpt-4o-mini",
45
+ tools: [...tools],
46
+ });
47
+
48
+ await run(agent, "Echo hello via ASAP.");
49
+ ```
50
+
51
+ ## Status
52
+
53
+ Pre-release **`0.0.0`** workspace package until publish workflow promotes a semver tag.
@@ -0,0 +1,44 @@
1
+ import { Agent, type AgentInputItem } from "@openai/agents";
2
+ import type { AsapExecuteClient } from "@asap-protocol/client/adapters/shared";
3
+ import { type AsapToolsForOpenAIAgentsOptions } from "./asap-to-openai-tool.js";
4
+ export type AsapRemoteAgentMode = "delegated" | "autonomous";
5
+ /** Mutable bag carried through {@link RunContext} when using {@link asapAsRemoteAgent}. */
6
+ export interface AsapRemoteRunContext {
7
+ /** Latest draft ASAP envelope captured when this agent starts (including after an SDK handoff). */
8
+ lastAsapHandoffEnvelope?: Record<string, unknown>;
9
+ }
10
+ export interface AsapAsRemoteAgentOptions {
11
+ readonly mode?: AsapRemoteAgentMode;
12
+ readonly name?: string;
13
+ readonly instructions?: string | undefined;
14
+ readonly handoffDescription?: string;
15
+ readonly model?: string;
16
+ readonly toolsOptions?: AsapToolsForOpenAIAgentsOptions;
17
+ /**
18
+ * Agent JWT scoped to `providerUrl` when it differs from `client.provider`.
19
+ * Required for cross-provider handoffs when `client.agentJwt` is set.
20
+ */
21
+ readonly remoteAgentJwt?: string;
22
+ }
23
+ /**
24
+ * Returns whether two provider URLs refer to the same ASAP host path (origin + pathname).
25
+ */
26
+ export declare function sameProviderOrigin(a: URL, b: URL): boolean;
27
+ /**
28
+ * Draft `task.request`-style envelope metadata used when delegating from OpenAI Agents handoffs to ASAP.
29
+ *
30
+ * The gateway still performs authorization and routing; this object mirrors how adapters attach agent mode.
31
+ */
32
+ export declare function draftTaskRequestEnvelopeForRemoteAgent(params: {
33
+ readonly mode: AsapRemoteAgentMode;
34
+ readonly providerUrl: URL;
35
+ readonly turnInput?: string | AgentInputItem[];
36
+ }): Record<string, unknown>;
37
+ /**
38
+ * Returns an OpenAI Agents {@link Agent} backed by ASAP capability tools on `providerUrl`.
39
+ *
40
+ * Subscribes to `agent_start` so {@link AsapRemoteRunContext.lastAsapHandoffEnvelope} captures draft envelope metadata
41
+ * and POSTs a real `task.request` via JSON-RPC `asap.send` whenever this agent begins a turn—including after an SDK handoff.
42
+ */
43
+ export declare function asapAsRemoteAgent(client: AsapExecuteClient, providerUrl: string | URL, options?: AsapAsRemoteAgentOptions): Promise<Agent<AsapRemoteRunContext>>;
44
+ //# sourceMappingURL=asap-as-remote-agent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asap-as-remote-agent.d.ts","sourceRoot":"","sources":["../../src/asap-as-remote-agent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,KAAK,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAE5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAE/E,OAAO,EACL,KAAK,+BAA+B,EAErC,MAAM,0BAA0B,CAAC;AAGlC,MAAM,MAAM,mBAAmB,GAAG,WAAW,GAAG,YAAY,CAAC;AAE7D,2FAA2F;AAC3F,MAAM,WAAW,oBAAoB;IACnC,mGAAmG;IACnG,uBAAuB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnD;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,IAAI,CAAC,EAAE,mBAAmB,CAAC;IACpC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,YAAY,CAAC,EAAE,+BAA+B,CAAC;IACxD;;;OAGG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;CAClC;AAgBD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,GAAG,OAAO,CAE1D;AAED;;;;GAIG;AACH,wBAAgB,sCAAsC,CAAC,MAAM,EAAE;IAC7D,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;IACnC,QAAQ,CAAC,WAAW,EAAE,GAAG,CAAC;IAC1B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,cAAc,EAAE,CAAC;CAChD,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAmB1B;AAgDD;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,iBAAiB,EACzB,WAAW,EAAE,MAAM,GAAG,GAAG,EACzB,OAAO,CAAC,EAAE,wBAAwB,GACjC,OAAO,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC,CAgCtC"}
@@ -0,0 +1,119 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sameProviderOrigin = sameProviderOrigin;
4
+ exports.draftTaskRequestEnvelopeForRemoteAgent = draftTaskRequestEnvelopeForRemoteAgent;
5
+ exports.asapAsRemoteAgent = asapAsRemoteAgent;
6
+ const agents_1 = require("@openai/agents");
7
+ const asap_to_openai_tool_js_1 = require("./asap-to-openai-tool.js");
8
+ const send_asap_envelope_js_1 = require("./send-asap-envelope.js");
9
+ function serializeTurnInput(turnInput) {
10
+ if (turnInput === undefined) {
11
+ return "";
12
+ }
13
+ if (typeof turnInput === "string") {
14
+ return turnInput;
15
+ }
16
+ try {
17
+ return JSON.stringify(turnInput);
18
+ }
19
+ catch {
20
+ return "";
21
+ }
22
+ }
23
+ /**
24
+ * Returns whether two provider URLs refer to the same ASAP host path (origin + pathname).
25
+ */
26
+ function sameProviderOrigin(a, b) {
27
+ return a.origin === b.origin && a.pathname === b.pathname;
28
+ }
29
+ /**
30
+ * Draft `task.request`-style envelope metadata used when delegating from OpenAI Agents handoffs to ASAP.
31
+ *
32
+ * The gateway still performs authorization and routing; this object mirrors how adapters attach agent mode.
33
+ */
34
+ function draftTaskRequestEnvelopeForRemoteAgent(params) {
35
+ const delegatedInput = serializeTurnInput(params.turnInput);
36
+ return {
37
+ asap_version: "2.2",
38
+ sender: "urn:asap:agent:openai-agents-adapter",
39
+ recipient: params.providerUrl.href,
40
+ payload_type: "task.request",
41
+ payload: {
42
+ conversation_id: "openai-agents-handoff",
43
+ skill_id: "asap-remote-handoff",
44
+ input: {
45
+ query: delegatedInput,
46
+ asap_agent_mode: params.mode,
47
+ },
48
+ },
49
+ extensions: {
50
+ asap_agent_mode: params.mode,
51
+ },
52
+ };
53
+ }
54
+ function defaultInstructions(mode, capabilities) {
55
+ const list = capabilities.length > 0 ? capabilities.join(", ") : "(none configured)";
56
+ return [
57
+ "You are an ASAP-backed specialist agent invoked via OpenAI Agents SDK handoffs.",
58
+ `Operate in ${mode} mode with respect to host policy.`,
59
+ `Use the ASAP capability tools wired for this agent (deterministic keys). Capability URNs: ${list}.`,
60
+ "Pass structured JSON arguments that satisfy each capability schema.",
61
+ ].join(" ");
62
+ }
63
+ function resolveProvider(providerUrl) {
64
+ return typeof providerUrl === "string" ? new URL(providerUrl) : providerUrl;
65
+ }
66
+ function resolveHandoffJwt(client, providerUrl, options) {
67
+ if (options?.remoteAgentJwt !== undefined) {
68
+ return options.remoteAgentJwt;
69
+ }
70
+ if (client.agentJwt !== undefined && !sameProviderOrigin(client.provider, providerUrl)) {
71
+ throw new Error(`client.agentJwt is scoped to ${client.provider.href}; pass remoteAgentJwt when providerUrl (${providerUrl.href}) differs`);
72
+ }
73
+ return client.agentJwt;
74
+ }
75
+ function buildMergedClient(client, resolvedProvider, handoffJwt) {
76
+ const merged = {
77
+ ...client,
78
+ provider: resolvedProvider,
79
+ };
80
+ if (handoffJwt !== undefined) {
81
+ return { ...merged, agentJwt: handoffJwt };
82
+ }
83
+ const { agentJwt: _omit, ...withoutJwt } = merged;
84
+ return withoutJwt;
85
+ }
86
+ /**
87
+ * Returns an OpenAI Agents {@link Agent} backed by ASAP capability tools on `providerUrl`.
88
+ *
89
+ * Subscribes to `agent_start` so {@link AsapRemoteRunContext.lastAsapHandoffEnvelope} captures draft envelope metadata
90
+ * and POSTs a real `task.request` via JSON-RPC `asap.send` whenever this agent begins a turn—including after an SDK handoff.
91
+ */
92
+ async function asapAsRemoteAgent(client, providerUrl, options) {
93
+ const mode = options?.mode ?? "delegated";
94
+ const resolvedProvider = resolveProvider(providerUrl);
95
+ const handoffJwt = resolveHandoffJwt(client, resolvedProvider, options);
96
+ const mergedClient = buildMergedClient(client, resolvedProvider, handoffJwt);
97
+ const tools = await (0, asap_to_openai_tool_js_1.asapToolsForOpenAIAgents)(mergedClient, options?.toolsOptions);
98
+ const agent = new agents_1.Agent({
99
+ name: options?.name ?? `asap-remote-${resolvedProvider.hostname}`,
100
+ instructions: options?.instructions ?? defaultInstructions(mode, mergedClient.capabilities),
101
+ handoffDescription: options?.handoffDescription ??
102
+ `Delegates to ASAP capabilities at ${resolvedProvider.href} (${mode} mode).`,
103
+ model: options?.model ?? "gpt-4o-mini",
104
+ tools: [...tools],
105
+ });
106
+ agent.on("agent_start", (runContext, _self, turnInput) => {
107
+ const draft = draftTaskRequestEnvelopeForRemoteAgent({
108
+ mode,
109
+ providerUrl: resolvedProvider,
110
+ turnInput,
111
+ });
112
+ runContext.context.lastAsapHandoffEnvelope = draft;
113
+ void (0, send_asap_envelope_js_1.sendAsapEnvelope)(resolvedProvider, draft, {
114
+ fetch: mergedClient.fetch,
115
+ agentJwt: mergedClient.agentJwt,
116
+ });
117
+ });
118
+ return agent;
119
+ }
@@ -0,0 +1,34 @@
1
+ import { tool } from "@openai/agents";
2
+ import { type AsapExecuteClient } from "@asap-protocol/client/adapters/shared";
3
+ export interface AsapToolsForOpenAIAgentsOptions {
4
+ /**
5
+ * Invoked when the provider returns `403` with `error.code === "capability_not_granted"`.
6
+ */
7
+ readonly requestCapability?: (requiredCapability: string) => void | Promise<void>;
8
+ readonly inputSchemas?: Readonly<Record<string, unknown>>;
9
+ readonly outputSchemas?: Readonly<Record<string, unknown>>;
10
+ /**
11
+ * Called when {@link describeCapability} fails for a capability. The error is rethrown unless
12
+ * {@link allowPermissiveDescribeFallback} is `true`.
13
+ */
14
+ readonly onDescribeError?: (capabilityId: string, error: unknown) => void;
15
+ /**
16
+ * When `true`, failed describe calls fall back to generic tool metadata instead of failing
17
+ * tool construction. Defaults to `false`.
18
+ */
19
+ readonly allowPermissiveDescribeFallback?: boolean;
20
+ /** Passed to {@link describeCapability} and {@link executeCapability} fetch calls. */
21
+ readonly signal?: AbortSignal;
22
+ }
23
+ /**
24
+ * Build OpenAI Agents SDK {@link tool} instances for each ASAP capability on the client.
25
+ *
26
+ * Uses top-level {@link executeCapability} from `@asap-protocol/client` on each execution path.
27
+ */
28
+ export declare function asapToolsForOpenAIAgents(client: AsapExecuteClient, options?: AsapToolsForOpenAIAgentsOptions): Promise<readonly ReturnType<typeof tool>[]>;
29
+ /**
30
+ * Synchronous variant when {@link AsapToolsForOpenAIAgentsOptions.inputSchemas} / `outputSchemas`
31
+ * are already materialized (skips describe round-trips).
32
+ */
33
+ export declare function asapToolsForOpenAIAgentsSync(client: AsapExecuteClient, options?: AsapToolsForOpenAIAgentsOptions): readonly ReturnType<typeof tool>[];
34
+ //# sourceMappingURL=asap-to-openai-tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asap-to-openai-tool.d.ts","sourceRoot":"","sources":["../../src/asap-to-openai-tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAEtC,OAAO,EAGL,KAAK,iBAAiB,EACvB,MAAM,uCAAuC,CAAC;AAiC/C,MAAM,WAAW,+BAA+B;IAC9C;;OAEG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC,kBAAkB,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClF,QAAQ,CAAC,YAAY,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC1D,QAAQ,CAAC,aAAa,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC3D;;;OAGG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAC1E;;;OAGG;IACH,QAAQ,CAAC,+BAA+B,CAAC,EAAE,OAAO,CAAC;IACnD,sFAAsF;IACtF,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;CAC/B;AAuID;;;;GAIG;AACH,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,iBAAiB,EACzB,OAAO,CAAC,EAAE,+BAA+B,GACxC,OAAO,CAAC,SAAS,UAAU,CAAC,OAAO,IAAI,CAAC,EAAE,CAAC,CA4C7C;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,iBAAiB,EACzB,OAAO,CAAC,EAAE,+BAA+B,GACxC,SAAS,UAAU,CAAC,OAAO,IAAI,CAAC,EAAE,CAepC"}
@@ -0,0 +1,172 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.asapToolsForOpenAIAgents = asapToolsForOpenAIAgents;
4
+ exports.asapToolsForOpenAIAgentsSync = asapToolsForOpenAIAgentsSync;
5
+ const agents_1 = require("@openai/agents");
6
+ const client_1 = require("@asap-protocol/client");
7
+ const shared_1 = require("@asap-protocol/client/adapters/shared");
8
+ const zod_1 = require("zod");
9
+ const errors_js_1 = require("./errors.js");
10
+ const schema_bridge_js_1 = require("./schema-bridge.js");
11
+ function buildToolParameters(inputJson) {
12
+ const props = inputJson.properties;
13
+ const hasProps = inputJson.type === "object" &&
14
+ typeof props === "object" &&
15
+ props !== null &&
16
+ !Array.isArray(props) &&
17
+ Object.keys(props).length > 0;
18
+ if (hasProps) {
19
+ const zSch = (0, schema_bridge_js_1.zodFromJsonSchema)(inputJson);
20
+ if (zSch instanceof zod_1.z.ZodObject) {
21
+ return { mode: "zod", schema: zSch.strict() };
22
+ }
23
+ }
24
+ return { mode: "json", schema: inputJson };
25
+ }
26
+ const DESCRIBE_CONCURRENCY = 5;
27
+ async function mapInBatches(items, batchSize, fn) {
28
+ const results = [];
29
+ for (let i = 0; i < items.length; i += batchSize) {
30
+ const batch = items.slice(i, i + batchSize);
31
+ const batchResults = await Promise.all(batch.map(fn));
32
+ results.push(...batchResults);
33
+ }
34
+ return results;
35
+ }
36
+ function isRecord(x) {
37
+ return typeof x === "object" && x !== null && !Array.isArray(x);
38
+ }
39
+ function wrapFetchWithCapabilityErrors(base, options) {
40
+ const impl = base ?? globalThis.fetch;
41
+ return async (input, init) => {
42
+ const res = await impl(input, init);
43
+ if (res.status !== 403) {
44
+ return res;
45
+ }
46
+ const text = await res.clone().text();
47
+ let parsed;
48
+ try {
49
+ parsed = text.length === 0 ? {} : JSON.parse(text);
50
+ }
51
+ catch {
52
+ return new Response(text, { status: res.status, statusText: res.statusText, headers: res.headers });
53
+ }
54
+ if (!isRecord(parsed)) {
55
+ return new Response(text, { status: res.status, statusText: res.statusText, headers: res.headers });
56
+ }
57
+ if (parsed.error === "constraint_violated") {
58
+ return new Response(text, { status: res.status, statusText: res.statusText, headers: res.headers });
59
+ }
60
+ const errObj = parsed.error;
61
+ if (!isRecord(errObj)) {
62
+ return new Response(text, { status: res.status, statusText: res.statusText, headers: res.headers });
63
+ }
64
+ const code = errObj.code;
65
+ if (code === "capability_not_granted") {
66
+ const data = isRecord(errObj.data) ? errObj.data : undefined;
67
+ const required = typeof data?.required_capability === "string" ? data.required_capability : "";
68
+ const msg = typeof errObj.message === "string" ? errObj.message : undefined;
69
+ throw new errors_js_1.CapabilityNotGrantedError(required, options?.requestCapability, msg);
70
+ }
71
+ if (code === "approval_required") {
72
+ const msg = typeof errObj.message === "string" ? errObj.message : "Capability execution requires approval";
73
+ throw new errors_js_1.ApprovalRequiredError(msg, errObj.data);
74
+ }
75
+ return new Response(text, { status: res.status, statusText: res.statusText, headers: res.headers });
76
+ };
77
+ }
78
+ function buildTools(client, fetchFn, describedByCapability, options) {
79
+ const tools = [];
80
+ const seenToolNames = new Map();
81
+ for (const capabilityId of client.capabilities) {
82
+ const id = (0, shared_1.capabilityToolKey)(capabilityId);
83
+ const existingCapabilityId = seenToolNames.get(id);
84
+ if (existingCapabilityId !== undefined && existingCapabilityId !== capabilityId) {
85
+ throw new Error(`OpenAI Agents tool name collision: "${id}" maps to both "${existingCapabilityId}" and "${capabilityId}". ` +
86
+ "Use distinct capability identifiers or provide inputSchemas to skip describe.");
87
+ }
88
+ seenToolNames.set(id, capabilityId);
89
+ const described = describedByCapability.get(capabilityId);
90
+ const inputJson = (0, shared_1.jsonSchemaForCapabilityInput)(options?.inputSchemas?.[capabilityId] ?? described?.input_schema);
91
+ const built = buildToolParameters(inputJson);
92
+ const exec = async (input) => {
93
+ const ctx = isRecord(input) ? input : {};
94
+ return (0, client_1.executeCapability)(client.provider, capabilityId, ctx, {
95
+ agentJwt: client.agentJwt,
96
+ fetch: fetchFn,
97
+ signal: options?.signal,
98
+ });
99
+ };
100
+ if (built.mode === "zod") {
101
+ tools.push((0, agents_1.tool)({
102
+ name: id,
103
+ description: described?.description ?? `ASAP capability: ${capabilityId}`,
104
+ parameters: built.schema,
105
+ strict: true,
106
+ errorFunction: null,
107
+ execute: exec,
108
+ }));
109
+ }
110
+ else {
111
+ tools.push((0, agents_1.tool)({
112
+ name: id,
113
+ description: described?.description ?? `ASAP capability: ${capabilityId}`,
114
+ parameters: built.schema,
115
+ strict: false,
116
+ errorFunction: null,
117
+ execute: exec,
118
+ }));
119
+ }
120
+ }
121
+ return tools;
122
+ }
123
+ /**
124
+ * Build OpenAI Agents SDK {@link tool} instances for each ASAP capability on the client.
125
+ *
126
+ * Uses top-level {@link executeCapability} from `@asap-protocol/client` on each execution path.
127
+ */
128
+ async function asapToolsForOpenAIAgents(client, options) {
129
+ const fetchFn = wrapFetchWithCapabilityErrors(client.fetch, options);
130
+ const describedByCapability = new Map();
131
+ const toDescribe = client.capabilities.filter((capabilityId) => options?.inputSchemas?.[capabilityId] === undefined);
132
+ for (const capabilityId of client.capabilities) {
133
+ if (options?.inputSchemas?.[capabilityId] !== undefined) {
134
+ describedByCapability.set(capabilityId, undefined);
135
+ }
136
+ }
137
+ await mapInBatches(toDescribe, DESCRIBE_CONCURRENCY, async (capabilityId) => {
138
+ try {
139
+ const described = await (0, client_1.describeCapability)(client.provider, capabilityId, {
140
+ fetch: fetchFn,
141
+ agentJwt: client.agentJwt,
142
+ signal: options?.signal,
143
+ });
144
+ describedByCapability.set(capabilityId, {
145
+ description: described.description,
146
+ input_schema: described.input_schema,
147
+ output_schema: described.output_schema,
148
+ });
149
+ }
150
+ catch (error) {
151
+ options?.onDescribeError?.(capabilityId, error);
152
+ if (options?.allowPermissiveDescribeFallback === true) {
153
+ describedByCapability.set(capabilityId, undefined);
154
+ return;
155
+ }
156
+ throw error;
157
+ }
158
+ });
159
+ return buildTools(client, fetchFn, describedByCapability, options);
160
+ }
161
+ /**
162
+ * Synchronous variant when {@link AsapToolsForOpenAIAgentsOptions.inputSchemas} / `outputSchemas`
163
+ * are already materialized (skips describe round-trips).
164
+ */
165
+ function asapToolsForOpenAIAgentsSync(client, options) {
166
+ const fetchFn = wrapFetchWithCapabilityErrors(client.fetch, options);
167
+ const describedByCapability = new Map();
168
+ for (const capabilityId of client.capabilities) {
169
+ describedByCapability.set(capabilityId, undefined);
170
+ }
171
+ return buildTools(client, fetchFn, describedByCapability, options);
172
+ }
@@ -0,0 +1,27 @@
1
+ export { FatalError, RecoverableError, RemoteFatalRPCError, RemoteRecoverableRPCError, } from "@asap-protocol/client";
2
+ /**
3
+ * Structured `approval_required` payload (`error.data`) from an ASAP provider JSON body.
4
+ */
5
+ export interface ApprovalRequiredDetail {
6
+ readonly reason?: string;
7
+ readonly approval_url?: string;
8
+ }
9
+ /**
10
+ * Raised when the provider indicates an approval step is required before the capability can run.
11
+ */
12
+ export declare class ApprovalRequiredError extends Error {
13
+ readonly name = "ApprovalRequiredError";
14
+ readonly detail?: ApprovalRequiredDetail;
15
+ constructor(message?: string, detail?: unknown);
16
+ }
17
+ /**
18
+ * Raised when the agent JWT is valid but the capability is not granted (HTTP 403 `capability_not_granted`).
19
+ */
20
+ export declare class CapabilityNotGrantedError extends Error {
21
+ readonly name = "CapabilityNotGrantedError";
22
+ readonly requiredCapability: string;
23
+ private readonly hook?;
24
+ constructor(requiredCapability: string, requestCapability?: (capability: string) => void | Promise<void>, message?: string);
25
+ requestCapability(): void | Promise<void>;
26
+ }
27
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,gBAAgB,EAChB,mBAAmB,EACnB,yBAAyB,GAC1B,MAAM,uBAAuB,CAAC;AAE/B;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC;AAmBD;;GAEG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,SAAkB,IAAI,2BAA2B;IAEjD,QAAQ,CAAC,MAAM,CAAC,EAAE,sBAAsB,CAAC;gBAE7B,OAAO,SAA2C,EAAE,MAAM,CAAC,EAAE,OAAO;CAIjF;AAED;;GAEG;AACH,qBAAa,yBAA0B,SAAQ,KAAK;IAClD,SAAkB,IAAI,+BAA+B;IAErD,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IAEpC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAA+C;gBAGnE,kBAAkB,EAAE,MAAM,EAC1B,iBAAiB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,EAChE,OAAO,CAAC,EAAE,MAAM;IAOlB,iBAAiB,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;CAG1C"}
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CapabilityNotGrantedError = exports.ApprovalRequiredError = exports.RemoteRecoverableRPCError = exports.RemoteFatalRPCError = exports.RecoverableError = exports.FatalError = void 0;
4
+ var client_1 = require("@asap-protocol/client");
5
+ Object.defineProperty(exports, "FatalError", { enumerable: true, get: function () { return client_1.FatalError; } });
6
+ Object.defineProperty(exports, "RecoverableError", { enumerable: true, get: function () { return client_1.RecoverableError; } });
7
+ Object.defineProperty(exports, "RemoteFatalRPCError", { enumerable: true, get: function () { return client_1.RemoteFatalRPCError; } });
8
+ Object.defineProperty(exports, "RemoteRecoverableRPCError", { enumerable: true, get: function () { return client_1.RemoteRecoverableRPCError; } });
9
+ function approvalDetailFromUnknown(data) {
10
+ if (!data || typeof data !== "object" || Array.isArray(data)) {
11
+ return undefined;
12
+ }
13
+ const rec = data;
14
+ const reason = rec.reason;
15
+ const approval_url = rec.approval_url;
16
+ const detail = {};
17
+ if (typeof reason === "string") {
18
+ detail.reason = reason;
19
+ }
20
+ if (typeof approval_url === "string") {
21
+ detail.approval_url = approval_url;
22
+ }
23
+ return Object.keys(detail).length > 0 ? detail : undefined;
24
+ }
25
+ /**
26
+ * Raised when the provider indicates an approval step is required before the capability can run.
27
+ */
28
+ class ApprovalRequiredError extends Error {
29
+ name = "ApprovalRequiredError";
30
+ detail;
31
+ constructor(message = "Capability execution requires approval", detail) {
32
+ super(message);
33
+ this.detail = approvalDetailFromUnknown(detail);
34
+ }
35
+ }
36
+ exports.ApprovalRequiredError = ApprovalRequiredError;
37
+ /**
38
+ * Raised when the agent JWT is valid but the capability is not granted (HTTP 403 `capability_not_granted`).
39
+ */
40
+ class CapabilityNotGrantedError extends Error {
41
+ name = "CapabilityNotGrantedError";
42
+ requiredCapability;
43
+ hook;
44
+ constructor(requiredCapability, requestCapability, message) {
45
+ super(message ?? `Capability not granted: ${requiredCapability}`);
46
+ this.requiredCapability = requiredCapability;
47
+ this.hook = requestCapability;
48
+ }
49
+ requestCapability() {
50
+ return this.hook?.(this.requiredCapability);
51
+ }
52
+ }
53
+ exports.CapabilityNotGrantedError = CapabilityNotGrantedError;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * OpenAI Agents SDK (`@openai/agents`) integration: ASAP capabilities as `tool()` and related helpers.
3
+ *
4
+ * For static `ChatCompletionTool[]` against the Chat Completions HTTP API, use `@asap-protocol/client/adapters/openai` instead.
5
+ */
6
+ export { asapToolsForOpenAIAgents, asapToolsForOpenAIAgentsSync, type AsapToolsForOpenAIAgentsOptions, } from "./asap-to-openai-tool.js";
7
+ export { asapAsRemoteAgent, draftTaskRequestEnvelopeForRemoteAgent, sameProviderOrigin, type AsapAsRemoteAgentOptions, type AsapRemoteAgentMode, type AsapRemoteRunContext, } from "./asap-as-remote-agent.js";
8
+ export { sendAsapEnvelope, type SendAsapEnvelopeOptions, type SendAsapFetch, } from "./send-asap-envelope.js";
9
+ export { zodFromJsonSchema } from "./schema-bridge.js";
10
+ export { asapStreamToOpenAIAgentsRunStreamChunks, asapStreamToOpenAIAgentsTextStream, type OpenAIAgentsStreamTextDelta, } from "./streaming.js";
11
+ export * from "./errors.js";
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,wBAAwB,EACxB,4BAA4B,EAC5B,KAAK,+BAA+B,GACrC,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,iBAAiB,EACjB,sCAAsC,EACtC,kBAAkB,EAClB,KAAK,wBAAwB,EAC7B,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,GAC1B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,gBAAgB,EAChB,KAAK,uBAAuB,EAC5B,KAAK,aAAa,GACnB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EACL,uCAAuC,EACvC,kCAAkC,EAClC,KAAK,2BAA2B,GACjC,MAAM,gBAAgB,CAAC;AACxB,cAAc,aAAa,CAAC"}
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ /**
3
+ * OpenAI Agents SDK (`@openai/agents`) integration: ASAP capabilities as `tool()` and related helpers.
4
+ *
5
+ * For static `ChatCompletionTool[]` against the Chat Completions HTTP API, use `@asap-protocol/client/adapters/openai` instead.
6
+ */
7
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ var desc = Object.getOwnPropertyDescriptor(m, k);
10
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
+ desc = { enumerable: true, get: function() { return m[k]; } };
12
+ }
13
+ Object.defineProperty(o, k2, desc);
14
+ }) : (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ o[k2] = m[k];
17
+ }));
18
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
19
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
20
+ };
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.asapStreamToOpenAIAgentsTextStream = exports.asapStreamToOpenAIAgentsRunStreamChunks = exports.zodFromJsonSchema = exports.sendAsapEnvelope = exports.sameProviderOrigin = exports.draftTaskRequestEnvelopeForRemoteAgent = exports.asapAsRemoteAgent = exports.asapToolsForOpenAIAgentsSync = exports.asapToolsForOpenAIAgents = void 0;
23
+ var asap_to_openai_tool_js_1 = require("./asap-to-openai-tool.js");
24
+ Object.defineProperty(exports, "asapToolsForOpenAIAgents", { enumerable: true, get: function () { return asap_to_openai_tool_js_1.asapToolsForOpenAIAgents; } });
25
+ Object.defineProperty(exports, "asapToolsForOpenAIAgentsSync", { enumerable: true, get: function () { return asap_to_openai_tool_js_1.asapToolsForOpenAIAgentsSync; } });
26
+ var asap_as_remote_agent_js_1 = require("./asap-as-remote-agent.js");
27
+ Object.defineProperty(exports, "asapAsRemoteAgent", { enumerable: true, get: function () { return asap_as_remote_agent_js_1.asapAsRemoteAgent; } });
28
+ Object.defineProperty(exports, "draftTaskRequestEnvelopeForRemoteAgent", { enumerable: true, get: function () { return asap_as_remote_agent_js_1.draftTaskRequestEnvelopeForRemoteAgent; } });
29
+ Object.defineProperty(exports, "sameProviderOrigin", { enumerable: true, get: function () { return asap_as_remote_agent_js_1.sameProviderOrigin; } });
30
+ var send_asap_envelope_js_1 = require("./send-asap-envelope.js");
31
+ Object.defineProperty(exports, "sendAsapEnvelope", { enumerable: true, get: function () { return send_asap_envelope_js_1.sendAsapEnvelope; } });
32
+ var schema_bridge_js_1 = require("./schema-bridge.js");
33
+ Object.defineProperty(exports, "zodFromJsonSchema", { enumerable: true, get: function () { return schema_bridge_js_1.zodFromJsonSchema; } });
34
+ var streaming_js_1 = require("./streaming.js");
35
+ Object.defineProperty(exports, "asapStreamToOpenAIAgentsRunStreamChunks", { enumerable: true, get: function () { return streaming_js_1.asapStreamToOpenAIAgentsRunStreamChunks; } });
36
+ Object.defineProperty(exports, "asapStreamToOpenAIAgentsTextStream", { enumerable: true, get: function () { return streaming_js_1.asapStreamToOpenAIAgentsTextStream; } });
37
+ __exportStar(require("./errors.js"), exports);
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "commonjs"
3
+ }
@@ -0,0 +1,8 @@
1
+ import { type ZodType } from "zod";
2
+ /**
3
+ * Minimal JSON Schema → Zod bridge for adapter tool schemas (subset only).
4
+ *
5
+ * Lossy for `$ref` / complex `oneOf`; mirrors `@asap-protocol/mastra` / legacy Chat Completions adapter patterns.
6
+ */
7
+ export declare function zodFromJsonSchema(schema: Record<string, unknown>): ZodType<unknown>;
8
+ //# sourceMappingURL=schema-bridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-bridge.d.ts","sourceRoot":"","sources":["../../src/schema-bridge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAK,KAAK,OAAO,EAAE,MAAM,KAAK,CAAC;AAqDtC;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CA4DnF"}