@guuey/chat 0.16.9 → 0.16.11

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.
@@ -1 +1 @@
1
- {"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../src/plan.ts"],"names":[],"mappings":"AAkCA,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAGpD,OAAO,KAAK,EAUV,gBAAgB,EAChB,mBAAmB,EACnB,cAAc,EAIf,MAAM,YAAY,CAAC;AAuqBpB,uCAAuC;AACvC,wBAAgB,cAAc,CAC5B,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE,gBAAgB,EACxB,SAAS,GAAE,mBAAwB,GAClC,cAAc,CA+VhB;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,IAAI,CAAC,gBAAgB,EAAE,QAAQ,GAAG,cAAc,CAAC,GACxD;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,SAAS,CAAC,SAAS,CAAC,CAAA;CAAE,GAAG,SAAS,CAiB5D"}
1
+ {"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../src/plan.ts"],"names":[],"mappings":"AAkCA,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAGpD,OAAO,KAAK,EAUV,gBAAgB,EAChB,mBAAmB,EACnB,cAAc,EAIf,MAAM,YAAY,CAAC;AAuqBpB,uCAAuC;AACvC,wBAAgB,cAAc,CAC5B,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE,gBAAgB,EACxB,SAAS,GAAE,mBAAwB,GAClC,cAAc,CAkXhB;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,IAAI,CAAC,gBAAgB,EAAE,QAAQ,GAAG,cAAc,CAAC,GACxD;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,SAAS,CAAC,SAAS,CAAC,CAAA;CAAE,GAAG,SAAS,CAiB5D"}
package/dist/plan.js CHANGED
@@ -760,14 +760,35 @@ export function planTranscript(inputs, policy, overrides = {}) {
760
760
  liveViewScopes.add(item.actionScope);
761
761
  }
762
762
  const cards = [...(inputs.historyCards ?? [])].sort((a, b) => a.seq - b.seq);
