@agent-api/sdk 1.0.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.
Files changed (48) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/LICENSE +21 -0
  3. package/README.md +115 -0
  4. package/dist/client.d.ts +25 -0
  5. package/dist/client.js +52 -0
  6. package/dist/errors.d.ts +61 -0
  7. package/dist/errors.js +130 -0
  8. package/dist/index.d.ts +7 -0
  9. package/dist/index.js +5 -0
  10. package/dist/internal/env.d.ts +1 -0
  11. package/dist/internal/env.js +4 -0
  12. package/dist/internal/http.d.ts +18 -0
  13. package/dist/internal/http.js +93 -0
  14. package/dist/internal/output-text.d.ts +2 -0
  15. package/dist/internal/output-text.js +12 -0
  16. package/dist/internal/query.d.ts +1 -0
  17. package/dist/internal/query.js +10 -0
  18. package/dist/local-functions.d.ts +9 -0
  19. package/dist/local-functions.js +32 -0
  20. package/dist/pagination.d.ts +21 -0
  21. package/dist/pagination.js +38 -0
  22. package/dist/resources/models.d.ts +8 -0
  23. package/dist/resources/models.js +9 -0
  24. package/dist/resources/presets.d.ts +8 -0
  25. package/dist/resources/presets.js +9 -0
  26. package/dist/resources/responses.d.ts +19 -0
  27. package/dist/resources/responses.js +49 -0
  28. package/dist/resources/tools.d.ts +8 -0
  29. package/dist/resources/tools.js +9 -0
  30. package/dist/streaming.d.ts +1 -0
  31. package/dist/streaming.js +39 -0
  32. package/dist/types/catalog.d.ts +40 -0
  33. package/dist/types/catalog.js +1 -0
  34. package/dist/types/common.d.ts +52 -0
  35. package/dist/types/common.js +1 -0
  36. package/dist/types/index.d.ts +6 -0
  37. package/dist/types/index.js +6 -0
  38. package/dist/types/input.d.ts +52 -0
  39. package/dist/types/input.js +1 -0
  40. package/dist/types/responses.d.ts +151 -0
  41. package/dist/types/responses.js +1 -0
  42. package/dist/types/streaming.d.ts +41 -0
  43. package/dist/types/streaming.js +1 -0
  44. package/dist/types/tools.d.ts +44 -0
  45. package/dist/types/tools.js +1 -0
  46. package/dist/version.d.ts +2 -0
  47. package/dist/version.js +2 -0
  48. package/package.json +56 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,13 @@
