@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.
- package/README.md +53 -0
- package/dist/commonjs/asap-as-remote-agent.d.ts +44 -0
- package/dist/commonjs/asap-as-remote-agent.d.ts.map +1 -0
- package/dist/commonjs/asap-as-remote-agent.js +119 -0
- package/dist/commonjs/asap-to-openai-tool.d.ts +34 -0
- package/dist/commonjs/asap-to-openai-tool.d.ts.map +1 -0
- package/dist/commonjs/asap-to-openai-tool.js +172 -0
- package/dist/commonjs/errors.d.ts +27 -0
- package/dist/commonjs/errors.d.ts.map +1 -0
- package/dist/commonjs/errors.js +53 -0
- package/dist/commonjs/index.d.ts +12 -0
- package/dist/commonjs/index.d.ts.map +1 -0
- package/dist/commonjs/index.js +37 -0
- package/dist/commonjs/package.json +3 -0
- package/dist/commonjs/schema-bridge.d.ts +8 -0
- package/dist/commonjs/schema-bridge.d.ts.map +1 -0
- package/dist/commonjs/schema-bridge.js +106 -0
- package/dist/commonjs/send-asap-envelope.d.ts +16 -0
- package/dist/commonjs/send-asap-envelope.d.ts.map +1 -0
- package/dist/commonjs/send-asap-envelope.js +100 -0
- package/dist/commonjs/streaming.d.ts +16 -0
- package/dist/commonjs/streaming.d.ts.map +1 -0
- package/dist/commonjs/streaming.js +45 -0
- package/dist/esm/asap-as-remote-agent.d.ts +44 -0
- package/dist/esm/asap-as-remote-agent.d.ts.map +1 -0
- package/dist/esm/asap-as-remote-agent.js +114 -0
- package/dist/esm/asap-to-openai-tool.d.ts +34 -0
- package/dist/esm/asap-to-openai-tool.d.ts.map +1 -0
- package/dist/esm/asap-to-openai-tool.js +168 -0
- package/dist/esm/errors.d.ts +27 -0
- package/dist/esm/errors.d.ts.map +1 -0
- package/dist/esm/errors.js +44 -0
- package/dist/esm/index.d.ts +12 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +11 -0
- package/dist/esm/package.json +3 -0
- package/dist/esm/schema-bridge.d.ts +8 -0
- package/dist/esm/schema-bridge.d.ts.map +1 -0
- package/dist/esm/schema-bridge.js +103 -0
- package/dist/esm/send-asap-envelope.d.ts +16 -0
- package/dist/esm/send-asap-envelope.d.ts.map +1 -0
- package/dist/esm/send-asap-envelope.js +97 -0
- package/dist/esm/streaming.d.ts +16 -0
- package/dist/esm/streaming.d.ts.map +1 -0
- package/dist/esm/streaming.js +41 -0
- package/package.json +69 -0
|
@@ -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,44 @@
|
|
|
1
|
+
export { FatalError, RecoverableError, RemoteFatalRPCError, RemoteRecoverableRPCError, } from "@asap-protocol/client";
|
|
2
|
+
function approvalDetailFromUnknown(data) {
|
|
3
|
+
if (!data || typeof data !== "object" || Array.isArray(data)) {
|
|
4
|
+
return undefined;
|
|
5
|
+
}
|
|
6
|
+
const rec = data;
|
|
7
|
+
const reason = rec.reason;
|
|
8
|
+
const approval_url = rec.approval_url;
|
|
9
|
+
const detail = {};
|
|
10
|
+
if (typeof reason === "string") {
|
|
11
|
+
detail.reason = reason;
|
|
12
|
+
}
|
|
13
|
+
if (typeof approval_url === "string") {
|
|
14
|
+
detail.approval_url = approval_url;
|
|
15
|
+
}
|
|
16
|
+
return Object.keys(detail).length > 0 ? detail : undefined;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Raised when the provider indicates an approval step is required before the capability can run.
|
|
20
|
+
*/
|
|
21
|
+
export class ApprovalRequiredError extends Error {
|
|
22
|
+
name = "ApprovalRequiredError";
|
|
23
|
+
detail;
|
|
24
|
+
constructor(message = "Capability execution requires approval", detail) {
|
|
25
|
+
super(message);
|
|
26
|
+
this.detail = approvalDetailFromUnknown(detail);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Raised when the agent JWT is valid but the capability is not granted (HTTP 403 `capability_not_granted`).
|
|
31
|
+
*/
|
|
32
|
+
export class CapabilityNotGrantedError extends Error {
|
|
33
|
+
name = "CapabilityNotGrantedError";
|
|
34
|
+
requiredCapability;
|
|
35
|
+
hook;
|
|
36
|
+
constructor(requiredCapability, requestCapability, message) {
|
|
37
|
+
super(message ?? `Capability not granted: ${requiredCapability}`);
|
|
38
|
+
this.requiredCapability = requiredCapability;
|
|
39
|
+
this.hook = requestCapability;
|
|
40
|
+
}
|
|
41
|
+
requestCapability() {
|
|
42
|
+
return this.hook?.(this.requiredCapability);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -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,11 @@
|
|
|
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, } from "./asap-to-openai-tool.js";
|
|
7
|
+
export { asapAsRemoteAgent, draftTaskRequestEnvelopeForRemoteAgent, sameProviderOrigin, } from "./asap-as-remote-agent.js";
|
|
8
|
+
export { sendAsapEnvelope, } from "./send-asap-envelope.js";
|
|
9
|
+
export { zodFromJsonSchema } from "./schema-bridge.js";
|
|
10
|
+
export { asapStreamToOpenAIAgentsRunStreamChunks, asapStreamToOpenAIAgentsTextStream, } from "./streaming.js";
|
|
11
|
+
export * from "./errors.js";
|
|
@@ -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"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
function enumLiteralKind(value) {
|
|
3
|
+
if (value === null) {
|
|
4
|
+
return "null";
|
|
5
|
+
}
|
|
6
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
7
|
+
return typeof value;
|
|
8
|
+
}
|
|
9
|
+
return "unsupported";
|
|
10
|
+
}
|
|
11
|
+
function zodFromJsonSchemaEnum(enumValues) {
|
|
12
|
+
if (enumValues.length === 0) {
|
|
13
|
+
throw new Error("JSON Schema enum must contain at least one value");
|
|
14
|
+
}
|
|
15
|
+
const kinds = new Set();
|
|
16
|
+
for (const value of enumValues) {
|
|
17
|
+
kinds.add(enumLiteralKind(value));
|
|
18
|
+
}
|
|
19
|
+
if (kinds.has("unsupported")) {
|
|
20
|
+
throw new Error("JSON Schema enum supports only string, number, boolean, and null literals");
|
|
21
|
+
}
|
|
22
|
+
const nonNullKinds = [...kinds].filter((kind) => kind !== "null");
|
|
23
|
+
if (nonNullKinds.length > 1) {
|
|
24
|
+
throw new Error(`JSON Schema enum with mixed primitive types is unsupported (found: ${[...kinds].join(", ")})`);
|
|
25
|
+
}
|
|
26
|
+
const literals = enumValues.map((value) => {
|
|
27
|
+
if (value === null) {
|
|
28
|
+
return z.null();
|
|
29
|
+
}
|
|
30
|
+
if (typeof value === "string") {
|
|
31
|
+
return z.literal(value);
|
|
32
|
+
}
|
|
33
|
+
if (typeof value === "number") {
|
|
34
|
+
return z.literal(value);
|
|
35
|
+
}
|
|
36
|
+
return z.literal(value);
|
|
37
|
+
});
|
|
38
|
+
return literals.length === 1
|
|
39
|
+
? literals[0]
|
|
40
|
+
: z.union(literals);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Minimal JSON Schema → Zod bridge for adapter tool schemas (subset only).
|
|
44
|
+
*
|
|
45
|
+
* Lossy for `$ref` / complex `oneOf`; mirrors `@asap-protocol/mastra` / legacy Chat Completions adapter patterns.
|
|
46
|
+
*/
|
|
47
|
+
export function zodFromJsonSchema(schema) {
|
|
48
|
+
if ("$ref" in schema) {
|
|
49
|
+
return z.record(z.string(), z.unknown());
|
|
50
|
+
}
|
|
51
|
+
if ("oneOf" in schema && Array.isArray(schema.oneOf)) {
|
|
52
|
+
const branches = schema.oneOf
|
|
53
|
+
.filter((s) => typeof s === "object" && s !== null && !Array.isArray(s))
|
|
54
|
+
.map((s) => zodFromJsonSchema(s));
|
|
55
|
+
return branches.length === 0
|
|
56
|
+
? z.unknown()
|
|
57
|
+
: branches.length === 1
|
|
58
|
+
? branches[0]
|
|
59
|
+
: z.union(branches);
|
|
60
|
+
}
|
|
61
|
+
if ("enum" in schema && Array.isArray(schema.enum) && schema.enum.length > 0) {
|
|
62
|
+
return zodFromJsonSchemaEnum(schema.enum);
|
|
63
|
+
}
|
|
64
|
+
switch (schema.type) {
|
|
65
|
+
case "object": {
|
|
66
|
+
const maybeProps = schema.properties;
|
|
67
|
+
if (maybeProps !== undefined &&
|
|
68
|
+
typeof maybeProps === "object" &&
|
|
69
|
+
maybeProps !== null &&
|
|
70
|
+
!Array.isArray(maybeProps)) {
|
|
71
|
+
const propsRecord = maybeProps;
|
|
72
|
+
const required = new Set(Array.isArray(schema.required) ? schema.required.filter((k) => typeof k === "string") : []);
|
|
73
|
+
const shape = {};
|
|
74
|
+
for (const [key, val] of Object.entries(propsRecord)) {
|
|
75
|
+
if (typeof val === "object" && val !== null && !Array.isArray(val)) {
|
|
76
|
+
const child = zodFromJsonSchema(val);
|
|
77
|
+
shape[key] = required.has(key) ? child : child.optional();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (Object.keys(shape).length > 0) {
|
|
81
|
+
return z.object(shape);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return z.record(z.string(), z.unknown());
|
|
85
|
+
}
|
|
86
|
+
case "string":
|
|
87
|
+
return z.string();
|
|
88
|
+
case "number":
|
|
89
|
+
case "integer":
|
|
90
|
+
return z.number();
|
|
91
|
+
case "boolean":
|
|
92
|
+
return z.boolean();
|
|
93
|
+
case "array": {
|
|
94
|
+
const items = schema.items;
|
|
95
|
+
if (typeof items === "object" && items !== null && !Array.isArray(items)) {
|
|
96
|
+
return z.array(zodFromJsonSchema(items));
|
|
97
|
+
}
|
|
98
|
+
return z.array(z.unknown());
|
|
99
|
+
}
|
|
100
|
+
default:
|
|
101
|
+
return z.record(z.string(), z.unknown());
|
|
102
|
+
}
|
|
103
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type SendAsapFetch = typeof fetch;
|
|
2
|
+
export interface SendAsapEnvelopeOptions {
|
|
3
|
+
readonly fetch?: SendAsapFetch;
|
|
4
|
+
readonly signal?: AbortSignal;
|
|
5
|
+
/** When set, sends `Authorization: Bearer <token>`. */
|
|
6
|
+
readonly agentJwt?: string;
|
|
7
|
+
/** Sent as `ASAP-Version` (default `2.2`). */
|
|
8
|
+
readonly asapVersion?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* POST a JSON-RPC `asap.send` request to the provider's `/asap` endpoint.
|
|
12
|
+
*
|
|
13
|
+
* @throws When HTTP status is not ok or the JSON-RPC response contains an error.
|
|
14
|
+
*/
|
|
15
|
+
export declare function sendAsapEnvelope(provider: URL, envelope: Record<string, unknown>, options?: SendAsapEnvelopeOptions): Promise<unknown>;
|
|
16
|
+
//# sourceMappingURL=send-asap-envelope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"send-asap-envelope.d.ts","sourceRoot":"","sources":["../../src/send-asap-envelope.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,aAAa,GAAG,OAAO,KAAK,CAAC;AAEzC,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,KAAK,CAAC,EAAE,aAAa,CAAC;IAC/B,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;IAC9B,uDAAuD;IACvD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,8CAA8C;IAC9C,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAiED;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,GAAG,EACb,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,OAAO,CAAC,EAAE,uBAAuB,GAChC,OAAO,CAAC,OAAO,CAAC,CAqClB"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { ASAP_SEND_METHOD, ASAP_VERSION_HEADER } from "@asap-protocol/client";
|
|
2
|
+
const DEFAULT_ASAP_VERSION = "2.2";
|
|
3
|
+
/** Base URL with trailing slash for safe relative resolution of `asap/...` paths. */
|
|
4
|
+
function providerBaseHref(provider) {
|
|
5
|
+
const href = provider.href;
|
|
6
|
+
return provider.pathname.endsWith("/") ? href : `${href}/`;
|
|
7
|
+
}
|
|
8
|
+
function asapSendHref(provider) {
|
|
9
|
+
return new URL("asap", providerBaseHref(provider)).href;
|
|
10
|
+
}
|
|
11
|
+
function isRecord(value) {
|
|
12
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
13
|
+
}
|
|
14
|
+
function jsonRpcErrorToError(error) {
|
|
15
|
+
if (!isRecord(error)) {
|
|
16
|
+
return new Error(String(error));
|
|
17
|
+
}
|
|
18
|
+
const message = typeof error.message === "string" ? error.message : JSON.stringify(error);
|
|
19
|
+
const err = new Error(message);
|
|
20
|
+
err.name = "JsonRpcError";
|
|
21
|
+
if (typeof error.code === "number") {
|
|
22
|
+
err.code = error.code;
|
|
23
|
+
}
|
|
24
|
+
return err;
|
|
25
|
+
}
|
|
26
|
+
function parseJsonRpcResult(payload) {
|
|
27
|
+
if (!isRecord(payload)) {
|
|
28
|
+
return payload;
|
|
29
|
+
}
|
|
30
|
+
if (payload.jsonrpc !== "2.0") {
|
|
31
|
+
return payload;
|
|
32
|
+
}
|
|
33
|
+
if (payload.error !== undefined && payload.error !== null) {
|
|
34
|
+
throw jsonRpcErrorToError(payload.error);
|
|
35
|
+
}
|
|
36
|
+
return payload.result;
|
|
37
|
+
}
|
|
38
|
+
function normalizeEnvelopeForSend(envelope) {
|
|
39
|
+
return {
|
|
40
|
+
...envelope,
|
|
41
|
+
id: typeof envelope.id === "string" ? envelope.id : crypto.randomUUID(),
|
|
42
|
+
timestamp: typeof envelope.timestamp === "string" ? envelope.timestamp : new Date().toISOString(),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function buildJsonRpcSendBody(envelope) {
|
|
46
|
+
const requestId = crypto.randomUUID();
|
|
47
|
+
const idempotencyKey = crypto.randomUUID();
|
|
48
|
+
const jsonRpcRequest = {
|
|
49
|
+
jsonrpc: "2.0",
|
|
50
|
+
method: ASAP_SEND_METHOD,
|
|
51
|
+
params: {
|
|
52
|
+
envelope,
|
|
53
|
+
idempotency_key: idempotencyKey,
|
|
54
|
+
},
|
|
55
|
+
id: requestId,
|
|
56
|
+
};
|
|
57
|
+
return { body: JSON.stringify(jsonRpcRequest), idempotencyKey };
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* POST a JSON-RPC `asap.send` request to the provider's `/asap` endpoint.
|
|
61
|
+
*
|
|
62
|
+
* @throws When HTTP status is not ok or the JSON-RPC response contains an error.
|
|
63
|
+
*/
|
|
64
|
+
export async function sendAsapEnvelope(provider, envelope, options) {
|
|
65
|
+
const fetchFn = options?.fetch ?? globalThis.fetch.bind(globalThis);
|
|
66
|
+
const asapVersion = options?.asapVersion ?? DEFAULT_ASAP_VERSION;
|
|
67
|
+
const wireEnvelope = normalizeEnvelopeForSend(envelope);
|
|
68
|
+
const { body, idempotencyKey } = buildJsonRpcSendBody(wireEnvelope);
|
|
69
|
+
const headers = {
|
|
70
|
+
"Content-Type": "application/json",
|
|
71
|
+
Accept: "application/json",
|
|
72
|
+
"X-Idempotency-Key": idempotencyKey,
|
|
73
|
+
[ASAP_VERSION_HEADER]: asapVersion,
|
|
74
|
+
};
|
|
75
|
+
if (options?.agentJwt !== undefined && options.agentJwt.length > 0) {
|
|
76
|
+
headers.Authorization = `Bearer ${options.agentJwt}`;
|
|
77
|
+
}
|
|
78
|
+
const response = await fetchFn(asapSendHref(provider), {
|
|
79
|
+
method: "POST",
|
|
80
|
+
headers,
|
|
81
|
+
body,
|
|
82
|
+
signal: options?.signal,
|
|
83
|
+
});
|
|
84
|
+
const text = await response.text();
|
|
85
|
+
let parsed;
|
|
86
|
+
try {
|
|
87
|
+
parsed = text.length === 0 ? {} : JSON.parse(text);
|
|
88
|
+
}
|
|
89
|
+
catch (e) {
|
|
90
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
91
|
+
throw new Error(`asap.send: invalid JSON (${msg})`);
|
|
92
|
+
}
|
|
93
|
+
if (!response.ok) {
|
|
94
|
+
throw new Error(`asap.send failed: HTTP ${String(response.status)} ${text.slice(0, 200)}`);
|
|
95
|
+
}
|
|
96
|
+
return parseJsonRpcResult(parsed);
|
|
97
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bridge ASAP TaskStream-style payloads into UTF-8 text chunks suitable for OpenAI Agents streaming UX.
|
|
3
|
+
*
|
|
4
|
+
* Pair with `@asap-protocol/client` streaming helpers (`createAsapStreamClient`, `streamTaskStreamEnvelopes`).
|
|
5
|
+
*/
|
|
6
|
+
/** Streaming text delta aligned with incremental assistant output (surface-only shape). */
|
|
7
|
+
export interface OpenAIAgentsStreamTextDelta {
|
|
8
|
+
readonly type: "text_delta";
|
|
9
|
+
readonly text: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function asapStreamToOpenAIAgentsTextStream(source: AsyncIterable<unknown>): AsyncIterable<string>;
|
|
12
|
+
/**
|
|
13
|
+
* Same mapping as {@link asapStreamToOpenAIAgentsTextStream}, wrapped as `{ type: "text_delta" }` chunks.
|
|
14
|
+
*/
|
|
15
|
+
export declare function asapStreamToOpenAIAgentsRunStreamChunks(source: AsyncIterable<unknown>): AsyncIterable<OpenAIAgentsStreamTextDelta>;
|
|
16
|
+
//# sourceMappingURL=streaming.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"streaming.d.ts","sourceRoot":"","sources":["../../src/streaming.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,2FAA2F;AAC3F,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,wBAAuB,kCAAkC,CAAC,MAAM,EAAE,aAAa,CAAC,OAAO,CAAC,GAAG,aAAa,CAAC,MAAM,CAAC,CAuB/G;AAED;;GAEG;AACH,wBAAuB,uCAAuC,CAC5D,MAAM,EAAE,aAAa,CAAC,OAAO,CAAC,GAC7B,aAAa,CAAC,2BAA2B,CAAC,CAI5C"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bridge ASAP TaskStream-style payloads into UTF-8 text chunks suitable for OpenAI Agents streaming UX.
|
|
3
|
+
*
|
|
4
|
+
* Pair with `@asap-protocol/client` streaming helpers (`createAsapStreamClient`, `streamTaskStreamEnvelopes`).
|
|
5
|
+
*/
|
|
6
|
+
function isRecord(x) {
|
|
7
|
+
return typeof x === "object" && x !== null && !Array.isArray(x);
|
|
8
|
+
}
|
|
9
|
+
export async function* asapStreamToOpenAIAgentsTextStream(source) {
|
|
10
|
+
const it = source[Symbol.asyncIterator]();
|
|
11
|
+
try {
|
|
12
|
+
while (true) {
|
|
13
|
+
const { value: event, done } = await it.next();
|
|
14
|
+
if (done) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
if (!isRecord(event) || event.type !== "task_stream") {
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
const payload = event.payload;
|
|
21
|
+
if (!isRecord(payload)) {
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
const chunk = payload.chunk;
|
|
25
|
+
if (typeof chunk === "string") {
|
|
26
|
+
yield chunk;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
finally {
|
|
31
|
+
await it.return?.();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Same mapping as {@link asapStreamToOpenAIAgentsTextStream}, wrapped as `{ type: "text_delta" }` chunks.
|
|
36
|
+
*/
|
|
37
|
+
export async function* asapStreamToOpenAIAgentsRunStreamChunks(source) {
|
|
38
|
+
for await (const text of asapStreamToOpenAIAgentsTextStream(source)) {
|
|
39
|
+
yield { type: "text_delta", text };
|
|
40
|
+
}
|
|
41
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@asap-protocol/openai-agents",
|
|
3
|
+
"version": "2.3.1",
|
|
4
|
+
"description": "ASAP Protocol capabilities as OpenAI Agents SDK tools (@openai/agents)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"publishConfig": {
|
|
8
|
+
"access": "public"
|
|
9
|
+
},
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://github.com/adriannoes/asap-protocol"
|
|
13
|
+
},
|
|
14
|
+
"engines": {
|
|
15
|
+
"node": ">=18"
|
|
16
|
+
},
|
|
17
|
+
"peerDependencies": {
|
|
18
|
+
"@asap-protocol/client": "^2.3.0",
|
|
19
|
+
"@openai/agents": "^0.11.0",
|
|
20
|
+
"zod": "^4.1.8"
|
|
21
|
+
},
|
|
22
|
+
"dependencies": {},
|
|
23
|
+
"files": [
|
|
24
|
+
"dist"
|
|
25
|
+
],
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "tshy",
|
|
28
|
+
"test": "vitest run --coverage",
|
|
29
|
+
"test:no-coverage": "vitest run",
|
|
30
|
+
"lint": "eslint .",
|
|
31
|
+
"check:treeshake": "pnpm run build && agadoo ./dist/esm/index.js",
|
|
32
|
+
"typecheck": "tsc --noEmit -p tsconfig.json"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@asap-protocol/client": "workspace:*",
|
|
36
|
+
"@eslint/js": "9.18.0",
|
|
37
|
+
"@openai/agents": "^0.11.4",
|
|
38
|
+
"@types/node": "^20.19.0",
|
|
39
|
+
"@vitest/coverage-v8": "4.1.5",
|
|
40
|
+
"agadoo": "3.0.0",
|
|
41
|
+
"eslint": "9.18.0",
|
|
42
|
+
"tshy": "^3.3.2",
|
|
43
|
+
"typescript": "^5.8.3",
|
|
44
|
+
"typescript-eslint": "8.59.1",
|
|
45
|
+
"vitest": "^4.1.1",
|
|
46
|
+
"zod": "^4.4.2"
|
|
47
|
+
},
|
|
48
|
+
"tshy": {
|
|
49
|
+
"project": "./tsconfig.build.json",
|
|
50
|
+
"exports": {
|
|
51
|
+
".": "./src/index.ts"
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"exports": {
|
|
55
|
+
".": {
|
|
56
|
+
"import": {
|
|
57
|
+
"types": "./dist/esm/index.d.ts",
|
|
58
|
+
"default": "./dist/esm/index.js"
|
|
59
|
+
},
|
|
60
|
+
"require": {
|
|
61
|
+
"types": "./dist/commonjs/index.d.ts",
|
|
62
|
+
"default": "./dist/commonjs/index.js"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"main": "./dist/commonjs/index.js",
|
|
67
|
+
"types": "./dist/commonjs/index.d.ts",
|
|
68
|
+
"module": "./dist/esm/index.js"
|
|
69
|
+
}
|