@almadar/sdk 0.1.0-alpha.4 → 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.
@@ -1,3 +1,7 @@
1
+ import { parseOrbitalSchema } from '@almadar/core';
2
+
3
+ // src/client/AlmadarClient.ts
4
+
1
5
  // src/client/errors.ts
2
6
  var AlmadarError = class extends Error {
3
7
  code;
@@ -124,7 +128,11 @@ var AlmadarClient = class {
124
128
  prompt: input.prompt,
125
129
  endUserId: input.endUserId,
126
130
  appId: input.appId,
127
- async: true
131
+ async: true,
132
+ provider: input.provider,
133
+ model: input.model,
134
+ catalogMode: input.catalogMode,
135
+ stdAllowList: input.stdAllowList
128
136
  });
129
137
  assertString(handle.jobId, "AsyncJobHandle.jobId");
130
138
  assertString(handle.statusUrl, "AsyncJobHandle.statusUrl");
@@ -158,20 +166,28 @@ var AlmadarClient = class {
158
166
  body: JSON.stringify({
159
167
  prompt: input.prompt,
160
168
  endUserId: input.endUserId,
161
- appId: input.appId
169
+ appId: input.appId,
170
+ provider: input.provider,
171
+ model: input.model,
172
+ catalogMode: input.catalogMode,
173
+ stdAllowList: input.stdAllowList
162
174
  })
163
175
  });
164
176
  if (!res.ok) throw await this.errorFromResponse(res);
165
177
  if (res.body === null) throw new Error("AlmadarClient.generate: server returned no body");
166
178
  let final = null;
167
179
  for await (const raw of parseSSE(res.body)) {
168
- const event = parseAgentEvent(raw.event, raw.data);
180
+ const event = parseSseEvent(raw.data);
169
181
  if (event === null) continue;
170
182
  input.onEvent?.(event);
171
183
  if (event.type === "complete") {
172
- final = { schema: event.schema, appId: event.appId };
184
+ if (event.data.schema === void 0) {
185
+ throw new ServerError({ code: 500, message: "`complete` event did not contain a schema" });
186
+ }
187
+ const schema = parseOrbitalSchema(event.data.schema);
188
+ final = { schema, appId: event.data.appId };
173
189
  } else if (event.type === "error") {
174
- throw errorFromBody({ code: event.code ?? 500, message: event.message });
190
+ throw errorFromBody({ code: 500, message: event.data.error });
175
191
  }
176
192
  }
177
193
  if (final === null) {
@@ -254,7 +270,7 @@ var AlmadarClient = class {
254
270
  return err;
255
271
  }
256
272
  };
