@guuey/chat 0.5.0 → 0.6.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.
Files changed (61) hide show
  1. package/dist/hitl.d.ts +58 -0
  2. package/dist/hitl.d.ts.map +1 -0
  3. package/dist/hitl.js +81 -0
  4. package/dist/index.d.ts +3 -2
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +2 -1
  7. package/dist/native/components.d.ts +18 -2
  8. package/dist/native/components.d.ts.map +1 -1
  9. package/dist/native/components.js +49 -0
  10. package/dist/native/transcript.d.ts +1 -1
  11. package/dist/native/transcript.d.ts.map +1 -1
  12. package/dist/native/transcript.js +2 -2
  13. package/dist/native.d.ts +1 -1
  14. package/dist/native.d.ts.map +1 -1
  15. package/dist/native.js +1 -1
  16. package/dist/plan.d.ts +15 -0
  17. package/dist/plan.d.ts.map +1 -1
  18. package/dist/plan.js +211 -13
  19. package/dist/policy.d.ts +4 -0
  20. package/dist/policy.d.ts.map +1 -1
  21. package/dist/policy.js +2 -0
  22. package/dist/react/components.d.ts +42 -5
  23. package/dist/react/components.d.ts.map +1 -1
  24. package/dist/react/components.js +51 -1
  25. package/dist/react/guuey-chat.d.ts +62 -4
  26. package/dist/react/guuey-chat.d.ts.map +1 -1
  27. package/dist/react/guuey-chat.js +73 -8
  28. package/dist/react/transcript.d.ts +1 -1
  29. package/dist/react/transcript.d.ts.map +1 -1
  30. package/dist/react/transcript.js +2 -2
  31. package/dist/react/use-transcript.d.ts +21 -2
  32. package/dist/react/use-transcript.d.ts.map +1 -1
  33. package/dist/react/use-transcript.js +57 -3
  34. package/dist/react.d.ts +2 -2
  35. package/dist/react.d.ts.map +1 -1
  36. package/dist/react.js +1 -1
  37. package/dist/strings.d.ts +13 -0
  38. package/dist/strings.d.ts.map +1 -1
  39. package/dist/strings.js +8 -0
  40. package/dist/types.d.ts +146 -7
  41. package/dist/types.d.ts.map +1 -1
  42. package/package.json +5 -5
  43. package/src/corpus/README.md +13 -1
  44. package/src/corpus/__snapshots__/corpus.test.ts.snap +304 -0
  45. package/src/corpus/drive.ts +3 -3
  46. package/src/corpus/fixtures.ts +220 -1
  47. package/src/hitl.ts +103 -0
  48. package/src/index.ts +15 -0
  49. package/src/native/components.tsx +136 -1
  50. package/src/native/transcript.tsx +4 -3
  51. package/src/native.tsx +1 -0
  52. package/src/plan.ts +233 -20
  53. package/src/policy.ts +4 -0
  54. package/src/react/components.tsx +171 -8
  55. package/src/react/guuey-chat.tsx +143 -9
  56. package/src/react/transcript.tsx +4 -3
  57. package/src/react/use-transcript.ts +83 -5
  58. package/src/react.tsx +3 -1
  59. package/src/strings.ts +25 -0
  60. package/src/types.ts +152 -6
  61. package/styles.css +21 -0
package/src/types.ts CHANGED
@@ -11,7 +11,14 @@
11
11
  * events. A category this UI needs but AgJSON cannot express is an upstream
12
12
  * silverprotocol change, never a guuey-side extension.
13
13
  */
14
- import type { AgReduceResult, AgSource, JsonValue } from "@silverprotocol/core";
14
+ import type {
15
+ AgGrantMode,
16
+ AgNoticeSource,
17
+ AgPausedAsk,
18
+ AgReduceResult,
19
+ AgSource,
20
+ JsonValue,
21
+ } from "@silverprotocol/core";
15
22
  import type { AgentInvokeStatus, HistoryCard } from "@guuey/agent-client";
16
23
  import type { ViewHostPhase, ViewMount, ViewMountChannel } from "@guuey/mcp-apps-host";
17
24
 
@@ -20,12 +27,18 @@ import type { ViewHostPhase, ViewMount, ViewMountChannel } from "@guuey/mcp-apps
20
27
  * compatible with the hook's `AgentMessage`, plus the optional
