@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
package/dist/index.cjs CHANGED
@@ -63,6 +63,14 @@ var CadraError = class extends Error {
63
63
  details;
64
64
  /** Request ID from server (for debugging) */
65
65
  requestId;
66
+ /**
67
+ * The server's own `error.code` exactly as sent on the wire (e.g.
68
+ * `FUNCTION_NOT_PUBLISHED`, `DUPLICATE_REQUEST`, `VARIABLE_TYPE`).
69
+ * Populated by `parseApiError` for EVERY status. `code` keeps its historic
70
+ * per-class values (`conflict`, `server_error`, `validation_error`, …) for
71
+ * compatibility; branch on `serverCode` when you need the precise reason.
72
+ */
73
+ serverCode;
66
74
  constructor(message, code, status, details, requestId) {
67
75
  super(message);
68
76
  this.name = "CadraError";
@@ -140,6 +148,12 @@ function parseApiError(status, body, requestId) {
140
148
  const message = errorBody?.error?.message ?? "An error occurred";
141
149
  const code = errorBody?.error?.code ?? "unknown_error";
142
150
  const details = errorBody?.error?.details;
151
+ const serverCode = typeof errorBody?.error?.code === "string" ? errorBody.error.code : void 0;
152
+ const error = buildApiError(status, message, code, details, requestId);
153
+ if (serverCode !== void 0) error.serverCode = serverCode;
154
+ return error;
155
+ }
156
+ function buildApiError(status, message, code, details, requestId) {
143
157
  switch (status) {
144
158
  case 400:
145
159
  case 422: {
@@ -175,6 +189,42 @@ function parseApiError(status, body, requestId) {
175
189
  }
176
190
  }
177
191
 
192
+ // src/errors/ai-function-errors.ts
193
+ var AiFunctionDuplicateError = class extends ConflictError {
194
+ /** The existing run's execution id. */
195
+ executionId;
196
+ /** The existing run's status (`running`, a terminal status, or `abandoned`). */
197
+ runStatus;
198
+ constructor(message, details, requestId) {
199
+ super(message, details, requestId);
200
+ this.name = "AiFunctionDuplicateError";
201
+ this.serverCode = "DUPLICATE_REQUEST";
202
+ this.executionId = typeof details?.executionId === "string" ? details.executionId : void 0;
203
+ this.runStatus = typeof details?.status === "string" ? details.status : void 0;
204
+ }
205
+ };
206
+ var AiFunctionChargedError = class extends CadraError {
207
+ constructor(source) {
208
+ super(source.message, source.code, source.status, source.details, source.requestId);
209
+ this.name = "AiFunctionChargedError";
210
+ this.serverCode = source.serverCode;
211
+ }
212
+ };
213
+ var AiFunctionParameterError = class extends ValidationError {
214
+ functionKey;
215
+ issues;
216
+ constructor(functionKey, issues) {
217
+ super(
218
+ `Invalid parameters for AI function "${functionKey}": ` + issues.map((i) => `${i.name} (${i.code})`).join(", "),
219
+ issues.map((i) => ({ field: i.name, message: i.code })),
220
+ { functionKey, issues }
221
+ );
222
+ this.name = "AiFunctionParameterError";
223
+ this.functionKey = functionKey;
224
+ this.issues = issues;
225
+ }
226
+ };
227
+
178
228
  // src/utils/retry.ts
179
229
  var DEFAULT_RETRY_CONFIG = {
180
230
  maxRetries: 3,
@@ -293,7 +343,8 @@ var HttpClient = class {
293
343
  headers["Idempotency-Key"] = options.idempotencyKey;
294
344
  }
295
345
  const controller = new AbortController();
296
- const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
346
+ const timeoutMs = options.timeoutMs ?? this.config.timeout;
347
+ const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
297
348
  try {
298
349
  const doFetch = this.config.fetch ?? fetch;
299
350
  const response = await doFetch(url, {
@@ -329,7 +380,7 @@ var HttpClient = class {
329
380
  } catch (error) {
330
381
  clearTimeout(timeoutId);
331
382
  if (error instanceof Error && error.name === "AbortError") {
332
- throw new TimeoutError(`Request timed out after ${this.config.timeout}ms`);
383
+ throw new TimeoutError(`Request timed out after ${options.timeoutMs ?? this.config.timeout}ms`);
333
384
  }
334
385
  if (error instanceof TypeError && error.message.includes("fetch")) {
335
386
  throw new NetworkError(`Network error: ${error.message}`);
@@ -361,7 +412,8 @@ var HttpClient = class {
361
412
  path,
362
413
  body,
363
414
  idempotencyKey: options?.idempotencyKey,
364
- skipRetry: options?.skipRetry
415
+ skipRetry: options?.skipRetry,
416
+ timeoutMs: options?.timeoutMs
365
417
  });
366
418
  }
367
419
  /**
@@ -1120,6 +1172,10 @@ var ExecutionStreamControllerImpl = class {
1120
1172
  toolName,
1121
1173
  result: data.result,
1122
1174
  durationMs: data.durationMs ?? 0,
1175
+ // CAD-243: pass the producer's failure verdict through.
1176
+ ...data.isError === true ? { isError: true } : {},
1177
+ ...typeof data.status === "string" ? { status: data.status } : {},
1178
+ ...typeof data.error === "string" ? { error: data.error } : {},
1123
1179
  forwardedFrom: event.data._forwardedFrom,
1124
1180
  // CAD-87 S1-001 EventIdentity → (execId, seq) reducer dedup (S1-003).
1125
1181
  sourceExecutionId: data.sourceExecutionId ?? data.executionId,
@@ -3358,6 +3414,156 @@ var RemoteRunnersAPI = class extends BaseResourceAPI {
3358
3414
  }
3359
3415
  };
3360
3416
 
3417
+ // src/resources/ai-functions.ts
3418
+ var AI_FUNCTION_RUN_TIMEOUT_MS = 6e4;
3419
+ var AI_FUNCTION_DESCRIPTOR_TTL_MS = 6e4;
3420
+ function checkAiFunctionParameters(parameters, variables) {
3421
+ const issues = [];
3422
+ const declared = /* @__PURE__ */ new Set();
3423
+ for (const p of parameters) {
3424
+ declared.add(p.name);
3425
+ const has = Object.prototype.hasOwnProperty.call(variables, p.name);
3426
+ const value = has ? variables[p.name] : void 0;
3427
+ if (value === void 0 || value === null) {
3428
+ if (p.required) issues.push({ name: p.name, code: "missing" });
3429
+ continue;
3430
+ }
3431
+ switch (p.type) {
3432
+ case "number":
3433
+ if (typeof value !== "number" || !Number.isFinite(value)) {
3434
+ issues.push({ name: p.name, code: "type" });
3435
+ }
3436
+ break;
3437
+ case "boolean":
3438
+ if (typeof value !== "boolean") issues.push({ name: p.name, code: "type" });
3439
+ break;
3440
+ case "enum":
3441
+ if (typeof value !== "string") issues.push({ name: p.name, code: "type" });
3442
+ else if (p.options && !p.options.includes(value)) {
3443
+ issues.push({ name: p.name, code: "option" });
3444
+ }
3445
+ break;
3446
+ case "string":
3447
+ case "text":
3448
+ if (typeof value !== "string") issues.push({ name: p.name, code: "type" });
3449
+ else if (typeof p.maxLength === "number" && value.length > p.maxLength) {
3450
+ issues.push({ name: p.name, code: "too_long" });
3451
+ }
3452
+ break;
3453
+ case "image":
3454
+ if (typeof value !== "string") issues.push({ name: p.name, code: "type" });
3455
+ break;
3456
+ }
3457
+ }
3458
+ for (const name of Object.keys(variables)) {
3459
+ if (!declared.has(name)) issues.push({ name, code: "unknown" });
3460
+ }
3461
+ return issues;
3462
+ }
3463
+ var AiFunctionsAPI = class extends BaseResourceAPI {
3464
+ descriptorCache = /* @__PURE__ */ new Map();
3465
+ constructor(http) {
3466
+ super(http, "/api/v1/ai-functions");
3467
+ }
3468
+ /**
3469
+ * List the functions this org can call — the index (D27a). Each entry carries
3470
+ * the live version's typed parameters; never prompt text.
3471
+ */
3472
+ async list() {
3473
+ const data = await this.httpGet("");
3474
+ const functions = Array.isArray(data) ? data : data?.functions ?? [];
3475
+ for (const d of functions) this.cacheDescriptor(d);
3476
+ return functions;
3477
+ }
3478
+ /**
3479
+ * Get one function's descriptor by key (D27a).
3480
+ * `NotFoundError` (`FUNCTION_NOT_FOUND`) / `ConflictError` (`FUNCTION_NOT_PUBLISHED`).
3481
+ */
3482
+ async get(functionKey) {
3483
+ const data = await this.httpGet(
3484
+ `/${encodeURIComponent(functionKey)}`
3485
+ );
3486
+ const descriptor = data && typeof data === "object" && "function" in data && !("functionKey" in data) ? data.function : data;
3487
+ this.cacheDescriptor(descriptor, functionKey);
3488
+ return descriptor;
3489
+ }
3490
+ /**
3491
+ * Read one of this org's own runs (safe projection, §6.5).
3492
+ */
3493
+ async getRun(executionId) {
3494
+ return this.httpGet(`/runs/${encodeURIComponent(executionId)}`);
3495
+ }
3496
+ /** Forget cached descriptors (one key, or all). */
3497
+ clearDescriptorCache(functionKey) {
3498
+ if (functionKey) this.descriptorCache.delete(functionKey);
3499
+ else this.descriptorCache.clear();
3500
+ }
3501
+ async run(refOrKey, parametersOrOptions, shorthandOpts) {
3502
+ let ref;
3503
+ let options;
3504
+ if (typeof refOrKey === "string") {
3505
+ ref = { functionKey: refOrKey };
3506
+ options = { ...shorthandOpts ?? {}, variables: parametersOrOptions };
3507
+ } else {
3508
+ ref = refOrKey;
3509
+ options = parametersOrOptions;
3510
+ }
3511
+ const variables = options.variables ?? {};
3512
+ const functionKey = "functionKey" in ref ? ref.functionKey : void 0;
3513
+ const shouldCheck = functionKey !== void 0 && options.version === void 0 && options.validate !== false;
3514
+ if (shouldCheck) {
3515
+ const descriptor = await this.getCachedDescriptor(functionKey);
3516
+ const issues = checkAiFunctionParameters(descriptor.parameters, variables);
3517
+ if (issues.length > 0) {
3518
+ throw new AiFunctionParameterError(functionKey, issues);
3519
+ }
3520
+ }
3521
+ const body = {
3522
+ ref,
3523
+ variables,
3524
+ version: options.version,
3525
+ idempotencyKey: options.idempotencyKey ?? generateExecutionId(),
3526
+ params: options.params
3527
+ };
3528
+ try {
3529
+ return await this.httpPost("/run", body, {
3530
+ skipRetry: true,
3531
+ timeoutMs: AI_FUNCTION_RUN_TIMEOUT_MS
3532
+ });
3533
+ } catch (error) {
3534
+ throw this.mapRunError(error, functionKey);
3535
+ }
3536
+ }
3537
+ // ── internals ──────────────────────────────────────────────────────────────
3538
+ cacheDescriptor(descriptor, key) {
3539
+ if (!descriptor || typeof descriptor !== "object") return;
3540
+ const cacheKey = key ?? descriptor.functionKey;
3541
+ if (!cacheKey) return;
3542
+ this.descriptorCache.set(cacheKey, {
3543
+ descriptor,
3544
+ expiresAt: Date.now() + AI_FUNCTION_DESCRIPTOR_TTL_MS
3545
+ });
3546
+ }
3547
+ async getCachedDescriptor(functionKey) {
3548
+ const hit = this.descriptorCache.get(functionKey);
3549
+ if (hit && hit.expiresAt > Date.now()) return hit.descriptor;
3550
+ return this.get(functionKey);
3551
+ }
3552
+ mapRunError(error, functionKey) {
3553
+ if (!(error instanceof CadraError)) return error;
3554
+ if (error.serverCode === "DUPLICATE_REQUEST") {
3555
+ return new AiFunctionDuplicateError(error.message, error.details, error.requestId);
3556
+ }
3557
+ if (error.details?.charged === true) {
3558
+ return new AiFunctionChargedError(error);
3559
+ }
3560
+ if (functionKey && error.serverCode?.startsWith("VARIABLE_")) {
3561
+ this.descriptorCache.delete(functionKey);
3562
+ }
3563
+ return error;
3564
+ }
3565
+ };
3566
+
3361
3567
  // src/client.ts
3362
3568
  var DEFAULT_BASE_URL = "https://api.cadraos.com";
3363
3569
  var DEFAULT_TIMEOUT = 3e4;
@@ -3404,6 +3610,10 @@ var CadraClient = class {
3404
3610
  * Remote runner operations (list)
3405
3611
  */
3406
3612
  remoteRunners;
3613
+ /**
3614
+ * AI function operations (list, get, run, getRun) — p93
3615
+ */
3616
+ aiFunctions;
3407
3617
  /**
3408
3618
  * Create a new AI SaaS client
3409
3619
  *
@@ -3493,6 +3703,7 @@ var CadraClient = class {
3493
3703
  this.kanban = new KanbanAPI(this.httpClient, getStreamConfig);
3494
3704
  this.remoteAgents = new RemoteAgentsAPI(this.httpClient, getStreamConfig);
3495
3705
  this.remoteRunners = new RemoteRunnersAPI(this.httpClient);
3706
+ this.aiFunctions = new AiFunctionsAPI(this.httpClient);
3496
3707
  }
3497
3708
  /**
3498
3709
  * Validate client options
@@ -3517,6 +3728,12 @@ var CadraClient = class {
3517
3728
 
3518
3729
  exports.AISaaSClient = CadraClient;
3519
3730
  exports.AISaaSError = CadraError;
3731
+ exports.AI_FUNCTION_DESCRIPTOR_TTL_MS = AI_FUNCTION_DESCRIPTOR_TTL_MS;
3732
+ exports.AI_FUNCTION_RUN_TIMEOUT_MS = AI_FUNCTION_RUN_TIMEOUT_MS;
3733
+ exports.AiFunctionChargedError = AiFunctionChargedError;
3734
+ exports.AiFunctionDuplicateError = AiFunctionDuplicateError;
3735
+ exports.AiFunctionParameterError = AiFunctionParameterError;
3736
+ exports.AiFunctionsAPI = AiFunctionsAPI;
3520
3737
  exports.AuthenticationError = AuthenticationError;
3521
3738
  exports.AuthorizationError = AuthorizationError;
3522
3739
  exports.CadraClient = CadraClient;
@@ -3528,6 +3745,7 @@ exports.RateLimitError = RateLimitError;
3528
3745
  exports.ServerError = ServerError;
3529
3746
  exports.TimeoutError = TimeoutError;
3530
3747
  exports.ValidationError = ValidationError;
3748
+ exports.checkAiFunctionParameters = checkAiFunctionParameters;
3531
3749
  exports.collectImagesFromStream = collectImagesFromStream;
3532
3750
  exports.deriveImagesFromToolCalls = deriveImagesFromToolCalls;
3533
3751
  exports.extractImagesFromExecutionOutput = extractImagesFromExecutionOutput;