@colixsystems/widget-sdk 0.154.0 → 0.155.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 +11 -1
- package/dist/contract.cjs +13 -2
- package/dist/contract.js +13 -2
- package/dist/hooks.js +29 -3
- package/dist/index.d.ts +9 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -72,7 +72,17 @@ See the design reference for the full architecture: [`docs/architecture/widget-m
|
|
|
72
72
|
|
|
73
73
|
## Status
|
|
74
74
|
|
|
75
|
-
`v0.
|
|
75
|
+
`v0.155.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.155.0 (contract 1.121.0)
|
|
78
|
+
|
|
79
|
+
**`useAgent()` returns `cancel()` — and two error codes that tell the truth about a slow turn (sc-8519).** A turn can legitimately run for minutes; the client used to give up after 10 seconds and report it as `NETWORK`, so a widget showed "you appear to be offline" to a user whose connection was fine, while the server finished the turn and the workspace paid for a reply nobody saw.
|
|
80
|
+
|
|
81
|
+
- **`cancel()`** stops WAITING for the turn in flight. The abort never reaches the server, which finishes and bills the turn either way — so label the control **stop**, not *cancel*, and never imply the work was called off.
|
|
82
|
+
- **`TIMEOUT`** — the client stopped waiting. Still running, still billed: say it is taking longer than usual, never that it failed.
|
|
83
|
+
- **`CANCELLED`** — the user pressed your stop control. Render no error at all.
|
|
84
|
+
|
|
85
|
+
Additive: `send` is unchanged for callers who ignore the new return key, and a widget that never calls `cancel()` behaves exactly as before.
|
|
76
86
|
|
|
77
87
|
### What's new in 0.154.0 (contract 1.120.0)
|
|
78
88
|
|
package/dist/contract.cjs
CHANGED
|
@@ -1308,7 +1308,12 @@ const HOOKS = [
|
|
|
1308
1308
|
"AI_QUOTA_EXCEEDED (429) is the workspace's credit ceiling and will " +
|
|
1309
1309
|
"NOT clear on a retry — never offer 'try again' for it — where " +
|
|
1310
1310
|
"RATE_LIMITED (429) will; AGENT_DISABLED (409) means the author turned " +
|
|
1311
|
-
"it off, so hide the affordance rather than retrying
|
|
1311
|
+
"it off, so hide the affordance rather than retrying; TIMEOUT means the " +
|
|
1312
|
+
"client stopped waiting and the turn is STILL running and billed, so " +
|
|
1313
|
+
"say it is taking longer, never that it failed or that they are " +
|
|
1314
|
+
"offline; CANCELLED is the user pressing your stop control, so render " +
|
|
1315
|
+
"no error at all. Call cancel() to stop waiting -- it ends the WAIT, " +
|
|
1316
|
+
"not the turn. NEVER surface a " +
|
|
1312
1317
|
"raw error or the workspace's billing state to an app user. " +
|
|
1313
1318
|
"Reads ctx.agents.",
|
|
1314
1319
|
returnShape: {
|
|
@@ -4232,6 +4237,12 @@ const CONTRACT = deepFreeze({
|
|
|
4232
4237
|
// and the inherited colours are hex-guarded on the way out as well as in.
|
|
4233
4238
|
// Every colour still falls back to the sidebar's: an untouched workspace is
|
|
4234
4239
|
// unchanged.
|
|
4240
|
+
// 1.121.0: additive (sc-8519) — `useAgent()` returns `cancel()`, which
|
|
4241
|
+
// stops WAITING for the turn in flight. The abort is client-side: the
|
|
4242
|
+
// server finishes the turn and the workspace is billed, so label the
|
|
4243
|
+
// control 'stop', never 'cancel'. Two new AgentError codes ride with it —
|
|
4244
|
+
// TIMEOUT (the client stopped waiting; still running, still billed) and
|
|
4245
|
+
// CANCELLED (the user pressed stop; render no error at all).
|
|
4235
4246
|
// 1.120.0: additive (sc-8332) — an assistant `AgentMessage` may carry
|
|
4236
4247
|
// `activity`, a compact record of what the agent DID with the user's data
|
|
4237
4248
|
// (the table it read; the table and columns it CHANGED). Absent on a
|
|
@@ -4298,7 +4309,7 @@ const CONTRACT = deepFreeze({
|
|
|
4298
4309
|
// untouched and renders byte-identically, and an unresolvable binding
|
|
4299
4310
|
// fails the existing hex guard, dropping the wash rather than painting it
|
|
4300
4311
|
// blank.
|
|
4301
|
-
version: "1.
|
|
4312
|
+
version: "1.121.0",
|
|
4302
4313
|
sharedTranslationKeys: SHARED_TRANSLATION_KEYS,
|
|
4303
4314
|
hooks: HOOKS,
|
|
4304
4315
|
primitives: PRIMITIVES,
|
package/dist/contract.js
CHANGED
|
@@ -1308,7 +1308,12 @@ const HOOKS = [
|
|
|
1308
1308
|
"AI_QUOTA_EXCEEDED (429) is the workspace's credit ceiling and will " +
|
|
1309
1309
|
"NOT clear on a retry — never offer 'try again' for it — where " +
|
|
1310
1310
|
"RATE_LIMITED (429) will; AGENT_DISABLED (409) means the author turned " +
|
|
1311
|
-
"it off, so hide the affordance rather than retrying
|
|
1311
|
+
"it off, so hide the affordance rather than retrying; TIMEOUT means the " +
|
|
1312
|
+
"client stopped waiting and the turn is STILL running and billed, so " +
|
|
1313
|
+
"say it is taking longer, never that it failed or that they are " +
|
|
1314
|
+
"offline; CANCELLED is the user pressing your stop control, so render " +
|
|
1315
|
+
"no error at all. Call cancel() to stop waiting -- it ends the WAIT, " +
|
|
1316
|
+
"not the turn. NEVER surface a " +
|
|
1312
1317
|
"raw error or the workspace's billing state to an app user. " +
|
|
1313
1318
|
"Reads ctx.agents.",
|
|
1314
1319
|
returnShape: {
|
|
@@ -4228,6 +4233,12 @@ const CONTRACT = deepFreeze({
|
|
|
4228
4233
|
// and the inherited colours are hex-guarded on the way out as well as in.
|
|
4229
4234
|
// Every colour still falls back to the sidebar's: an untouched workspace is
|
|
4230
4235
|
// unchanged.
|
|
4236
|
+
// 1.121.0: additive (sc-8519) — `useAgent()` returns `cancel()`, which
|
|
4237
|
+
// stops WAITING for the turn in flight. The abort is client-side: the
|
|
4238
|
+
// server finishes the turn and the workspace is billed, so label the
|
|
4239
|
+
// control 'stop', never 'cancel'. Two new AgentError codes ride with it —
|
|
4240
|
+
// TIMEOUT (the client stopped waiting; still running, still billed) and
|
|
4241
|
+
// CANCELLED (the user pressed stop; render no error at all).
|
|
4231
4242
|
// 1.120.0: additive (sc-8332) — an assistant `AgentMessage` may carry
|
|
4232
4243
|
// `activity`, a compact record of what the agent DID with the user's data
|
|
4233
4244
|
// (the table it read; the table and columns it CHANGED). Absent on a
|
|
@@ -4294,7 +4305,7 @@ const CONTRACT = deepFreeze({
|
|
|
4294
4305
|
// untouched and renders byte-identically, and an unresolvable binding
|
|
4295
4306
|
// fails the existing hex guard, dropping the wash rather than painting it
|
|
4296
4307
|
// blank.
|
|
4297
|
-
version: "1.
|
|
4308
|
+
version: "1.121.0",
|
|
4298
4309
|
sharedTranslationKeys: SHARED_TRANSLATION_KEYS,
|
|
4299
4310
|
hooks: HOOKS,
|
|
4300
4311
|
primitives: PRIMITIVES,
|
package/dist/hooks.js
CHANGED
|
@@ -2713,7 +2713,15 @@ export function useInterpretDraft(tableId) {
|
|
|
2713
2713
|
* - "AI_UNAVAILABLE" — 503 (no AI provider configured)
|
|
2714
2714
|
* - "AI_GENERATION_FAILED" — 502 (the provider did not answer)
|
|
2715
2715
|
* - "AUTH_REQUIRED" — 401 (no signed-in app user)
|
|
2716
|
-
* - "
|
|
2716
|
+
* - "NETWORK" — the request never reached the server
|
|
2717
|
+
* - "TIMEOUT" — the client stopped waiting. NOT a failed
|
|
2718
|
+
* turn: the server finishes it and the
|
|
2719
|
+
* workspace is billed, so say "still
|
|
2720
|
+
* working", never "failed"
|
|
2721
|
+
* - "CANCELLED" — `cancel()` was called. The user chose it,
|
|
2722
|
+
* so render no error at all (the turn is
|
|
2723
|
+
* still billed — never imply it stopped)
|
|
2724
|
+
* - "INTERNAL" — anything else (a 5xx carrying no code)
|
|
2717
2725
|
*/
|
|
2718
2726
|
export class AgentError extends Error {
|
|
2719
2727
|
constructor(code, message, opts) {
|
|
@@ -2816,12 +2824,21 @@ export function useAgent(agentRef) {
|
|
|
2816
2824
|
pendingResetRef.current = true;
|
|
2817
2825
|
}
|
|
2818
2826
|
|
|
2827
|
+
const abortRef = useRef(null);
|
|
2828
|
+
|
|
2819
2829
|
const reset = useCallback(() => {
|
|
2820
2830
|
conversationRef.current = null;
|
|
2821
2831
|
setMessages([]);
|
|
2822
2832
|
setError(null);
|
|
2823
2833
|
}, []);
|
|
2824
2834
|
|
|
2835
|
+
// Ends the WAIT, not the turn: the abort never reaches the server, which
|
|
2836
|
+
// finishes and bills it either way. Never imply the work was stopped.
|
|
2837
|
+
const cancel = useCallback(() => {
|
|
2838
|
+
const controller = abortRef.current;
|
|
2839
|
+
if (controller) controller.abort();
|
|
2840
|
+
}, []);
|
|
2841
|
+
|
|
2825
2842
|
const send = useCallback(async (text) => {
|
|
2826
2843
|
const client = clientRef.current;
|
|
2827
2844
|
const agentId = agentIdRef.current;
|
|
@@ -2855,7 +2872,13 @@ export function useAgent(agentRef) {
|
|
|
2855
2872
|
conversationRef.current = null;
|
|
2856
2873
|
throw err;
|
|
2857
2874
|
}
|
|
2858
|
-
const
|
|
2875
|
+
const controller =
|
|
2876
|
+
typeof AbortController === "function" ? new AbortController() : null;
|
|
2877
|
+
abortRef.current = controller;
|
|
2878
|
+
const turn = await thread
|
|
2879
|
+
.messages(conversationId)
|
|
2880
|
+
.send({ content }, controller ? { signal: controller.signal } : undefined);
|
|
2881
|
+
abortRef.current = null;
|
|
2859
2882
|
// A rebind during the round trip makes this the PREVIOUS agent's reply;
|
|
2860
2883
|
// writing it now would render it under the new one.
|
|
2861
2884
|
if (agentIdRef.current !== agentId) {
|
|
@@ -2874,8 +2897,10 @@ export function useAgent(agentRef) {
|
|
|
2874
2897
|
// A stale thread is recoverable on the next send rather than permanently
|
|
2875
2898
|
// broken: drop it so the widget opens a fresh one.
|
|
2876
2899
|
if (e.code === "CONVERSATION_NOT_FOUND") conversationRef.current = null;
|
|
2900
|
+
abortRef.current = null;
|
|
2877
2901
|
// Same rebind guard: a new agent must not inherit the old one's error.
|
|
2878
|
-
|
|
2902
|
+
// A cancel is the user's own choice, so it is not a failure to report.
|
|
2903
|
+
if (e.code !== "CANCELLED" && agentIdRef.current === agentId) setError(e);
|
|
2879
2904
|
setSending(false);
|
|
2880
2905
|
throw e;
|
|
2881
2906
|
}
|
|
@@ -2897,6 +2922,7 @@ export function useAgent(agentRef) {
|
|
|
2897
2922
|
|
|
2898
2923
|
return {
|
|
2899
2924
|
send,
|
|
2925
|
+
cancel,
|
|
2900
2926
|
reset,
|
|
2901
2927
|
messages: visibleMessages,
|
|
2902
2928
|
sending,
|
package/dist/index.d.ts
CHANGED
|
@@ -1239,6 +1239,12 @@ export interface AgentActivity {
|
|
|
1239
1239
|
export interface AgentApi {
|
|
1240
1240
|
/** Imperative — call from an event handler. The first send opens the thread. */
|
|
1241
1241
|
send(text: string): Promise<AgentMessage | null>;
|
|
1242
|
+
/**
|
|
1243
|
+
* Stop WAITING for the turn in flight. The abort never reaches the server,
|
|
1244
|
+
* which finishes and bills it either way — label the control "stop", not
|
|
1245
|
+
* "cancel", and show no error when the user presses it.
|
|
1246
|
+
*/
|
|
1247
|
+
cancel(): void;
|
|
1242
1248
|
/** Drop the open thread and clear the transcript this widget has seen. */
|
|
1243
1249
|
reset(): void;
|
|
1244
1250
|
/** Oldest first. The SERVER owns the real transcript. */
|
|
@@ -1997,6 +2003,9 @@ export class AgentError extends Error {
|
|
|
1997
2003
|
| "AI_UNAVAILABLE"
|
|
1998
2004
|
| "AI_GENERATION_FAILED"
|
|
1999
2005
|
| "AUTH_REQUIRED"
|
|
2006
|
+
| "NETWORK"
|
|
2007
|
+
| "TIMEOUT"
|
|
2008
|
+
| "CANCELLED"
|
|
2000
2009
|
| "INTERNAL"
|
|
2001
2010
|
| (string & {});
|
|
2002
2011
|
constructor(code: string, message: string, opts?: { cause?: unknown });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@colixsystems/widget-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.155.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",
|