@classic-homes/agent-chat 0.11.0 → 0.13.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 (117) hide show
  1. package/README.md +67 -2
  2. package/dist/components/AgentChat.svelte +60 -25
  3. package/dist/components/AgentChat.svelte.d.ts +11 -1
  4. package/dist/components/AgentChat.svelte.d.ts.map +1 -1
  5. package/dist/components/ArtifactPanel.svelte +4 -2
  6. package/dist/components/AssistantMessage.svelte +58 -16
  7. package/dist/components/AssistantMessage.svelte.d.ts +2 -0
  8. package/dist/components/AssistantMessage.svelte.d.ts.map +1 -1
  9. package/dist/components/ChatHeader.svelte +4 -1
  10. package/dist/components/ChatHeader.svelte.d.ts +2 -0
  11. package/dist/components/ChatHeader.svelte.d.ts.map +1 -1
  12. package/dist/components/ChatLauncher.svelte +175 -0
  13. package/dist/components/ChatLauncher.svelte.d.ts +26 -0
  14. package/dist/components/ChatLauncher.svelte.d.ts.map +1 -0
  15. package/dist/components/Composer.svelte +7 -3
  16. package/dist/components/Composer.svelte.d.ts.map +1 -1
  17. package/dist/components/FloatingWindow.svelte +280 -0
  18. package/dist/components/FloatingWindow.svelte.d.ts +35 -0
  19. package/dist/components/FloatingWindow.svelte.d.ts.map +1 -0
  20. package/dist/components/Markdown.svelte +4 -0
  21. package/dist/components/Markdown.svelte.d.ts.map +1 -1
  22. package/dist/components/MessageFeedback.svelte +11 -4
  23. package/dist/components/MessageFeedback.svelte.d.ts.map +1 -1
  24. package/dist/components/MessageFiles.svelte +133 -40
  25. package/dist/components/MessageFiles.svelte.d.ts +6 -0
  26. package/dist/components/MessageFiles.svelte.d.ts.map +1 -1
  27. package/dist/components/MessageItem.svelte +2 -0
  28. package/dist/components/MessageItem.svelte.d.ts +2 -0
  29. package/dist/components/MessageItem.svelte.d.ts.map +1 -1
  30. package/dist/components/MessageList.svelte +40 -7
  31. package/dist/components/MessageList.svelte.d.ts +3 -1
  32. package/dist/components/MessageList.svelte.d.ts.map +1 -1
  33. package/dist/components/ShortcutsDialog.svelte +10 -3
  34. package/dist/components/ShortcutsDialog.svelte.d.ts +2 -0
  35. package/dist/components/ShortcutsDialog.svelte.d.ts.map +1 -1
  36. package/dist/components/UiFrame.svelte +12 -4
  37. package/dist/components/UiFrame.svelte.d.ts.map +1 -1
  38. package/dist/components/UserMessage.svelte +10 -1
  39. package/dist/components/UserMessage.svelte.d.ts.map +1 -1
  40. package/dist/index.d.ts +5 -0
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +5 -0
  43. package/dist/markdown.d.ts.map +1 -1
  44. package/dist/markdown.js +94 -61
  45. package/dist/reducer.d.ts +11 -0
  46. package/dist/reducer.d.ts.map +1 -1
  47. package/dist/reducer.js +18 -2
  48. package/dist/session.svelte.d.ts +40 -0
  49. package/dist/session.svelte.d.ts.map +1 -1
  50. package/dist/session.svelte.js +178 -23
  51. package/dist/shortcuts.d.ts +7 -0
  52. package/dist/shortcuts.d.ts.map +1 -1
  53. package/dist/shortcuts.js +9 -0
  54. package/dist/surface-geometry.d.ts +60 -0
  55. package/dist/surface-geometry.d.ts.map +1 -0
  56. package/dist/surface-geometry.js +112 -0
  57. package/dist/surface.svelte.d.ts +79 -0
  58. package/dist/surface.svelte.d.ts.map +1 -0
  59. package/dist/surface.svelte.js +178 -0
  60. package/dist/thinking.d.ts +10 -0
  61. package/dist/thinking.d.ts.map +1 -0
  62. package/dist/thinking.js +61 -0
  63. package/dist/ui-frame-protocol.d.ts +6 -0
  64. package/dist/ui-frame-protocol.d.ts.map +1 -1
  65. package/dist/ui-frame-protocol.js +11 -0
  66. package/package.json +8 -7
  67. package/dist/artifact-pages.test.d.ts +0 -2
  68. package/dist/artifact-pages.test.d.ts.map +0 -1
  69. package/dist/artifact-pages.test.js +0 -102
  70. package/dist/components/a11y.svelte.test.d.ts +0 -2
  71. package/dist/components/a11y.svelte.test.d.ts.map +0 -1
  72. package/dist/components/a11y.svelte.test.js +0 -183
  73. package/dist/components/agent-picker.svelte.test.d.ts +0 -2
  74. package/dist/components/agent-picker.svelte.test.d.ts.map +0 -1
  75. package/dist/components/agent-picker.svelte.test.js +0 -84
  76. package/dist/components/composer.svelte.test.d.ts +0 -2
  77. package/dist/components/composer.svelte.test.d.ts.map +0 -1
  78. package/dist/components/composer.svelte.test.js +0 -162
  79. package/dist/components/continue.svelte.test.d.ts +0 -2
  80. package/dist/components/continue.svelte.test.d.ts.map +0 -1
  81. package/dist/components/continue.svelte.test.js +0 -109
  82. package/dist/components/conversation-chrome.svelte.test.d.ts +0 -2
  83. package/dist/components/conversation-chrome.svelte.test.d.ts.map +0 -1
  84. package/dist/components/conversation-chrome.svelte.test.js +0 -147
  85. package/dist/components/feedback.svelte.test.d.ts +0 -2
  86. package/dist/components/feedback.svelte.test.d.ts.map +0 -1
  87. package/dist/components/feedback.svelte.test.js +0 -99
  88. package/dist/components/live-fixes.svelte.test.d.ts +0 -2
  89. package/dist/components/live-fixes.svelte.test.d.ts.map +0 -1
  90. package/dist/components/live-fixes.svelte.test.js +0 -127
  91. package/dist/components/markdown-prose.svelte.test.d.ts +0 -2
  92. package/dist/components/markdown-prose.svelte.test.d.ts.map +0 -1
  93. package/dist/components/markdown-prose.svelte.test.js +0 -26
  94. package/dist/components/messages.svelte.test.d.ts +0 -2
  95. package/dist/components/messages.svelte.test.d.ts.map +0 -1
  96. package/dist/components/messages.svelte.test.js +0 -215
  97. package/dist/components/regenerate.svelte.test.d.ts +0 -2
  98. package/dist/components/regenerate.svelte.test.d.ts.map +0 -1
  99. package/dist/components/regenerate.svelte.test.js +0 -108
  100. package/dist/components/welcome.svelte.test.d.ts +0 -2
  101. package/dist/components/welcome.svelte.test.d.ts.map +0 -1
  102. package/dist/components/welcome.svelte.test.js +0 -119
  103. package/dist/composer-keys.test.d.ts +0 -2
  104. package/dist/composer-keys.test.d.ts.map +0 -1
  105. package/dist/composer-keys.test.js +0 -16
  106. package/dist/markdown.test.d.ts +0 -2
  107. package/dist/markdown.test.d.ts.map +0 -1
  108. package/dist/markdown.test.js +0 -35
  109. package/dist/reducer.test.d.ts +0 -2
  110. package/dist/reducer.test.d.ts.map +0 -1
  111. package/dist/reducer.test.js +0 -153
  112. package/dist/ui-frame-protocol.test.d.ts +0 -2
  113. package/dist/ui-frame-protocol.test.d.ts.map +0 -1
  114. package/dist/ui-frame-protocol.test.js +0 -48
  115. package/dist/ui-frame-relay.test.d.ts +0 -2
  116. package/dist/ui-frame-relay.test.d.ts.map +0 -1
  117. package/dist/ui-frame-relay.test.js +0 -36