1
+ # Changelog — @agent-api/sdk
2
+
3
+ ## 1.0.0
4
+
5
+ ### Added
6
+
7
+ - Modular package layout with retries, typed errors, pagination, and streaming.
8
+ - CI via `.github/workflows/sdk.yml` and npm publish via `sdk-javascript-release.yml`.
9
+ - Route coverage check via `scripts/check-routes.mjs`.
10
+
11
+ ### Notes
12
+
13
+ - Independent from the Python `cloudsway-agent` package; version and release tags are separate.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 AgentsWay
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,115 @@
1
+ # JavaScript SDK
2
+
3
+ Production JavaScript/TypeScript SDK for the Managed Agent API.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @agent-api/sdk
9
+ ```
10
+
11
+ For local development from this repository:
12
+
13
+ ```bash
14
+ cd sdk/javascript
15
+ npm install
16
+ npm run build
17
+ ```
18
+
19
+ ## Quick start
20
+
21
+ ```javascript
22
+ import { AgentAPI } from "@agent-api/sdk";
23
+
24
+ const client = new AgentAPI({
25
+ apiKey: process.env.AGENT_API_KEY,
26
+ baseURL: "https://api.agentsway.dev",
27
+ });
28
+
29
+ const response = await client.responses.create({
30
+ preset: "pro-search",
31
+ input: "What changed in AI this week?",
32
+ });
33
+ console.log(response.output_text);
34
+ ```
35
+
36
+ Environment variables `AGENT_API_KEY` and `AGENT_API_BASE_URL` are used by default.
37
+ The default base URL is `https://api.agentsway.dev` when neither option nor env is set.
38
+
39
+ ## Package layout
40
+
41
+ ```
42
+ src/
43
+ client.ts # AgentAPI entrypoint
44
+ errors.ts # Typed error hierarchy + retry helpers
45
+ pagination.ts # Cursor pagination utilities
46
+ streaming.ts # SSE parser
47
+ resources/ # responses, models, presets, tools
48
+ types/ # Request/response TypeScript types
49
+ internal/http.ts # Retries, timeouts, User-Agent
50
+ ```
51
+
52
+ ## Resources
53
+
54
+ | Resource | Methods |
55
+ |----------|---------|
56
+ | `client.responses` / `client.agent` | `create`, `list`, `listPage`, `listIterator`, `retrieve`, `cancel`, `listChildren`, `listEvents` |
57
+ | `client.models` | `list` |
58
+ | `client.presets` | `list` |
59
+ | `client.tools` | `list` |
60
+
61
+ ## Production features
62
+
63
+ - **Retries:** automatic exponential backoff for network failures, 429, and 5xx (default 2 retries).
64
+ - **Timeouts:** 10 minute default for requests; 1 hour for streaming agent runs (configurable via `timeout` / `streamTimeout`).
65
+ - **Typed errors:** `AuthenticationError`, `RateLimitError`, `NotFoundError`, `BadRequestError`, etc.
66
+ - **Pagination:** `listPage` returns a cursor page; `listIterator` auto-fetches all pages.
67
+
68
+ ```typescript
69
+ for await (const item of client.responses.listIterator({ limit: 20 })) {
70
+ console.log(item.id, item.status);
71
+ }
72
+ ```
73
+
74
+ ## Streaming
75
+
76
+ ```typescript
77
+ const stream = await client.responses.create({
78
+ preset: "fast-search",
79
+ input: "Summarize today's AI news.",
80
+ stream: true,
81
+ });
82
+
83
+ for await (const event of stream) {
84
+ if (event.type === "response.output_text.delta") {
85
+ process.stdout.write(event.delta ?? "");
86
+ }
87
+ }
88
+ ```
89
+
90
+ ## Client options
91
+
92
+ ```typescript
93
+ const client = new AgentAPI({
94
+ apiKey: "sk-...",
95
+ baseURL: "https://api.agentsway.dev",
96
+ timeout: 600_000,
97
+ streamTimeout: 3_600_000,
98
+ maxRetries: 2,
99
+ defaultHeaders: { "X-Custom": "value" },
100
+ });
101
+ ```
102
+
103
+ ## Tests
104
+
105
+ ```bash
106
+ npm run check:routes # optional route manifest check
107
+ npm test
108
+ AGENT_API_INTEGRATION=1 AGENT_API_KEY=sk-... AGENT_API_BASE_URL=https://api.agentsway.dev npm run test:integration
109
+ ```
110
+
111
+ ## Scope
112
+
113
+ The SDK covers the public agent/Responses API and discovery endpoints. Console
114
+ auth, workspace administration, and internal audit records are intentionally
115
+ out of scope.
@@ -0,0 +1,25 @@
1
+ import { ModelsResource } from "./resources/models.js";
2
+ import { PresetsResource } from "./resources/presets.js";
3
+ import { ResponsesResource } from "./resources/responses.js";
4
+ import { ToolsResource } from "./resources/tools.js";
5
+ import type { ClientOptions } from "./types/common.js";
6
+ import { VERSION } from "./version.js";
7
+ export declare const DEFAULT_TIMEOUT_MS = 600000;
8
+ export declare const DEFAULT_STREAM_TIMEOUT_MS = 3600000;
9
+ export declare const DEFAULT_MAX_RETRIES = 2;
10
+ export declare class AgentAPI {
11
+ readonly apiKey?: string;
12
+ readonly baseURL: string;
13
+ readonly timeout: number;
14
+ readonly streamTimeout: number;
15
+ readonly maxRetries: number;
16
+ readonly defaultHeaders: Record<string, string>;
17
+ readonly responses: ResponsesResource;
18
+ readonly agent: ResponsesResource;
19
+ readonly models: ModelsResource;
20
+ readonly presets: PresetsResource;
21
+ readonly tools: ToolsResource;
22
+ private readonly http;
23
+ constructor(options?: ClientOptions);
24
+ }
25
+ export { VERSION };
package/dist/client.js ADDED
@@ -0,0 +1,52 @@
1
+ import { APIConnectionError } from "./errors.js";
2
+ import { readEnv } from "./internal/env.js";
3
+ import { HTTPClient } from "./internal/http.js";
4
+ import { ModelsResource } from "./resources/models.js";
5
+ import { PresetsResource } from "./resources/presets.js";
6
+ import { ResponsesResource } from "./resources/responses.js";
7
+ import { ToolsResource } from "./resources/tools.js";
8
+ import { VERSION } from "./version.js";
9
+ export const DEFAULT_TIMEOUT_MS = 600_000;
10
+ export const DEFAULT_STREAM_TIMEOUT_MS = 3_600_000;
11
+ export const DEFAULT_MAX_RETRIES = 2;
12
+ export class AgentAPI {
13
+ apiKey;
14
+ baseURL;
15
+ timeout;
16
+ streamTimeout;
17
+ maxRetries;
18
+ defaultHeaders;
19
+ responses;
20
+ agent;
21
+ models;
22
+ presets;
23
+ tools;
24
+ http;
25
+ constructor(options = {}) {
26
+ this.apiKey = options.apiKey ?? readEnv("AGENT_API_KEY");
27
+ this.baseURL = (options.baseURL ?? readEnv("AGENT_API_BASE_URL") ?? "https://api.agentsway.dev").replace(/\/+$/, "");
28
+ this.timeout = options.timeout ?? DEFAULT_TIMEOUT_MS;
29
+ this.streamTimeout = options.streamTimeout ?? DEFAULT_STREAM_TIMEOUT_MS;
30
+ this.maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;
31
+ this.defaultHeaders = options.defaultHeaders ?? {};
32
+ const fetchImpl = options.fetch ?? globalThis.fetch;
33
+ if (!fetchImpl) {
34
+ throw new APIConnectionError("No fetch implementation is available");
35
+ }
36
+ this.http = new HTTPClient({
37
+ baseURL: this.baseURL,
38
+ apiKey: this.apiKey,
39
+ timeout: this.timeout,
40
+ streamTimeout: this.streamTimeout,
41
+ maxRetries: this.maxRetries,
42
+ defaultHeaders: this.defaultHeaders,
43
+ fetchImpl,
44
+ });
45
+ this.responses = new ResponsesResource(this.http, "/v1/responses");
46
+ this.agent = new ResponsesResource(this.http, "/v1/agent");
47
+ this.models = new ModelsResource(this.http);
48
+ this.presets = new PresetsResource(this.http);
49
+ this.tools = new ToolsResource(this.http);
50
+ }
51
+ }
52
+ export { VERSION };
@@ -0,0 +1,61 @@
1
+ export interface APIErrorBody {
2
+ error?: {
3
+ message?: string;
4
+ code?: string;
5
+ type?: string;
6
+ };
7
+ }
8
+ export declare class APIError extends Error {
9
+ readonly status?: number;
10
+ readonly headers?: Headers;
11
+ readonly body?: unknown;
12
+ readonly code?: string;
13
+ readonly errorType?: string;
14
+ readonly requestID?: string;
15
+ constructor(message: string, options?: {
16
+ status?: number;
17
+ headers?: Headers;
18
+ body?: unknown;
19
+ code?: string;
20
+ errorType?: string;
21
+ requestID?: string;
22
+ });
23
+ }
24
+ export declare class APIConnectionError extends APIError {
25
+ constructor(message: string, cause?: unknown);
26
+ }
27
+ export declare class APIStatusError extends APIError {
28
+ readonly status: number;
29
+ constructor(message: string, status: number, headers: Headers, body: unknown, options?: {
30
+ code?: string;
31
+ errorType?: string;
32
+ requestID?: string;
33
+ });
34
+ }
35
+ export declare class AuthenticationError extends APIStatusError {
36
+ constructor(message: string, status: number, headers: Headers, body: unknown, options?: {});
37
+ }
38
+ export declare class PermissionDeniedError extends APIStatusError {
39
+ constructor(message: string, status: number, headers: Headers, body: unknown, options?: {});
40
+ }
41
+ export declare class NotFoundError extends APIStatusError {
42
+ constructor(message: string, status: number, headers: Headers, body: unknown, options?: {});
43
+ }
44
+ export declare class BadRequestError extends APIStatusError {
45
+ constructor(message: string, status: number, headers: Headers, body: unknown, options?: {});
46
+ }
47
+ export declare class RateLimitError extends APIStatusError {
48
+ readonly retryAfterMs?: number;
49
+ constructor(message: string, status: number, headers: Headers, body: unknown, retryAfterMs?: number, options?: {
50
+ code?: string;
51
+ errorType?: string;
52
+ requestID?: string;
53
+ });
54
+ }
55
+ export declare class InternalServerError extends APIStatusError {
56
+ constructor(message: string, status: number, headers: Headers, body: unknown, options?: {});
57
+ }
58
+ export declare function requestIDFromHeaders(headers: Headers): string | undefined;
59
+ export declare function retryAfterMsFromHeaders(headers: Headers): number | undefined;
60
+ export declare function parseResponseError(response: Response): Promise<APIStatusError>;
61
+ export declare function isRetryableStatus(status: number): boolean;
package/dist/errors.js ADDED
@@ -0,0 +1,130 @@
1
+ export class APIError extends Error {
2
+ status;
3
+ headers;
4
+ body;
5
+ code;
6
+ errorType;
7
+ requestID;
8
+ constructor(message, options = {}) {
9
+ super(message);
10
+ this.name = "APIError";
11
+ this.status = options.status;
12
+ this.headers = options.headers;
13
+ this.body = options.body;
14
+ this.code = options.code;
15
+ this.errorType = options.errorType;
16
+ this.requestID = options.requestID;
17
+ }
18
+ }
19
+ export class APIConnectionError extends APIError {
20
+ constructor(message, cause) {
21
+ super(message, { body: cause });
22
+ this.name = "APIConnectionError";
23
+ }
24
+ }
25
+ export class APIStatusError extends APIError {
26
+ status;
27
+ constructor(message, status, headers, body, options = {}) {
28
+ super(message, { status, headers, body, ...options });
29
+ this.name = "APIStatusError";
30
+ this.status = status;
31
+ }
32
+ }
33
+ export class AuthenticationError extends APIStatusError {
34
+ constructor(message, status, headers, body, options = {}) {
35
+ super(message, status, headers, body, options);
36
+ this.name = "AuthenticationError";
37
+ }
38
+ }
39
+ export class PermissionDeniedError extends APIStatusError {
40
+ constructor(message, status, headers, body, options = {}) {
41
+ super(message, status, headers, body, options);
42
+ this.name = "PermissionDeniedError";
43
+ }
44
+ }
45
+ export class NotFoundError extends APIStatusError {
46
+ constructor(message, status, headers, body, options = {}) {
47
+ super(message, status, headers, body, options);
48
+ this.name = "NotFoundError";
49
+ }
50
+ }
51
+ export class BadRequestError extends APIStatusError {
52
+ constructor(message, status, headers, body, options = {}) {
53
+ super(message, status, headers, body, options);
54
+ this.name = "BadRequestError";
55
+ }
56
+ }
57
+ export class RateLimitError extends APIStatusError {
58
+ retryAfterMs;
59
+ constructor(message, status, headers, body, retryAfterMs, options = {}) {
60
+ super(message, status, headers, body, options);
61
+ this.name = "RateLimitError";
62
+ this.retryAfterMs = retryAfterMs;
63
+ }
64
+ }
65
+ export class InternalServerError extends APIStatusError {
66
+ constructor(message, status, headers, body, options = {}) {
67
+ super(message, status, headers, body, options);
68
+ this.name = "InternalServerError";
69
+ }
70
+ }
71
+ export function requestIDFromHeaders(headers) {
72
+ return headers.get("x-request-id") ?? headers.get("request-id") ?? undefined;
73
+ }
74
+ export function retryAfterMsFromHeaders(headers) {
75
+ const raw = headers.get("retry-after");
76
+ if (!raw) {
77
+ return undefined;
78
+ }
79
+ const seconds = Number(raw);
80
+ if (Number.isFinite(seconds)) {
81
+ return Math.max(0, seconds * 1000);
82
+ }
83
+ const date = Date.parse(raw);
84
+ if (Number.isFinite(date)) {
85
+ return Math.max(0, date - Date.now());
86
+ }
87
+ return undefined;
88
+ }
89
+ function errorFields(body) {
90
+ if (typeof body === "object" && body !== null && "error" in body) {
91
+ const err = body.error;
92
+ if (err && typeof err.message === "string") {
93
+ return { message: err.message, code: err.code, errorType: err.type };
94
+ }
95
+ }
96
+ return { message: "" };
97
+ }
98
+ export async function parseResponseError(response) {
99
+ let body;
100
+ try {
101
+ body = await response.json();
102
+ }
103
+ catch {
104
+ body = await response.text().catch(() => "");
105
+ }
106
+ const { message, code, errorType } = errorFields(body);
107
+ const requestID = requestIDFromHeaders(response.headers);
108
+ const finalMessage = message || `API request failed with status ${response.status}`;
109
+ const common = { code, errorType, requestID };
110
+ switch (response.status) {
111
+ case 400:
112
+ return new BadRequestError(finalMessage, response.status, response.headers, body, common);
113
+ case 401:
114
+ return new AuthenticationError(finalMessage, response.status, response.headers, body, common);
115
+ case 403:
116
+ return new PermissionDeniedError(finalMessage, response.status, response.headers, body, common);
117
+ case 404:
118
+ return new NotFoundError(finalMessage, response.status, response.headers, body, common);
119
+ case 429:
120
+ return new RateLimitError(finalMessage, response.status, response.headers, body, retryAfterMsFromHeaders(response.headers), common);
121
+ default:
122
+ if (response.status >= 500) {
123
+ return new InternalServerError(finalMessage, response.status, response.headers, body, common);
124
+ }
125
+ return new APIStatusError(finalMessage, response.status, response.headers, body, common);
126
+ }
127
+ }
128
+ export function isRetryableStatus(status) {
129
+ return status === 408 || status === 409 || status === 429 || status === 500 || status === 502 || status === 503 || status === 504;
130
+ }
@@ -0,0 +1,7 @@
1
+ export { AgentAPI, DEFAULT_MAX_RETRIES, DEFAULT_STREAM_TIMEOUT_MS, DEFAULT_TIMEOUT_MS, VERSION } from "./client.js";
2
+ export { Page, collectPage } from "./pagination.js";
3
+ export type { PageParams, PageResult } from "./pagination.js";
4
+ export { APIError, APIConnectionError, APIStatusError, AuthenticationError, BadRequestError, InternalServerError, NotFoundError, PermissionDeniedError, RateLimitError, isRetryableStatus, parseResponseError, } from "./errors.js";
5
+ export * from "./types/index.js";
6
+ export { functionCallOutputInput, pendingFunctionCalls, runLocalFunctionHandlers, } from "./local-functions.js";
7
+ export type { LocalFunctionHandler, LocalFunctionHandlers } from "./local-functions.js";
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export { AgentAPI, DEFAULT_MAX_RETRIES, DEFAULT_STREAM_TIMEOUT_MS, DEFAULT_TIMEOUT_MS, VERSION } from "./client.js";
2
+ export { Page, collectPage } from "./pagination.js";
3
+ export { APIError, APIConnectionError, APIStatusError, AuthenticationError, BadRequestError, InternalServerError, NotFoundError, PermissionDeniedError, RateLimitError, isRetryableStatus, parseResponseError, } from "./errors.js";
4
+ export * from "./types/index.js";
5
+ export { functionCallOutputInput, pendingFunctionCalls, runLocalFunctionHandlers, } from "./local-functions.js";
@@ -0,0 +1 @@
1
+ export declare function readEnv(name: string): string | undefined;
@@ -0,0 +1,4 @@
1
+ export function readEnv(name) {
2
+ const env = globalThis.process?.env;
3
+ return env?.[name];
4
+ }
@@ -0,0 +1,18 @@
1
+ import type { RequestOptions } from "../types/common.js";
2
+ export interface HTTPClientOptions {
3
+ baseURL: string;
4
+ apiKey?: string;
5
+ timeout: number;
6
+ streamTimeout: number;
7
+ maxRetries: number;
8
+ defaultHeaders: Record<string, string>;
9
+ fetchImpl: typeof fetch;
10
+ }
11
+ export declare class HTTPClient {
12
+ private readonly options;
13
+ constructor(options: HTTPClientOptions);
14
+ request<T>(method: string, path: string, body?: unknown, options?: RequestOptions): Promise<T>;
15
+ stream<T>(path: string, body: unknown, options?: RequestOptions): Promise<AsyncIterable<T>>;
16
+ private fetchWithRetry;
17
+ private fetchOnce;
18
+ }
@@ -0,0 +1,93 @@
1
+ import { APIConnectionError, APIError, isRetryableStatus, parseResponseError, RateLimitError, } from "../errors.js";
2
+ import { parseSSE } from "../streaming.js";
3
+ import { USER_AGENT } from "../version.js";
4
+ export class HTTPClient {
5
+ options;
6
+ constructor(options) {
7
+ this.options = options;
8
+ }
9
+ async request(method, path, body, options = {}) {
10
+ const response = await this.fetchWithRetry(method, path, body, options, false);
11
+ return (await response.json());
12
+ }
13
+ async stream(path, body, options = {}) {
14
+ const response = await this.fetchWithRetry("POST", path, body, options, true);
15
+ return parseSSE(response);
16
+ }
17
+ async fetchWithRetry(method, path, body, options, stream) {
18
+ const maxRetries = options.maxRetries ?? this.options.maxRetries;
19
+ let attempt = 0;
20
+ for (;;) {
21
+ try {
22
+ return await this.fetchOnce(method, path, body, options, stream);
23
+ }
24
+ catch (error) {
25
+ if (!(error instanceof APIError) || attempt >= maxRetries) {
26
+ throw error;
27
+ }
28
+ const retryable = error instanceof APIConnectionError ||
29
+ (error.status !== undefined && isRetryableStatus(error.status));
30
+ if (!retryable) {
31
+ throw error;
32
+ }
33
+ attempt += 1;
34
+ const delayMs = retryDelayMs(error, attempt);
35
+ await sleep(delayMs);
36
+ }
37
+ }
38
+ }
39
+ async fetchOnce(method, path, body, options, stream) {
40
+ const controller = new AbortController();
41
+ const timeout = options.timeout ?? (stream ? this.options.streamTimeout : this.options.timeout);
42
+ const timeoutID = setTimeout(() => controller.abort(), timeout);
43
+ try {
44
+ const headers = {
45
+ Accept: stream ? "text/event-stream" : "application/json",
46
+ "User-Agent": USER_AGENT,
47
+ ...this.options.defaultHeaders,
48
+ ...options.headers,
49
+ };
50
+ if (body !== undefined) {
51
+ headers["Content-Type"] = "application/json";
52
+ }
53
+ if (this.options.apiKey) {
54
+ headers.Authorization = `Bearer ${this.options.apiKey}`;
55
+ }
56
+ const response = await this.options.fetchImpl(`${this.options.baseURL}${path}`, {
57
+ method,
58
+ headers,
59
+ body: body === undefined ? undefined : JSON.stringify(body),
60
+ signal: controller.signal,
61
+ });
62
+ if (!response.ok) {
63
+ throw await parseResponseError(response);
64
+ }
65
+ return response;
66
+ }
67
+ catch (error) {
68
+ if (error instanceof APIError) {
69
+ throw error;
70
+ }
71
+ if (error instanceof Error && error.name === "AbortError") {
72
+ throw new APIConnectionError(`Request timed out after ${timeout}ms`, error);
73
+ }
74
+ throw new APIConnectionError("Request failed", error);
75
+ }
76
+ finally {
77
+ clearTimeout(timeoutID);
78
+ }
79
+ }
80
+ }
81
+ function retryDelayMs(error, attempt) {
82
+ if (error instanceof RateLimitError && error.retryAfterMs !== undefined) {
83
+ return error.retryAfterMs;
84
+ }
85
+ const base = 250;
86
+ const cap = 8000;
87
+ const exponential = Math.min(cap, base * 2 ** (attempt - 1));
88
+ const jitter = Math.floor(Math.random() * 100);
89
+ return exponential + jitter;
90
+ }
91
+ function sleep(ms) {
92
+ return new Promise((resolve) => setTimeout(resolve, ms));
93
+ }
@@ -0,0 +1,2 @@
1
+ import type { AgentResponse } from "../types/responses.js";
2
+ export declare function addOutputText(response: AgentResponse): AgentResponse;
@@ -0,0 +1,12 @@
1
+ export function addOutputText(response) {
2
+ if (response.output_text !== undefined) {
3
+ return response;
4
+ }
5
+ response.output_text = response.output
6
+ .filter((item) => item.type === "message")
7
+ .flatMap((item) => item.content)
8
+ .filter((part) => part.type === "output_text")
9
+ .map((part) => part.text ?? "")
10
+ .join("");
11
+ return response;
12
+ }
@@ -0,0 +1 @@
1
+ export declare function buildQuery(params: Record<string, string | number | undefined>): string;
@@ -0,0 +1,10 @@
1
+ export function buildQuery(params) {
2
+ const search = new URLSearchParams();
3
+ for (const [key, value] of Object.entries(params)) {
4
+ if (value !== undefined && value !== "") {
5
+ search.set(key, String(value));
6
+ }
7
+ }
8
+ const qs = search.toString();
9
+ return qs ? `?${qs}` : "";
10
+ }
@@ -0,0 +1,9 @@
1
+ import type { FunctionCallOutputInput } from "./types/input.js";
2
+ import type { AgentResponse, FunctionCallOutputItem } from "./types/responses.js";
3
+ /** Pending client-executed function calls from a requires_action response. */
4
+ export declare function pendingFunctionCalls(response: AgentResponse): FunctionCallOutputItem[];
5
+ export declare function functionCallOutputInput(callID: string, output: string | Record<string, unknown>): FunctionCallOutputInput;
6
+ export type LocalFunctionHandler = (args: Record<string, unknown>) => string | Record<string, unknown> | Promise<string | Record<string, unknown>>;
7
+ export type LocalFunctionHandlers = Record<string, LocalFunctionHandler>;
8
+ /** Run local handlers for pending function calls and return function_call_output input items. */
9
+ export declare function runLocalFunctionHandlers(response: AgentResponse, handlers: LocalFunctionHandlers): Promise<FunctionCallOutputInput[]>;
@@ -0,0 +1,32 @@
1
+ /** Pending client-executed function calls from a requires_action response. */
2
+ export function pendingFunctionCalls(response) {
3
+ if (response.status !== "requires_action") {
4
+ return [];
5
+ }
6
+ return response.output.filter((item) => item.type === "function_call");
7
+ }
8
+ export function functionCallOutputInput(callID, output) {
9
+ return {
10
+ type: "function_call_output",
11
+ call_id: callID,
12
+ output: typeof output === "string" ? output : JSON.stringify(output),
13
+ };
14
+ }
15
+ /** Run local handlers for pending function calls and return function_call_output input items. */
16
+ export async function runLocalFunctionHandlers(response, handlers) {
17
+ const pending = pendingFunctionCalls(response);
18
+ const outputs = [];
19
+ for (const call of pending) {
20
+ const handler = handlers[call.name];
21
+ if (!handler) {
22
+ throw new Error(`no local handler registered for function ${call.name}`);
23
+ }
24
+ let args = {};
25
+ if (call.arguments) {
26
+ args = JSON.parse(call.arguments);
27
+ }
28
+ const result = await handler(args);
29
+ outputs.push(functionCallOutputInput(call.call_id, result));
30
+ }
31
+ return outputs;
32
+ }
@@ -0,0 +1,21 @@
1
+ export interface PageParams {
2
+ limit?: number;
3
+ page_token?: string;
4
+ }
5
+ export interface PageResult<T> {
6
+ data: T[];
7
+ has_more: boolean;
8
+ next_page_token?: string;
9
+ }
10
+ export declare class Page<TItem, TParams extends PageParams> implements AsyncIterable<TItem> {
11
+ private readonly fetchPage;
12
+ readonly params: TParams;
13
+ readonly data: TItem[];
14
+ readonly hasMore: boolean;
15
+ readonly nextPageToken?: string | undefined;
16
+ constructor(fetchPage: (params: TParams) => Promise<PageResult<TItem>>, params: TParams, data: TItem[], hasMore: boolean, nextPageToken?: string | undefined);
17
+ [Symbol.asyncIterator](): AsyncIterator<TItem>;
18
+ getNextPage(): Promise<Page<TItem, TParams> | null>;
19
+ iterateAll(): AsyncGenerator<TItem, void, undefined>;
20
+ }
21
+ export declare function collectPage<TItem, TParams extends PageParams>(fetchPage: (params: TParams) => Promise<PageResult<TItem>>, params: TParams): Promise<Page<TItem, TParams>>;