@cadraos/sdk 0.3.14-p46.4 → 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 (38) 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/chat/index.cjs +299 -17
  15. package/dist/chat/index.cjs.map +1 -1
  16. package/dist/chat/index.d.cts +208 -0
  17. package/dist/chat/index.d.ts +208 -0
  18. package/dist/chat/index.js +299 -17
  19. package/dist/chat/index.js.map +1 -1
  20. package/dist/index.cjs +221 -3
  21. package/dist/index.cjs.map +1 -1
  22. package/dist/index.d.cts +269 -1
  23. package/dist/index.d.ts +269 -1
  24. package/dist/index.js +215 -4
  25. package/dist/index.js.map +1 -1
  26. package/dist/kanban/index.cjs +214 -3
  27. package/dist/kanban/index.cjs.map +1 -1
  28. package/dist/kanban/index.d.cts +208 -0
  29. package/dist/kanban/index.d.ts +208 -0
  30. package/dist/kanban/index.js +214 -3
  31. package/dist/kanban/index.js.map +1 -1
  32. package/dist/teams/index.cjs +214 -3
  33. package/dist/teams/index.cjs.map +1 -1
  34. package/dist/teams/index.d.cts +208 -0
  35. package/dist/teams/index.d.ts +208 -0
  36. package/dist/teams/index.js +214 -3
  37. package/dist/teams/index.js.map +1 -1
  38. package/package.json +21 -1
