@colixsystems/widget-sdk 0.152.0 → 0.154.0
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.
- package/README.md +18 -2
- package/dist/contract.cjs +11 -1
- package/dist/contract.js +11 -1
- package/dist/datetimepicker-format.js +24 -5
- package/dist/datetimepicker.js +7 -13
- package/dist/hooks.js +3 -1
- package/dist/host.d.ts +19 -0
- package/dist/host.js +7 -0
- package/dist/index.d.ts +21 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -47,7 +47,7 @@ The data layer lives in **four separate domain-client packages**, each instantia
|
|
|
47
47
|
| **DATASTORE** | `useDatastoreSchema(tableId)` | `{ schema, loading, error, refetch }` | `schema(tableId)` — `datastore.read:<table>` |
|
|
48
48
|
| **DATASTORE** | `useBoundColumns(tableId, shape, props)` | `{ columns, resolved, missing, loading, error }` | `schema(tableId)` (built on `useDatastoreSchema`) — `datastore.read:<table>`. Resolves author-bound column NAMES from `props` by exact name → case-insensitive name → first unclaimed column matching `shape[key].dataType`, so a column an author renamed after install still resolves instead of `record[props.titleField]` reading `undefined`. `columns` holds the resolved NAME (`record[columns.titleField]`); `resolved` holds the full `Column`; `missing` lists non-`optional` keys that never resolved. Falsy `tableId` collapses to `{ columns: {}, resolved: {}, missing: Object.keys(shape), loading: false, error: null }`. |
|
|
49
49
|
| **DATASTORE** | `useInterpretDraft(tableId)` | `{ interpret, interpreting, error, result, available }` | `interpret(tableId, body)` — `datastore.read:<table>`. Turns ONE sentence a user typed ("walk at 11 am tomorrow") into DRAFT column values so a form can prefill itself. IMPERATIVE: call `interpret(text, { fields?, timeZone? })` from an event handler, never on mount. It DRAFTS and writes nothing — show the values for review, then submit through `useDatastoreMutation().create`. Resolves to `{ values, unresolved }`; `values` is keyed by column NAME (the shape `create()` takes) and `unresolved` names the fields the sentence did not state. Only text / number / boolean / date / datetime / array columns are drafted — `FILE`, `RELATION`, `USER` and `USER_GROUP` carry ids and are never guessed. Fails closed to an empty draft. **Every call spends the workspace's AI credits** and is rate-limited per actor, so call it once per user action (never on mount or in a render loop); once the workspace runs out the call is refused with a generic 429 — an app user is deliberately **not** told the workspace's billing state, since they have never heard of an AI credit and cannot buy one. Never surface a raw error to the person filling the form: say drafting is unavailable and keep every field editable by hand. `available` is false where the host brokers no interpreter. |
|
|
50
|
-
| **AGENTS** | `useAgent(agentRef)` | `{ send, reset, messages, sending, error, available }` | `ctx.agents` — `ai.invoke:*`. Hold a conversation with one of the WORKSPACE's own AI agents (an author-written name + system prompt). IMPERATIVE: call `send(text)` from an event handler, never on mount — the first send opens the conversation, so a widget nobody types into costs nothing. `messages` is the running transcript, oldest first. You **cannot** set or read the system prompt, replay an edited transcript, or pick a model: the server assembles every turn from the stored prompt plus the stored history, and `content` is the only thing that reaches the wire. `reset()` drops the thread (a "new chat" affordance). **Every send spends the workspace's AI credits** and is rate-limited per caller AND per workspace. Rejects with `AgentError`; branch on `.code` — `AI_QUOTA_EXCEEDED` (429) is the workspace's credit ceiling and will NOT clear on a retry, unlike `RATE_LIMITED`, so never offer "try again" for it, and `AGENT_DISABLED` (409) means the author turned it off, so hide the affordance. Never surface a raw error or the workspace's billing state to an app user. `available` is false when no agent is bound or the host brokers none — render a visible unbound state, never a blank box. |
|
|
50
|
+
| **AGENTS** | `useAgent(agentRef)` | `{ send, reset, messages, sending, error, available }` | `ctx.agents` — `ai.invoke:*`. Hold a conversation with one of the WORKSPACE's own AI agents (an author-written name + system prompt). IMPERATIVE: call `send(text)` from an event handler, never on mount — the first send opens the conversation, so a widget nobody types into costs nothing. `messages` is the running transcript, oldest first. You **cannot** set or read the system prompt, replay an edited transcript, or pick a model: the server assembles every turn from the stored prompt plus the stored history, and `content` is the only thing that reaches the wire. `reset()` drops the thread (a "new chat" affordance). **Every send spends the workspace's AI credits** and is rate-limited per caller AND per workspace. Rejects with `AgentError`; branch on `.code` — `AI_QUOTA_EXCEEDED` (429) is the workspace's credit ceiling and will NOT clear on a retry, unlike `RATE_LIMITED`, so never offer "try again" for it, and `AGENT_DISABLED` (409) means the author turned it off, so hide the affordance. Never surface a raw error or the workspace's billing state to an app user. `available` is false when no agent is bound or the host brokers none — render a visible unbound state, never a blank box. An assistant message that used a tool also carries **`activity`** — what the agent DID with the user's data: the table it read, or the table and columns it CHANGED (never the values, and never a row the permissions refused). **Render a write.** A reply saying "done!" is not evidence a row was written, and if the agent got it wrong the user has no other way to notice. A talk-only turn omits the key entirely. |
|
|
51
51
|
| **DATASTORE** | `useDatastoreMutation(table)` | `{ create, update, delete }` | `records(table).{ create, update (PATCH), delete }` — `datastore.write:*`. **To CLEAR a cell, pass it empty** — `update(id, { when: null })` (also `""` or `[]`) empties that cell and it reads back as `null` (`[]` on an array column). There is no separate clear call, so never write a sentinel such as `0` or a placeholder date to mean "no value". `false` and `0` are values, not clears, and a REQUIRED column cannot be cleared. |
|
|
52
52
|
| **DATASTORE** | `useDatastoreSubscription(table, handlers, options)` (optional: options) | `{ status }` — `"connecting" \| "live" \| "reconnecting" \| "fallback"` | `records(table).subscribe` — `datastore.read:<table>`. Live `onCreated` / `onUpdated` / `onDeleted` off the REQ-RT-07 socket; never throws, resolving to `{ status: "fallback" }` so the widget polls instead. A whole-table subscribe is gated on read-EVERY-row, because one envelope reaches every subscriber of the table — so for a table governed by per-record grants pass `options.scope`: `{ kind: "record", record_id }` for one row, or `{ kind: "parent", relation_column, record_id }` for the rows whose RELATION column points at that parent (the column must carry `inheritAcl`, else the subscribe reports `"fallback"`). Re-subscribes on the scope's VALUES, so a fresh object literal each render is fine. |
|
|
53
53
|
| **DATASTORE** | `useRecordPermissions(tableId, recordId)` | `{ permissions, loading, error, grant, revoke, update, refetch }` | `records(table).permissions(record).{ list, grant, update, revoke }` — `acl.write:records` (+ `can_grant` on the record) |
|
|
@@ -72,7 +72,23 @@ See the design reference for the full architecture: [`docs/architecture/widget-m
|
|
|
72
72
|
|
|
73
73
|
## Status
|
|
74
74
|
|
|
75
|
-
`v0.
|
|
75
|
+
`v0.154.0` — pre-publish. The package surface (types, function names, export paths) is the v1 contract; runtime behaviour for some hooks is stubbed (each hook documents what's wired and what isn't). It is **not yet published to npm**.
|
|
76
|
+
|
|
77
|
+
### What's new in 0.154.0 (contract 1.120.0)
|
|
78
|
+
|
|
79
|
+
**An agent can now tell you what it DID (sc-8332).** An assistant `AgentMessage` may carry `activity`: one entry per tool the agent ran, naming the table it read, or the table and the columns it changed. Additive — a talk-only turn omits the key, so nothing existing changes shape.
|
|
80
|
+
|
|
81
|
+
Render the writes. An assistant that silently changes a person's data is not trustworthy however correct its permissions are, and a chat bubble saying "done!" is not evidence a row was written. Reads can stay quiet; a change should not. The summary never carries row VALUES and never names a row the permissions refused, so showing it cannot leak what the reader could not already see.
|
|
82
|
+
|
|
83
|
+
### What's new in 0.153.0 (contract 1.118.0 — unchanged)
|
|
84
|
+
|
|
85
|
+
**`./host` publishes the local-clock DATETIME conversion `<DateTimePicker>` uses (sc-8448).** The Studio's Data Manager sliced the stored UTC string and saved the input's value without a zone, so it showed and wrote UTC labelled as local. It now reads the same conversion the picker does, so a stored instant shows the same wall clock in the Studio and in the Player.
|
|
86
|
+
|
|
87
|
+
- **`isoToDateTimeLocalInput(value)`** — a stored instant as `<input type="datetime-local">`'s `YYYY-MM-DDTHH:mm` on the viewer's clock. A bare `YYYY-MM-DD` is local midnight.
|
|
88
|
+
- **`dateTimeLocalInputToIso(raw)`** — the inverse: a local `YYYY-MM-DDTHH:mm` as a full UTC ISO instant.
|
|
89
|
+
- **`formatDateTimeLabel(value, mode)`** — the picker's trigger label (`YYYY-MM-DD HH:mm` local for `"datetime"`).
|
|
90
|
+
|
|
91
|
+
Behaviour: a bare date given to a `mode="datetime"` picker now shows local midnight instead of UTC midnight (which read as the previous evening west of Greenwich), and a year before 1000 is zero-padded so typing a year no longer clears the web input. Otherwise additive.
|
|
76
92
|
|
|
77
93
|
### What's new in 0.152.0 (contract 1.118.0 — unchanged)
|
|
78
94
|
|
package/dist/contract.cjs
CHANGED
|
@@ -1286,6 +1286,11 @@ const HOOKS = [
|
|
|
1286
1286
|
"opens the conversation, so a widget nobody types into costs nothing. " +
|
|
1287
1287
|
"`messages` is the running transcript, oldest first, each " +
|
|
1288
1288
|
"{ id, role, content, created_at } with role 'user' | 'assistant'. " +
|
|
1289
|
+
"An assistant message that used a tool also carries `activity`: what " +
|
|
1290
|
+
"the agent DID — the table it read, or the table and columns it " +
|
|
1291
|
+
"CHANGED. Render a write: a reply saying 'done!' is not evidence a " +
|
|
1292
|
+
"row was written, and the user has no other way to notice a mistake. " +
|
|
1293
|
+
"A talk-only turn omits the key entirely. " +
|
|
1289
1294
|
"You CANNOT set the system prompt, replay an edited transcript, " +
|
|
1290
1295
|
"or pick a model. No API returns the prompt — but that is a guarantee " +
|
|
1291
1296
|
"about the WIRE, not secrecy: a model can be talked into repeating its " +
|
|
@@ -4227,6 +4232,11 @@ const CONTRACT = deepFreeze({
|
|
|
4227
4232
|
// and the inherited colours are hex-guarded on the way out as well as in.
|
|
4228
4233
|
// Every colour still falls back to the sidebar's: an untouched workspace is
|
|
4229
4234
|
// unchanged.
|
|
4235
|
+
// 1.120.0: additive (sc-8332) — an assistant `AgentMessage` may carry
|
|
4236
|
+
// `activity`, a compact record of what the agent DID with the user's data
|
|
4237
|
+
// (the table it read; the table and columns it CHANGED). Absent on a
|
|
4238
|
+
// talk-only turn, so nothing existing changes shape. Render a write: a
|
|
4239
|
+
// reply saying "done!" is not evidence a row was written.
|
|
4230
4240
|
// 1.116.0: additive (sc-7991) — `useAgent(agentRef)` + the `agents` host
|
|
4231
4241
|
// client + the `agentRef` propertySchema type + the `ai.invoke:*` scope. A
|
|
4232
4242
|
// widget can hold a conversation with one of the WORKSPACE's own AI agents.
|
|
@@ -4288,7 +4298,7 @@ const CONTRACT = deepFreeze({
|
|
|
4288
4298
|
// untouched and renders byte-identically, and an unresolvable binding
|
|
4289
4299
|
// fails the existing hex guard, dropping the wash rather than painting it
|
|
4290
4300
|
// blank.
|
|
4291
|
-
version: "1.
|
|
4301
|
+
version: "1.120.0",
|
|
4292
4302
|
sharedTranslationKeys: SHARED_TRANSLATION_KEYS,
|
|
4293
4303
|
hooks: HOOKS,
|
|
4294
4304
|
primitives: PRIMITIVES,
|
package/dist/contract.js
CHANGED
|
@@ -1286,6 +1286,11 @@ const HOOKS = [
|
|
|
1286
1286
|
"opens the conversation, so a widget nobody types into costs nothing. " +
|
|
1287
1287
|
"`messages` is the running transcript, oldest first, each " +
|
|
1288
1288
|
"{ id, role, content, created_at } with role 'user' | 'assistant'. " +
|
|
1289
|
+
"An assistant message that used a tool also carries `activity`: what " +
|
|
1290
|
+
"the agent DID — the table it read, or the table and columns it " +
|
|
1291
|
+
"CHANGED. Render a write: a reply saying 'done!' is not evidence a " +
|
|
1292
|
+
"row was written, and the user has no other way to notice a mistake. " +
|
|
1293
|
+
"A talk-only turn omits the key entirely. " +
|
|
1289
1294
|
"You CANNOT set the system prompt, replay an edited transcript, " +
|
|
1290
1295
|
"or pick a model. No API returns the prompt — but that is a guarantee " +
|
|
1291
1296
|
"about the WIRE, not secrecy: a model can be talked into repeating its " +
|
|
@@ -4223,6 +4228,11 @@ const CONTRACT = deepFreeze({
|
|
|
4223
4228
|
// and the inherited colours are hex-guarded on the way out as well as in.
|
|
4224
4229
|
// Every colour still falls back to the sidebar's: an untouched workspace is
|
|
4225
4230
|
// unchanged.
|
|
4231
|
+
// 1.120.0: additive (sc-8332) — an assistant `AgentMessage` may carry
|
|
4232
|
+
// `activity`, a compact record of what the agent DID with the user's data
|
|
4233
|
+
// (the table it read; the table and columns it CHANGED). Absent on a
|
|
4234
|
+
// talk-only turn, so nothing existing changes shape. Render a write: a
|
|
4235
|
+
// reply saying "done!" is not evidence a row was written.
|
|
4226
4236
|
// 1.116.0: additive (sc-7991) — `useAgent(agentRef)` + the `agents` host
|
|
4227
4237
|
// client + the `agentRef` propertySchema type + the `ai.invoke:*` scope. A
|
|
4228
4238
|
// widget can hold a conversation with one of the WORKSPACE's own AI agents.
|
|
@@ -4284,7 +4294,7 @@ const CONTRACT = deepFreeze({
|
|
|
4284
4294
|
// untouched and renders byte-identically, and an unresolvable binding
|
|
4285
4295
|
// fails the existing hex guard, dropping the wash rather than painting it
|
|
4286
4296
|
// blank.
|
|
4287
|
-
version: "1.
|
|
4297
|
+
version: "1.120.0",
|
|
4288
4298
|
sharedTranslationKeys: SHARED_TRANSLATION_KEYS,
|
|
4289
4299
|
hooks: HOOKS,
|
|
4290
4300
|
primitives: PRIMITIVES,
|
|
@@ -15,12 +15,33 @@ export function parseToDate(value) {
|
|
|
15
15
|
return new Date();
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
const DATE_ONLY = /^\d{4}-\d{2}-\d{2}$/;
|
|
19
|
+
|
|
20
|
+
// A stored DATETIME instant → `<input type="datetime-local">`'s
|
|
21
|
+
// `YYYY-MM-DDTHH:mm` on the viewer's local clock. A bare calendar date is
|
|
22
|
+
// local midnight, not UTC midnight, so it never slips a day west of Greenwich.
|
|
23
|
+
export function isoToDateTimeLocalInput(value) {
|
|
24
|
+
if (value == null || value === "") return "";
|
|
25
|
+
if (typeof value === "string" && DATE_ONLY.test(value)) return `${value}T00:00`;
|
|
26
|
+
const d = new Date(value);
|
|
27
|
+
if (Number.isNaN(d.getTime())) return "";
|
|
28
|
+
return `${formatToIso(d, "date")}T${formatToIso(d, "time")}`;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// The inverse: a naive local `YYYY-MM-DDTHH:mm` → a full UTC ISO instant.
|
|
32
|
+
export function dateTimeLocalInputToIso(raw) {
|
|
33
|
+
if (raw == null || raw === "") return "";
|
|
34
|
+
const d = new Date(raw);
|
|
35
|
+
if (Number.isNaN(d.getTime())) return "";
|
|
36
|
+
return d.toISOString();
|
|
37
|
+
}
|
|
38
|
+
|
|
18
39
|
export function formatToIso(date, mode) {
|
|
19
40
|
if (!(date instanceof Date) || Number.isNaN(date.getTime())) return null;
|
|
20
41
|
if (mode === "date") {
|
|
21
42
|
// Local-date ISO (yyyy-mm-dd) — calendar dates are timezone-free so a
|
|
22
43
|
// "May 28" picked in Stockholm doesn't read as "May 27" in NYC.
|
|
23
|
-
const y = date.getFullYear();
|
|
44
|
+
const y = String(date.getFullYear()).padStart(4, "0");
|
|
24
45
|
const m = String(date.getMonth() + 1).padStart(2, "0");
|
|
25
46
|
const d = String(date.getDate()).padStart(2, "0");
|
|
26
47
|
return `${y}-${m}-${d}`;
|
|
@@ -46,10 +67,8 @@ export function formatDisplayLabel(value, mode) {
|
|
|
46
67
|
}
|
|
47
68
|
if (effectiveMode === "date") return String(value).slice(0, 10);
|
|
48
69
|
if (effectiveMode === "time") return String(value).slice(0, 5);
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
if (Number.isNaN(d.getTime())) return String(value);
|
|
52
|
-
return `${formatToIso(d, "date")} ${formatToIso(d, "time")}`;
|
|
70
|
+
const local = isoToDateTimeLocalInput(value);
|
|
71
|
+
return local ? local.replace("T", " ") : String(value);
|
|
53
72
|
}
|
|
54
73
|
|
|
55
74
|
// Perceived-luminance test for a hex colour (`#rgb` or `#rrggbb`). The web
|
package/dist/datetimepicker.js
CHANGED
|
@@ -26,7 +26,11 @@
|
|
|
26
26
|
|
|
27
27
|
import React from "react";
|
|
28
28
|
import { useHostTheme } from "./hooks.js";
|
|
29
|
-
import {
|
|
29
|
+
import {
|
|
30
|
+
isDarkColor,
|
|
31
|
+
isoToDateTimeLocalInput,
|
|
32
|
+
dateTimeLocalInputToIso,
|
|
33
|
+
} from "./datetimepicker-format.js";
|
|
30
34
|
import { DEFAULT_THEME_TOKENS } from "./_theme-tokens.js";
|
|
31
35
|
|
|
32
36
|
const MODE_TO_INPUT_TYPE = {
|
|
@@ -51,15 +55,7 @@ function _isoToInputValue(value, mode) {
|
|
|
51
55
|
if (mode === "time") {
|
|
52
56
|
return String(value).slice(0, 5);
|
|
53
57
|
}
|
|
54
|
-
|
|
55
|
-
const d = new Date(value);
|
|
56
|
-
if (Number.isNaN(d.getTime())) return "";
|
|
57
|
-
const y = d.getFullYear();
|
|
58
|
-
const m = String(d.getMonth() + 1).padStart(2, "0");
|
|
59
|
-
const day = String(d.getDate()).padStart(2, "0");
|
|
60
|
-
const hh = String(d.getHours()).padStart(2, "0");
|
|
61
|
-
const mm = String(d.getMinutes()).padStart(2, "0");
|
|
62
|
-
return `${y}-${m}-${day}T${hh}:${mm}`;
|
|
58
|
+
return isoToDateTimeLocalInput(value);
|
|
63
59
|
}
|
|
64
60
|
|
|
65
61
|
// Translate the input's typed string back to the ISO format the wire wants.
|
|
@@ -69,9 +65,7 @@ function _isoToInputValue(value, mode) {
|
|
|
69
65
|
function _inputValueToIso(raw, mode) {
|
|
70
66
|
if (raw == null || raw === "") return "";
|
|
71
67
|
if (mode === "date" || mode === "time") return raw;
|
|
72
|
-
|
|
73
|
-
if (Number.isNaN(d.getTime())) return "";
|
|
74
|
-
return d.toISOString();
|
|
68
|
+
return dateTimeLocalInputToIso(raw);
|
|
75
69
|
}
|
|
76
70
|
|
|
77
71
|
export function DateTimePicker({
|
package/dist/hooks.js
CHANGED
|
@@ -2762,7 +2762,9 @@ function toAgentError(err) {
|
|
|
2762
2762
|
* who places the widget and never types costs the workspace nothing.
|
|
2763
2763
|
*
|
|
2764
2764
|
* `messages` is the running transcript this widget has seen, oldest first,
|
|
2765
|
-
* each `{ id, role, content, created_at }` with `role` of "user" | "assistant".
|
|
2765
|
+
* each `{ id, role, content, created_at }` with `role` of "user" | "assistant".
|
|
2766
|
+
* An assistant message that used a tool also carries `activity` — what the
|
|
2767
|
+
* agent DID with the user's data. Render the writes: "done!" is not evidence.
|
|
2766
2768
|
* The SERVER owns the real transcript and the system prompt: the widget sends
|
|
2767
2769
|
* one message and can neither read nor set the prompt.
|
|
2768
2770
|
*
|
package/dist/host.d.ts
CHANGED
|
@@ -452,3 +452,22 @@ export function resolveGradientTokenStops(
|
|
|
452
452
|
gradient: unknown,
|
|
453
453
|
theme: unknown,
|
|
454
454
|
): unknown;
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* sc-8448 — a stored DATETIME instant as `<input type="datetime-local">`'s
|
|
458
|
+
* `YYYY-MM-DDTHH:mm` on the viewer's local clock. A bare `YYYY-MM-DD` is local
|
|
459
|
+
* midnight. Empty or unparseable input returns `""`.
|
|
460
|
+
*/
|
|
461
|
+
export function isoToDateTimeLocalInput(value: unknown): string;
|
|
462
|
+
|
|
463
|
+
/** sc-8448 — a local `YYYY-MM-DDTHH:mm` as a full UTC ISO instant, or `""`. */
|
|
464
|
+
export function dateTimeLocalInputToIso(raw: unknown): string;
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* sc-8448 — the `<DateTimePicker>` trigger label: for `"datetime"` the stored
|
|
468
|
+
* instant as `YYYY-MM-DD HH:mm` local time, falling back to the raw string.
|
|
469
|
+
*/
|
|
470
|
+
export function formatDateTimeLabel(
|
|
471
|
+
value: unknown,
|
|
472
|
+
mode: "date" | "time" | "datetime",
|
|
473
|
+
): string;
|
package/dist/host.js
CHANGED
|
@@ -124,3 +124,10 @@ export {
|
|
|
124
124
|
normaliseThemeGradient,
|
|
125
125
|
normaliseLoginDesign,
|
|
126
126
|
} from "./theme-background.js";
|
|
127
|
+
|
|
128
|
+
// sc-8448: one DATETIME local-clock conversion for the picker and the Studio.
|
|
129
|
+
export {
|
|
130
|
+
isoToDateTimeLocalInput,
|
|
131
|
+
dateTimeLocalInputToIso,
|
|
132
|
+
formatDisplayLabel as formatDateTimeLabel,
|
|
133
|
+
} from "./datetimepicker-format.js";
|
package/dist/index.d.ts
CHANGED
|
@@ -1212,9 +1212,30 @@ export interface AgentMessage {
|
|
|
1212
1212
|
/** The system prompt is NOT part of the transcript — it lives on the agent. */
|
|
1213
1213
|
role: "user" | "assistant";
|
|
1214
1214
|
content: string;
|
|
1215
|
+
/**
|
|
1216
|
+
* sc-8332 — what the agent DID on this turn, for the person to see. Present
|
|
1217
|
+
* only on an assistant message that used a tool; a talk-only turn omits the
|
|
1218
|
+
* key rather than carrying an empty marker you would have to special-case.
|
|
1219
|
+
*
|
|
1220
|
+
* Show a WRITE. A reply saying "done!" is not evidence a row was changed,
|
|
1221
|
+
* and if the agent got it wrong the user has no other way to notice.
|
|
1222
|
+
*/
|
|
1223
|
+
activity?: AgentActivity[];
|
|
1215
1224
|
created_at: string;
|
|
1216
1225
|
}
|
|
1217
1226
|
|
|
1227
|
+
/**
|
|
1228
|
+
* One tool the agent ran. Names the table it touched and, for a write, the
|
|
1229
|
+
* columns it set — never the values, and never a row the permissions refused.
|
|
1230
|
+
*/
|
|
1231
|
+
export interface AgentActivity {
|
|
1232
|
+
tool: string;
|
|
1233
|
+
ok: boolean;
|
|
1234
|
+
table?: string;
|
|
1235
|
+
record_id?: string;
|
|
1236
|
+
fields?: string[];
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1218
1239
|
export interface AgentApi {
|
|
1219
1240
|
/** Imperative — call from an event handler. The first send opens the thread. */
|
|
1220
1241
|
send(text: string): Promise<AgentMessage | null>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@colixsystems/widget-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.154.0",
|
|
4
4
|
"description": "Common widget interface for AppStudio. Implements WidgetManifest, WidgetContext, property schema, and helper hooks.",
|
|
5
5
|
"homepage": "https://github.com/Colix-AB/AppStudio",
|
|
6
6
|
"type": "module",
|