257
- function parseAgentEvent(eventName, dataLine) {
273
+ function parseSseEvent(dataLine) {
258
274
  if (dataLine === "") return null;
259
275
  let payload;
260
276
  try {
@@ -262,11 +278,9 @@ function parseAgentEvent(eventName, dataLine) {
262
278
  } catch {
263
279
  return null;
264
280
  }
265
- if (payload === null || typeof payload !== "object") return null;
266
- if (typeof payload.type === "string") return payload;
267
- if (eventName === "") return null;
268
- const synthesized = Object.assign(payload, { type: eventName });
269
- return synthesized;
281
+ if (payload === null || typeof payload !== "object" || Array.isArray(payload)) return null;
282
+ if (typeof payload.type !== "string" || typeof payload.timestamp !== "number") return null;
283
+ return payload;
270
284
  }
271
285
  function assertString(v, name) {
272
286
  if (typeof v !== "string" || v === "") {
@@ -280,68 +294,110 @@ function sleep(ms) {
280
294
  // src/server/index.ts
281
295
  function resolveEndUserId(opts, req) {
282
296
  if (opts.endUserId) return opts.endUserId(req);
283
- const header = req.headers["x-user-id"];
297
+ const header = req.headers.get("x-user-id");
284
298
  return typeof header === "string" && header.length > 0 ? header : void 0;
285
299
  }
286
- function writeSseEvent(res, event) {
287
- res.write(`data: ${JSON.stringify(event)}
300
+ function encodeSseEvent(event) {
301
+ return `data: ${JSON.stringify(event)}
288
302
 
289
- `);
303
+ `;
290
304
  }
291
305
  function createGenerateHandler(opts) {
292
- return async (req, res) => {
293
- const body = req.body;
306
+ return async (request) => {
307
+ let body;
308
+ try {
309
+ body = await request.json();
310
+ } catch {
311
+ return new Response(JSON.stringify({ error: "invalid JSON body" }), {
312
+ status: 400,
313
+ headers: { "content-type": "application/json" }
314
+ });
315
+ }
294
316
  const rawPrompt = body.prompt ?? body.message;
295
317
  const prompt = typeof rawPrompt === "string" ? rawPrompt : "";
296
318
  if (!prompt) {
297
- res.status(400).json({ error: "prompt or message is required" });
298
- return;
319
+ return new Response(JSON.stringify({ error: "prompt or message is required" }), {
320
+ status: 400,
321
+ headers: { "content-type": "application/json" }
322
+ });
299
323
  }
300
324
  const bodyEndUserId = typeof body.endUserId === "string" ? body.endUserId : void 0;
301
- const endUserId = bodyEndUserId ?? resolveEndUserId(opts, req);
325
+ const endUserId = bodyEndUserId ?? resolveEndUserId(opts, request);
302
326
  const appId = typeof body.appId === "string" ? body.appId : void 0;
303
- res.setHeader("Content-Type", "text/event-stream");
304
- res.setHeader("Cache-Control", "no-cache");
305
- res.setHeader("Connection", "keep-alive");
306
327
  const client = new AlmadarClient({ apiKey: opts.apiKey, baseUrl: opts.baseUrl });
307
- try {
308
- await client.generate({
309
- prompt,
310
- endUserId,
311
- appId,
312
- onEvent: (event) => {
313
- writeSseEvent(res, event);
328
+ const stream = new ReadableStream({
329
+ async start(controller) {
330
+ const encoder = new TextEncoder();
331
+ try {
332
+ await client.generate({
333
+ prompt,
334
+ endUserId,
335
+ appId,
336
+ onEvent: (event) => {
337
+ controller.enqueue(encoder.encode(encodeSseEvent(event)));
338
+ }
339
+ });
340
+ } catch (err) {
341
+ const message = err instanceof Error ? err.message : String(err);
342
+ const errorEvent = {
343
+ type: "error",
344
+ timestamp: Date.now(),
345
+ data: { error: message }
346
+ };
347
+ controller.enqueue(encoder.encode(encodeSseEvent(errorEvent)));
348
+ } finally {
349
+ controller.close();
314
350
  }
315
- });
316
- } catch (err) {
317
- const message = err instanceof Error ? err.message : String(err);
318
- const errorEvent = { type: "error", message };
319
- writeSseEvent(res, errorEvent);
320
- } finally {
321
- res.end();
322
- }
351
+ }
352
+ });
353
+ return new Response(stream, {
354
+ status: 200,
355
+ headers: {
356
+ "content-type": "text/event-stream",
357
+ "cache-control": "no-cache",
358
+ connection: "keep-alive"
359
+ }
360
+ });
323
361
  };
324
362
  }
325
363
  function createEditHandler(opts) {
326
- return async (req, res) => {
327
- const body = req.body;
364
+ return async (request) => {
365
+ let body;
366
+ try {
367
+ body = await request.json();
368
+ } catch {
369
+ return new Response(JSON.stringify({ error: "invalid JSON body" }), {
370
+ status: 400,
371
+ headers: { "content-type": "application/json" }
372
+ });
373
+ }
328
374
  const appId = typeof body.appId === "string" ? body.appId : "";
329
375
  if (!appId) {
330
- res.status(400).json({ error: "appId is required" });
331
- return;
376
+ return new Response(JSON.stringify({ error: "appId is required" }), {
377
+ status: 400,
378
+ headers: { "content-type": "application/json" }
379
+ });
332
380
  }
333
381
  const patch = body.patch;
334
382
  if (patch === void 0 || patch === null || typeof patch !== "object") {
335
- res.status(400).json({ error: "patch is required" });
336
- return;
383
+ return new Response(JSON.stringify({ error: "patch is required" }), {
384
+ status: 400,
385
+ headers: { "content-type": "application/json" }
386
+ });
337
387
  }
338
388
  const client = new AlmadarClient({ apiKey: opts.apiKey, baseUrl: opts.baseUrl });
339
389
  try {
340
390
  const schema = await client.editSchema(appId, patch);
341
- res.json(schema);
391
+ return new Response(JSON.stringify(schema), {
392
+ status: 200,
393
+ headers: { "content-type": "application/json" }
394
+ });
342
395
  } catch (err) {
343
396
  const message = err instanceof Error ? err.message : String(err);
344
- res.status(500).json({ error: message });
397
+ return new Response(JSON.stringify({ error: message }), {
398
+ status: 500,
399
+ headers: { "content-type": "application/json" }
400
+ });
345
401
  }
346
402
  };
347
403
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/client/errors.ts","../../src/client/sseParser.ts","../../src/client/AlmadarClient.ts","../../src/server/index.ts"],"names":[],"mappings":"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","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 type { OrbitalSchema } from '@almadar/core';\nimport type {\n AgentEvent,\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 AgentEvent[];\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 });\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 }),\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 = parseAgentEvent(raw.event, raw.data);\n if (event === null) continue;\n input.onEvent?.(event);\n if (event.type === 'complete') {\n final = { schema: event.schema, appId: event.appId };\n } else if (event.type === 'error') {\n throw errorFromBody({ code: event.code ?? 500, message: event.message });\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\nfunction parseAgentEvent(eventName: string, dataLine: string): AgentEvent | null {\n if (dataLine === '') return null;\n let payload: AgentEvent | null;\n try {\n payload = JSON.parse(dataLine);\n } catch {\n return null;\n }\n if (payload === null || typeof payload !== 'object') return null;\n if (typeof payload.type === 'string') return payload;\n if (eventName === '') return null;\n // Server sent only an `event:` field name — write `type` onto the payload.\n // Mutating the parsed result is safe because we own it.\n const synthesized: AgentEvent & { type: string } = Object.assign(payload, { type: eventName });\n return synthesized;\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","/**\n * `@almadar/sdk/server` — Express handler factories for the Almadar agent.\n *\n * Node-only. Never import this from browser or React code.\n *\n * Usage:\n * import { createGenerateHandler, createEditHandler } from '@almadar/sdk/server';\n */\n\nimport type { Request, Response } from 'express';\nimport type { OrbitalSchema } from '@almadar/core';\nimport { AlmadarClient } from '../client/AlmadarClient';\nimport type { AgentEvent, EditSchemaRequest, EditSchemaPatch, GenerateRequest } from '../types';\n\n// ============================================================================\n// Public option surface\n// ============================================================================\n\nexport interface GenerateHandlerOptions {\n /** API key issued from Studio's /settings/sdk panel. */\n apiKey: string;\n /** Defaults to https://studio.almadar.io. */\n baseUrl?: string;\n /** Derive a stable end-user id from the request. */\n endUserId?: (req: Request) => string;\n}\n\n// ============================================================================\n// Internal helpers\n// ============================================================================\n\nfunction resolveEndUserId(opts: GenerateHandlerOptions, req: Request): string | undefined {\n if (opts.endUserId) return opts.endUserId(req);\n const header = req.headers['x-user-id'];\n return typeof header === 'string' && header.length > 0 ? header : undefined;\n}\n\nfunction writeSseEvent(res: Response, event: AgentEvent): void {\n res.write(`data: ${JSON.stringify(event)}\\n\\n`);\n}\n\n// ============================================================================\n// createGenerateHandler\n// ============================================================================\n\n/**\n * Returns an Express route handler that streams a generate call as SSE.\n *\n * Body shape accepted: `{ prompt: string; endUserId?: string; appId?: string }`\n */\nexport function createGenerateHandler(\n opts: GenerateHandlerOptions,\n): (req: Request, res: Response) => Promise<void> {\n return async (req: Request, res: Response): Promise<void> => {\n const body = req.body as GenerateRequest;\n const rawPrompt = body.prompt ?? body.message;\n const prompt = typeof rawPrompt === 'string' ? rawPrompt : '';\n\n if (!prompt) {\n res.status(400).json({ error: 'prompt or message is required' });\n return;\n }\n\n const bodyEndUserId = typeof body.endUserId === 'string' ? body.endUserId : undefined;\n const endUserId = bodyEndUserId ?? resolveEndUserId(opts, req);\n const appId = typeof body.appId === 'string' ? body.appId : undefined;\n\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n\n const client = new AlmadarClient({ apiKey: opts.apiKey, baseUrl: opts.baseUrl });\n\n try {\n await client.generate({\n prompt,\n endUserId,\n appId,\n onEvent: (event: AgentEvent) => {\n writeSseEvent(res, event);\n },\n });\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n const errorEvent: AgentEvent = { type: 'error', message };\n writeSseEvent(res, errorEvent);\n } finally {\n res.end();\n }\n };\n}\n\n// ============================================================================\n// createEditHandler\n// ============================================================================\n\n/**\n * Returns an Express route handler that calls `editSchema` and returns JSON.\n *\n * Body shape accepted: `{ appId: string; patch: EditSchemaPatch }`\n */\nexport function createEditHandler(\n opts: GenerateHandlerOptions,\n): (req: Request, res: Response) => Promise<void> {\n return async (req: Request, res: Response): Promise<void> => {\n const body = req.body as EditSchemaRequest;\n const appId = typeof body.appId === 'string' ? body.appId : '';\n\n if (!appId) {\n res.status(400).json({ error: 'appId is required' });\n return;\n }\n\n const patch: EditSchemaPatch | undefined = body.patch;\n if (patch === undefined || patch === null || typeof patch !== 'object') {\n res.status(400).json({ error: 'patch is required' });\n return;\n }\n\n const client = new AlmadarClient({ apiKey: opts.apiKey, baseUrl: opts.baseUrl });\n\n try {\n const schema: OrbitalSchema = await client.editSchema(appId, patch);\n res.json(schema);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n res.status(500).json({ error: message });\n }\n };\n}\n"]}
1
+ {"version":3,"sources":["../../src/client/errors.ts","../../src/client/sseParser.ts","../../src/client/AlmadarClient.ts","../../src/server/index.ts"],"names":[],"mappings":"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","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","/**\n * `@almadar/sdk/server` — Framework-agnostic Web-standard Fetch handlers for\n * the Almadar agent proxy. Node-only; never import from browser or React code.\n *\n * Usage:\n * import { createGenerateHandler, createEditHandler } from '@almadar/sdk/server';\n * const handler = createGenerateHandler({ apiKey: process.env.ALMADAR_API_KEY! });\n * // handler: (request: Request) => Promise<Response>\n *\n * For framework adapters see `@almadar/sdk/server/express` and `@almadar/sdk/server/hono`.\n */\n\nimport type { OrbitalSchema } from '@almadar/core';\nimport { AlmadarClient } from '../client/AlmadarClient';\nimport type { EditSchemaRequest, EditSchemaPatch, GenerateRequest, SSEEvent } from '../types';\n\n// ============================================================================\n// Public option surface\n// ============================================================================\n\nexport interface GenerateHandlerOptions {\n /** API key issued from Studio's /settings/sdk panel. */\n apiKey: string;\n /** Defaults to https://studio.almadar.io. */\n baseUrl?: string;\n /**\n * Derive a stable end-user id from the incoming Web Request.\n * Falls back to the `x-user-id` request header when omitted.\n */\n endUserId?: (req: Request) => string;\n}\n\n// ============================================================================\n// Internal helpers\n// ============================================================================\n\nfunction resolveEndUserId(opts: GenerateHandlerOptions, req: Request): string | undefined {\n if (opts.endUserId) return opts.endUserId(req);\n const header = req.headers.get('x-user-id');\n return typeof header === 'string' && header.length > 0 ? header : undefined;\n}\n\nfunction encodeSseEvent(event: SSEEvent): string {\n return `data: ${JSON.stringify(event)}\\n\\n`;\n}\n\n// ============================================================================\n// createGenerateHandler\n// ============================================================================\n\n/**\n * Returns a Web-standard Fetch handler that streams a generate call as SSE.\n *\n * Body shape accepted: `{ prompt: string; endUserId?: string; appId?: string }`\n */\nexport function createGenerateHandler(\n opts: GenerateHandlerOptions,\n): (request: Request) => Promise<Response> {\n return async (request: Request): Promise<Response> => {\n let body: GenerateRequest;\n try {\n body = (await request.json()) as GenerateRequest;\n } catch {\n return new Response(JSON.stringify({ error: 'invalid JSON body' }), {\n status: 400,\n headers: { 'content-type': 'application/json' },\n });\n }\n\n const rawPrompt = body.prompt ?? body.message;\n const prompt = typeof rawPrompt === 'string' ? rawPrompt : '';\n\n if (!prompt) {\n return new Response(JSON.stringify({ error: 'prompt or message is required' }), {\n status: 400,\n headers: { 'content-type': 'application/json' },\n });\n }\n\n const bodyEndUserId = typeof body.endUserId === 'string' ? body.endUserId : undefined;\n const endUserId = bodyEndUserId ?? resolveEndUserId(opts, request);\n const appId = typeof body.appId === 'string' ? body.appId : undefined;\n\n const client = new AlmadarClient({ apiKey: opts.apiKey, baseUrl: opts.baseUrl });\n\n const stream = new ReadableStream<Uint8Array>({\n async start(controller) {\n const encoder = new TextEncoder();\n try {\n await client.generate({\n prompt,\n endUserId,\n appId,\n onEvent: (event: SSEEvent) => {\n controller.enqueue(encoder.encode(encodeSseEvent(event)));\n },\n });\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n const errorEvent: SSEEvent = {\n type: 'error',\n timestamp: Date.now(),\n data: { error: message },\n };\n controller.enqueue(encoder.encode(encodeSseEvent(errorEvent)));\n } finally {\n controller.close();\n }\n },\n });\n\n return new Response(stream, {\n status: 200,\n headers: {\n 'content-type': 'text/event-stream',\n 'cache-control': 'no-cache',\n connection: 'keep-alive',\n },\n });\n };\n}\n\n// ============================================================================\n// createEditHandler\n// ============================================================================\n\n/**\n * Returns a Web-standard Fetch handler that calls `editSchema` and returns JSON.\n *\n * Body shape accepted: `{ appId: string; patch: EditSchemaPatch }`\n */\nexport function createEditHandler(\n opts: GenerateHandlerOptions,\n): (request: Request) => Promise<Response> {\n return async (request: Request): Promise<Response> => {\n let body: EditSchemaRequest;\n try {\n body = (await request.json()) as EditSchemaRequest;\n } catch {\n return new Response(JSON.stringify({ error: 'invalid JSON body' }), {\n status: 400,\n headers: { 'content-type': 'application/json' },\n });\n }\n\n const appId = typeof body.appId === 'string' ? body.appId : '';\n if (!appId) {\n return new Response(JSON.stringify({ error: 'appId is required' }), {\n status: 400,\n headers: { 'content-type': 'application/json' },\n });\n }\n\n const patch: EditSchemaPatch | undefined = body.patch;\n if (patch === undefined || patch === null || typeof patch !== 'object') {\n return new Response(JSON.stringify({ error: 'patch is required' }), {\n status: 400,\n headers: { 'content-type': 'application/json' },\n });\n }\n\n const client = new AlmadarClient({ apiKey: opts.apiKey, baseUrl: opts.baseUrl });\n\n try {\n const schema: OrbitalSchema = await client.editSchema(appId, patch);\n return new Response(JSON.stringify(schema), {\n status: 200,\n headers: { 'content-type': 'application/json' },\n });\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return new Response(JSON.stringify({ error: message }), {\n status: 500,\n headers: { 'content-type': 'application/json' },\n });\n }\n };\n}\n"]}
@@ -1,65 +1,11 @@
1
- import { OrbitalSchema, EntityData, EventPayload } from '@almadar/core';
1
+ import { SSEEvent, OrbitalSchema, EventPayload, EntityData } from '@almadar/core';
2
2
 
3
3
  /**
4
4
  * Public SDK types. Canonical schema / payload types come from `@almadar/core`;
5
- * the SDK adds the typed event union and HTTP-layer option shapes.
5
+ * the SDK adds the HTTP-layer option shapes and re-exports the canonical SSE
6
+ * event union.
6
7
  */
7
8
 
8
- /**
9
- * Canonical JSON value type — the closure of every value that survives a
10
- * `JSON.parse(JSON.stringify(x))` round-trip. Used as the JSON-parse output
11
- * type so we never widen to `unknown` at HTTP boundaries.
12
- *
13
- * Mirrors `packages/almadar-agent/src/api-types.ts:25-31`.
14
- */
15
- type JsonValue = string | number | boolean | null | JsonValue[] | {
16
- [key: string]: JsonValue;
17
- };
18
- /**
19
- * Lifecycle events emitted by the agent during a `generate()` call. Mirrors
20
- * the SSE event types from
21
- * `apps/builder/packages/server/src/routes/agent/deepagent.ts` — keep in sync
22
- * when new events are added on the server.
23
- */
24
- type AgentEvent = {
25
- type: 'start';
26
- threadId: string;
27
- workDir: string;
28
- } | {
29
- type: 'plan_committed';
30
- orbitals: readonly string[];
31
- } | {
32
- type: 'orbital_added';
33
- orbital: string;
34
- } | {
35
- type: 'schema_update';
36
- schema: OrbitalSchema;
37
- } | {
38
- type: 'app_created';
39
- appId: string;
40
- name: string;
41
- } | {
42
- type: 'subagent_start';
43
- subagent: string;
44
- } | {
45
- type: 'subagent_progress';
46
- subagent: string;
47
- message: string;
48
- } | {
49
- type: 'subagent_complete';
50
- subagent: string;
51
- } | {
52
- type: 'coordinator_decision';
53
- decision: string;
54
- } | {
55
- type: 'complete';
56
- schema: OrbitalSchema;
57
- appId?: string;
58
- } | {
59
- type: 'error';
60
- message: string;
61
- code?: number;
62
- };
63
9
  /**
64
10
  * Server-emitted error envelope. `code` maps to the SDK error subclasses:
65
11
  * 4001 → ApiKeyError, 4029 → RateLimitedError, 4040 → CatalogOutOfScopeError.
@@ -81,13 +27,33 @@ interface GenerateOptions {
81
27
  prompt: string;
82
28
  endUserId?: string;
83
29
  appId?: string;
84
- /** Streaming callback for SSE events. */
85
- onEvent?: (event: AgentEvent) => void;
30
+ /** Streaming callback for canonical SSE events. */
31
+ onEvent?: (event: SSEEvent) => void;
86
32
  /**
87
33
  * When true, server responds with an `AsyncJobHandle` immediately and the
88
34
  * client polls. Useful for generations expected to exceed proxy SSE timeouts.
89
35
  */
90
36
  async?: boolean;
37
+ /**
38
+ * Agent provider override (e.g. 'deepseek', 'openai').
39
+ * Omit to use the server's default.
40
+ */
41
+ provider?: string;
42
+ /**
43
+ * Agent model override (e.g. 'deepseek-chat').
44
+ * Omit to use the server's default.
45
+ */
46
+ model?: string;
47
+ /**
48
+ * Behavior catalog mode — 'subset' narrows generation to stdAllowList.
49
+ * Server-specific; omit if the agent does not support it.
50
+ */
51
+ catalogMode?: string;
52
+ /**
53
+ * Allow-list of std behavior names. Requires a server that supports catalog
54
+ * narrowing (e.g. the builder Rabit/Studio agent).
55
+ */
56
+ stdAllowList?: string[];
91
57
  }
92
58
  interface GenerateResult {
93
59
  schema: OrbitalSchema;
@@ -136,10 +102,6 @@ interface AlmadarAppProps {
136
102
  initialPagePath?: string;
137
103
  height?: string;
138
104
  className?: string;
139
- theme?: 'copper' | 'wireframe' | 'default';
140
- }
141
- interface AlmadarAppRef {
142
- emit(eventName: string, payload?: EventPayload): void;
143
105
  }
144
106
 
145
- export type { AgentEvent as A, CompileOptions as C, EditSchemaPatch as E, GenerateOptions as G, JsonValue as J, AlmadarAppProps as a, AlmadarAppRef as b, AlmadarClientOptions as c, ApiErrorBody as d, AsyncJobHandle as e, CompileResult as f, GenerateResult as g };
107
+ export type { AlmadarAppProps as A, CompileOptions as C, EditSchemaPatch as E, GenerateOptions as G, AlmadarClientOptions as a, ApiErrorBody as b, AsyncJobHandle as c, CompileResult as d, GenerateResult as e };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almadar/sdk",
3
- "version": "0.1.0-alpha.4",
3
+ "version": "0.1.0",
4
4
  "description": "Almadar SDK — embed agent-generated orbital schemas in your React app. AlmadarApp component + AlmadarClient HTTP client.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -22,6 +22,14 @@
22
22
  "./server": {
23
23
  "types": "./dist/server/index.d.ts",
24
24
  "import": "./dist/server/index.js"
25
+ },
26
+ "./server/express": {
27
+ "types": "./dist/server/express.d.ts",
28
+ "import": "./dist/server/express.js"
29
+ },
30
+ "./server/hono": {
31
+ "types": "./dist/server/hono.d.ts",
32
+ "import": "./dist/server/hono.js"
25
33
  }
26
34
  },
27
35
  "files": [
@@ -29,24 +37,17 @@
29
37
  "README.md",
30
38
  "LICENSE"
31
39
  ],
40
+ "dependencies": {
41
+ "@almadar/core": "^10.11.0",
42
+ "@almadar/runtime": "^6.17.0",
43
+ "@almadar/ui": "^5.76.7"
44
+ },
32
45
  "peerDependencies": {
33
- "@almadar/core": ">=10",
34
- "@almadar/runtime": ">=6.13",
35
- "@almadar/ui": ">=5.32",
36
- "express": ">=4.0.0",
37
46
  "react": ">=18.0.0",
38
47
  "react-dom": ">=18.0.0"
39
48
  },
40
- "peerDependenciesMeta": {
41
- "express": {
42
- "optional": true
43
- }
44
- },
45
49
  "devDependencies": {
46
- "@almadar/core": ">=10",
47
50
  "@almadar/eslint-plugin": ">=2.7.0",
48
- "@almadar/runtime": ">=6.13",
49
- "@almadar/ui": ">=5.32",
50
51
  "@testing-library/react": "^16.1.0",
51
52
  "@types/express": "^4.17.21",
52
53
  "@types/react": "^18.3.12",
@@ -55,6 +56,7 @@
55
56
  "eslint": "10.0.0",
56
57
  "express": "^4.21.0",
57
58
  "happy-dom": "^15.11.7",
59
+ "hono": "^4.12.27",
58
60
  "react": "^18.3.1",
59
61
  "react-dom": "^18.3.1",
60
62
  "tsup": "^8.3.5",