@@ -3672,6 +3672,14 @@ var CadraError = class extends Error {
3672
3672
  details;
3673
3673
  /** Request ID from server (for debugging) */
3674
3674
  requestId;
3675
+ /**
3676
+ * The server's own `error.code` exactly as sent on the wire (e.g.
3677
+ * `FUNCTION_NOT_PUBLISHED`, `DUPLICATE_REQUEST`, `VARIABLE_TYPE`).
3678
+ * Populated by `parseApiError` for EVERY status. `code` keeps its historic
3679
+ * per-class values (`conflict`, `server_error`, `validation_error`, …) for
3680
+ * compatibility; branch on `serverCode` when you need the precise reason.
3681
+ */
3682
+ serverCode;
3675
3683
  constructor(message, code, status, details, requestId) {
3676
3684
  super(message);
3677
3685
  this.name = "CadraError";
@@ -3749,6 +3757,12 @@ function parseApiError(status, body, requestId) {
3749
3757
  const message = errorBody?.error?.message ?? "An error occurred";
3750
3758
  const code = errorBody?.error?.code ?? "unknown_error";
3751
3759
  const details = errorBody?.error?.details;
3760
+ const serverCode = typeof errorBody?.error?.code === "string" ? errorBody.error.code : void 0;
3761
+ const error = buildApiError(status, message, code, details, requestId);
3762
+ if (serverCode !== void 0) error.serverCode = serverCode;
3763
+ return error;
3764
+ }
3765
+ function buildApiError(status, message, code, details, requestId) {
3752
3766
  switch (status) {
3753
3767
  case 400:
3754
3768
  case 422: {
@@ -3784,6 +3798,42 @@ function parseApiError(status, body, requestId) {
3784
3798
  }
3785
3799
  }
3786
3800
 
3801
+ // src/errors/ai-function-errors.ts
3802
+ var AiFunctionDuplicateError = class extends ConflictError {
3803
+ /** The existing run's execution id. */
3804
+ executionId;
3805
+ /** The existing run's status (`running`, a terminal status, or `abandoned`). */
3806
+ runStatus;
3807
+ constructor(message, details, requestId) {
3808
+ super(message, details, requestId);
3809
+ this.name = "AiFunctionDuplicateError";
3810
+ this.serverCode = "DUPLICATE_REQUEST";
3811
+ this.executionId = typeof details?.executionId === "string" ? details.executionId : void 0;
3812
+ this.runStatus = typeof details?.status === "string" ? details.status : void 0;
3813
+ }
3814
+ };
3815
+ var AiFunctionChargedError = class extends CadraError {
3816
+ constructor(source) {
3817
+ super(source.message, source.code, source.status, source.details, source.requestId);
3818
+ this.name = "AiFunctionChargedError";
3819
+ this.serverCode = source.serverCode;
3820
+ }
3821
+ };
3822
+ var AiFunctionParameterError = class extends ValidationError {
3823
+ functionKey;
3824
+ issues;
3825
+ constructor(functionKey, issues) {
3826
+ super(
3827
+ `Invalid parameters for AI function "${functionKey}": ` + issues.map((i) => `${i.name} (${i.code})`).join(", "),
3828
+ issues.map((i) => ({ field: i.name, message: i.code })),
3829
+ { functionKey, issues }
3830
+ );
3831
+ this.name = "AiFunctionParameterError";
3832
+ this.functionKey = functionKey;
3833
+ this.issues = issues;
3834
+ }
3835
+ };
3836
+
3787
3837
  // src/utils/retry.ts
3788
3838
  var DEFAULT_RETRY_CONFIG = {
3789
3839
  maxRetries: 3,
@@ -3902,7 +3952,8 @@ var HttpClient = class {
3902
3952
  headers["Idempotency-Key"] = options.idempotencyKey;
3903
3953
  }
3904
3954
  const controller = new AbortController();
3905
- const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
3955
+ const timeoutMs = options.timeoutMs ?? this.config.timeout;
3956
+ const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
3906
3957
  try {
3907
3958
  const doFetch = this.config.fetch ?? fetch;
3908
3959
  const response = await doFetch(url, {
@@ -3938,7 +3989,7 @@ var HttpClient = class {
3938
3989
  } catch (error) {
3939
3990
  clearTimeout(timeoutId);
3940
3991
  if (error instanceof Error && error.name === "AbortError") {
3941
- throw new TimeoutError(`Request timed out after ${this.config.timeout}ms`);
3992
+ throw new TimeoutError(`Request timed out after ${options.timeoutMs ?? this.config.timeout}ms`);
3942
3993
  }
3943
3994
  if (error instanceof TypeError && error.message.includes("fetch")) {
3944
3995
  throw new NetworkError(`Network error: ${error.message}`);
@@ -3970,7 +4021,8 @@ var HttpClient = class {
3970
4021
  path,
3971
4022
  body,
3972
4023
  idempotencyKey: options?.idempotencyKey,
3973
- skipRetry: options?.skipRetry
4024
+ skipRetry: options?.skipRetry,
4025
+ timeoutMs: options?.timeoutMs
3974
4026
  });
3975
4027
  }
3976
4028
  /**
@@ -4719,6 +4771,10 @@ var ExecutionStreamControllerImpl = class {
4719
4771
  toolName,
4720
4772
  result: data.result,
4721
4773
  durationMs: data.durationMs ?? 0,
4774
+ // CAD-243: pass the producer's failure verdict through.
4775
+ ...data.isError === true ? { isError: true } : {},
4776
+ ...typeof data.status === "string" ? { status: data.status } : {},
4777
+ ...typeof data.error === "string" ? { error: data.error } : {},
4722
4778
  forwardedFrom: event.data._forwardedFrom,
4723
4779
  // CAD-87 S1-001 EventIdentity → (execId, seq) reducer dedup (S1-003).
4724
4780
  sourceExecutionId: data.sourceExecutionId ?? data.executionId,
@@ -6957,6 +7013,156 @@ var RemoteRunnersAPI = class extends BaseResourceAPI {
6957
7013
  }
6958
7014
  };
6959
7015
 
7016
+ // src/resources/ai-functions.ts
7017
+ var AI_FUNCTION_RUN_TIMEOUT_MS = 6e4;
7018
+ var AI_FUNCTION_DESCRIPTOR_TTL_MS = 6e4;
7019
+ function checkAiFunctionParameters(parameters, variables) {
7020
+ const issues = [];
7021
+ const declared = /* @__PURE__ */ new Set();
7022
+ for (const p of parameters) {
7023
+ declared.add(p.name);
7024
+ const has = Object.prototype.hasOwnProperty.call(variables, p.name);
7025
+ const value = has ? variables[p.name] : void 0;
7026
+ if (value === void 0 || value === null) {
7027
+ if (p.required) issues.push({ name: p.name, code: "missing" });
7028
+ continue;
7029
+ }
7030
+ switch (p.type) {
7031
+ case "number":
7032
+ if (typeof value !== "number" || !Number.isFinite(value)) {
7033
+ issues.push({ name: p.name, code: "type" });
7034
+ }
7035
+ break;
7036
+ case "boolean":
7037
+ if (typeof value !== "boolean") issues.push({ name: p.name, code: "type" });
7038
+ break;
7039
+ case "enum":
7040
+ if (typeof value !== "string") issues.push({ name: p.name, code: "type" });
7041
+ else if (p.options && !p.options.includes(value)) {
7042
+ issues.push({ name: p.name, code: "option" });
7043
+ }
7044
+ break;
7045
+ case "string":
7046
+ case "text":
7047
+ if (typeof value !== "string") issues.push({ name: p.name, code: "type" });
7048
+ else if (typeof p.maxLength === "number" && value.length > p.maxLength) {
7049
+ issues.push({ name: p.name, code: "too_long" });
7050
+ }
7051
+ break;
7052
+ case "image":
7053
+ if (typeof value !== "string") issues.push({ name: p.name, code: "type" });
7054
+ break;
7055
+ }
7056
+ }
7057
+ for (const name of Object.keys(variables)) {
7058
+ if (!declared.has(name)) issues.push({ name, code: "unknown" });
7059
+ }
7060
+ return issues;
7061
+ }
7062
+ var AiFunctionsAPI = class extends BaseResourceAPI {
7063
+ descriptorCache = /* @__PURE__ */ new Map();
7064
+ constructor(http) {
7065
+ super(http, "/api/v1/ai-functions");
7066
+ }
7067
+ /**
7068
+ * List the functions this org can call — the index (D27a). Each entry carries
7069
+ * the live version's typed parameters; never prompt text.
7070
+ */
7071
+ async list() {
7072
+ const data = await this.httpGet("");
7073
+ const functions = Array.isArray(data) ? data : data?.functions ?? [];
7074
+ for (const d of functions) this.cacheDescriptor(d);
7075
+ return functions;
7076
+ }
7077
+ /**
7078
+ * Get one function's descriptor by key (D27a).
7079
+ * `NotFoundError` (`FUNCTION_NOT_FOUND`) / `ConflictError` (`FUNCTION_NOT_PUBLISHED`).
7080
+ */
7081
+ async get(functionKey) {
7082
+ const data = await this.httpGet(
7083
+ `/${encodeURIComponent(functionKey)}`
7084
+ );
7085
+ const descriptor = data && typeof data === "object" && "function" in data && !("functionKey" in data) ? data.function : data;
7086
+ this.cacheDescriptor(descriptor, functionKey);
7087
+ return descriptor;
7088
+ }
7089
+ /**
7090
+ * Read one of this org's own runs (safe projection, §6.5).
7091
+ */
7092
+ async getRun(executionId) {
7093
+ return this.httpGet(`/runs/${encodeURIComponent(executionId)}`);
7094
+ }
7095
+ /** Forget cached descriptors (one key, or all). */
7096
+ clearDescriptorCache(functionKey) {
7097
+ if (functionKey) this.descriptorCache.delete(functionKey);
7098
+ else this.descriptorCache.clear();
7099
+ }
7100
+ async run(refOrKey, parametersOrOptions, shorthandOpts) {
7101
+ let ref;
7102
+ let options;
7103
+ if (typeof refOrKey === "string") {
7104
+ ref = { functionKey: refOrKey };
7105
+ options = { ...shorthandOpts ?? {}, variables: parametersOrOptions };
7106
+ } else {
7107
+ ref = refOrKey;
7108
+ options = parametersOrOptions;
7109
+ }
7110
+ const variables = options.variables ?? {};
7111
+ const functionKey = "functionKey" in ref ? ref.functionKey : void 0;
7112
+ const shouldCheck = functionKey !== void 0 && options.version === void 0 && options.validate !== false;
7113
+ if (shouldCheck) {
7114
+ const descriptor = await this.getCachedDescriptor(functionKey);
7115
+ const issues = checkAiFunctionParameters(descriptor.parameters, variables);
7116
+ if (issues.length > 0) {
7117
+ throw new AiFunctionParameterError(functionKey, issues);
7118
+ }
7119
+ }
7120
+ const body = {
7121
+ ref,
7122
+ variables,
7123
+ version: options.version,
7124
+ idempotencyKey: options.idempotencyKey ?? generateExecutionId(),
7125
+ params: options.params
7126
+ };
7127
+ try {
7128
+ return await this.httpPost("/run", body, {
7129
+ skipRetry: true,
7130
+ timeoutMs: AI_FUNCTION_RUN_TIMEOUT_MS
7131
+ });
7132
+ } catch (error) {
7133
+ throw this.mapRunError(error, functionKey);
7134
+ }
7135
+ }
7136
+ // ── internals ──────────────────────────────────────────────────────────────
7137
+ cacheDescriptor(descriptor, key) {
7138
+ if (!descriptor || typeof descriptor !== "object") return;
7139
+ const cacheKey = key ?? descriptor.functionKey;
7140
+ if (!cacheKey) return;
7141
+ this.descriptorCache.set(cacheKey, {
7142
+ descriptor,
7143
+ expiresAt: Date.now() + AI_FUNCTION_DESCRIPTOR_TTL_MS
7144
+ });
7145
+ }
7146
+ async getCachedDescriptor(functionKey) {
7147
+ const hit = this.descriptorCache.get(functionKey);
7148
+ if (hit && hit.expiresAt > Date.now()) return hit.descriptor;
7149
+ return this.get(functionKey);
7150
+ }
7151
+ mapRunError(error, functionKey) {
7152
+ if (!(error instanceof CadraError)) return error;
7153
+ if (error.serverCode === "DUPLICATE_REQUEST") {
7154
+ return new AiFunctionDuplicateError(error.message, error.details, error.requestId);
7155
+ }
7156
+ if (error.details?.charged === true) {
7157
+ return new AiFunctionChargedError(error);
7158
+ }
7159
+ if (functionKey && error.serverCode?.startsWith("VARIABLE_")) {
7160
+ this.descriptorCache.delete(functionKey);
7161
+ }
7162
+ return error;
7163
+ }
7164
+ };
7165
+
6960
7166
  // src/client.ts
6961
7167
  var DEFAULT_BASE_URL = "https://api.cadraos.com";
6962
7168
  var DEFAULT_TIMEOUT = 3e4;
@@ -7003,6 +7209,10 @@ var CadraClient = class {
7003
7209
  * Remote runner operations (list)
7004
7210
  */
7005
7211
  remoteRunners;
7212
+ /**
7213
+ * AI function operations (list, get, run, getRun) — p93
7214
+ */
7215
+ aiFunctions;
7006
7216
  /**
7007
7217
  * Create a new AI SaaS client
7008
7218
  *
@@ -7092,6 +7302,7 @@ var CadraClient = class {
7092
7302
  this.kanban = new KanbanAPI(this.httpClient, getStreamConfig);
7093
7303
  this.remoteAgents = new RemoteAgentsAPI(this.httpClient, getStreamConfig);
7094
7304
  this.remoteRunners = new RemoteRunnersAPI(this.httpClient);
7305
+ this.aiFunctions = new AiFunctionsAPI(this.httpClient);
7095
7306
  }
7096
7307
  /**
7097
7308
  * Validate client options