@@ -2,55 +2,150 @@
2
2
  @component
3
3
  Files the agent produced in a turn: images as thumbnails that open in a lightbox, everything
4
4
  else as a download card with a type icon and size.
5
+
6
+ The file endpoint needs the bearer, which `<img src>` and download links cannot send. With
7
+ `loadFile` (e.g. the client's `fetchFile`) files are fetched with it and shown from blob URLs;
8
+ without it they link to `fileUrl` (cookie-authenticated hosts).
5
9
  -->
6
10
  <script lang="ts">
7
11
  import { cn, Icon, Lightbox } from '@classic-homes/theme-svelte';
12
+ import { SvelteMap } from 'svelte/reactivity';
8
13
  import type { FileState } from '../reducer.js';
9
14
  import { fileIcon, formatBytes } from '../message-format.js';
10
15
 
11
16
  interface Props {
12
17
  files: FileState[];
13
18
  fileUrl: (fileId: string) => string;
19
+ /** Fetch a file with the host's credentials; its blob is shown and downloaded. */
20
+ loadFile?: (fileId: string) => Promise<Blob>;
14
21
  class?: string;
15
22
  }
16
- let { files, fileUrl, class: className }: Props = $props();
23
+ let { files, fileUrl, loadFile, class: className }: Props = $props();
24
+
25
+ type Loaded = { state: 'loading' } | { state: 'ready'; url: string } | { state: 'error' };
26
+ const loaded = new SvelteMap<string, Loaded>();
27
+ let destroyed = false;
28
+
29
+ function load(fileId: string): Promise<string | undefined> {
30
+ const known = loaded.get(fileId);
31
+ if (known?.state === 'ready') return Promise.resolve(known.url);
32
+ if (!loadFile) return Promise.resolve(undefined);
33
+ loaded.set(fileId, { state: 'loading' });
34
+ return loadFile(fileId).then(
35
+ (blob) => {
36
+ if (destroyed) return undefined;
37
+ const url = URL.createObjectURL(blob);
38
+ loaded.set(fileId, { state: 'ready', url });
39
+ return url;
40
+ },
41
+ () => {
42
+ if (!destroyed) loaded.set(fileId, { state: 'error' });
43
+ return undefined;
44
+ },
45
+ );
46
+ }
17
47
 
18
48
  const images = $derived(files.filter((f) => f.mimeType.startsWith('image/')));
19
49
  const others = $derived(files.filter((f) => !f.mimeType.startsWith('image/')));
50
+
51
+ // Thumbnails load at once; other files when they are downloaded.
52
+ $effect(() => {
53
+ if (!loadFile) return;
54
+ for (const file of images) if (!loaded.has(file.fileId)) void load(file.fileId);
55
+ });
56
+ $effect(() => () => {
57
+ destroyed = true;
58
+ for (const entry of loaded.values())
59
+ if (entry.state === 'ready') URL.revokeObjectURL(entry.url);
60
+ });
61
+
62
+ /** Where an image shows from: its blob once loaded, nothing while loading, else `fileUrl`. */
63
+ function srcFor(fileId: string): string | undefined {
64
+ if (!loadFile) return fileUrl(fileId);
65
+ const entry = loaded.get(fileId);
66
+ return entry?.state === 'ready' ? entry.url : undefined;
67
+ }
20
68
  const items = $derived(
21
- images.map((f) => ({
22
- id: f.fileId,
23
- kind: 'image' as const,
24
- src: fileUrl(f.fileId),
25
- alt: f.name,
26
- title: f.name,
27
- })),
69
+ images.flatMap((f) => {
70
+ const src = srcFor(f.fileId);
71
+ return src ? [{ id: f.fileId, kind: 'image' as const, src, alt: f.name, title: f.name }] : [];
72
+ }),
28
73
  );
29
74
  let open = $state(false);
30
75
  let index = $state(0);
76
+
77
+ async function download(file: FileState): Promise<void> {
78
+ const url = await load(file.fileId);
79
+ if (!url) return;
80
+ const a = document.createElement('a');
81
+ a.href = url;
82
+ a.download = file.name;
83
+ a.click();
84
+ }
85
+ const CARD =
86
+ 'flex max-w-xs items-center gap-3 rounded-lg border border-border bg-background px-3 py-2 text-left text-sm shadow-sm transition hover:border-primary/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring';
31
87
  </script>
32
88
 
89
+ {#snippet card(file: FileState)}
90
+ <span
91
+ class="flex h-9 w-9 shrink-0 items-center justify-center rounded-md bg-muted text-muted-foreground"
92
+ >
93
+ <Icon name={fileIcon(file.mimeType)} size={18} />
94
+ </span>
95
+ <span class="min-w-0 flex-1">
96
+ <span class="block truncate font-medium text-foreground">{file.name}</span>
97
+ <span class="block text-xs text-muted-foreground">
98
+ {#if loaded.get(file.fileId)?.state === 'error'}
99
+ Could not download; try again
100
+ {:else if loaded.get(file.fileId)?.state === 'loading'}
101
+ Downloading…
102
+ {:else}
103
+ {formatBytes(file.bytes)}
104
+ {/if}
105
+ </span>
106
+ </span>
107
+ <Icon name="download" size={16} class="text-muted-foreground" />
108
+ {/snippet}
109
+
33
110
  <div class={cn('flex flex-col gap-2', className)}>
34
111
  {#if images.length}
35
112
  <ul class="flex flex-wrap gap-2" aria-label="Images">
36
- {#each images as file, i (file.fileId)}
113
+ {#each images as file (file.fileId)}
114
+ {@const src = srcFor(file.fileId)}
115
+ {@const state = loadFile ? loaded.get(file.fileId)?.state : 'ready'}
37
116
  <li>
38
- <button
39
- type="button"
40
- class="block overflow-hidden rounded-lg border border-border focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
41
- aria-label={`View ${file.name}`}
42
- onclick={() => {
43
- index = i;
44
- open = true;
45
- }}
46
- >
47
- <img
48
- class="block h-40 max-w-xs object-cover"
49
- src={fileUrl(file.fileId)}
50
- alt={file.name}
51
- loading="lazy"
52
- />
53
- </button>
117
+ {#if src}
118
+ <button
119
+ type="button"
120
+ class="block overflow-hidden rounded-lg border border-border focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
121
+ aria-label={`View ${file.name}`}
122
+ onclick={() => {
123
+ index = Math.max(
124
+ 0,
125
+ items.findIndex((item) => item.id === file.fileId),
126
+ );
127
+ open = true;
128
+ }}
129
+ >
130
+ <img class="block h-40 max-w-xs object-cover" {src} alt={file.name} loading="lazy" />
131
+ </button>
132
+ {:else if state === 'error'}
133
+ <button
134
+ type="button"
135
+ class="flex h-40 w-40 flex-col items-center justify-center gap-1 rounded-lg border border-border bg-muted p-2 text-center text-xs text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
136
+ aria-label={`Could not load ${file.name}; try again`}
137
+ onclick={() => void load(file.fileId)}
138
+ >
139
+ <Icon name="refresh" size={16} />
140
+ <span class="line-clamp-2 break-all">{file.name}</span>
141
+ </button>
142
+ {:else}
143
+ <div
144
+ class="h-40 w-40 animate-pulse rounded-lg border border-border bg-muted"
145
+ role="img"
146
+ aria-label={`Loading ${file.name}`}
147
+ ></div>
148
+ {/if}
54
149
  </li>
55
150
  {/each}
56
151
  </ul>
@@ -60,22 +155,20 @@
60
155
  <ul class="flex flex-wrap gap-2" aria-label="Files">
61
156
  {#each others as file (file.fileId)}
62
157
  <li>
63
- <a
64
- class="flex max-w-xs items-center gap-3 rounded-lg border border-border bg-background px-3 py-2 text-sm shadow-sm transition hover:border-primary/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
65
- href={fileUrl(file.fileId)}
66
- download={file.name}
67
- >
68
- <span
69
- class="flex h-9 w-9 shrink-0 items-center justify-center rounded-md bg-muted text-muted-foreground"
158
+ {#if loadFile}
159
+ <button
160
+ type="button"
161
+ class={CARD}
162
+ aria-label={`Download ${file.name}`}
163
+ onclick={() => void download(file)}
70
164
  >
71
- <Icon name={fileIcon(file.mimeType)} size={18} />
72
- </span>
73
- <span class="min-w-0 flex-1">
74
- <span class="block truncate font-medium text-foreground">{file.name}</span>
75
- <span class="block text-xs text-muted-foreground">{formatBytes(file.bytes)}</span>
76
- </span>
77
- <Icon name="download" size={16} class="text-muted-foreground" />
78
- </a>
165
+ {@render card(file)}
166
+ </button>
167
+ {:else}
168
+ <a class={CARD} href={fileUrl(file.fileId)} download={file.name}>
169
+ {@render card(file)}
170
+ </a>
171
+ {/if}
79
172
  </li>
80
173
  {/each}
81
174
  </ul>
@@ -2,11 +2,17 @@ import type { FileState } from '../reducer.js';
2
2
  interface Props {
3
3
  files: FileState[];
4
4
  fileUrl: (fileId: string) => string;
5
+ /** Fetch a file with the host's credentials; its blob is shown and downloaded. */
6
+ loadFile?: (fileId: string) => Promise<Blob>;
5
7
  class?: string;
6
8
  }
7
9
  /**
8
10
  * Files the agent produced in a turn: images as thumbnails that open in a lightbox, everything
9
11
  * else as a download card with a type icon and size.
12
+ *
13
+ * The file endpoint needs the bearer, which `<img src>` and download links cannot send. With
14
+ * `loadFile` (e.g. the client's `fetchFile`) files are fetched with it and shown from blob URLs;
15
+ * without it they link to `fileUrl` (cookie-authenticated hosts).
10
16
  */
11
17
  declare const MessageFiles: import("svelte").Component<Props, {}, "">;
12
18
  type MessageFiles = ReturnType<typeof MessageFiles>;
@@ -1 +1 @@
1
- {"version":3,"file":"MessageFiles.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/MessageFiles.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAI7C,UAAU,KAAK;IACb,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA8DH;;;GAGG;AACH,QAAA,MAAM,YAAY,2CAAwC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"MessageFiles.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/MessageFiles.svelte.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAI7C,UAAU,KAAK;IACb,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC;IACpC,kFAAkF;IAClF,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA6IH;;;;;;;GAOG;AACH,QAAA,MAAM,YAAY,2CAAwC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}
@@ -14,6 +14,8 @@
14
14
  last?: boolean;
15
15
  sandboxOrigin: string;
16
16
  fileUrl: (fileId: string) => string;
17
+ /** Fetch a file with the host's credentials (blob URLs); without it files link to `fileUrl`. */
18
+ loadFile?: (fileId: string) => Promise<Blob>;
17
19
  toolLabels?: Record<string, string>;
18
20
  onnavigate?: (href: string) => void;
19
21
  onopenartifact?: (artifactId: string) => void;
@@ -6,6 +6,8 @@ interface Props {
6
6
  last?: boolean;
7
7
  sandboxOrigin: string;
8
8
  fileUrl: (fileId: string) => string;
9
+ /** Fetch a file with the host's credentials (blob URLs); without it files link to `fileUrl`. */
10
+ loadFile?: (fileId: string) => Promise<Blob>;
9
11
  toolLabels?: Record<string, string>;
10
12
  onnavigate?: (href: string) => void;
11
13
  onopenartifact?: (artifactId: string) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"MessageItem.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/MessageItem.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAK/C,UAAU,KAAK;IACb,OAAO,EAAE,WAAW,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,cAAc,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACtE,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/E,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,2CAA2C;IAC3C,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC;AAmBH,sEAAsE;AACtE,QAAA,MAAM,WAAW,2CAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"MessageItem.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/MessageItem.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAK/C,UAAU,KAAK;IACb,OAAO,EAAE,WAAW,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC;IACpC,gGAAgG;IAChG,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,cAAc,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACtE,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/E,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,2CAA2C;IAC3C,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC;AAmBH,sEAAsE;AACtE,QAAA,MAAM,WAAW,2CAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
@@ -2,7 +2,7 @@
2
2
  import { tick } from 'svelte';
3
3
  import { Button, Icon } from '@classic-homes/theme-svelte';
4
4
  import type { TurnRating } from '@classic-homes/agent-contracts';
5
- import type { ChatMessage } from '../reducer.js';
5
+ import { errorTitle, type ChatMessage } from '../reducer.js';
6
6
  import { daySeparators, formatDay } from '../message-format.js';
7
7
  import MessageItem from './MessageItem.svelte';
8
8
 
@@ -11,6 +11,8 @@
11
11
  streaming: boolean;
12
12
  sandboxOrigin: string;
13
13
  fileUrl: (fileId: string) => string;
14
+ /** Fetch a file with the host's credentials (blob URLs); without it files link to `fileUrl`. */
15
+ loadFile?: (fileId: string) => Promise<Blob>;
14
16
  toolLabels?: Record<string, string>;
15
17
  onnavigate?: (href: string) => void;
16
18
  onopenartifact?: (artifactId: string) => void;
@@ -36,6 +38,7 @@
36
38
  streaming,
37
39
  sandboxOrigin,
38
40
  fileUrl,
41
+ loadFile,
39
42
  toolLabels,
40
43
  onnavigate,
41
44
  onopenartifact,
@@ -58,6 +61,7 @@
58
61
  });
59
62
 
60
63
  let container: HTMLDivElement | undefined = $state();
64
+ let transcript: HTMLDivElement | undefined = $state();
61
65
  /** Pinned to the bottom: new content scrolls into view. Off once the reader scrolls up. */
62
66
  let follow = $state(true);
63
67
  /** Content arrived while the reader was scrolled up. */
@@ -113,16 +117,43 @@
113
117
  });
114
118
  });
115
119
 
120
+ // The answer's markdown lands in the DOM after the throttled parse (and images, frames and
121
+ // code headers grow it later still): keep pinned to the bottom whenever the transcript grows.
122
+ $effect(() => {
123
+ if (!transcript || typeof ResizeObserver !== 'function') return;
124
+ const observer = new ResizeObserver(() => {
125
+ if (container && follow) container.scrollTop = container.scrollHeight;
126
+ });
127
+ observer.observe(transcript);
128
+ return () => observer.disconnect();
129
+ });
130
+
116
131
  const RENDER_TAIL = 6;
117
132
  const separators = $derived(daySeparators(messages));
118
133
  // Only show day labels when the transcript spans more than one day.
119
134
  const multiDay = $derived(separators.size > 1);
120
135
 
121
- // Announce the finished answer once, not every token.
122
- const announcement = $derived.by(() => {
123
- if (streaming) return '';
124
- const last = messages[messages.length - 1];
125
- return last?.role === 'assistant' ? last.text : '';
136
+ // Announce a short outcome when an answer stops streaming (never the answer itself, which a
137
+ // screen reader reads from the transcript, and nothing on load).
138
+ let announcement = $state('');
139
+ let wasStreaming = false;
140
+ $effect(() => {
141
+ const now = streaming;
142
+ if (now) announcement = '';
143
+ else if (wasStreaming) {
144
+ const last = messages[messages.length - 1];
145
+ announcement =
146
+ last?.role !== 'assistant'
147
+ ? ''
148
+ : last.error
149
+ ? errorTitle(last.error.code)
150
+ : last.status === 'cancelled'
151
+ ? 'Stopped'
152
+ : last.status === 'incomplete'
153
+ ? 'Answer cut short'
154
+ : 'Answer ready';
155
+ }
156
+ wasStreaming = now;
126
157
  });
127
158
  </script>
128
159
 
@@ -133,12 +164,13 @@
133
164
  bind:this={container}
134
165
  {onscroll}
135
166
  role="log"
167
+ aria-live="off"
136
168
  aria-label="Conversation"
137
169
  >
138
170
  {#if messages.length === 0}
139
171
  {#if empty}{@render empty()}{/if}
140
172
  {:else}
141
- <div class="mx-auto flex w-full max-w-3xl flex-col">
173
+ <div class="mx-auto flex w-full max-w-3xl flex-col" bind:this={transcript}>
142
174
  {#each messages as message, i (message.id)}
143
175
  {#if multiDay && separators.has(i)}
144
176
  <div
@@ -164,6 +196,7 @@
164
196
  streaming={streaming && i === messages.length - 1 && message.role === 'assistant'}
165
197
  {sandboxOrigin}
166
198
  {fileUrl}
199
+ {loadFile}
167
200
  {toolLabels}
168
201
  {onnavigate}
169
202
  {onopenartifact}
@@ -1,10 +1,12 @@
1
1
  import type { TurnRating } from '@classic-homes/agent-contracts';
2
- import type { ChatMessage } from '../reducer.js';
2
+ import { type ChatMessage } from '../reducer.js';
3
3
  interface Props {
4
4
  messages: ChatMessage[];
5
5
  streaming: boolean;
6
6
  sandboxOrigin: string;
7
7
  fileUrl: (fileId: string) => string;
8
+ /** Fetch a file with the host's credentials (blob URLs); without it files link to `fileUrl`. */
9
+ loadFile?: (fileId: string) => Promise<Blob>;
8
10
  toolLabels?: Record<string, string>;
9
11
  onnavigate?: (href: string) => void;
10
12
  onopenartifact?: (artifactId: string) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"MessageList.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/MessageList.svelte.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAK/C,UAAU,KAAK;IACb,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,cAAc,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACtE,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,uDAAuD;IACvD,YAAY,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,yCAAyC;IACzC,MAAM,CAAC,EAAE,CACP,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,UAAU,GAAG,IAAI,EACzB,OAAO,CAAC,EAAE,MAAM,KACb,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,mDAAmD;IACnD,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACnD,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,KAAK,CAAC,EAAE,OAAO,QAAQ,EAAE,OAAO,CAAC;CAClC;AAwJH,QAAA,MAAM,WAAW,2CAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"MessageList.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/MessageList.svelte.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAc,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAK3D,UAAU,KAAK;IACb,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC;IACpC,gGAAgG;IAChG,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,cAAc,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACtE,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,uDAAuD;IACvD,YAAY,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,yCAAyC;IACzC,MAAM,CAAC,EAAE,CACP,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,UAAU,GAAG,IAAI,EACzB,OAAO,CAAC,EAAE,MAAM,KACb,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,mDAAmD;IACnD,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACnD,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,KAAK,CAAC,EAAE,OAAO,QAAQ,EAAE,OAAO,CAAC;CAClC;AAqLH,QAAA,MAAM,WAAW,2CAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
@@ -6,20 +6,27 @@
6
6
  <script lang="ts">
7
7
  import { Dialog, Kbd } from '@classic-homes/theme-svelte';
8
8
  import { releaseStuckBodyLock } from '../body-lock.js';
9
- import { CHAT_SHORTCUTS, type ChatShortcut } from '../shortcuts.js';
9
+ import { chatShortcuts, type ChatShortcut } from '../shortcuts.js';
10
10
 
11
11
  interface Props {
12
12
  open?: boolean;
13
13
  /** Host shortcuts, e.g. opening the agent panel or starting a new chat. */
14
14
  shortcuts?: ChatShortcut[];
15
15
  returnFocus?: HTMLElement | null;
16
+ /** False when the chat has no saved prompts: the `/` entry is left out. Default true. */
17
+ savedPrompts?: boolean;
16
18
  }
17
- let { open = $bindable(false), shortcuts = [], returnFocus = null }: Props = $props();
19
+ let {
20
+ open = $bindable(false),
21
+ shortcuts = [],
22
+ returnFocus = null,
23
+ savedPrompts = true,
24
+ }: Props = $props();
18
25
 
19
26
  const groups = $derived(
20
27
  [
21
28
  { title: 'App', items: shortcuts },
22
- { title: 'Chat', items: [...CHAT_SHORTCUTS] },
29
+ { title: 'Chat', items: chatShortcuts({ savedPrompts }) },
23
30
  ].filter((g) => g.items.length),
24
31
  );
25
32
  </script>
@@ -4,6 +4,8 @@ interface Props {
4
4
  /** Host shortcuts, e.g. opening the agent panel or starting a new chat. */
5
5
  shortcuts?: ChatShortcut[];
6
6
  returnFocus?: HTMLElement | null;
7
+ /** False when the chat has no saved prompts: the `/` entry is left out. Default true. */
8
+ savedPrompts?: boolean;
7
9
  }
8
10
  /**
9
11
  * Lists the chat's keyboard shortcuts (`CHAT_SHORTCUTS`) and the host's own (`shortcuts`, shown
@@ -1 +1 @@
1
- {"version":3,"file":"ShortcutsDialog.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/ShortcutsDialog.svelte.ts"],"names":[],"mappings":"AAKA,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAGlE,UAAU,KAAK;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,2EAA2E;IAC3E,SAAS,CAAC,EAAE,YAAY,EAAE,CAAC;IAC3B,WAAW,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;CAClC;AA6CH;;;GAGG;AACH,QAAA,MAAM,eAAe,+CAAwC,CAAC;AAC9D,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;AAC1D,eAAe,eAAe,CAAC"}
1
+ {"version":3,"file":"ShortcutsDialog.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/ShortcutsDialog.svelte.ts"],"names":[],"mappings":"AAKA,OAAO,EAAiB,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAGjE,UAAU,KAAK;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,2EAA2E;IAC3E,SAAS,CAAC,EAAE,YAAY,EAAE,CAAC;IAC3B,WAAW,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IACjC,yFAAyF;IACzF,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAkDH;;;GAGG;AACH,QAAA,MAAM,eAAe,+CAAwC,CAAC;AAC9D,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;AAC1D,eAAe,eAAe,CAAC"}
@@ -1,7 +1,12 @@
1
1
  <script lang="ts">
2
2
  import SandboxFrame from './SandboxFrame.svelte';
3
3
  import type { UiResourceState } from '../reducer.js';
4
- import { MIN_FRAME_HEIGHT, composerTextFor, type FrameAction } from '../ui-frame-protocol.js';
4
+ import {
5
+ MIN_FRAME_HEIGHT,
6
+ composerTextFor,
7
+ initialFrameHeight,
8
+ type FrameAction,
9
+ } from '../ui-frame-protocol.js';
5
10
 
6
11
  interface Props {
7
12
  resource: UiResourceState;
@@ -14,7 +19,7 @@
14
19
  let { resource, sandboxOrigin, onprompt, ontool, onnotify }: Props = $props();
15
20
 
16
21
  let height = $state(MIN_FRAME_HEIGHT);
17
- const initialHeight = $derived(resource.preferredFrameSize?.[1] ?? `${MIN_FRAME_HEIGHT}px`);
22
+ const initialHeight = $derived(initialFrameHeight(resource.preferredFrameSize?.[1]));
18
23
 
19
24
  function handle(action: FrameAction): void {
20
25
  switch (action.type) {
@@ -38,13 +43,16 @@
38
43
  }
39
44
  </script>
40
45
 
41
- <div class="my-2 overflow-hidden rounded-lg border border-border bg-card">
46
+ <div
47
+ class="my-2 overflow-hidden rounded-lg border border-border bg-card"
48
+ style:height={`${height > MIN_FRAME_HEIGHT ? height : initialHeight}px`}
49
+ >
42
50
  <SandboxFrame
43
51
  {sandboxOrigin}
44
52
  html={resource.html}
45
53
  uri={resource.uri}
46
54
  title={resource.uri}
47
- style={`height:${height > MIN_FRAME_HEIGHT ? `${height}px` : initialHeight}`}
55
+ style="height:100%"
48
56
  onaction={handle}
49
57
  />
50
58
  </div>
@@ -1 +1 @@
1
- {"version":3,"file":"UiFrame.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/UiFrame.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAInD,UAAU,KAAK;IACb,QAAQ,EAAE,eAAe,CAAC;IAC1B,gGAAgG;IAChG,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACtE,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACtC;AAuCH,QAAA,MAAM,OAAO,2CAAwC,CAAC;AACtD,KAAK,OAAO,GAAG,UAAU,CAAC,OAAO,OAAO,CAAC,CAAC;AAC1C,eAAe,OAAO,CAAC"}
1
+ {"version":3,"file":"UiFrame.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/UiFrame.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AASnD,UAAU,KAAK;IACb,QAAQ,EAAE,eAAe,CAAC;IAC1B,gGAAgG;IAChG,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACtE,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACtC;AAuCH,QAAA,MAAM,OAAO,2CAAwC,CAAC;AACtD,KAAK,OAAO,GAAG,UAAU,CAAC,OAAO,OAAO,CAAC,CAAC;AAC1C,eAAe,OAAO,CAAC"}
@@ -39,9 +39,18 @@
39
39
  function save(): void {
40
40
  const text = draft.trim();
41
41
  if (!text) return;
42
+ // Unchanged: nothing to send, so leave the editor like Cancel (focus back on Edit).
43
+ if (text === message.text.trim()) {
44
+ void cancel();
45
+ return;
46
+ }
42
47
  editing = false;
43
- if (text !== message.text.trim()) onedit?.(text);
48
+ onedit?.(text);
44
49
  }
50
+ // The question can no longer be edited (a turn started, or it is not the latest any more).
51
+ $effect(() => {
52
+ if (!onedit && editing) editing = false;
53
+ });
45
54
  function onkeydown(event: KeyboardEvent): void {
46
55
  if (event.isComposing || event.keyCode === 229) return;
47
56
  if (event.key === 'Escape') {
@@ -1 +1 @@
1
- {"version":3,"file":"UserMessage.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/UserMessage.svelte.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAK/C,UAAU,KAAK;IACb,OAAO,EAAE,WAAW,CAAC;IACrB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,+DAA+D;IAC/D,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC;AAsFH;;;GAGG;AACH,QAAA,MAAM,WAAW,2CAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"UserMessage.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/UserMessage.svelte.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAK/C,UAAU,KAAK;IACb,OAAO,EAAE,WAAW,CAAC;IACrB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,+DAA+D;IAC/D,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC;AA+FH;;;GAGG;AACH,QAAA,MAAM,WAAW,2CAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
package/dist/index.d.ts CHANGED
@@ -6,6 +6,9 @@ export * from './message-format.js';
6
6
  export * from './reducer.js';
7
7
  export * from './session.svelte.js';
8
8
  export * from './shortcuts.js';
9
+ export * from './surface-geometry.js';
10
+ export * from './surface.svelte.js';
11
+ export * from './thinking.js';
9
12
  export * from './ui-frame-protocol.js';
10
13
  export * from './welcome.js';
11
14
  export { default as AgentChat } from './components/AgentChat.svelte';
@@ -26,4 +29,6 @@ export { default as MessageFiles } from './components/MessageFiles.svelte';
26
29
  export { default as ProposalCard } from './components/ProposalCard.svelte';
27
30
  export { default as Welcome } from './components/Welcome.svelte';
28
31
  export { default as ShortcutsDialog } from './components/ShortcutsDialog.svelte';
32
+ export { default as ChatLauncher } from './components/ChatLauncher.svelte';
33
+ export { default as FloatingWindow } from './components/FloatingWindow.svelte';
29
34
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/lib/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC;AAC7B,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC;AACvC,cAAc,cAAc,CAAC;AAC7B,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAC7E,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,yCAAyC,CAAC;AACzF,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAC3E,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AACnF,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAC/E,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAC3E,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAC3E,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAC3E,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,qCAAqC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/lib/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC;AAC7B,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,eAAe,CAAC;AAC9B,cAAc,wBAAwB,CAAC;AACvC,cAAc,cAAc,CAAC;AAC7B,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAC7E,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,yCAAyC,CAAC;AACzF,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAC3E,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AACnF,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAC/E,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAC3E,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAC3E,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAC3E,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,qCAAqC,CAAC;AACjF,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAC3E,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,oCAAoC,CAAC"}
package/dist/index.js CHANGED
@@ -6,6 +6,9 @@ export * from './message-format.js';
6
6
  export * from './reducer.js';
7
7
  export * from './session.svelte.js';
8
8
  export * from './shortcuts.js';
9
+ export * from './surface-geometry.js';
10
+ export * from './surface.svelte.js';
11
+ export * from './thinking.js';
9
12
  export * from './ui-frame-protocol.js';
10
13
  export * from './welcome.js';
11
14
  export { default as AgentChat } from './components/AgentChat.svelte';
@@ -26,3 +29,5 @@ export { default as MessageFiles } from './components/MessageFiles.svelte';
26
29
  export { default as ProposalCard } from './components/ProposalCard.svelte';
27
30
  export { default as Welcome } from './components/Welcome.svelte';
28
31
  export { default as ShortcutsDialog } from './components/ShortcutsDialog.svelte';
32
+ export { default as ChatLauncher } from './components/ChatLauncher.svelte';
33
+ export { default as FloatingWindow } from './components/FloatingWindow.svelte';
@@ -1 +1 @@
1
- {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../src/lib/markdown.ts"],"names":[],"mappings":"AAkEA,MAAM,WAAW,eAAe;IAC9B,yFAAyF;IACzF,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,uFAAuF;IACvF,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAQD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAK/C;AAED,uFAAuF;AACvF,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAO9C;AAMD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,WAAsB,GAAG,OAAO,CAenF;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,cAAc,qBAAe,GAAG,OAAO,CAOjF;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB,GAAG,MAAM,CAiEjF"}
1
+ {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../src/lib/markdown.ts"],"names":[],"mappings":"AAsGA,MAAM,WAAW,eAAe;IAC9B,yFAAyF;IACzF,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,uFAAuF;IACvF,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AA4BD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAK/C;AAED,uFAAuF;AACvF,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAO9C;AAUD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,WAAsB,GAAG,OAAO,CAcnF;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,cAAc,qBAAe,GAAG,OAAO,CAOjF;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB,GAAG,MAAM,CAwEjF"}