typebulb 0.15.2 → 0.15.4
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 +1 -1
- package/dist/agents/claude/client.js +172 -170
- package/dist/agents/claude/styles.css +17 -4
- package/dist/format/parse.d.ts +10 -0
- package/dist/format/parse.d.ts.map +1 -1
- package/dist/format/parse.js +47 -4
- package/dist/format/parse.js.map +1 -1
- package/dist/index.js +141 -141
- package/dist/render.d.ts +4 -0
- package/dist/render.js +80 -80
- package/dist/servers.js +85 -85
- package/package.json +1 -1
|
@@ -589,13 +589,14 @@ a.server-port:hover { text-decoration: underline; }
|
|
|
589
589
|
.md :first-child { margin-top: 0; }
|
|
590
590
|
.md :last-child { margin-bottom: 0; }
|
|
591
591
|
.md p { margin: .5rem 0; }
|
|
592
|
-
/* Thematic break — also the divider between merged consecutive user sends (see
|
|
593
|
-
|
|
592
|
+
/* Thematic break — also the divider between merged consecutive user sends (see applyUser): faint
|
|
593
|
+
so the bubble still reads as one turn, but legible in both themes. Mixed off --fg (text contrast)
|
|
594
|
+
rather than --border + opacity: --border is itself dim in dark mode, so dimming it again left the
|
|
595
|
+
line invisible there — and the faintness is a property of the line's color, not the element. */
|
|
594
596
|
.md hr {
|
|
595
597
|
border: none;
|
|
596
|
-
border-top: 1px solid var(--
|
|
598
|
+
border-top: 1px solid color-mix(in srgb, var(--fg) 12%, transparent);
|
|
597
599
|
margin: .55rem 0;
|
|
598
|
-
opacity: .5;
|
|
599
600
|
}
|
|
600
601
|
.md pre {
|
|
601
602
|
background: var(--veil);
|
|
@@ -944,6 +945,18 @@ a.server-port:hover { text-decoration: underline; }
|
|
|
944
945
|
white-space: pre-wrap;
|
|
945
946
|
}
|
|
946
947
|
|
|
948
|
+
/* Structural-defect strip (a malformed bulb that still rendered) — same shape as the error strip but
|
|
949
|
+
amber: a warning, not a failure. */
|
|
950
|
+
.md .bulb-warn-strip {
|
|
951
|
+
padding: .45rem .7rem;
|
|
952
|
+
border-top: 1px solid var(--border);
|
|
953
|
+
background: color-mix(in srgb, rgb(200 140 30) 10%, var(--bg));
|
|
954
|
+
font-family: ui-monospace, monospace;
|
|
955
|
+
font-size: .8em;
|
|
956
|
+
color: color-mix(in srgb, rgb(200 140 30) 80%, var(--fg));
|
|
957
|
+
white-space: pre-wrap;
|
|
958
|
+
}
|
|
959
|
+
|
|
947
960
|
/* tool calls */
|
|
948
961
|
/* Closed tool: just a single-line row, no chrome — a tool-only turn stays a
|
|
949
962
|
tight list, not N stacked panels. Open tools get the panel treatment below. */
|
package/dist/format/parse.d.ts
CHANGED
|
@@ -8,6 +8,8 @@ export interface ParsedBulb {
|
|
|
8
8
|
frontmatter: BulbFrontmatter;
|
|
9
9
|
/** Block contents keyed by filename (e.g. `code.tsx`). */
|
|
10
10
|
files: Map<string, string>;
|
|
11
|
+
/** Structural defects tolerated during parse (an unterminated fence); empty when well-formed. */
|
|
12
|
+
warnings: string[];
|
|
11
13
|
}
|
|
12
14
|
/** Structured per-block content, keyed by kind. */
|
|
13
15
|
export type BulbData = {
|
|
@@ -15,6 +17,14 @@ export type BulbData = {
|
|
|
15
17
|
} & Record<SubscriptKind, string>;
|
|
16
18
|
/** Parse a `.bulb.md` file into frontmatter and file contents, or null if malformed. */
|
|
17
19
|
export declare function parseBulb(content: string): ParsedBulb | null;
|
|
20
|
+
/**
|
|
21
|
+
* Structural problems parseBulb tolerates silently — chiefly an unterminated code fence, which makes
|
|
22
|
+
* the blocks below it fall *inside* the open one. parseBulb still "succeeds" (it just produces wrong
|
|
23
|
+
* blocks), so on its own a malformed bulb compiles and renders as if clean — the gap a caller needs
|
|
24
|
+
* flagged. A thin read over parseBulb's own structural pass (same single walk, so the two can't drift);
|
|
25
|
+
* `null` (not a bulb at all) has no fence warnings to report. Empty when well-formed; never throws.
|
|
26
|
+
*/
|
|
27
|
+
export declare function validateBulbStructure(content: string): string[];
|
|
18
28
|
/** Convert a parsed bulb to a structured per-kind object (missing blocks become ''). */
|
|
19
29
|
export declare function toBulbData(parsed: ParsedBulb): BulbData;
|
|
20
30
|
//# sourceMappingURL=parse.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../format/src/parse.ts"],"names":[],"mappings":"AAAA,uGAAuG;AAEvG,OAAO,EAAE,KAAK,aAAa,EAAsC,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../format/src/parse.ts"],"names":[],"mappings":"AAAA,uGAAuG;AAEvG,OAAO,EAAE,KAAK,aAAa,EAAsC,MAAM,eAAe,CAAA;AAStF,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,eAAe,CAAA;IAC5B,0DAA0D;IAC1D,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC1B,iGAAiG;IACjG,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB;AAED,mDAAmD;AACnD,MAAM,MAAM,QAAQ,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAAA;AAEvE,wFAAwF;AACxF,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CA8D5D;AA6CD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAE/D;AAED,wFAAwF;AACxF,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,QAAQ,CAKvD"}
|
package/dist/format/parse.js
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
/** Parse a `.bulb.md` file: strict Markdown bundle with YAML frontmatter and `**filename**` blocks. */
|
|
2
2
|
import { blocks, orderedKinds, isBulbFormat } from './registry.js';
|
|
3
3
|
import { unescapeYamlString } from './yaml.js';
|
|
4
|
+
// The block grammar: a `**filename**` header on its own line, then a fenced code block (3+ backticks,
|
|
5
|
+
// optional language).
|
|
6
|
+
const BLOCK_HEADER_RE = /^\*\*(.+)\*\*$/;
|
|
7
|
+
const FENCE_OPEN_RE = /^(`{3,})(\w*)\s*$/;
|
|
8
|
+
const BLOCK_PATHS = new Set(orderedKinds.map(k => blocks[k].path));
|
|
4
9
|
/** Parse a `.bulb.md` file into frontmatter and file contents, or null if malformed. */
|
|
5
10
|
export function parseBulb(content) {
|
|
6
11
|
try {
|
|
@@ -23,10 +28,11 @@ export function parseBulb(content) {
|
|
|
23
28
|
return null;
|
|
24
29
|
// Parse file sections
|
|
25
30
|
const files = new Map();
|
|
31
|
+
const warnings = [];
|
|
26
32
|
while (i < lines.length) {
|
|
27
33
|
const line = lines[i]?.trim();
|
|
28
34
|
// Look for **filename** (bold markdown, tolerant of whitespace)
|
|
29
|
-
const fileMatch = line?.match(
|
|
35
|
+
const fileMatch = line?.match(BLOCK_HEADER_RE);
|
|
30
36
|
if (fileMatch) {
|
|
31
37
|
const filename = fileMatch[1].trim();
|
|
32
38
|
i++;
|
|
@@ -34,7 +40,7 @@ export function parseBulb(content) {
|
|
|
34
40
|
while (i < lines.length && lines[i]?.trim() === '')
|
|
35
41
|
i++;
|
|
36
42
|
// Parse fenced code block (tolerant of trailing whitespace)
|
|
37
|
-
const fenceMatch = lines[i]?.match(
|
|
43
|
+
const fenceMatch = lines[i]?.match(FENCE_OPEN_RE);
|
|
38
44
|
if (!fenceMatch) {
|
|
39
45
|
i++;
|
|
40
46
|
continue;
|
|
@@ -46,19 +52,46 @@ export function parseBulb(content) {
|
|
|
46
52
|
contentLines.push(lines[i]);
|
|
47
53
|
i++;
|
|
48
54
|
}
|
|
49
|
-
|
|
55
|
+
const terminated = i < lines.length;
|
|
56
|
+
i++; // Skip closing fence (no-op past EOF)
|
|
57
|
+
warnings.push(...blockWarnings(filename, contentLines, terminated));
|
|
50
58
|
files.set(filename, contentLines.join('\n'));
|
|
51
59
|
}
|
|
52
60
|
else {
|
|
53
61
|
i++;
|
|
54
62
|
}
|
|
55
63
|
}
|
|
56
|
-
return { frontmatter, files };
|
|
64
|
+
return { frontmatter, files, warnings };
|
|
57
65
|
}
|
|
58
66
|
catch {
|
|
59
67
|
return null;
|
|
60
68
|
}
|
|
61
69
|
}
|
|
70
|
+
// Structural defects an unterminated fence causes, reported per block: it either swallows a later block
|
|
71
|
+
// (that block's header lands inside this body, followed by its own fence) or simply runs to EOF. The
|
|
72
|
+
// swallow is the more specific signal, so prefer it. Anchored to the block registry (the authoritative
|
|
73
|
+
// set of block names), so a `**name**` in prose isn't mistaken for a real block start.
|
|
74
|
+
function blockWarnings(filename, body, terminated) {
|
|
75
|
+
const swallowed = [];
|
|
76
|
+
for (let j = 0; j < body.length; j++) {
|
|
77
|
+
const m = body[j]?.trim().match(BLOCK_HEADER_RE);
|
|
78
|
+
if (m && BLOCK_PATHS.has(m[1].trim()) && fenceFollows(body, j))
|
|
79
|
+
swallowed.push(m[1].trim());
|
|
80
|
+
}
|
|
81
|
+
if (swallowed.length)
|
|
82
|
+
return swallowed.map(sw => `**${filename}** block has an unterminated code fence — it swallowed the **${sw}** block.`);
|
|
83
|
+
if (!terminated)
|
|
84
|
+
return [`**${filename}** block has an unterminated code fence (it runs to the end of the file).`];
|
|
85
|
+
return [];
|
|
86
|
+
}
|
|
87
|
+
// A `**name**` line is a genuine swallowed block start (not prose mentioning a filename) only when a
|
|
88
|
+
// fence opens right after it — the same header+fence shape parseBulb requires.
|
|
89
|
+
function fenceFollows(body, headerIdx) {
|
|
90
|
+
let k = headerIdx + 1;
|
|
91
|
+
while (k < body.length && body[k]?.trim() === '')
|
|
92
|
+
k++;
|
|
93
|
+
return !!body[k]?.match(FENCE_OPEN_RE);
|
|
94
|
+
}
|
|
62
95
|
function parseFrontmatter(lines) {
|
|
63
96
|
const fm = {};
|
|
64
97
|
for (const line of lines) {
|
|
@@ -80,6 +113,16 @@ function parseFrontmatter(lines) {
|
|
|
80
113
|
return null;
|
|
81
114
|
return fm;
|
|
82
115
|
}
|
|
116
|
+
/**
|
|
117
|
+
* Structural problems parseBulb tolerates silently — chiefly an unterminated code fence, which makes
|
|
118
|
+
* the blocks below it fall *inside* the open one. parseBulb still "succeeds" (it just produces wrong
|
|
119
|
+
* blocks), so on its own a malformed bulb compiles and renders as if clean — the gap a caller needs
|
|
120
|
+
* flagged. A thin read over parseBulb's own structural pass (same single walk, so the two can't drift);
|
|
121
|
+
* `null` (not a bulb at all) has no fence warnings to report. Empty when well-formed; never throws.
|
|
122
|
+
*/
|
|
123
|
+
export function validateBulbStructure(content) {
|
|
124
|
+
return parseBulb(content)?.warnings ?? [];
|
|
125
|
+
}
|
|
83
126
|
/** Convert a parsed bulb to a structured per-kind object (missing blocks become ''). */
|
|
84
127
|
export function toBulbData(parsed) {
|
|
85
128
|
const kinds = Object.fromEntries(orderedKinds.map(kind => [kind, parsed.files.get(blocks[kind].path) || '']));
|
package/dist/format/parse.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse.js","sourceRoot":"","sources":["../../format/src/parse.ts"],"names":[],"mappings":"AAAA,uGAAuG;AAEvG,OAAO,EAAsB,MAAM,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AACtF,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"parse.js","sourceRoot":"","sources":["../../format/src/parse.ts"],"names":[],"mappings":"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"}
|