@almadar/sdk 0.2.5 → 0.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 CHANGED
@@ -48,11 +48,7 @@ const { schema } = await almadar.generate({
48
48
 
49
49
  `AlmadarClient.generate()` streams SSE events (`start`, `orbital_added`, `complete`, …) via `onEvent`. The returned `schema` is the final `OrbitalSchema` you pass to `<AlmadarApp />`.
50
50
 
51
- For long-running generations, pass `async: true` to flip to job-polling mode:
52
-
53
- ```ts
54
- const { schema } = await almadar.generate({ prompt, async: true });
55
- ```
51
+ There is no job-polling mode — `generate({ async: true })` throws `AsyncUnsupportedError` before any network call. For long-running generations, consume the stream via `onEvent` instead.
56
52
 
57
53
  ## Issuing API keys
58
54
 
@@ -1,5 +1,5 @@
1
1
  import * as react from 'react';
2
- import { A as AlmadarAppProps } from './types-C6RJADoY.js';
2
+ import { a as AlmadarAppProps } from './types-CVGXdQRM.js';
3
3
 
4
4
  declare function AlmadarApp(props: AlmadarAppProps): react.JSX.Element;
5
5
  declare namespace AlmadarApp {
@@ -1,7 +1,7 @@
1
1
  import { OrbitalSchema } from '@almadar/core';
2
2
  export { EntityData, EventPayload, OrbitalSchema, SSEEvent } from '@almadar/core';
3
- import { a as AlmadarClientOptions, G as GenerateOptions, e as GenerateResult, E as EditSchemaPatch, C as CompileOptions, d as CompileResult, b as ApiErrorBody } from '../types-C6RJADoY.js';
4
- export { c as AsyncJobHandle } from '../types-C6RJADoY.js';
3
+ import { b as AlmadarClientOptions, i as GenerateOptions, k as GenerateResult, E as EditSchemaPatch, f as CompileOptions, g as CompileResult, c as ApiErrorBody } from '../types-CVGXdQRM.js';
4
+ export { A as API_ERROR_CODES, d as ApiErrorCode, C as CATALOG_MODES, e as CatalogMode, G as GenerateMeta, h as GenerateMetaOrganism, j as GeneratePin, l as GenerateStreamEvent, m as GenerationMetaEvent, n as GenerationTier, S as STREAM_ERROR_CODES, o as StreamErrorCode, p as isGenerateMeta } from '../types-CVGXdQRM.js';
5
5
 
6
6
  /**
7
7
  * `AlmadarClient` — server / Node-side HTTP client targeting `/api/v1/agent/*`.
@@ -21,7 +21,6 @@ declare class AlmadarClient {
21
21
  editSchema(appId: string, patch: EditSchemaPatch): Promise<OrbitalSchema>;
22
22
  compileToApp(schema: OrbitalSchema, opts?: CompileOptions): Promise<CompileResult>;
23
23
  private streamGenerate;
24
- private pollUntilComplete;
25
24
  private requestJson;
26
25
  private headers;
27
26
  private errorFromResponse;
@@ -54,5 +53,22 @@ declare class CatalogOutOfScopeError extends AlmadarError {
54
53
  declare class ServerError extends AlmadarError {
55
54
  constructor(body: ApiErrorBody);
56
55
  }
56
+ /** 4041-4045 — pin resolution failed: unknown organism, out-of-scope, conflicting pins, unknown knob, or a missing required orbital. */
57
+ declare class PinError extends AlmadarError {
58
+ constructor(body: ApiErrorBody);
59
+ }
60
+ /** 4060 — `generate({ async: true })` has no server-side job surface; use the default streaming mode instead. */
61
+ declare class AsyncUnsupportedError extends AlmadarError {
62
+ constructor(body: ApiErrorBody);
63
+ }
64
+ /** 5001 — generation failed server-side. */
65
+ declare class GenerationFailedError extends AlmadarError {
66
+ constructor(body: ApiErrorBody);
67
+ }
68
+ /** Maps a `generate` SSE `error` event's `{ error, code }` payload to a typed SDK error. */
69
+ declare function streamErrorFromEvent(data: {
70
+ error: string;
71
+ code?: string;
72
+ }): AlmadarError;
57
73
 
58
- export { AlmadarClient, AlmadarClientOptions, AlmadarError, ApiErrorBody, ApiKeyError, CatalogOutOfScopeError, CompileOptions, CompileResult, EditSchemaPatch, GenerateOptions, GenerateResult, RateLimitedError, ServerError };
74
+ export { AlmadarClient, AlmadarClientOptions, AlmadarError, ApiErrorBody, ApiKeyError, AsyncUnsupportedError, CatalogOutOfScopeError, CompileOptions, CompileResult, EditSchemaPatch, GenerateOptions, GenerateResult, GenerationFailedError, PinError, RateLimitedError, ServerError, streamErrorFromEvent };
@@ -2,6 +2,52 @@ import { parseOrbitalSchema } from '@almadar/core';
2
2
 
3
3
  // src/client/AlmadarClient.ts
4
4
 
5
+ // src/types.ts
6
+ var CATALOG_MODES = ["extend", "subset", "replace"];
7
+ function isGenerateMetaOrganism(value) {
8
+ if (value === null || typeof value !== "object") return false;
9
+ const v = value;
10
+ if (typeof v.name !== "string") return false;
11
+ return v.source === "factory" || v.source === "free-lolo";
12
+ }
13
+ function isGenerateMetaCacheVerdict(value) {
14
+ if (value === null) return true;
15
+ if (typeof value !== "object") return false;
16
+ const v = value;
17
+ if (v.verdict !== "hit" && v.verdict !== "miss") return false;
18
+ return v.chosen === null || typeof v.chosen === "string";
19
+ }
20
+ function isGenerateMeta(value) {
21
+ if (value === null || typeof value !== "object") return false;
22
+ const v = value;
23
+ if (v.tier !== "confirmed" && v.tier !== "hit" && v.tier !== "miss") return false;
24
+ if (!Array.isArray(v.organisms) || !v.organisms.every(isGenerateMetaOrganism)) return false;
25
+ if (!Array.isArray(v.demoted) || !v.demoted.every((d) => typeof d === "string")) return false;
26
+ if (!isGenerateMetaCacheVerdict(v.cacheVerdict)) return false;
27
+ return typeof v.durationMs === "number";
28
+ }
29
+ var API_ERROR_CODES = {
30
+ INVALID_REQUEST: 4e3,
31
+ API_KEY: 4001,
32
+ ORIGIN_FORBIDDEN: 4003,
33
+ EDIT_CONFIRM_REQUIRED: 4009,
34
+ RATE_LIMITED: 4029,
35
+ CATALOG_OUT_OF_SCOPE: 4040,
36
+ PIN_UNKNOWN_ORGANISM: 4041,
37
+ PIN_OUT_OF_SCOPE: 4042,
38
+ PIN_CONFLICT: 4043,
39
+ PIN_UNKNOWN_KNOB: 4044,
40
+ PIN_ORBITAL_REQUIRED: 4045,
41
+ ASYNC_UNSUPPORTED: 4060,
42
+ FOCUS_STALE: 4090,
43
+ SERVER: 5e3,
44
+ GENERATION_FAILED: 5001,
45
+ RUNTIME: 5002,
46
+ WORKSPACE_OPEN: 5003,
47
+ AI_UNCONFIGURED: 5030
48
+ };
49
+ var STREAM_ERROR_CODES = ["failed", "runtime", "workspace_open", "ai_unconfigured", "focus_stale"];
50
+
5
51
  // src/client/errors.ts
6
52
  var AlmadarError = class extends Error {
7
53
  code;
@@ -39,18 +85,68 @@ var ServerError = class extends AlmadarError {
39
85
  this.name = "ServerError";
40
86
  }
41
87
  };
88
+ var PinError = class extends AlmadarError {
89
+ constructor(body) {
90
+ super(body);
91
+ this.name = "PinError";
92
+ }
93
+ };
94
+ var AsyncUnsupportedError = class extends AlmadarError {
95
+ constructor(body) {
96
+ super(body);
97
+ this.name = "AsyncUnsupportedError";
98
+ }
99
+ };
100
+ var GenerationFailedError = class extends AlmadarError {
101
+ constructor(body) {
102
+ super(body);
103
+ this.name = "GenerationFailedError";
104
+ }
105
+ };
42
106
  function errorFromBody(body) {
43
107
  switch (body.code) {
44
- case 4001:
108
+ case API_ERROR_CODES.API_KEY:
45
109
  return new ApiKeyError(body);
46
- case 4029:
110
+ case API_ERROR_CODES.RATE_LIMITED:
47
111
  return new RateLimitedError(body);
48
- case 4040:
112
+ case API_ERROR_CODES.CATALOG_OUT_OF_SCOPE:
49
113
  return new CatalogOutOfScopeError(body);
114
+ case API_ERROR_CODES.PIN_UNKNOWN_ORGANISM:
115
+ case API_ERROR_CODES.PIN_OUT_OF_SCOPE:
116
+ case API_ERROR_CODES.PIN_CONFLICT:
117
+ case API_ERROR_CODES.PIN_UNKNOWN_KNOB:
118
+ case API_ERROR_CODES.PIN_ORBITAL_REQUIRED:
119
+ return new PinError(body);
120
+ case API_ERROR_CODES.ASYNC_UNSUPPORTED:
121
+ return new AsyncUnsupportedError(body);
122
+ case API_ERROR_CODES.GENERATION_FAILED:
123
+ return new GenerationFailedError(body);
50
124
  default:
51
125
  return new ServerError(body);
52
126
  }
53
127
  }
128
+ function isStreamErrorCode(code) {
129
+ if (code === void 0) return false;
130
+ return STREAM_ERROR_CODES.some((c) => c === code);
131
+ }
132
+ function streamErrorFromEvent(data) {
133
+ const message = data.error;
134
+ if (!isStreamErrorCode(data.code)) {
135
+ return new ServerError({ code: API_ERROR_CODES.SERVER, message });
136
+ }
137
+ switch (data.code) {
138
+ case "failed":
139
+ return new GenerationFailedError({ code: API_ERROR_CODES.GENERATION_FAILED, message });
140
+ case "ai_unconfigured":
141
+ return new ServerError({ code: API_ERROR_CODES.AI_UNCONFIGURED, message });
142
+ case "workspace_open":
143
+ return new ServerError({ code: API_ERROR_CODES.WORKSPACE_OPEN, message });
144
+ case "focus_stale":
145
+ return new ServerError({ code: API_ERROR_CODES.FOCUS_STALE, message });
146
+ case "runtime":
147
+ return new ServerError({ code: API_ERROR_CODES.RUNTIME, message });
148
+ }
149
+ }
54
150
 
55
151
  // src/client/sseParser.ts
56
152
  async function* parseSSE(stream) {
@@ -106,7 +202,6 @@ function indexOfNewline(s) {
106
202
 
107
203
  // src/client/AlmadarClient.ts
108
204
  var DEFAULT_BASE_URL = "https://studio.almadar.io";
109
- var POLL_BACKOFF_MS = [1e3, 2e3, 5e3, 1e4, 3e4];
110
205
  var AlmadarClient = class {
111
206
  apiKey;
112
207
  baseUrl;
@@ -124,19 +219,10 @@ var AlmadarClient = class {
124
219
  }
125
220
  async generate(input) {
126
221
  if (input.async === true) {
127
- const handle = await this.requestJson("POST", "/api/v1/agent/generate", {
128
- prompt: input.prompt,
129
- endUserId: input.endUserId,
130
- appId: input.appId,
131
- async: true,
132
- provider: input.provider,
133
- model: input.model,
134
- catalogMode: input.catalogMode,
135
- stdAllowList: input.stdAllowList
222
+ throw new AsyncUnsupportedError({
223
+ code: API_ERROR_CODES.ASYNC_UNSUPPORTED,
224
+ message: "AlmadarClient has no async job surface. Omit `async` (or pass false) and consume the streaming response via `onEvent` instead."
136
225
  });
137
- assertString(handle.jobId, "AsyncJobHandle.jobId");
138
- assertString(handle.statusUrl, "AsyncJobHandle.statusUrl");
139
- return this.pollUntilComplete(handle, input.onEvent);
140
226
  }
141
227
  return this.streamGenerate(input);
142
228
  }
@@ -170,56 +256,35 @@ var AlmadarClient = class {
170
256
  provider: input.provider,
171
257
  model: input.model,
172
258
  catalogMode: input.catalogMode,
173
- stdAllowList: input.stdAllowList
259
+ stdAllowList: input.stdAllowList,
260
+ pin: input.pin
174
261
  })
175
262
  });
176
263
  if (!res.ok) throw await this.errorFromResponse(res);
177
264
  if (res.body === null) throw new Error("AlmadarClient.generate: server returned no body");
178
265
  let final = null;
266
+ let meta;
179
267
  for await (const raw of parseSSE(res.body)) {
180
268
  const event = parseSseEvent(raw.data);
181
269
  if (event === null) continue;
182
270
  input.onEvent?.(event);
183
- if (event.type === "complete") {
271
+ if (event.type === "generation_meta") {
272
+ meta = event.data;
273
+ } else if (event.type === "complete") {
184
274
  if (event.data.schema === void 0) {
185
- throw new ServerError({ code: 500, message: "`complete` event did not contain a schema" });
275
+ throw new ServerError({ code: API_ERROR_CODES.SERVER, message: "`complete` event did not contain a schema" });
186
276
  }
187
277
  const schema = parseOrbitalSchema(event.data.schema);
188
- final = { schema, appId: event.data.appId };
278
+ final = { schema, appId: event.data.appId, meta };
189
279
  } else if (event.type === "error") {
190
- throw errorFromBody({ code: 500, message: event.data.error });
280
+ throw streamErrorFromEvent(event.data);
191
281
  }
192
282
  }
193
283
  if (final === null) {
194
- throw new ServerError({ code: 500, message: "SSE stream ended without `complete` event" });
284
+ throw new ServerError({ code: API_ERROR_CODES.SERVER, message: "SSE stream ended without `complete` event" });
195
285
  }
196
286
  return final;
197
287
  }
198
- async pollUntilComplete(handle, onEvent) {
199
- let attempt = 0;
200
- for (; ; ) {
201
- const delay = POLL_BACKOFF_MS[Math.min(attempt, POLL_BACKOFF_MS.length - 1)];
202
- await sleep(delay);
203
- attempt += 1;
204
- const status = await this.requestJson("GET", handle.statusUrl);
205
- assertString(status.state, "JobStatus.state");
206
- if (status.events !== void 0 && onEvent !== void 0) {
207
- for (const e of status.events) onEvent(e);
208
- }
209
- if (status.state === "complete") {
210
- if (status.result === void 0) {
211
- throw new ServerError({ code: 500, message: "Job complete but no result returned" });
212
- }
213
- return status.result;
214
- }
215
- if (status.state === "error") {
216
- throw errorFromBody({
217
- code: status.errorCode ?? 500,
218
- message: status.errorMessage ?? "Job failed"
219
- });
220
- }
221
- }
222
- }
223
288
  async requestJson(method, path, body) {
224
289
  const isAbsolute = path.startsWith("http://") || path.startsWith("https://");
225
290
  const url = isAbsolute ? path : `${this.baseUrl}${path}`;
@@ -235,7 +300,7 @@ var AlmadarClient = class {
235
300
  if (!res.ok) throw await this.errorFromResponse(res);
236
301
  const text = await res.text();
237
302
  if (text === "") {
238
- throw new ServerError({ code: 500, message: "Empty response body" });
303
+ throw new ServerError({ code: API_ERROR_CODES.SERVER, message: "Empty response body" });
239
304
  }
240
305
  const parsed = JSON.parse(text);
241
306
  return parsed;
@@ -280,17 +345,17 @@ function parseSseEvent(dataLine) {
280
345
  }
281
346
  if (payload === null || typeof payload !== "object" || Array.isArray(payload)) return null;
282
347
  if (typeof payload.type !== "string" || typeof payload.timestamp !== "number") return null;
348
+ if (payload.type === "generation_meta") {
349
+ return isGenerateMeta(payload.data) ? { type: "generation_meta", data: payload.data, timestamp: payload.timestamp } : null;
350
+ }
283
351
  return payload;
284
352
  }
285
353
  function assertString(v, name) {
286
354
  if (typeof v !== "string" || v === "") {
287
- throw new ServerError({ code: 500, message: `Malformed server response: ${name} is not a string` });
355
+ throw new ServerError({ code: API_ERROR_CODES.SERVER, message: `Malformed server response: ${name} is not a string` });
288
356
  }
289
357
  }
290
- function sleep(ms) {
291
- return new Promise((resolve) => setTimeout(resolve, ms));
292
- }
293
358
 
294
- export { AlmadarClient, AlmadarError, ApiKeyError, CatalogOutOfScopeError, RateLimitedError, ServerError };
359
+ export { API_ERROR_CODES, AlmadarClient, AlmadarError, ApiKeyError, AsyncUnsupportedError, CATALOG_MODES, CatalogOutOfScopeError, GenerationFailedError, PinError, RateLimitedError, STREAM_ERROR_CODES, ServerError, isGenerateMeta, streamErrorFromEvent };
295
360
  //# sourceMappingURL=index.js.map
296
361
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/client/errors.ts","../../src/client/sseParser.ts","../../src/client/AlmadarClient.ts"],"names":[],"mappings":";;;;;AAOO,IAAM,YAAA,GAAN,cAA2B,KAAA,CAAM;AAAA,EAC7B,IAAA;AAAA,EACA,OAAA;AAAA,EACT,YAAY,IAAA,EAAoB;AAC9B,IAAA,KAAA,CAAM,KAAK,OAAO,CAAA;AAClB,IAAA,IAAA,CAAK,IAAA,GAAO,cAAA;AACZ,IAAA,IAAA,CAAK,OAAO,IAAA,CAAK,IAAA;AACjB,IAAA,IAAA,CAAK,UAAU,IAAA,CAAK,OAAA;AAAA,EACtB;AACF;AAGO,IAAM,WAAA,GAAN,cAA0B,YAAA,CAAa;AAAA,EAC5C,YAAY,IAAA,EAAoB;AAC9B,IAAA,KAAA,CAAM,IAAI,CAAA;AACV,IAAA,IAAA,CAAK,IAAA,GAAO,aAAA;AAAA,EACd;AACF;AAGO,IAAM,gBAAA,GAAN,cAA+B,YAAA,CAAa;AAAA,EACxC,iBAAA;AAAA,EACT,WAAA,CAAY,MAAoB,iBAAA,EAA4B;AAC1D,IAAA,KAAA,CAAM,IAAI,CAAA;AACV,IAAA,IAAA,CAAK,IAAA,GAAO,kBAAA;AACZ,IAAA,IAAA,CAAK,iBAAA,GAAoB,iBAAA;AAAA,EAC3B;AACF;AAGO,IAAM,sBAAA,GAAN,cAAqC,YAAA,CAAa;AAAA,EACvD,YAAY,IAAA,EAAoB;AAC9B,IAAA,KAAA,CAAM,IAAI,CAAA;AACV,IAAA,IAAA,CAAK,IAAA,GAAO,wBAAA;AAAA,EACd;AACF;AAGO,IAAM,WAAA,GAAN,cAA0B,YAAA,CAAa;AAAA,EAC5C,YAAY,IAAA,EAAoB;AAC9B,IAAA,KAAA,CAAM,IAAI,CAAA;AACV,IAAA,IAAA,CAAK,IAAA,GAAO,aAAA;AAAA,EACd;AACF;AAEO,SAAS,cAAc,IAAA,EAAkC;AAC9D,EAAA,QAAQ,KAAK,IAAA;AAAM,IACjB,KAAK,IAAA;AACH,MAAA,OAAO,IAAI,YAAY,IAAI,CAAA;AAAA,IAC7B,KAAK,IAAA;AACH,MAAA,OAAO,IAAI,iBAAiB,IAAI,CAAA;AAAA,IAClC,KAAK,IAAA;AACH,MAAA,OAAO,IAAI,uBAAuB,IAAI,CAAA;AAAA,IACxC;AACE,MAAA,OAAO,IAAI,YAAY,IAAI,CAAA;AAAA;AAEjC;;;ACxCA,gBAAuB,SACrB,MAAA,EACyC;AACzC,EAAA,MAAM,MAAA,GAAS,OAAO,SAAA,EAAU;AAChC,EAAA,MAAM,OAAA,GAAU,IAAI,WAAA,CAAY,OAAO,CAAA;AACvC,EAAA,IAAI,MAAA,GAAS,EAAA;AACb,EAAA,IAAI,YAAA,GAAe,EAAA;AACnB,EAAA,IAAI,WAAA,GAAc,EAAA;AAElB,EAAA,IAAI;AACF,IAAA,WAAS;AACP,MAAA,MAAM,EAAE,KAAA,EAAO,IAAA,EAAK,GAAI,MAAM,OAAO,IAAA,EAAK;AAC1C,MAAA,IAAI,IAAA,EAAM;AACV,MAAA,MAAA,IAAU,QAAQ,MAAA,CAAO,KAAA,EAAO,EAAE,MAAA,EAAQ,MAAM,CAAA;AAEhD,MAAA,IAAI,UAAA;AACJ,MAAA,OAAA,CAAQ,UAAA,GAAa,cAAA,CAAe,MAAM,CAAA,MAAO,CAAA,CAAA,EAAI;AACnD,QAAA,MAAM,OAAA,GAAU,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,UAAU,CAAA;AAC1C,QAAA,MAAA,GAAS,MAAA,CAAO,KAAA,CAAM,UAAA,IAAc,MAAA,CAAO,UAAU,CAAA,KAAM,IAAA,IAAQ,MAAA,CAAO,UAAA,GAAa,CAAC,CAAA,KAAM,IAAA,GAAO,IAAI,CAAA,CAAE,CAAA;AAE3G,QAAA,IAAI,YAAY,EAAA,EAAI;AAClB,UAAA,IAAI,WAAA,KAAgB,EAAA,IAAM,YAAA,KAAiB,EAAA,EAAI;AAC7C,YAAA,MAAM,EAAE,KAAA,EAAO,YAAA,EAAc,IAAA,EAAM,WAAA,EAAY;AAC/C,YAAA,YAAA,GAAe,EAAA;AACf,YAAA,WAAA,GAAc,EAAA;AAAA,UAChB;AACA,UAAA;AAAA,QACF;AACA,QAAA,IAAI,OAAA,CAAQ,UAAA,CAAW,GAAG,CAAA,EAAG;AAE7B,QAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,OAAA,CAAQ,GAAG,CAAA;AACjC,QAAA,MAAM,QAAQ,KAAA,KAAU,CAAA,CAAA,GAAK,UAAU,OAAA,CAAQ,KAAA,CAAM,GAAG,KAAK,CAAA;AAC7D,QAAA,MAAM,WAAW,KAAA,KAAU,CAAA,CAAA,GAAK,KAAK,OAAA,CAAQ,KAAA,CAAM,QAAQ,CAAC,CAAA;AAC5D,QAAA,MAAM,MAAA,GAAS,SAAS,UAAA,CAAW,GAAG,IAAI,QAAA,CAAS,KAAA,CAAM,CAAC,CAAA,GAAI,QAAA;AAE9D,QAAA,IAAI,UAAU,OAAA,EAAS;AACrB,UAAA,YAAA,GAAe,MAAA;AAAA,QACjB,CAAA,MAAA,IAAW,UAAU,MAAA,EAAQ;AAC3B,UAAA,WAAA,GAAc,WAAA,KAAgB,EAAA,GAAK,MAAA,GAAS,CAAA,EAAG,WAAW;AAAA,EAAK,MAAM,CAAA,CAAA;AAAA,QACvE;AAAA,MACF;AAAA,IACF;AACA,IAAA,IAAI,WAAA,KAAgB,EAAA,IAAM,YAAA,KAAiB,EAAA,EAAI;AAC7C,MAAA,MAAM,EAAE,KAAA,EAAO,YAAA,EAAc,IAAA,EAAM,WAAA,EAAY;AAAA,IACjD;AAAA,EACF,CAAA,SAAE;AACA,IAAA,MAAA,CAAO,WAAA,EAAY;AAAA,EACrB;AACF;AAEA,SAAS,eAAe,CAAA,EAAmB;AACzC,EAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,CAAA,CAAE,MAAA,EAAQ,KAAK,CAAA,EAAG;AACpC,IAAA,MAAM,CAAA,GAAI,EAAE,CAAC,CAAA;AACb,IAAA,IAAI,CAAA,KAAM,IAAA,IAAQ,CAAA,KAAM,IAAA,EAAM,OAAO,CAAA;AAAA,EACvC;AACA,EAAA,OAAO,EAAA;AACT;;;ACxDA,IAAM,gBAAA,GAAmB,2BAAA;AACzB,IAAM,kBAAqC,CAAC,GAAA,EAAM,GAAA,EAAM,GAAA,EAAM,KAAQ,GAAM,CAAA;AAUrE,IAAM,gBAAN,MAAoB;AAAA,EACR,MAAA;AAAA,EACA,OAAA;AAAA,EACA,SAAA;AAAA,EAEjB,YAAY,IAAA,EAA4B;AACtC,IAAA,IAAI,CAAC,IAAA,CAAK,MAAA,IAAU,OAAO,IAAA,CAAK,WAAW,QAAA,EAAU;AACnD,MAAA,MAAM,IAAI,MAAM,wCAAwC,CAAA;AAAA,IAC1D;AACA,IAAA,IAAA,CAAK,SAAS,IAAA,CAAK,MAAA;AACnB,IAAA,IAAA,CAAK,WAAW,IAAA,CAAK,OAAA,IAAW,gBAAA,EAAkB,OAAA,CAAQ,OAAO,EAAE,CAAA;AACnE,IAAA,IAAA,CAAK,SAAA,GAAY,IAAA,CAAK,KAAA,IAAS,UAAA,CAAW,KAAA;AAC1C,IAAA,IAAI,OAAO,IAAA,CAAK,SAAA,KAAc,UAAA,EAAY;AACxC,MAAA,MAAM,IAAI,MAAM,uEAAkE,CAAA;AAAA,IACpF;AAAA,EACF;AAAA,EAEA,MAAM,SAAS,KAAA,EAAiD;AAC9D,IAAA,IAAI,KAAA,CAAM,UAAU,IAAA,EAAM;AACxB,MAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,WAAA,CAA4B,QAAQ,wBAAA,EAA0B;AAAA,QACtF,QAAQ,KAAA,CAAM,MAAA;AAAA,QACd,WAAW,KAAA,CAAM,SAAA;AAAA,QACjB,OAAO,KAAA,CAAM,KAAA;AAAA,QACb,KAAA,EAAO,IAAA;AAAA,QACP,UAAU,KAAA,CAAM,QAAA;AAAA,QAChB,OAAO,KAAA,CAAM,KAAA;AAAA,QACb,aAAa,KAAA,CAAM,WAAA;AAAA,QACnB,cAAc,KAAA,CAAM;AAAA,OACrB,CAAA;AACD,MAAA,YAAA,CAAa,MAAA,CAAO,OAAO,sBAAsB,CAAA;AACjD,MAAA,YAAA,CAAa,MAAA,CAAO,WAAW,0BAA0B,CAAA;AACzD,MAAA,OAAO,IAAA,CAAK,iBAAA,CAAkB,MAAA,EAAQ,KAAA,CAAM,OAAO,CAAA;AAAA,IACrD;AACA,IAAA,OAAO,IAAA,CAAK,eAAe,KAAK,CAAA;AAAA,EAClC;AAAA,EAEA,MAAM,UAAA,CAAW,KAAA,EAAe,KAAA,EAAgD;AAC9E,IAAA,IAAI,CAAC,KAAA,EAAO,MAAM,IAAI,MAAM,6CAA6C,CAAA;AACzE,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,WAAA,CAA2B,OAAO,2BAAA,EAA6B;AAAA,MACvF,KAAA;AAAA,MACA;AAAA,KACD,CAAA;AACD,IAAA,YAAA,CAAa,MAAA,CAAO,MAAM,oBAAoB,CAAA;AAC9C,IAAA,OAAO,MAAA;AAAA,EACT;AAAA,EAEA,MAAM,YAAA,CAAa,MAAA,EAAuB,IAAA,EAA+C;AACvF,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,WAAA,CAA2B,QAAQ,uBAAA,EAAyB;AAAA,MACpF,MAAA;AAAA,MACA,QAAQ,IAAA,EAAM,MAAA;AAAA,MACd,OAAO,IAAA,EAAM;AAAA,KACd,CAAA;AACD,IAAA,YAAA,CAAa,MAAA,CAAO,aAAa,2BAA2B,CAAA;AAC5D,IAAA,YAAA,CAAa,MAAA,CAAO,WAAW,yBAAyB,CAAA;AACxD,IAAA,OAAO,MAAA;AAAA,EACT;AAAA,EAEA,MAAc,eAAe,KAAA,EAAiD;AAC5E,IAAA,MAAM,MAAM,MAAM,IAAA,CAAK,UAAU,CAAA,EAAG,IAAA,CAAK,OAAO,CAAA,sBAAA,CAAA,EAA0B;AAAA,MACxE,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS,IAAA,CAAK,OAAA,CAAQ,EAAE,MAAA,EAAQ,qBAAqB,WAAA,EAAa,kBAAA,EAAmB,EAAG,KAAA,CAAM,SAAS,CAAA;AAAA,MACvG,IAAA,EAAM,KAAK,SAAA,CAAU;AAAA,QACnB,QAAQ,KAAA,CAAM,MAAA;AAAA,QACd,WAAW,KAAA,CAAM,SAAA;AAAA,QACjB,OAAO,KAAA,CAAM,KAAA;AAAA,QACb,UAAU,KAAA,CAAM,QAAA;AAAA,QAChB,OAAO,KAAA,CAAM,KAAA;AAAA,QACb,aAAa,KAAA,CAAM,WAAA;AAAA,QACnB,cAAc,KAAA,CAAM;AAAA,OACrB;AAAA,KACF,CAAA;AACD,IAAA,IAAI,CAAC,GAAA,CAAI,EAAA,QAAU,MAAM,IAAA,CAAK,kBAAkB,GAAG,CAAA;AACnD,IAAA,IAAI,IAAI,IAAA,KAAS,IAAA,EAAM,MAAM,IAAI,MAAM,iDAAiD,CAAA;AAExF,IAAA,IAAI,KAAA,GAA+B,IAAA;AACnC,IAAA,WAAA,MAAiB,GAAA,IAAO,QAAA,CAAS,GAAA,CAAI,IAAI,CAAA,EAAG;AAC1C,MAAA,MAAM,KAAA,GAAQ,aAAA,CAAc,GAAA,CAAI,IAAI,CAAA;AACpC,MAAA,IAAI,UAAU,IAAA,EAAM;AACpB,MAAA,KAAA,CAAM,UAAU,KAAK,CAAA;AACrB,MAAA,IAAI,KAAA,CAAM,SAAS,UAAA,EAAY;AAC7B,QAAA,IAAI,KAAA,CAAM,IAAA,CAAK,MAAA,KAAW,MAAA,EAAW;AACnC,UAAA,MAAM,IAAI,WAAA,CAAY,EAAE,MAAM,GAAA,EAAK,OAAA,EAAS,6CAA6C,CAAA;AAAA,QAC3F;AACA,QAAA,MAAM,MAAA,GAAS,kBAAA,CAAmB,KAAA,CAAM,IAAA,CAAK,MAAM,CAAA;AACnD,QAAA,KAAA,GAAQ,EAAE,MAAA,EAAQ,KAAA,EAAO,KAAA,CAAM,KAAK,KAAA,EAAM;AAAA,MAC5C,CAAA,MAAA,IAAW,KAAA,CAAM,IAAA,KAAS,OAAA,EAAS;AACjC,QAAA,MAAM,aAAA,CAAc,EAAE,IAAA,EAAM,GAAA,EAAK,SAAS,KAAA,CAAM,IAAA,CAAK,OAAO,CAAA;AAAA,MAC9D;AAAA,IACF;AACA,IAAA,IAAI,UAAU,IAAA,EAAM;AAClB,MAAA,MAAM,IAAI,WAAA,CAAY,EAAE,MAAM,GAAA,EAAK,OAAA,EAAS,6CAA6C,CAAA;AAAA,IAC3F;AACA,IAAA,OAAO,KAAA;AAAA,EACT;AAAA,EAEA,MAAc,iBAAA,CACZ,MAAA,EACA,OAAA,EACyB;AACzB,IAAA,IAAI,OAAA,GAAU,CAAA;AACd,IAAA,WAAS;AACP,MAAA,MAAM,KAAA,GAAQ,gBAAgB,IAAA,CAAK,GAAA,CAAI,SAAS,eAAA,CAAgB,MAAA,GAAS,CAAC,CAAC,CAAA;AAC3E,MAAA,MAAM,MAAM,KAAK,CAAA;AACjB,MAAA,OAAA,IAAW,CAAA;AACX,MAAA,MAAM,SAAS,MAAM,IAAA,CAAK,WAAA,CAAuB,KAAA,EAAO,OAAO,SAAS,CAAA;AACxE,MAAA,YAAA,CAAa,MAAA,CAAO,OAAO,iBAAiB,CAAA;AAC5C,MAAA,IAAI,MAAA,CAAO,MAAA,KAAW,MAAA,IAAa,OAAA,KAAY,MAAA,EAAW;AACxD,QAAA,KAAA,MAAW,CAAA,IAAK,MAAA,CAAO,MAAA,EAAQ,OAAA,CAAQ,CAAC,CAAA;AAAA,MAC1C;AACA,MAAA,IAAI,MAAA,CAAO,UAAU,UAAA,EAAY;AAC/B,QAAA,IAAI,MAAA,CAAO,WAAW,MAAA,EAAW;AAC/B,UAAA,MAAM,IAAI,WAAA,CAAY,EAAE,MAAM,GAAA,EAAK,OAAA,EAAS,uCAAuC,CAAA;AAAA,QACrF;AACA,QAAA,OAAO,MAAA,CAAO,MAAA;AAAA,MAChB;AACA,MAAA,IAAI,MAAA,CAAO,UAAU,OAAA,EAAS;AAC5B,QAAA,MAAM,aAAA,CAAc;AAAA,UAClB,IAAA,EAAM,OAAO,SAAA,IAAa,GAAA;AAAA,UAC1B,OAAA,EAAS,OAAO,YAAA,IAAgB;AAAA,SACjC,CAAA;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,WAAA,CAAe,MAAA,EAAgB,IAAA,EAAc,IAAA,EAA2B;AACpF,IAAA,MAAM,aAAa,IAAA,CAAK,UAAA,CAAW,SAAS,CAAA,IAAK,IAAA,CAAK,WAAW,UAAU,CAAA;AAC3E,IAAA,MAAM,MAAM,UAAA,GAAa,IAAA,GAAO,GAAG,IAAA,CAAK,OAAO,GAAG,IAAI,CAAA,CAAA;AACtD,IAAA,MAAM,IAAA,GAAoB;AAAA,MACxB,MAAA;AAAA,MACA,OAAA,EAAS,KAAK,OAAA,CAAQ;AAAA,QACpB,MAAA,EAAQ,kBAAA;AAAA,QACR,WAAA,EAAa,IAAA,KAAS,MAAA,GAAY,kBAAA,GAAqB;AAAA,OACxD;AAAA,KACH;AACA,IAAA,IAAI,SAAS,MAAA,EAAW,IAAA,CAAK,IAAA,GAAO,IAAA,CAAK,UAAU,IAAI,CAAA;AACvD,IAAA,MAAM,GAAA,GAAM,MAAM,IAAA,CAAK,SAAA,CAAU,KAAK,IAAI,CAAA;AAC1C,IAAA,IAAI,CAAC,GAAA,CAAI,EAAA,QAAU,MAAM,IAAA,CAAK,kBAAkB,GAAG,CAAA;AACnD,IAAA,MAAM,IAAA,GAAO,MAAM,GAAA,CAAI,IAAA,EAAK;AAC5B,IAAA,IAAI,SAAS,EAAA,EAAI;AACf,MAAA,MAAM,IAAI,WAAA,CAAY,EAAE,MAAM,GAAA,EAAK,OAAA,EAAS,uBAAuB,CAAA;AAAA,IACrE;AACA,IAAA,MAAM,MAAA,GAAY,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA;AACjC,IAAA,OAAO,MAAA;AAAA,EACT;AAAA,EAEQ,OAAA,CACN,MACA,SAAA,EACwB;AACxB,IAAA,MAAM,IAA4B,EAAE,aAAA,EAAe,CAAA,OAAA,EAAU,IAAA,CAAK,MAAM,CAAA,CAAA,EAAG;AAC3E,IAAA,IAAI,KAAK,MAAA,KAAW,MAAA,EAAW,CAAA,CAAE,QAAQ,IAAI,IAAA,CAAK,MAAA;AAClD,IAAA,IAAI,KAAK,WAAA,KAAgB,MAAA,EAAW,CAAA,CAAE,cAAc,IAAI,IAAA,CAAK,WAAA;AAC7D,IAAA,IAAI,cAAc,MAAA,IAAa,SAAA,KAAc,EAAA,EAAI,CAAA,CAAE,eAAe,CAAA,GAAI,SAAA;AACtE,IAAA,OAAO,CAAA;AAAA,EACT;AAAA,EAEA,MAAc,kBAAkB,GAAA,EAA+B;AAC7D,IAAA,MAAM,IAAA,GAAO,MAAM,GAAA,CAAI,IAAA,EAAK;AAC5B,IAAA,IAAI,IAAA;AACJ,IAAA,IAAI;AACF,MAAA,MAAM,SAA8B,IAAA,KAAS,EAAA,GAAK,IAAA,GAAO,IAAA,CAAK,MAAM,IAAI,CAAA;AACxE,MAAA,IAAA,GAAO,MAAA,KAAW,IAAA,IAAQ,OAAO,MAAA,CAAO,IAAA,KAAS,YAAY,OAAO,MAAA,CAAO,OAAA,KAAY,QAAA,GACnF,MAAA,GACA;AAAA,QACE,MAAM,GAAA,CAAI,MAAA;AAAA,QACV,OAAA,EAAS,GAAA,CAAI,UAAA,KAAe,EAAA,GAAK,IAAI,UAAA,GAAa;AAAA,OACpD;AAAA,IACN,CAAA,CAAA,MAAQ;AACN,MAAA,IAAA,GAAO,EAAE,MAAM,GAAA,CAAI,MAAA,EAAQ,SAAS,IAAA,KAAS,EAAA,GAAK,IAAA,GAAO,GAAA,CAAI,UAAA,EAAW;AAAA,IAC1E;AACA,IAAA,MAAM,UAAA,GAAa,GAAA,CAAI,OAAA,CAAQ,GAAA,CAAI,aAAa,CAAA;AAChD,IAAA,MAAM,GAAA,GAAM,cAAc,IAAI,CAAA;AAC9B,IAAA,IAAI,GAAA,CAAI,IAAA,KAAS,kBAAA,IAAsB,UAAA,KAAe,IAAA,EAAM;AAC1D,MAAA,MAAM,OAAA,GAAU,OAAO,UAAU,CAAA;AACjC,MAAA,IAAI,MAAA,CAAO,QAAA,CAAS,OAAO,CAAA,EAAG;AAC5B,QAAA,MAAA,CAAO,cAAA,CAAe,KAAK,mBAAA,EAAqB,EAAE,OAAO,OAAA,EAAS,UAAA,EAAY,MAAM,CAAA;AAAA,MACtF;AAAA,IACF;AACA,IAAA,OAAO,GAAA;AAAA,EACT;AACF;AAQA,SAAS,cAAc,QAAA,EAAmC;AACxD,EAAA,IAAI,QAAA,KAAa,IAAI,OAAO,IAAA;AAC5B,EAAA,IAAI,OAAA;AACJ,EAAA,IAAI;AACF,IAAA,OAAA,GAAU,IAAA,CAAK,MAAM,QAAQ,CAAA;AAAA,EAC/B,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,IAAI,OAAA,KAAY,QAAQ,OAAO,OAAA,KAAY,YAAY,KAAA,CAAM,OAAA,CAAQ,OAAO,CAAA,EAAG,OAAO,IAAA;AACtF,EAAA,IAAI,OAAO,QAAQ,IAAA,KAAS,QAAA,IAAY,OAAO,OAAA,CAAQ,SAAA,KAAc,UAAU,OAAO,IAAA;AACtF,EAAA,OAAO,OAAA;AACT;AAEA,SAAS,YAAA,CAAa,GAAuB,IAAA,EAAmC;AAC9E,EAAA,IAAI,OAAO,CAAA,KAAM,QAAA,IAAY,CAAA,KAAM,EAAA,EAAI;AACrC,IAAA,MAAM,IAAI,YAAY,EAAE,IAAA,EAAM,KAAK,OAAA,EAAS,CAAA,2BAAA,EAA8B,IAAI,CAAA,gBAAA,CAAA,EAAoB,CAAA;AAAA,EACpG;AACF;AAEA,SAAS,MAAM,EAAA,EAA2B;AACxC,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,YAAY,UAAA,CAAW,OAAA,EAAS,EAAE,CAAC,CAAA;AACzD","file":"index.js","sourcesContent":["/**\n * Typed SDK errors. Server emits a structured `ApiErrorBody`; the HTTP layer\n * maps the `code` to one of these subclasses. Customers `catch` by class.\n */\n\nimport type { ApiErrorBody } from '../types';\n\nexport class AlmadarError extends Error {\n readonly code: number;\n readonly details?: ApiErrorBody['details'];\n constructor(body: ApiErrorBody) {\n super(body.message);\n this.name = 'AlmadarError';\n this.code = body.code;\n this.details = body.details;\n }\n}\n\n/** 4001 — invalid, revoked, or missing API key. */\nexport class ApiKeyError extends AlmadarError {\n constructor(body: ApiErrorBody) {\n super(body);\n this.name = 'ApiKeyError';\n }\n}\n\n/** 4029 — team cap (feature counter) exceeded. Retry after a billing cycle. */\nexport class RateLimitedError extends AlmadarError {\n readonly retryAfterSeconds?: number;\n constructor(body: ApiErrorBody, retryAfterSeconds?: number) {\n super(body);\n this.name = 'RateLimitedError';\n this.retryAfterSeconds = retryAfterSeconds;\n }\n}\n\n/** 4040 — the team's behavior catalog (subset/replace mode) cannot serve the request. */\nexport class CatalogOutOfScopeError extends AlmadarError {\n constructor(body: ApiErrorBody) {\n super(body);\n this.name = 'CatalogOutOfScopeError';\n }\n}\n\n/** Anything else from the server with a recognized envelope but no specific subclass. */\nexport class ServerError extends AlmadarError {\n constructor(body: ApiErrorBody) {\n super(body);\n this.name = 'ServerError';\n }\n}\n\nexport function errorFromBody(body: ApiErrorBody): AlmadarError {\n switch (body.code) {\n case 4001:\n return new ApiKeyError(body);\n case 4029:\n return new RateLimitedError(body);\n case 4040:\n return new CatalogOutOfScopeError(body);\n default:\n return new ServerError(body);\n }\n}\n","/**\n * Minimal Server-Sent Events parser. Reads a `ReadableStream<Uint8Array>`\n * (the body of a `fetch` Response) and yields decoded events. Universal:\n * works in browser, Node 18+, Deno, Bun.\n *\n * Spec subset implemented:\n * - `event:` and `data:` fields\n * - dispatch on blank line\n * - newline-tolerant (CRLF + LF)\n * - skips comments (`:`-prefixed lines)\n *\n * Not implemented (we don't need them):\n * - `id:` / `retry:` fields\n * - reconnection / last-event-id\n */\n\nexport interface RawSseEvent {\n /** `event:` field value. Empty string when absent — matches the spec default. */\n event: string;\n /** Concatenated `data:` lines, joined by newlines. */\n data: string;\n}\n\nexport async function* parseSSE(\n stream: ReadableStream<Uint8Array>,\n): AsyncGenerator<RawSseEvent, void, void> {\n const reader = stream.getReader();\n const decoder = new TextDecoder('utf-8');\n let buffer = '';\n let currentEvent = '';\n let currentData = '';\n\n try {\n for (;;) {\n const { value, done } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n\n let newlineIdx: number;\n while ((newlineIdx = indexOfNewline(buffer)) !== -1) {\n const rawLine = buffer.slice(0, newlineIdx);\n buffer = buffer.slice(newlineIdx + (buffer[newlineIdx] === '\\r' && buffer[newlineIdx + 1] === '\\n' ? 2 : 1));\n\n if (rawLine === '') {\n if (currentData !== '' || currentEvent !== '') {\n yield { event: currentEvent, data: currentData };\n currentEvent = '';\n currentData = '';\n }\n continue;\n }\n if (rawLine.startsWith(':')) continue;\n\n const colon = rawLine.indexOf(':');\n const field = colon === -1 ? rawLine : rawLine.slice(0, colon);\n const rawValue = colon === -1 ? '' : rawLine.slice(colon + 1);\n const value2 = rawValue.startsWith(' ') ? rawValue.slice(1) : rawValue;\n\n if (field === 'event') {\n currentEvent = value2;\n } else if (field === 'data') {\n currentData = currentData === '' ? value2 : `${currentData}\\n${value2}`;\n }\n }\n }\n if (currentData !== '' || currentEvent !== '') {\n yield { event: currentEvent, data: currentData };\n }\n } finally {\n reader.releaseLock();\n }\n}\n\nfunction indexOfNewline(s: string): number {\n for (let i = 0; i < s.length; i += 1) {\n const c = s[i];\n if (c === '\\n' || c === '\\r') return i;\n }\n return -1;\n}\n","/**\n * `AlmadarClient` — server / Node-side HTTP client targeting `/api/v1/agent/*`.\n * Authenticates with a team-bound API key (`sk_*`) issued from\n * Studio's `/settings/sdk` panel. See `docs/Almadar_Studio_SDK.md` §5.\n *\n * Never instantiate this in a browser bundle — `apiKey` must never leave\n * the customer's server.\n */\n\nimport { parseOrbitalSchema, type OrbitalSchema, type SSEEvent } from '@almadar/core';\nimport type {\n AlmadarClientOptions,\n ApiErrorBody,\n AsyncJobHandle,\n CompileOptions,\n CompileResult,\n EditSchemaPatch,\n GenerateOptions,\n GenerateResult,\n} from '../types';\nimport { errorFromBody, ServerError } from './errors';\nimport { parseSSE } from './sseParser';\n\nconst DEFAULT_BASE_URL = 'https://studio.almadar.io';\nconst POLL_BACKOFF_MS: readonly number[] = [1000, 2000, 5000, 10_000, 30_000];\n\ninterface JobStatus {\n state: 'pending' | 'complete' | 'error';\n events?: readonly SSEEvent[];\n result?: GenerateResult;\n errorCode?: number;\n errorMessage?: string;\n}\n\nexport class AlmadarClient {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly fetchImpl: typeof fetch;\n\n constructor(opts: AlmadarClientOptions) {\n if (!opts.apiKey || typeof opts.apiKey !== 'string') {\n throw new Error('AlmadarClient: opts.apiKey is required');\n }\n this.apiKey = opts.apiKey;\n this.baseUrl = (opts.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/$/, '');\n this.fetchImpl = opts.fetch ?? globalThis.fetch;\n if (typeof this.fetchImpl !== 'function') {\n throw new Error('AlmadarClient: no fetch available — pass opts.fetch for Node <18');\n }\n }\n\n async generate(input: GenerateOptions): Promise<GenerateResult> {\n if (input.async === true) {\n const handle = await this.requestJson<AsyncJobHandle>('POST', '/api/v1/agent/generate', {\n prompt: input.prompt,\n endUserId: input.endUserId,\n appId: input.appId,\n async: true,\n provider: input.provider,\n model: input.model,\n catalogMode: input.catalogMode,\n stdAllowList: input.stdAllowList,\n });\n assertString(handle.jobId, 'AsyncJobHandle.jobId');\n assertString(handle.statusUrl, 'AsyncJobHandle.statusUrl');\n return this.pollUntilComplete(handle, input.onEvent);\n }\n return this.streamGenerate(input);\n }\n\n async editSchema(appId: string, patch: EditSchemaPatch): Promise<OrbitalSchema> {\n if (!appId) throw new Error('AlmadarClient.editSchema: appId is required');\n const schema = await this.requestJson<OrbitalSchema>('PUT', '/api/v1/agent/edit-schema', {\n appId,\n patch,\n });\n assertString(schema.name, 'OrbitalSchema.name');\n return schema;\n }\n\n async compileToApp(schema: OrbitalSchema, opts?: CompileOptions): Promise<CompileResult> {\n const result = await this.requestJson<CompileResult>('POST', '/api/v1/agent/compile', {\n schema,\n target: opts?.target,\n shell: opts?.shell,\n });\n assertString(result.downloadUrl, 'CompileResult.downloadUrl');\n assertString(result.expiresAt, 'CompileResult.expiresAt');\n return result;\n }\n\n private async streamGenerate(input: GenerateOptions): Promise<GenerateResult> {\n const res = await this.fetchImpl(`${this.baseUrl}/api/v1/agent/generate`, {\n method: 'POST',\n headers: this.headers({ accept: 'text/event-stream', contentType: 'application/json' }, input.endUserId),\n body: JSON.stringify({\n prompt: input.prompt,\n endUserId: input.endUserId,\n appId: input.appId,\n provider: input.provider,\n model: input.model,\n catalogMode: input.catalogMode,\n stdAllowList: input.stdAllowList,\n }),\n });\n if (!res.ok) throw await this.errorFromResponse(res);\n if (res.body === null) throw new Error('AlmadarClient.generate: server returned no body');\n\n let final: GenerateResult | null = null;\n for await (const raw of parseSSE(res.body)) {\n const event = parseSseEvent(raw.data);\n if (event === null) continue;\n input.onEvent?.(event);\n if (event.type === 'complete') {\n if (event.data.schema === undefined) {\n throw new ServerError({ code: 500, message: '`complete` event did not contain a schema' });\n }\n const schema = parseOrbitalSchema(event.data.schema);\n final = { schema, appId: event.data.appId };\n } else if (event.type === 'error') {\n throw errorFromBody({ code: 500, message: event.data.error });\n }\n }\n if (final === null) {\n throw new ServerError({ code: 500, message: 'SSE stream ended without `complete` event' });\n }\n return final;\n }\n\n private async pollUntilComplete(\n handle: AsyncJobHandle,\n onEvent: GenerateOptions['onEvent'],\n ): Promise<GenerateResult> {\n let attempt = 0;\n for (;;) {\n const delay = POLL_BACKOFF_MS[Math.min(attempt, POLL_BACKOFF_MS.length - 1)];\n await sleep(delay);\n attempt += 1;\n const status = await this.requestJson<JobStatus>('GET', handle.statusUrl);\n assertString(status.state, 'JobStatus.state');\n if (status.events !== undefined && onEvent !== undefined) {\n for (const e of status.events) onEvent(e);\n }\n if (status.state === 'complete') {\n if (status.result === undefined) {\n throw new ServerError({ code: 500, message: 'Job complete but no result returned' });\n }\n return status.result;\n }\n if (status.state === 'error') {\n throw errorFromBody({\n code: status.errorCode ?? 500,\n message: status.errorMessage ?? 'Job failed',\n });\n }\n }\n }\n\n private async requestJson<T>(method: string, path: string, body?: object): Promise<T> {\n const isAbsolute = path.startsWith('http://') || path.startsWith('https://');\n const url = isAbsolute ? path : `${this.baseUrl}${path}`;\n const init: RequestInit = {\n method,\n headers: this.headers({\n accept: 'application/json',\n contentType: body !== undefined ? 'application/json' : undefined,\n }),\n };\n if (body !== undefined) init.body = JSON.stringify(body);\n const res = await this.fetchImpl(url, init);\n if (!res.ok) throw await this.errorFromResponse(res);\n const text = await res.text();\n if (text === '') {\n throw new ServerError({ code: 500, message: 'Empty response body' });\n }\n const parsed: T = JSON.parse(text);\n return parsed;\n }\n\n private headers(\n opts: { accept?: string; contentType?: string },\n endUserId?: string,\n ): Record<string, string> {\n const h: Record<string, string> = { authorization: `Bearer ${this.apiKey}` };\n if (opts.accept !== undefined) h['accept'] = opts.accept;\n if (opts.contentType !== undefined) h['content-type'] = opts.contentType;\n if (endUserId !== undefined && endUserId !== '') h['x-end-user-id'] = endUserId;\n return h;\n }\n\n private async errorFromResponse(res: Response): Promise<Error> {\n const text = await res.text();\n let body: ApiErrorBody;\n try {\n const parsed: ApiErrorBody | null = text === '' ? null : JSON.parse(text);\n body = parsed !== null && typeof parsed.code === 'number' && typeof parsed.message === 'string'\n ? parsed\n : {\n code: res.status,\n message: res.statusText !== '' ? res.statusText : 'HTTP error',\n };\n } catch {\n body = { code: res.status, message: text !== '' ? text : res.statusText };\n }\n const retryAfter = res.headers.get('retry-after');\n const err = errorFromBody(body);\n if (err.name === 'RateLimitedError' && retryAfter !== null) {\n const seconds = Number(retryAfter);\n if (Number.isFinite(seconds)) {\n Object.defineProperty(err, 'retryAfterSeconds', { value: seconds, enumerable: true });\n }\n }\n return err;\n }\n}\n\n/**\n * Parse one SSE `data:` line into the canonical `SSEEvent` union.\n * The server is the trusted emitter, so we validate only the envelope\n * (object with string `type` and numeric `timestamp`) and cast to the\n * discriminated union. Malformed lines are ignored.\n */\nfunction parseSseEvent(dataLine: string): SSEEvent | null {\n if (dataLine === '') return null;\n let payload;\n try {\n payload = JSON.parse(dataLine);\n } catch {\n return null;\n }\n if (payload === null || typeof payload !== 'object' || Array.isArray(payload)) return null;\n if (typeof payload.type !== 'string' || typeof payload.timestamp !== 'number') return null;\n return payload as SSEEvent;\n}\n\nfunction assertString(v: string | undefined, name: string): asserts v is string {\n if (typeof v !== 'string' || v === '') {\n throw new ServerError({ code: 500, message: `Malformed server response: ${name} is not a string` });\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n"]}
1
+ {"version":3,"sources":["../../src/types.ts","../../src/client/errors.ts","../../src/client/sseParser.ts","../../src/client/AlmadarClient.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Public SDK types. Canonical schema / payload types come from `@almadar/core`;\n * the SDK adds the HTTP-layer option shapes and re-exports the canonical SSE\n * event union.\n */\n\nimport type { EntityData, EventPayload, OrbitalSchema, SSEEvent } from '@almadar/core';\n\nexport type { EntityData, EventPayload, OrbitalSchema, SSEEvent };\n\n/**\n * Typed request envelope for `createGenerateHandler`.\n * Body shape: `{ prompt: string; endUserId?: string; appId?: string }`\n */\nexport interface GenerateRequest {\n prompt?: string;\n /** Alias accepted alongside `prompt`. */\n message?: string;\n endUserId?: string;\n appId?: string;\n}\n\n/**\n * Typed request envelope for `createEditHandler`.\n * Body shape: `{ appId: string; patch: EditSchemaPatch }`\n */\nexport interface EditSchemaRequest {\n appId?: string;\n patch?: EditSchemaPatch;\n}\n\n/**\n * Server-emitted error envelope. `code` maps to the SDK error subclasses:\n * 4001 → ApiKeyError, 4029 → RateLimitedError, 4040 → CatalogOutOfScopeError,\n * 4041-4045 → PinError, 4060 → AsyncUnsupportedError, 5001 → GenerationFailedError.\n * See `API_ERROR_CODES` for the full code table.\n */\nexport interface ApiErrorBody {\n code: number;\n message: string;\n details?: EventPayload;\n}\n\nexport const CATALOG_MODES = ['extend', 'subset', 'replace'] as const;\nexport type CatalogMode = (typeof CATALOG_MODES)[number];\n\n/**\n * Pin generation to a specific organism (and, when the organism has more than\n * one factory orbital, the orbital to use). `knobs` fills factory config.\n */\nexport interface GeneratePin {\n organism: string;\n /** Required iff the organism has more than one orbital. */\n orbital?: string;\n appName?: string;\n knobs?: Record<string, string | number | boolean>;\n}\n\n/** Which cache tier served the generation — L1 confirmed factory HIT, HIT-fail demote, or free-compose MISS. */\nexport type GenerationTier = 'confirmed' | 'hit' | 'miss';\n\nexport interface GenerateMetaOrganism {\n name: string;\n source: 'factory' | 'free-lolo';\n}\n\nexport interface GenerateMeta {\n tier: GenerationTier;\n organisms: GenerateMetaOrganism[];\n /** Organism names that HIT-failed and were demoted to free-compose. */\n demoted: string[];\n cacheVerdict: { verdict: 'hit' | 'miss'; chosen: string | null } | null;\n durationMs: number;\n}\n\nexport interface GenerationMetaEvent {\n type: 'generation_meta';\n data: GenerateMeta;\n timestamp: number;\n}\n\n/** Canonical SSE events plus the SDK-only `generation_meta` summary event. */\nexport type GenerateStreamEvent = SSEEvent | GenerationMetaEvent;\n\nfunction isGenerateMetaOrganism(value: unknown): value is GenerateMetaOrganism {\n if (value === null || typeof value !== 'object') return false;\n const v = value as { name?: unknown; source?: unknown };\n if (typeof v.name !== 'string') return false;\n return v.source === 'factory' || v.source === 'free-lolo';\n}\n\nfunction isGenerateMetaCacheVerdict(value: unknown): value is GenerateMeta['cacheVerdict'] {\n if (value === null) return true;\n if (typeof value !== 'object') return false;\n const v = value as { verdict?: unknown; chosen?: unknown };\n if (v.verdict !== 'hit' && v.verdict !== 'miss') return false;\n return v.chosen === null || typeof v.chosen === 'string';\n}\n\n/** Runtime guard for the `generation_meta` SSE payload — the zero-cast bridge from JSON. */\nexport function isGenerateMeta(value: unknown): value is GenerateMeta {\n if (value === null || typeof value !== 'object') return false;\n const v = value as {\n tier?: unknown;\n organisms?: unknown;\n demoted?: unknown;\n cacheVerdict?: unknown;\n durationMs?: unknown;\n };\n if (v.tier !== 'confirmed' && v.tier !== 'hit' && v.tier !== 'miss') return false;\n if (!Array.isArray(v.organisms) || !v.organisms.every(isGenerateMetaOrganism)) return false;\n if (!Array.isArray(v.demoted) || !v.demoted.every((d) => typeof d === 'string')) return false;\n if (!isGenerateMetaCacheVerdict(v.cacheVerdict)) return false;\n return typeof v.durationMs === 'number';\n}\n\nexport const API_ERROR_CODES = {\n INVALID_REQUEST: 4000,\n API_KEY: 4001,\n ORIGIN_FORBIDDEN: 4003,\n EDIT_CONFIRM_REQUIRED: 4009,\n RATE_LIMITED: 4029,\n CATALOG_OUT_OF_SCOPE: 4040,\n PIN_UNKNOWN_ORGANISM: 4041,\n PIN_OUT_OF_SCOPE: 4042,\n PIN_CONFLICT: 4043,\n PIN_UNKNOWN_KNOB: 4044,\n PIN_ORBITAL_REQUIRED: 4045,\n ASYNC_UNSUPPORTED: 4060,\n FOCUS_STALE: 4090,\n SERVER: 5000,\n GENERATION_FAILED: 5001,\n RUNTIME: 5002,\n WORKSPACE_OPEN: 5003,\n AI_UNCONFIGURED: 5030,\n} as const;\nexport type ApiErrorCode = (typeof API_ERROR_CODES)[keyof typeof API_ERROR_CODES];\n\n/** `error` event `code` values on the generate SSE stream. */\nexport const STREAM_ERROR_CODES = ['failed', 'runtime', 'workspace_open', 'ai_unconfigured', 'focus_stale'] as const;\nexport type StreamErrorCode = (typeof STREAM_ERROR_CODES)[number];\n\nexport interface GenerateOptions {\n prompt: string;\n endUserId?: string;\n appId?: string;\n /** Streaming callback for canonical SSE events plus the SDK's `generation_meta` summary. */\n onEvent?: (event: GenerateStreamEvent) => void;\n /**\n * The client has no async job surface: passing `true` throws\n * `AsyncUnsupportedError` (code 4060) before any network call is made.\n * For long-running generations use the default streaming mode with `onEvent`.\n */\n async?: boolean;\n /**\n * Agent provider override (e.g. 'deepseek', 'openai').\n * Omit to use the server's default.\n */\n provider?: string;\n /**\n * Agent model override (e.g. 'deepseek-chat').\n * Omit to use the server's default.\n */\n model?: string;\n /**\n * Behavior catalog mode — 'subset' narrows generation to stdAllowList.\n * Server-specific; omit if the agent does not support it.\n */\n catalogMode?: CatalogMode;\n /**\n * Allow-list of std behavior names. Requires a server that supports catalog\n * narrowing (e.g. the builder Rabit/Studio agent).\n */\n stdAllowList?: string[];\n /** Pin generation to a specific organism/orbital instead of free-composing. */\n pin?: GeneratePin;\n}\n\nexport interface GenerateResult {\n schema: OrbitalSchema;\n appId?: string;\n /** Absent for third-party servers built with `createGenerateHandler` that don't emit `generation_meta`. */\n meta?: GenerateMeta;\n}\n\n/**\n * Body of a `PUT /api/v1/agent/edit-schema`. Strictly structural; the SDK\n * does not deep-type the patch — that's the server's job. Field types are\n * `EventPayload`-compatible so callers can't sneak in arbitrary objects.\n */\nexport interface EditSchemaPatch {\n orbital?: string;\n traitOverrides?: EventPayload;\n config?: EventPayload;\n}\n\nexport interface CompileOptions {\n target?: 'express' | 'hono';\n shell?: 'typescript' | 'python' | 'mobile';\n}\n\nexport interface CompileResult {\n downloadUrl: string;\n expiresAt: string;\n}\n\nexport interface AlmadarClientOptions {\n apiKey: string;\n baseUrl?: string;\n fetch?: typeof fetch;\n}\n\n/**\n * Props for `<AlmadarApp />` — renders an orbital schema. The runtime mode\n * decides whether effects (persist/fetch/call-service) hit a backend or stay\n * mocked in-browser.\n */\nexport interface AlmadarAppProps {\n schema: OrbitalSchema;\n /**\n * - `static`: pure client-side, no server effects. Use with `data`.\n * - `mock` (default): in-browser fake server, faker-seeded if `data` is undefined.\n * - `server`: real backend at `serverUrl`.\n */\n mode?: 'static' | 'mock' | 'server';\n /** Seed data keyed by entity name (canonical `EntityData` shape). */\n data?: EntityData;\n /** Required when `mode === 'server'`. */\n serverUrl?: string;\n initialPagePath?: string;\n height?: string;\n className?: string;\n /**\n * Tiers of config knobs to surface as auto-derived controls. When provided,\n * a control rail is rendered next to the app. Omit to hide controls.\n * Common values: `['presentation']`, `['presentation', 'domain']`.\n */\n exposedTiers?: string[];\n /** Where to render the auto-derived controls rail. Default: 'right'. */\n controlsPosition?: 'right' | 'bottom';\n /**\n * Explicit override for whether the config-controls rail renders. When\n * omitted, falls back to legacy behavior: `exposedTiers` non-empty and\n * `mode !== 'server'`.\n */\n showControls?: boolean;\n}\n\n/**\n * Props for `<OrbitalConfigPanel />` — low-level control rail used by\n * `<AlmadarApp />` when `exposedTiers` is set.\n */\nexport interface OrbitalConfigPanelProps {\n schema: string | OrbitalSchema;\n exposedTiers?: string[];\n position?: 'right' | 'bottom';\n onSchemaChange?: (schema: OrbitalSchema) => void;\n}\n","/**\n * Typed SDK errors. Server emits a structured `ApiErrorBody`; the HTTP layer\n * maps the `code` to one of these subclasses. Customers `catch` by class.\n */\n\nimport { API_ERROR_CODES, STREAM_ERROR_CODES } from '../types';\nimport type { ApiErrorBody, StreamErrorCode } from '../types';\n\nexport class AlmadarError extends Error {\n readonly code: number;\n readonly details?: ApiErrorBody['details'];\n constructor(body: ApiErrorBody) {\n super(body.message);\n this.name = 'AlmadarError';\n this.code = body.code;\n this.details = body.details;\n }\n}\n\n/** 4001 — invalid, revoked, or missing API key. */\nexport class ApiKeyError extends AlmadarError {\n constructor(body: ApiErrorBody) {\n super(body);\n this.name = 'ApiKeyError';\n }\n}\n\n/** 4029 — team cap (feature counter) exceeded. Retry after a billing cycle. */\nexport class RateLimitedError extends AlmadarError {\n readonly retryAfterSeconds?: number;\n constructor(body: ApiErrorBody, retryAfterSeconds?: number) {\n super(body);\n this.name = 'RateLimitedError';\n this.retryAfterSeconds = retryAfterSeconds;\n }\n}\n\n/** 4040 — the team's behavior catalog (subset/replace mode) cannot serve the request. */\nexport class CatalogOutOfScopeError extends AlmadarError {\n constructor(body: ApiErrorBody) {\n super(body);\n this.name = 'CatalogOutOfScopeError';\n }\n}\n\n/** Anything else from the server with a recognized envelope but no specific subclass. */\nexport class ServerError extends AlmadarError {\n constructor(body: ApiErrorBody) {\n super(body);\n this.name = 'ServerError';\n }\n}\n\n/** 4041-4045 — pin resolution failed: unknown organism, out-of-scope, conflicting pins, unknown knob, or a missing required orbital. */\nexport class PinError extends AlmadarError {\n constructor(body: ApiErrorBody) {\n super(body);\n this.name = 'PinError';\n }\n}\n\n/** 4060 — `generate({ async: true })` has no server-side job surface; use the default streaming mode instead. */\nexport class AsyncUnsupportedError extends AlmadarError {\n constructor(body: ApiErrorBody) {\n super(body);\n this.name = 'AsyncUnsupportedError';\n }\n}\n\n/** 5001 — generation failed server-side. */\nexport class GenerationFailedError extends AlmadarError {\n constructor(body: ApiErrorBody) {\n super(body);\n this.name = 'GenerationFailedError';\n }\n}\n\nexport function errorFromBody(body: ApiErrorBody): AlmadarError {\n switch (body.code) {\n case API_ERROR_CODES.API_KEY:\n return new ApiKeyError(body);\n case API_ERROR_CODES.RATE_LIMITED:\n return new RateLimitedError(body);\n case API_ERROR_CODES.CATALOG_OUT_OF_SCOPE:\n return new CatalogOutOfScopeError(body);\n case API_ERROR_CODES.PIN_UNKNOWN_ORGANISM:\n case API_ERROR_CODES.PIN_OUT_OF_SCOPE:\n case API_ERROR_CODES.PIN_CONFLICT:\n case API_ERROR_CODES.PIN_UNKNOWN_KNOB:\n case API_ERROR_CODES.PIN_ORBITAL_REQUIRED:\n return new PinError(body);\n case API_ERROR_CODES.ASYNC_UNSUPPORTED:\n return new AsyncUnsupportedError(body);\n case API_ERROR_CODES.GENERATION_FAILED:\n return new GenerationFailedError(body);\n default:\n return new ServerError(body);\n }\n}\n\nfunction isStreamErrorCode(code: string | undefined): code is StreamErrorCode {\n if (code === undefined) return false;\n return STREAM_ERROR_CODES.some((c) => c === code);\n}\n\n/** Maps a `generate` SSE `error` event's `{ error, code }` payload to a typed SDK error. */\nexport function streamErrorFromEvent(data: { error: string; code?: string }): AlmadarError {\n const message = data.error;\n if (!isStreamErrorCode(data.code)) {\n return new ServerError({ code: API_ERROR_CODES.SERVER, message });\n }\n switch (data.code) {\n case 'failed':\n return new GenerationFailedError({ code: API_ERROR_CODES.GENERATION_FAILED, message });\n case 'ai_unconfigured':\n return new ServerError({ code: API_ERROR_CODES.AI_UNCONFIGURED, message });\n case 'workspace_open':\n return new ServerError({ code: API_ERROR_CODES.WORKSPACE_OPEN, message });\n case 'focus_stale':\n return new ServerError({ code: API_ERROR_CODES.FOCUS_STALE, message });\n case 'runtime':\n return new ServerError({ code: API_ERROR_CODES.RUNTIME, message });\n }\n}\n","/**\n * Minimal Server-Sent Events parser. Reads a `ReadableStream<Uint8Array>`\n * (the body of a `fetch` Response) and yields decoded events. Universal:\n * works in browser, Node 18+, Deno, Bun.\n *\n * Spec subset implemented:\n * - `event:` and `data:` fields\n * - dispatch on blank line\n * - newline-tolerant (CRLF + LF)\n * - skips comments (`:`-prefixed lines)\n *\n * Not implemented (we don't need them):\n * - `id:` / `retry:` fields\n * - reconnection / last-event-id\n */\n\nexport interface RawSseEvent {\n /** `event:` field value. Empty string when absent — matches the spec default. */\n event: string;\n /** Concatenated `data:` lines, joined by newlines. */\n data: string;\n}\n\nexport async function* parseSSE(\n stream: ReadableStream<Uint8Array>,\n): AsyncGenerator<RawSseEvent, void, void> {\n const reader = stream.getReader();\n const decoder = new TextDecoder('utf-8');\n let buffer = '';\n let currentEvent = '';\n let currentData = '';\n\n try {\n for (;;) {\n const { value, done } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n\n let newlineIdx: number;\n while ((newlineIdx = indexOfNewline(buffer)) !== -1) {\n const rawLine = buffer.slice(0, newlineIdx);\n buffer = buffer.slice(newlineIdx + (buffer[newlineIdx] === '\\r' && buffer[newlineIdx + 1] === '\\n' ? 2 : 1));\n\n if (rawLine === '') {\n if (currentData !== '' || currentEvent !== '') {\n yield { event: currentEvent, data: currentData };\n currentEvent = '';\n currentData = '';\n }\n continue;\n }\n if (rawLine.startsWith(':')) continue;\n\n const colon = rawLine.indexOf(':');\n const field = colon === -1 ? rawLine : rawLine.slice(0, colon);\n const rawValue = colon === -1 ? '' : rawLine.slice(colon + 1);\n const value2 = rawValue.startsWith(' ') ? rawValue.slice(1) : rawValue;\n\n if (field === 'event') {\n currentEvent = value2;\n } else if (field === 'data') {\n currentData = currentData === '' ? value2 : `${currentData}\\n${value2}`;\n }\n }\n }\n if (currentData !== '' || currentEvent !== '') {\n yield { event: currentEvent, data: currentData };\n }\n } finally {\n reader.releaseLock();\n }\n}\n\nfunction indexOfNewline(s: string): number {\n for (let i = 0; i < s.length; i += 1) {\n const c = s[i];\n if (c === '\\n' || c === '\\r') return i;\n }\n return -1;\n}\n","/**\n * `AlmadarClient` — server / Node-side HTTP client targeting `/api/v1/agent/*`.\n * Authenticates with a team-bound API key (`sk_*`) issued from\n * Studio's `/settings/sdk` panel. See `docs/Almadar_Studio_SDK.md` §5.\n *\n * Never instantiate this in a browser bundle — `apiKey` must never leave\n * the customer's server.\n */\n\nimport { parseOrbitalSchema, type OrbitalSchema, type SSEEvent } from '@almadar/core';\nimport { API_ERROR_CODES, isGenerateMeta } from '../types';\nimport type {\n AlmadarClientOptions,\n ApiErrorBody,\n CompileOptions,\n CompileResult,\n EditSchemaPatch,\n GenerateMeta,\n GenerateOptions,\n GenerateResult,\n GenerateStreamEvent,\n} from '../types';\nimport { AsyncUnsupportedError, errorFromBody, ServerError, streamErrorFromEvent } from './errors';\nimport { parseSSE } from './sseParser';\n\nconst DEFAULT_BASE_URL = 'https://studio.almadar.io';\n\nexport class AlmadarClient {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly fetchImpl: typeof fetch;\n\n constructor(opts: AlmadarClientOptions) {\n if (!opts.apiKey || typeof opts.apiKey !== 'string') {\n throw new Error('AlmadarClient: opts.apiKey is required');\n }\n this.apiKey = opts.apiKey;\n this.baseUrl = (opts.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/$/, '');\n this.fetchImpl = opts.fetch ?? globalThis.fetch;\n if (typeof this.fetchImpl !== 'function') {\n throw new Error('AlmadarClient: no fetch available — pass opts.fetch for Node <18');\n }\n }\n\n async generate(input: GenerateOptions): Promise<GenerateResult> {\n if (input.async === true) {\n throw new AsyncUnsupportedError({\n code: API_ERROR_CODES.ASYNC_UNSUPPORTED,\n message: 'AlmadarClient has no async job surface. Omit `async` (or pass false) and consume the streaming response via `onEvent` instead.',\n });\n }\n return this.streamGenerate(input);\n }\n\n async editSchema(appId: string, patch: EditSchemaPatch): Promise<OrbitalSchema> {\n if (!appId) throw new Error('AlmadarClient.editSchema: appId is required');\n const schema = await this.requestJson<OrbitalSchema>('PUT', '/api/v1/agent/edit-schema', {\n appId,\n patch,\n });\n assertString(schema.name, 'OrbitalSchema.name');\n return schema;\n }\n\n async compileToApp(schema: OrbitalSchema, opts?: CompileOptions): Promise<CompileResult> {\n const result = await this.requestJson<CompileResult>('POST', '/api/v1/agent/compile', {\n schema,\n target: opts?.target,\n shell: opts?.shell,\n });\n assertString(result.downloadUrl, 'CompileResult.downloadUrl');\n assertString(result.expiresAt, 'CompileResult.expiresAt');\n return result;\n }\n\n private async streamGenerate(input: GenerateOptions): Promise<GenerateResult> {\n const res = await this.fetchImpl(`${this.baseUrl}/api/v1/agent/generate`, {\n method: 'POST',\n headers: this.headers({ accept: 'text/event-stream', contentType: 'application/json' }, input.endUserId),\n body: JSON.stringify({\n prompt: input.prompt,\n endUserId: input.endUserId,\n appId: input.appId,\n provider: input.provider,\n model: input.model,\n catalogMode: input.catalogMode,\n stdAllowList: input.stdAllowList,\n pin: input.pin,\n }),\n });\n if (!res.ok) throw await this.errorFromResponse(res);\n if (res.body === null) throw new Error('AlmadarClient.generate: server returned no body');\n\n let final: GenerateResult | null = null;\n let meta: GenerateMeta | undefined;\n for await (const raw of parseSSE(res.body)) {\n const event = parseSseEvent(raw.data);\n if (event === null) continue;\n input.onEvent?.(event);\n if (event.type === 'generation_meta') {\n meta = event.data;\n } else if (event.type === 'complete') {\n if (event.data.schema === undefined) {\n throw new ServerError({ code: API_ERROR_CODES.SERVER, message: '`complete` event did not contain a schema' });\n }\n const schema = parseOrbitalSchema(event.data.schema);\n final = { schema, appId: event.data.appId, meta };\n } else if (event.type === 'error') {\n throw streamErrorFromEvent(event.data);\n }\n }\n if (final === null) {\n throw new ServerError({ code: API_ERROR_CODES.SERVER, message: 'SSE stream ended without `complete` event' });\n }\n return final;\n }\n\n private async requestJson<T>(method: string, path: string, body?: object): Promise<T> {\n const isAbsolute = path.startsWith('http://') || path.startsWith('https://');\n const url = isAbsolute ? path : `${this.baseUrl}${path}`;\n const init: RequestInit = {\n method,\n headers: this.headers({\n accept: 'application/json',\n contentType: body !== undefined ? 'application/json' : undefined,\n }),\n };\n if (body !== undefined) init.body = JSON.stringify(body);\n const res = await this.fetchImpl(url, init);\n if (!res.ok) throw await this.errorFromResponse(res);\n const text = await res.text();\n if (text === '') {\n throw new ServerError({ code: API_ERROR_CODES.SERVER, message: 'Empty response body' });\n }\n const parsed: T = JSON.parse(text);\n return parsed;\n }\n\n private headers(\n opts: { accept?: string; contentType?: string },\n endUserId?: string,\n ): Record<string, string> {\n const h: Record<string, string> = { authorization: `Bearer ${this.apiKey}` };\n if (opts.accept !== undefined) h['accept'] = opts.accept;\n if (opts.contentType !== undefined) h['content-type'] = opts.contentType;\n if (endUserId !== undefined && endUserId !== '') h['x-end-user-id'] = endUserId;\n return h;\n }\n\n private async errorFromResponse(res: Response): Promise<Error> {\n const text = await res.text();\n let body: ApiErrorBody;\n try {\n const parsed: ApiErrorBody | null = text === '' ? null : JSON.parse(text);\n body = parsed !== null && typeof parsed.code === 'number' && typeof parsed.message === 'string'\n ? parsed\n : {\n code: res.status,\n message: res.statusText !== '' ? res.statusText : 'HTTP error',\n };\n } catch {\n body = { code: res.status, message: text !== '' ? text : res.statusText };\n }\n const retryAfter = res.headers.get('retry-after');\n const err = errorFromBody(body);\n if (err.name === 'RateLimitedError' && retryAfter !== null) {\n const seconds = Number(retryAfter);\n if (Number.isFinite(seconds)) {\n Object.defineProperty(err, 'retryAfterSeconds', { value: seconds, enumerable: true });\n }\n }\n return err;\n }\n}\n\n/**\n * Parse one SSE `data:` line into the `GenerateStreamEvent` union. The server\n * is the trusted emitter, so we validate only the envelope (object with\n * string `type` and numeric `timestamp`) and cast to the canonical `SSEEvent`\n * union — except `generation_meta`, which is SDK-only and goes through the\n * `isGenerateMeta` runtime guard instead of a cast. Malformed lines are ignored.\n */\nfunction parseSseEvent(dataLine: string): GenerateStreamEvent | null {\n if (dataLine === '') return null;\n let payload;\n try {\n payload = JSON.parse(dataLine);\n } catch {\n return null;\n }\n if (payload === null || typeof payload !== 'object' || Array.isArray(payload)) return null;\n if (typeof payload.type !== 'string' || typeof payload.timestamp !== 'number') return null;\n if (payload.type === 'generation_meta') {\n return isGenerateMeta(payload.data)\n ? { type: 'generation_meta', data: payload.data, timestamp: payload.timestamp }\n : null;\n }\n return payload as SSEEvent;\n}\n\nfunction assertString(v: string | undefined, name: string): asserts v is string {\n if (typeof v !== 'string' || v === '') {\n throw new ServerError({ code: API_ERROR_CODES.SERVER, message: `Malformed server response: ${name} is not a string` });\n }\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- export { A as AlmadarApp } from './AlmadarApp-DgwtnIRy.js';
1
+ export { A as AlmadarApp } from './AlmadarApp-mS7H6kiA.js';
2
2
  export { useEventBus as useOrbBus } from '@almadar/ui/hooks';
3
- export { AlmadarClient, AlmadarError, ApiKeyError, CatalogOutOfScopeError, RateLimitedError, ServerError } from './client/index.js';
4
- export { A as AlmadarAppProps, a as AlmadarClientOptions, b as ApiErrorBody, c as AsyncJobHandle, C as CompileOptions, d as CompileResult, E as EditSchemaPatch, G as GenerateOptions, e as GenerateResult } from './types-C6RJADoY.js';
3
+ export { AlmadarClient, AlmadarError, ApiKeyError, AsyncUnsupportedError, CatalogOutOfScopeError, GenerationFailedError, PinError, RateLimitedError, ServerError, streamErrorFromEvent } from './client/index.js';
4
+ export { A as API_ERROR_CODES, a as AlmadarAppProps, b as AlmadarClientOptions, c as ApiErrorBody, d as ApiErrorCode, C as CATALOG_MODES, e as CatalogMode, f as CompileOptions, g as CompileResult, E as EditSchemaPatch, G as GenerateMeta, h as GenerateMetaOrganism, i as GenerateOptions, j as GeneratePin, k as GenerateResult, l as GenerateStreamEvent, m as GenerationMetaEvent, n as GenerationTier, S as STREAM_ERROR_CODES, o as StreamErrorCode, p as isGenerateMeta } from './types-CVGXdQRM.js';
5
5
  export { EntityData, EventPayload, OrbitalSchema, SSEEvent } from '@almadar/core';
6
6
  import 'react';