@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
@@ -86,6 +86,14 @@ var CadraError = class extends Error {
86
86
  details;
87
87
  /** Request ID from server (for debugging) */
88
88
  requestId;
89
+ /**
90
+ * The server's own `error.code` exactly as sent on the wire (e.g.
91
+ * `FUNCTION_NOT_PUBLISHED`, `DUPLICATE_REQUEST`, `VARIABLE_TYPE`).
92
+ * Populated by `parseApiError` for EVERY status. `code` keeps its historic
93
+ * per-class values (`conflict`, `server_error`, `validation_error`, …) for
94
+ * compatibility; branch on `serverCode` when you need the precise reason.
95
+ */
96
+ serverCode;
89
97
  constructor(message, code, status, details, requestId) {
90
98
  super(message);
91
99
  this.name = "CadraError";
@@ -163,6 +171,12 @@ function parseApiError(status, body, requestId) {
163
171
  const message = errorBody?.error?.message ?? "An error occurred";
164
172
  const code = errorBody?.error?.code ?? "unknown_error";
165
173
  const details = errorBody?.error?.details;
174
+ const serverCode = typeof errorBody?.error?.code === "string" ? errorBody.error.code : void 0;
175
+ const error = buildApiError(status, message, code, details, requestId);
176
+ if (serverCode !== void 0) error.serverCode = serverCode;
177
+ return error;
178
+ }
179
+ function buildApiError(status, message, code, details, requestId) {
166
180
  switch (status) {
167
181
  case 400:
168
182
  case 422: {
@@ -198,6 +212,42 @@ function parseApiError(status, body, requestId) {
198
212
  }
199
213
  }
200
214
 
215
+ // src/errors/ai-function-errors.ts
216
+ var AiFunctionDuplicateError = class extends ConflictError {
217
+ /** The existing run's execution id. */
218
+ executionId;
219
+ /** The existing run's status (`running`, a terminal status, or `abandoned`). */
220
+ runStatus;
221
+ constructor(message, details, requestId) {
222
+ super(message, details, requestId);
223
+ this.name = "AiFunctionDuplicateError";
224
+ this.serverCode = "DUPLICATE_REQUEST";
225
+ this.executionId = typeof details?.executionId === "string" ? details.executionId : void 0;
226
+ this.runStatus = typeof details?.status === "string" ? details.status : void 0;
227
+ }
228
+ };
229
+ var AiFunctionChargedError = class extends CadraError {
230
+ constructor(source) {
231
+ super(source.message, source.code, source.status, source.details, source.requestId);
232
+ this.name = "AiFunctionChargedError";
233
+ this.serverCode = source.serverCode;
234
+ }
235
+ };
236
+ var AiFunctionParameterError = class extends ValidationError {
237
+ functionKey;
238
+ issues;
239
+ constructor(functionKey, issues) {
240
+ super(
241
+ `Invalid parameters for AI function "${functionKey}": ` + issues.map((i) => `${i.name} (${i.code})`).join(", "),
242
+ issues.map((i) => ({ field: i.name, message: i.code })),
243
+ { functionKey, issues }
244
+ );
245
+ this.name = "AiFunctionParameterError";
246
+ this.functionKey = functionKey;
247
+ this.issues = issues;
248
+ }
249
+ };
250
+
201
251
  // src/utils/retry.ts
202
252
  var DEFAULT_RETRY_CONFIG = {
203
253
  maxRetries: 3,
@@ -316,7 +366,8 @@ var HttpClient = class {
316
366
  headers["Idempotency-Key"] = options.idempotencyKey;
317
367
  }
318
368
  const controller = new AbortController();
319
- const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
369
+ const timeoutMs = options.timeoutMs ?? this.config.timeout;
370
+ const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
320
371
  try {
321
372
  const doFetch = this.config.fetch ?? fetch;
322
373
  const response = await doFetch(url, {
@@ -352,7 +403,7 @@ var HttpClient = class {
352
403
  } catch (error) {
353
404
  clearTimeout(timeoutId);
354
405
  if (error instanceof Error && error.name === "AbortError") {
355
- throw new TimeoutError(`Request timed out after ${this.config.timeout}ms`);
406
+ throw new TimeoutError(`Request timed out after ${options.timeoutMs ?? this.config.timeout}ms`);
356
407
  }
357
408
  if (error instanceof TypeError && error.message.includes("fetch")) {
358
409
  throw new NetworkError(`Network error: ${error.message}`);
@@ -384,7 +435,8 @@ var HttpClient = class {
384
435
  path,
385
436
  body,
386
437
  idempotencyKey: options?.idempotencyKey,
387
- skipRetry: options?.skipRetry
438
+ skipRetry: options?.skipRetry,
439
+ timeoutMs: options?.timeoutMs
388
440
  });
389
441
  }
390
442
  /**
@@ -1133,6 +1185,10 @@ var ExecutionStreamControllerImpl = class {
1133
1185
  toolName,
1134
1186
  result: data.result,
1135
1187
  durationMs: data.durationMs ?? 0,
1188
+ // CAD-243: pass the producer's failure verdict through.
1189
+ ...data.isError === true ? { isError: true } : {},
1190
+ ...typeof data.status === "string" ? { status: data.status } : {},
1191
+ ...typeof data.error === "string" ? { error: data.error } : {},
1136
1192
  forwardedFrom: event.data._forwardedFrom,
1137
1193
  // CAD-87 S1-001 EventIdentity → (execId, seq) reducer dedup (S1-003).
1138
1194
  sourceExecutionId: data.sourceExecutionId ?? data.executionId,
@@ -3371,6 +3427,156 @@ var RemoteRunnersAPI = class extends BaseResourceAPI {
3371
3427
  }
3372
3428
  };
3373
3429
 
3430
+ // src/resources/ai-functions.ts
3431
+ var AI_FUNCTION_RUN_TIMEOUT_MS = 6e4;
3432
+ var AI_FUNCTION_DESCRIPTOR_TTL_MS = 6e4;
3433
+ function checkAiFunctionParameters(parameters, variables) {
3434
+ const issues = [];
3435
+ const declared = /* @__PURE__ */ new Set();
3436
+ for (const p of parameters) {
3437
+ declared.add(p.name);
3438
+ const has = Object.prototype.hasOwnProperty.call(variables, p.name);
3439
+ const value = has ? variables[p.name] : void 0;
3440
+ if (value === void 0 || value === null) {
3441
+ if (p.required) issues.push({ name: p.name, code: "missing" });
3442
+ continue;
3443
+ }
3444
+ switch (p.type) {
3445
+ case "number":
3446
+ if (typeof value !== "number" || !Number.isFinite(value)) {
3447
+ issues.push({ name: p.name, code: "type" });
3448
+ }
3449
+ break;
3450
+ case "boolean":
3451
+ if (typeof value !== "boolean") issues.push({ name: p.name, code: "type" });
3452
+ break;
3453
+ case "enum":
3454
+ if (typeof value !== "string") issues.push({ name: p.name, code: "type" });
3455
+ else if (p.options && !p.options.includes(value)) {
3456
+ issues.push({ name: p.name, code: "option" });
3457
+ }
3458
+ break;
3459
+ case "string":
3460
+ case "text":
3461
+ if (typeof value !== "string") issues.push({ name: p.name, code: "type" });
3462
+ else if (typeof p.maxLength === "number" && value.length > p.maxLength) {
3463
+ issues.push({ name: p.name, code: "too_long" });
3464
+ }
3465
+ break;
3466
+ case "image":
3467
+ if (typeof value !== "string") issues.push({ name: p.name, code: "type" });
3468
+ break;
3469
+ }
3470
+ }
3471
+ for (const name of Object.keys(variables)) {
3472
+ if (!declared.has(name)) issues.push({ name, code: "unknown" });
3473
+ }
3474
+ return issues;
3475
+ }
3476
+ var AiFunctionsAPI = class extends BaseResourceAPI {
3477
+ descriptorCache = /* @__PURE__ */ new Map();
3478
+ constructor(http) {
3479
+ super(http, "/api/v1/ai-functions");
3480
+ }
3481
+ /**
3482
+ * List the functions this org can call — the index (D27a). Each entry carries
3483
+ * the live version's typed parameters; never prompt text.
3484
+ */
3485
+ async list() {
3486
+ const data = await this.httpGet("");
3487
+ const functions = Array.isArray(data) ? data : data?.functions ?? [];
3488
+ for (const d of functions) this.cacheDescriptor(d);
3489
+ return functions;
3490
+ }
3491
+ /**
3492
+ * Get one function's descriptor by key (D27a).
3493
+ * `NotFoundError` (`FUNCTION_NOT_FOUND`) / `ConflictError` (`FUNCTION_NOT_PUBLISHED`).
3494
+ */
3495
+ async get(functionKey) {
3496
+ const data = await this.httpGet(
3497
+ `/${encodeURIComponent(functionKey)}`
3498
+ );
3499
+ const descriptor = data && typeof data === "object" && "function" in data && !("functionKey" in data) ? data.function : data;
3500
+ this.cacheDescriptor(descriptor, functionKey);
3501
+ return descriptor;
3502
+ }
3503
+ /**
3504
+ * Read one of this org's own runs (safe projection, §6.5).
3505
+ */
3506
+ async getRun(executionId) {
3507
+ return this.httpGet(`/runs/${encodeURIComponent(executionId)}`);
3508
+ }
3509
+ /** Forget cached descriptors (one key, or all). */
3510
+ clearDescriptorCache(functionKey) {
3511
+ if (functionKey) this.descriptorCache.delete(functionKey);
3512
+ else this.descriptorCache.clear();
3513
+ }
3514
+ async run(refOrKey, parametersOrOptions, shorthandOpts) {
3515
+ let ref;
3516
+ let options;
3517
+ if (typeof refOrKey === "string") {
3518
+ ref = { functionKey: refOrKey };
3519
+ options = { ...shorthandOpts ?? {}, variables: parametersOrOptions };
3520
+ } else {
3521
+ ref = refOrKey;
3522
+ options = parametersOrOptions;
3523
+ }
3524
+ const variables = options.variables ?? {};
3525
+ const functionKey = "functionKey" in ref ? ref.functionKey : void 0;
3526
+ const shouldCheck = functionKey !== void 0 && options.version === void 0 && options.validate !== false;
3527
+ if (shouldCheck) {
3528
+ const descriptor = await this.getCachedDescriptor(functionKey);
3529
+ const issues = checkAiFunctionParameters(descriptor.parameters, variables);
3530
+ if (issues.length > 0) {
3531
+ throw new AiFunctionParameterError(functionKey, issues);
3532
+ }
3533
+ }
3534
+ const body = {
3535
+ ref,
3536
+ variables,
3537
+ version: options.version,
3538
+ idempotencyKey: options.idempotencyKey ?? generateExecutionId(),
3539
+ params: options.params
3540
+ };
3541
+ try {
3542
+ return await this.httpPost("/run", body, {
3543
+ skipRetry: true,
3544
+ timeoutMs: AI_FUNCTION_RUN_TIMEOUT_MS
3545
+ });
3546
+ } catch (error) {
3547
+ throw this.mapRunError(error, functionKey);
3548
+ }
3549
+ }
3550
+ // ── internals ──────────────────────────────────────────────────────────────
3551
+ cacheDescriptor(descriptor, key) {
3552
+ if (!descriptor || typeof descriptor !== "object") return;
3553
+ const cacheKey = key ?? descriptor.functionKey;
3554
+ if (!cacheKey) return;
3555
+ this.descriptorCache.set(cacheKey, {
3556
+ descriptor,
3557
+ expiresAt: Date.now() + AI_FUNCTION_DESCRIPTOR_TTL_MS
3558
+ });
3559
+ }
3560
+ async getCachedDescriptor(functionKey) {
3561
+ const hit = this.descriptorCache.get(functionKey);
3562
+ if (hit && hit.expiresAt > Date.now()) return hit.descriptor;
3563
+ return this.get(functionKey);
3564
+ }
3565
+ mapRunError(error, functionKey) {
3566
+ if (!(error instanceof CadraError)) return error;
3567
+ if (error.serverCode === "DUPLICATE_REQUEST") {
3568
+ return new AiFunctionDuplicateError(error.message, error.details, error.requestId);
3569
+ }
3570
+ if (error.details?.charged === true) {
3571
+ return new AiFunctionChargedError(error);
3572
+ }
3573
+ if (functionKey && error.serverCode?.startsWith("VARIABLE_")) {
3574
+ this.descriptorCache.delete(functionKey);
3575
+ }
3576
+ return error;
3577
+ }
3578
+ };
3579
+
3374
3580
  // src/client.ts
3375
3581
  var DEFAULT_BASE_URL = "https://api.cadraos.com";
3376
3582
  var DEFAULT_TIMEOUT = 3e4;
@@ -3417,6 +3623,10 @@ var CadraClient = class {
3417
3623
  * Remote runner operations (list)
3418
3624
  */
3419
3625
  remoteRunners;
3626
+ /**
3627
+ * AI function operations (list, get, run, getRun) — p93
3628
+ */
3629
+ aiFunctions;
3420
3630
  /**
3421
3631
  * Create a new AI SaaS client
3422
3632
  *
@@ -3506,6 +3716,7 @@ var CadraClient = class {
3506
3716
  this.kanban = new KanbanAPI(this.httpClient, getStreamConfig);
3507
3717
  this.remoteAgents = new RemoteAgentsAPI(this.httpClient, getStreamConfig);
3508
3718
  this.remoteRunners = new RemoteRunnersAPI(this.httpClient);
3719
+ this.aiFunctions = new AiFunctionsAPI(this.httpClient);
3509
3720
  }
3510
3721
  /**
3511
3722
  * Validate client options