@happyrobot-ai/sdk 0.1.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/client.d.ts +85 -0
- package/client.js +115 -0
- package/client.mjs +3 -0
- package/core/errors.d.ts +48 -0
- package/core/errors.js +82 -0
- package/core/errors.mjs +3 -0
- package/core/http.d.ts +26 -0
- package/core/http.js +189 -0
- package/core/http.mjs +3 -0
- package/core/pagination.d.ts +22 -0
- package/core/pagination.js +43 -0
- package/core/pagination.mjs +3 -0
- package/core/sse.d.ts +20 -0
- package/core/sse.js +104 -0
- package/core/sse.mjs +3 -0
- package/core/types.d.ts +50 -0
- package/core/types.js +6 -0
- package/core/types.mjs +3 -0
- package/helpers/index.d.ts +14 -0
- package/helpers/index.js +18 -0
- package/helpers/index.mjs +3 -0
- package/helpers/template-workflows.d.ts +49 -0
- package/helpers/template-workflows.js +46 -0
- package/helpers/template-workflows.mjs +3 -0
- package/helpers/trigger-and-wait.d.ts +37 -0
- package/helpers/trigger-and-wait.js +62 -0
- package/helpers/trigger-and-wait.mjs +3 -0
- package/helpers/voice-agent.d.ts +47 -0
- package/helpers/voice-agent.js +47 -0
- package/helpers/voice-agent.mjs +3 -0
- package/index.d.ts +75 -0
- package/index.js +90 -0
- package/index.mjs +3 -0
- package/package.json +42 -0
- package/resources/adversarial-suites.d.ts +42 -0
- package/resources/adversarial-suites.js +96 -0
- package/resources/adversarial-suites.mjs +3 -0
- package/resources/adversarial-tests.d.ts +36 -0
- package/resources/adversarial-tests.js +78 -0
- package/resources/adversarial-tests.mjs +3 -0
- package/resources/api-key.d.ts +23 -0
- package/resources/api-key.js +24 -0
- package/resources/api-key.mjs +3 -0
- package/resources/audit-remarks.d.ts +22 -0
- package/resources/audit-remarks.js +44 -0
- package/resources/audit-remarks.mjs +3 -0
- package/resources/billing.d.ts +25 -0
- package/resources/billing.js +34 -0
- package/resources/billing.mjs +3 -0
- package/resources/contacts.d.ts +40 -0
- package/resources/contacts.js +61 -0
- package/resources/contacts.mjs +3 -0
- package/resources/custom-evals.d.ts +28 -0
- package/resources/custom-evals.js +62 -0
- package/resources/custom-evals.mjs +3 -0
- package/resources/integrations.d.ts +95 -0
- package/resources/integrations.js +220 -0
- package/resources/integrations.mjs +3 -0
- package/resources/issues.d.ts +14 -0
- package/resources/issues.js +25 -0
- package/resources/issues.mjs +3 -0
- package/resources/knowledge-bases.d.ts +35 -0
- package/resources/knowledge-bases.js +68 -0
- package/resources/knowledge-bases.mjs +3 -0
- package/resources/mcp.d.ts +20 -0
- package/resources/mcp.js +42 -0
- package/resources/mcp.mjs +3 -0
- package/resources/messages.d.ts +17 -0
- package/resources/messages.js +37 -0
- package/resources/messages.mjs +3 -0
- package/resources/nodes.d.ts +50 -0
- package/resources/nodes.js +86 -0
- package/resources/nodes.mjs +3 -0
- package/resources/northstars.d.ts +29 -0
- package/resources/northstars.js +69 -0
- package/resources/northstars.mjs +3 -0
- package/resources/phone-numbers.d.ts +47 -0
- package/resources/phone-numbers.js +121 -0
- package/resources/phone-numbers.mjs +3 -0
- package/resources/runs.d.ts +31 -0
- package/resources/runs.js +71 -0
- package/resources/runs.mjs +3 -0
- package/resources/sessions.d.ts +36 -0
- package/resources/sessions.js +62 -0
- package/resources/sessions.mjs +3 -0
- package/resources/sip-trunks.d.ts +32 -0
- package/resources/sip-trunks.js +78 -0
- package/resources/sip-trunks.mjs +3 -0
- package/resources/usage.d.ts +27 -0
- package/resources/usage.js +70 -0
- package/resources/usage.mjs +3 -0
- package/resources/variables.d.ts +23 -0
- package/resources/variables.js +54 -0
- package/resources/variables.mjs +3 -0
- package/resources/versions.d.ts +38 -0
- package/resources/versions.js +90 -0
- package/resources/versions.mjs +3 -0
- package/resources/workflow-folders.d.ts +26 -0
- package/resources/workflow-folders.js +62 -0
- package/resources/workflow-folders.mjs +3 -0
- package/resources/workflows.d.ts +55 -0
- package/resources/workflows.js +134 -0
- package/resources/workflows.mjs +3 -0
package/client.d.ts
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HappyRobotClient — the main SDK entry point.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```ts
|
|
6
|
+
* import { HappyRobotClient } from "@happyrobot/sdk";
|
|
7
|
+
*
|
|
8
|
+
* const client = new HappyRobotClient({ apiKey: "sk_live_..." });
|
|
9
|
+
* const workflows = await client.workflows.list();
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
import type { ClientConfig } from "./core/types";
|
|
13
|
+
import { WorkflowsResource } from "./resources/workflows";
|
|
14
|
+
import { VersionsResource } from "./resources/versions";
|
|
15
|
+
import { NodesResource } from "./resources/nodes";
|
|
16
|
+
import { RunsResource } from "./resources/runs";
|
|
17
|
+
import { SessionsResource } from "./resources/sessions";
|
|
18
|
+
import { MessagesResource } from "./resources/messages";
|
|
19
|
+
import { VariablesResource } from "./resources/variables";
|
|
20
|
+
import { PhoneNumbersResource } from "./resources/phone-numbers";
|
|
21
|
+
import { SipTrunksResource } from "./resources/sip-trunks";
|
|
22
|
+
import { IntegrationsResource } from "./resources/integrations";
|
|
23
|
+
import { ContactsResource } from "./resources/contacts";
|
|
24
|
+
import { KnowledgeBasesResource } from "./resources/knowledge-bases";
|
|
25
|
+
import { WorkflowFoldersResource } from "./resources/workflow-folders";
|
|
26
|
+
import { MCPResource } from "./resources/mcp";
|
|
27
|
+
import { UsageResource } from "./resources/usage";
|
|
28
|
+
import { BillingResource } from "./resources/billing";
|
|
29
|
+
import { ApiKeyResource } from "./resources/api-key";
|
|
30
|
+
import { AdversarialSuitesResource } from "./resources/adversarial-suites";
|
|
31
|
+
import { AdversarialTestsResource } from "./resources/adversarial-tests";
|
|
32
|
+
import { NorthstarsResource } from "./resources/northstars";
|
|
33
|
+
import { CustomEvalsResource } from "./resources/custom-evals";
|
|
34
|
+
import { IssuesResource } from "./resources/issues";
|
|
35
|
+
import { AuditRemarksResource } from "./resources/audit-remarks";
|
|
36
|
+
export declare class HappyRobotClient {
|
|
37
|
+
private readonly http;
|
|
38
|
+
/** Workflow CRUD, publishing, runs, and templates. */
|
|
39
|
+
readonly workflows: WorkflowsResource;
|
|
40
|
+
/** Version management (fork, publish, lock, test). */
|
|
41
|
+
readonly versions: VersionsResource;
|
|
42
|
+
/** Node CRUD, config schema, and available variables. */
|
|
43
|
+
readonly nodes: NodesResource;
|
|
44
|
+
/** Run details, cancellation, and annotations. */
|
|
45
|
+
readonly runs: RunsResource;
|
|
46
|
+
/** Session details and messages. */
|
|
47
|
+
readonly sessions: SessionsResource;
|
|
48
|
+
/** Message quality flags. */
|
|
49
|
+
readonly messages: MessagesResource;
|
|
50
|
+
/** Workflow-scoped variables. */
|
|
51
|
+
readonly variables: VariablesResource;
|
|
52
|
+
/** Phone number management. */
|
|
53
|
+
readonly phoneNumbers: PhoneNumbersResource;
|
|
54
|
+
/** SIP trunk management. */
|
|
55
|
+
readonly sipTrunks: SipTrunksResource;
|
|
56
|
+
/** Integration and event discovery. */
|
|
57
|
+
readonly integrations: IntegrationsResource;
|
|
58
|
+
/** Contact lookup and history. */
|
|
59
|
+
readonly contacts: ContactsResource;
|
|
60
|
+
/** Knowledge base document management. */
|
|
61
|
+
readonly knowledgeBases: KnowledgeBasesResource;
|
|
62
|
+
/** Workflow folder organization. */
|
|
63
|
+
readonly workflowFolders: WorkflowFoldersResource;
|
|
64
|
+
/** MCP server management. */
|
|
65
|
+
readonly mcp: MCPResource;
|
|
66
|
+
/** Usage metrics (call minutes, tokens, etc.). */
|
|
67
|
+
readonly usage: UsageResource;
|
|
68
|
+
/** Billing usage details and totals. */
|
|
69
|
+
readonly billing: BillingResource;
|
|
70
|
+
/** API key introspection. */
|
|
71
|
+
readonly apiKey: ApiKeyResource;
|
|
72
|
+
/** Adversarial suite management and execution. */
|
|
73
|
+
readonly adversarialSuites: AdversarialSuitesResource;
|
|
74
|
+
/** Adversarial test management and execution. */
|
|
75
|
+
readonly adversarialTests: AdversarialTestsResource;
|
|
76
|
+
/** Northstar quality criteria management. */
|
|
77
|
+
readonly northstars: NorthstarsResource;
|
|
78
|
+
/** Custom eval management and execution. */
|
|
79
|
+
readonly customEvals: CustomEvalsResource;
|
|
80
|
+
/** Quality issue (flag) status management. */
|
|
81
|
+
readonly issues: IssuesResource;
|
|
82
|
+
/** Audit remark feedback management. */
|
|
83
|
+
readonly auditRemarks: AuditRemarksResource;
|
|
84
|
+
constructor(config: ClientConfig);
|
|
85
|
+
}
|
package/client.js
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* HappyRobotClient — the main SDK entry point.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```ts
|
|
7
|
+
* import { HappyRobotClient } from "@happyrobot/sdk";
|
|
8
|
+
*
|
|
9
|
+
* const client = new HappyRobotClient({ apiKey: "sk_live_..." });
|
|
10
|
+
* const workflows = await client.workflows.list();
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.HappyRobotClient = void 0;
|
|
15
|
+
const http_1 = require("./core/http");
|
|
16
|
+
const workflows_1 = require("./resources/workflows");
|
|
17
|
+
const versions_1 = require("./resources/versions");
|
|
18
|
+
const nodes_1 = require("./resources/nodes");
|
|
19
|
+
const runs_1 = require("./resources/runs");
|
|
20
|
+
const sessions_1 = require("./resources/sessions");
|
|
21
|
+
const messages_1 = require("./resources/messages");
|
|
22
|
+
const variables_1 = require("./resources/variables");
|
|
23
|
+
const phone_numbers_1 = require("./resources/phone-numbers");
|
|
24
|
+
const sip_trunks_1 = require("./resources/sip-trunks");
|
|
25
|
+
const integrations_1 = require("./resources/integrations");
|
|
26
|
+
const contacts_1 = require("./resources/contacts");
|
|
27
|
+
const knowledge_bases_1 = require("./resources/knowledge-bases");
|
|
28
|
+
const workflow_folders_1 = require("./resources/workflow-folders");
|
|
29
|
+
const mcp_1 = require("./resources/mcp");
|
|
30
|
+
const usage_1 = require("./resources/usage");
|
|
31
|
+
const billing_1 = require("./resources/billing");
|
|
32
|
+
const api_key_1 = require("./resources/api-key");
|
|
33
|
+
const adversarial_suites_1 = require("./resources/adversarial-suites");
|
|
34
|
+
const adversarial_tests_1 = require("./resources/adversarial-tests");
|
|
35
|
+
const northstars_1 = require("./resources/northstars");
|
|
36
|
+
const custom_evals_1 = require("./resources/custom-evals");
|
|
37
|
+
const issues_1 = require("./resources/issues");
|
|
38
|
+
const audit_remarks_1 = require("./resources/audit-remarks");
|
|
39
|
+
class HappyRobotClient {
|
|
40
|
+
http;
|
|
41
|
+
/** Workflow CRUD, publishing, runs, and templates. */
|
|
42
|
+
workflows;
|
|
43
|
+
/** Version management (fork, publish, lock, test). */
|
|
44
|
+
versions;
|
|
45
|
+
/** Node CRUD, config schema, and available variables. */
|
|
46
|
+
nodes;
|
|
47
|
+
/** Run details, cancellation, and annotations. */
|
|
48
|
+
runs;
|
|
49
|
+
/** Session details and messages. */
|
|
50
|
+
sessions;
|
|
51
|
+
/** Message quality flags. */
|
|
52
|
+
messages;
|
|
53
|
+
/** Workflow-scoped variables. */
|
|
54
|
+
variables;
|
|
55
|
+
/** Phone number management. */
|
|
56
|
+
phoneNumbers;
|
|
57
|
+
/** SIP trunk management. */
|
|
58
|
+
sipTrunks;
|
|
59
|
+
/** Integration and event discovery. */
|
|
60
|
+
integrations;
|
|
61
|
+
/** Contact lookup and history. */
|
|
62
|
+
contacts;
|
|
63
|
+
/** Knowledge base document management. */
|
|
64
|
+
knowledgeBases;
|
|
65
|
+
/** Workflow folder organization. */
|
|
66
|
+
workflowFolders;
|
|
67
|
+
/** MCP server management. */
|
|
68
|
+
mcp;
|
|
69
|
+
/** Usage metrics (call minutes, tokens, etc.). */
|
|
70
|
+
usage;
|
|
71
|
+
/** Billing usage details and totals. */
|
|
72
|
+
billing;
|
|
73
|
+
/** API key introspection. */
|
|
74
|
+
apiKey;
|
|
75
|
+
/** Adversarial suite management and execution. */
|
|
76
|
+
adversarialSuites;
|
|
77
|
+
/** Adversarial test management and execution. */
|
|
78
|
+
adversarialTests;
|
|
79
|
+
/** Northstar quality criteria management. */
|
|
80
|
+
northstars;
|
|
81
|
+
/** Custom eval management and execution. */
|
|
82
|
+
customEvals;
|
|
83
|
+
/** Quality issue (flag) status management. */
|
|
84
|
+
issues;
|
|
85
|
+
/** Audit remark feedback management. */
|
|
86
|
+
auditRemarks;
|
|
87
|
+
constructor(config) {
|
|
88
|
+
this.http = new http_1.HttpClient(config);
|
|
89
|
+
this.workflows = new workflows_1.WorkflowsResource(this.http);
|
|
90
|
+
this.versions = new versions_1.VersionsResource(this.http);
|
|
91
|
+
this.nodes = new nodes_1.NodesResource(this.http);
|
|
92
|
+
this.runs = new runs_1.RunsResource(this.http);
|
|
93
|
+
this.sessions = new sessions_1.SessionsResource(this.http);
|
|
94
|
+
this.messages = new messages_1.MessagesResource(this.http);
|
|
95
|
+
this.variables = new variables_1.VariablesResource(this.http);
|
|
96
|
+
this.phoneNumbers = new phone_numbers_1.PhoneNumbersResource(this.http);
|
|
97
|
+
this.sipTrunks = new sip_trunks_1.SipTrunksResource(this.http);
|
|
98
|
+
this.integrations = new integrations_1.IntegrationsResource(this.http);
|
|
99
|
+
this.contacts = new contacts_1.ContactsResource(this.http);
|
|
100
|
+
this.knowledgeBases = new knowledge_bases_1.KnowledgeBasesResource(this.http);
|
|
101
|
+
this.workflowFolders = new workflow_folders_1.WorkflowFoldersResource(this.http);
|
|
102
|
+
this.mcp = new mcp_1.MCPResource(this.http);
|
|
103
|
+
this.usage = new usage_1.UsageResource(this.http);
|
|
104
|
+
this.billing = new billing_1.BillingResource(this.http);
|
|
105
|
+
this.apiKey = new api_key_1.ApiKeyResource(this.http);
|
|
106
|
+
this.adversarialSuites = new adversarial_suites_1.AdversarialSuitesResource(this.http);
|
|
107
|
+
this.adversarialTests = new adversarial_tests_1.AdversarialTestsResource(this.http);
|
|
108
|
+
this.northstars = new northstars_1.NorthstarsResource(this.http);
|
|
109
|
+
this.customEvals = new custom_evals_1.CustomEvalsResource(this.http);
|
|
110
|
+
this.issues = new issues_1.IssuesResource(this.http);
|
|
111
|
+
this.auditRemarks = new audit_remarks_1.AuditRemarksResource(this.http);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
exports.HappyRobotClient = HappyRobotClient;
|
|
115
|
+
//# sourceMappingURL=client.js.map
|
package/client.mjs
ADDED
package/core/errors.d.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error classes for the HappyRobot SDK.
|
|
3
|
+
*
|
|
4
|
+
* Hierarchy:
|
|
5
|
+
* HappyRobotError (base)
|
|
6
|
+
* ├── ApiError (any non-2xx with status, error, message, details)
|
|
7
|
+
* │ ├── AuthenticationError (401)
|
|
8
|
+
* │ ├── NotFoundError (404)
|
|
9
|
+
* │ ├── ValidationError (400/422)
|
|
10
|
+
* │ └── RateLimitError (429, includes retryAfter)
|
|
11
|
+
* ├── TimeoutError (fetch timeout)
|
|
12
|
+
* └── NetworkError (fetch failures)
|
|
13
|
+
*/
|
|
14
|
+
export declare class HappyRobotError extends Error {
|
|
15
|
+
constructor(message: string);
|
|
16
|
+
}
|
|
17
|
+
export interface ApiErrorBody {
|
|
18
|
+
error?: string;
|
|
19
|
+
message?: string;
|
|
20
|
+
statusCode?: number;
|
|
21
|
+
details?: unknown;
|
|
22
|
+
detail?: unknown;
|
|
23
|
+
}
|
|
24
|
+
export declare class ApiError extends HappyRobotError {
|
|
25
|
+
readonly status: number;
|
|
26
|
+
readonly body: ApiErrorBody;
|
|
27
|
+
constructor(status: number, body: ApiErrorBody);
|
|
28
|
+
}
|
|
29
|
+
export declare class AuthenticationError extends ApiError {
|
|
30
|
+
constructor(body: ApiErrorBody);
|
|
31
|
+
}
|
|
32
|
+
export declare class NotFoundError extends ApiError {
|
|
33
|
+
constructor(body: ApiErrorBody);
|
|
34
|
+
}
|
|
35
|
+
export declare class ValidationError extends ApiError {
|
|
36
|
+
constructor(status: number, body: ApiErrorBody);
|
|
37
|
+
}
|
|
38
|
+
export declare class RateLimitError extends ApiError {
|
|
39
|
+
readonly retryAfter: number | null;
|
|
40
|
+
constructor(body: ApiErrorBody, retryAfter: number | null);
|
|
41
|
+
}
|
|
42
|
+
export declare class TimeoutError extends HappyRobotError {
|
|
43
|
+
constructor(timeoutMs: number);
|
|
44
|
+
}
|
|
45
|
+
export declare class NetworkError extends HappyRobotError {
|
|
46
|
+
readonly cause: unknown;
|
|
47
|
+
constructor(message: string, cause?: unknown);
|
|
48
|
+
}
|
package/core/errors.js
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Error classes for the HappyRobot SDK.
|
|
4
|
+
*
|
|
5
|
+
* Hierarchy:
|
|
6
|
+
* HappyRobotError (base)
|
|
7
|
+
* ├── ApiError (any non-2xx with status, error, message, details)
|
|
8
|
+
* │ ├── AuthenticationError (401)
|
|
9
|
+
* │ ├── NotFoundError (404)
|
|
10
|
+
* │ ├── ValidationError (400/422)
|
|
11
|
+
* │ └── RateLimitError (429, includes retryAfter)
|
|
12
|
+
* ├── TimeoutError (fetch timeout)
|
|
13
|
+
* └── NetworkError (fetch failures)
|
|
14
|
+
*/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.NetworkError = exports.TimeoutError = exports.RateLimitError = exports.ValidationError = exports.NotFoundError = exports.AuthenticationError = exports.ApiError = exports.HappyRobotError = void 0;
|
|
17
|
+
class HappyRobotError extends Error {
|
|
18
|
+
constructor(message) {
|
|
19
|
+
super(message);
|
|
20
|
+
this.name = "HappyRobotError";
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
exports.HappyRobotError = HappyRobotError;
|
|
24
|
+
class ApiError extends HappyRobotError {
|
|
25
|
+
status;
|
|
26
|
+
body;
|
|
27
|
+
constructor(status, body) {
|
|
28
|
+
const msg = body.message || body.error || `API error ${status}`;
|
|
29
|
+
super(msg);
|
|
30
|
+
this.name = "ApiError";
|
|
31
|
+
this.status = status;
|
|
32
|
+
this.body = body;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
exports.ApiError = ApiError;
|
|
36
|
+
class AuthenticationError extends ApiError {
|
|
37
|
+
constructor(body) {
|
|
38
|
+
super(401, body);
|
|
39
|
+
this.name = "AuthenticationError";
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
exports.AuthenticationError = AuthenticationError;
|
|
43
|
+
class NotFoundError extends ApiError {
|
|
44
|
+
constructor(body) {
|
|
45
|
+
super(404, body);
|
|
46
|
+
this.name = "NotFoundError";
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
exports.NotFoundError = NotFoundError;
|
|
50
|
+
class ValidationError extends ApiError {
|
|
51
|
+
constructor(status, body) {
|
|
52
|
+
super(status, body);
|
|
53
|
+
this.name = "ValidationError";
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
exports.ValidationError = ValidationError;
|
|
57
|
+
class RateLimitError extends ApiError {
|
|
58
|
+
retryAfter;
|
|
59
|
+
constructor(body, retryAfter) {
|
|
60
|
+
super(429, body);
|
|
61
|
+
this.name = "RateLimitError";
|
|
62
|
+
this.retryAfter = retryAfter;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
exports.RateLimitError = RateLimitError;
|
|
66
|
+
class TimeoutError extends HappyRobotError {
|
|
67
|
+
constructor(timeoutMs) {
|
|
68
|
+
super(`Request timed out after ${timeoutMs}ms`);
|
|
69
|
+
this.name = "TimeoutError";
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
exports.TimeoutError = TimeoutError;
|
|
73
|
+
class NetworkError extends HappyRobotError {
|
|
74
|
+
cause;
|
|
75
|
+
constructor(message, cause) {
|
|
76
|
+
super(message);
|
|
77
|
+
this.name = "NetworkError";
|
|
78
|
+
this.cause = cause;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
exports.NetworkError = NetworkError;
|
|
82
|
+
//# sourceMappingURL=errors.js.map
|
package/core/errors.mjs
ADDED
package/core/http.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed HTTP client for the HappyRobot API.
|
|
3
|
+
* Uses native fetch with auth, retry (exponential backoff), and timeout.
|
|
4
|
+
*/
|
|
5
|
+
import type { ClientConfig, RequestConfig } from "./types";
|
|
6
|
+
export declare class HttpClient {
|
|
7
|
+
private readonly apiKey;
|
|
8
|
+
private readonly baseUrl;
|
|
9
|
+
private readonly timeout;
|
|
10
|
+
private readonly maxRetries;
|
|
11
|
+
private readonly fetchFn;
|
|
12
|
+
constructor(config: ClientConfig);
|
|
13
|
+
/**
|
|
14
|
+
* Perform a request and return the raw Response (for streaming endpoints).
|
|
15
|
+
* Applies auth and timeout but does NOT parse the body.
|
|
16
|
+
*/
|
|
17
|
+
requestRaw(config: RequestConfig): Promise<Response>;
|
|
18
|
+
request<T>(config: RequestConfig): Promise<T>;
|
|
19
|
+
private buildUrl;
|
|
20
|
+
private fetchWithTimeout;
|
|
21
|
+
private parseErrorBody;
|
|
22
|
+
private createApiError;
|
|
23
|
+
private isRetryable;
|
|
24
|
+
private getBackoff;
|
|
25
|
+
private sleep;
|
|
26
|
+
}
|
package/core/http.js
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Typed HTTP client for the HappyRobot API.
|
|
4
|
+
* Uses native fetch with auth, retry (exponential backoff), and timeout.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.HttpClient = void 0;
|
|
8
|
+
const errors_1 = require("./errors");
|
|
9
|
+
const DEFAULT_BASE_URL = "https://platform.happyrobot.ai/api/v2";
|
|
10
|
+
const DEFAULT_TIMEOUT = 30_000;
|
|
11
|
+
const DEFAULT_MAX_RETRIES = 2;
|
|
12
|
+
const INITIAL_BACKOFF_MS = 500;
|
|
13
|
+
class HttpClient {
|
|
14
|
+
apiKey;
|
|
15
|
+
baseUrl;
|
|
16
|
+
timeout;
|
|
17
|
+
maxRetries;
|
|
18
|
+
fetchFn;
|
|
19
|
+
constructor(config) {
|
|
20
|
+
if (!config.apiKey) {
|
|
21
|
+
throw new Error("apiKey is required");
|
|
22
|
+
}
|
|
23
|
+
this.apiKey = config.apiKey;
|
|
24
|
+
this.baseUrl = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
25
|
+
this.timeout = config.timeout ?? DEFAULT_TIMEOUT;
|
|
26
|
+
this.maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
27
|
+
this.fetchFn = config.fetch ?? globalThis.fetch.bind(globalThis);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Perform a request and return the raw Response (for streaming endpoints).
|
|
31
|
+
* Applies auth and timeout but does NOT parse the body.
|
|
32
|
+
*/
|
|
33
|
+
async requestRaw(config) {
|
|
34
|
+
const url = this.buildUrl(config.path, config.query);
|
|
35
|
+
const timeout = config.timeout ?? this.timeout;
|
|
36
|
+
const headers = {
|
|
37
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
38
|
+
Accept: "text/event-stream",
|
|
39
|
+
...config.headers,
|
|
40
|
+
};
|
|
41
|
+
const response = await this.fetchWithTimeout(url, { method: config.method, headers }, timeout);
|
|
42
|
+
if (!response.ok) {
|
|
43
|
+
const errorBody = await this.parseErrorBody(response);
|
|
44
|
+
throw this.createApiError(response.status, errorBody, response);
|
|
45
|
+
}
|
|
46
|
+
return response;
|
|
47
|
+
}
|
|
48
|
+
async request(config) {
|
|
49
|
+
const url = this.buildUrl(config.path, config.query);
|
|
50
|
+
const timeout = config.timeout ?? this.timeout;
|
|
51
|
+
const maxRetries = config.maxRetries ?? this.maxRetries;
|
|
52
|
+
const headers = {
|
|
53
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
54
|
+
Accept: "application/json",
|
|
55
|
+
...config.headers,
|
|
56
|
+
};
|
|
57
|
+
if (config.body !== undefined) {
|
|
58
|
+
headers["Content-Type"] = "application/json";
|
|
59
|
+
}
|
|
60
|
+
let lastError;
|
|
61
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
62
|
+
try {
|
|
63
|
+
const response = await this.fetchWithTimeout(url, {
|
|
64
|
+
method: config.method,
|
|
65
|
+
headers,
|
|
66
|
+
body: config.body !== undefined ? JSON.stringify(config.body) : undefined,
|
|
67
|
+
}, timeout);
|
|
68
|
+
if (response.ok) {
|
|
69
|
+
if (response.status === 204) {
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
const text = await response.text();
|
|
73
|
+
if (!text)
|
|
74
|
+
return undefined;
|
|
75
|
+
return JSON.parse(text);
|
|
76
|
+
}
|
|
77
|
+
const errorBody = await this.parseErrorBody(response);
|
|
78
|
+
const error = this.createApiError(response.status, errorBody, response);
|
|
79
|
+
// Only retry on 429 and 5xx
|
|
80
|
+
if (this.isRetryable(response.status) && attempt < maxRetries) {
|
|
81
|
+
lastError = error;
|
|
82
|
+
const backoff = this.getBackoff(attempt, response);
|
|
83
|
+
await this.sleep(backoff);
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
throw error;
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
if (err instanceof errors_1.ApiError)
|
|
90
|
+
throw err;
|
|
91
|
+
if (err instanceof errors_1.TimeoutError) {
|
|
92
|
+
if (attempt < maxRetries) {
|
|
93
|
+
lastError = err;
|
|
94
|
+
await this.sleep(this.getBackoff(attempt));
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
throw err;
|
|
98
|
+
}
|
|
99
|
+
// Network errors
|
|
100
|
+
if (attempt < maxRetries) {
|
|
101
|
+
lastError = err instanceof Error ? err : new Error(String(err));
|
|
102
|
+
await this.sleep(this.getBackoff(attempt));
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
throw new errors_1.NetworkError(err instanceof Error ? err.message : "Network request failed", err);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// Should not reach here, but just in case
|
|
109
|
+
throw lastError ?? new errors_1.NetworkError("Request failed after retries");
|
|
110
|
+
}
|
|
111
|
+
buildUrl(path, query) {
|
|
112
|
+
const url = new URL(`${this.baseUrl}${path}`);
|
|
113
|
+
if (query) {
|
|
114
|
+
for (const [key, value] of Object.entries(query)) {
|
|
115
|
+
if (value !== undefined) {
|
|
116
|
+
url.searchParams.set(key, String(value));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return url.toString();
|
|
121
|
+
}
|
|
122
|
+
async fetchWithTimeout(url, init, timeoutMs) {
|
|
123
|
+
const controller = new AbortController();
|
|
124
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
125
|
+
try {
|
|
126
|
+
return await this.fetchFn(url, { ...init, signal: controller.signal });
|
|
127
|
+
}
|
|
128
|
+
catch (err) {
|
|
129
|
+
if (err instanceof DOMException && err.name === "AbortError") {
|
|
130
|
+
throw new errors_1.TimeoutError(timeoutMs);
|
|
131
|
+
}
|
|
132
|
+
throw err;
|
|
133
|
+
}
|
|
134
|
+
finally {
|
|
135
|
+
clearTimeout(timer);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
async parseErrorBody(response) {
|
|
139
|
+
try {
|
|
140
|
+
const text = await response.text();
|
|
141
|
+
if (!text)
|
|
142
|
+
return {};
|
|
143
|
+
return JSON.parse(text);
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
return {};
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
createApiError(status, body, response) {
|
|
150
|
+
switch (status) {
|
|
151
|
+
case 401:
|
|
152
|
+
return new errors_1.AuthenticationError(body);
|
|
153
|
+
case 404:
|
|
154
|
+
return new errors_1.NotFoundError(body);
|
|
155
|
+
case 400:
|
|
156
|
+
case 422:
|
|
157
|
+
return new errors_1.ValidationError(status, body);
|
|
158
|
+
case 429: {
|
|
159
|
+
const retryAfter = response.headers.get("retry-after");
|
|
160
|
+
return new errors_1.RateLimitError(body, retryAfter ? parseInt(retryAfter, 10) : null);
|
|
161
|
+
}
|
|
162
|
+
default:
|
|
163
|
+
return new errors_1.ApiError(status, body);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
isRetryable(status) {
|
|
167
|
+
return status === 429 || status >= 500;
|
|
168
|
+
}
|
|
169
|
+
getBackoff(attempt, response) {
|
|
170
|
+
// Use Retry-After header for 429 if available
|
|
171
|
+
if (response?.status === 429) {
|
|
172
|
+
const retryAfter = response.headers.get("retry-after");
|
|
173
|
+
if (retryAfter) {
|
|
174
|
+
const seconds = parseInt(retryAfter, 10);
|
|
175
|
+
if (!isNaN(seconds))
|
|
176
|
+
return seconds * 1000;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
// Exponential backoff with jitter
|
|
180
|
+
const base = INITIAL_BACKOFF_MS * Math.pow(2, attempt);
|
|
181
|
+
const jitter = Math.random() * base * 0.1;
|
|
182
|
+
return base + jitter;
|
|
183
|
+
}
|
|
184
|
+
sleep(ms) {
|
|
185
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
exports.HttpClient = HttpClient;
|
|
189
|
+
//# sourceMappingURL=http.js.map
|
package/core/http.mjs
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pagination utilities for the HappyRobot SDK.
|
|
3
|
+
* Provides an async iterator that auto-paginates through all pages.
|
|
4
|
+
*/
|
|
5
|
+
import type { HttpClient } from "./http";
|
|
6
|
+
import type { PaginationQuery } from "./types";
|
|
7
|
+
export interface PaginateOptions extends PaginationQuery {
|
|
8
|
+
/** Additional query parameters to include in each request. */
|
|
9
|
+
[key: string]: string | number | boolean | undefined;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Returns an async iterable that automatically fetches all pages of a
|
|
13
|
+
* paginated endpoint and yields individual items.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* for await (const workflow of paginate<Workflow>(http, "/workflows", { page_size: 50 })) {
|
|
18
|
+
* console.log(workflow.name);
|
|
19
|
+
* }
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export declare function paginate<T>(http: HttpClient, path: string, options?: PaginateOptions): AsyncGenerator<T, void, undefined>;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Pagination utilities for the HappyRobot SDK.
|
|
4
|
+
* Provides an async iterator that auto-paginates through all pages.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.paginate = paginate;
|
|
8
|
+
/**
|
|
9
|
+
* Returns an async iterable that automatically fetches all pages of a
|
|
10
|
+
* paginated endpoint and yields individual items.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* for await (const workflow of paginate<Workflow>(http, "/workflows", { page_size: 50 })) {
|
|
15
|
+
* console.log(workflow.name);
|
|
16
|
+
* }
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
async function* paginate(http, path, options = {}) {
|
|
20
|
+
const { page: startPage = 1, page_size = 50, sort, ...rest } = options;
|
|
21
|
+
let currentPage = startPage;
|
|
22
|
+
while (true) {
|
|
23
|
+
const query = {
|
|
24
|
+
page: currentPage,
|
|
25
|
+
page_size,
|
|
26
|
+
sort,
|
|
27
|
+
...rest,
|
|
28
|
+
};
|
|
29
|
+
const response = await http.request({
|
|
30
|
+
method: "GET",
|
|
31
|
+
path,
|
|
32
|
+
query,
|
|
33
|
+
});
|
|
34
|
+
for (const item of response.data) {
|
|
35
|
+
yield item;
|
|
36
|
+
}
|
|
37
|
+
if (!response.pagination.has_next_page) {
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
currentPage++;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=pagination.js.map
|
package/core/sse.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lightweight SSE (Server-Sent Events) stream parser.
|
|
3
|
+
*
|
|
4
|
+
* Consumes a `Response` body and yields typed `SSEEvent` objects.
|
|
5
|
+
*/
|
|
6
|
+
export interface SSEEvent<T = unknown> {
|
|
7
|
+
/** The SSE event name (e.g. "message", "connected", "session_ended"). */
|
|
8
|
+
event: string;
|
|
9
|
+
/** Parsed JSON payload. */
|
|
10
|
+
data: T;
|
|
11
|
+
/** Optional SSE `id` field. */
|
|
12
|
+
id?: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Async generator that reads an SSE stream from a `Response` and yields
|
|
16
|
+
* parsed events. Comments and empty keep-alive lines are silently skipped.
|
|
17
|
+
*
|
|
18
|
+
* @param response - A fetch `Response` whose body is `text/event-stream`.
|
|
19
|
+
*/
|
|
20
|
+
export declare function iterateSSE<T = unknown>(response: Response): AsyncGenerator<SSEEvent<T>, void, undefined>;
|