@classic-homes/agent-chat 0.11.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +57 -2
- package/dist/components/AgentChat.svelte +58 -22
- package/dist/components/AgentChat.svelte.d.ts +11 -1
- package/dist/components/AgentChat.svelte.d.ts.map +1 -1
- package/dist/components/ArtifactPanel.svelte +4 -2
- package/dist/components/AssistantMessage.svelte +14 -5
- package/dist/components/AssistantMessage.svelte.d.ts +2 -0
- package/dist/components/AssistantMessage.svelte.d.ts.map +1 -1
- package/dist/components/ChatHeader.svelte +4 -1
- package/dist/components/ChatHeader.svelte.d.ts +2 -0
- package/dist/components/ChatHeader.svelte.d.ts.map +1 -1
- package/dist/components/ChatLauncher.svelte +157 -0
- package/dist/components/ChatLauncher.svelte.d.ts +23 -0
- package/dist/components/ChatLauncher.svelte.d.ts.map +1 -0
- package/dist/components/Composer.svelte +7 -3
- package/dist/components/Composer.svelte.d.ts.map +1 -1
- package/dist/components/FloatingWindow.svelte +239 -0
- package/dist/components/FloatingWindow.svelte.d.ts +26 -0
- package/dist/components/FloatingWindow.svelte.d.ts.map +1 -0
- package/dist/components/Markdown.svelte +4 -0
- package/dist/components/Markdown.svelte.d.ts.map +1 -1
- package/dist/components/MessageFeedback.svelte +11 -4
- package/dist/components/MessageFeedback.svelte.d.ts.map +1 -1
- package/dist/components/MessageFiles.svelte +133 -40
- package/dist/components/MessageFiles.svelte.d.ts +6 -0
- package/dist/components/MessageFiles.svelte.d.ts.map +1 -1
- package/dist/components/MessageItem.svelte +2 -0
- package/dist/components/MessageItem.svelte.d.ts +2 -0
- package/dist/components/MessageItem.svelte.d.ts.map +1 -1
- package/dist/components/MessageList.svelte +40 -7
- package/dist/components/MessageList.svelte.d.ts +3 -1
- package/dist/components/MessageList.svelte.d.ts.map +1 -1
- package/dist/components/ShortcutsDialog.svelte +10 -3
- package/dist/components/ShortcutsDialog.svelte.d.ts +2 -0
- package/dist/components/ShortcutsDialog.svelte.d.ts.map +1 -1
- package/dist/components/UiFrame.svelte +12 -4
- package/dist/components/UiFrame.svelte.d.ts.map +1 -1
- package/dist/components/UserMessage.svelte +10 -1
- package/dist/components/UserMessage.svelte.d.ts.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/markdown.d.ts.map +1 -1
- package/dist/markdown.js +94 -61
- package/dist/reducer.d.ts +11 -0
- package/dist/reducer.d.ts.map +1 -1
- package/dist/reducer.js +18 -2
- package/dist/session.svelte.d.ts +38 -0
- package/dist/session.svelte.d.ts.map +1 -1
- package/dist/session.svelte.js +176 -23
- package/dist/shortcuts.d.ts +7 -0
- package/dist/shortcuts.d.ts.map +1 -1
- package/dist/shortcuts.js +9 -0
- package/dist/surface-geometry.d.ts +56 -0
- package/dist/surface-geometry.d.ts.map +1 -0
- package/dist/surface-geometry.js +99 -0
- package/dist/surface.svelte.d.ts +69 -0
- package/dist/surface.svelte.d.ts.map +1 -0
- package/dist/surface.svelte.js +156 -0
- package/dist/ui-frame-protocol.d.ts +6 -0
- package/dist/ui-frame-protocol.d.ts.map +1 -1
- package/dist/ui-frame-protocol.js +11 -0
- package/package.json +8 -7
- package/dist/artifact-pages.test.d.ts +0 -2
- package/dist/artifact-pages.test.d.ts.map +0 -1
- package/dist/artifact-pages.test.js +0 -102
- package/dist/components/a11y.svelte.test.d.ts +0 -2
- package/dist/components/a11y.svelte.test.d.ts.map +0 -1
- package/dist/components/a11y.svelte.test.js +0 -183
- package/dist/components/agent-picker.svelte.test.d.ts +0 -2
- package/dist/components/agent-picker.svelte.test.d.ts.map +0 -1
- package/dist/components/agent-picker.svelte.test.js +0 -84
- package/dist/components/composer.svelte.test.d.ts +0 -2
- package/dist/components/composer.svelte.test.d.ts.map +0 -1
- package/dist/components/composer.svelte.test.js +0 -162
- package/dist/components/continue.svelte.test.d.ts +0 -2
- package/dist/components/continue.svelte.test.d.ts.map +0 -1
- package/dist/components/continue.svelte.test.js +0 -109
- package/dist/components/conversation-chrome.svelte.test.d.ts +0 -2
- package/dist/components/conversation-chrome.svelte.test.d.ts.map +0 -1
- package/dist/components/conversation-chrome.svelte.test.js +0 -147
- package/dist/components/feedback.svelte.test.d.ts +0 -2
- package/dist/components/feedback.svelte.test.d.ts.map +0 -1
- package/dist/components/feedback.svelte.test.js +0 -99
- package/dist/components/live-fixes.svelte.test.d.ts +0 -2
- package/dist/components/live-fixes.svelte.test.d.ts.map +0 -1
- package/dist/components/live-fixes.svelte.test.js +0 -127
- package/dist/components/markdown-prose.svelte.test.d.ts +0 -2
- package/dist/components/markdown-prose.svelte.test.d.ts.map +0 -1
- package/dist/components/markdown-prose.svelte.test.js +0 -26
- package/dist/components/messages.svelte.test.d.ts +0 -2
- package/dist/components/messages.svelte.test.d.ts.map +0 -1
- package/dist/components/messages.svelte.test.js +0 -215
- package/dist/components/regenerate.svelte.test.d.ts +0 -2
- package/dist/components/regenerate.svelte.test.d.ts.map +0 -1
- package/dist/components/regenerate.svelte.test.js +0 -108
- package/dist/components/welcome.svelte.test.d.ts +0 -2
- package/dist/components/welcome.svelte.test.d.ts.map +0 -1
- package/dist/components/welcome.svelte.test.js +0 -119
- package/dist/composer-keys.test.d.ts +0 -2
- package/dist/composer-keys.test.d.ts.map +0 -1
- package/dist/composer-keys.test.js +0 -16
- package/dist/markdown.test.d.ts +0 -2
- package/dist/markdown.test.d.ts.map +0 -1
- package/dist/markdown.test.js +0 -35
- package/dist/reducer.test.d.ts +0 -2
- package/dist/reducer.test.d.ts.map +0 -1
- package/dist/reducer.test.js +0 -153
- package/dist/ui-frame-protocol.test.d.ts +0 -2
- package/dist/ui-frame-protocol.test.d.ts.map +0 -1
- package/dist/ui-frame-protocol.test.js +0 -48
- package/dist/ui-frame-relay.test.d.ts +0 -2
- package/dist/ui-frame-relay.test.d.ts.map +0 -1
- package/dist/ui-frame-relay.test.js +0 -36
|
@@ -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
|
|
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
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
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
|
|
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,
|
|
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 {
|
|
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 {
|
|
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:
|
|
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,
|
|
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 {
|
|
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]
|
|
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
|
|
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=
|
|
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;
|
|
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
|
-
|
|
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;
|
|
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,8 @@ 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';
|
|
9
11
|
export * from './ui-frame-protocol.js';
|
|
10
12
|
export * from './welcome.js';
|
|
11
13
|
export { default as AgentChat } from './components/AgentChat.svelte';
|
|
@@ -26,4 +28,6 @@ export { default as MessageFiles } from './components/MessageFiles.svelte';
|
|
|
26
28
|
export { default as ProposalCard } from './components/ProposalCard.svelte';
|
|
27
29
|
export { default as Welcome } from './components/Welcome.svelte';
|
|
28
30
|
export { default as ShortcutsDialog } from './components/ShortcutsDialog.svelte';
|
|
31
|
+
export { default as ChatLauncher } from './components/ChatLauncher.svelte';
|
|
32
|
+
export { default as FloatingWindow } from './components/FloatingWindow.svelte';
|
|
29
33
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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,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,8 @@ 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';
|
|
9
11
|
export * from './ui-frame-protocol.js';
|
|
10
12
|
export * from './welcome.js';
|
|
11
13
|
export { default as AgentChat } from './components/AgentChat.svelte';
|
|
@@ -26,3 +28,5 @@ export { default as MessageFiles } from './components/MessageFiles.svelte';
|
|
|
26
28
|
export { default as ProposalCard } from './components/ProposalCard.svelte';
|
|
27
29
|
export { default as Welcome } from './components/Welcome.svelte';
|
|
28
30
|
export { default as ShortcutsDialog } from './components/ShortcutsDialog.svelte';
|
|
31
|
+
export { default as ChatLauncher } from './components/ChatLauncher.svelte';
|
|
32
|
+
export { default as FloatingWindow } from './components/FloatingWindow.svelte';
|
package/dist/markdown.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../src/lib/markdown.ts"],"names":[],"mappings":"
|
|
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"}
|
package/dist/markdown.js
CHANGED
|
@@ -10,6 +10,9 @@
|
|
|
10
10
|
import DOMPurify from 'dompurify';
|
|
11
11
|
const OWN_CLASS_RE = /^agent-[\w-]+( agent-[\w-]+)*$/;
|
|
12
12
|
let hooked = false;
|
|
13
|
+
// Image hosts of the parseMarkdown call currently sanitizing; undefined outside it, so the
|
|
14
|
+
// hooks below never touch other DOMPurify users on the page.
|
|
15
|
+
let activeImageHosts;
|
|
13
16
|
function ensureHook() {
|
|
14
17
|
if (hooked || typeof DOMPurify.addHook !== 'function')
|
|
15
18
|
return;
|
|
@@ -18,6 +21,39 @@ function ensureHook() {
|
|
|
18
21
|
if (data.attrName === 'class' && !OWN_CLASS_RE.test(data.attrValue))
|
|
19
22
|
data.keepAttr = false;
|
|
20
23
|
});
|
|
24
|
+
// Defence in depth: the parser escapes all model text, so these only ever see our own tags.
|
|
25
|
+
DOMPurify.addHook('afterSanitizeAttributes', (node) => {
|
|
26
|
+
if (!activeImageHosts)
|
|
27
|
+
return;
|
|
28
|
+
const el = node;
|
|
29
|
+
if (typeof el.tagName !== 'string')
|
|
30
|
+
return;
|
|
31
|
+
const tag = el.tagName.toLowerCase();
|
|
32
|
+
if (tag === 'input') {
|
|
33
|
+
if ((el.getAttribute('type') ?? '').toLowerCase() !== 'checkbox') {
|
|
34
|
+
el.remove();
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
el.setAttribute('disabled', '');
|
|
38
|
+
}
|
|
39
|
+
if (tag !== 'img')
|
|
40
|
+
el.removeAttribute('src');
|
|
41
|
+
else {
|
|
42
|
+
const src = el.getAttribute('src');
|
|
43
|
+
if (src === null || !isAllowedImageUrl(src, activeImageHosts))
|
|
44
|
+
el.remove();
|
|
45
|
+
}
|
|
46
|
+
if (el.hasAttribute('role') || el.hasAttribute('tabindex')) {
|
|
47
|
+
const region = el.getAttribute('role') === 'region' && el.getAttribute('tabindex') === '0';
|
|
48
|
+
const scroller = (tag === 'div' && el.classList.contains('agent-table-wrap')) || tag === 'pre';
|
|
49
|
+
if (!region || !scroller) {
|
|
50
|
+
el.removeAttribute('role');
|
|
51
|
+
el.removeAttribute('tabindex');
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (el.hasAttribute('aria-label') && tag !== 'input' && tag !== 'div')
|
|
55
|
+
el.removeAttribute('aria-label');
|
|
56
|
+
});
|
|
21
57
|
}
|
|
22
58
|
const DOMPURIFY_CONFIG = {
|
|
23
59
|
ALLOWED_TAGS: [
|
|
@@ -60,12 +96,27 @@ const DOMPURIFY_CONFIG = {
|
|
|
60
96
|
'type',
|
|
61
97
|
'checked',
|
|
62
98
|
'disabled',
|
|
99
|
+
'aria-label',
|
|
100
|
+
'role',
|
|
101
|
+
'tabindex',
|
|
63
102
|
],
|
|
64
103
|
ALLOWED_URI_REGEXP: /^(?:(?:https?|mailto):|[^a-z]|[a-z+.-]+(?:[^a-z+.\-:]|$))/i,
|
|
65
104
|
};
|
|
66
105
|
// Sentinels for the scrolling wrapper around tables (see parseMarkdown).
|
|
67
106
|
const TABLE_OPEN = '\u0000TO\u0000';
|
|
68
107
|
const TABLE_CLOSE = '\u0000TC\u0000';
|
|
108
|
+
const TABLE_WRAP_OPEN = '<div class="agent-table-wrap" tabindex="0" role="region" aria-label="Table">';
|
|
109
|
+
function tagRegistry() {
|
|
110
|
+
const trusted = [];
|
|
111
|
+
return {
|
|
112
|
+
tag: (html) => {
|
|
113
|
+
trusted.push(html);
|
|
114
|
+
return `\u0000T${trusted.length - 1}\u0000`;
|
|
115
|
+
},
|
|
116
|
+
// eslint-disable-next-line no-control-regex -- NUL delimits the sentinels on purpose
|
|
117
|
+
restore: (html) => html.replace(/\u0000T(\d+)\u0000/g, (_, i) => trusted[Number(i)]),
|
|
118
|
+
};
|
|
119
|
+
}
|
|
69
120
|
const DEFAULT_IMAGE_HOSTS = ['classichomes.com', '.classichomes.com'];
|
|
70
121
|
export function escapeHtml(text) {
|
|
71
122
|
return text.replace(/[&<>"']/g, (c) => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' })[c]);
|
|
@@ -83,17 +134,18 @@ export function isSafeUrl(url) {
|
|
|
83
134
|
function pageOrigin() {
|
|
84
135
|
return typeof window !== 'undefined' ? window.location.origin : undefined;
|
|
85
136
|
}
|
|
137
|
+
// Base for resolving relative URLs when there is no page (SSR): only a URL that stays on it is
|
|
138
|
+
// same-origin. `/\\host/x` and `//host/x` resolve to another host and fail the check.
|
|
139
|
+
const NO_PAGE_ORIGIN = 'https://same-origin.invalid';
|
|
86
140
|
export function isAllowedImageUrl(url, hosts = DEFAULT_IMAGE_HOSTS) {
|
|
87
141
|
if (!isSafeUrl(url))
|
|
88
142
|
return false;
|
|
89
|
-
if (url.startsWith('/') && !url.startsWith('//'))
|
|
90
|
-
return true;
|
|
91
143
|
try {
|
|
92
|
-
const origin = pageOrigin();
|
|
93
|
-
const parsed = new URL(url, origin
|
|
144
|
+
const origin = pageOrigin() ?? NO_PAGE_ORIGIN;
|
|
145
|
+
const parsed = new URL(url, origin);
|
|
94
146
|
if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:')
|
|
95
147
|
return false;
|
|
96
|
-
if (
|
|
148
|
+
if (parsed.origin === origin)
|
|
97
149
|
return true;
|
|
98
150
|
const host = parsed.hostname.toLowerCase();
|
|
99
151
|
return hosts.some((h) => h.startsWith('.') ? host.endsWith(h) || host === h.slice(1) : host === h);
|
|
@@ -116,7 +168,10 @@ export function parseMarkdown(text, options = {}) {
|
|
|
116
168
|
ensureHook();
|
|
117
169
|
const CODE = '\u0000CB';
|
|
118
170
|
const INLINE = '\u0000IC';
|
|
119
|
-
|
|
171
|
+
// NUL is reserved for the sentinels below; model text cannot forge one.
|
|
172
|
+
// eslint-disable-next-line no-control-regex -- strips NUL so text cannot forge a sentinel
|
|
173
|
+
let html = text.replace(/\r\n/g, '\n').replace(/\u0000/g, '');
|
|
174
|
+
const { tag, restore } = tagRegistry();
|
|
120
175
|
const codeBlocks = [];
|
|
121
176
|
html = html.replace(/```([\w-]*)[^\n]*\n([\s\S]*?)```/g, (_, lang, code) => {
|
|
122
177
|
const cls = lang
|
|
@@ -130,14 +185,13 @@ export function parseMarkdown(text, options = {}) {
|
|
|
130
185
|
inlineCodes.push(`<code>${escapeHtml(code)}</code>`);
|
|
131
186
|
return `${INLINE}${inlineCodes.length - 1}${INLINE}`;
|
|
132
187
|
});
|
|
133
|
-
html = parseBlockquotes(html);
|
|
134
|
-
html = parseTables(html);
|
|
135
|
-
html = parseLists(html);
|
|
136
|
-
|
|
137
|
-
//
|
|
138
|
-
html = html
|
|
139
|
-
|
|
140
|
-
.replaceAll(TABLE_CLOSE, '</div>');
|
|
188
|
+
html = parseBlockquotes(html, tag);
|
|
189
|
+
html = parseTables(html, tag);
|
|
190
|
+
html = parseLists(html, tag);
|
|
191
|
+
// Escape everything (sentinels contain no escapable characters), then put back only our own
|
|
192
|
+
// tags, so a literal `<input>`, `<table>` or `<div>` in the text is never trusted.
|
|
193
|
+
html = restore(escapeHtml(html));
|
|
194
|
+
html = html.replaceAll(TABLE_OPEN, TABLE_WRAP_OPEN).replaceAll(TABLE_CLOSE, '</div>');
|
|
141
195
|
html = html.replace(/^[\t ]*(?:---+|\*\*\*+|___+)[\t ]*$/gm, '<hr>');
|
|
142
196
|
html = html.replace(/^#### (.+)$/gm, '<h4>$1</h4>');
|
|
143
197
|
html = html.replace(/^### (.+)$/gm, '<h4>$1</h4>');
|
|
@@ -170,38 +224,15 @@ export function parseMarkdown(text, options = {}) {
|
|
|
170
224
|
if (!html.startsWith('<'))
|
|
171
225
|
html = `<p>${html}</p>`;
|
|
172
226
|
html = html.replace(/<p>\s*<\/p>/g, '');
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
'tbody',
|
|
181
|
-
'tr',
|
|
182
|
-
'th',
|
|
183
|
-
'td',
|
|
184
|
-
'ul',
|
|
185
|
-
'ol',
|
|
186
|
-
'li',
|
|
187
|
-
'br',
|
|
188
|
-
'input',
|
|
189
|
-
];
|
|
190
|
-
const tagPattern = tags.map((t) => `<\\/?${t}[^>]*>`).join('|');
|
|
191
|
-
const markerPattern = markers.map((m) => `${m}\\d+${m}`).join('|');
|
|
192
|
-
const pattern = new RegExp(`(${tagPattern}|${markerPattern})`, 'gi');
|
|
193
|
-
return html
|
|
194
|
-
.split(pattern)
|
|
195
|
-
.map((part) => {
|
|
196
|
-
if (tags.some((t) => new RegExp(`^<\\/?${t}[^>]*>$`, 'i').test(part)))
|
|
197
|
-
return part;
|
|
198
|
-
if (markers.some((m) => part.startsWith(m) && part.endsWith(m)))
|
|
199
|
-
return part;
|
|
200
|
-
return escapeHtml(part);
|
|
201
|
-
})
|
|
202
|
-
.join('');
|
|
227
|
+
activeImageHosts = hosts;
|
|
228
|
+
try {
|
|
229
|
+
return DOMPurify.sanitize(html, DOMPURIFY_CONFIG);
|
|
230
|
+
}
|
|
231
|
+
finally {
|
|
232
|
+
activeImageHosts = undefined;
|
|
233
|
+
}
|
|
203
234
|
}
|
|
204
|
-
function parseBlockquotes(html) {
|
|
235
|
+
function parseBlockquotes(html, tag) {
|
|
205
236
|
const lines = html.split('\n');
|
|
206
237
|
const out = [];
|
|
207
238
|
let i = 0;
|
|
@@ -212,7 +243,7 @@ function parseBlockquotes(html) {
|
|
|
212
243
|
quote.push(lines[i].replace(/^\s*>+\s?/, ''));
|
|
213
244
|
i += 1;
|
|
214
245
|
}
|
|
215
|
-
out.push(
|
|
246
|
+
out.push(`${tag('<blockquote class="agent-blockquote">')}${quote.join(tag('<br>'))}${tag('</blockquote>')}`);
|
|
216
247
|
continue;
|
|
217
248
|
}
|
|
218
249
|
out.push(lines[i]);
|
|
@@ -241,36 +272,36 @@ function parseItem(line) {
|
|
|
241
272
|
};
|
|
242
273
|
return null;
|
|
243
274
|
}
|
|
244
|
-
function buildList(items, start, indent) {
|
|
275
|
+
function buildList(items, start, indent, tag) {
|
|
245
276
|
const first = items[start];
|
|
246
277
|
const startAttr = first.type === 'ol' && first.start !== 1 ? ` start="${first.start}"` : '';
|
|
247
|
-
let html = `<${first.type}${startAttr}${first.task !== undefined ? ' class="agent-tasklist"' : ''}
|
|
278
|
+
let html = tag(`<${first.type}${startAttr}${first.task !== undefined ? ' class="agent-tasklist"' : ''}>`);
|
|
248
279
|
let i = start;
|
|
249
280
|
while (i < items.length && items[i].indent >= indent) {
|
|
250
281
|
const item = items[i];
|
|
251
282
|
if (item.indent > indent) {
|
|
252
|
-
const nested = buildList(items, i, item.indent);
|
|
283
|
+
const nested = buildList(items, i, item.indent, tag);
|
|
253
284
|
html += nested.html;
|
|
254
285
|
i = nested.end;
|
|
255
286
|
continue;
|
|
256
287
|
}
|
|
257
288
|
const box = item.task === undefined
|
|
258
289
|
? ''
|
|
259
|
-
: `<input type="checkbox" disabled${item.task ? ' checked' : ''}
|
|
290
|
+
: `${tag(`<input type="checkbox" disabled${item.task ? ' checked aria-label="Done"' : ' aria-label="Not done"'}>`)} `;
|
|
260
291
|
if (i + 1 < items.length && items[i + 1].indent > indent) {
|
|
261
|
-
html +=
|
|
262
|
-
const nested = buildList(items, i + 1, items[i + 1].indent);
|
|
263
|
-
html += `${nested.html}</li
|
|
292
|
+
html += `${tag('<li>')}${box}${item.content}`;
|
|
293
|
+
const nested = buildList(items, i + 1, items[i + 1].indent, tag);
|
|
294
|
+
html += `${nested.html}${tag('</li>')}`;
|
|
264
295
|
i = nested.end;
|
|
265
296
|
}
|
|
266
297
|
else {
|
|
267
|
-
html +=
|
|
298
|
+
html += `${tag('<li>')}${box}${item.content}${tag('</li>')}`;
|
|
268
299
|
i += 1;
|
|
269
300
|
}
|
|
270
301
|
}
|
|
271
|
-
return { html: `${html}
|
|
302
|
+
return { html: `${html}${tag(`</${first.type}>`)}`, end: i };
|
|
272
303
|
}
|
|
273
|
-
function parseLists(html) {
|
|
304
|
+
function parseLists(html, tag) {
|
|
274
305
|
const lines = html.split('\n');
|
|
275
306
|
const out = [];
|
|
276
307
|
let i = 0;
|
|
@@ -295,7 +326,7 @@ function parseLists(html) {
|
|
|
295
326
|
else
|
|
296
327
|
break;
|
|
297
328
|
}
|
|
298
|
-
out.push(buildList(items, 0, item.indent).html);
|
|
329
|
+
out.push(buildList(items, 0, item.indent, tag).html);
|
|
299
330
|
}
|
|
300
331
|
return out.join('\n');
|
|
301
332
|
}
|
|
@@ -306,7 +337,7 @@ const cells = (line) => line
|
|
|
306
337
|
.replace(/\|$/, '')
|
|
307
338
|
.split('|')
|
|
308
339
|
.map((c) => c.trim());
|
|
309
|
-
function parseTables(html) {
|
|
340
|
+
function parseTables(html, tag) {
|
|
310
341
|
const lines = html.split('\n');
|
|
311
342
|
const out = [];
|
|
312
343
|
let i = 0;
|
|
@@ -320,9 +351,11 @@ function parseTables(html) {
|
|
|
320
351
|
rows.push(cells(lines[j]));
|
|
321
352
|
j += 1;
|
|
322
353
|
}
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
354
|
+
const cell = (name, c) => `${tag(`<${name}>`)}${c}${tag(`</${name}>`)}`;
|
|
355
|
+
const row = (r, name) => `${tag('<tr>')}${r.map((c) => cell(name, c)).join('')}${tag('</tr>')}`;
|
|
356
|
+
out.push(`${TABLE_OPEN}${tag('<table class="agent-table"><thead>')}${row(header, 'th')}${tag('</thead><tbody>')}${rows
|
|
357
|
+
.map((r) => row(r, 'td'))
|
|
358
|
+
.join('')}${tag('</tbody></table>')}${TABLE_CLOSE}`);
|
|
326
359
|
i = j;
|
|
327
360
|
continue;
|
|
328
361
|
}
|
package/dist/reducer.d.ts
CHANGED
|
@@ -80,6 +80,12 @@ export interface AssistantMessage {
|
|
|
80
80
|
mode?: BackendMode;
|
|
81
81
|
/** The user's rating of this answer, when given. */
|
|
82
82
|
feedback?: TurnRating;
|
|
83
|
+
/**
|
|
84
|
+
* Internal: the stored turn this request was sent to replace (regenerate, edit, retry). Kept
|
|
85
|
+
* only until the runtime accepts the request (`start`); a retry of a request that never
|
|
86
|
+
* started replaces this turn instead of the never-stored request.
|
|
87
|
+
*/
|
|
88
|
+
replaces?: string;
|
|
83
89
|
createdAt: number;
|
|
84
90
|
}
|
|
85
91
|
export type ChatMessage = UserMessage | AssistantMessage;
|
|
@@ -92,6 +98,11 @@ export declare function newUserMessage(requestId: string, text: string, options?
|
|
|
92
98
|
export declare function describeContext(context: DocumentContext): string;
|
|
93
99
|
/** Fold one stream event into the assistant message it belongs to. Returns a new object. */
|
|
94
100
|
export declare function applyEvent(message: AssistantMessage, event: ChatEvent): AssistantMessage;
|
|
101
|
+
/**
|
|
102
|
+
* Whether Continue can carry on this answer: it was cut short (output limit) or stopped, and has
|
|
103
|
+
* text. A dropped connection or an error is retried instead.
|
|
104
|
+
*/
|
|
105
|
+
export declare function isContinuable(message: AssistantMessage): boolean;
|
|
95
106
|
/**
|
|
96
107
|
* Prepare a retry of the turn `requestId`: returns the user message to resend and the transcript
|
|
97
108
|
* without that turn (its user message and the failed assistant reply), so the retried turn
|
package/dist/reducer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reducer.d.ts","sourceRoot":"","sources":["../src/lib/reducer.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"reducer.d.ts","sourceRoot":"","sources":["../src/lib/reducer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EACjB,WAAW,EACX,SAAS,EACT,UAAU,EACV,eAAe,EACf,OAAO,EACP,iBAAiB,EACjB,gBAAgB,EAChB,UAAU,EACX,MAAM,gCAAgC,CAAC;AACxC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAEnE;;;GAGG;AAEH,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,OAAO,GAAG,KAAK,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,QAAQ;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,iBAAiB,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,kBAAkB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG,MAAM,GAAG,WAAW,GAAG,OAAO,GAAG,YAAY,CAAC;AAE1F,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,OAAO,EAAE,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,WAAW,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,eAAe,CAAC;IACxB,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,WAAW,EAAE,eAAe,EAAE,CAAC;IAC/B,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,EAAE,EAAE,eAAe,EAAE,CAAC;IACtB,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,SAAS,EAAE,iBAAiB,EAAE,CAAC;IAC/B,KAAK,EAAE,UAAU,CAAC;IAClB,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,eAAe,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC;IACvE,YAAY,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,WAAW,GAAG,OAAO,CAAC;IACzD,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,oDAAoD;IACpD,QAAQ,CAAC,EAAE,UAAU,CAAC;IACtB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,WAAW,GAAG,WAAW,GAAG,gBAAgB,CAAC;AAEzD,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,SAAa,GAAG,gBAAgB,CAgBzF;AAED,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;IAAE,WAAW,CAAC,EAAE,OAAO,EAAE,CAAC;IAAC,OAAO,CAAC,EAAE,eAAe,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAO,GACjF,WAAW,CASb;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CAIhE;AAED,4FAA4F;AAC5F,wBAAgB,UAAU,CAAC,OAAO,EAAE,gBAAgB,EAAE,KAAK,EAAE,SAAS,GAAG,gBAAgB,CAgJxF;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAMhE;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,WAAW,EAAE,EACvB,SAAS,EAAE,MAAM,GAChB;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,WAAW,EAAE,CAAA;CAAE,GAAG,SAAS,CAOxD;AAED;;;GAGG;AACH,wBAAgB,UAAU,CACxB,QAAQ,EAAE,WAAW,EAAE,EACvB,SAAS,EAAE,MAAM,GAChB;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,WAAW,EAAE,CAAA;CAAE,GAAG,SAAS,CAOxD;AAED,6EAA6E;AAC7E,wBAAgB,UAAU,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,CAkBxD;AAED,YAAY,EAAE,UAAU,EAAE,CAAC"}
|