21
28
  * `clientMessageId` the R0 send-lifecycle join needs (the 3b live assembler
22
29
  * threads it through; history entries and older callers simply omit it).
30
+ *
31
+ * `role: "notice"` (spec draft.2, silverprotocol#16) is a host/adapter/
32
+ * framework-injected session annotation — a PEER of user/assistant rows,
33
+ * never assistant content. `noticeSource` is its provenance label (R16).
23
34
  */
24
35
  export interface TranscriptMessage {
25
- role: "user" | "assistant";
36
+ role: "user" | "assistant" | "notice";
26
37
  text: string;
27
38
  /** Present on live-sent user turns — the `sendStates` join key (R0). */
28
39
  clientMessageId?: string;
40
+ /** R16 provenance — meaningful only when `role === "notice"`. */
41
+ noticeSource?: AgNoticeSource;
29
42
  }
30
43
 
31
44
  /**
@@ -34,7 +47,7 @@ export interface TranscriptMessage {
34
47
  * The assembler (3b) accumulates these from `invokeTurn` events; `id` is
35
48
  * assembler-chosen and stable for the ask's lifetime.
36
49
  */
37
- export interface PromptItemInput {
50
+ export interface ProfilePromptInput {
38
51
  id: string;
39
52
  kind: "consent" | "link";
40
53
  appId: string;
@@ -42,9 +55,49 @@ export interface PromptItemInput {
42
55
  state: "pending" | "answered" | "declined" | "dismissed";
43
56
  }
44
57
 
58
+ /**
59
+ * An AgJSON HITL ask (spec draft.2, silverprotocol#16) lifted from the
60
+ * fold's PERSISTED declaration — the `AgPausedAsk` record in
61
+ * `turn.done.outcome:"paused".asks[]` (the ask event itself is live-only;
62
+ * the paused record is what a late-joining client renders from). Produced
63
+ * by `hitlPromptsFromFold`; `id === ask.askId`.
64
+ *
65
+ * States encode guuey's ratified dismissal ruling (issue #16): `cancelled`
66
+ * is still-pending-and-re-askable (the card stays answerable), `declined`
67
+ * is the durable explicit deny.
68
+ */
69
+ export interface HitlPromptInput {
70
+ id: string;
71
+ kind: "hitl";
72
+ /** The persisted declaration — message, kind, and any declared grantModes. */
73
+ ask: AgPausedAsk;
74
+ state: "pending" | "resolved" | "declined" | "cancelled";
75
+ /** Echo of the chosen declared mode; present iff `state === "resolved"`. */
76
+ grantModeId?: string;
77
+ }
78
+
79
+ /**
80
+ * R10 prompt inputs — a discriminated union (narrow on `kind`). The
81
+ * profile arm is the original guuey-wire shape unchanged; `hitl` arrived
82
+ * with spec draft.2. (Direct un-narrowed reads of profile-only fields are
83
+ * the one shape this union retired — narrow first.)
84
+ */
85
+ export type PromptItemInput = ProfilePromptInput | HitlPromptInput;
86
+
45
87
  /** Everything the plan derives from. All fields are data — no clocks, no DOM. */
46
88
  export interface TranscriptInputs {
47
- /** The Reducer's fold (silver mode); null on bypass-frame streams. */
89
+ /**
90
+ * The Reducer's fold (silver mode); null on bypass-frame streams.
91
+ *
92
+ * TURN-SCOPED (guuey#135 kit refinement): the fold owns the TRAILING
93
+ * assistant turns it covers — its settled sources replace that many
94
+ * trailing flat assistant entries, and any earlier flat entries (a
95
+ * rehydrated/persisted prefix the session's Reducer never saw) render as
96
+ * text in front. A fold spanning the whole conversation plans exactly as
97
+ * before, so pure-live sessions are unaffected; persisted-overlay hosts
98
+ * (portal's thread views) can now pass the session fold beside their
99
+ * persisted rows instead of nulling it.
100
+ */
48
101
  result: AgReduceResult | null;
49
102
  /**
50
103
  * The in-flight turn's cumulative text fold (ALWAYS present; the sole
@@ -75,6 +128,19 @@ export interface TranscriptInputs {
75
128
  sendStates?: Readonly<Record<string, "sending" | "failed">>;
76
129
  /** mountKey → live phase (R6 states). Keys match `ViewMountItem.key`. */
77
130
  viewPhases?: Readonly<Record<string, ViewHostPhase>>;
131
+ /**
132
+ * The mount key a host-owned stage/canvas surface currently shows
133
+ * (guuey#204 "promote and reference") — renderer-supplied state, like
134
+ * `sendStates`. When set, the plan emits a compact {@link ViewRefItem}
135
+ * in that mount's transcript slot instead of the full
136
+ * {@link ViewMountItem}, so an interactive surface exists exactly ONCE.
137
+ * Absent (or matching nothing / an expired mount) = today's behavior —
138
+ * every mount renders inline. Hosts derive the key with
139
+ * {@link newestViewKey} rather than hand-building it; the issue's
140
+ * phase-2 (every card a chip, click-to-swap) is this same field set per
141
+ * host click, no further plan changes.
142
+ */
143
+ promotedViewKey?: string;
78
144
  /** The last turn ended by user abort (R1 aborted-partial + "Stopped."). */
79
145
  aborted?: boolean;
80
146
  /**
@@ -195,6 +261,21 @@ export interface ViewMountItem extends BaseItem {
195
261
  actionScope: string | null;
196
262
  }
197
263
 
264
+ /**
265
+ * R6's "promote and reference" chip (guuey#204): stands in for the ONE
266
+ * {@link ViewMountItem} a host's stage/canvas currently shows
267
+ * (`TranscriptInputs.promotedViewKey`), so the interactive surface exists
268
+ * exactly once. `key` is the replaced mount's key — overrides and phase
269
+ * reports keep their identity if the item swaps back to a full mount.
270
+ */
271
+ export interface ViewRefItem extends BaseItem {
272
+ kind: "viewRef";
273
+ /** The display title (the producing call's, or the strings fallback). */
274
+ title: string;
275
+ /** The full resolved chip text (`strings.viewPromoted(title)`). */
276
+ label: string;
277
+ }
278
+
198
279
  /** R7 — media blocks. */
199
280
  export interface MediaItem extends BaseItem {
200
281
  kind: "media";
@@ -220,8 +301,8 @@ export interface CitationsItem extends BaseItem {
220
301
  style: "chips" | "list";
221
302
  }
222
303
 
223
- /** R10 — a consent/link prompt card. */
224
- export interface PromptItem extends BaseItem {
304
+ /** R10 — the guuey-wire consent/link prompt card (the original arm). */
305
+ export interface ProfilePromptItem extends BaseItem {
225
306
  kind: "prompt";
226
307
  /** The `PromptItemInput.id` this row records — the host's resolution key. */
227
308
  promptId: string;
@@ -233,6 +314,50 @@ export interface PromptItem extends BaseItem {
233
314
  raw: JsonValue | null;
234
315
  }
235
316
 
317
+ /**
318
+ * R10 — an AgJSON HITL ask card (spec draft.2). Display keys off each
319
+ * mode's `label`/`description` ONLY — ids are echo-only identity, and
320
+ * mode SEMANTICS are asker-scoped (normative: never hard-code meaning
321
+ * onto an id string). `cancelled` renders as a dismissed record that is
322
+ * still answerable when expanded (guuey's re-askable ruling); `declined`
323
+ * and `resolved` are settled records.
324
+ */
325
+ export interface HitlPromptItem extends BaseItem {
326
+ kind: "prompt";
327
+ promptId: string;
328
+ promptKind: "hitl";
329
+ /** The persisted declaration — carried so answer construction/validation has the record. */
330
+ ask: AgPausedAsk;
331
+ /** The asker's message, when it sent one. */
332
+ message: string | null;
333
+ askKind: AgPausedAsk["kind"];
334
+ /** Declared accept variants; empty = a plain accept/decline ask. */
335
+ grantModes: readonly AgGrantMode[];
336
+ state: "pending" | "resolved" | "declined" | "cancelled";
337
+ /** Echo of the chosen mode id (identity, never displayed as meaning). */
338
+ chosenModeId: string | null;
339
+ /** Resolved display text for the chosen mode (label, else the id as literal text). */
340
+ chosenModeLabel: string | null;
341
+ /** Raw ask payload, populated only under the debug policy. */
342
+ raw: JsonValue | null;
343
+ }
344
+
345
+ /** R10 union — narrow on `promptKind`. */
346
+ export type PromptItem = ProfilePromptItem | HitlPromptItem;
347
+
348
+ /**
349
+ * R16 — a `role:"notice"` session annotation (spec draft.2): a labeled,
350
+ * NON-conversational row that must never read as agent-authored.
351
+ */
352
+ export interface NoticeItem extends BaseItem {
353
+ kind: "notice";
354
+ text: string;
355
+ /** Provenance facet; null when the producer omitted it. */
356
+ source: AgNoticeSource | null;
357
+ /** Resolved provenance display — the facet verbatim under debug, else null. */
358
+ sourceLabel: string | null;
359
+ }
360
+
236
361
  /** R11 — a coded, human-worded error notice. */
237
362
  export interface ErrorItem extends BaseItem {
238
363
  kind: "error";
@@ -281,10 +406,12 @@ export type DisplayItem =
281
406
  | ToolGroupItem
282
407
  | DataResultItem
283
408
  | ViewMountItem
409
+ | ViewRefItem
284
410
  | MediaItem
285
411
  | CodeItem
286
412
  | CitationsItem
287
413
  | PromptItem
414
+ | NoticeItem
288
415
  | ErrorItem
289
416
  | HistoryBoundaryItem
290
417
  | CompactionItem
@@ -306,6 +433,25 @@ export interface StatusLineItem {
306
433
  detail: string | null;
307
434
  }
308
435
 
436
+ /**
437
+ * The debug sink's event union (spec §5's `onDebugEvent`, shipped as real
438
+ * API in the #135 refinement wave) — built strictly from what the kit
439
+ * actually knows, never invented telemetry:
440
+ *
441
+ * - `view-phase`: an R6 mount's host-phase transition (incl. the R13
442
+ * `expired` verdict from a failed locator resolution);
443
+ * - `unknown-block`: an R15 sighting — a block type this kit version does
444
+ * not know rendered as a labeled row;
445
+ * - `turn-recovered`: the #192 adopted-turn marker resolved on the plan.
446
+ *
447
+ * The sink only fires under the debug policy (`debugDetail`) — `calm`
448
+ * ignores it by design (spec §5's per-preset row).
449
+ */
450
+ export type ChatDebugEvent =
451
+ | { type: "view-phase"; key: ItemKey; phase: ViewHostPhase | "expired" }
452
+ | { type: "unknown-block"; key: ItemKey; typeName: string; byteSize: number }
453
+ | { type: "turn-recovered"; marker: string };
454
+
309
455
  export interface TranscriptPlan {
310
456
  /** Ordered, stable keys (spec §7's determinism contract). */
311
457
  items: DisplayItem[];
package/styles.css CHANGED
@@ -241,6 +241,27 @@
241
241
  font-size: 0.78em;
242
242
  border-top: 1px solid color-mix(in srgb, var(--guuey-chat-ink) 6%, transparent);
243
243
  }
244
+ /* guuey#204: the promoted-view reference chip — compact, never a frame. */
245
+ .guuey-chat-view-ref {
246
+ display: inline-block;
247
+ margin: 0;
248
+ padding: 6px 12px;
249
+ border: 1px solid color-mix(in srgb, var(--guuey-chat-ink) 12%, transparent);
250
+ border-radius: 999px;
251
+ background: var(--guuey-chat-surface);
252
+ color: var(--guuey-chat-ink-muted);
253
+ font-size: 0.85em;
254
+ line-height: 1.2;
255
+ }
256
+ .guuey-chat-view-ref-button {
257
+ cursor: pointer;
258
+ font: inherit;
259
+ font-size: 0.85em;
260
+ }
261
+ .guuey-chat-view-ref-button:hover {
262
+ color: var(--guuey-chat-ink);
263
+ border-color: color-mix(in srgb, var(--guuey-chat-ink) 24%, transparent);
264
+ }
244
265
 
245
266
  /* ── R7 media ── */
246
267
  .guuey-chat-media-image img {