@amigo-ai/platform-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.
Files changed (107) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +330 -0
  3. package/dist/core/auth.js +32 -0
  4. package/dist/core/auth.js.map +1 -0
  5. package/dist/core/branded-types.js +22 -0
  6. package/dist/core/branded-types.js.map +1 -0
  7. package/dist/core/errors.js +168 -0
  8. package/dist/core/errors.js.map +1 -0
  9. package/dist/core/openapi-client.js +66 -0
  10. package/dist/core/openapi-client.js.map +1 -0
  11. package/dist/core/retry.js +48 -0
  12. package/dist/core/retry.js.map +1 -0
  13. package/dist/core/utils.js +35 -0
  14. package/dist/core/utils.js.map +1 -0
  15. package/dist/index.cjs +1005 -0
  16. package/dist/index.cjs.map +7 -0
  17. package/dist/index.js +111 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/index.mjs +982 -0
  20. package/dist/index.mjs.map +7 -0
  21. package/dist/resources/agents.js +49 -0
  22. package/dist/resources/agents.js.map +1 -0
  23. package/dist/resources/analytics.js +54 -0
  24. package/dist/resources/analytics.js.map +1 -0
  25. package/dist/resources/api-keys.js +45 -0
  26. package/dist/resources/api-keys.js.map +1 -0
  27. package/dist/resources/base.js +50 -0
  28. package/dist/resources/base.js.map +1 -0
  29. package/dist/resources/billing.js +15 -0
  30. package/dist/resources/billing.js.map +1 -0
  31. package/dist/resources/calls.js +28 -0
  32. package/dist/resources/calls.js.map +1 -0
  33. package/dist/resources/context-graphs.js +44 -0
  34. package/dist/resources/context-graphs.js.map +1 -0
  35. package/dist/resources/data-sources.js +29 -0
  36. package/dist/resources/data-sources.js.map +1 -0
  37. package/dist/resources/integrations.js +45 -0
  38. package/dist/resources/integrations.js.map +1 -0
  39. package/dist/resources/memory.js +31 -0
  40. package/dist/resources/memory.js.map +1 -0
  41. package/dist/resources/phone-numbers.js +38 -0
  42. package/dist/resources/phone-numbers.js.map +1 -0
  43. package/dist/resources/services.js +30 -0
  44. package/dist/resources/services.js.map +1 -0
  45. package/dist/resources/settings.js +47 -0
  46. package/dist/resources/settings.js.map +1 -0
  47. package/dist/resources/simulations.js +50 -0
  48. package/dist/resources/simulations.js.map +1 -0
  49. package/dist/resources/skills.js +44 -0
  50. package/dist/resources/skills.js.map +1 -0
  51. package/dist/resources/workspaces.js +57 -0
  52. package/dist/resources/workspaces.js.map +1 -0
  53. package/dist/resources/world.js +131 -0
  54. package/dist/resources/world.js.map +1 -0
  55. package/dist/types/api.js +12 -0
  56. package/dist/types/api.js.map +1 -0
  57. package/dist/types/core/auth.d.ts +20 -0
  58. package/dist/types/core/auth.d.ts.map +1 -0
  59. package/dist/types/core/branded-types.d.ts +50 -0
  60. package/dist/types/core/branded-types.d.ts.map +1 -0
  61. package/dist/types/core/errors.d.ts +76 -0
  62. package/dist/types/core/errors.d.ts.map +1 -0
  63. package/dist/types/core/openapi-client.d.ts +14 -0
  64. package/dist/types/core/openapi-client.d.ts.map +1 -0
  65. package/dist/types/core/retry.d.ts +21 -0
  66. package/dist/types/core/retry.d.ts.map +1 -0
  67. package/dist/types/core/utils.d.ts +39 -0
  68. package/dist/types/core/utils.d.ts.map +1 -0
  69. package/dist/types/index.d.ts +114 -0
  70. package/dist/types/index.d.ts.map +1 -0
  71. package/dist/types/resources/agents.d.ts +32 -0
  72. package/dist/types/resources/agents.d.ts.map +1 -0
  73. package/dist/types/resources/analytics.d.ts +146 -0
  74. package/dist/types/resources/analytics.d.ts.map +1 -0
  75. package/dist/types/resources/api-keys.d.ts +28 -0
  76. package/dist/types/resources/api-keys.d.ts.map +1 -0
  77. package/dist/types/resources/base.d.ts +18 -0
  78. package/dist/types/resources/base.d.ts.map +1 -0
  79. package/dist/types/resources/billing.d.ts +19 -0
  80. package/dist/types/resources/billing.d.ts.map +1 -0
  81. package/dist/types/resources/calls.d.ts +50 -0
  82. package/dist/types/resources/calls.d.ts.map +1 -0
  83. package/dist/types/resources/context-graphs.d.ts +32 -0
  84. package/dist/types/resources/context-graphs.d.ts.map +1 -0
  85. package/dist/types/resources/data-sources.d.ts +24 -0
  86. package/dist/types/resources/data-sources.d.ts.map +1 -0
  87. package/dist/types/resources/integrations.d.ts +38 -0
  88. package/dist/types/resources/integrations.d.ts.map +1 -0
  89. package/dist/types/resources/memory.d.ts +99 -0
  90. package/dist/types/resources/memory.d.ts.map +1 -0
  91. package/dist/types/resources/phone-numbers.d.ts +26 -0
  92. package/dist/types/resources/phone-numbers.d.ts.map +1 -0
  93. package/dist/types/resources/services.d.ts +21 -0
  94. package/dist/types/resources/services.d.ts.map +1 -0
  95. package/dist/types/resources/settings.d.ts +102 -0
  96. package/dist/types/resources/settings.d.ts.map +1 -0
  97. package/dist/types/resources/simulations.d.ts +39 -0
  98. package/dist/types/resources/simulations.d.ts.map +1 -0
  99. package/dist/types/resources/skills.d.ts +31 -0
  100. package/dist/types/resources/skills.d.ts.map +1 -0
  101. package/dist/types/resources/workspaces.d.ts +28 -0
  102. package/dist/types/resources/workspaces.d.ts.map +1 -0
  103. package/dist/types/resources/world.d.ts +177 -0
  104. package/dist/types/resources/world.d.ts.map +1 -0
  105. package/dist/types/types/api.d.ts +739 -0
  106. package/dist/types/types/api.d.ts.map +1 -0
  107. package/package.json +82 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Amigo AI
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,330 @@
1
+ # @amigo-ai/platform-sdk
2
+
3
+ Official TypeScript SDK for the [Amigo Platform API](https://api.platform.amigo.ai/v1/docs).
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @amigo-ai/platform-sdk
9
+ ```
10
+
11
+ ## Quick start
12
+
13
+ ```typescript
14
+ import { AmigoClient } from '@amigo-ai/platform-sdk'
15
+
16
+ const client = new AmigoClient({
17
+ apiKey: 'your-api-key',
18
+ workspaceId: 'your-workspace-id',
19
+ })
20
+
21
+ // List agents
22
+ const { items: agents } = await client.agents.list()
23
+
24
+ // Emit a world event
25
+ await client.world.emitEvent({
26
+ entity_id: 'entity-id',
27
+ event_type: 'appointment_scheduled',
28
+ data: { appointment_id: 'appt-001' },
29
+ })
30
+
31
+ // Get call analytics for the last 30 days
32
+ const stats = await client.analytics.getCalls({ period: '30d' })
33
+ console.log(stats.total_calls, stats.avg_duration_seconds)
34
+ ```
35
+
36
+ ## Configuration
37
+
38
+ | Option | Type | Required | Description |
39
+ |--------|------|----------|-------------|
40
+ | `apiKey` | `string` | Yes | Your Platform API key — create one at Workspace Settings > API Keys |
41
+ | `workspaceId` | `string` | Yes | Your workspace ID — all resource operations are scoped to this |
42
+ | `baseUrl` | `string` | No | Override the API base URL (default: `https://api.platform.amigo.ai`) |
43
+ | `retry` | `RetryOptions` | No | Retry configuration for transient failures |
44
+
45
+ ### Retry options
46
+
47
+ ```typescript
48
+ const client = new AmigoClient({
49
+ apiKey: 'your-key',
50
+ workspaceId: 'your-workspace-id',
51
+ retry: {
52
+ maxAttempts: 3, // Total attempts including first. Default: 3
53
+ baseDelayMs: 250, // Base delay for exponential backoff. Default: 250
54
+ maxDelayMs: 30000, // Cap on delay. Default: 30_000
55
+ },
56
+ })
57
+ ```
58
+
59
+ GET requests are retried on 408, 429, 500, 502, 503, 504. POST requests are only retried on 429 with a `Retry-After` header. Backoff uses full jitter.
60
+
61
+ ## Resources
62
+
63
+ ### Agents
64
+
65
+ ```typescript
66
+ // Create an agent
67
+ const agent = await client.agents.create({
68
+ name: 'Patient Intake Agent',
69
+ description: 'Handles inbound scheduling calls',
70
+ })
71
+
72
+ // Create a version (the versioned config object)
73
+ const version = await client.agents.createVersion(agent.id, {
74
+ name: 'v1',
75
+ identity: {
76
+ name: 'Alex',
77
+ role: 'Scheduling Coordinator',
78
+ developed_by: 'Acme Health',
79
+ default_spoken_language: 'en',
80
+ relationship_to_developer: {
81
+ ownership: 'Acme Health',
82
+ type: 'assistant',
83
+ conversation_visibility: 'public',
84
+ thought_visibility: 'private',
85
+ },
86
+ },
87
+ })
88
+
89
+ // Get the latest version
90
+ const latest = await client.agents.getVersion(agent.id, 'latest')
91
+
92
+ const { items: agents } = await client.agents.list({ search: 'intake' })
93
+ ```
94
+
95
+ ### Skills
96
+
97
+ ```typescript
98
+ const skill = await client.skills.create({
99
+ slug: 'schedule-appointment',
100
+ name: 'Schedule Appointment',
101
+ description: 'Books appointments in the EHR system',
102
+ input_schema: {
103
+ type: 'object',
104
+ properties: {
105
+ patient_id: { type: 'string' },
106
+ appointment_type: { type: 'string' },
107
+ },
108
+ required: ['patient_id', 'appointment_type'],
109
+ },
110
+ execution_tier: 'orchestrated',
111
+ })
112
+
113
+ // Test with a sample input
114
+ const result = await client.skills.test(skill.id, {
115
+ input: { patient_id: 'MRN-001', appointment_type: 'follow-up' },
116
+ })
117
+ console.log(result.success, result.output)
118
+ ```
119
+
120
+ ### Services
121
+
122
+ Services wire together an agent + context graph + phone channel.
123
+
124
+ ```typescript
125
+ const { items: services } = await client.services.list()
126
+ const service = await client.services.get('service-id')
127
+ console.log(service.agent_name, service.channel_type, service.version_sets)
128
+ ```
129
+
130
+ ### World Model
131
+
132
+ The world model tracks entities (patients, contacts, appointments) and the events that flow through them.
133
+
134
+ ```typescript
135
+ // Create an entity
136
+ const patient = await client.world.createEntity({
137
+ entity_type: 'patient',
138
+ canonical_id: 'MRN-12345',
139
+ display_name: 'Jane Doe',
140
+ })
141
+
142
+ // Emit an event
143
+ await client.world.emitEvent({
144
+ entity_id: patient.id,
145
+ event_type: 'call_completed',
146
+ data: { duration_seconds: 180, outcome: 'appointment_scheduled' },
147
+ })
148
+
149
+ // Query timeline
150
+ const timeline = await client.world.getTimeline(patient.id)
151
+
152
+ // Search entities
153
+ const results = await client.world.search('Jane Doe', { entity_type: 'patient' })
154
+
155
+ // View sync status from connectors
156
+ const syncStatus = await client.world.getSyncStatusBySink()
157
+ ```
158
+
159
+ ### Calls
160
+
161
+ Calls are read-only — they are created by the voice pipeline.
162
+
163
+ ```typescript
164
+ const { items: calls } = await client.calls.list({
165
+ direction: 'inbound',
166
+ service_id: 'service-id',
167
+ })
168
+
169
+ // Get full detail with transcript and intelligence
170
+ const detail = await client.calls.get(calls[0].call_sid)
171
+ console.log(detail.intelligence?.summary)
172
+ console.log(detail.transcript)
173
+
174
+ // Analytics benchmarks
175
+ const benchmarks = await client.calls.getBenchmarks({ days: 30 })
176
+ ```
177
+
178
+ ### Analytics
179
+
180
+ ```typescript
181
+ // Dashboard KPIs with period-over-period deltas
182
+ const dashboard = await client.analytics.getDashboard({ days: 7 })
183
+ console.log(dashboard.call_volume.value, dashboard.call_volume.delta_pct)
184
+ console.log(dashboard.avg_quality.value)
185
+
186
+ // Call volume time series
187
+ const calls = await client.analytics.getCalls({ period: '30d' })
188
+ console.log(calls.total_calls, calls.calls_by_date)
189
+
190
+ // Per-agent performance
191
+ const { agents } = await client.analytics.getAgents({ period: '7d' })
192
+
193
+ // Compare two periods
194
+ const comparison = await client.analytics.compareCallPeriods({
195
+ current_from: '2026-04-01',
196
+ current_to: '2026-04-15',
197
+ previous_from: '2026-03-15',
198
+ previous_to: '2026-03-31',
199
+ })
200
+ ```
201
+
202
+ ### Agent Memory
203
+
204
+ Agent Memory tracks structured long-term facts about entities across conversations.
205
+
206
+ ```typescript
207
+ // Get all dimension scores for an entity
208
+ const dims = await client.memory.getEntityDimensions('entity-id')
209
+ console.log(dims.dimensions) // preferences, health_history, etc.
210
+
211
+ // Get individual facts for a dimension
212
+ const facts = await client.memory.getEntityFacts('entity-id', { dimension: 'preferences' })
213
+
214
+ // Workspace-level memory health
215
+ const analytics = await client.memory.getAnalytics()
216
+ console.log(analytics.coverage_rate, analytics.total_facts)
217
+ ```
218
+
219
+ ### Integrations
220
+
221
+ ```typescript
222
+ const { items: integrations } = await client.integrations.list({ enabled: true })
223
+
224
+ // Test a specific endpoint
225
+ const result = await client.integrations.testEndpoint(
226
+ 'integration-id',
227
+ 'geocode',
228
+ { textQuery: '123 Main St, Springfield' },
229
+ )
230
+ ```
231
+
232
+ ### Data Sources
233
+
234
+ ```typescript
235
+ const { items: sources } = await client.dataSources.list()
236
+ const source = await client.dataSources.get('source-id')
237
+ console.log(source.source_type, source.health_status, source.last_sync_at)
238
+ ```
239
+
240
+ ### Settings
241
+
242
+ ```typescript
243
+ // Voice
244
+ const voice = await client.settings.voice.get()
245
+ await client.settings.voice.update({ voice_id: 'new-voice-id', speed: 1.1 })
246
+
247
+ // Retention
248
+ const retention = await client.settings.retention.get()
249
+ await client.settings.retention.update({ call_recordings_days: 90 })
250
+
251
+ // Memory dimensions
252
+ const memory = await client.settings.memory.get()
253
+ console.log(memory.dimensions) // list of configured memory dimensions
254
+ ```
255
+
256
+ ### Billing
257
+
258
+ ```typescript
259
+ const usage = await client.billing.getUsage()
260
+ console.log(usage.meters, usage.total_events)
261
+
262
+ const { items: invoices } = await client.billing.listInvoices()
263
+ ```
264
+
265
+ ## Pagination
266
+
267
+ All list methods return `{ items, has_more, continuation_token }`. Use the `paginate` utility to iterate all pages automatically:
268
+
269
+ ```typescript
270
+ import { AmigoClient, paginate } from '@amigo-ai/platform-sdk'
271
+
272
+ for await (const entity of paginate((token) =>
273
+ client.world.listEntities({ continuation_token: token, limit: 100 }),
274
+ )) {
275
+ // process entity
276
+ }
277
+ ```
278
+
279
+ ## Error handling
280
+
281
+ All SDK errors extend `AmigoError`. Use type guards for specific handling:
282
+
283
+ ```typescript
284
+ import {
285
+ AmigoClient,
286
+ AmigoError,
287
+ isNotFoundError,
288
+ isRateLimitError,
289
+ isAuthenticationError,
290
+ } from '@amigo-ai/platform-sdk'
291
+
292
+ try {
293
+ await client.agents.get('agent-id')
294
+ } catch (err) {
295
+ if (isNotFoundError(err)) {
296
+ console.log('Agent not found')
297
+ } else if (isRateLimitError(err)) {
298
+ console.log('Rate limited, retry after:', err.retryAfter, 'seconds')
299
+ } else if (isAuthenticationError(err)) {
300
+ console.log('Invalid API key')
301
+ } else if (err instanceof AmigoError) {
302
+ console.log('API error:', err.message, err.errorCode, err.requestId)
303
+ }
304
+ }
305
+ ```
306
+
307
+ ### Error classes
308
+
309
+ | Class | HTTP Status | Description |
310
+ |-------|-------------|-------------|
311
+ | `BadRequestError` | 400 | Malformed request |
312
+ | `AuthenticationError` | 401 | Invalid or expired API key |
313
+ | `PermissionError` | 403 | Insufficient permissions |
314
+ | `NotFoundError` | 404 | Resource does not exist |
315
+ | `ConflictError` | 409 | Duplicate slug or version conflict |
316
+ | `ValidationError` | 422 | Request body validation failure |
317
+ | `RateLimitError` | 429 | Too many requests — check `.retryAfter` |
318
+ | `ServerError` | 5xx | Server-side error |
319
+ | `ConfigurationError` | — | SDK misconfiguration at init time |
320
+ | `NetworkError` | — | Fetch/network failure |
321
+
322
+ ## CommonJS (CJS) usage
323
+
324
+ ```javascript
325
+ const { AmigoClient } = require('@amigo-ai/platform-sdk')
326
+ ```
327
+
328
+ ## License
329
+
330
+ MIT
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Auth middleware for the Amigo Platform SDK.
3
+ *
4
+ * The platform-api accepts Bearer tokens in two forms:
5
+ * 1. RS256 JWT issued by the Identity service
6
+ * 2. Legacy API keys (created via POST /v1/{workspace_id}/api-keys)
7
+ *
8
+ * This SDK accepts an API key string and attaches it directly as
9
+ * `Authorization: Bearer {apiKey}`. No token exchange is required.
10
+ */
11
+ import { AuthenticationError } from './errors.js';
12
+ /**
13
+ * Creates openapi-fetch middleware that attaches the Bearer token
14
+ * to every outgoing request and converts 401 responses to AuthenticationError.
15
+ */
16
+ export function createAuthMiddleware(config) {
17
+ return {
18
+ async onRequest({ request }) {
19
+ request.headers.set('Authorization', `Bearer ${config.apiKey}`);
20
+ return request;
21
+ },
22
+ async onResponse({ response }) {
23
+ if (response.status === 401) {
24
+ throw new AuthenticationError('Invalid or expired API key. Check your credentials.', {
25
+ statusCode: 401,
26
+ });
27
+ }
28
+ return response;
29
+ },
30
+ };
31
+ }
32
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/core/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAMjD;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAkB;IACrD,OAAO;QACL,KAAK,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE;YACzB,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,UAAU,MAAM,CAAC,MAAM,EAAE,CAAC,CAAA;YAC/D,OAAO,OAAO,CAAA;QAChB,CAAC;QAED,KAAK,CAAC,UAAU,CAAC,EAAE,QAAQ,EAAE;YAC3B,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBAC5B,MAAM,IAAI,mBAAmB,CAAC,qDAAqD,EAAE;oBACnF,UAAU,EAAE,GAAG;iBAChB,CAAC,CAAA;YACJ,CAAC;YACD,OAAO,QAAQ,CAAA;QACjB,CAAC;KACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,22 @@
1
+ // --- Constructors ---
2
+ export const workspaceId = (id) => id;
3
+ export const apiKeyId = (id) => id;
4
+ export const agentId = (id) => id;
5
+ export const personaId = (id) => id;
6
+ export const skillId = (id) => id;
7
+ export const serviceId = (id) => id;
8
+ export const contextGraphId = (id) => id;
9
+ export const callId = (id) => id;
10
+ export const phoneNumberId = (id) => id;
11
+ export const integrationId = (id) => id;
12
+ export const entityId = (id) => id;
13
+ export const eventId = (id) => id;
14
+ export const surfaceId = (id) => id;
15
+ export const operatorId = (id) => id;
16
+ export const triggerId = (id) => id;
17
+ export const simulationRunId = (id) => id;
18
+ export const simulationSessionId = (id) => id;
19
+ export const scribeSessionId = (id) => id;
20
+ export const functionId = (id) => id;
21
+ export const dataSourceId = (id) => id;
22
+ //# sourceMappingURL=branded-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branded-types.js","sourceRoot":"","sources":["../../src/core/branded-types.ts"],"names":[],"mappings":"AA8BA,uBAAuB;AACvB,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,EAAU,EAAe,EAAE,CAAC,EAAiB,CAAA;AACzE,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,EAAU,EAAY,EAAE,CAAC,EAAc,CAAA;AAChE,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,EAAU,EAAW,EAAE,CAAC,EAAa,CAAA;AAC7D,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,EAAU,EAAa,EAAE,CAAC,EAAe,CAAA;AACnE,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,EAAU,EAAW,EAAE,CAAC,EAAa,CAAA;AAC7D,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,EAAU,EAAa,EAAE,CAAC,EAAe,CAAA;AACnE,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,EAAU,EAAkB,EAAE,CAAC,EAAoB,CAAA;AAClF,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,EAAU,EAAU,EAAE,CAAC,EAAY,CAAA;AAC1D,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,EAAU,EAAiB,EAAE,CAAC,EAAmB,CAAA;AAC/E,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,EAAU,EAAiB,EAAE,CAAC,EAAmB,CAAA;AAC/E,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,EAAU,EAAY,EAAE,CAAC,EAAc,CAAA;AAChE,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,EAAU,EAAW,EAAE,CAAC,EAAa,CAAA;AAC7D,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,EAAU,EAAa,EAAE,CAAC,EAAe,CAAA;AACnE,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,EAAU,EAAc,EAAE,CAAC,EAAgB,CAAA;AACtE,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,EAAU,EAAa,EAAE,CAAC,EAAe,CAAA;AACnE,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,EAAU,EAAmB,EAAE,CAAC,EAAqB,CAAA;AACrF,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,EAAU,EAAuB,EAAE,CAAC,EAAyB,CAAA;AACjG,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,EAAU,EAAmB,EAAE,CAAC,EAAqB,CAAA;AACrF,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,EAAU,EAAc,EAAE,CAAC,EAAgB,CAAA;AACtE,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,EAAU,EAAgB,EAAE,CAAC,EAAkB,CAAA"}
@@ -0,0 +1,168 @@
1
+ /**
2
+ * Error hierarchy for the Amigo Platform SDK.
3
+ * All errors extend AmigoError which can be caught with a single catch.
4
+ */
5
+ /** Base class for all Amigo Platform SDK errors */
6
+ export class AmigoError extends Error {
7
+ statusCode;
8
+ errorCode;
9
+ requestId;
10
+ detail;
11
+ constructor(message, ctx = {}) {
12
+ super(message);
13
+ this.name = this.constructor.name;
14
+ this.statusCode = ctx.statusCode;
15
+ this.errorCode = ctx.errorCode;
16
+ this.requestId = ctx.requestId;
17
+ this.detail = ctx.detail;
18
+ // Maintain proper prototype chain
19
+ Object.setPrototypeOf(this, new.target.prototype);
20
+ }
21
+ }
22
+ /** 400 Bad Request */
23
+ export class BadRequestError extends AmigoError {
24
+ constructor(message, ctx = {}) {
25
+ super(message, { ...ctx, statusCode: 400 });
26
+ }
27
+ }
28
+ /** 401 Unauthorized — invalid or missing API key */
29
+ export class AuthenticationError extends AmigoError {
30
+ constructor(message, ctx = {}) {
31
+ super(message, { ...ctx, statusCode: 401 });
32
+ }
33
+ }
34
+ /** 403 Forbidden — insufficient permissions */
35
+ export class PermissionError extends AmigoError {
36
+ constructor(message, ctx = {}) {
37
+ super(message, { ...ctx, statusCode: 403 });
38
+ }
39
+ }
40
+ /** 404 Not Found */
41
+ export class NotFoundError extends AmigoError {
42
+ constructor(message, ctx = {}) {
43
+ super(message, { ...ctx, statusCode: 404 });
44
+ }
45
+ }
46
+ /** 409 Conflict — duplicate slug or resource version conflict */
47
+ export class ConflictError extends AmigoError {
48
+ constructor(message, ctx = {}) {
49
+ super(message, { ...ctx, statusCode: 409 });
50
+ }
51
+ }
52
+ /** 422 Unprocessable Entity — validation failure */
53
+ export class ValidationError extends AmigoError {
54
+ constructor(message, ctx = {}) {
55
+ super(message, { ...ctx, statusCode: 422 });
56
+ }
57
+ }
58
+ /** 429 Too Many Requests */
59
+ export class RateLimitError extends AmigoError {
60
+ retryAfter;
61
+ constructor(message, ctx = {}) {
62
+ super(message, { ...ctx, statusCode: 429 });
63
+ this.retryAfter = ctx.retryAfter;
64
+ }
65
+ }
66
+ /** 5xx Server Error */
67
+ export class ServerError extends AmigoError {
68
+ constructor(message, ctx = {}) {
69
+ super(message, { ...ctx, statusCode: ctx.statusCode ?? 500 });
70
+ }
71
+ }
72
+ /** 503 Service Unavailable */
73
+ export class ServiceUnavailableError extends ServerError {
74
+ constructor(message, ctx = {}) {
75
+ super(message, { ...ctx, statusCode: 503 });
76
+ }
77
+ }
78
+ /** Network or fetch failure (no HTTP status available) */
79
+ export class NetworkError extends AmigoError {
80
+ constructor(message, cause) {
81
+ super(message);
82
+ if (cause !== undefined) {
83
+ ;
84
+ this.cause = cause;
85
+ }
86
+ }
87
+ }
88
+ /** Failed to parse response body */
89
+ export class ParseError extends AmigoError {
90
+ body;
91
+ constructor(message, body) {
92
+ super(message);
93
+ this.body = body;
94
+ }
95
+ }
96
+ /** SDK misconfiguration */
97
+ export class ConfigurationError extends AmigoError {
98
+ constructor(message) {
99
+ super(message);
100
+ }
101
+ }
102
+ export async function createApiError(response) {
103
+ let body = {};
104
+ let rawBody;
105
+ try {
106
+ rawBody = await response.text();
107
+ body = JSON.parse(rawBody);
108
+ }
109
+ catch {
110
+ // ignore parse failure
111
+ }
112
+ const ctx = {
113
+ statusCode: response.status,
114
+ errorCode: body.error_code,
115
+ requestId: body.request_id,
116
+ detail: body.detail,
117
+ };
118
+ const message = body.message ?? body.detail ?? response.statusText ?? `HTTP ${response.status}`;
119
+ switch (response.status) {
120
+ case 400:
121
+ return new BadRequestError(message, ctx);
122
+ case 401:
123
+ return new AuthenticationError(message, ctx);
124
+ case 403:
125
+ return new PermissionError(message, ctx);
126
+ case 404:
127
+ return new NotFoundError(message, ctx);
128
+ case 409:
129
+ return new ConflictError(message, ctx);
130
+ case 422:
131
+ return new ValidationError(message, ctx);
132
+ case 429: {
133
+ const retryAfter = parseRetryAfter(response);
134
+ return new RateLimitError(message, { ...ctx, retryAfter });
135
+ }
136
+ case 503:
137
+ return new ServiceUnavailableError(message, ctx);
138
+ default:
139
+ return new ServerError(message, ctx);
140
+ }
141
+ }
142
+ function parseRetryAfter(response) {
143
+ const header = response.headers.get('Retry-After');
144
+ if (!header)
145
+ return undefined;
146
+ const seconds = Number(header);
147
+ if (!isNaN(seconds))
148
+ return seconds;
149
+ const date = new Date(header);
150
+ if (!isNaN(date.getTime())) {
151
+ return Math.max(0, Math.ceil((date.getTime() - Date.now()) / 1000));
152
+ }
153
+ return undefined;
154
+ }
155
+ // --- Type guards ---
156
+ export function isAmigoError(err) {
157
+ return err instanceof AmigoError;
158
+ }
159
+ export function isNotFoundError(err) {
160
+ return err instanceof NotFoundError;
161
+ }
162
+ export function isRateLimitError(err) {
163
+ return err instanceof RateLimitError;
164
+ }
165
+ export function isAuthenticationError(err) {
166
+ return err instanceof AuthenticationError;
167
+ }
168
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Creates a configured openapi-fetch client with auth, error handling, and retry middleware.
3
+ */
4
+ import createClient from 'openapi-fetch';
5
+ import { createAuthMiddleware } from './auth.js';
6
+ import { createApiError } from './errors.js';
7
+ import { shouldRetry, computeDelay, resolveRetryOptions } from './retry.js';
8
+ export function createAmigoClient(config) {
9
+ const retryOptions = resolveRetryOptions(config.retry);
10
+ const client = createClient({ baseUrl: config.baseUrl });
11
+ // Auth middleware — attaches Bearer token and converts 401
12
+ client.use(createAuthMiddleware({ apiKey: config.apiKey }));
13
+ // Error middleware — converts HTTP error responses to typed errors
14
+ const errorMiddleware = {
15
+ async onResponse({ response }) {
16
+ if (response.status >= 400) {
17
+ throw await createApiError(response);
18
+ }
19
+ return response;
20
+ },
21
+ };
22
+ client.use(errorMiddleware);
23
+ // Retry middleware — exponential backoff with jitter
24
+ const retryMiddleware = {
25
+ async onRequest({ request, schemaPath }) {
26
+ // Store method for use in onResponse
27
+ ;
28
+ request._method =
29
+ request.method.toUpperCase();
30
+ void schemaPath;
31
+ return request;
32
+ },
33
+ async onResponse({ request, response }) {
34
+ const method = request._method ?? request.method.toUpperCase();
35
+ let attempt = 0;
36
+ let currentResponse = response;
37
+ while (shouldRetry({
38
+ method,
39
+ attempt,
40
+ response: currentResponse,
41
+ options: retryOptions,
42
+ })) {
43
+ const delayMs = computeDelay(attempt, currentResponse, retryOptions);
44
+ await sleep(delayMs);
45
+ attempt++;
46
+ try {
47
+ const retried = await fetch(request.clone());
48
+ currentResponse = retried;
49
+ if (currentResponse.status < 400)
50
+ return currentResponse;
51
+ }
52
+ catch {
53
+ // Network error on retry — fall through to throw original
54
+ break;
55
+ }
56
+ }
57
+ return currentResponse;
58
+ },
59
+ };
60
+ client.use(retryMiddleware);
61
+ return client;
62
+ }
63
+ function sleep(ms) {
64
+ return new Promise((resolve) => setTimeout(resolve, ms));
65
+ }
66
+ //# sourceMappingURL=openapi-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openapi-client.js","sourceRoot":"","sources":["../../src/core/openapi-client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,YAAiC,MAAM,eAAe,CAAA;AAE7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAA;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAC5C,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,mBAAmB,EAAqB,MAAM,YAAY,CAAA;AAU9F,MAAM,UAAU,iBAAiB,CAAC,MAAoB;IACpD,MAAM,YAAY,GAAG,mBAAmB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IAEtD,MAAM,MAAM,GAAG,YAAY,CAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAA;IAE/D,2DAA2D;IAC3D,MAAM,CAAC,GAAG,CAAC,oBAAoB,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;IAE3D,mEAAmE;IACnE,MAAM,eAAe,GAAe;QAClC,KAAK,CAAC,UAAU,CAAC,EAAE,QAAQ,EAAE;YAC3B,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;gBAC3B,MAAM,MAAM,cAAc,CAAC,QAAQ,CAAC,CAAA;YACtC,CAAC;YACD,OAAO,QAAQ,CAAA;QACjB,CAAC;KACF,CAAA;IACD,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC,CAAA;IAE3B,qDAAqD;IACrD,MAAM,eAAe,GAAe;QAClC,KAAK,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE;YACrC,qCAAqC;YACrC,CAAC;YAAC,OAA0C,CAAC,OAAO;gBAClD,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,CAAA;YAC9B,KAAK,UAAU,CAAA;YACf,OAAO,OAAO,CAAA;QAChB,CAAC;QAED,KAAK,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE;YACpC,MAAM,MAAM,GAAI,OAA0C,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,CAAA;YAClG,IAAI,OAAO,GAAG,CAAC,CAAA;YACf,IAAI,eAAe,GAAG,QAAQ,CAAA;YAE9B,OACE,WAAW,CAAC;gBACV,MAAM;gBACN,OAAO;gBACP,QAAQ,EAAE,eAAe;gBACzB,OAAO,EAAE,YAAY;aACtB,CAAC,EACF,CAAC;gBACD,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,EAAE,eAAe,EAAE,YAAY,CAAC,CAAA;gBACpE,MAAM,KAAK,CAAC,OAAO,CAAC,CAAA;gBACpB,OAAO,EAAE,CAAA;gBACT,IAAI,CAAC;oBACH,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAA;oBAC5C,eAAe,GAAG,OAAO,CAAA;oBACzB,IAAI,eAAe,CAAC,MAAM,GAAG,GAAG;wBAAE,OAAO,eAAe,CAAA;gBAC1D,CAAC;gBAAC,MAAM,CAAC;oBACP,0DAA0D;oBAC1D,MAAK;gBACP,CAAC;YACH,CAAC;YAED,OAAO,eAAe,CAAA;QACxB,CAAC;KACF,CAAA;IACD,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC,CAAA;IAE3B,OAAO,MAAM,CAAA;AACf,CAAC;AAED,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAA;AAC1D,CAAC"}