@poodle64/librarian 2026.9.28 → 2026.10.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 +66 -116
- package/dist/attachments.d.ts +2 -2
- package/dist/attachments.js +3 -3
- package/dist/chat.svelte.d.ts +22 -23
- package/dist/chat.svelte.js +41 -64
- package/dist/citations.d.ts +7 -7
- package/dist/citations.js +6 -6
- package/dist/client.d.ts +16 -45
- package/dist/client.js +15 -23
- package/dist/components/activity-group/activity-group.svelte +1 -1
- package/dist/components/agent-transcript/agent-transcript.svelte +9 -110
- package/dist/components/agent-transcript/agent-transcript.svelte.d.ts +4 -16
- package/dist/components/answer-mark/answer-mark.svelte +2 -2
- package/dist/components/answer-mark/answer-mark.svelte.d.ts +2 -2
- package/dist/components/answer-share/answer-share.svelte +2 -2
- package/dist/components/answer-share/answer-share.svelte.d.ts +2 -2
- package/dist/components/artefact-card/artefact-card.svelte +2 -2
- package/dist/components/artefact-card/artefact-card.svelte.d.ts +2 -2
- package/dist/components/artefact-pane/artefact-pane.svelte +2 -2
- package/dist/components/artefact-pane/artefact-pane.svelte.d.ts +2 -2
- package/dist/components/composer/composer.svelte +39 -112
- package/dist/components/composer/composer.svelte.d.ts +18 -18
- package/dist/components/composer/index.d.ts +1 -2
- package/dist/components/conversation/conversation.svelte +7 -18
- package/dist/components/conversation/conversation.svelte.d.ts +7 -12
- package/dist/components/conversation-list/conversation-list.svelte +2 -2
- package/dist/components/conversation-list/conversation-list.svelte.d.ts +2 -2
- package/dist/components/document-pane/document-pane.svelte +2 -2
- package/dist/components/document-pane/document-pane.svelte.d.ts +2 -2
- package/dist/components/fair-use-notice/fair-use-notice.svelte +2 -2
- package/dist/components/fair-use-notice/fair-use-notice.svelte.d.ts +2 -2
- package/dist/components/scope-statement/scope-statement.svelte +5 -5
- package/dist/components/scope-statement/scope-statement.svelte.d.ts +2 -2
- package/dist/components/source-list/source-list.svelte +2 -2
- package/dist/components/source-list/source-list.svelte.d.ts +2 -2
- package/dist/components/working/working.svelte +2 -2
- package/dist/components/working/working.svelte.d.ts +2 -2
- package/dist/copy.d.ts +16 -24
- package/dist/copy.js +10 -16
- package/dist/session.svelte.d.ts +1 -1
- package/dist/session.svelte.js +6 -7
- package/dist/transcript.svelte.d.ts +18 -32
- package/dist/transcript.svelte.js +19 -40
- package/package.json +1 -5
- package/dist/history.svelte.d.ts +0 -37
- package/dist/history.svelte.js +0 -59
|
@@ -1,20 +1,25 @@
|
|
|
1
|
-
import type
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { type ChatCopy } from '../../copy';
|
|
2
|
+
/** A collection a person may read, as the app lists it: `name` is what a
|
|
3
|
+
* question is narrowed to, `summary` is what the picker shows. */
|
|
4
|
+
export interface CollectionChoice {
|
|
5
|
+
name: string;
|
|
6
|
+
summary: string;
|
|
7
|
+
}
|
|
4
8
|
interface Props {
|
|
5
9
|
value: string;
|
|
6
10
|
running: boolean;
|
|
7
|
-
/**
|
|
8
|
-
*
|
|
9
|
-
|
|
11
|
+
/** The collections this person may read. The picker renders when there
|
|
12
|
+
* are two or more: with one, or none, there is nothing to choose. */
|
|
13
|
+
collections?: CollectionChoice[];
|
|
14
|
+
/** The collection the next question is narrowed to, by name; undefined
|
|
15
|
+
* asks across all of them. */
|
|
16
|
+
collection?: string;
|
|
10
17
|
/** Files to send with the next question. Cleared by the caller on send. */
|
|
11
18
|
files?: File[];
|
|
12
|
-
/** Names for the two narrower scopes; absent means that scope is unavailable. */
|
|
13
|
-
documentName?: string;
|
|
14
|
-
collectionName?: string;
|
|
15
19
|
/** Hides the paperclip for a host whose ask route takes no files. */
|
|
16
20
|
attachments?: boolean;
|
|
17
|
-
|
|
21
|
+
/** The person picked a collection by name, or all of them (undefined). */
|
|
22
|
+
oncollection?: (collection: string | undefined) => void;
|
|
18
23
|
onsubmit: () => void;
|
|
19
24
|
onstop: () => void;
|
|
20
25
|
/** Asks for a study artefact instead of an ordinary answer. Omit and no
|
|
@@ -25,21 +30,16 @@ interface Props {
|
|
|
25
30
|
* both placeholders are composed from it. */
|
|
26
31
|
name?: string;
|
|
27
32
|
/** Overrides for the package's own words. */
|
|
28
|
-
copy?: Partial<
|
|
33
|
+
copy?: Partial<ChatCopy>;
|
|
29
34
|
/** The session reads a message sent while it works — a job whose
|
|
30
35
|
* route writes it onto the running process — so the box stays open
|
|
31
36
|
* and Send sits beside Stop. Words only: the paperclip still waits for
|
|
32
37
|
* the run. Absent, a chat waits for its answer. */
|
|
33
38
|
sendWhileRunning?: boolean;
|
|
34
|
-
/** One quiet line in the box's footer, where
|
|
39
|
+
/** One quiet line in the box's footer, where the collection picker would
|
|
35
40
|
* sit, in the host's words: what sending does here ("It carries on
|
|
36
41
|
* from where it stopped."). */
|
|
37
42
|
note?: string;
|
|
38
|
-
/** Quick or Thorough for the next question, as a two-way switch with a
|
|
39
|
-
* one-line hint. Bind it and pass it to `ask()`; omit it and nothing
|
|
40
|
-
* renders. Once shown it is never disabled or hidden, and never names
|
|
41
|
-
* the model behind it. */
|
|
42
|
-
depth?: Depth;
|
|
43
43
|
/** How many turns are in the conversation so far. Past `turnLimit`
|
|
44
44
|
* (8 by default), a quiet banner appears above the box offering to
|
|
45
45
|
* start over. Omit and no banner ever renders — a host that does not
|
|
@@ -51,6 +51,6 @@ interface Props {
|
|
|
51
51
|
* action is worse than none. */
|
|
52
52
|
onnewquestion?: () => void;
|
|
53
53
|
}
|
|
54
|
-
declare const Composer: import("svelte").Component<Props, {}, "value" | "
|
|
54
|
+
declare const Composer: import("svelte").Component<Props, {}, "value" | "files">;
|
|
55
55
|
type Composer = ReturnType<typeof Composer>;
|
|
56
56
|
export default Composer;
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
import type { DescribeTool, Turn } from '../../transcript.svelte';
|
|
15
15
|
import type { Verdict } from '../../chat.svelte';
|
|
16
16
|
import type { Citation, LoadDocument } from '../../citations';
|
|
17
|
-
import { DEFAULT_PERSONA, personaName, resolveCopy, type
|
|
17
|
+
import { DEFAULT_PERSONA, personaName, resolveCopy, type ChatCopy } from '../../copy';
|
|
18
18
|
import { FollowScroll } from '../../follow-scroll.svelte';
|
|
19
19
|
import AgentTranscript, {
|
|
20
20
|
type AgentTranscriptProps
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
/** Who is speaking. A slug is fine — `penny` renders as "Penny" — and
|
|
38
38
|
* every word this package says is composed from it: the working line,
|
|
39
39
|
* the failure sentences, the scope label, the composer's placeholder
|
|
40
|
-
* and the accessible name of the scroll region. Absent is
|
|
41
|
-
*
|
|
40
|
+
* and the accessible name of the scroll region. Absent is a neutral
|
|
41
|
+
* default, never one app's persona. */
|
|
42
42
|
name?: string;
|
|
43
43
|
/** The empty state's opening line. Absent takes the persona's own. */
|
|
44
44
|
welcome?: string;
|
|
@@ -46,27 +46,22 @@
|
|
|
46
46
|
examples?: string[];
|
|
47
47
|
onexample?: (question: string) => void;
|
|
48
48
|
/** What this surface answers from and what it does not hold, in the
|
|
49
|
-
* host's own words. One statement per
|
|
49
|
+
* host's own words. One statement per persona, above the first turn,
|
|
50
50
|
* folded once the conversation starts. */
|
|
51
51
|
scope?: string;
|
|
52
52
|
/** Re-asks the last question. Offered on the last answer only. */
|
|
53
53
|
onregenerate?: () => void;
|
|
54
|
-
/** Asks a follow-up the librarian suggested. Offered on the last answer
|
|
55
|
-
* only; without it the suggestion chips do not render. */
|
|
56
|
-
onsuggest?: (question: string) => void;
|
|
57
54
|
/** Records a verdict on an answer. Offered on the last answer only, as
|
|
58
55
|
* asking again is; without it no mark renders. */
|
|
59
56
|
onmark?: (turn: Turn, verdict: Verdict) => Promise<boolean>;
|
|
60
57
|
/** Shares an answer read-only, or stops sharing it (`Chat.share`).
|
|
61
58
|
* Offered on every settled answer; without it nothing is shareable. */
|
|
62
59
|
onshare?: (turn: Turn, share: boolean) => Promise<boolean>;
|
|
63
|
-
/** The last question waits behind somebody else's (`Chat.waiting`). */
|
|
64
|
-
waiting?: boolean;
|
|
65
60
|
/** When the last answer began, epoch ms, where this page did not see it
|
|
66
61
|
* start (`Chat.answering`): it reads as still being written. */
|
|
67
62
|
answering?: number | null;
|
|
68
63
|
/** Overrides for the package's own words. */
|
|
69
|
-
copy?: Partial<
|
|
64
|
+
copy?: Partial<ChatCopy>;
|
|
70
65
|
/** Enables the source pane. Without it, chips render but do not open. */
|
|
71
66
|
loadDocument?: LoadDocument;
|
|
72
67
|
/** Takes every citation tap instead, for a host that shows the source
|
|
@@ -83,8 +78,8 @@
|
|
|
83
78
|
describeTool?: DescribeTool;
|
|
84
79
|
/** Prices a turn's `outcome.costUsd` in the host's own currency and
|
|
85
80
|
* words ("about A$0.34"), for the footer's cost line beside a turn's
|
|
86
|
-
*
|
|
87
|
-
* line shows
|
|
81
|
+
* duration. The package never converts currency itself; omitted, the
|
|
82
|
+
* line shows the duration only. */
|
|
88
83
|
formatCost?: (usd: number) => string;
|
|
89
84
|
collectionNames?: Set<string>;
|
|
90
85
|
/** The composer, rendered INSIDE the transcript column so the source
|
|
@@ -112,10 +107,8 @@
|
|
|
112
107
|
onexample,
|
|
113
108
|
scope,
|
|
114
109
|
onregenerate,
|
|
115
|
-
onsuggest,
|
|
116
110
|
onmark,
|
|
117
111
|
onshare,
|
|
118
|
-
waiting = false,
|
|
119
112
|
answering = null,
|
|
120
113
|
copy,
|
|
121
114
|
loadDocument,
|
|
@@ -309,10 +302,8 @@
|
|
|
309
302
|
blocks: turn.blocks,
|
|
310
303
|
outcome: turn.outcome,
|
|
311
304
|
running: running && last,
|
|
312
|
-
waiting: waiting && last,
|
|
313
305
|
answering: last ? (answering ?? undefined) : undefined,
|
|
314
306
|
citations: turn.citations ?? [],
|
|
315
|
-
suggestions: turn.suggestions ?? [],
|
|
316
307
|
collectionNames,
|
|
317
308
|
copy: words,
|
|
318
309
|
name: who,
|
|
@@ -321,11 +312,9 @@
|
|
|
321
312
|
artefactOpen: isShowing(turn),
|
|
322
313
|
onopenartefact: opener(turn),
|
|
323
314
|
describeTool,
|
|
324
|
-
depth: turn.depth,
|
|
325
315
|
formatCost,
|
|
326
316
|
oncite: oncite || loadDocument ? cite : undefined,
|
|
327
317
|
onregenerate: last && !running ? onregenerate : undefined,
|
|
328
|
-
onsuggest: last && !running ? onsuggest : undefined,
|
|
329
318
|
onmark:
|
|
330
319
|
last && !running && onmark ? (verdict: Verdict) => onmark(turn, verdict) : undefined,
|
|
331
320
|
shared: turn.shared,
|
|
@@ -2,7 +2,7 @@ import type { Snippet } from 'svelte';
|
|
|
2
2
|
import type { DescribeTool, Turn } from '../../transcript.svelte';
|
|
3
3
|
import type { Verdict } from '../../chat.svelte';
|
|
4
4
|
import type { Citation, LoadDocument } from '../../citations';
|
|
5
|
-
import { type
|
|
5
|
+
import { type ChatCopy } from '../../copy';
|
|
6
6
|
import { type AgentTranscriptProps } from '../agent-transcript/agent-transcript.svelte';
|
|
7
7
|
interface Props {
|
|
8
8
|
turns: Turn[];
|
|
@@ -13,8 +13,8 @@ interface Props {
|
|
|
13
13
|
/** Who is speaking. A slug is fine — `penny` renders as "Penny" — and
|
|
14
14
|
* every word this package says is composed from it: the working line,
|
|
15
15
|
* the failure sentences, the scope label, the composer's placeholder
|
|
16
|
-
* and the accessible name of the scroll region. Absent is
|
|
17
|
-
*
|
|
16
|
+
* and the accessible name of the scroll region. Absent is a neutral
|
|
17
|
+
* default, never one app's persona. */
|
|
18
18
|
name?: string;
|
|
19
19
|
/** The empty state's opening line. Absent takes the persona's own. */
|
|
20
20
|
welcome?: string;
|
|
@@ -22,27 +22,22 @@ interface Props {
|
|
|
22
22
|
examples?: string[];
|
|
23
23
|
onexample?: (question: string) => void;
|
|
24
24
|
/** What this surface answers from and what it does not hold, in the
|
|
25
|
-
* host's own words. One statement per
|
|
25
|
+
* host's own words. One statement per persona, above the first turn,
|
|
26
26
|
* folded once the conversation starts. */
|
|
27
27
|
scope?: string;
|
|
28
28
|
/** Re-asks the last question. Offered on the last answer only. */
|
|
29
29
|
onregenerate?: () => void;
|
|
30
|
-
/** Asks a follow-up the librarian suggested. Offered on the last answer
|
|
31
|
-
* only; without it the suggestion chips do not render. */
|
|
32
|
-
onsuggest?: (question: string) => void;
|
|
33
30
|
/** Records a verdict on an answer. Offered on the last answer only, as
|
|
34
31
|
* asking again is; without it no mark renders. */
|
|
35
32
|
onmark?: (turn: Turn, verdict: Verdict) => Promise<boolean>;
|
|
36
33
|
/** Shares an answer read-only, or stops sharing it (`Chat.share`).
|
|
37
34
|
* Offered on every settled answer; without it nothing is shareable. */
|
|
38
35
|
onshare?: (turn: Turn, share: boolean) => Promise<boolean>;
|
|
39
|
-
/** The last question waits behind somebody else's (`Chat.waiting`). */
|
|
40
|
-
waiting?: boolean;
|
|
41
36
|
/** When the last answer began, epoch ms, where this page did not see it
|
|
42
37
|
* start (`Chat.answering`): it reads as still being written. */
|
|
43
38
|
answering?: number | null;
|
|
44
39
|
/** Overrides for the package's own words. */
|
|
45
|
-
copy?: Partial<
|
|
40
|
+
copy?: Partial<ChatCopy>;
|
|
46
41
|
/** Enables the source pane. Without it, chips render but do not open. */
|
|
47
42
|
loadDocument?: LoadDocument;
|
|
48
43
|
/** Takes every citation tap instead, for a host that shows the source
|
|
@@ -59,8 +54,8 @@ interface Props {
|
|
|
59
54
|
describeTool?: DescribeTool;
|
|
60
55
|
/** Prices a turn's `outcome.costUsd` in the host's own currency and
|
|
61
56
|
* words ("about A$0.34"), for the footer's cost line beside a turn's
|
|
62
|
-
*
|
|
63
|
-
* line shows
|
|
57
|
+
* duration. The package never converts currency itself; omitted, the
|
|
58
|
+
* line shows the duration only. */
|
|
64
59
|
formatCost?: (usd: number) => string;
|
|
65
60
|
collectionNames?: Set<string>;
|
|
66
61
|
/** The composer, rendered INSIDE the transcript column so the source
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
import PlusIcon from '@lucide/svelte/icons/plus';
|
|
19
19
|
import TrashIcon from '@lucide/svelte/icons/trash-2';
|
|
20
20
|
import type { ConversationSummary } from '../../chat.svelte';
|
|
21
|
-
import { DEFAULT_PERSONA, resolveCopy, type
|
|
21
|
+
import { DEFAULT_PERSONA, resolveCopy, type ChatCopy } from '../../copy';
|
|
22
22
|
|
|
23
23
|
interface Props {
|
|
24
24
|
/** Null while it is still being read. */
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
ondelete?: (id: string) => Promise<boolean>;
|
|
40
40
|
/** Who is answering, for the line on a conversation still being answered. */
|
|
41
41
|
name?: string;
|
|
42
|
-
copy?: Partial<
|
|
42
|
+
copy?: Partial<ChatCopy>;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
let {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ConversationSummary } from '../../chat.svelte';
|
|
2
|
-
import { type
|
|
2
|
+
import { type ChatCopy } from '../../copy';
|
|
3
3
|
interface Props {
|
|
4
4
|
/** Null while it is still being read. */
|
|
5
5
|
conversations: ConversationSummary[] | null;
|
|
@@ -19,7 +19,7 @@ interface Props {
|
|
|
19
19
|
ondelete?: (id: string) => Promise<boolean>;
|
|
20
20
|
/** Who is answering, for the line on a conversation still being answered. */
|
|
21
21
|
name?: string;
|
|
22
|
-
copy?: Partial<
|
|
22
|
+
copy?: Partial<ChatCopy>;
|
|
23
23
|
}
|
|
24
24
|
declare const ConversationList: import("svelte").Component<Props, {}, "">;
|
|
25
25
|
type ConversationList = ReturnType<typeof ConversationList>;
|
|
@@ -10,14 +10,14 @@
|
|
|
10
10
|
<script lang="ts">
|
|
11
11
|
import XIcon from '@lucide/svelte/icons/x';
|
|
12
12
|
import { trustMark, type Citation, type LoadDocument, type LoadedDocument } from '../../citations';
|
|
13
|
-
import { resolveCopy, type
|
|
13
|
+
import { resolveCopy, type ChatCopy } from '../../copy';
|
|
14
14
|
import Markdown from '../markdown/markdown.svelte';
|
|
15
15
|
|
|
16
16
|
interface Props {
|
|
17
17
|
citation: Citation;
|
|
18
18
|
loadDocument: LoadDocument;
|
|
19
19
|
onclose: () => void;
|
|
20
|
-
copy?: Partial<
|
|
20
|
+
copy?: Partial<ChatCopy>;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
let { citation, loadDocument, onclose, copy }: Props = $props();
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { type Citation, type LoadDocument } from '../../citations';
|
|
2
|
-
import { type
|
|
2
|
+
import { type ChatCopy } from '../../copy';
|
|
3
3
|
interface Props {
|
|
4
4
|
citation: Citation;
|
|
5
5
|
loadDocument: LoadDocument;
|
|
6
6
|
onclose: () => void;
|
|
7
|
-
copy?: Partial<
|
|
7
|
+
copy?: Partial<ChatCopy>;
|
|
8
8
|
}
|
|
9
9
|
declare const DocumentPane: import("svelte").Component<Props, {}, "">;
|
|
10
10
|
type DocumentPane = ReturnType<typeof DocumentPane>;
|
|
@@ -14,13 +14,13 @@
|
|
|
14
14
|
<script lang="ts">
|
|
15
15
|
import InfoIcon from '@lucide/svelte/icons/info';
|
|
16
16
|
import type { Quota } from '../../chat.svelte';
|
|
17
|
-
import { fill, resolveCopy, type
|
|
17
|
+
import { fill, resolveCopy, type ChatCopy } from '../../copy';
|
|
18
18
|
|
|
19
19
|
interface Props {
|
|
20
20
|
quota: Quota | null;
|
|
21
21
|
/** Where to ask about the limit. Absent takes the allowance's own. */
|
|
22
22
|
supportHref?: string;
|
|
23
|
-
copy?: Partial<
|
|
23
|
+
copy?: Partial<ChatCopy>;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
let { quota, supportHref, copy }: Props = $props();
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { Quota } from '../../chat.svelte';
|
|
2
|
-
import { type
|
|
2
|
+
import { type ChatCopy } from '../../copy';
|
|
3
3
|
interface Props {
|
|
4
4
|
quota: Quota | null;
|
|
5
5
|
/** Where to ask about the limit. Absent takes the allowance's own. */
|
|
6
6
|
supportHref?: string;
|
|
7
|
-
copy?: Partial<
|
|
7
|
+
copy?: Partial<ChatCopy>;
|
|
8
8
|
}
|
|
9
9
|
declare const FairUseNotice: import("svelte").Component<Props, {}, "">;
|
|
10
10
|
type FairUseNotice = ReturnType<typeof FairUseNotice>;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
<!--
|
|
2
|
-
What
|
|
2
|
+
What a persona answers from, and what it does not hold.
|
|
3
3
|
|
|
4
|
-
A colleague's first question about a
|
|
4
|
+
A colleague's first question about a persona is not the one they type — it is
|
|
5
5
|
whether the answer they are about to read covers their case at all. Saying it
|
|
6
|
-
once, in the
|
|
6
|
+
once, in the persona's own words, is cheaper than every answer hedging.
|
|
7
7
|
|
|
8
8
|
It leads while there is nothing else on the surface, and folds to one line as
|
|
9
9
|
soon as there is: a boundary a reader has already read is a banner in the way
|
|
@@ -15,14 +15,14 @@
|
|
|
15
15
|
import { untrack } from 'svelte';
|
|
16
16
|
import ChevronDownIcon from '@lucide/svelte/icons/chevron-down';
|
|
17
17
|
import InfoIcon from '@lucide/svelte/icons/info';
|
|
18
|
-
import { resolveCopy, type
|
|
18
|
+
import { resolveCopy, type ChatCopy } from '../../copy';
|
|
19
19
|
|
|
20
20
|
interface Props {
|
|
21
21
|
/** The statement itself, in the host's own words. */
|
|
22
22
|
statement: string;
|
|
23
23
|
/** Open on arrival. Goes false once the conversation has a first turn. */
|
|
24
24
|
expanded?: boolean;
|
|
25
|
-
copy?: Partial<
|
|
25
|
+
copy?: Partial<ChatCopy>;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
let { statement, expanded = true, copy }: Props = $props();
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type ChatCopy } from '../../copy';
|
|
2
2
|
interface Props {
|
|
3
3
|
/** The statement itself, in the host's own words. */
|
|
4
4
|
statement: string;
|
|
5
5
|
/** Open on arrival. Goes false once the conversation has a first turn. */
|
|
6
6
|
expanded?: boolean;
|
|
7
|
-
copy?: Partial<
|
|
7
|
+
copy?: Partial<ChatCopy>;
|
|
8
8
|
}
|
|
9
9
|
declare const ScopeStatement: import("svelte").Component<Props, {}, "">;
|
|
10
10
|
type ScopeStatement = ReturnType<typeof ScopeStatement>;
|
|
@@ -8,11 +8,11 @@
|
|
|
8
8
|
-->
|
|
9
9
|
<script lang="ts">
|
|
10
10
|
import { trustMark, type Citation } from '../../citations';
|
|
11
|
-
import type {
|
|
11
|
+
import type { ChatCopy } from '../../copy';
|
|
12
12
|
|
|
13
13
|
interface Props {
|
|
14
14
|
sources: Citation[];
|
|
15
|
-
words:
|
|
15
|
+
words: ChatCopy;
|
|
16
16
|
/** Opens the document. Omit and the rows list but do not open. */
|
|
17
17
|
oncite?: (citation: Citation) => void;
|
|
18
18
|
/** `h2` in a transcript turn, `h3` under the artefact's own title. */
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { type Citation } from '../../citations';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ChatCopy } from '../../copy';
|
|
3
3
|
interface Props {
|
|
4
4
|
sources: Citation[];
|
|
5
|
-
words:
|
|
5
|
+
words: ChatCopy;
|
|
6
6
|
/** Opens the document. Omit and the rows list but do not open. */
|
|
7
7
|
oncite?: (citation: Citation) => void;
|
|
8
8
|
/** `h2` in a transcript turn, `h3` under the artefact's own title. */
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
`copy`, which the host's `name` composed, so this component knows no persona.
|
|
13
13
|
-->
|
|
14
14
|
<script lang="ts">
|
|
15
|
-
import { resolveCopy, type
|
|
15
|
+
import { resolveCopy, type ChatCopy } from '../../copy';
|
|
16
16
|
|
|
17
17
|
interface Props {
|
|
18
18
|
/** Shown instead of the cycling word once real work is identifiable. */
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* the clock counts from it rather than from the moment it appeared. */
|
|
22
22
|
since?: number;
|
|
23
23
|
/** The persona's words. Resolved from `name` upstream. */
|
|
24
|
-
copy?: Partial<
|
|
24
|
+
copy?: Partial<ChatCopy>;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
let { label, since, copy }: Props = $props();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type ChatCopy } from '../../copy';
|
|
2
2
|
interface Props {
|
|
3
3
|
/** Shown instead of the cycling word once real work is identifiable. */
|
|
4
4
|
label?: string;
|
|
@@ -6,7 +6,7 @@ interface Props {
|
|
|
6
6
|
* the clock counts from it rather than from the moment it appeared. */
|
|
7
7
|
since?: number;
|
|
8
8
|
/** The persona's words. Resolved from `name` upstream. */
|
|
9
|
-
copy?: Partial<
|
|
9
|
+
copy?: Partial<ChatCopy>;
|
|
10
10
|
}
|
|
11
11
|
declare const Working: import("svelte").Component<Props, {}, "">;
|
|
12
12
|
type Working = ReturnType<typeof Working>;
|
package/dist/copy.d.ts
CHANGED
|
@@ -3,24 +3,23 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Here rather than inline in each component because these sentences are the
|
|
5
5
|
* package's opinion about how an agent talks to a colleague, and an app that
|
|
6
|
-
* needs a different register — a
|
|
6
|
+
* needs a different register — a persona whose boundary is worded by its own
|
|
7
7
|
* subject-matter owner — must be able to change one string without forking a
|
|
8
8
|
* component.
|
|
9
9
|
*
|
|
10
10
|
* NO STRING HERE NAMES A PERSONA. The name is an argument: a consuming app
|
|
11
11
|
* says who is speaking once, and every sentence the package renders is built
|
|
12
|
-
* from that.
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* Pebblestone's Penny introduced herself as Milton for a fortnight.
|
|
12
|
+
* from that. The default is a neutral name, never one app's persona: a
|
|
13
|
+
* package that hardcodes one app's persona is a package that lies in every
|
|
14
|
+
* other app.
|
|
16
15
|
*
|
|
17
16
|
* Every component takes `copy` as a PARTIAL and resolves it itself, so a host
|
|
18
17
|
* overriding one line does not have to restate the others, and a component
|
|
19
18
|
* used directly behaves the same as one reached through `Conversation`.
|
|
20
19
|
*/
|
|
21
|
-
/** The
|
|
22
|
-
export declare const DEFAULT_PERSONA = "
|
|
23
|
-
export interface
|
|
20
|
+
/** The name used wherever a consumer names no persona. */
|
|
21
|
+
export declare const DEFAULT_PERSONA = "Assistant";
|
|
22
|
+
export interface ChatCopy {
|
|
24
23
|
/** Prefixes the date on a verified source: "verified 23 Jun 2026". */
|
|
25
24
|
verified: string;
|
|
26
25
|
/** A source the catalogue has never confirmed against its publisher. */
|
|
@@ -35,8 +34,6 @@ export interface LibrarianCopy {
|
|
|
35
34
|
noAnswer: string;
|
|
36
35
|
/** Heading over the list of what an answer cited. */
|
|
37
36
|
sources: string;
|
|
38
|
-
/** Heading over the follow-up questions the persona offered. */
|
|
39
|
-
suggestions: string;
|
|
40
37
|
/** The collapsed scope statement's own label. */
|
|
41
38
|
scope: string;
|
|
42
39
|
/** The empty transcript's opening line. */
|
|
@@ -44,14 +41,11 @@ export interface LibrarianCopy {
|
|
|
44
41
|
/** The composer's placeholder, idle and while an answer streams. */
|
|
45
42
|
askPlaceholder: string;
|
|
46
43
|
answeringPlaceholder: string;
|
|
47
|
-
/** The
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
depthThorough: string;
|
|
53
|
-
depthQuickHint: string;
|
|
54
|
-
depthThoroughHint: string;
|
|
44
|
+
/** The composer's collection picker: its group's accessible name, and the
|
|
45
|
+
* choice that asks across everything the person may read. A collection is
|
|
46
|
+
* shown by its own summary, supplied by the app. */
|
|
47
|
+
collectionsLabel: string;
|
|
48
|
+
allCollections: string;
|
|
55
49
|
/** Past a few turns, the quiet line above the composer that offers to
|
|
56
50
|
* start over — a follow-up re-reads the whole conversation, so each one
|
|
57
51
|
* costs more than the last. */
|
|
@@ -69,8 +63,6 @@ export interface LibrarianCopy {
|
|
|
69
63
|
/** An artefact card's action, and the same action while it is open. */
|
|
70
64
|
openArtefact: string;
|
|
71
65
|
showingArtefact: string;
|
|
72
|
-
/** Beside the clock while the question waits behind someone else's. */
|
|
73
|
-
waiting: string;
|
|
74
66
|
/** Beside the clock on an answer this page did not start. */
|
|
75
67
|
stillAnswering: string;
|
|
76
68
|
/** The answer mark: the two verdicts, the optional note, and after. */
|
|
@@ -127,12 +119,12 @@ export declare function personaName(name: string): string;
|
|
|
127
119
|
* Deliberately free of pronouns: the persona is whoever the consuming app
|
|
128
120
|
* says it is, and a sentence that guesses is wrong for half of them.
|
|
129
121
|
*/
|
|
130
|
-
export declare function copyFor(name?: string):
|
|
122
|
+
export declare function copyFor(name?: string): ChatCopy;
|
|
131
123
|
/** A sentence with `{name}` places, filled. A place with no value stays as
|
|
132
124
|
* written, so a host's override that drops one loses nothing else. */
|
|
133
125
|
export declare function fill(template: string, values: Record<string, string | number>): string;
|
|
134
|
-
/** The
|
|
135
|
-
export declare const DEFAULT_COPY:
|
|
126
|
+
/** The package's own words, for a host that names no persona. */
|
|
127
|
+
export declare const DEFAULT_COPY: ChatCopy;
|
|
136
128
|
/**
|
|
137
129
|
* One persona's words with a host's overrides on top.
|
|
138
130
|
*
|
|
@@ -141,4 +133,4 @@ export declare const DEFAULT_COPY: LibrarianCopy;
|
|
|
141
133
|
* nothing at all — and that is exactly the shape a host produces by passing a
|
|
142
134
|
* value it computed from state that has not loaded yet.
|
|
143
135
|
*/
|
|
144
|
-
export declare function resolveCopy(overrides?: Partial<
|
|
136
|
+
export declare function resolveCopy(overrides?: Partial<ChatCopy>, name?: string): ChatCopy;
|
package/dist/copy.js
CHANGED
|
@@ -3,23 +3,22 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Here rather than inline in each component because these sentences are the
|
|
5
5
|
* package's opinion about how an agent talks to a colleague, and an app that
|
|
6
|
-
* needs a different register — a
|
|
6
|
+
* needs a different register — a persona whose boundary is worded by its own
|
|
7
7
|
* subject-matter owner — must be able to change one string without forking a
|
|
8
8
|
* component.
|
|
9
9
|
*
|
|
10
10
|
* NO STRING HERE NAMES A PERSONA. The name is an argument: a consuming app
|
|
11
11
|
* says who is speaking once, and every sentence the package renders is built
|
|
12
|
-
* from that.
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* Pebblestone's Penny introduced herself as Milton for a fortnight.
|
|
12
|
+
* from that. The default is a neutral name, never one app's persona: a
|
|
13
|
+
* package that hardcodes one app's persona is a package that lies in every
|
|
14
|
+
* other app.
|
|
16
15
|
*
|
|
17
16
|
* Every component takes `copy` as a PARTIAL and resolves it itself, so a host
|
|
18
17
|
* overriding one line does not have to restate the others, and a component
|
|
19
18
|
* used directly behaves the same as one reached through `Conversation`.
|
|
20
19
|
*/
|
|
21
|
-
/** The
|
|
22
|
-
export const DEFAULT_PERSONA = '
|
|
20
|
+
/** The name used wherever a consumer names no persona. */
|
|
21
|
+
export const DEFAULT_PERSONA = 'Assistant';
|
|
23
22
|
/**
|
|
24
23
|
* The display name for a persona a host identified by its slug.
|
|
25
24
|
*
|
|
@@ -52,7 +51,7 @@ export function copyFor(name = DEFAULT_PERSONA) {
|
|
|
52
51
|
notVerified: 'not verified',
|
|
53
52
|
// Two sentences, both plain: what happened, and the likeliest reason. It
|
|
54
53
|
// says nothing about collections, indexes or retrieval — a colleague
|
|
55
|
-
// reading it has no model of any of those, and the
|
|
54
|
+
// reading it has no model of any of those, and the persona's own
|
|
56
55
|
// instruction forbids naming them either.
|
|
57
56
|
notHeld: `${who} answered this one without a source. There may be no document here that covers it.`,
|
|
58
57
|
// A run can end `is_error` carrying no message at all, and a turn that
|
|
@@ -61,16 +60,12 @@ export function copyFor(name = DEFAULT_PERSONA) {
|
|
|
61
60
|
unreachable: `${who} can't be reached right now.`,
|
|
62
61
|
noAnswer: 'Stopped before an answer came.',
|
|
63
62
|
sources: 'Sources',
|
|
64
|
-
suggestions: 'Ask next',
|
|
65
63
|
scope: `What ${who} answers from`,
|
|
66
64
|
welcome: `Ask ${who} a question.`,
|
|
67
65
|
askPlaceholder: `Ask ${who}…`,
|
|
68
66
|
answeringPlaceholder: `${who} is answering…`,
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
depthThorough: 'Thorough',
|
|
72
|
-
depthQuickHint: 'Fast, for looking something up',
|
|
73
|
-
depthThoroughHint: 'Slower, reads more, for questions of interpretation',
|
|
67
|
+
collectionsLabel: `Where ${who} looks`,
|
|
68
|
+
allCollections: 'All your collections',
|
|
74
69
|
longConversation: `This conversation is getting long. A new question keeps ${who} quick.`,
|
|
75
70
|
working: [`${who} is looking`, `${who} is reading`],
|
|
76
71
|
conversationLabel: `Conversation with ${who}`,
|
|
@@ -82,7 +77,6 @@ export function copyFor(name = DEFAULT_PERSONA) {
|
|
|
82
77
|
documentUnavailable: "That document can't be opened right now.",
|
|
83
78
|
openArtefact: 'Open',
|
|
84
79
|
showingArtefact: 'Showing',
|
|
85
|
-
waiting: `${who} is answering another question first`,
|
|
86
80
|
stillAnswering: `${who} is still answering`,
|
|
87
81
|
markHelpful: 'Helpful',
|
|
88
82
|
markNotHelpful: 'Not helpful',
|
|
@@ -124,7 +118,7 @@ export function copyFor(name = DEFAULT_PERSONA) {
|
|
|
124
118
|
export function fill(template, values) {
|
|
125
119
|
return template.replace(/\{(\w+)\}/g, (place, key) => key in values ? String(values[key]) : place);
|
|
126
120
|
}
|
|
127
|
-
/** The
|
|
121
|
+
/** The package's own words, for a host that names no persona. */
|
|
128
122
|
export const DEFAULT_COPY = copyFor();
|
|
129
123
|
/**
|
|
130
124
|
* One persona's words with a host's overrides on top.
|
package/dist/session.svelte.d.ts
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* Every Claude Code event carries a `uuid`, and one already folded is
|
|
13
13
|
* skipped: a watch route replays from the first event, so opening it again
|
|
14
14
|
* after the session moves on folds only what is new. A frame the server adds
|
|
15
|
-
* itself (an error, the
|
|
15
|
+
* itself (an error, the citations) carries none, and is known by
|
|
16
16
|
* the event it follows.
|
|
17
17
|
*/
|
|
18
18
|
import type { AgentEvent } from './client';
|