typebulb 0.15.8 → 0.16.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.
@@ -18,6 +18,7 @@
18
18
  --veil: rgba(0, 0, 0, 0.05); /* one shade step; alpha-stacks as panels nest */
19
19
  --tool-bg: var(--panel);
20
20
  --err: rgb(206, 60, 60);
21
+ --warn: rgb(176, 120, 12); /* amber — the cache-leak (cost-caution) tier, milder than --err */
21
22
  --diff-add: rgb(40, 140, 70);
22
23
  --fold-marker: rgb(24, 145, 72);
23
24
  /* Prose measure for text (bubbles + notes) — kept to a readable line length.
@@ -37,6 +38,7 @@ html[data-theme="dark"] {
37
38
  --veil: rgba(255, 255, 255, 0.06);
38
39
  --tool-bg: var(--panel);
39
40
  --err: rgb(230, 60, 60);
41
+ --warn: rgb(232, 184, 80); /* amber — the cache-leak (cost-caution) tier, milder than --err */
40
42
  --diff-add: rgb(100, 210, 130);
41
43
  --fold-marker: rgb(0, 255, 0);
42
44
  color-scheme: dark;
@@ -147,13 +149,13 @@ body {
147
149
  session list). Wrap = positioning context; the popover anchors bottom/right and
148
150
  grows up-and-left — the chips sit in the right-aligned cluster, so left:0 would
149
151
  run them off the viewport's right edge. */
150
- .token-wrap, .sid-wrap, .servers-wrap { position: relative; display: inline-block; }
152
+ .token-wrap, .sid-wrap, .servers-wrap, .model-wrap { position: relative; display: inline-block; }
151
153
  /* Each pill renders its wrap unconditionally, emitting an empty div when it has
152
154
  nothing to show (no tokens / no session / nothing running). An empty wrap is
153
155
  still a flex child, so .statusbar-actions' gap lands on both its sides —
154
156
  doubling the visible gap between its neighbours. Collapse the empties so the
155
157
  cluster spaces evenly regardless of which pills are present. */