763
- for (const card of cards) {
764
- const key = `card.${card.seq}`;
763
+ // guuey#535: ONE render session = ONE surface. Multiple history cards
764
+ // sharing an actionScope are the same surface referenced across turns
765
+ // (ggui SPEC §7.1.2.1 makes the amend result's {sessionId, resourceUri}
766
+ // the normative re-anchor reference — ggui#652; the stamp rides the
767
+ // existing locator persistence lane untouched). The LATEST reference
768
+ // anchors the surface; earlier references emit nothing — and latest
769
+ // wins even when it is locator-only, because the locator re-fetch
770
+ // restores CURRENT session state, better than an older frozen snapshot.
771
+ const scopes = cards.map((card) => {
765
772
  const mount = snapshotViewMount(card.cardSnapshot);
766
- const scope = mount === undefined
767
- ? null
768
- : mount.channel === "locator"
769
- ? mount.resourceUri
770
- : mount.resource.uri;
773
+ return {
774
+ card,
775
+ mount,
776
+ scope: mount === undefined
777
+ ? null
778
+ : mount.channel === "locator"
779
+ ? mount.resourceUri
780
+ : mount.resource.uri,
781
+ };
782
+ });
783
+ const latestSeqByScope = new Map();
784
+ for (const { card, scope } of scopes) {
785
+ if (scope !== null)
786
+ latestSeqByScope.set(scope, card.seq);
787
+ }
788
+ for (const { card, mount, scope } of scopes) {
789
+ const key = `card.${card.seq}`;
790
+ if (scope !== null && latestSeqByScope.get(scope) !== card.seq)
791
+ continue; // a later turn re-anchored it
771
792
  if (scope !== null && liveViewScopes.has(scope))
772
793
  continue; // live mount owns it
773
794
  const view = {
@@ -118,6 +118,28 @@ export interface GuueyChatHandle {
118
118
  * to the transcript).
119
119
  */
120
120
  viewSlotProps(): ViewSlotProps;
121
+ /**
122
+ * Forget this conversation (guuey#526 — the public-computer story).
123
+ *
124
+ * Local half, unconditional and immediate: aborts any in-flight turn
125
+ * FIRST (a completing turn can re-persist its own rows), drops the
126
+ * durable thread pointer AND its persisted storage key, wipes the
127
+ * visible transcript, clears the typed draft and any pending link ask —
128
+ * the next send mints a fresh thread.
129
+ *
130
+ * Server half, best-effort: when the surface has a platform door
131
+ * (`apiBaseUrl`) and a minted thread, fires
132
+ * `DELETE /v1/threads/:threadId` with the SAME identity the thread was
133
+ * created under (captured before any rotation) — real, child-first
134
+ * server-side erasure. A denied or failed delete still clears the
135
+ * device (the contract's unlinkability fallback) and surfaces nothing
136
+ * louder than the `thread-delete` debug event.
137
+ *
138
+ * Afterwards `onGuestSecretRotate` fires (when wired), so the identity
139
+ * owner mints a fresh guest secret — even an orphaned server row is
140
+ * unreachable from a rotated identity.
141
+ */
142
+ clearConversation(): void;
121
143
  }
122
144
  export interface GuueyChatProps {
123
145
  /** Pod base URL (with or without `/agent/invoke`). `null` disables chat. */
@@ -188,6 +210,39 @@ export interface GuueyChatProps {
188
210
  * pod door) when omitted; an explicit reader always wins.
189
211
  */
190
212
  reader?: UiResourceReader;
213
+ /**
214
+ * The forget-this-device affordance (guuey#526 — the public-computer
215
+ * story): a quiet "Clear conversation" control with a two-tap confirm,
216
+ * wired to {@link GuueyChatHandle.clearConversation}. Default: ON when
217
+ * the surface runs GUEST identity (`getGuestSecret` present — the
218
+ * founder's seamless principle; a signed-in surface has account-level
219
+ * recourse), OFF otherwise; pass a boolean to override either way.
220
+ */
221
+ clearAffordance?: boolean;
222
+ /**
223
+ * Guest-secret rotation hook (guuey#526): called at the END of every
224
+ * {@link GuueyChatHandle.clearConversation} — after the server delete
225
+ * has been dispatched with the OLD identity — so the owner of the
226
+ * secret's storage (the kit never stores it; `getGuestSecret` is a
227
+ * getter) mints a fresh one. Rotation is what makes even an orphaned
228
+ * server row unreachable: the new identity is a stranger to it. Guest
229
+ * KV state is (user,mcp)-scoped and is orphaned by rotation, by design.
230
+ */
231
+ onGuestSecretRotate?: () => void;
232
+ /**
233
+ * Suggestion chips (guuey#533 — declared content, the one-truth design):
234
+ * rendered on the EMPTY transcript only (they retire the moment a
235
+ * message exists — live send or restored history both count), one tap
236
+ * SENDS the chip text verbatim through exactly the Send button's gate.
237
+ * Default-ON when content exists; `false` opts the surface out. The kit
238
+ * mirrors the card projection's caps render-side (4 shown, ≤80 chars
239
+ * each, blank-rejected) — a direct consumer bypassing the platform's
240
+ * emit gate gets the same bounds. Content is the host's (the widget
241
+ * passes the card's `suggestions`; a direct consumer passes its own);
242
+ * the kit never invents chips — an honest empty state beats invented
243
+ * questions in the builder's voice.
244
+ */
245
+ suggestions?: readonly string[] | false;
191
246
  /** The debug sink (spec §5) — fires only under the debug policy. */
192
247
  onDebugEvent?: (event: ChatDebugEvent) => void;
193
248
  /** R6 pass-through (relay hook, sandbox page/flags, host context…). */
@@ -1 +1 @@
1
- {"version":3,"file":"guuey-chat.d.ts","sourceRoot":"","sources":["../../src/react/guuey-chat.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,OAAO,EASL,KAAK,aAAa,EAEnB,MAAM,OAAO,CAAC;AACf,OAAO,EAIL,KAAK,mBAAmB,EACzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAGtE,OAAO,KAAK,EAAsC,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACjG,OAAO,EAA2B,KAAK,yBAAyB,EAAE,MAAM,cAAc,CAAC;AAEvF,OAAO,EAAsB,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AACrE,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AACtE,OAAO,KAAK,EACV,cAAc,EACd,SAAS,EACT,eAAe,EACf,UAAU,EAEV,WAAW,EACZ,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAc,KAAK,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACvE,OAAO,KAAK,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAIlG;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACxC,SAAS,EAAE,qBAAqB,CAAC,WAAW,CAAC,EAC7C,IAAI,EAAE,SAAS,EACf,QAAQ,GAAE,IAAI,CACZ,aAAa,EACb,YAAY,GAAG,sBAAsB,GAAG,eAAe,GAAG,YAAY,CAClE,GACL,qBAAqB,CAAC,WAAW,CAAC,CAgBpC;AAED;;;;;GAKG;AACH;;;;;GAKG;AACH,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,QAAQ,GAAG,SAAS,CAAC;CAC5B;AAED,MAAM,WAAW,eAAe;IAC9B;;;;;;;OAOG;IACH,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAC5B;;;;;OAKG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IAC1E,gCAAgC;IAChC,aAAa,IAAI,IAAI,CAAC;IACtB;;;;;;;OAOG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC;;;;;;;;OAQG;IACH,aAAa,IAAI,aAAa,CAAC;CAChC;AAED,MAAM,WAAW,cAAc;IAC7B,4EAA4E;IAC5E,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,yDAAyD;IACzD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;;;OASG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC/E,cAAc,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;IACrC;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,mBAAmB,CAAC;IAC/B,iDAAiD;IACjD,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC1B;;;;OAIG;IACH,MAAM,CAAC,EAAE,yBAAyB,CAAC;IACnC,gEAAgE;IAChE,UAAU,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAC3C,wEAAwE;IACxE,OAAO,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IAC/B,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1B;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,wDAAwD;IACxD,MAAM,CAAC,EAAE,mBAAmB,GAAG,KAAK,CAAC;IACrC;;;;OAIG;IACH,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,oEAAoE;IACpE,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAC/C,uEAAuE;IACvE,SAAS,CAAC,EAAE,qBAAqB,CAAC,WAAW,CAAC,CAAC;IAC/C;;;;OAIG;IACH,cAAc,CAAC,EAAE,CACf,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,KAC/D,IAAI,CAAC;IACV;;;;OAIG;IACH,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,EAAE,WAAW,KAAK,IAAI,CAAC;IAChE;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,KAAK,IAAI,CAAC;IAC5D,qDAAqD;IACrD,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;IAC1C;;;;;;;;;;OAUG;IACH,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,sBAAsB,KAAK,IAAI,CAAC;IACrD;;;;OAIG;IACH,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;IAC5C;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC;;;;;;;;;OASG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC;IACxC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,EAAE,KAAK,IAAI,CAAC;IACnD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB;AAQD,eAAO,MAAM,SAAS,4GA4kBpB,CAAC"}
1
+ {"version":3,"file":"guuey-chat.d.ts","sourceRoot":"","sources":["../../src/react/guuey-chat.tsx"],"names":[],"mappings":"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"}
@@ -46,7 +46,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
46
46
  * native GuueyChat, so there is no native surface to put a handle on yet.
47
47
  */
48
48
  import { forwardRef, useCallback, useEffect, useId, useImperativeHandle, useMemo, useRef, useState, } from "react";
49
- import { createUiActionRelay, createUiResourceReader, createWebAdapters, } from "@guuey/agent-client";
49
+ import { createUiActionRelay, createUiResourceReader, createWebAdapters, deleteThread, } from "@guuey/agent-client";
50
50
  import { useAgentInvoke } from "@guuey/agent-client/react";
51
51
  import { unavailableToolCallResult } from "@guuey/mcp-apps-host";
52
52
  import { calmPolicy, debugPolicy } from "../policy.js";
@@ -85,7 +85,7 @@ const PROMPT_STATE = {
85
85
  dismiss: "dismissed",
86
86
  };
87
87
  export const GuueyChat = forwardRef(function GuueyChat(props, ref) {
88
- const { endpointUrl, appId, apiBaseUrl, getAccessToken, getGuestSecret, adapters: adaptersProp, preset = "calm", policy: policyOverrides, components, strings: stringOverrides, theme = DEFAULT_CHAT_THEME, mode = "light", surface = "card", composer = true, window: windowing, reader, onDebugEvent, viewProps, promotedViewKey, onViewRef, onViewsChange, onPromptAction, onHitlAnswer, oauthReturnTo, onOAuthAuthorize, onErrorAction, onActivity, onReady, onThread, className, style, } = props;
88
+ const { endpointUrl, appId, apiBaseUrl, getAccessToken, getGuestSecret, adapters: adaptersProp, preset = "calm", policy: policyOverrides, components, strings: stringOverrides, theme = DEFAULT_CHAT_THEME, mode = "light", surface = "card", composer = true, window: windowing, reader, onDebugEvent, viewProps, promotedViewKey, onViewRef, onViewsChange, onPromptAction, onHitlAnswer, oauthReturnTo, onOAuthAuthorize, onErrorAction, clearAffordance, onGuestSecretRotate, suggestions, onActivity, onReady, onThread, className, style, } = props;
89
89
  // Identity stabilization (guuey#303 QA — the template's own chat-rail
90
90
  // shipped the failure): hosts pass inline literals and arrows, so prop
91
91
  // IDENTITY is noise. The getter props route through refs (presence, not
@@ -96,8 +96,14 @@ export const GuueyChat = forwardRef(function GuueyChat(props, ref) {
96
96
  // host back → setState → re-render → "Maximum update depth exceeded".
97
97
  const getAccessTokenRef = useRef(getAccessToken);
98
98
  getAccessTokenRef.current = getAccessToken;
99
+ // The handle is created once ([] deps) but must read the LIVE base —
100
+ // same ref discipline as every other handle-read value in this file.
101
+ const apiBaseUrlRef = useRef(apiBaseUrl);
102
+ apiBaseUrlRef.current = apiBaseUrl;
99
103
  const getGuestSecretRef = useRef(getGuestSecret);
100
104
  getGuestSecretRef.current = getGuestSecret;
105
+ const onGuestSecretRotateRef = useRef(onGuestSecretRotate);
106
+ onGuestSecretRotateRef.current = onGuestSecretRotate;
101
107
  const hasAccessToken = getAccessToken !== undefined;
102
108
  const hasGuestSecret = getGuestSecret !== undefined;
103
109
  const adapters = useMemo(() => adaptersProp ??
@@ -357,6 +363,40 @@ export const GuueyChat = forwardRef(function GuueyChat(props, ref) {
357
363
  // by construction. ONE pending ask at a time, newest replaces (a
358
364
  // card spamming asks can never grow an unbounded stack).
359
365
  const [pendingLink, setPendingLink] = useState(null);
366
+ // guuey#526: the two-tap confirm window for the clear affordance (an
367
+ // accidental tap must not nuke a conversation; a second tap within the
368
+ // window does — the state auto-expires).
369
+ const [clearArmed, setClearArmed] = useState(false);
370
+ useEffect(() => {
371
+ if (!clearArmed)
372
+ return;
373
+ const timer = setTimeout(() => setClearArmed(false), 4000);
374
+ return () => clearTimeout(timer);
375
+ }, [clearArmed]);
376
+ const showClearAffordance = clearAffordance ?? getGuestSecret !== undefined;
377
+ // guuey#533: the render-side mirror of the card projection's emit caps
378
+ // (4 shown / <=80 chars / blank-rejected) — same defense posture as the
379
+ // table normalizer: the kit is public npm and cannot assume every host
380
+ // routed content through platform's write gate.
381
+ const chips = useMemo(() => {
382
+ if (suggestions === false || suggestions === undefined)
383
+ return [];
384
+ return suggestions
385
+ .map((c) => c.trim())
386
+ .filter((c) => c.length > 0 && c.length <= 80)
387
+ .slice(0, 4);
388
+ }, [suggestions]);
389
+ const sendSuggestion = useCallback((text) => {
390
+ const live = liveRef.current;
391
+ // Exactly the Send button's gate (the #210 rule): unavailable, busy,
392
+ // or blank -> the tap is a no-op, never a bypass. The typed draft is
393
+ // left untouched (a chip send must not eat a half-typed message).
394
+ if (!live.available || live.busy || text.trim() === "")
395
+ return;
396
+ void live.invoke.send(text).catch(() => {
397
+ // Same contract as submit: the hook owns failure surfacing.
398
+ });
399
+ }, []);
360
400
  const defaultOnOpenLink = useCallback((url) => {
361
401
  setPendingLink(url);
362
402
  }, []);
@@ -413,6 +453,49 @@ export const GuueyChat = forwardRef(function GuueyChat(props, ref) {
413
453
  focusComposer: () => {
414
454
  inputRef.current?.focus();
415
455
  },
456
+ clearConversation: () => {
457
+ const live = liveRef.current;
458
+ // Contract ordering (guuey#526, platform's frozen comment): abort
459
+ // FIRST — a completing turn can re-persist its own rows after the
460
+ // delete. Capture the id + guest secret BEFORE anything clears or
461
+ // rotates them: the delete must authenticate as the identity that
462
+ // OWNS the thread.
463
+ live.invoke.abort();
464
+ const threadId = threadIdRef.current;
465
+ const getGuest = getGuestSecretRef.current;
466
+ const guestSecret = getGuest !== undefined ? getGuest() : null;
467
+ if (apiBaseUrlRef.current !== undefined && threadId !== null) {
468
+ // Best-effort server erasure — fire-and-forget, never blocks the
469
+ // local clear. 200 and 404 are both "deleted" (idempotent by
470
+ // contract); denied/failed still cleared locally below (the
471
+ // unlinkability fallback) and surface ONLY as a debug line.
472
+ void deleteThread({
473
+ apiBaseUrl: apiBaseUrlRef.current,
474
+ threadId,
475
+ ...(getAccessTokenRef.current !== undefined
476
+ ? { getAccessToken: getAccessTokenRef.current }
477
+ : {}),
478
+ guestSecret,
479
+ }).then((outcome) => {
480
+ onDebugEventRef.current?.({ type: "thread-delete", threadId, outcome });
481
+ });
482
+ }
483
+ else {
484
+ onDebugEventRef.current?.({ type: "thread-delete", threadId, outcome: "skipped" });
485
+ }
486
+ // The hook's reset owns the durable local half (pointer + storage
487
+ // key, transcript/fold/cards); the kit clears ITS OWN residue —
488
+ // the typed draft, a pending link ask, queued doorbells — so the
489
+ // device holds nothing of the conversation.
490
+ live.invoke.reset();
491
+ setInput("");
492
+ setPendingLink(null);
493
+ pendingDoorbellsRef.current = [];
494
+ // Rotation LAST: the delete above already captured the old
495
+ // identity, so the fresh secret is a stranger to even an orphaned
496
+ // server row.
497
+ onGuestSecretRotateRef.current?.();
498
+ },
416
499
  // A getter, not a captured value: the handle is created once, but the
417
500
  // thread hydrates after mount and can change — reads go through the
418
501
  // same ref the default reader uses, so it is always the live id.
@@ -491,7 +574,15 @@ export const GuueyChat = forwardRef(function GuueyChat(props, ref) {
491
574
  onPromptAction?.(item, action);
492
575
  }, [resolvePrompt, answerHitlPrompt, onHitlAnswer, onPromptAction, oauthReturnTo, onOAuthAuthorize]);
493
576
  const strings = policy.strings;
494
- return (_jsxs("div", { className: `guuey-chat-surface${className !== undefined ? ` ${className}` : ""}`, style: style, children: [_jsx(Transcript, { plan: plan, strings: strings, theme: theme, mode: mode, surface: surface, ...(windowing !== undefined ? { window: windowing } : {}), ...(components !== undefined ? { components } : {}), onToggle: toggle, onRetry: handleRetry, onPromptAction: handlePromptAction, ...(onErrorAction !== undefined ? { onErrorAction } : {}), resolvedMounts: resolvedMounts, onViewPhase: onViewPhase, onViewDiagnosis: onViewDiagnosis, ...(onViewRef !== undefined ? { onViewRef } : {}), viewProps: effectiveViewProps }), pendingLink !== null && (_jsxs("div", { role: "status", className: "guuey-chat-link-ask", children: [_jsx("span", { className: "guuey-chat-link-ask-label", children: strings.linkAskLabel(new URL(pendingLink).host) }), _jsx("span", { className: "guuey-chat-link-ask-url", children: pendingLink }), _jsx("a", { className: "guuey-chat-link-ask-open", href: pendingLink, target: "_blank", rel: "noopener noreferrer", onClick: () => setPendingLink(null), children: strings.linkOpen }), _jsx("button", { type: "button", className: "guuey-chat-link-ask-dismiss", onClick: () => setPendingLink(null), children: strings.linkDismiss })] })), oauthReturn.notice !== null && (_jsxs("p", { role: "status", className: `guuey-chat-oauth-notice guuey-chat-oauth-${oauthReturn.notice.kind}`, children: [oauthReturn.notice.kind === "connected"
577
+ return (_jsxs("div", { className: `guuey-chat-surface${className !== undefined ? ` ${className}` : ""}`, style: style, children: [_jsx(Transcript, { plan: plan, strings: strings, theme: theme, mode: mode, surface: surface, ...(windowing !== undefined ? { window: windowing } : {}), ...(components !== undefined ? { components } : {}), onToggle: toggle, onRetry: handleRetry, onPromptAction: handlePromptAction, ...(onErrorAction !== undefined ? { onErrorAction } : {}), resolvedMounts: resolvedMounts, onViewPhase: onViewPhase, onViewDiagnosis: onViewDiagnosis, ...(onViewRef !== undefined ? { onViewRef } : {}), viewProps: effectiveViewProps }), chips.length > 0 && inputs.messages.length === 0 && (_jsx("nav", { className: "guuey-chat-chips-row", "aria-label": strings.suggestionsLabel, children: chips.map((chip) => (_jsx("button", { type: "button", className: "guuey-chat-chip", onClick: () => sendSuggestion(chip), children: chip }, chip))) })), showClearAffordance && inputs.messages.length > 0 && (_jsx("div", { className: "guuey-chat-clear-row", children: _jsx("button", { type: "button", className: `guuey-chat-clear${clearArmed ? " guuey-chat-clear-armed" : ""}`, onClick: () => {
578
+ if (clearArmed) {
579
+ setClearArmed(false);
580
+ handle.clearConversation();
581
+ }
582
+ else {
583
+ setClearArmed(true);
584
+ }
585
+ }, children: clearArmed ? strings.clearConversationConfirm : strings.clearConversationLabel }) })), pendingLink !== null && (_jsxs("div", { role: "status", className: "guuey-chat-link-ask", children: [_jsx("span", { className: "guuey-chat-link-ask-label", children: strings.linkAskLabel(new URL(pendingLink).host) }), _jsx("span", { className: "guuey-chat-link-ask-url", children: pendingLink }), _jsx("a", { className: "guuey-chat-link-ask-open", href: pendingLink, target: "_blank", rel: "noopener noreferrer", onClick: () => setPendingLink(null), children: strings.linkOpen }), _jsx("button", { type: "button", className: "guuey-chat-link-ask-dismiss", onClick: () => setPendingLink(null), children: strings.linkDismiss })] })), oauthReturn.notice !== null && (_jsxs("p", { role: "status", className: `guuey-chat-oauth-notice guuey-chat-oauth-${oauthReturn.notice.kind}`, children: [oauthReturn.notice.kind === "connected"
495
586
  ? strings.oauthConnected(oauthReturn.notice.serverName)
496
587
  : strings.oauthFailed(oauthReturn.notice.reason), _jsx("button", { type: "button", className: "guuey-chat-oauth-dismiss", onClick: oauthReturn.dismiss, children: strings.promptDismissed })] })), composer && (_jsxs("form", { className: "guuey-chat-composer", onSubmit: (e) => {
497
588
  e.preventDefault();
@@ -1,29 +1,3 @@
1
- /**
2
- * The R1 markdown surface — the ONE place `@guuey/chat` renders
3
- * agent-influenced content in the embedder's origin, and therefore the
4
- * package's sanitizer boundary (spec §3.1).
5
- *
6
- * The pipeline is `@silverprotocol/richtext`: markdown → a TYPED AST in
7
- * which raw HTML is structurally unrepresentable (no HTML node type
8
- * exists; angle brackets can only ever be literal text) → React elements.
9
- * That is deliberately STRONGER than the spec's letter (markdown → HTML →
10
- * sanitize): there is no HTML string at any point, so there is nothing to
11
- * sanitize incorrectly — no `dangerouslySetInnerHTML` anywhere in this
12
- * package.
13
- *
14
- * Safety properties, each pinned by a test:
15
- * - raw HTML (`<img onerror=…>`, `<script>`) renders as literal text;
16
- * - link `href` is populated upstream ONLY for http/https/mailto —
17
- * `javascript:`, `data:`, `vbscript:`, and relative targets parse as
18
- * styled text with NO anchor `href` (richtext's `SAFE_HREF` allowlist);
19
- * - navigable links carry `rel="noopener noreferrer" target="_blank"`;
20
- * - there is NO image syntax in the node vocabulary at all — the spec's
21
- * F5 ruling (markdown images off; R7 media blocks are the sanctioned
22
- * image path) holds structurally, not by configuration.
23
- *
24
- * Streaming-tolerant by upstream design: unclosed emphasis mid-delta
25
- * renders as formatted-so-far.
26
- */
27
1
  import type { ReactNode } from "react";
28
2
  import { type RichTextTableBlock } from "../richtext-table.js";
29
3
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/react/markdown.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAMvC,OAAO,EAAqB,KAAK,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AA0GlF;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,EAAE,KAAK,EAAE,EAAE;IAAE,KAAK,EAAE,kBAAkB,CAAA;CAAE,GAAG,SAAS,CA4B9E;AAmCD,qEAAqE;AACrE,wBAAgB,QAAQ,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAQ9D"}
1
+ {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/react/markdown.tsx"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAMvC,OAAO,EAAqB,KAAK,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AA0GlF;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,EAAE,KAAK,EAAE,EAAE;IAAE,KAAK,EAAE,kBAAkB,CAAA;CAAE,GAAG,SAAS,CA4B9E;AAwED,qEAAqE;AACrE,wBAAgB,QAAQ,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAQ9D"}
@@ -1,4 +1,31 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ /**
3
+ * The R1 markdown surface — the ONE place `@guuey/chat` renders
4
+ * agent-influenced content in the embedder's origin, and therefore the
5
+ * package's sanitizer boundary (spec §3.1).
6
+ *
7
+ * The pipeline is `@silverprotocol/richtext`: markdown → a TYPED AST in
8
+ * which raw HTML is structurally unrepresentable (no HTML node type
9
+ * exists; angle brackets can only ever be literal text) → React elements.
10
+ * That is deliberately STRONGER than the spec's letter (markdown → HTML →
11
+ * sanitize): there is no HTML string at any point, so there is nothing to
12
+ * sanitize incorrectly — no `dangerouslySetInnerHTML` anywhere in this
13
+ * package.
14
+ *
15
+ * Safety properties, each pinned by a test:
16
+ * - raw HTML (`<img onerror=…>`, `<script>`) renders as literal text;
17
+ * - link `href` is populated upstream ONLY for http/https/mailto —
18
+ * `javascript:`, `data:`, `vbscript:`, and relative targets parse as
19
+ * styled text with NO anchor `href` (richtext's `SAFE_HREF` allowlist);
20
+ * - navigable links carry `rel="noopener noreferrer" target="_blank"`;
21
+ * - there is NO image syntax in the node vocabulary at all — the spec's
22
+ * F5 ruling (markdown images off; R7 media blocks are the sanctioned
23
+ * image path) holds structurally, not by configuration.
24
+ *
25
+ * Streaming-tolerant by upstream design: unclosed emphasis mid-delta
26
+ * renders as formatted-so-far.
27
+ */
28
+ import { useState } from "react";
2
29
  import { parseRichText, } from "@silverprotocol/richtext";
3
30
  import { normalizeTableRow } from "../richtext-table.js";
4
31
  /**
@@ -103,13 +130,35 @@ function Block({ block }) {
103
130
  case "heading":
104
131
  return (_jsx("p", { className: `guuey-chat-heading${block.level <= 3 ? " guuey-chat-heading-major" : ""}`, children: _jsx(Inline, { nodes: block.children }) }));
105
132
  case "code-fence":
106
- return _jsx("pre", { className: "guuey-chat-code-fence", children: block.code });
133
+ return _jsx(CodeFence, { code: block.code });
107
134
  case "list": {
108
135
  const Tag = block.ordered ? "ol" : "ul";
109
136
  return (_jsx(Tag, { ...(block.ordered && block.start !== undefined ? { start: block.start } : {}), children: block.items.map((item, j) => (_jsx("li", { children: _jsx(Inline, { nodes: item.children }) }, j))) }));
110
137
  }
111
138
  }
112
139
  }
140
+ /**
141
+ * A fenced code block with its copy affordance (guuey#529 — the
142
+ * seamless-default family: every embedder's visitors get it with zero
143
+ * setup). The button lives in a wrapper DIV so the `<pre>` holds ONLY the
144
+ * code (select-all inside the fence never picks up UI text); the
145
+ * transcript's sibling-margin rules name the wrapper class alongside
146
+ * `pre`. Copy failure is shown truthfully: the label simply stays "Copy"
147
+ * (clipboard access needs a secure context + the iframe's
148
+ * clipboard-write grant — manual selection always still works).
149
+ */
150
+ function CodeFence({ code }) {
151
+ const [copied, setCopied] = useState(false);
152
+ return (_jsxs("div", { className: "guuey-chat-code-wrap", children: [_jsx("pre", { className: "guuey-chat-code-fence", children: code }), _jsx("button", { type: "button", className: "guuey-chat-code-copy", "aria-label": copied ? "Copied" : "Copy code", onClick: () => {
153
+ const clipboard = navigator.clipboard;
154
+ if (clipboard === undefined)
155
+ return;
156
+ clipboard.writeText(code).then(() => {
157
+ setCopied(true);
158
+ setTimeout(() => setCopied(false), 1600);
159
+ }, () => setCopied(false));
160
+ }, children: copied ? "Copied" : "Copy" })] }));
161
+ }
113
162
  /** Sanitized markdown → React elements (see the module docblock). */
114
163
  export function Markdown({ text }) {
115
164
  return (_jsx(_Fragment, { children: parseRichText(text).map((block, i) => (_jsx(Block, { block: block }, i))) }));
@@ -1 +1 @@
1
- {"version":3,"file":"theme-css.d.ts","sourceRoot":"","sources":["../../src/react/theme-css.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;AAazC;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAsB3F"}
1
+ {"version":3,"file":"theme-css.d.ts","sourceRoot":"","sources":["../../src/react/theme-css.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;AAazC;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAyB3F"}
@@ -35,6 +35,9 @@ export function themeCssVars(theme, mode) {
35
35
  "--_guuey-chat-gap": DENSITY_GAP[theme.shape.density],
36
36
  "--_guuey-chat-scale": String(theme.typography.scale ?? 1),
37
37
  };
38
+ if (palette.link !== undefined) {
39
+ vars["--_guuey-chat-link"] = palette.link;
40
+ }
38
41
  if (theme.typography.fontFamily !== undefined) {
39
42
  vars["--_guuey-chat-font"] = theme.typography.fontFamily;
40
43
  }
package/dist/strings.d.ts CHANGED
@@ -121,6 +121,17 @@ export interface ChatStrings {
121
121
  linkAskLabel: (host: string) => string;
122
122
  linkOpen: string;
123
123
  linkDismiss: string;
124
+ /**
125
+ * The forget-this-device affordance (guuey#526): the quiet clear
126
+ * control and its two-tap confirm face.
127
+ */
128
+ clearConversationLabel: string;
129
+ clearConversationConfirm: string;
130
+ /**
131
+ * The suggestion-chip row's accessible name (guuey#533) — the chips
132
+ * themselves are declared content (the app's own words), never kit copy.
133
+ */
134
+ suggestionsLabel: string;
124
135
  /** The 3c composer (`<GuueyChat>`). */
125
136
  composerPlaceholder: string;
126
137
  composerUnavailable: string;
@@ -1 +1 @@
1
- {"version":3,"file":"strings.d.ts","sourceRoot":"","sources":["../src/strings.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"strings.d.ts","sourceRoot":"","sources":["../src/strings.ts"],"names":[],"mappings":"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"}
package/dist/strings.js CHANGED
@@ -80,6 +80,9 @@ export const defaultChatStrings = {
80
80
  linkAskLabel: (host) => `This card wants to open ${host}`,
81
81
  linkOpen: "Open",
82
82
  linkDismiss: "Dismiss",
83
+ clearConversationLabel: "Clear conversation",
84
+ suggestionsLabel: "Suggestions",
85
+ clearConversationConfirm: "Tap again to clear this device",
83
86
  composerPlaceholder: "Message the agent…",
84
87
  composerUnavailable: "Chat is unavailable.",
85
88
  composerLabel: "Message",
package/dist/theme.d.ts CHANGED
@@ -32,6 +32,7 @@ export declare const GuueyChatPalette: z.ZodObject<{
32
32
  canvas: z.ZodString;
33
33
  canvasMuted: z.ZodString;
34
34
  error: z.ZodString;
35
+ link: z.ZodOptional<z.ZodString>;
35
36
  }, z.core.$loose>;
36
37
  export type GuueyChatPalette = z.infer<typeof GuueyChatPalette>;
37
38
  /**
@@ -160,6 +161,7 @@ export declare const GuueyChatTheme: z.ZodObject<{
160
161
  canvas: z.ZodString;
161
162
  canvasMuted: z.ZodString;
162
163
  error: z.ZodString;
164
+ link: z.ZodOptional<z.ZodString>;
163
165
  }, z.core.$loose>;
164
166
  dark: z.ZodObject<{
165
167
  accent: z.ZodString;
@@ -170,6 +172,7 @@ export declare const GuueyChatTheme: z.ZodObject<{
170
172
  canvas: z.ZodString;
171
173
  canvasMuted: z.ZodString;
172
174
  error: z.ZodString;
175
+ link: z.ZodOptional<z.ZodString>;
173
176
  }, z.core.$loose>;
174
177
  }, z.core.$loose>;
175
178
  ramps: z.ZodOptional<z.ZodObject<{
@@ -240,6 +243,7 @@ export declare const GuueyChatTheme: z.ZodObject<{
240
243
  comfortable: "comfortable";
241
244
  }>;
242
245
  }, z.core.$loose>;
246
+ courts: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
243
247
  }, z.core.$loose>;
244
248
  export type GuueyChatTheme = z.infer<typeof GuueyChatTheme>;
245
249
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../src/theme.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;GAGG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;iBAWnB,CAAC;AACX,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAEhE;;;;;;;;;GASG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;iBAUtB,CAAC;AACX,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEtE,eAAO,MAAM,kBAAkB;;;;iBAMrB,CAAC;AACX,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAEpE,eAAO,MAAM,iBAAiB;;iBAAqD,CAAC;AACpF,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAElE,+DAA+D;AAC/D,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;iBAQnB,CAAC;AACX,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAEhE,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAKjB,CAAC;AACX,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAE5D,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA8BjB,CAAC;AACX,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAE5D;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,kBAAkB,EAAE,cA0BhC,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,EAAE,cA0B9B,CAAC;AA4CF;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,SAAS,EAAE,OAAO,EAClB,IAAI,GAAE,cAAmC,GACxC,cAAc,CAuBhB;AAYD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,OAAO,EAClB,KAAK,EAAE,MAAM,EACb,IAAI,GAAE,cAAmC,GACxC,cAAc,CAOhB"}
1
+ {"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../src/theme.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;GAGG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;iBAiBnB,CAAC;AACX,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAEhE;;;;;;;;;GASG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;iBAUtB,CAAC;AACX,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEtE,eAAO,MAAM,kBAAkB;;;;iBAMrB,CAAC;AACX,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAEpE,eAAO,MAAM,iBAAiB;;iBAAqD,CAAC;AACpF,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAElE,+DAA+D;AAC/D,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;iBAQnB,CAAC;AACX,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAEhE,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAKjB,CAAC;AACX,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAE5D,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAsCjB,CAAC;AACX,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAE5D;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,kBAAkB,EAAE,cA4BhC,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,EAAE,cAgC9B,CAAC;AA6CF;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,SAAS,EAAE,OAAO,EAClB,IAAI,GAAE,cAAmC,GACxC,cAAc,CAuBhB;AAYD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,OAAO,EAClB,KAAK,EAAE,MAAM,EACb,IAAI,GAAE,cAAmC,GACxC,cAAc,CAOhB"}
package/dist/theme.js CHANGED
@@ -33,6 +33,12 @@ export const GuueyChatPalette = z
33
33
  canvas: z.string(),
34
34
  canvasMuted: z.string(),
35
35
  error: z.string(),
36
+ /**
37
+ * Anchor color (guuey#528) — OPTIONAL by the evolution rule (a stored
38
+ * pre-#528 theme must keep passing the strict write gate); the default
39
+ * theme states it, so RESOLVED themes always carry it.
40
+ */
41
+ link: z.string().optional(),
36
42
  })
37
43
  .loose();
38
44
  /**
@@ -109,6 +115,14 @@ export const GuueyChatTheme = z
109
115
  density: z.enum(["compact", "comfortable"]),
110
116
  })
111
117
  .loose(),
118
+ /**
119
+ * Per-court override DOCUMENTS (guuey#519), keyed by serving court —
120
+ * declared vocabulary (guuey#536: the manifest grammar mirrors this
121
+ * schema key-for-key, so the member must be stated, not passthrough).
122
+ * Entries are partial theme documents; `resolveCourtTheme` owns the
123
+ * per-token layering and resolved themes are always court-free.
124
+ */
125
+ courts: z.record(z.string(), z.unknown()).optional(),
112
126
  })
113
127
  .loose();
114
128
  /**
@@ -136,6 +150,7 @@ export const DEFAULT_CHAT_THEME = {
136
150
  canvas: "#f7f7f5",
137
151
  canvasMuted: "#eceded",
138
152
  error: "#d64545",
153
+ link: "#111318",
139
154
  },
140
155
  dark: {
141
156
  accent: "#e8e9ee",
@@ -146,6 +161,7 @@ export const DEFAULT_CHAT_THEME = {
146
161
  canvas: "#0f1116",
147
162
  canvasMuted: "#1b1e26",
148
163
  error: "#ff6b6b",
164
+ link: "#e8e9ee",
149
165
  },
150
166
  },
151
167
  typography: {},
@@ -170,6 +186,9 @@ export const GUUEY_CHAT_THEME = {
170
186
  canvas: "#f6f5ee",
171
187
  canvasMuted: "#ecebe0",
172
188
  error: "#ff5b5b",
189
+ // slime-4, the founder-minted brand link green (guuey#528, 08-30) —
190
+ // the ladder had no readable green at link weight on light.
191
+ link: "#4e7a0e",
173
192
  },
174
193
  dark: {
175
194
  accent: "#b8ff3a",
@@ -180,6 +199,9 @@ export const GUUEY_CHAT_THEME = {
180
199
  canvas: "#0e1014",
181
200
  canvasMuted: "#1a1d24",
182
201
  error: "#ff5b5b",
202
+ // On dark the ladder's own slime IS readable at link weight — the
203
+ // #528 ruling minted slime-4 for LIGHT, where #b8ff3a is not.
204
+ link: "#b8ff3a",
183
205
  },
184
206
  },
185
207
  typography: {},
@@ -211,6 +233,7 @@ const PALETTE_TOKENS = [
211
233
  "canvas",
212
234
  "canvasMuted",
213
235
  "error",
236
+ "link",
214
237
  ];
215
238
  function mergePalette(base, over) {
216
239
  if (!over)
package/dist/types.d.ts CHANGED
@@ -497,6 +497,19 @@ export type ChatDebugEvent = {
497
497
  key: ItemKey;
498
498
  resourceUri: string;
499
499
  origin: "live" | "history";
500
+ }
501
+ /**
502
+ * `clearConversation()`'s server-erasure outcome (guuey#526). The clear
503
+ * itself is ALWAYS local-first and never blocks on this — the contract's
504
+ * unlinkability fallback says a denied/failed delete still clears the
505
+ * device and surfaces "nothing louder than a debug line"; this event IS
506
+ * that line. `"skipped"` = no platform door to call (no `apiBaseUrl`,
507
+ * or no thread ever minted) — the local-only clear, by construction.
508
+ */
509
+ | {
510
+ type: "thread-delete";
511
+ threadId: string | null;
512
+ outcome: "deleted" | "denied" | "failed" | "skipped";
500
513
  };
501
514
  /**
502
515
  * One renderable view the plan saw, BEFORE any chips/promotion pass —
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@guuey/chat",
3
- "version": "0.16.9",
3
+ "version": "0.16.11",
4
4
  "description": "The default end-user transcript UI for guuey agents — the headless view-model (planTranscript), calm/debug presets, the GuueyChatTheme token schema, the ChatStrings i18n seam, and (at ./react) the component kit that renders it: per-category components, <Transcript>, the live + history input assemblers, and stick-to-bottom/windowed/accessible transcript behavior; at ./native, the React Native renderer over the same view-model.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -39,8 +39,8 @@
39
39
  "@silverprotocol/core": "0.5.3",
40
40
  "@silverprotocol/richtext": "0.5.3",
41
41
  "zod": "^4.3.6",
42
- "@guuey/agent-client": "0.16.9",
43
- "@guuey/mcp-apps-host": "0.16.9"
42
+ "@guuey/agent-client": "0.16.11",
43
+ "@guuey/mcp-apps-host": "0.16.11"
44
44
  },
45
45
  "peerDependencies": {
46
46
  "react": ">=18",
package/src/plan.ts CHANGED
@@ -883,15 +883,34 @@ export function planTranscript(
883
883
  if (item.kind === "view" && item.actionScope !== null) liveViewScopes.add(item.actionScope);
884
884
  }
885
885
  const cards = [...(inputs.historyCards ?? [])].sort((a, b) => a.seq - b.seq);
886
- for (const card of cards) {
887
- const key = `card.${card.seq}`;
886
+ // guuey#535: ONE render session = ONE surface. Multiple history cards
887
+ // sharing an actionScope are the same surface referenced across turns
888
+ // (ggui SPEC §7.1.2.1 makes the amend result's {sessionId, resourceUri}
889
+ // the normative re-anchor reference — ggui#652; the stamp rides the
890
+ // existing locator persistence lane untouched). The LATEST reference
891
+ // anchors the surface; earlier references emit nothing — and latest
892
+ // wins even when it is locator-only, because the locator re-fetch
893
+ // restores CURRENT session state, better than an older frozen snapshot.
894
+ const scopes = cards.map((card) => {
888
895
  const mount = snapshotViewMount(card.cardSnapshot);
889
- const scope =
890
- mount === undefined
891
- ? null
892
- : mount.channel === "locator"
893
- ? mount.resourceUri
894
- : mount.resource.uri;
896
+ return {
897
+ card,
898
+ mount,
899
+ scope:
900
+ mount === undefined
901
+ ? null
902
+ : mount.channel === "locator"
903
+ ? mount.resourceUri
904
+ : mount.resource.uri,
905
+ };
906
+ });
907
+ const latestSeqByScope = new Map<string, number>();
908
+ for (const { card, scope } of scopes) {
909
+ if (scope !== null) latestSeqByScope.set(scope, card.seq);
910
+ }
911
+ for (const { card, mount, scope } of scopes) {
912
+ const key = `card.${card.seq}`;
913
+ if (scope !== null && latestSeqByScope.get(scope) !== card.seq) continue; // a later turn re-anchored it
895
914
  if (scope !== null && liveViewScopes.has(scope)) continue; // live mount owns it
896
915
  const view: ViewMountItem = {
897
916
  kind: "view",
@@ -60,6 +60,7 @@ import {
60
60
  createUiActionRelay,
61
61
  createUiResourceReader,
62
62
  createWebAdapters,
63
+ deleteThread,
63
64
  type AgentInvokeAdapters,
64
65
  } from "@guuey/agent-client";
65
66
  import type { AgHitlAnswer, AgPausedAsk } from "@silverprotocol/core";
@@ -169,6 +170,28 @@ export interface GuueyChatHandle {
169
170
  * to the transcript).
170
171
  */
171
172
  viewSlotProps(): ViewSlotProps;
173
+ /**
174
+ * Forget this conversation (guuey#526 — the public-computer story).
175
+ *
176
+ * Local half, unconditional and immediate: aborts any in-flight turn
177
+ * FIRST (a completing turn can re-persist its own rows), drops the
178
+ * durable thread pointer AND its persisted storage key, wipes the
179
+ * visible transcript, clears the typed draft and any pending link ask —
180
+ * the next send mints a fresh thread.
181
+ *
182
+ * Server half, best-effort: when the surface has a platform door
183
+ * (`apiBaseUrl`) and a minted thread, fires
184
+ * `DELETE /v1/threads/:threadId` with the SAME identity the thread was
185
+ * created under (captured before any rotation) — real, child-first
186
+ * server-side erasure. A denied or failed delete still clears the
187
+ * device (the contract's unlinkability fallback) and surfaces nothing
188
+ * louder than the `thread-delete` debug event.
189
+ *
190
+ * Afterwards `onGuestSecretRotate` fires (when wired), so the identity
191
+ * owner mints a fresh guest secret — even an orphaned server row is
192
+ * unreachable from a rotated identity.
193
+ */
194
+ clearConversation(): void;
172
195
  }
173
196
 
174
197
  export interface GuueyChatProps {
@@ -238,6 +261,39 @@ export interface GuueyChatProps {
238
261
  * pod door) when omitted; an explicit reader always wins.
239
262
  */
240
263
  reader?: UiResourceReader;
264
+ /**
265
+ * The forget-this-device affordance (guuey#526 — the public-computer
266
+ * story): a quiet "Clear conversation" control with a two-tap confirm,
267
+ * wired to {@link GuueyChatHandle.clearConversation}. Default: ON when
268
+ * the surface runs GUEST identity (`getGuestSecret` present — the
269
+ * founder's seamless principle; a signed-in surface has account-level
270
+ * recourse), OFF otherwise; pass a boolean to override either way.
271
+ */
272
+ clearAffordance?: boolean;
273
+ /**
274
+ * Guest-secret rotation hook (guuey#526): called at the END of every
275
+ * {@link GuueyChatHandle.clearConversation} — after the server delete
276
+ * has been dispatched with the OLD identity — so the owner of the
277
+ * secret's storage (the kit never stores it; `getGuestSecret` is a
278
+ * getter) mints a fresh one. Rotation is what makes even an orphaned
279
+ * server row unreachable: the new identity is a stranger to it. Guest
280
+ * KV state is (user,mcp)-scoped and is orphaned by rotation, by design.
281
+ */
282
+ onGuestSecretRotate?: () => void;
283
+ /**
284
+ * Suggestion chips (guuey#533 — declared content, the one-truth design):
285
+ * rendered on the EMPTY transcript only (they retire the moment a
286
+ * message exists — live send or restored history both count), one tap
287
+ * SENDS the chip text verbatim through exactly the Send button's gate.
288
+ * Default-ON when content exists; `false` opts the surface out. The kit
289
+ * mirrors the card projection's caps render-side (4 shown, ≤80 chars
290
+ * each, blank-rejected) — a direct consumer bypassing the platform's
291
+ * emit gate gets the same bounds. Content is the host's (the widget
292
+ * passes the card's `suggestions`; a direct consumer passes its own);
293
+ * the kit never invents chips — an honest empty state beats invented
294
+ * questions in the builder's voice.
295
+ */
296
+ suggestions?: readonly string[] | false;
241
297
  /** The debug sink (spec §5) — fires only under the debug policy. */
242
298
  onDebugEvent?: (event: ChatDebugEvent) => void;
243
299
  /** R6 pass-through (relay hook, sandbox page/flags, host context…). */
@@ -353,6 +409,9 @@ export const GuueyChat = forwardRef<GuueyChatHandle, GuueyChatProps>(function Gu
353
409
  oauthReturnTo,
354
410
  onOAuthAuthorize,
355
411
  onErrorAction,
412
+ clearAffordance,
413
+ onGuestSecretRotate,
414
+ suggestions,
356
415
  onActivity,
357
416
  onReady,
358
417
  onThread,
@@ -370,8 +429,14 @@ export const GuueyChat = forwardRef<GuueyChatHandle, GuueyChatProps>(function Gu
370
429
  // host back → setState → re-render → "Maximum update depth exceeded".
371
430
  const getAccessTokenRef = useRef(getAccessToken);
372
431
  getAccessTokenRef.current = getAccessToken;
432
+ // The handle is created once ([] deps) but must read the LIVE base —
433
+ // same ref discipline as every other handle-read value in this file.
434
+ const apiBaseUrlRef = useRef(apiBaseUrl);
435
+ apiBaseUrlRef.current = apiBaseUrl;
373
436
  const getGuestSecretRef = useRef(getGuestSecret);
374
437
  getGuestSecretRef.current = getGuestSecret;
438
+ const onGuestSecretRotateRef = useRef(onGuestSecretRotate);
439
+ onGuestSecretRotateRef.current = onGuestSecretRotate;
375
440
  const hasAccessToken = getAccessToken !== undefined;
376
441
  const hasGuestSecret = getGuestSecret !== undefined;
377
442
 
@@ -646,6 +711,37 @@ export const GuueyChat = forwardRef<GuueyChatHandle, GuueyChatProps>(function Gu
646
711
  // by construction. ONE pending ask at a time, newest replaces (a
647
712
  // card spamming asks can never grow an unbounded stack).
648
713
  const [pendingLink, setPendingLink] = useState<string | null>(null);
714
+ // guuey#526: the two-tap confirm window for the clear affordance (an
715
+ // accidental tap must not nuke a conversation; a second tap within the
716
+ // window does — the state auto-expires).
717
+ const [clearArmed, setClearArmed] = useState(false);
718
+ useEffect(() => {
719
+ if (!clearArmed) return;
720
+ const timer = setTimeout(() => setClearArmed(false), 4000);
721
+ return () => clearTimeout(timer);
722
+ }, [clearArmed]);
723
+ const showClearAffordance = clearAffordance ?? getGuestSecret !== undefined;
724
+ // guuey#533: the render-side mirror of the card projection's emit caps
725
+ // (4 shown / <=80 chars / blank-rejected) — same defense posture as the
726
+ // table normalizer: the kit is public npm and cannot assume every host
727
+ // routed content through platform's write gate.
728
+ const chips = useMemo<readonly string[]>(() => {
729
+ if (suggestions === false || suggestions === undefined) return [];
730
+ return suggestions
731
+ .map((c) => c.trim())
732
+ .filter((c) => c.length > 0 && c.length <= 80)
733
+ .slice(0, 4);
734
+ }, [suggestions]);
735
+ const sendSuggestion = useCallback((text: string): void => {
736
+ const live = liveRef.current;
737
+ // Exactly the Send button's gate (the #210 rule): unavailable, busy,
738
+ // or blank -> the tap is a no-op, never a bypass. The typed draft is
739
+ // left untouched (a chip send must not eat a half-typed message).
740
+ if (!live.available || live.busy || text.trim() === "") return;
741
+ void live.invoke.send(text).catch(() => {
742
+ // Same contract as submit: the hook owns failure surfacing.
743
+ });
744
+ }, []);
649
745
  const defaultOnOpenLink = useCallback((url: string) => {
650
746
  setPendingLink(url);
651
747
  }, []);
@@ -709,6 +805,48 @@ export const GuueyChat = forwardRef<GuueyChatHandle, GuueyChatProps>(function Gu
709
805
  focusComposer: (): void => {
710
806
  inputRef.current?.focus();
711
807
  },
808
+ clearConversation: (): void => {
809
+ const live = liveRef.current;
810
+ // Contract ordering (guuey#526, platform's frozen comment): abort
811
+ // FIRST — a completing turn can re-persist its own rows after the
812
+ // delete. Capture the id + guest secret BEFORE anything clears or
813
+ // rotates them: the delete must authenticate as the identity that
814
+ // OWNS the thread.
815
+ live.invoke.abort();
816
+ const threadId = threadIdRef.current;
817
+ const getGuest = getGuestSecretRef.current;
818
+ const guestSecret = getGuest !== undefined ? getGuest() : null;
819
+ if (apiBaseUrlRef.current !== undefined && threadId !== null) {
820
+ // Best-effort server erasure — fire-and-forget, never blocks the
821
+ // local clear. 200 and 404 are both "deleted" (idempotent by
822
+ // contract); denied/failed still cleared locally below (the
823
+ // unlinkability fallback) and surface ONLY as a debug line.
824
+ void deleteThread({
825
+ apiBaseUrl: apiBaseUrlRef.current,
826
+ threadId,
827
+ ...(getAccessTokenRef.current !== undefined
828
+ ? { getAccessToken: getAccessTokenRef.current }
829
+ : {}),
830
+ guestSecret,
831
+ }).then((outcome) => {
832
+ onDebugEventRef.current?.({ type: "thread-delete", threadId, outcome });
833
+ });
834
+ } else {
835
+ onDebugEventRef.current?.({ type: "thread-delete", threadId, outcome: "skipped" });
836
+ }
837
+ // The hook's reset owns the durable local half (pointer + storage
838
+ // key, transcript/fold/cards); the kit clears ITS OWN residue —
839
+ // the typed draft, a pending link ask, queued doorbells — so the
840
+ // device holds nothing of the conversation.
841
+ live.invoke.reset();
842
+ setInput("");
843
+ setPendingLink(null);
844
+ pendingDoorbellsRef.current = [];
845
+ // Rotation LAST: the delete above already captured the old
846
+ // identity, so the fresh secret is a stranger to even an orphaned
847
+ // server row.
848
+ onGuestSecretRotateRef.current?.();
849
+ },
712
850
  // A getter, not a captured value: the handle is created once, but the
713
851
  // thread hydrates after mount and can change — reads go through the
714
852
  // same ref the default reader uses, so it is always the live id.
@@ -828,6 +966,38 @@ export const GuueyChat = forwardRef<GuueyChatHandle, GuueyChatProps>(function Gu
828
966
  {...(onViewRef !== undefined ? { onViewRef } : {})}
829
967
  viewProps={effectiveViewProps}
830
968
  />
969
+ {chips.length > 0 && inputs.messages.length === 0 && (
970
+ <nav className="guuey-chat-chips-row" aria-label={strings.suggestionsLabel}>
971
+ {chips.map((chip) => (
972
+ <button
973
+ key={chip}
974
+ type="button"
975
+ className="guuey-chat-chip"
976
+ onClick={() => sendSuggestion(chip)}
977
+ >
978
+ {chip}
979
+ </button>
980
+ ))}
981
+ </nav>
982
+ )}
983
+ {showClearAffordance && inputs.messages.length > 0 && (
984
+ <div className="guuey-chat-clear-row">
985
+ <button
986
+ type="button"
987
+ className={`guuey-chat-clear${clearArmed ? " guuey-chat-clear-armed" : ""}`}
988
+ onClick={() => {
989
+ if (clearArmed) {
990
+ setClearArmed(false);
991
+ handle.clearConversation();
992
+ } else {
993
+ setClearArmed(true);
994
+ }
995
+ }}
996
+ >
997
+ {clearArmed ? strings.clearConversationConfirm : strings.clearConversationLabel}
998
+ </button>
999
+ </div>
1000
+ )}
831
1001
  {pendingLink !== null && (
832
1002
  <div role="status" className="guuey-chat-link-ask">
833
1003
  <span className="guuey-chat-link-ask-label">
@@ -24,6 +24,7 @@
24
24
  * Streaming-tolerant by upstream design: unclosed emphasis mid-delta
25
25
  * renders as formatted-so-far.
26
26
  */
27
+ import { useState } from "react";
27
28
  import type { ReactNode } from "react";
28
29
  import {
29
30
  parseRichText,
@@ -188,7 +189,7 @@ function Block({ block }: { block: RichTextBlock }): ReactNode {
188
189
  </p>
189
190
  );
190
191
  case "code-fence":
191
- return <pre className="guuey-chat-code-fence">{block.code}</pre>;
192
+ return <CodeFence code={block.code} />;
192
193
  case "list": {
193
194
  const Tag = block.ordered ? "ol" : "ul";
194
195
  return (
@@ -204,6 +205,43 @@ function Block({ block }: { block: RichTextBlock }): ReactNode {
204
205
  }
205
206
  }
206
207
 
208
+ /**
209
+ * A fenced code block with its copy affordance (guuey#529 — the
210
+ * seamless-default family: every embedder's visitors get it with zero
211
+ * setup). The button lives in a wrapper DIV so the `<pre>` holds ONLY the
212
+ * code (select-all inside the fence never picks up UI text); the
213
+ * transcript's sibling-margin rules name the wrapper class alongside
214
+ * `pre`. Copy failure is shown truthfully: the label simply stays "Copy"
215
+ * (clipboard access needs a secure context + the iframe's
216
+ * clipboard-write grant — manual selection always still works).
217
+ */
218
+ function CodeFence({ code }: { code: string }): ReactNode {
219
+ const [copied, setCopied] = useState(false);
220
+ return (
221
+ <div className="guuey-chat-code-wrap">
222
+ <pre className="guuey-chat-code-fence">{code}</pre>
223
+ <button
224
+ type="button"
225
+ className="guuey-chat-code-copy"
226
+ aria-label={copied ? "Copied" : "Copy code"}
227
+ onClick={() => {
228
+ const clipboard = navigator.clipboard;
229
+ if (clipboard === undefined) return;
230
+ clipboard.writeText(code).then(
231
+ () => {
232
+ setCopied(true);
233
+ setTimeout(() => setCopied(false), 1600);
234
+ },
235
+ () => setCopied(false),
236
+ );
237
+ }}
238
+ >
239
+ {copied ? "Copied" : "Copy"}
240
+ </button>
241
+ </div>
242
+ );
243
+ }
244
+
207
245
  /** Sanitized markdown → React elements (see the module docblock). */
208
246
  export function Markdown({ text }: { text: string }): ReactNode {
209
247
  return (
@@ -48,6 +48,9 @@ export function themeCssVars(theme: GuueyChatTheme, mode: ThemeMode): Record<str
48
48
  "--_guuey-chat-gap": DENSITY_GAP[theme.shape.density],
49
49
  "--_guuey-chat-scale": String(theme.typography.scale ?? 1),
50
50
  };
51
+ if (palette.link !== undefined) {
52
+ vars["--_guuey-chat-link"] = palette.link;
53
+ }
51
54
  if (theme.typography.fontFamily !== undefined) {
52
55
  vars["--_guuey-chat-font"] = theme.typography.fontFamily;
53
56
  }
package/src/strings.ts CHANGED
@@ -137,6 +137,19 @@ export interface ChatStrings {
137
137
  linkOpen: string;
138
138
  linkDismiss: string;
139
139
 
140
+ /**
141
+ * The forget-this-device affordance (guuey#526): the quiet clear
142
+ * control and its two-tap confirm face.
143
+ */
144
+ clearConversationLabel: string;
145
+ clearConversationConfirm: string;
146
+
147
+ /**
148
+ * The suggestion-chip row's accessible name (guuey#533) — the chips
149
+ * themselves are declared content (the app's own words), never kit copy.
150
+ */
151
+ suggestionsLabel: string;
152
+
140
153
  /** The 3c composer (`<GuueyChat>`). */
141
154
  composerPlaceholder: string;
142
155
  composerUnavailable: string;
@@ -246,6 +259,10 @@ export const defaultChatStrings: ChatStrings = {
246
259
  linkOpen: "Open",
247
260
  linkDismiss: "Dismiss",
248
261
 
262
+ clearConversationLabel: "Clear conversation",
263
+ suggestionsLabel: "Suggestions",
264
+ clearConversationConfirm: "Tap again to clear this device",
265
+
249
266
  composerPlaceholder: "Message the agent…",
250
267
  composerUnavailable: "Chat is unavailable.",
251
268
  composerLabel: "Message",
package/src/theme.ts CHANGED
@@ -34,6 +34,12 @@ export const GuueyChatPalette = z
34
34
  canvas: z.string(),
35
35
  canvasMuted: z.string(),
36
36
  error: z.string(),
37
+ /**
38
+ * Anchor color (guuey#528) — OPTIONAL by the evolution rule (a stored
39
+ * pre-#528 theme must keep passing the strict write gate); the default
40
+ * theme states it, so RESOLVED themes always carry it.
41
+ */
42
+ link: z.string().optional(),
37
43
  })
38
44
  .loose();
39
45
  export type GuueyChatPalette = z.infer<typeof GuueyChatPalette>;
@@ -122,6 +128,14 @@ export const GuueyChatTheme = z
122
128
  density: z.enum(["compact", "comfortable"]),
123
129
  })
124
130
  .loose(),
131
+ /**
132
+ * Per-court override DOCUMENTS (guuey#519), keyed by serving court —
133
+ * declared vocabulary (guuey#536: the manifest grammar mirrors this
134
+ * schema key-for-key, so the member must be stated, not passthrough).
135
+ * Entries are partial theme documents; `resolveCourtTheme` owns the
136
+ * per-token layering and resolved themes are always court-free.
137
+ */
138
+ courts: z.record(z.string(), z.unknown()).optional(),
125
139
  })
126
140
  .loose();
127
141
  export type GuueyChatTheme = z.infer<typeof GuueyChatTheme>;
@@ -151,6 +165,7 @@ export const DEFAULT_CHAT_THEME: GuueyChatTheme = {
151
165
  canvas: "#f7f7f5",
152
166
  canvasMuted: "#eceded",
153
167
  error: "#d64545",
168
+ link: "#111318",
154
169
  },
155
170
  dark: {
156
171
  accent: "#e8e9ee",
@@ -161,6 +176,7 @@ export const DEFAULT_CHAT_THEME: GuueyChatTheme = {
161
176
  canvas: "#0f1116",
162
177
  canvasMuted: "#1b1e26",
163
178
  error: "#ff6b6b",
179
+ link: "#e8e9ee",
164
180
  },
165
181
  },
166
182
  typography: {},
@@ -186,6 +202,9 @@ export const GUUEY_CHAT_THEME: GuueyChatTheme = {
186
202
  canvas: "#f6f5ee",
187
203
  canvasMuted: "#ecebe0",
188
204
  error: "#ff5b5b",
205
+ // slime-4, the founder-minted brand link green (guuey#528, 08-30) —
206
+ // the ladder had no readable green at link weight on light.
207
+ link: "#4e7a0e",
189
208
  },
190
209
  dark: {
191
210
  accent: "#b8ff3a",
@@ -196,6 +215,9 @@ export const GUUEY_CHAT_THEME: GuueyChatTheme = {
196
215
  canvas: "#0e1014",
197
216
  canvasMuted: "#1a1d24",
198
217
  error: "#ff5b5b",
218
+ // On dark the ladder's own slime IS readable at link weight — the
219
+ // #528 ruling minted slime-4 for LIGHT, where #b8ff3a is not.
220
+ link: "#b8ff3a",
199
221
  },
200
222
  },
201
223
  typography: {},
@@ -229,6 +251,7 @@ const PALETTE_TOKENS = [
229
251
  "canvas",
230
252
  "canvasMuted",
231
253
  "error",
254
+ "link",
232
255
  ] as const;
233
256
 
234
257
  function mergePalette(
package/src/types.ts CHANGED
@@ -540,7 +540,20 @@ export type ChatDebugEvent =
540
540
  * is by construction, not a failure). Debug-only like every event here
541
541
  * — calm end-user UX keeps deny == miss un-oracled.
542
542
  */
543
- | { type: "locator-read-miss"; key: ItemKey; resourceUri: string; origin: "live" | "history" };
543
+ | { type: "locator-read-miss"; key: ItemKey; resourceUri: string; origin: "live" | "history" }
544
+ /**
545
+ * `clearConversation()`'s server-erasure outcome (guuey#526). The clear
546
+ * itself is ALWAYS local-first and never blocks on this — the contract's
547
+ * unlinkability fallback says a denied/failed delete still clears the
548
+ * device and surfaces "nothing louder than a debug line"; this event IS
549
+ * that line. `"skipped"` = no platform door to call (no `apiBaseUrl`,
550
+ * or no thread ever minted) — the local-only clear, by construction.
551
+ */
552
+ | {
553
+ type: "thread-delete";
554
+ threadId: string | null;
555
+ outcome: "deleted" | "denied" | "failed" | "skipped";
556
+ };
544
557
 
545
558
  /**
546
559
  * One renderable view the plan saw, BEFORE any chips/promotion pass —
package/styles.css CHANGED
@@ -40,6 +40,48 @@
40
40
  margin-inline: auto;
41
41
  }
42
42
 
43
+ /* ── suggestion chips (guuey#533) — empty-state only, one-tap-sends;
44
+ restyled ENTIRELY by the #521 composable tokens (surface/ink/radius
45
+ — no new tokens). ── */
46
+ .guuey-chat-chips-row {
47
+ display: flex;
48
+ flex-wrap: wrap;
49
+ gap: 8px;
50
+ padding: 4px calc(var(--guuey-chat-gap) * 1.5);
51
+ }
52
+ .guuey-chat-chip {
53
+ background: var(--guuey-chat-surface, var(--_guuey-chat-surface));
54
+ color: var(--guuey-chat-ink, var(--_guuey-chat-ink));
55
+ border: 1px solid var(--guuey-chat-ink-muted);
56
+ border-radius: var(--guuey-chat-radius, var(--_guuey-chat-radius));
57
+ padding: 6px 12px;
58
+ font-size: 0.85em;
59
+ cursor: pointer;
60
+ text-align: start;
61
+ }
62
+ .guuey-chat-chip:hover {
63
+ border-color: var(--guuey-chat-ink, var(--_guuey-chat-ink));
64
+ }
65
+
66
+ /* ── forget-this-device (guuey#526) — quiet, right-aligned, two-tap. ── */
67
+ .guuey-chat-clear-row {
68
+ display: flex;
69
+ justify-content: flex-end;
70
+ padding: 0 calc(var(--guuey-chat-gap) * 1.5);
71
+ }
72
+ .guuey-chat-clear {
73
+ background: none;
74
+ border: none;
75
+ padding: 2px 4px;
76
+ font-size: 0.8em;
77
+ color: var(--guuey-chat-ink-muted);
78
+ cursor: pointer;
79
+ }
80
+ .guuey-chat-clear-armed {
81
+ color: var(--guuey-chat-error);
82
+ font-weight: 600;
83
+ }
84
+
43
85
  /* ── ui/open-link disclosure (guuey#522) — the URL is SHOWN before any
44
86
  navigation; Open is the human's own anchor click. ── */
45
87
  .guuey-chat-link-ask {
@@ -123,6 +165,14 @@
123
165
  font-size: inherit;
124
166
  }
125
167
 
168
+ /* Links (guuey#528): the one text class with its own token. The neutral
169
+ default equals ink (underline alone distinguishes — native), so an
170
+ unthemed embed stays monochrome; a brand states its link color once
171
+ (theme or the host CSS-var channel, composing per #521's model). */
172
+ .guuey-chat a {
173
+ color: var(--guuey-chat-link, var(--_guuey-chat-link, inherit));
174
+ }
175
+
126
176
  /* ── R1 assistant text ── */
127
177
  .guuey-chat-text {
128
178
  align-self: flex-start;
@@ -152,6 +202,8 @@
152
202
  .guuey-chat-text p + p,
153
203
  .guuey-chat-text pre + p,
154
204
  .guuey-chat-text p + pre,
205
+ .guuey-chat-text .guuey-chat-code-wrap + p,
206
+ .guuey-chat-text p + .guuey-chat-code-wrap,
155
207
  .guuey-chat-text ul + p,
156
208
  .guuey-chat-text p + ul,
157
209
  .guuey-chat-text p + ol {
@@ -177,6 +229,39 @@
177
229
  padding: 8px 10px;
178
230
  overflow-x: auto;
179
231
  }
232
+ /* The fence's copy affordance (guuey#529): hover-reveal on pointer
233
+ devices, persistent on touch — the common grammar. Tokens ride the
234
+ composable channel like everything else. */
235
+ .guuey-chat-code-wrap {
236
+ position: relative;
237
+ }
238
+ .guuey-chat-code-copy {
239
+ position: absolute;
240
+ top: 5px;
241
+ right: 5px;
242
+ padding: 2px 8px;
243
+ font: 600 11px/1.6 inherit;
244
+ border: 1px solid color-mix(in srgb, var(--guuey-chat-ink, var(--_guuey-chat-ink)) 15%, transparent);
245
+ border-radius: 6px;
246
+ background: var(--guuey-chat-surface, var(--_guuey-chat-surface));
247
+ color: var(--guuey-chat-ink-muted, var(--_guuey-chat-ink-muted));
248
+ cursor: pointer;
249
+ opacity: 0;
250
+ }
251
+ .guuey-chat-code-wrap:hover .guuey-chat-code-copy,
252
+ .guuey-chat-code-copy:focus-visible {
253
+ opacity: 1;
254
+ }
255
+ @media (hover: none) {
256
+ .guuey-chat-code-copy {
257
+ opacity: 1;
258
+ }
259
+ }
260
+ @media (prefers-reduced-motion: no-preference) {
261
+ .guuey-chat-code-copy {
262
+ transition: opacity 120ms ease-out;
263
+ }
264
+ }
180
265
  .guuey-chat-verbatim {
181
266
  white-space: pre-wrap;
182
267
  margin: 0;