@cadraos/sdk 0.3.14-p46.3 → 0.3.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/README.md +104 -53
  2. package/dist/ai-functions/react/index.cjs +176 -0
  3. package/dist/ai-functions/react/index.cjs.map +1 -0
  4. package/dist/ai-functions/react/index.d.cts +129 -0
  5. package/dist/ai-functions/react/index.d.ts +129 -0
  6. package/dist/ai-functions/react/index.js +153 -0
  7. package/dist/ai-functions/react/index.js.map +1 -0
  8. package/dist/ai-functions/server/index.cjs +296 -0
  9. package/dist/ai-functions/server/index.cjs.map +1 -0
  10. package/dist/ai-functions/server/index.d.cts +334 -0
  11. package/dist/ai-functions/server/index.d.ts +334 -0
  12. package/dist/ai-functions/server/index.js +284 -0
  13. package/dist/ai-functions/server/index.js.map +1 -0
  14. package/dist/board-host/index.cjs +217 -129
  15. package/dist/board-host/index.cjs.map +1 -1
  16. package/dist/board-host/index.d.cts +96 -1
  17. package/dist/board-host/index.d.ts +96 -1
  18. package/dist/board-host/index.js +218 -131
  19. package/dist/board-host/index.js.map +1 -1
  20. package/dist/board-host/server/index.d.cts +44 -0
  21. package/dist/board-host/server/index.d.ts +44 -0
  22. package/dist/chat/index.cjs +299 -17
  23. package/dist/chat/index.cjs.map +1 -1
  24. package/dist/chat/index.d.cts +225 -0
  25. package/dist/chat/index.d.ts +225 -0
  26. package/dist/chat/index.js +299 -17
  27. package/dist/chat/index.js.map +1 -1
  28. package/dist/index.cjs +221 -3
  29. package/dist/index.cjs.map +1 -1
  30. package/dist/index.d.cts +286 -1
  31. package/dist/index.d.ts +286 -1
  32. package/dist/index.js +215 -4
  33. package/dist/index.js.map +1 -1
  34. package/dist/kanban/engine/index.cjs +774 -683
  35. package/dist/kanban/engine/index.cjs.map +1 -1
  36. package/dist/kanban/engine/index.d.cts +90 -1
  37. package/dist/kanban/engine/index.d.ts +90 -1
  38. package/dist/kanban/engine/index.js +774 -684
  39. package/dist/kanban/engine/index.js.map +1 -1
  40. package/dist/kanban/index.cjs +214 -3
  41. package/dist/kanban/index.cjs.map +1 -1
  42. package/dist/kanban/index.d.cts +252 -0
  43. package/dist/kanban/index.d.ts +252 -0
  44. package/dist/kanban/index.js +214 -3
  45. package/dist/kanban/index.js.map +1 -1
  46. package/dist/teams/index.cjs +214 -3
  47. package/dist/teams/index.cjs.map +1 -1
  48. package/dist/teams/index.d.cts +225 -0
  49. package/dist/teams/index.d.ts +225 -0
  50. package/dist/teams/index.js +214 -3
  51. package/dist/teams/index.js.map +1 -1
  52. package/package.json +21 -1
