@poodle64/librarian 2026.10.3 → 2026.10.5
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 +12 -4
- package/dist/chat.svelte.d.ts +40 -0
- package/dist/chat.svelte.js +57 -3
- package/dist/client.d.ts +3 -0
- package/dist/client.js +4 -1
- package/dist/components/activity-group/activity-group.svelte +72 -77
- package/dist/components/activity-group/activity-group.svelte.d.ts +6 -1
- package/dist/components/agent-transcript/agent-transcript.svelte +225 -9
- package/dist/components/agent-transcript/agent-transcript.svelte.d.ts +19 -0
- package/dist/components/artefact-pane/artefact-pane.svelte +387 -43
- package/dist/components/artefact-pane/artefact-pane.svelte.d.ts +10 -1
- package/dist/components/conversation/conversation.svelte +74 -4
- package/dist/components/conversation/conversation.svelte.d.ts +15 -0
- package/dist/components/markdown/markdown.d.ts +30 -2
- package/dist/components/markdown/markdown.js +142 -5
- package/dist/components/markdown/markdown.svelte +130 -16
- package/dist/components/markdown/markdown.svelte.d.ts +12 -0
- package/dist/components/source-fold/index.d.ts +2 -0
- package/dist/components/source-fold/index.js +2 -0
- package/dist/components/source-fold/source-fold.svelte +225 -0
- package/dist/components/source-fold/source-fold.svelte.d.ts +17 -0
- package/dist/components/source-list/source-list.svelte +5 -3
- package/dist/components/source-list/source-list.svelte.d.ts +2 -0
- package/dist/components/thinking-row/thinking-row.svelte +38 -16
- package/dist/components/thinking-row/thinking-row.svelte.d.ts +3 -0
- package/dist/components/tool-row/tool-row.svelte +161 -49
- package/dist/components/tool-row/tool-row.svelte.d.ts +2 -3
- package/dist/components/visual-block/entity-card.svelte +94 -0
- package/dist/components/visual-block/entity-card.svelte.d.ts +7 -0
- package/dist/components/visual-block/timeline.svelte +99 -0
- package/dist/components/visual-block/timeline.svelte.d.ts +7 -0
- package/dist/components/visual-block/vega-chart.svelte +110 -0
- package/dist/components/visual-block/vega-chart.svelte.d.ts +7 -0
- package/dist/components/visual-block/visual-block.svelte +53 -0
- package/dist/components/visual-block/visual-block.svelte.d.ts +13 -0
- package/dist/components/written-card/index.d.ts +2 -0
- package/dist/components/written-card/index.js +2 -0
- package/dist/components/written-card/written-card.svelte +178 -0
- package/dist/components/written-card/written-card.svelte.d.ts +15 -0
- package/dist/copy.d.ts +73 -0
- package/dist/copy.js +56 -0
- package/dist/diff.d.ts +8 -0
- package/dist/diff.js +37 -0
- package/dist/steps.d.ts +28 -0
- package/dist/steps.js +168 -0
- package/dist/transcript.svelte.d.ts +19 -34
- package/dist/transcript.svelte.js +64 -56
- package/dist/visuals.d.ts +38 -0
- package/dist/visuals.js +82 -0
- package/dist/web-sources.d.ts +34 -0
- package/dist/web-sources.js +90 -0
- package/dist/written.d.ts +71 -0
- package/dist/written.js +83 -0
- package/package.json +14 -1
package/dist/written.js
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The documents a persona writes while it answers.
|
|
3
|
+
*
|
|
4
|
+
* The app emits an `artefact` frame after each successful Write or Edit, and a
|
|
5
|
+
* reopened conversation lists the same versions on its turns. The page shows
|
|
6
|
+
* each version in the reading column and links it for download; the bytes
|
|
7
|
+
* come from the host's own route, never from this package.
|
|
8
|
+
*/
|
|
9
|
+
import { fill } from './copy';
|
|
10
|
+
export const writtenKey = (written) => `${written.name}@${written.version}`;
|
|
11
|
+
export const isHtml = (mediaType) => mediaType.toLowerCase().startsWith('text/html');
|
|
12
|
+
/** The newest version of each document in `written`, in the order they first appear. */
|
|
13
|
+
export function newestPerName(written) {
|
|
14
|
+
const newest = new Map();
|
|
15
|
+
for (const w of written) {
|
|
16
|
+
const had = newest.get(w.name);
|
|
17
|
+
if (!had || w.version >= had.version)
|
|
18
|
+
newest.set(w.name, w);
|
|
19
|
+
}
|
|
20
|
+
return [...newest.values()];
|
|
21
|
+
}
|
|
22
|
+
/** "Minute", or "Document" where the document has no kind. */
|
|
23
|
+
export function kindLabel(written, words) {
|
|
24
|
+
const kind = (written.kind ?? '').trim() || words.documentKind;
|
|
25
|
+
return kind.charAt(0).toUpperCase() + kind.slice(1);
|
|
26
|
+
}
|
|
27
|
+
/** "Minute · 1 page · v1": kind, pages where known, version. */
|
|
28
|
+
export function writtenMeta(written, words) {
|
|
29
|
+
const parts = [kindLabel(written, words)];
|
|
30
|
+
if (written.pages > 0)
|
|
31
|
+
parts.push(written.pages === 1 ? words.pageCount : fill(words.pagesCount, { n: written.pages }));
|
|
32
|
+
parts.push(fill(words.writtenVersion, { n: written.version }));
|
|
33
|
+
return parts.join(' · ');
|
|
34
|
+
}
|
|
35
|
+
const baseName = (name) => name.split('/').filter(Boolean).at(-1) ?? name;
|
|
36
|
+
/** The download a card's chip offers: Word where the app renders it, else the source as written. */
|
|
37
|
+
export function chipFor(written, words) {
|
|
38
|
+
const file = baseName(written.name);
|
|
39
|
+
if (written.formats.includes('docx')) {
|
|
40
|
+
const stem = file.replace(/\.[^.]+$/, '');
|
|
41
|
+
return { format: 'docx', file: `${stem}.docx`, label: words.formatWord };
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
format: 'source',
|
|
45
|
+
file,
|
|
46
|
+
label: isHtml(written.media_type) ? words.formatHtml : words.formatMarkdown
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/** A leading `---` front matter block is metadata, not the document. */
|
|
50
|
+
export function stripFrontMatter(text) {
|
|
51
|
+
return text.replace(/^\uFEFF?---[ \t]*\r?\n[\s\S]*?\r?\n---[ \t]*(?:\r?\n|$)/, '').replace(/^\s*\n/, '');
|
|
52
|
+
}
|
|
53
|
+
/** Every version of `name` across the conversation, oldest first. */
|
|
54
|
+
export function writtenVersions(turns, name) {
|
|
55
|
+
const found = new Map();
|
|
56
|
+
for (const turn of turns)
|
|
57
|
+
for (const written of turn.written ?? [])
|
|
58
|
+
if (written.name === name)
|
|
59
|
+
found.set(written.version, written);
|
|
60
|
+
return [...found.values()].sort((a, b) => a.version - b.version);
|
|
61
|
+
}
|
|
62
|
+
/** What a version downloads as: its source, then each format the app renders. */
|
|
63
|
+
export function downloads(written, words) {
|
|
64
|
+
const label = (format) => format === 'docx' ? words.formatWord : format === 'pdf' ? words.formatPdf : format.toUpperCase();
|
|
65
|
+
return [
|
|
66
|
+
{ format: 'source', label: isHtml(written.media_type) ? words.formatHtml : words.formatMarkdown },
|
|
67
|
+
...written.formats.map((format) => ({ format, label: label(format) }))
|
|
68
|
+
];
|
|
69
|
+
}
|
|
70
|
+
/** An empty sandbox stops scripts, not fetches: a written page's <img> or CSS url() would be a beacon without this. */
|
|
71
|
+
export const FRAME_CSP = '<meta http-equiv="Content-Security-Policy" content="default-src \'none\'; style-src \'unsafe-inline\'; img-src data:; font-src data:">';
|
|
72
|
+
/**
|
|
73
|
+
* A written HTML page as its sandboxed frame shows it: under `FRAME_CSP`, and
|
|
74
|
+
* without a refresh, which navigates the frame itself, a fetch no policy stops.
|
|
75
|
+
*/
|
|
76
|
+
export function framed(html) {
|
|
77
|
+
const page = new DOMParser().parseFromString(html, 'text/html');
|
|
78
|
+
for (const meta of page.querySelectorAll('meta[http-equiv]')) {
|
|
79
|
+
if (meta.getAttribute('http-equiv')?.trim().toLowerCase() === 'refresh')
|
|
80
|
+
meta.remove();
|
|
81
|
+
}
|
|
82
|
+
return FRAME_CSP + page.documentElement.outerHTML;
|
|
83
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@poodle64/librarian",
|
|
3
|
-
"version": "2026.10.
|
|
3
|
+
"version": "2026.10.5",
|
|
4
4
|
"description": "An agent's conversation surface as a consumable Svelte 5 package: the stream client, transcript state and self-styling chat components (transcript, composer, markdown) every household app renders instead of rebuilding, speaking as whichever persona the app names.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -43,6 +43,14 @@
|
|
|
43
43
|
"types": "./dist/copy.d.ts",
|
|
44
44
|
"svelte": "./dist/copy.js"
|
|
45
45
|
},
|
|
46
|
+
"./written": {
|
|
47
|
+
"types": "./dist/written.d.ts",
|
|
48
|
+
"svelte": "./dist/written.js"
|
|
49
|
+
},
|
|
50
|
+
"./visuals": {
|
|
51
|
+
"types": "./dist/visuals.d.ts",
|
|
52
|
+
"svelte": "./dist/visuals.js"
|
|
53
|
+
},
|
|
46
54
|
"./attachments": {
|
|
47
55
|
"types": "./dist/attachments.d.ts",
|
|
48
56
|
"svelte": "./dist/attachments.js"
|
|
@@ -64,6 +72,11 @@
|
|
|
64
72
|
"isomorphic-dompurify": "^3.23.0",
|
|
65
73
|
"shiki": "^4.4.3"
|
|
66
74
|
},
|
|
75
|
+
"dependencies": {
|
|
76
|
+
"vega": "6.4.0",
|
|
77
|
+
"vega-embed": "7.3.0",
|
|
78
|
+
"vega-lite": "6.4.3"
|
|
79
|
+
},
|
|
67
80
|
"devDependencies": {
|
|
68
81
|
"@lucide/svelte": "^1.7.0",
|
|
69
82
|
"@poodle64/design-tokens": "workspace:*",
|