156
- .token-wrap:empty, .sid-wrap:empty, .servers-wrap:empty { display: none; }
158
+ .token-wrap:empty, .sid-wrap:empty, .servers-wrap:empty, .model-wrap:empty { display: none; }
157
159
  .picker, .servers-pop {
158
160
  --menu-h: 428px; /* one height for both statusbar menus — they sit side by side, so a
159
161
  mismatched cap reads as a glitch; .picker grows to it, .servers-pop
@@ -209,6 +211,11 @@ body {
209
211
  /* Shrink-to-fit, so the sweep paces the text's own length, not the container's — on a full-width
210
212
  box the band spends most of its run off-glyph (same move as typebulb.com's shimmer.ts). */
211
213
  display: inline-block;
214
+ /* background-clip:text paints the glyphs through this element's own box, so the box must be tall
215
+ enough to cover descenders — inheriting the statusbar's line-height:1 clips the "g" in "probing"/
216
+ "working…" at the baseline. A descender-clearing line-height restores the paint area; the button
217
+ centres this box, so the extra height never unbalances the row. */
218
+ line-height: 1.3;
212
219
  background-image: linear-gradient(100deg, currentColor 35%, var(--accent) 50%, currentColor 65%) !important;
213
220
  -webkit-background-clip: text;
214
221
  background-clip: text;
@@ -296,6 +303,180 @@ body {
296
303
  color: var(--fg);
297
304
  }
298
305
 
306
+ /* Agent switcher (TB-Agent-Switcher.md) — reuses the .picker popover + rows; just its own width and
307
+ the no-key entry form. The active model is marked with .picker-row.current (the accent dot), like
308
+ the attached session; the "active" tag rides .picker-time's muted right-aligned slot. */
309
+ .model-picker { width: min(380px, calc(100vw - 2rem)); }
310
+ .model-err { color: var(--danger, #f87171); font-size: .76rem; padding: .3rem .55rem; }
311
+ /* Key-entry form: the popover flips to this in place of the list when no key is set yet. */
312
+ .key-entry { gap: .5rem; padding: .7rem; }
313
+ .key-entry-head { font-size: .85rem; color: var(--fg); }
314
+ .key-entry .bulb-filter { width: 100%; }
315
+ .key-entry-acts { display: flex; gap: .4rem; justify-content: flex-end; }
316
+ .key-entry-note { font-size: .72rem; color: var(--muted); line-height: 1.4; }
317
+
318
+ /* Agent switcher watchdog (TB-Agent-Switcher.md). TWO tiers, both surfaced live while the menu is
319
+ closed: RED when an Anthropic model is riding the OpenRouter route (the $-per-turn Opus footgun), and
320
+ AMBER when the route served a turn uncached (the cache flip — a cost leak, pennies-scale, so quieter
321
+ than red so the red stays meaningful). The latch outranks the .on accent (equal specificity → source
322
+ order wins): coloured border + text, the bar's loudest states. */
323
+ .pill.danger, .pill.danger:hover { border-color: var(--err); color: var(--err); }
324
+ .pill.warn, .pill.warn:hover { border-color: var(--warn); color: var(--warn); }
325
+ /* The watchdog banner: rendered by Root just above the statusbar, anchored to the .app box. Centered,
326
+ capped width, opaque so it reads over the message text the strip lets through. Only present when a
327
+ tier is live, so it never costs layout in the common case. .danger is red + a glow ring (loud);
328
+ .warn is amber, no ring (a quieter cost cue). */
329
+ .model-banner {
330
+ position: absolute;
331
+ left: 0; right: 0; bottom: 2.6rem;
332
+ margin: 0 auto;
333
+ max-width: min(640px, calc(100vw - 2rem));
334
+ display: flex;
335
+ align-items: flex-start;
336
+ gap: .5rem;
337
+ padding: .55rem .75rem;
338
+ border-radius: 8px;
339
+ background: var(--bg);
340
+ color: var(--fg);
341
+ font-size: .8rem;
342
+ line-height: 1.4;
343
+ }
344
+ .model-banner.danger { border: 1px solid var(--err); box-shadow: 0 0 0 2px color-mix(in srgb, var(--err) 22%, transparent), 0 4px 14px rgba(0,0,0,.25); }
345
+ .model-banner.warn { border: 1px solid var(--warn); box-shadow: 0 4px 14px rgba(0,0,0,.22); }
346
+ .model-banner-icon { flex: none; }
347
+ .model-banner-text { color: var(--fg); }
348
+ /* L2 predictor: a status line at the top of the model popover saying what the next send will bill.
349
+ Muted by default; red when the live model is the Anthropic-via-OpenRouter footgun. */
350
+ /* The model menu's top section: ONE row — the route headline (ellipsizing) + the reasoning dial pinned
351
+ right. Height is one model-row minus its own border, so the row + border + the popover gap to the list
352
+ equal one list-row pitch — the section subtracts a whole row, never a fraction, so no model is clipped
353
+ under the scroll. (Eyeball-tune the height; exact pixel math isn't worth it.) The headline carries only
354
+ what the user cares about; reroute/uncached mechanics live in its title, not on the line. */
355
+ .model-head {
356
+ display: flex; align-items: center; justify-content: space-between; gap: .5rem; flex: none;
357
+ height: calc(var(--menu-row-h) - 1px); box-sizing: border-box;
358
+ /* left padding lines "More info" up with the model titles (row padding .55rem + dot 7px + gap .6rem);
359
+ right padding lines the dial up with the per-row "probe" column (row padding .55rem + list
360
+ padding-right 4px + scrollbar ~15px — the scrollbar is effectively always present, so it's accounted
361
+ for unconditionally; tweak the 15px by eye). */
362
+ padding: 0 calc(.55rem + 4px + 15px) 0 calc(.55rem + 7px + .6rem);
363
+ border-bottom: 1px solid var(--border);
364
+ font-size: .74rem; line-height: 1.35; color: var(--muted); /* line-height clears "g"/"y" descenders */
365
+ }
366
+ /* The external-override warning is the one case that still puts words on this row. */
367
+ .model-route { flex: 0 1 auto; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
368
+ .model-route.warn { color: var(--warn); }
369
+ /* "More info" — a quiet text link (not a pill); drills into the routing/reasoning explainer (diag chrome). */
370
+ .model-info-toggle {
371
+ appearance: none; background: none; border: 0; margin: 0; padding: 0;
372
+ font: inherit; font-size: .74rem; color: var(--accent); cursor: pointer; flex: none;
373
+ }
374
+ .model-info-toggle:hover { text-decoration: underline; }
375
+ /* The reasoning label sits a clear gap to the left of the dial; the pair hugs the right edge. */
376
+ .reasoning-ctl { display: flex; align-items: center; gap: .5rem; flex: none; }
377
+ .reasoning-label { flex: none; }
378
+
379
+ /* The reasoning dial — a Min/Low/Med/High native select styled as an accent pill (a full combobox is
380
+ over-powered for four fixed levels), pinned to the right of the headline so the dropdown is the row's
381
+ last element. */
382
+ .reasoning-select {
383
+ appearance: none; margin: 0; font: inherit; font-size: .72rem;
384
+ width: 4rem; /* match the probe button so the dial shares its column */
385
+ /* centred text (symmetric padding) so the label sits like the probe button's centred caption; the
386
+ chevron still rides the right padding zone. */
387
+ height: 1.5rem; padding: 0 1.1rem; text-align: center; text-align-last: center; border-radius: 999px;
388
+ border: 1px solid color-mix(in srgb, var(--accent) 50%, transparent);
389
+ /* OPAQUE (mixed over --panel, not transparent) so the OPEN native option list matches the CLOSED
390
+ pill — a transparent fill left the open list on the browser's default bg, a jarring mismatch.
391
+ The option rows reuse the same --rs-bg so the two states are identical. */
392
+ --rs-bg: color-mix(in srgb, var(--accent) 14%, var(--panel));
393
+ background-color: var(--rs-bg);
394
+ color: var(--accent); cursor: pointer;
395
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath fill='none' stroke='%237aa2fa' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' d='M1 1l4 4 4-4'/%3E%3C/svg%3E");
396
+ background-repeat: no-repeat; background-position: right .5rem center;
397
+ }
398
+ .reasoning-select option { background-color: var(--rs-bg); color: var(--fg); }
399
+ .reasoning-select:hover { border-color: var(--accent); }
400
+ .reasoning-select:focus { outline: none; border-color: var(--accent); }
401
+
402
+ /* The Anthropic brand glyph stands in for the word on the default pill (same square footprint as the
403
+ prose toggle). currentColor tracks the pill's muted→accent state; grayscale at rest like the monkey. */
404
+ .anthropic-glyph { display: block; }
405
+ .pill.glyph .anthropic-glyph { filter: grayscale(1); opacity: .8; }
406
+ .pill.glyph:hover .anthropic-glyph { filter: none; opacity: 1; }
407
+
408
+ .model-row .picker-row-main { align-items: center; }
409
+ /* Hold the shared --menu-row-h pitch (TB-Agent-Mirror.md: "rows must match pitch exactly or the
410
+ side-by-side menus read as two designs"). The trailing control is the tallest per-row element; like
411
+ the launcher's .server-row, trim the inherited .picker-row vertical padding so it stays under the
412
+ --menu-row-h floor and that floor — not the padded content — governs the row height. The highlight
413
+ still fills the full 29px (it paints the row box, not the padding). */
414
+ .model-row { padding-top: .05rem; padding-bottom: .05rem; }
415
+ /* The Anthropic (default) row is its own group below the OpenRouter models — it's the distinct "off the
416
+ proxy, back to your subscription" choice, not just another model. Marked with a subtle background wash
417
+ rather than a divider line: a line fought the rows' rounded corners + inset highlights (poking corners,
418
+ uneven gaps), whereas the wash inherits the row's own 6px radius, so it reads as a contained band that
419
+ sits naturally. Zero layout impact; lower specificity than :hover/.active, so the row still gives its
420
+ normal accent feedback on top. */
421
+ .model-default-row { background: color-mix(in srgb, var(--fg) 6%, transparent); }
422
+ /* Right-aligned trailing cluster: the green `active` marker (only on the current row) then the
423
+ fixed-width status control. The status control is rightmost + fixed width, so its column never moves
424
+ as rows probe — least musical chairs. */
425
+ .model-trailing { flex: none; display: flex; gap: .35rem; justify-content: flex-end; align-items: center; }
426
+ /* ONE button look AND width shared by every trailing pill — probe, probing, the measured status, and
427
+ the active marker — so they all line up and a transition only ever changes colour/text, never the
428
+ shape. The width is snug to the widest short label ("uncached"); the labels are kept terse precisely
429
+ so this stays tight rather than gutter-heavy. */
430
+ .model-btn {
431
+ appearance: none; margin: 0; font: inherit; font-size: .72rem;
432
+ width: 4rem; height: 1.5rem; padding: 0 .25rem; border-radius: 999px;
433
+ display: inline-flex; align-items: center; justify-content: center;
434
+ border: 1px solid var(--border); background: transparent; color: var(--muted);
435
+ white-space: nowrap; cursor: pointer;
436
+ }
437
+ .model-status.probe:hover { color: var(--accent); border-color: var(--accent); }
438
+ /* Measured states. cached = the blue accent (the positive "good route" cue); uncached/unavailable =
439
+ red (the states that bite on cost); cache-unconfirmed = neutral. All reuse existing theme colours. */
440
+ .model-status.ok { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 50%, transparent); background: color-mix(in srgb, var(--accent) 12%, transparent); }
441
+ .model-status.bad { color: var(--err); border-color: color-mix(in srgb, var(--err) 50%, transparent); background: color-mix(in srgb, var(--err) 12%, transparent); }
442
+ .model-status.warn { color: var(--muted); border-color: var(--border); }
443
+ .model-status.ok:hover, .model-status.bad:hover, .model-status.warn:hover { filter: brightness(1.12); text-decoration: underline; }
444
+ /* Same pill as every other state — only the text/colour change across probe → probing → result, never
445
+ the box. Non-interactive (cursor default); the accent-tinted border holds against the row's accent
446
+ hover tint, where the faint default --border washed out. */
447
+ .model-status.probing { color: var(--muted); border-color: color-mix(in srgb, var(--accent) 35%, transparent); cursor: default; }
448
+ /* The active marker — the lime/green live-axis colour (--fold-marker), matching the launcher's running
449
+ :port. A cue, not a control: no hover, default cursor. */
450
+ .model-active { color: var(--fold-marker); border-color: color-mix(in srgb, var(--fold-marker) 50%, transparent); background: color-mix(in srgb, var(--fold-marker) 12%, transparent); cursor: default; }
451
+ /* Don't double-mark the current row: the green `active` pill is the marker now, so drop the accent dot
452
+ fill (keep the gutter transparent for name alignment). */
453
+ .model-picker .picker-row.current .picker-dot { background: transparent; }
454
+
455
+ /* Drill-in surface — the probe diagnostics and the "More info" routing/reasoning explainer (the
456
+ launcher's logs analogue). Flips the whole popover; reuses the console head/back chrome. Held at the
457
+ FULL menu height (not content-sized) so drilling in from the list never resizes the popover — the body
458
+ fills and scrolls if the content is long, leaving quiet space if it's short. */
459
+ .model-picker.diag-mode { padding: 0; gap: 0; height: var(--menu-h); }
460
+ .model-picker.diag-mode .diag-body { flex: 1; min-height: 0; overflow-y: auto; }
461
+ .model-picker.diag-mode:focus { outline: none; }
462
+ .diag-head { display: flex; align-items: center; justify-content: space-between; gap: .5rem; padding: .35rem .5rem; background: var(--panel); border-bottom: 1px solid var(--border); }
463
+ .diag-head-acts { display: flex; gap: .4rem; align-items: center; flex: none; }
464
+ .diag-back:disabled { opacity: .5; cursor: default; }
465
+ /* line-height clears descenders: the popover inherits the statusbar's line-height:1, and overflow:hidden
466
+ would otherwise crop the tails of "g"/"y" (same root cause as .shimmer-text's fix). */
467
+ .diag-name { min-width: 0; color: var(--fg); font-size: .8rem; line-height: 1.35; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
468
+ .diag-back { font: inherit; font-size: .76rem; appearance: none; margin: 0; padding: .15rem .5rem; border-radius: 5px; background: transparent; border: 1px solid var(--border); color: var(--muted); cursor: pointer; white-space: nowrap; }
469
+ .diag-back:hover { color: var(--accent); border-color: var(--accent); }
470
+ .diag-body { display: flex; flex-direction: column; gap: .4rem; padding: .6rem; background: var(--bg); }
471
+ .diag-line { font-size: .8rem; line-height: 1.45; overflow-wrap: anywhere; }
472
+ /* Hanging-indent bullet under a lead-in line — wrapped lines align past the “• ”. */
473
+ .diag-bullet { padding-left: 1rem; text-indent: -0.55rem; }
474
+ .diag-line.ok { color: var(--diff-add); }
475
+ .diag-line.bad { color: var(--err); }
476
+ .diag-line.warn { color: var(--fg); }
477
+ .diag-line.muted { color: var(--muted); }
478
+ .diag-line.small { font-size: .72rem; }
479
+
299
480
  /* Running-breakouts list — shares the popover chrome (.servers-pop above); its own dimensions +
300
481
  per-row layout: the play/stop button + name read together on the left (▶/■ Title, name flex:1),
301
482
  and the metadata/controls form a right-aligned cluster of fixed-width columns (logs · trust ·
@@ -1097,6 +1278,8 @@ a.server-port:hover { text-decoration: underline; }
1097
1278
  }
1098
1279
 
1099
1280
  .thinking { margin-bottom: .4rem; font-size: .82rem; color: var(--muted); }
1281
+ /* The <summary> toggle defaults to a text cursor — give it the pointer every other expandable uses. */
1282
+ .thinking summary { cursor: pointer; }
1100
1283
  .thinking pre { white-space: pre-wrap; }
1101
1284
 
1102
1285
  /* Copy button: an .overlay-pill revealed on bubble-hover. */
@@ -10,6 +10,14 @@ export interface ParsedBulb {
10
10
  files: Map<string, string>;
11
11
  /** Structural defects tolerated during parse (an unterminated fence); empty when well-formed. */
12
12
  warnings: string[];
13
+ /**
14
+ * Line index (0-based, into the parsed content's `split('\n')`) just past the last *captured* block's
15
+ * closing fence — i.e. where the bulb's body ends. NOT end-of-content: trailing lines that set no block
16
+ * (prose, a stray `---`) sit beyond it. Equals the line after the frontmatter when no block was captured.
17
+ * Lets a caller slice a bulb out of surrounding prose without swallowing what follows it (see
18
+ * `findEmbeddedBulbs`).
19
+ */
20
+ bodyEndLine: number;
13
21
  }
14
22
  /** Structured per-block content, keyed by kind. */
15
23
  export type BulbData = {
@@ -25,6 +33,28 @@ export declare function parseBulb(content: string): ParsedBulb | null;
25
33
  * `null` (not a bulb at all) has no fence warnings to report. Empty when well-formed; never throws.
26
34
  */
27
35
  export declare function validateBulbStructure(content: string): string[];
36
+ /** A bulb found sitting "naked" in prose — frontmatter and blocks dumped straight into the text with no
37
+ * enclosing ````bulb```` fence. `start`/`end` are the half-open `[start, end)` line range (0-based, into
38
+ * `content.split('\n')`); `source` is that slice, ready to feed back to `parseBulb` or a renderer. */
39
+ export interface EmbeddedBulb {
40
+ start: number;
41
+ end: number;
42
+ source: string;
43
+ }
44
+ /**
45
+ * Find bulbs embedded unfenced in arbitrary prose. The normal path wraps a bulb in a ````bulb```` fence
46
+ * (and the mislabel-tolerant host promotes a fence whose body parses); but some non-SOTA models — Kimi
47
+ * notably — skip the fence entirely and dump the raw frontmatter + blocks into the message, using `---`
48
+ * thematic breaks as ad-hoc delimiters, so no fence token ever wraps the bulb. This scans for that.
49
+ *
50
+ * The frontmatter gate (`---\nformat: typebulb…`) is the same near-zero-false-positive signal the fenced
51
+ * mislabel tolerance leans on, so we anchor on a `---` line, run `parseBulb` from there, and accept it
52
+ * only if it yields at least one real block. The extent is `parseBulb`'s own `bodyEndLine` (just past the
53
+ * last captured block) — NOT end-of-text — so trailing prose after the bulb (Kimi's closing `---`, a
54
+ * follow-up paragraph) stays prose instead of being swallowed into the embed. Returned spans are
55
+ * non-overlapping and in document order; the caller slices the surrounding prose around them.
56
+ */
57
+ export declare function findEmbeddedBulbs(content: string): EmbeddedBulb[];
28
58
  /** Convert a parsed bulb to a structured per-kind object (missing blocks become ''). */
29
59
  export declare function toBulbData(parsed: ParsedBulb): BulbData;
30
60
  //# 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;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"}
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;IAClB;;;;;;OAMG;IACH,WAAW,EAAE,MAAM,CAAA;CACpB;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,CAkE5D;AA6CD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAE/D;AAED;;sGAEsG;AACtG,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,MAAM,CAAA;CACf;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,EAAE,CAkBjE;AAED,wFAAwF;AACxF,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,QAAQ,CAKvD"}
@@ -29,6 +29,9 @@ export function parseBulb(content) {
29
29
  // Parse file sections
30
30
  const files = new Map();
31
31
  const warnings = [];
32
+ // Where the body ends: bumped to the line past each captured block's closing fence. Starts at the
33
+ // first line after the frontmatter, so a block-less bulb reports that.
34
+ let bodyEndLine = i;
32
35
  while (i < lines.length) {
33
36
  const line = lines[i]?.trim();
34
37
  // Look for **filename** (bold markdown, tolerant of whitespace)
@@ -56,12 +59,13 @@ export function parseBulb(content) {
56
59
  i++; // Skip closing fence (no-op past EOF)
57
60
  warnings.push(...blockWarnings(filename, contentLines, terminated));
58
61
  files.set(filename, contentLines.join('\n'));
62
+ bodyEndLine = i;
59
63
  }
60
64
  else {
61
65
  i++;
62
66
  }
63
67
  }
64
- return { frontmatter, files, warnings };
68
+ return { frontmatter, files, warnings, bodyEndLine };
65
69
  }
66
70
  catch {
67
71
  return null;
@@ -123,6 +127,42 @@ function parseFrontmatter(lines) {
123
127
  export function validateBulbStructure(content) {
124
128
  return parseBulb(content)?.warnings ?? [];
125
129
  }
130
+ /**
131
+ * Find bulbs embedded unfenced in arbitrary prose. The normal path wraps a bulb in a ````bulb```` fence
132
+ * (and the mislabel-tolerant host promotes a fence whose body parses); but some non-SOTA models — Kimi
133
+ * notably — skip the fence entirely and dump the raw frontmatter + blocks into the message, using `---`
134
+ * thematic breaks as ad-hoc delimiters, so no fence token ever wraps the bulb. This scans for that.
135
+ *
136
+ * The frontmatter gate (`---\nformat: typebulb…`) is the same near-zero-false-positive signal the fenced
137
+ * mislabel tolerance leans on, so we anchor on a `---` line, run `parseBulb` from there, and accept it
138
+ * only if it yields at least one real block. The extent is `parseBulb`'s own `bodyEndLine` (just past the
139
+ * last captured block) — NOT end-of-text — so trailing prose after the bulb (Kimi's closing `---`, a
140
+ * follow-up paragraph) stays prose instead of being swallowed into the embed. Returned spans are
141
+ * non-overlapping and in document order; the caller slices the surrounding prose around them.
142
+ */
143
+ export function findEmbeddedBulbs(content) {
144
+ const lines = content.split('\n');
145
+ const found = [];
146
+ let i = 0;
147
+ while (i < lines.length) {
148
+ if (lines[i]?.trim() !== '---') {
149
+ i++;
150
+ continue;
151
+ }
152
+ const parsed = parseBulb(lines.slice(i).join('\n'));
153
+ // Require at least one captured block: a lone `---…---` frontmatter region with no blocks isn't a
154
+ // renderable bulb (and `bodyEndLine` would be the frontmatter end — an empty slice).
155
+ if (parsed && parsed.files.size > 0) {
156
+ const end = i + parsed.bodyEndLine;
157
+ found.push({ start: i, end, source: lines.slice(i, end).join('\n') });
158
+ i = end;
159
+ }
160
+ else {
161
+ i++;
162
+ }
163
+ }
164
+ return found;
165
+ }
126
166
  /** Convert a parsed bulb to a structured per-kind object (missing blocks become ''). */
127
167
  export function toBulbData(parsed) {
128
168
  const kinds = Object.fromEntries(orderedKinds.map(kind => [kind, parsed.files.get(blocks[kind].path) || '']));
@@ -1 +1 @@
1
- {"version":3,"file":"parse.js","sourceRoot":"","sources":["../../format/src/parse.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"parse.js","sourceRoot":"","sources":["../../format/src/parse.ts"],"names":[],"mappings":"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"}