@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
package/README.md CHANGED
@@ -2,36 +2,19 @@
2
2
 
3
3
  Official SDK for the CadraOS platform - programmatic access to agents, skills, tools, and artifacts.
4
4
 
5
- > **Note**: For React chat components, use the new [@cadraos/react](https://www.npmjs.com/package/@cadraos/react) package.
6
- > The `@cadraos/sdk/chat` subpath is deprecated.
7
-
8
- ## Deprecation Notice
9
-
10
- The `@cadraos/sdk/chat` subpath is **deprecated** and will be removed in a future version.
11
-
12
- **If you're using React chat components**, please migrate to `@cadraos/react`:
13
-
14
- ```tsx
15
- // Before (deprecated)
16
- import { AgentChat, ChatConfigProvider } from '@cadraos/sdk/chat';
17
- import '@cadraos/sdk/chat/styles.css';
18
-
19
- // After (recommended)
20
- import '@cadraos/react/styles.css';
21
- import { CadraCopilot } from '@cadraos/react';
22
-
23
- function App() {
24
- return (
25
- <CadraCopilot
26
- apiKey="cdr_live_xxx"
27
- orgId={123}
28
- agentId="agent-uuid"
29
- />
30
- );
31
- }
32
- ```
33
-
34
- For full migration instructions, see the [migration guide](https://github.com/cadraos/cadra-sdk/blob/main/packages/react/MIGRATION.md).
5
+ ## Entry Points
6
+
7
+ | Import path | Contents |
8
+ |---|---|
9
+ | `@cadraos/sdk` | `CadraClient`, resource APIs, types, error classes, image-stream helpers |
10
+ | `@cadraos/sdk/chat` | React chat components and hooks (`AgentChat`, `ChatConfigProvider`, adapters) — the canonical chat surface |
11
+ | `@cadraos/sdk/teams` | React components for visualizing agent team structures |
12
+ | `@cadraos/sdk/kanban` | Agent-first kanban: React board + data adapter |
13
+ | `@cadraos/sdk/kanban/engine` | Server-side board engine (host backend only, never the browser) |
14
+ | `@cadraos/sdk/board-host` | Board-host mapping types + `<BoardHostMapping/>` editor widget (see [Board Host](#board-host-run-a-cadra-agentic-board-over-your-own-tables)) |
15
+ | `@cadraos/sdk/board-host/server` | Server board-host kit (read compiler) + `runBoardHostConformance` |
16
+ | `@cadraos/sdk/ai-functions/server` | Server-only handlers for host-app AI-function slots |
17
+ | `@cadraos/sdk/ai-functions/react` | `<AiFunctionSlotsPanel/>` client component (React is an optional peer dep) |
35
18
 
36
19
  ## Installation
37
20
 
@@ -50,7 +33,7 @@ import { CadraClient } from '@cadraos/sdk';
50
33
 
51
34
  // Initialize the client
52
35
  const client = new CadraClient({
53
- apiKey: process.env.CADRA_API_KEY!, // e.g., cdr_live_xxx
36
+ apiKey: process.env.CADRA_API_KEY!, // <api-key>
54
37
  orgId: Number(process.env.CADRA_ORG_ID),
55
38
  });
56
39
 
@@ -65,7 +48,7 @@ const execution = await client.agents.executeSync(agents[0].uuid, {
65
48
  console.log('Result:', execution.output);
66
49
  ```
67
50
 
68
- > **Note**: `AISaaSClient` is deprecated but still works as an alias for `CadraClient`.
51
+ > **Note**: `AISaaSClient` / `AISaaSError` are deprecated aliases for `CadraClient` / `CadraError`.
69
52
 
70
53
  ## Authentication
71
54
 
@@ -74,8 +57,8 @@ The SDK supports three authentication methods:
74
57
  ### API Key (recommended for server-side)
75
58
 
76
59
  ```typescript
77
- const client = new AISaaSClient({
78
- apiKey: 'sk_...',
60
+ const client = new CadraClient({
61
+ apiKey: '<api-key>',
79
62
  orgId: 123,
80
63
  });
81
64
  ```
@@ -83,8 +66,8 @@ const client = new AISaaSClient({
83
66
  ### OAuth Token
84
67
 
85
68
  ```typescript
86
- const client = new AISaaSClient({
87
- token: 'eyJ...',
69
+ const client = new CadraClient({
70
+ token: '<oauth-token>',
88
71
  orgId: 123,
89
72
  });
90
73
  ```
@@ -92,7 +75,7 @@ const client = new AISaaSClient({
92
75
  ### Token Provider (for automatic refresh)
93
76
 
94
77
  ```typescript
95
- const client = new AISaaSClient({
78
+ const client = new CadraClient({
96
79
  tokenProvider: async () => myAuth.getAccessToken(),
97
80
  orgId: 123,
98
81
  });
@@ -132,6 +115,8 @@ stream.on('log', (log) => console.log(log.title));
132
115
  stream.on('toolCall', ({ toolName }) => console.log(`Calling: ${toolName}`));
133
116
  stream.on('complete', ({ execution }) => console.log(execution.output));
134
117
 
118
+ // agents.stream() does NOT connect — register handlers first, then connect once
119
+ await stream.connect();
135
120
  const result = await stream.wait();
136
121
 
137
122
  // Get execution result
@@ -143,6 +128,14 @@ const updated = await client.agents.update('agent-uuid', {
143
128
  description: 'New description',
144
129
  });
145
130
 
131
+ // Update agent config
132
+ await client.agents.updateConfig('agent-uuid', { /* AgentConfigUpdateInput */ });
133
+
134
+ // Attach to an existing execution (register handlers, then connect once)
135
+ const live = client.agents.streamExecution('execution-uuid');
136
+ live.on('complete', ({ execution }) => console.log(execution.output));
137
+ await live.connect();
138
+
146
139
  // Cancel execution
147
140
  await client.agents.cancelExecution('execution-uuid');
148
141
  ```
@@ -280,7 +273,7 @@ const execution = await client.sessions.sendMessageSync('session-id', {
280
273
  message: 'Tell me more about that',
281
274
  });
282
275
 
283
- // Stream message
276
+ // Stream message (sessions.stream() connects for you)
284
277
  const stream = await client.sessions.stream('session-id', {
285
278
  message: 'Explain in detail',
286
279
  });
@@ -296,6 +289,66 @@ history.messages.forEach(msg => {
296
289
  await client.sessions.delete('session-id');
297
290
  ```
298
291
 
292
+ ### Attachments
293
+
294
+ ```typescript
295
+ // 1. Get a presigned upload URL
296
+ const { attachmentUuid, uploadUrl } = await client.attachments.getUploadUrl({
297
+ filename: 'photo.png',
298
+ mimeType: 'image/png',
299
+ size: file.size,
300
+ });
301
+ // 2. PUT the bytes to uploadUrl, then confirm
302
+ await client.attachments.confirm(attachmentUuid);
303
+ // 3. Reference it in an execution
304
+ await client.agents.execute('agent-uuid', { task: 'Describe this', attachmentIds: [attachmentUuid] });
305
+
306
+ // Download URL
307
+ const url = await client.attachments.getDownloadUrl(attachmentUuid);
308
+ ```
309
+
310
+ ### Teams
311
+
312
+ ```typescript
313
+ const { data: teams } = await client.teams.list({ isActive: true });
314
+ const team = await client.teams.get('team-uuid'); // includeMembers defaults to true
315
+ ```
316
+
317
+ ### Kanban
318
+
319
+ `client.kanban` drives an agentic board: `getBoard()`, `listCards()`, `createCard()`,
320
+ `getCard()`, `updateCard()`, `transitionCard({ cardId, ... })`, `getCardRun(executionId)`,
321
+ and `streamCardRun(executionId)` (attach `.on(...)` handlers, then call `.connect()` once).
322
+ See the [Kanban HTTP adapter guide](./docs/guides/kanban-http-adapter.md).
323
+
324
+ ### Remote Agents & Runners
325
+
326
+ `client.remoteAgents`: `list()`, `get()`, `create()`, `update()`, `delete()`, `deploy()`,
327
+ `execute()`, `stream()`. `client.remoteRunners`: `list()`.
328
+
329
+ ### AI Functions
330
+
331
+ ```typescript
332
+ // orgId must be set on the client config — never in run() options
333
+ const fns = await client.aiFunctions.list();
334
+ const descriptor = await client.aiFunctions.get('function_key');
335
+
336
+ // Shorthand: run(functionKey, parameters, opts?)
337
+ const result = await client.aiFunctions.run('function_key', { topic: 'AI' });
338
+ console.log(result.output, result.usage);
339
+
340
+ // Object form: run(ref, { variables, version?, idempotencyKey?, params?, validate? })
341
+ await client.aiFunctions.run({ functionKey: 'function_key' }, { variables: { topic: 'AI' } });
342
+
343
+ // Read a run back
344
+ const run = await client.aiFunctions.getRun(result.executionId);
345
+ ```
346
+
347
+ Paid runs are never auto-retried (an idempotency key is generated when omitted).
348
+ Errors: `AiFunctionParameterError` (client-side check failed, nothing sent),
349
+ `AiFunctionDuplicateError` (409), `AiFunctionChargedError` (metered but output failed).
350
+ See the [AI Functions reference](./docs/api-reference/ai-functions.md).
351
+
299
352
  ## Streaming
300
353
 
301
354
  The SDK supports real-time streaming for agent executions:
@@ -333,6 +386,9 @@ stream.on('connectionChange', ({ connected, usingFallback }) => {
333
386
  }
334
387
  });
335
388
 
389
+ // Connect AFTER registering handlers (agents.stream() does not auto-connect)
390
+ await stream.connect();
391
+
336
392
  // Wait for completion
337
393
  const execution = await stream.wait();
338
394
 
@@ -346,7 +402,7 @@ The SDK provides typed error classes for different error scenarios:
346
402
 
347
403
  ```typescript
348
404
  import {
349
- AISaaSError,
405
+ CadraError,
350
406
  AuthenticationError,
351
407
  AuthorizationError,
352
408
  NotFoundError,
@@ -370,7 +426,7 @@ try {
370
426
  error.errors.forEach(e => {
371
427
  console.log(`${e.field}: ${e.message}`);
372
428
  });
373
- } else if (error instanceof AISaaSError) {
429
+ } else if (error instanceof CadraError) {
374
430
  console.log(`Error [${error.code}]: ${error.message}`);
375
431
  console.log('Request ID:', error.requestId);
376
432
  }
@@ -380,18 +436,19 @@ try {
380
436
  ## Configuration Options
381
437
 
382
438
  ```typescript
383
- const client = new AISaaSClient({
439
+ const client = new CadraClient({
384
440
  // Required
385
- apiKey: 'sk_...', // or token/tokenProvider
441
+ apiKey: '<api-key>', // or token/tokenProvider
386
442
  orgId: 123,
387
443
 
388
444
  // Optional
389
- baseUrl: 'https://api.aisaas.com/v1', // Custom API URL
445
+ baseUrl: '<base-url>', // Origin only; SDK adds /api/v1 (default: https://api.cadraos.com)
390
446
  timeout: 30000, // Request timeout (ms)
391
447
  maxRetries: 3, // Retry attempts
392
448
  headers: { // Custom headers
393
449
  'X-Custom-Header': 'value',
394
450
  },
451
+ fetch: customFetch, // Optional fetch impl (e.g. expo/fetch for React Native streaming)
395
452
  });
396
453
  ```
397
454
 
@@ -413,16 +470,10 @@ import type {
413
470
 
414
471
  ## Browser Support
415
472
 
416
- The SDK works in modern browsers for non-streaming operations. Streaming (SSE) is only supported in Node.js in v1.
417
-
418
- ```typescript
419
- // Works in browser
420
- const agents = await client.agents.list();
421
- const execution = await client.agents.executeSync(uuid, { task: '...' });
422
-
423
- // Node.js only (v1)
424
- const stream = await client.agents.stream(uuid, { task: '...' });
425
- ```
473
+ The SDK works in Node.js >= 18 and modern browsers, including streaming: SSE is
474
+ read with `fetch` + `ReadableStream` and authenticates via headers. For React
475
+ Native streaming, pass a streaming-capable `fetch` (e.g. `expo/fetch`) in the
476
+ client options.
426
477
 
427
478
  ## Board Host (run a Cadra agentic board over your own tables)
428
479
 
@@ -0,0 +1,176 @@
1
+ 'use strict';
2
+
3
+ var React = require('react');
4
+ var jsxRuntime = require('react/jsx-runtime');
5
+
6
+ function _interopNamespace(e) {
7
+ if (e && e.__esModule) return e;
8
+ var n = Object.create(null);
9
+ if (e) {
10
+ Object.keys(e).forEach(function (k) {
11
+ if (k !== 'default') {
12
+ var d = Object.getOwnPropertyDescriptor(e, k);
13
+ Object.defineProperty(n, k, d.get ? d : {
14
+ enumerable: true,
15
+ get: function () { return e[k]; }
16
+ });
17
+ }
18
+ });
19
+ }
20
+ n.default = e;
21
+ return Object.freeze(n);
22
+ }
23
+
24
+ var React__namespace = /*#__PURE__*/_interopNamespace(React);
25
+
26
+ var DEFAULT_AI_FUNCTION_SLOTS_PANEL_LABELS = {
27
+ slot: "Slot",
28
+ usedFor: "Used for",
29
+ boundTo: "Bound to",
30
+ actions: "Actions",
31
+ notSet: "Not set",
32
+ reset: "Reset",
33
+ retry: "Retry",
34
+ loading: "Loading\u2026",
35
+ empty: "No AI function slots are declared.",
36
+ loadFailed: "Could not load AI function slots",
37
+ saveFailed: "Could not save",
38
+ incompatible: "Incompatible",
39
+ unavailable: "unavailable",
40
+ version: (n) => `v${n}`
41
+ };
42
+ function messageOf(error) {
43
+ if (error && typeof error === "object" && typeof error.message === "string") {
44
+ return error.message;
45
+ }
46
+ return typeof error === "string" ? error : "";
47
+ }
48
+ function AiFunctionSlotsPanel(props) {
49
+ const { api, className, classNames = {} } = props;
50
+ const L = { ...DEFAULT_AI_FUNCTION_SLOTS_PANEL_LABELS, ...props.labels };
51
+ const [state, setState] = React__namespace.useState({ status: "loading" });
52
+ const [pendingKey, setPendingKey] = React__namespace.useState(null);
53
+ const [rowErrors, setRowErrors] = React__namespace.useState({});
54
+ const mounted = React__namespace.useRef(true);
55
+ const load = React__namespace.useCallback(async () => {
56
+ try {
57
+ const rows2 = await api.listSlots();
58
+ if (mounted.current) setState({ status: "ready", rows: rows2 });
59
+ } catch (error) {
60
+ if (mounted.current) setState({ status: "error", message: messageOf(error) });
61
+ }
62
+ }, [api]);
63
+ React__namespace.useEffect(() => {
64
+ mounted.current = true;
65
+ void load();
66
+ return () => {
67
+ mounted.current = false;
68
+ };
69
+ }, [load]);
70
+ const mutate = async (key, action) => {
71
+ setPendingKey(key);
72
+ setRowErrors((e) => {
73
+ const next = { ...e };
74
+ delete next[key];
75
+ return next;
76
+ });
77
+ try {
78
+ await action();
79
+ await load();
80
+ } catch (error) {
81
+ if (mounted.current) {
82
+ const msg = messageOf(error);
83
+ setRowErrors((e) => ({ ...e, [key]: msg ? `${L.saveFailed}: ${msg}` : L.saveFailed }));
84
+ }
85
+ } finally {
86
+ if (mounted.current) setPendingKey(null);
87
+ }
88
+ };
89
+ const rootClass = [classNames.root, className].filter(Boolean).join(" ") || void 0;
90
+ if (state.status === "loading") {
91
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: rootClass, "aria-busy": "true", "data-state": "loading", children: L.loading });
92
+ }
93
+ if (state.status === "error") {
94
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: rootClass, "data-state": "error", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { role: "alert", className: classNames.banner, children: [
95
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: state.message ? `${L.loadFailed}: ${state.message}` : L.loadFailed }),
96
+ " ",
97
+ /* @__PURE__ */ jsxRuntime.jsx(
98
+ "button",
99
+ {
100
+ type: "button",
101
+ className: classNames.button,
102
+ onClick: () => {
103
+ setState({ status: "loading" });
104
+ void load();
105
+ },
106
+ children: L.retry
107
+ }
108
+ )
109
+ ] }) });
110
+ }
111
+ const { rows } = state;
112
+ if (rows.length === 0) {
113
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: rootClass, "data-state": "empty", children: L.empty });
114
+ }
115
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: rootClass, "data-state": "ready", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: classNames.table, children: [
116
+ /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: classNames.headerRow, children: [
117
+ /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: classNames.headerCell, children: L.slot }),
118
+ /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: classNames.headerCell, children: L.usedFor }),
119
+ /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: classNames.headerCell, children: L.boundTo }),
120
+ /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: classNames.headerCell, children: L.actions })
121
+ ] }) }),
122
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: rows.map((row) => {
123
+ const bound = row.binding?.functionKey ?? "";
124
+ const boundIsOption = row.options.some((o) => o.functionKey === bound);
125
+ const busy = pendingKey === row.key;
126
+ const incompatible = row.compat && !row.compat.compatible;
127
+ return /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: classNames.row, "data-slot": row.key, children: [
128
+ /* @__PURE__ */ jsxRuntime.jsxs("td", { className: classNames.cell, children: [
129
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: classNames.slotLabel, children: row.label }),
130
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: classNames.slotKey, children: row.key })
131
+ ] }),
132
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: classNames.cell, children: row.usedFor ?? "" }),
133
+ /* @__PURE__ */ jsxRuntime.jsxs("td", { className: classNames.cell, children: [
134
+ /* @__PURE__ */ jsxRuntime.jsxs(
135
+ "select",
136
+ {
137
+ "aria-label": `${L.boundTo}: ${row.label}`,
138
+ className: classNames.select,
139
+ value: bound,
140
+ disabled: busy,
141
+ onChange: (e) => {
142
+ const functionKey = e.target.value;
143
+ if (functionKey && functionKey !== bound) {
144
+ void mutate(row.key, () => api.setSlot({ key: row.key, functionKey }));
145
+ }
146
+ },
147
+ children: [
148
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", disabled: Boolean(bound), children: L.notSet }),
149
+ bound && !boundIsOption ? /* @__PURE__ */ jsxRuntime.jsx("option", { value: bound, disabled: true, children: `${row.boundFunction?.title ?? bound} (${incompatible ? L.incompatible : L.unavailable})` }) : null,
150
+ row.options.map((o) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: o.functionKey, children: `${o.title} \xB7 ${L.version(o.liveVersion)}` }, o.functionKey))
151
+ ]
152
+ }
153
+ ),
154
+ row.boundFunction ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: classNames.meta, children: `${row.boundFunction.functionKey} \xB7 ${L.version(row.boundFunction.liveVersion)}` }) : null,
155
+ incompatible ? /* @__PURE__ */ jsxRuntime.jsx("ul", { role: "alert", className: classNames.issues, "aria-label": L.incompatible, children: row.compat.issues.map((issue, i) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: issue.message }, i)) }) : null,
156
+ rowErrors[row.key] ? /* @__PURE__ */ jsxRuntime.jsx("div", { role: "alert", className: classNames.rowError, children: rowErrors[row.key] }) : null
157
+ ] }),
158
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: classNames.cell, children: /* @__PURE__ */ jsxRuntime.jsx(
159
+ "button",
160
+ {
161
+ type: "button",
162
+ className: classNames.button,
163
+ disabled: busy || !row.binding,
164
+ onClick: () => void mutate(row.key, () => api.resetSlot({ key: row.key })),
165
+ children: L.reset
166
+ }
167
+ ) })
168
+ ] }, row.key);
169
+ }) })
170
+ ] }) });
171
+ }
172
+
173
+ exports.AiFunctionSlotsPanel = AiFunctionSlotsPanel;
174
+ exports.DEFAULT_AI_FUNCTION_SLOTS_PANEL_LABELS = DEFAULT_AI_FUNCTION_SLOTS_PANEL_LABELS;
175
+ //# sourceMappingURL=index.cjs.map
176
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/ai-functions/react/AiFunctionSlotsPanel.tsx"],"names":["React","rows","jsx","jsxs"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * <AiFunctionSlotsPanel/> — admin table for a host app's AI function slots\n * (p93 AIF-017, specs D28).\n *\n * Table: Slot | Used for | Bound to (select of compatible functions + live\n * version) | Reset. Zero-dependency and unstyled: every element takes a class\n * from `classNames` so the host styles it with its own tokens. No toasts — a\n * failed load shows an error banner (never an empty table) and a failed write\n * shows inline on its row. All visible text can be replaced via `labels`.\n */\n\nimport * as React from 'react';\nimport type { AiFunctionSetSlotResult, AiFunctionSlotRow } from '../server/types.js';\n\nexport interface AiFunctionSlotsPanelApi {\n listSlots(): Promise<AiFunctionSlotRow[]>;\n setSlot(input: { key: string; functionKey: string }): Promise<AiFunctionSetSlotResult | unknown>;\n resetSlot(input: { key: string }): Promise<unknown>;\n}\n\nexport interface AiFunctionSlotsPanelLabels {\n slot: string;\n usedFor: string;\n boundTo: string;\n actions: string;\n notSet: string;\n reset: string;\n retry: string;\n loading: string;\n empty: string;\n loadFailed: string;\n saveFailed: string;\n incompatible: string;\n unavailable: string;\n version: (n: number) => string;\n}\n\nexport const DEFAULT_AI_FUNCTION_SLOTS_PANEL_LABELS: AiFunctionSlotsPanelLabels = {\n slot: 'Slot',\n usedFor: 'Used for',\n boundTo: 'Bound to',\n actions: 'Actions',\n notSet: 'Not set',\n reset: 'Reset',\n retry: 'Retry',\n loading: 'Loading…',\n empty: 'No AI function slots are declared.',\n loadFailed: 'Could not load AI function slots',\n saveFailed: 'Could not save',\n incompatible: 'Incompatible',\n unavailable: 'unavailable',\n version: (n) => `v${n}`,\n};\n\nexport type AiFunctionSlotsPanelPart =\n | 'root'\n | 'banner'\n | 'table'\n | 'headerRow'\n | 'headerCell'\n | 'row'\n | 'cell'\n | 'slotLabel'\n | 'slotKey'\n | 'select'\n | 'meta'\n | 'issues'\n | 'rowError'\n | 'button';\n\nexport interface AiFunctionSlotsPanelProps {\n api: AiFunctionSlotsPanelApi;\n /** Class on the root element. */\n className?: string;\n /** Classes per part, for host styling. */\n classNames?: Partial<Record<AiFunctionSlotsPanelPart, string>>;\n /** Replace any visible text. */\n labels?: Partial<AiFunctionSlotsPanelLabels>;\n}\n\ntype LoadState =\n | { status: 'loading' }\n | { status: 'ready'; rows: AiFunctionSlotRow[] }\n | { status: 'error'; message: string };\n\nfunction messageOf(error: unknown): string {\n if (error && typeof error === 'object' && typeof (error as { message?: unknown }).message === 'string') {\n return (error as { message: string }).message;\n }\n return typeof error === 'string' ? error : '';\n}\n\nexport function AiFunctionSlotsPanel(props: AiFunctionSlotsPanelProps): React.ReactElement {\n const { api, className, classNames = {} } = props;\n const L: AiFunctionSlotsPanelLabels = { ...DEFAULT_AI_FUNCTION_SLOTS_PANEL_LABELS, ...props.labels };\n\n const [state, setState] = React.useState<LoadState>({ status: 'loading' });\n const [pendingKey, setPendingKey] = React.useState<string | null>(null);\n const [rowErrors, setRowErrors] = React.useState<Record<string, string>>({});\n const mounted = React.useRef(true);\n\n const load = React.useCallback(async () => {\n try {\n const rows = await api.listSlots();\n if (mounted.current) setState({ status: 'ready', rows });\n } catch (error) {\n if (mounted.current) setState({ status: 'error', message: messageOf(error) });\n }\n }, [api]);\n\n React.useEffect(() => {\n mounted.current = true;\n void load();\n return () => {\n mounted.current = false;\n };\n }, [load]);\n\n const mutate = async (key: string, action: () => Promise<unknown>) => {\n setPendingKey(key);\n setRowErrors((e) => {\n const next = { ...e };\n delete next[key];\n return next;\n });\n try {\n await action();\n await load();\n } catch (error) {\n if (mounted.current) {\n const msg = messageOf(error);\n setRowErrors((e) => ({ ...e, [key]: msg ? `${L.saveFailed}: ${msg}` : L.saveFailed }));\n }\n } finally {\n if (mounted.current) setPendingKey(null);\n }\n };\n\n const rootClass = [classNames.root, className].filter(Boolean).join(' ') || undefined;\n\n if (state.status === 'loading') {\n return (\n <div className={rootClass} aria-busy=\"true\" data-state=\"loading\">\n {L.loading}\n </div>\n );\n }\n\n if (state.status === 'error') {\n return (\n <div className={rootClass} data-state=\"error\">\n <div role=\"alert\" className={classNames.banner}>\n <span>{state.message ? `${L.loadFailed}: ${state.message}` : L.loadFailed}</span>{' '}\n <button\n type=\"button\"\n className={classNames.button}\n onClick={() => {\n setState({ status: 'loading' });\n void load();\n }}\n >\n {L.retry}\n </button>\n </div>\n </div>\n );\n }\n\n const { rows } = state;\n if (rows.length === 0) {\n return (\n <div className={rootClass} data-state=\"empty\">\n {L.empty}\n </div>\n );\n }\n\n return (\n <div className={rootClass} data-state=\"ready\">\n <table className={classNames.table}>\n <thead>\n <tr className={classNames.headerRow}>\n <th scope=\"col\" className={classNames.headerCell}>{L.slot}</th>\n <th scope=\"col\" className={classNames.headerCell}>{L.usedFor}</th>\n <th scope=\"col\" className={classNames.headerCell}>{L.boundTo}</th>\n <th scope=\"col\" className={classNames.headerCell}>{L.actions}</th>\n </tr>\n </thead>\n <tbody>\n {rows.map((row) => {\n const bound = row.binding?.functionKey ?? '';\n const boundIsOption = row.options.some((o) => o.functionKey === bound);\n const busy = pendingKey === row.key;\n const incompatible = row.compat && !row.compat.compatible;\n return (\n <tr key={row.key} className={classNames.row} data-slot={row.key}>\n <td className={classNames.cell}>\n <div className={classNames.slotLabel}>{row.label}</div>\n <div className={classNames.slotKey}>{row.key}</div>\n </td>\n <td className={classNames.cell}>{row.usedFor ?? ''}</td>\n <td className={classNames.cell}>\n <select\n aria-label={`${L.boundTo}: ${row.label}`}\n className={classNames.select}\n value={bound}\n disabled={busy}\n onChange={(e) => {\n const functionKey = e.target.value;\n if (functionKey && functionKey !== bound) {\n void mutate(row.key, () => api.setSlot({ key: row.key, functionKey }));\n }\n }}\n >\n <option value=\"\" disabled={Boolean(bound)}>\n {L.notSet}\n </option>\n {bound && !boundIsOption ? (\n <option value={bound} disabled>\n {`${row.boundFunction?.title ?? bound} (${incompatible ? L.incompatible : L.unavailable})`}\n </option>\n ) : null}\n {row.options.map((o) => (\n <option key={o.functionKey} value={o.functionKey}>\n {`${o.title} · ${L.version(o.liveVersion)}`}\n </option>\n ))}\n </select>\n {row.boundFunction ? (\n <div className={classNames.meta}>\n {`${row.boundFunction.functionKey} · ${L.version(row.boundFunction.liveVersion)}`}\n </div>\n ) : null}\n {incompatible ? (\n <ul role=\"alert\" className={classNames.issues} aria-label={L.incompatible}>\n {row.compat!.issues.map((issue, i) => (\n <li key={i}>{issue.message}</li>\n ))}\n </ul>\n ) : null}\n {rowErrors[row.key] ? (\n <div role=\"alert\" className={classNames.rowError}>\n {rowErrors[row.key]}\n </div>\n ) : null}\n </td>\n <td className={classNames.cell}>\n <button\n type=\"button\"\n className={classNames.button}\n disabled={busy || !row.binding}\n onClick={() => void mutate(row.key, () => api.resetSlot({ key: row.key }))}\n >\n {L.reset}\n </button>\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n );\n}\n"]}
@@ -0,0 +1,129 @@
1
+ import * as React from 'react';
2
+
3
+ /**
4
+ * AI function types (p93 — specs §4 run contract, D27 discovery, §6.5 run reads).
5
+ *
6
+ * An AI function is a published prompt in the Cadra Prompts library that makes
7
+ * ONE direct AI-provider call (never an agent). Callers reference it by its
8
+ * `functionKey` (unique per org), by prompt uuid, or — for platform features —
9
+ * by slot key.
10
+ */
11
+ /** Output kind of an AI function. */
12
+ type AiFunctionOutputKind = 'text' | 'json' | 'image';
13
+ /** Parameter (prompt variable) types — specs D10 + D26d. */
14
+ type AiFunctionParameterType = 'string' | 'text' | 'number' | 'boolean' | 'enum' | 'image';
15
+
16
+ /**
17
+ * Host-app AI function slots — shared types (p93 AIF-017, specs D28).
18
+ *
19
+ * Type-only module: imported by both `@cadraos/sdk/ai-functions/server` and
20
+ * `@cadraos/sdk/ai-functions/react` (the panel renders the rows the server
21
+ * handlers return), so it must stay free of runtime code and of React.
22
+ */
23
+
24
+ /** One parameter a host slot passes when it calls its function. */
25
+ interface AiFunctionSlotParameter {
26
+ name: string;
27
+ type: AiFunctionParameterType;
28
+ required: boolean;
29
+ maxLength?: number;
30
+ options?: string[];
31
+ }
32
+ /** What a slot is bound to: a function of the host's Cadra org. */
33
+ interface AiFunctionSlotBinding {
34
+ functionKey: string;
35
+ }
36
+ /** Why a function does not fit a slot (D16 rule applied to a D27 descriptor). */
37
+ type AiFunctionSlotCompatIssueCode = 'function_unavailable' | 'output_kind' | 'parameter_missing' | 'parameter_type' | 'parameter_required' | 'options' | 'max_length';
38
+ interface AiFunctionSlotCompatIssue {
39
+ code: AiFunctionSlotCompatIssueCode;
40
+ /** The parameter concerned, when there is one. */
41
+ parameter?: string;
42
+ message: string;
43
+ }
44
+ interface AiFunctionSlotCompatVerdict {
45
+ compatible: boolean;
46
+ issues: AiFunctionSlotCompatIssue[];
47
+ }
48
+ /** A function offered in a slot's picker. */
49
+ interface AiFunctionSlotOption {
50
+ functionKey: string;
51
+ title: string;
52
+ liveVersion: number;
53
+ }
54
+ /** One row of `listSlots()` — catalog + binding + live descriptor + verdict. */
55
+ interface AiFunctionSlotRow {
56
+ key: string;
57
+ label: string;
58
+ usedFor: string | null;
59
+ outputKind: AiFunctionOutputKind;
60
+ parameters: AiFunctionSlotParameter[];
61
+ /** The stored binding, or null when the slot is unset. */
62
+ binding: AiFunctionSlotBinding | null;
63
+ /** The bound function's live descriptor summary; null when unset or unavailable. */
64
+ boundFunction: (AiFunctionSlotOption & {
65
+ outputKind: AiFunctionOutputKind;
66
+ }) | null;
67
+ /** Compatibility of the bound function; null when the slot is unset. */
68
+ compat: AiFunctionSlotCompatVerdict | null;
69
+ /** Functions compatible with this slot (the picker's choices). */
70
+ options: AiFunctionSlotOption[];
71
+ }
72
+ /** Result of a successful `setSlot`. */
73
+ interface AiFunctionSetSlotResult {
74
+ key: string;
75
+ functionKey: string;
76
+ liveVersion: number;
77
+ }
78
+
79
+ /**
80
+ * <AiFunctionSlotsPanel/> — admin table for a host app's AI function slots
81
+ * (p93 AIF-017, specs D28).
82
+ *
83
+ * Table: Slot | Used for | Bound to (select of compatible functions + live
84
+ * version) | Reset. Zero-dependency and unstyled: every element takes a class
85
+ * from `classNames` so the host styles it with its own tokens. No toasts — a
86
+ * failed load shows an error banner (never an empty table) and a failed write
87
+ * shows inline on its row. All visible text can be replaced via `labels`.
88
+ */
89
+
90
+ interface AiFunctionSlotsPanelApi {
91
+ listSlots(): Promise<AiFunctionSlotRow[]>;
92
+ setSlot(input: {
93
+ key: string;
94
+ functionKey: string;
95
+ }): Promise<AiFunctionSetSlotResult | unknown>;
96
+ resetSlot(input: {
97
+ key: string;
98
+ }): Promise<unknown>;
99
+ }
100
+ interface AiFunctionSlotsPanelLabels {
101
+ slot: string;
102
+ usedFor: string;
103
+ boundTo: string;
104
+ actions: string;
105
+ notSet: string;
106
+ reset: string;
107
+ retry: string;
108
+ loading: string;
109
+ empty: string;
110
+ loadFailed: string;
111
+ saveFailed: string;
112
+ incompatible: string;
113
+ unavailable: string;
114
+ version: (n: number) => string;
115
+ }
116
+ declare const DEFAULT_AI_FUNCTION_SLOTS_PANEL_LABELS: AiFunctionSlotsPanelLabels;
117
+ type AiFunctionSlotsPanelPart = 'root' | 'banner' | 'table' | 'headerRow' | 'headerCell' | 'row' | 'cell' | 'slotLabel' | 'slotKey' | 'select' | 'meta' | 'issues' | 'rowError' | 'button';
118
+ interface AiFunctionSlotsPanelProps {
119
+ api: AiFunctionSlotsPanelApi;
120
+ /** Class on the root element. */
121
+ className?: string;
122
+ /** Classes per part, for host styling. */
123
+ classNames?: Partial<Record<AiFunctionSlotsPanelPart, string>>;
124
+ /** Replace any visible text. */
125
+ labels?: Partial<AiFunctionSlotsPanelLabels>;
126
+ }
127
+ declare function AiFunctionSlotsPanel(props: AiFunctionSlotsPanelProps): React.ReactElement;
128
+
129
+ export { type AiFunctionSetSlotResult, type AiFunctionSlotCompatVerdict, type AiFunctionSlotOption, type AiFunctionSlotRow, AiFunctionSlotsPanel, type AiFunctionSlotsPanelApi, type AiFunctionSlotsPanelLabels, type AiFunctionSlotsPanelPart, type AiFunctionSlotsPanelProps, DEFAULT_AI_FUNCTION_SLOTS_PANEL_LABELS };