@@ -65,6 +65,14 @@ var CadraError = class extends Error {
65
65
  details;
66
66
  /** Request ID from server (for debugging) */
67
67
  requestId;
68
+ /**
69
+ * The server's own `error.code` exactly as sent on the wire (e.g.
70
+ * `FUNCTION_NOT_PUBLISHED`, `DUPLICATE_REQUEST`, `VARIABLE_TYPE`).
71
+ * Populated by `parseApiError` for EVERY status. `code` keeps its historic
72
+ * per-class values (`conflict`, `server_error`, `validation_error`, …) for
73
+ * compatibility; branch on `serverCode` when you need the precise reason.
74
+ */
75
+ serverCode;
68
76
  constructor(message, code, status, details, requestId) {
69
77
  super(message);
70
78
  this.name = "CadraError";
@@ -142,6 +150,12 @@ function parseApiError(status, body, requestId) {
142
150
  const message = errorBody?.error?.message ?? "An error occurred";
143
151
  const code = errorBody?.error?.code ?? "unknown_error";
144
152
  const details = errorBody?.error?.details;
153
+ const serverCode = typeof errorBody?.error?.code === "string" ? errorBody.error.code : void 0;
154
+ const error = buildApiError(status, message, code, details, requestId);
155
+ if (serverCode !== void 0) error.serverCode = serverCode;
156
+ return error;
157
+ }
158
+ function buildApiError(status, message, code, details, requestId) {
145
159
  switch (status) {
146
160
  case 400:
147
161
  case 422: {
@@ -177,6 +191,42 @@ function parseApiError(status, body, requestId) {
177
191
  }
178
192
  }
179
193
 
194
+ // src/errors/ai-function-errors.ts
195
+ var AiFunctionDuplicateError = class extends ConflictError {
196
+ /** The existing run's execution id. */
197
+ executionId;
198
+ /** The existing run's status (`running`, a terminal status, or `abandoned`). */
199
+ runStatus;
200
+ constructor(message, details, requestId) {
201
+ super(message, details, requestId);
202
+ this.name = "AiFunctionDuplicateError";
203
+ this.serverCode = "DUPLICATE_REQUEST";
204
+ this.executionId = typeof details?.executionId === "string" ? details.executionId : void 0;
205
+ this.runStatus = typeof details?.status === "string" ? details.status : void 0;
206
+ }
207
+ };
208
+ var AiFunctionChargedError = class extends CadraError {
209
+ constructor(source) {
210
+ super(source.message, source.code, source.status, source.details, source.requestId);
211
+ this.name = "AiFunctionChargedError";
212
+ this.serverCode = source.serverCode;
213
+ }
214
+ };
215
+ var AiFunctionParameterError = class extends ValidationError {
216
+ functionKey;
217
+ issues;
218
+ constructor(functionKey, issues) {
219
+ super(
220
+ `Invalid parameters for AI function "${functionKey}": ` + issues.map((i) => `${i.name} (${i.code})`).join(", "),
221
+ issues.map((i) => ({ field: i.name, message: i.code })),
222
+ { functionKey, issues }
223
+ );
224
+ this.name = "AiFunctionParameterError";
225
+ this.functionKey = functionKey;
226
+ this.issues = issues;
227
+ }
228
+ };
229
+
180
230
  // src/utils/retry.ts
181
231
  var DEFAULT_RETRY_CONFIG = {
182
232
  maxRetries: 3,
@@ -295,7 +345,8 @@ var HttpClient = class {
295
345
  headers["Idempotency-Key"] = options.idempotencyKey;
296
346
  }
297
347
  const controller = new AbortController();
298
- const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
348
+ const timeoutMs = options.timeoutMs ?? this.config.timeout;
349
+ const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
299
350
  try {
300
351
  const doFetch = this.config.fetch ?? fetch;
301
352
  const response = await doFetch(url, {
@@ -331,7 +382,7 @@ var HttpClient = class {
331
382
  } catch (error) {
332
383
  clearTimeout(timeoutId);
333
384
  if (error instanceof Error && error.name === "AbortError") {
334
- throw new TimeoutError(`Request timed out after ${this.config.timeout}ms`);
385
+ throw new TimeoutError(`Request timed out after ${options.timeoutMs ?? this.config.timeout}ms`);
335
386
  }
336
387
  if (error instanceof TypeError && error.message.includes("fetch")) {
337
388
  throw new NetworkError(`Network error: ${error.message}`);
@@ -363,7 +414,8 @@ var HttpClient = class {
363
414
  path,
364
415
  body,
365
416
  idempotencyKey: options?.idempotencyKey,
366
- skipRetry: options?.skipRetry
417
+ skipRetry: options?.skipRetry,
418
+ timeoutMs: options?.timeoutMs
367
419
  });
368
420
  }
369
421
  /**
@@ -1112,6 +1164,10 @@ var ExecutionStreamControllerImpl = class {
1112
1164
  toolName,
1113
1165
  result: data.result,
1114
1166
  durationMs: data.durationMs ?? 0,
1167
+ // CAD-243: pass the producer's failure verdict through.
1168
+ ...data.isError === true ? { isError: true } : {},
1169
+ ...typeof data.status === "string" ? { status: data.status } : {},
1170
+ ...typeof data.error === "string" ? { error: data.error } : {},
1115
1171
  forwardedFrom: event.data._forwardedFrom,
1116
1172
  // CAD-87 S1-001 EventIdentity → (execId, seq) reducer dedup (S1-003).
1117
1173
  sourceExecutionId: data.sourceExecutionId ?? data.executionId,
@@ -3350,6 +3406,156 @@ var RemoteRunnersAPI = class extends BaseResourceAPI {
3350
3406
  }
3351
3407
  };
3352
3408
 
3409
+ // src/resources/ai-functions.ts
3410
+ var AI_FUNCTION_RUN_TIMEOUT_MS = 6e4;
3411
+ var AI_FUNCTION_DESCRIPTOR_TTL_MS = 6e4;
3412
+ function checkAiFunctionParameters(parameters, variables) {
3413
+ const issues = [];
3414
+ const declared = /* @__PURE__ */ new Set();
3415
+ for (const p of parameters) {
3416
+ declared.add(p.name);
3417
+ const has = Object.prototype.hasOwnProperty.call(variables, p.name);
3418
+ const value = has ? variables[p.name] : void 0;
3419
+ if (value === void 0 || value === null) {
3420
+ if (p.required) issues.push({ name: p.name, code: "missing" });
3421
+ continue;
3422
+ }
3423
+ switch (p.type) {
3424
+ case "number":
3425
+ if (typeof value !== "number" || !Number.isFinite(value)) {
3426
+ issues.push({ name: p.name, code: "type" });
3427
+ }
3428
+ break;
3429
+ case "boolean":
3430
+ if (typeof value !== "boolean") issues.push({ name: p.name, code: "type" });
3431
+ break;
3432
+ case "enum":
3433
+ if (typeof value !== "string") issues.push({ name: p.name, code: "type" });
3434
+ else if (p.options && !p.options.includes(value)) {
3435
+ issues.push({ name: p.name, code: "option" });
3436
+ }
3437
+ break;
3438
+ case "string":
3439
+ case "text":
3440
+ if (typeof value !== "string") issues.push({ name: p.name, code: "type" });
3441
+ else if (typeof p.maxLength === "number" && value.length > p.maxLength) {
3442
+ issues.push({ name: p.name, code: "too_long" });
3443
+ }
3444
+ break;
3445
+ case "image":
3446
+ if (typeof value !== "string") issues.push({ name: p.name, code: "type" });
3447
+ break;
3448
+ }
3449
+ }
3450
+ for (const name of Object.keys(variables)) {
3451
+ if (!declared.has(name)) issues.push({ name, code: "unknown" });
3452
+ }
3453
+ return issues;
3454
+ }
3455
+ var AiFunctionsAPI = class extends BaseResourceAPI {
3456
+ descriptorCache = /* @__PURE__ */ new Map();
3457
+ constructor(http) {
3458
+ super(http, "/api/v1/ai-functions");
3459
+ }
3460
+ /**
3461
+ * List the functions this org can call — the index (D27a). Each entry carries
3462
+ * the live version's typed parameters; never prompt text.
3463
+ */
3464
+ async list() {
3465
+ const data = await this.httpGet("");
3466
+ const functions = Array.isArray(data) ? data : data?.functions ?? [];
3467
+ for (const d of functions) this.cacheDescriptor(d);
3468
+ return functions;
3469
+ }
3470
+ /**
3471
+ * Get one function's descriptor by key (D27a).
3472
+ * `NotFoundError` (`FUNCTION_NOT_FOUND`) / `ConflictError` (`FUNCTION_NOT_PUBLISHED`).
3473
+ */
3474
+ async get(functionKey) {
3475
+ const data = await this.httpGet(
3476
+ `/${encodeURIComponent(functionKey)}`
3477
+ );
3478
+ const descriptor = data && typeof data === "object" && "function" in data && !("functionKey" in data) ? data.function : data;
3479
+ this.cacheDescriptor(descriptor, functionKey);
3480
+ return descriptor;
3481
+ }
3482
+ /**
3483
+ * Read one of this org's own runs (safe projection, §6.5).
3484
+ */
3485
+ async getRun(executionId) {
3486
+ return this.httpGet(`/runs/${encodeURIComponent(executionId)}`);
3487
+ }
3488
+ /** Forget cached descriptors (one key, or all). */
3489
+ clearDescriptorCache(functionKey) {
3490
+ if (functionKey) this.descriptorCache.delete(functionKey);
3491
+ else this.descriptorCache.clear();
3492
+ }
3493
+ async run(refOrKey, parametersOrOptions, shorthandOpts) {
3494
+ let ref;
3495
+ let options;
3496
+ if (typeof refOrKey === "string") {
3497
+ ref = { functionKey: refOrKey };
3498
+ options = { ...shorthandOpts ?? {}, variables: parametersOrOptions };
3499
+ } else {
3500
+ ref = refOrKey;
3501
+ options = parametersOrOptions;
3502
+ }
3503
+ const variables = options.variables ?? {};
3504
+ const functionKey = "functionKey" in ref ? ref.functionKey : void 0;
3505
+ const shouldCheck = functionKey !== void 0 && options.version === void 0 && options.validate !== false;
3506
+ if (shouldCheck) {
3507
+ const descriptor = await this.getCachedDescriptor(functionKey);
3508
+ const issues = checkAiFunctionParameters(descriptor.parameters, variables);
3509
+ if (issues.length > 0) {
3510
+ throw new AiFunctionParameterError(functionKey, issues);
3511
+ }
3512
+ }
3513
+ const body = {
3514
+ ref,
3515
+ variables,
3516
+ version: options.version,
3517
+ idempotencyKey: options.idempotencyKey ?? generateExecutionId(),
3518
+ params: options.params
3519
+ };
3520
+ try {
3521
+ return await this.httpPost("/run", body, {
3522
+ skipRetry: true,
3523
+ timeoutMs: AI_FUNCTION_RUN_TIMEOUT_MS
3524
+ });
3525
+ } catch (error) {
3526
+ throw this.mapRunError(error, functionKey);
3527
+ }
3528
+ }
3529
+ // ── internals ──────────────────────────────────────────────────────────────
3530
+ cacheDescriptor(descriptor, key) {
3531
+ if (!descriptor || typeof descriptor !== "object") return;
3532
+ const cacheKey = key ?? descriptor.functionKey;
3533
+ if (!cacheKey) return;
3534
+ this.descriptorCache.set(cacheKey, {
3535
+ descriptor,
3536
+ expiresAt: Date.now() + AI_FUNCTION_DESCRIPTOR_TTL_MS
3537
+ });
3538
+ }
3539
+ async getCachedDescriptor(functionKey) {
3540
+ const hit = this.descriptorCache.get(functionKey);
3541
+ if (hit && hit.expiresAt > Date.now()) return hit.descriptor;
3542
+ return this.get(functionKey);
3543
+ }
3544
+ mapRunError(error, functionKey) {
3545
+ if (!(error instanceof CadraError)) return error;
3546
+ if (error.serverCode === "DUPLICATE_REQUEST") {
3547
+ return new AiFunctionDuplicateError(error.message, error.details, error.requestId);
3548
+ }
3549
+ if (error.details?.charged === true) {
3550
+ return new AiFunctionChargedError(error);
3551
+ }
3552
+ if (functionKey && error.serverCode?.startsWith("VARIABLE_")) {
3553
+ this.descriptorCache.delete(functionKey);
3554
+ }
3555
+ return error;
3556
+ }
3557
+ };
3558
+
3353
3559
  // src/client.ts
3354
3560
  var DEFAULT_BASE_URL = "https://api.cadraos.com";
3355
3561
  var DEFAULT_TIMEOUT = 3e4;
@@ -3396,6 +3602,10 @@ var CadraClient = class {
3396
3602
  * Remote runner operations (list)
3397
3603
  */
3398
3604
  remoteRunners;
3605
+ /**
3606
+ * AI function operations (list, get, run, getRun) — p93
3607
+ */
3608
+ aiFunctions;
3399
3609
  /**
3400
3610
  * Create a new AI SaaS client
3401
3611
  *
@@ -3485,6 +3695,7 @@ var CadraClient = class {
3485
3695
  this.kanban = new KanbanAPI(this.httpClient, getStreamConfig);
3486
3696
  this.remoteAgents = new RemoteAgentsAPI(this.httpClient, getStreamConfig);
3487
3697
  this.remoteRunners = new RemoteRunnersAPI(this.httpClient);
3698
+ this.aiFunctions = new AiFunctionsAPI(this.httpClient);
3488
3699
  }
3489
3700
  /**
3490
3701
  * Validate client options