@colixsystems/widget-sdk 0.153.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 +8 -2
- package/dist/contract.cjs +11 -1
- package/dist/contract.js +11 -1
- package/dist/hooks.js +3 -1
- 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,13 @@ 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.
|
|
76
82
|
|
|
77
83
|
### What's new in 0.153.0 (contract 1.118.0 — unchanged)
|
|
78
84
|
|
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,
|
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/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",
|