typebulb 0.24.3 → 0.26.1

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.
@@ -2217,7 +2217,7 @@ var Patcher = class _Patcher {
2217
2217
 
2218
2218
  // cli/agents/pi/server/piPatcherExtension.ts
2219
2219
  var DESCRIPTION = true ? "Apply unified diffs to files \u2014 tolerant of form, strict about intent. Repairs sloppy AI-generated diffs (mangled headers, whitespace drift, missing prefixes; line numbers can be wrong or absent \u2014 hunks anchor by fuzzy-matched context lines) and applies all hunks atomically when the intent is unambiguous; fails with a precise, typed error when it isn't. Use for multi-hunk edits in one step, or when exact string-replacement editing fails on whitespace or invisible characters." : "Apply unified diffs to files.";
2220
- var BUILD_TAG = true ? "matchu-patchu-pi 0.2.0, built 2026-07-13 08:46:55" : "matchu-patchu-pi dev";
2220
+ var BUILD_TAG = true ? "matchu-patchu-pi 0.2.0, built 2026-07-15 08:57:22" : "matchu-patchu-pi dev";
2221
2221
  var errorBlocks = (errors) => {
2222
2222
  const parts = [`Patch failed with ${errors.length} error(s):`];
2223
2223
  for (const e of errors) parts.push("", e.toString());
@@ -178,13 +178,13 @@ body {
178
178
  session list). Wrap = positioning context; the popover anchors bottom/right and
179
179
  grows up-and-left — the chips sit in the right-aligned cluster, so left:0 would
180
180
  run them off the viewport's right edge. */
181
- .token-wrap, .sid-wrap, .servers-wrap, .model-wrap { position: relative; display: inline-block; }
181
+ .token-wrap, .sid-wrap, .servers-wrap, .model-wrap, .gitdiff-wrap { position: relative; display: inline-block; }
182
182
  /* Each pill renders its wrap unconditionally, emitting an empty div when it has
183
183
  nothing to show (no tokens / no session / nothing running). An empty wrap is
184
184
  still a flex child, so .statusbar-actions' gap lands on both its sides —
185
185
  doubling the visible gap between its neighbours. Collapse the empties so the
186
186
  cluster spaces evenly regardless of which pills are present. */
187
- .token-wrap:empty, .sid-wrap:empty, .servers-wrap:empty, .model-wrap:empty { display: none; }
187
+ .token-wrap:empty, .sid-wrap:empty, .servers-wrap:empty, .model-wrap:empty, .gitdiff-wrap:empty { display: none; }
188
188
  .picker, .servers-pop {
189
189
  --menu-h: 428px; /* one height for both statusbar menus — they sit side by side, so a
190
190
  mismatched cap reads as a glitch; .picker grows to it, .servers-pop
@@ -913,6 +913,73 @@ a.server-port:hover { text-decoration: underline; }
913
913
  color: var(--fg);
914
914
  }
915
915
  .bulb-log-text { white-space: pre-wrap; word-break: break-word; }
916
+
917
+ /* ── Git diff pill + menu (TB-Agent-Mirror.md): a `± N` chip (custom two-color glyph, icons.ts, +
918
+ changed-file count) that exists only when the tree is dirty — presence is the signal, so the glyph
919
+ keeps its red/green at rest (no grayscale: the chip can't be "idle", a clean tree removes it) and
920
+ the accent border stays reserved for latched, like every pill. Picking a menu row swaps the
921
+ transcript for a full-context unified diff. Flex like the square glyph pills (an svg mis-seats
922
+ under the word-pill text-box trim), width freed for the count. ── */
923
+ /* Three classes to out-specify .pill.glyph's fixed square (width: var(--pill-h); padding: 0) —
924
+ this is the one glyph pill that carries content beside its icon, so its width must be free. */
925
+ .pill.glyph.gitdiff-pill { width: auto; padding: 0 .45rem; gap: .3rem; }
926
+ /* 2:3, the cropped viewBox's aspect — a square box would re-add the side margins. */
927
+ .gitdiff-pill .icon { width: 8px; height: 12px; }
928
+ .gitdiff-count { font-size: var(--pill-font); font-variant-numeric: tabular-nums; }
929
+ .gitdiff-pop { width: min(480px, calc(100vw - 2rem)); }
930
+ .gitdiff-list { display: flex; flex-direction: column; gap: .15rem; flex: 1; min-height: 0; overflow-y: auto; padding-right: 4px; }
931
+ .gitdiff-row { display: flex; align-items: center; gap: .55rem; flex: none; min-height: var(--menu-row-h); padding: .05rem .45rem; border-radius: 6px; font-size: .85rem; cursor: pointer; }
932
+ .gitdiff-row:hover { background: color-mix(in srgb, var(--accent) 10%, transparent); }
933
+ .gitdiff-row.active { background: color-mix(in srgb, var(--accent) 16%, transparent); }
934
+ .gitdiff-row.viewing .gitdiff-path { color: var(--accent); }
935
+ /* One status letter, VS Code's palette: modified/renamed amber, added/untracked green, deleted red. */
936
+ .gitdiff-status { flex: none; width: 1rem; text-align: center; font: 600 .74rem ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; color: var(--muted); }
937
+ .gitdiff-status.s-M, .gitdiff-status.s-R { color: var(--warn); }
938
+ .gitdiff-status.s-A, .gitdiff-status.s-U { color: var(--diff-add); }
939
+ .gitdiff-status.s-D { color: var(--err); }
940
+ .gitdiff-path { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
941
+ .gitdiff-counts { flex: none; display: inline-flex; gap: .35rem; font-size: .72rem; font-variant-numeric: tabular-nums; }
942
+ .gitdiff-counts .count-add { color: var(--diff-add); }
943
+ .gitdiff-counts .count-del { color: var(--err); }
944
+
945
+ /* The diff doc — takes the transcript's slot in .chat (same flex geometry as .messages). Full-bleed
946
+ like a code surface (no --content-max column: diff lines want the width); the body is the scroll
947
+ surface, its bottom padding clearing the overlaid statusbar like .messages' does. The ± markers and
948
+ red/green bands are the shared .udiff-* rules the tool cards use. */
949
+ .diff-doc { flex: 1; min-height: 0; display: flex; flex-direction: column; outline: none; }
950
+ .diff-doc-head { display: flex; align-items: center; gap: .6rem; padding: .5rem 1.75rem .4rem; font-size: .8rem; border-bottom: 1px solid var(--border); }
951
+ .diff-doc-path { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--accent); cursor: pointer; }
952
+ .diff-doc-path:hover { text-decoration: underline; }
953
+ .diff-doc-head .bulb-log-back { margin-left: auto; }
954
+ .diff-doc-body {
955
+ flex: 1; min-height: 0; overflow: auto;
956
+ scrollbar-gutter: stable both-edges;
957
+ padding: .75rem 1.75rem 2.5rem;
958
+ font: .78rem/1.5 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
959
+ white-space: pre-wrap; word-break: break-word;
960
+ }
961
+ .diff-doc-empty, .diff-doc-trunc { color: var(--muted); padding: .4rem 0; }
962
+ /* The wrong-cwd empty state (Root.#cwdHint): centered over the empty transcript. */
963
+ .cwd-hint { position: absolute; inset: 0; display: grid; place-content: center; text-align: center; gap: .5rem; padding: 2rem; color: var(--muted); font-size: .9rem; max-width: 40rem; margin-inline: auto; }
964
+ .cwd-hint-head { font-weight: 600; color: var(--fg); }
965
+ .cwd-hint-dir { color: var(--accent); }
966
+ /* With token colors under them, the full-strength (24%) bands compete — red tokens on a red band
967
+ turn to mud — so the doc view's bands drop to a tint: polarity is still carried per-line by the
968
+ gutter ± glyphs and at file scale by the ruler. Scoped: the tool-card hunks keep 24%, where the
969
+ unhighlighted band is the only signal. Del a touch stronger than add — red-leaning tokens
970
+ camouflage against red tint more than anything does against green. */
971
+ .diff-doc-body .udiff-add { background: color-mix(in srgb, var(--diff-add) 10%, transparent); }
972
+ .diff-doc-body .udiff-del { background: color-mix(in srgb, var(--err) 13%, transparent); }
973
+ /* The overview ruler — VS Code's scrollbar change-marks, owned since the native scrollbar can't be
974
+ painted: a thin track beside the scrollbar (17px clears Windows Chromium's classic bar — plain px
975
+ on a desktop-only surface, the menus' own stance), red/green marks at each change run's fractional
976
+ position, min-height so a one-line change stays visible. The wrapper keeps it overlaid rather than
977
+ scrolling with the body. Marks are pointer-inert so a click anywhere on the track jumps. */
978
+ .diff-doc-scroll { position: relative; flex: 1; min-height: 0; display: flex; flex-direction: column; }
979
+ .diff-ruler { position: absolute; top: 2px; bottom: 2px; right: 17px; width: 6px; cursor: pointer; z-index: 5; }
980
+ .diff-ruler-mark { position: absolute; left: 0; right: 0; min-height: 3px; border-radius: 1px; pointer-events: none; }
981
+ .diff-ruler-mark.add { background: var(--diff-add); opacity: .8; }
982
+ .diff-ruler-mark.del { background: var(--err); opacity: .8; }
916
983
  /* messages */
917
984
  .messages {
918
985
  flex: 1;
@@ -1364,24 +1431,25 @@ html[data-theme="dark"] .masthead-logo.dark { display: block; }
1364
1431
  background: transparent;
1365
1432
  overflow-x: auto;
1366
1433
  }
1367
- /* hljs token colors for the code view, mapped to the bulb's own theme vars (no hljs
1434
+ /* hljs token colors for the code view AND the diff doc (one palette, or the same file reads as two
1435
+ languages across surfaces), mapped to the bulb's own theme vars (no hljs
1368
1436
  theme stylesheet) so highlighting follows light/dark rather than baking a palette
1369
1437
  that would clash in dark mode. Minimal token set — enough for legible TS/HTML/CSS/
1370
1438
  JSON/markdown without chasing every grammar scope. */
1371
- .bulb-code .hljs-comment, .bulb-code .hljs-quote { color: var(--muted); font-style: italic; }
1372
- .bulb-code .hljs-keyword, .bulb-code .hljs-literal, .bulb-code .hljs-built_in { color: var(--accent); }
1373
- .bulb-code .hljs-tag, .bulb-code .hljs-name, .bulb-code .hljs-selector-tag { color: var(--accent); }
1374
- .bulb-code .hljs-string, .bulb-code .hljs-regexp, .bulb-code .hljs-meta .hljs-string {
1439
+ .bulb-code .hljs-comment, .diff-doc-body .hljs-comment, .bulb-code .hljs-quote, .diff-doc-body .hljs-quote { color: var(--muted); font-style: italic; }
1440
+ .bulb-code .hljs-keyword, .diff-doc-body .hljs-keyword, .bulb-code .hljs-literal, .diff-doc-body .hljs-literal, .bulb-code .hljs-built_in, .diff-doc-body .hljs-built_in { color: var(--accent); }
1441
+ .bulb-code .hljs-tag, .diff-doc-body .hljs-tag, .bulb-code .hljs-name, .diff-doc-body .hljs-name, .bulb-code .hljs-selector-tag, .diff-doc-body .hljs-selector-tag { color: var(--accent); }
1442
+ .bulb-code .hljs-string, .diff-doc-body .hljs-string, .bulb-code .hljs-regexp, .diff-doc-body .hljs-regexp, .bulb-code .hljs-meta .hljs-string, .diff-doc-body .hljs-meta .hljs-string {
1375
1443
  color: color-mix(in srgb, var(--diff-add) 85%, var(--fg));
1376
1444
  }
1377
- .bulb-code .hljs-number { color: color-mix(in srgb, var(--accent) 55%, var(--fg)); }
1378
- .bulb-code .hljs-attr, .bulb-code .hljs-attribute, .bulb-code .hljs-property, .bulb-code .hljs-type {
1445
+ .bulb-code .hljs-number, .diff-doc-body .hljs-number { color: color-mix(in srgb, var(--accent) 55%, var(--fg)); }
1446
+ .bulb-code .hljs-attr, .diff-doc-body .hljs-attr, .bulb-code .hljs-attribute, .diff-doc-body .hljs-attribute, .bulb-code .hljs-property, .diff-doc-body .hljs-property, .bulb-code .hljs-type, .diff-doc-body .hljs-type {
1379
1447
  color: color-mix(in srgb, var(--accent) 75%, var(--fg));
1380
1448
  }
1381
- .bulb-code .hljs-title, .bulb-code .hljs-title.function_, .bulb-code .hljs-section {
1449
+ .bulb-code .hljs-title, .diff-doc-body .hljs-title, .bulb-code .hljs-title.function_, .diff-doc-body .hljs-title.function_, .bulb-code .hljs-section, .diff-doc-body .hljs-section {
1382
1450
  color: var(--fg); font-weight: 600;
1383
1451
  }
1384
- .bulb-code .hljs-symbol, .bulb-code .hljs-bullet, .bulb-code .hljs-punctuation { color: var(--muted); }
1452
+ .bulb-code .hljs-symbol, .diff-doc-body .hljs-symbol, .bulb-code .hljs-bullet, .diff-doc-body .hljs-bullet, .bulb-code .hljs-punctuation, .diff-doc-body .hljs-punctuation { color: var(--muted); }
1385
1453
  /* Draft-streaming bulb card (#draftBulbCard): the code view wearing a progress header — never a
1386
1454
  live mount; the durable row's BulbEmbed takes this slot when the entry lands. Cap tighter than
1387
1455
  .bulb-code's resting 480px: ambient progress, not reading material. */
@@ -2,6 +2,7 @@ export * from './protocol.js';
2
2
  export { AIProvider, ProviderStreamError, type ChatRequestOpts } from './aiProvider.js';
3
3
  export { getProvider, sendAIRequest, normalizeUpstreamError, type ResolvedAIProvider, type SendAIRequestOpts } from './aiProviders.js';
4
4
  export { parseSseBlock, consumeSseStream, consumeSseStreamGen, consumeStreamText, streamAiChunks } from './sseParser.js';
5
+ export { buildInferencePrompt, sanitizeJsonOutput, encodeToHash, decodeFromHash, hashContainsTb, type InferenceScriptContent, type SanitizeResult, type InferenceResult } from './inference.js';
5
6
  export * from './providers/chatCompletions.js';
6
7
  export * from './providers/anthropic.js';
7
8
  export * from './providers/gemini.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../ai/src/index.ts"],"names":[],"mappings":"AACA,cAAc,eAAe,CAAA;AAE7B,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACvF,OAAO,EACL,WAAW,EACX,aAAa,EACb,sBAAsB,EACtB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACvB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAGxH,cAAc,gCAAgC,CAAA;AAC9C,cAAc,0BAA0B,CAAA;AACxC,cAAc,uBAAuB,CAAA;AACrC,cAAc,uBAAuB,CAAA;AACrC,cAAc,2BAA2B,CAAA;AACzC,cAAc,uBAAuB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../ai/src/index.ts"],"names":[],"mappings":"AACA,cAAc,eAAe,CAAA;AAE7B,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACvF,OAAO,EACL,WAAW,EACX,aAAa,EACb,sBAAsB,EACtB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACvB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAGxH,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,YAAY,EACZ,cAAc,EACd,cAAc,EACd,KAAK,sBAAsB,EAC3B,KAAK,cAAc,EACnB,KAAK,eAAe,EACrB,MAAM,gBAAgB,CAAA;AAGvB,cAAc,gCAAgC,CAAA;AAC9C,cAAc,0BAA0B,CAAA;AACxC,cAAc,uBAAuB,CAAA;AACrC,cAAc,uBAAuB,CAAA;AACrC,cAAc,2BAA2B,CAAA;AACzC,cAAc,uBAAuB,CAAA"}
package/dist/ai/index.js CHANGED
@@ -3,6 +3,8 @@ export * from './protocol.js';
3
3
  export { AIProvider, ProviderStreamError } from './aiProvider.js';
4
4
  export { getProvider, sendAIRequest, normalizeUpstreamError } from './aiProviders.js';
5
5
  export { parseSseBlock, consumeSseStream, consumeSseStreamGen, consumeStreamText, streamAiChunks } from './sseParser.js';
6
+ // Inference layer shared with typebulb.com: prompt template, JSON sanitizer, #tb= result encoding.
7
+ export { buildInferencePrompt, sanitizeJsonOutput, encodeToHash, decodeFromHash, hashContainsTb } from './inference.js';
6
8
  // Per-provider wire DTOs + provider implementations.
7
9
  export * from './providers/chatCompletions.js';
8
10
  export * from './providers/anthropic.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../ai/src/index.ts"],"names":[],"mappings":"AAAA,qFAAqF;AACrF,cAAc,eAAe,CAAA;AAE7B,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAwB,MAAM,iBAAiB,CAAA;AACvF,OAAO,EACL,WAAW,EACX,aAAa,EACb,sBAAsB,EAGvB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAExH,qDAAqD;AACrD,cAAc,gCAAgC,CAAA;AAC9C,cAAc,0BAA0B,CAAA;AACxC,cAAc,uBAAuB,CAAA;AACrC,cAAc,uBAAuB,CAAA;AACrC,cAAc,2BAA2B,CAAA;AACzC,cAAc,uBAAuB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../ai/src/index.ts"],"names":[],"mappings":"AAAA,qFAAqF;AACrF,cAAc,eAAe,CAAA;AAE7B,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAwB,MAAM,iBAAiB,CAAA;AACvF,OAAO,EACL,WAAW,EACX,aAAa,EACb,sBAAsB,EAGvB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAExH,mGAAmG;AACnG,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,YAAY,EACZ,cAAc,EACd,cAAc,EAIf,MAAM,gBAAgB,CAAA;AAEvB,qDAAqD;AACrD,cAAc,gCAAgC,CAAA;AAC9C,cAAc,0BAA0B,CAAA;AACxC,cAAc,uBAAuB,CAAA;AACrC,cAAc,uBAAuB,CAAA;AACrC,cAAc,2BAA2B,CAAA;AACzC,cAAc,uBAAuB,CAAA"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Inference layer shared by typebulb.com and the CLI (TB-Inference.md): the prompt template,
3
+ * the LLM-output JSON sanitizer, and the `#tb=` result encoding. Single-sourced here so the two
4
+ * surfaces may differ in UX but never in what is sent, how output is repaired, or how a result
5
+ * is encoded for sharing.
6
+ */
7
+ export interface InferenceScriptContent {
8
+ /** Inference instructions (markdown) */
9
+ infer?: string;
10
+ /** Example insight output (JSON string) */
11
+ insight?: string;
12
+ /** Script code that will consume the output */
13
+ code?: string;
14
+ }
15
+ /**
16
+ * Build the inference prompt from script content and data
17
+ */
18
+ export declare function buildInferencePrompt(script: InferenceScriptContent, data: string[]): string;
19
+ export interface SanitizeResult {
20
+ parsed: unknown | null;
21
+ json: string;
22
+ fixesApplied: string[];
23
+ }
24
+ /**
25
+ * Attempt to parse JSON, applying conservative fixes for common LLM errors
26
+ */
27
+ export declare function sanitizeJsonOutput(content: string): SanitizeResult;
28
+ /** The result of an inference run: the AI's insight plus the data it analyzed */
29
+ export interface InferenceResult {
30
+ insight: unknown;
31
+ insightJson: string;
32
+ data: string[];
33
+ }
34
+ /** Encode result to URL hash. Returns "#tb=1:..." or empty string if too large. */
35
+ export declare function encodeToHash(result: InferenceResult): string;
36
+ /** Decode result from URL hash. Returns null if no result or decode fails. */
37
+ export declare function decodeFromHash(hash: string): InferenceResult | null;
38
+ /** Check if hash contains a tb= fragment (for error detection) */
39
+ export declare function hashContainsTb(hash: string): boolean;
40
+ //# sourceMappingURL=inference.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inference.d.ts","sourceRoot":"","sources":["../../ai/src/inference.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,MAAM,WAAW,sBAAsB;IACrC,wCAAwC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,2CAA2C;IAC3C,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,+CAA+C;IAC/C,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,sBAAsB,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAoC3F;AAMD,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,OAAO,GAAG,IAAI,CAAA;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,YAAY,EAAE,MAAM,EAAE,CAAA;CACvB;AA8GD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CA+DlE;AAID,iFAAiF;AACjF,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,MAAM,EAAE,CAAA;CACf;AAWD,mFAAmF;AACnF,wBAAgB,YAAY,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,CAa5D;AAED,8EAA8E;AAC9E,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAwBnE;AAED,kEAAkE;AAClE,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEpD"}
@@ -0,0 +1,301 @@
1
+ /**
2
+ * Inference layer shared by typebulb.com and the CLI (TB-Inference.md): the prompt template,
3
+ * the LLM-output JSON sanitizer, and the `#tb=` result encoding. Single-sourced here so the two
4
+ * surfaces may differ in UX but never in what is sent, how output is repaired, or how a result
5
+ * is encoded for sharing.
6
+ */
7
+ import { strToU8, strFromU8, deflateSync, inflateSync } from 'fflate';
8
+ /**
9
+ * Build the inference prompt from script content and data
10
+ */
11
+ export function buildInferencePrompt(script, data) {
12
+ const parts = [];
13
+ parts.push(`You are a data processor. Follow the instructions to analyze the provided data. Output valid JSON that the code can consume.
14
+
15
+ ---
16
+ Instructions:
17
+ ${script.infer || 'Process the data and return a JSON object.'}`);
18
+ if (script.insight) {
19
+ parts.push(`---
20
+ Example output:
21
+ ${script.insight}`);
22
+ }
23
+ if (script.code) {
24
+ parts.push(`---
25
+ Code that will consume your output:
26
+ ${script.code}`);
27
+ }
28
+ if (data.length > 0) {
29
+ const dataContent = data.length === 1
30
+ ? data[0]
31
+ : data.map((chunk, i) => `[Chunk ${i + 1}]\n${chunk}`).join('\n\n');
32
+ parts.push(`---
33
+ Data to process:
34
+ <data>
35
+ ${dataContent}
36
+ </data>`);
37
+ }
38
+ parts.push(`
39
+ Output only valid JSON. No explanation, no markdown fences, just the JSON object. Every number must be a JSON literal — never an expression like 2 * pi; write the computed decimal instead.`);
40
+ return parts.join('\n\n');
41
+ }
42
+ /** Try to parse, return result or null */
43
+ function tryParse(json) {
44
+ try {
45
+ return JSON.parse(json);
46
+ }
47
+ catch {
48
+ return null;
49
+ }
50
+ }
51
+ /** Sanitization strategies: [name, fix function] */
52
+ const strategies = [
53
+ ['orphan quote', (s) => { const f = s.replace(/^[ \t]*"[ \t]*\r?\n/gm, ''); return f !== s ? f : null; }],
54
+ ['trailing }', (s) => s.endsWith('}}') ? s.slice(0, -1) : null],
55
+ ['trailing ]', (s) => s.endsWith(']]') ? s.slice(0, -1) : null],
56
+ ['trailing },', (s) => s.endsWith('},') ? s.slice(0, -1) : null],
57
+ ['trailing ],', (s) => s.endsWith('],') ? s.slice(0, -1) : null],
58
+ ['trailing comma in object', (s) => s.match(/,\s*\}$/) ? s.replace(/,\s*\}$/, '}') : null],
59
+ ['trailing comma in array', (s) => s.match(/,\s*\]$/) ? s.replace(/,\s*\]$/, ']') : null],
60
+ ['arithmetic constants', foldArithmeticConstants],
61
+ ];
62
+ /** Apply fn to the segments of near-JSON text that lie OUTSIDE string literals. */
63
+ function mapOutsideStrings(text, fn) {
64
+ let out = '';
65
+ let segStart = 0;
66
+ let inString = false;
67
+ let escape = false;
68
+ for (let i = 0; i < text.length; i++) {
69
+ const c = text[i];
70
+ if (escape) {
71
+ escape = false;
72
+ continue;
73
+ }
74
+ if (c === '\\') {
75
+ escape = true;
76
+ continue;
77
+ }
78
+ if (c === '"') {
79
+ if (inString) {
80
+ out += text.slice(segStart, i + 1);
81
+ segStart = i + 1;
82
+ }
83
+ else {
84
+ out += fn(text.slice(segStart, i)) + '"';
85
+ segStart = i + 1;
86
+ }
87
+ inString = !inString;
88
+ }
89
+ }
90
+ out += inString ? text.slice(segStart) : fn(text.slice(segStart));
91
+ return out;
92
+ }
93
+ /** Fold constant arithmetic in value position — "range": [0, 4 * pi] — into JSON number literals.
94
+ * Cheap models routinely emit these, and the free tier runs on cheap models, so absorbing the
95
+ * artifact is load-bearing. Conservative like every strategy: only wins if the result parses, and
96
+ * string contents are never touched (a "period of 2*pi radians" explanation stays verbatim). */
97
+ function foldArithmeticConstants(s) {
98
+ const folded = mapOutsideStrings(s, (seg) => seg
99
+ // Standalone constants first ("1e3" has no word boundary before its e, so exponents survive).
100
+ .replace(/\bpi\b/g, '3.141592653589793')
101
+ .replace(/\be\b/g, '2.718281828459045')
102
+ // Fold a run only if it actually computes: contains an operator between operands.
103
+ .replace(/-?\d[\d.\s+\-*/()]*\d|\(-?\d[\d.\s+\-*/()]*\d\)/g, (run) => {
104
+ if (!/[+\-*/]/.test(run.replace(/^-/, '')) || run.length > 64)
105
+ return run;
106
+ if (!/^[\d\s.+\-*/()]+$/.test(run))
107
+ return run;
108
+ try {
109
+ const v = Function(`"use strict"; return (${run})`)();
110
+ return typeof v === 'number' && Number.isFinite(v) ? String(v) : run;
111
+ }
112
+ catch {
113
+ return run;
114
+ }
115
+ }));
116
+ return folded !== s ? folded : null;
117
+ }
118
+ /** Find the end index of a balanced {...} or [...] starting at `start`.
119
+ * String-aware (so braces inside JSON string literals don't count).
120
+ * Returns -1 if unbalanced. */
121
+ function findBalancedEnd(text, start) {
122
+ let depth = 0;
123
+ let inString = false;
124
+ let escape = false;
125
+ for (let i = start; i < text.length; i++) {
126
+ const c = text[i];
127
+ if (escape) {
128
+ escape = false;
129
+ continue;
130
+ }
131
+ if (c === '\\') {
132
+ escape = true;
133
+ continue;
134
+ }
135
+ if (c === '"') {
136
+ inString = !inString;
137
+ continue;
138
+ }
139
+ if (inString)
140
+ continue;
141
+ if (c === '{' || c === '[')
142
+ depth++;
143
+ else if (c === '}' || c === ']') {
144
+ depth--;
145
+ if (depth === 0)
146
+ return i;
147
+ }
148
+ }
149
+ return -1;
150
+ }
151
+ /** Scan for top-level balanced JSON values and return the last one that parses.
152
+ * Handles the case where a strong model with no thinking budget emits visible
153
+ * self-correction in the text channel — e.g. draft → "wait, reconsider" →
154
+ * revised JSON. The final value is essentially always the intended answer. */
155
+ function findLastValidJson(text) {
156
+ let last = null;
157
+ let i = 0;
158
+ while (i < text.length) {
159
+ const c = text[i];
160
+ if (c === '{' || c === '[') {
161
+ const end = findBalancedEnd(text, i);
162
+ if (end !== -1) {
163
+ const candidate = text.slice(i, end + 1);
164
+ const parsed = tryParse(candidate);
165
+ if (parsed !== null)
166
+ last = { parsed, json: candidate };
167
+ i = end + 1;
168
+ continue;
169
+ }
170
+ }
171
+ i++;
172
+ }
173
+ return last;
174
+ }
175
+ /**
176
+ * Attempt to parse JSON, applying conservative fixes for common LLM errors
177
+ */
178
+ export function sanitizeJsonOutput(content) {
179
+ const fixesApplied = [];
180
+ let json = content.trim();
181
+ // Strip markdown fences (common LLM behavior despite instructions)
182
+ if (json.startsWith('```')) {
183
+ json = json.replace(/^```(?:json)?\s*\n?/, '').replace(/\n?```\s*$/, '');
184
+ fixesApplied.push('markdown fences');
185
+ }
186
+ // Try parsing as-is
187
+ let parsed = tryParse(json);
188
+ if (parsed !== null) {
189
+ return { parsed, json, fixesApplied };
190
+ }
191
+ // Extract from embedded markdown fences (reasoning/preamble text before ```json block)
192
+ const fenceMatch = json.match(/```(?:json)?\s*\n([\s\S]*?)\n?```\s*$/);
193
+ if (fenceMatch) {
194
+ json = fenceMatch[1].trim();
195
+ fixesApplied.push('preamble before fenced JSON');
196
+ parsed = tryParse(json);
197
+ if (parsed !== null) {
198
+ return { parsed, json, fixesApplied };
199
+ }
200
+ }
201
+ // Strip preamble text before bare JSON (find first { or [)
202
+ if (!json.startsWith('{') && !json.startsWith('[')) {
203
+ const objIdx = json.indexOf('{');
204
+ const arrIdx = json.indexOf('[');
205
+ const idx = objIdx >= 0 && arrIdx >= 0 ? Math.min(objIdx, arrIdx) :
206
+ objIdx >= 0 ? objIdx : arrIdx;
207
+ if (idx > 0) {
208
+ json = json.slice(idx);
209
+ fixesApplied.push('preamble text');
210
+ parsed = tryParse(json);
211
+ if (parsed !== null) {
212
+ return { parsed, json, fixesApplied };
213
+ }
214
+ }
215
+ }
216
+ // Try each sanitization strategy (operates on cleaned json from above)
217
+ for (const [name, fix] of strategies) {
218
+ const fixed = fix(json);
219
+ if (fixed !== null) {
220
+ const parsed = tryParse(fixed);
221
+ if (parsed !== null) {
222
+ return { parsed, json: fixed, fixesApplied: [...fixesApplied, name] };
223
+ }
224
+ }
225
+ }
226
+ // Final fallback: scan the original content for the last syntactically
227
+ // complete JSON value. Catches the "model emitted draft + revision in text"
228
+ // pattern that the linear strategies above can't handle.
229
+ const found = findLastValidJson(content);
230
+ if (found !== null) {
231
+ return { ...found, fixesApplied: [...fixesApplied, 'extracted last JSON value'] };
232
+ }
233
+ return { parsed: null, json, fixesApplied };
234
+ }
235
+ const TB_PREFIX = 'tb=';
236
+ const TB_VERSION = '1';
237
+ const MAX_ENCODED_LENGTH = 60000; // ~60KB; Firefox's ~64K URL limit is the cross-browser floor
238
+ /** Encode result to URL hash. Returns "#tb=1:..." or empty string if too large. */
239
+ export function encodeToHash(result) {
240
+ try {
241
+ const payload = { i: result.insight, d: result.data };
242
+ const json = JSON.stringify(payload);
243
+ const compressed = deflateSync(strToU8(json), { level: 9 });
244
+ const base64 = base64UrlEncode(compressed);
245
+ const encoded = `${TB_VERSION}:${base64}`;
246
+ if (encoded.length > MAX_ENCODED_LENGTH)
247
+ return '';
248
+ return '#' + TB_PREFIX + encoded;
249
+ }
250
+ catch {
251
+ return '';
252
+ }
253
+ }
254
+ /** Decode result from URL hash. Returns null if no result or decode fails. */
255
+ export function decodeFromHash(hash) {
256
+ try {
257
+ const fragment = hash.startsWith('#') ? hash.slice(1) : hash;
258
+ if (!fragment.startsWith(TB_PREFIX))
259
+ return null;
260
+ const encoded = fragment.slice(TB_PREFIX.length);
261
+ const colonIndex = encoded.indexOf(':');
262
+ if (colonIndex === -1 || encoded.slice(0, colonIndex) !== TB_VERSION)
263
+ return null;
264
+ const compressed = base64UrlDecode(encoded.slice(colonIndex + 1));
265
+ const payload = JSON.parse(strFromU8(inflateSync(compressed)));
266
+ if (!payload || typeof payload.i === 'undefined' || !Array.isArray(payload.d)) {
267
+ return null;
268
+ }
269
+ return {
270
+ insight: payload.i,
271
+ insightJson: JSON.stringify(payload.i, null, 2),
272
+ data: payload.d
273
+ };
274
+ }
275
+ catch {
276
+ return null;
277
+ }
278
+ }
279
+ /** Check if hash contains a tb= fragment (for error detection) */
280
+ export function hashContainsTb(hash) {
281
+ return hash.includes('tb=');
282
+ }
283
+ function base64UrlEncode(bytes) {
284
+ let binary = '';
285
+ // Chunked: a single String.fromCharCode(...bytes) spread overflows the arg limit near 64K bytes.
286
+ for (let i = 0; i < bytes.length; i += 0x8000) {
287
+ binary += String.fromCharCode(...bytes.subarray(i, i + 0x8000));
288
+ }
289
+ return btoa(binary).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
290
+ }
291
+ function base64UrlDecode(str) {
292
+ let base64 = str.replace(/-/g, '+').replace(/_/g, '/');
293
+ while (base64.length % 4)
294
+ base64 += '=';
295
+ const binary = atob(base64);
296
+ const bytes = new Uint8Array(binary.length);
297
+ for (let i = 0; i < binary.length; i++)
298
+ bytes[i] = binary.charCodeAt(i);
299
+ return bytes;
300
+ }
301
+ //# sourceMappingURL=inference.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inference.js","sourceRoot":"","sources":["../../ai/src/inference.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAA;AAarE;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAA8B,EAAE,IAAc;IACjF,MAAM,KAAK,GAAa,EAAE,CAAA;IAE1B,KAAK,CAAC,IAAI,CAAC;;;;EAIX,MAAM,CAAC,KAAK,IAAI,4CAA4C,EAAE,CAAC,CAAA;IAE/D,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,KAAK,CAAC,IAAI,CAAC;;EAEb,MAAM,CAAC,OAAO,EAAE,CAAC,CAAA;IACjB,CAAC;IAED,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QAChB,KAAK,CAAC,IAAI,CAAC;;EAEb,MAAM,CAAC,IAAI,EAAE,CAAC,CAAA;IACd,CAAC;IAED,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpB,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,KAAK,CAAC;YACnC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;YACT,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QACrE,KAAK,CAAC,IAAI,CAAC;;;EAGb,WAAW;QACL,CAAC,CAAA;IACP,CAAC;IAED,KAAK,CAAC,IAAI,CAAC;6LACgL,CAAC,CAAA;IAE5L,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;AAC3B,CAAC;AAYD,0CAA0C;AAC1C,SAAS,QAAQ,CAAC,IAAY;IAC5B,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC;AAED,oDAAoD;AACpD,MAAM,UAAU,GAAkD;IAChE,CAAC,cAAc,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,uBAAuB,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA,CAAC,CAAC,CAAC;IACxG,CAAC,YAAY,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/D,CAAC,YAAY,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/D,CAAC,aAAa,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAChE,CAAC,aAAa,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAChE,CAAC,0BAA0B,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC1F,CAAC,yBAAyB,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACzF,CAAC,sBAAsB,EAAE,uBAAuB,CAAC;CAClD,CAAA;AAED,mFAAmF;AACnF,SAAS,iBAAiB,CAAC,IAAY,EAAE,EAA2B;IAClE,IAAI,GAAG,GAAG,EAAE,CAAA;IACZ,IAAI,QAAQ,GAAG,CAAC,CAAA;IAChB,IAAI,QAAQ,GAAG,KAAK,CAAA;IACpB,IAAI,MAAM,GAAG,KAAK,CAAA;IAClB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAE,CAAA;QAClB,IAAI,MAAM,EAAE,CAAC;YAAC,MAAM,GAAG,KAAK,CAAC;YAAC,SAAQ;QAAC,CAAC;QACxC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;YAAC,MAAM,GAAG,IAAI,CAAC;YAAC,SAAQ;QAAC,CAAC;QAC3C,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;YACd,IAAI,QAAQ,EAAE,CAAC;gBAAC,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;gBAAC,QAAQ,GAAG,CAAC,GAAG,CAAC,CAAA;YAAC,CAAC;iBACjE,CAAC;gBAAC,GAAG,IAAI,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;gBAAC,QAAQ,GAAG,CAAC,GAAG,CAAC,CAAA;YAAC,CAAC;YACnE,QAAQ,GAAG,CAAC,QAAQ,CAAA;QACtB,CAAC;IACH,CAAC;IACD,GAAG,IAAI,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAA;IACjE,OAAO,GAAG,CAAA;AACZ,CAAC;AAED;;;iGAGiG;AACjG,SAAS,uBAAuB,CAAC,CAAS;IACxC,MAAM,MAAM,GAAG,iBAAiB,CAAC,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG;QAC9C,8FAA8F;SAC7F,OAAO,CAAC,SAAS,EAAE,mBAAmB,CAAC;SACvC,OAAO,CAAC,QAAQ,EAAE,mBAAmB,CAAC;QACvC,kFAAkF;SACjF,OAAO,CAAC,kDAAkD,EAAE,CAAC,GAAG,EAAE,EAAE;QACnE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,GAAG,CAAC,MAAM,GAAG,EAAE;YAAE,OAAO,GAAG,CAAA;QACzE,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,GAAG,CAAC;YAAE,OAAO,GAAG,CAAA;QAC9C,IAAI,CAAC;YACH,MAAM,CAAC,GAAG,QAAQ,CAAC,yBAAyB,GAAG,GAAG,CAAC,EAAa,CAAA;YAChE,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAA;QACtE,CAAC;QAAC,MAAM,CAAC;YAAC,OAAO,GAAG,CAAA;QAAC,CAAC;IACxB,CAAC,CAAC,CAAC,CAAA;IACL,OAAO,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAA;AACrC,CAAC;AAED;;gCAEgC;AAChC,SAAS,eAAe,CAAC,IAAY,EAAE,KAAa;IAClD,IAAI,KAAK,GAAG,CAAC,CAAA;IACb,IAAI,QAAQ,GAAG,KAAK,CAAA;IACpB,IAAI,MAAM,GAAG,KAAK,CAAA;IAClB,KAAK,IAAI,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAE,CAAA;QAClB,IAAI,MAAM,EAAE,CAAC;YAAC,MAAM,GAAG,KAAK,CAAC;YAAC,SAAQ;QAAC,CAAC;QACxC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;YAAC,MAAM,GAAG,IAAI,CAAC;YAAC,SAAQ;QAAC,CAAC;QAC3C,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;YAAC,QAAQ,GAAG,CAAC,QAAQ,CAAC;YAAC,SAAQ;QAAC,CAAC;QACjD,IAAI,QAAQ;YAAE,SAAQ;QACtB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG;YAAE,KAAK,EAAE,CAAA;aAC9B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;YAChC,KAAK,EAAE,CAAA;YACP,IAAI,KAAK,KAAK,CAAC;gBAAE,OAAO,CAAC,CAAA;QAC3B,CAAC;IACH,CAAC;IACD,OAAO,CAAC,CAAC,CAAA;AACX,CAAC;AAED;;;+EAG+E;AAC/E,SAAS,iBAAiB,CAAC,IAAY;IACrC,IAAI,IAAI,GAA6C,IAAI,CAAA;IACzD,IAAI,CAAC,GAAG,CAAC,CAAA;IACT,OAAO,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QACvB,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAE,CAAA;QAClB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;YAC3B,MAAM,GAAG,GAAG,eAAe,CAAC,IAAI,EAAE,CAAC,CAAC,CAAA;YACpC,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC;gBACf,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,CAAA;gBACxC,MAAM,MAAM,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAA;gBAClC,IAAI,MAAM,KAAK,IAAI;oBAAE,IAAI,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,CAAA;gBACvD,CAAC,GAAG,GAAG,GAAG,CAAC,CAAA;gBACX,SAAQ;YACV,CAAC;QACH,CAAC;QACD,CAAC,EAAE,CAAA;IACL,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAe;IAChD,MAAM,YAAY,GAAa,EAAE,CAAA;IACjC,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,CAAA;IAEzB,mEAAmE;IACnE,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3B,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,qBAAqB,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAA;QACxE,YAAY,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAA;IACtC,CAAC;IAED,oBAAoB;IACpB,IAAI,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAA;IAC3B,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QACpB,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,CAAA;IACvC,CAAC;IAED,uFAAuF;IACvF,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAA;IACtE,IAAI,UAAU,EAAE,CAAC;QACf,IAAI,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;QAC3B,YAAY,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAA;QAChD,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAA;QACvB,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YACpB,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,CAAA;QACvC,CAAC;IACH,CAAC;IAED,2DAA2D;IAC3D,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACnD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QAChC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QAChC,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;YACvD,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAA;QACzC,IAAI,GAAG,GAAG,CAAC,EAAE,CAAC;YACZ,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;YACtB,YAAY,CAAC,IAAI,CAAC,eAAe,CAAC,CAAA;YAClC,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAA;YACvB,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;gBACpB,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,CAAA;YACvC,CAAC;QACH,CAAC;IACH,CAAC;IAED,uEAAuE;IACvE,KAAK,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,UAAU,EAAE,CAAC;QACrC,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,CAAA;QACvB,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACnB,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;YAC9B,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;gBACpB,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,GAAG,YAAY,EAAE,IAAI,CAAC,EAAE,CAAA;YACvE,CAAC;QACH,CAAC;IACH,CAAC;IAED,uEAAuE;IACvE,4EAA4E;IAC5E,yDAAyD;IACzD,MAAM,KAAK,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAA;IACxC,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,OAAO,EAAE,GAAG,KAAK,EAAE,YAAY,EAAE,CAAC,GAAG,YAAY,EAAE,2BAA2B,CAAC,EAAE,CAAA;IACnF,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,CAAA;AAC7C,CAAC;AAWD,MAAM,SAAS,GAAG,KAAK,CAAA;AACvB,MAAM,UAAU,GAAG,GAAG,CAAA;AACtB,MAAM,kBAAkB,GAAG,KAAK,CAAA,CAAE,6DAA6D;AAO/F,mFAAmF;AACnF,MAAM,UAAU,YAAY,CAAC,MAAuB;IAClD,IAAI,CAAC;QACH,MAAM,OAAO,GAAmB,EAAE,CAAC,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,EAAE,MAAM,CAAC,IAAI,EAAE,CAAA;QACrE,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAA;QACpC,MAAM,UAAU,GAAG,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAA;QAC3D,MAAM,MAAM,GAAG,eAAe,CAAC,UAAU,CAAC,CAAA;QAC1C,MAAM,OAAO,GAAG,GAAG,UAAU,IAAI,MAAM,EAAE,CAAA;QAEzC,IAAI,OAAO,CAAC,MAAM,GAAG,kBAAkB;YAAE,OAAO,EAAE,CAAA;QAClD,OAAO,GAAG,GAAG,SAAS,GAAG,OAAO,CAAA;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAA;IACX,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;QAC5D,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC;YAAE,OAAO,IAAI,CAAA;QAEhD,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;QAChD,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QACvC,IAAI,UAAU,KAAK,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,KAAK,UAAU;YAAE,OAAO,IAAI,CAAA;QAEjF,MAAM,UAAU,GAAG,eAAe,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,CAAA;QACjE,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,CAAmB,CAAA;QAEhF,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,CAAC,CAAC,KAAK,WAAW,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;YAC9E,OAAO,IAAI,CAAA;QACb,CAAC;QAED,OAAO;YACL,OAAO,EAAE,OAAO,CAAC,CAAC;YAClB,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;YAC/C,IAAI,EAAE,OAAO,CAAC,CAAC;SAChB,CAAA;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;AAC7B,CAAC;AAED,SAAS,eAAe,CAAC,KAAiB;IACxC,IAAI,MAAM,GAAG,EAAE,CAAA;IACf,iGAAiG;IACjG,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,MAAM,EAAE,CAAC;QAC9C,MAAM,IAAI,MAAM,CAAC,YAAY,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAA;IACjE,CAAC;IACD,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;AAChF,CAAC;AAED,SAAS,eAAe,CAAC,GAAW;IAClC,IAAI,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACtD,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,IAAI,GAAG,CAAA;IACvC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAA;IAC3B,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IAC3C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAA;IACvE,OAAO,KAAK,CAAA;AACd,CAAC"}
@@ -18,11 +18,14 @@ export interface GeminiGoogleSearchTool {
18
18
  google_search: Record<string, never>;
19
19
  }
20
20
  export type GeminiTool = GeminiGoogleSearchTool;
21
+ export type GeminiThinkingLevel = 'minimal' | 'low' | 'medium' | 'high';
21
22
  export interface GeminiThinkingConfig {
22
23
  /** Surface thought summaries as `thought` parts in the response. */
23
24
  includeThoughts?: boolean;
24
25
  /** Token budget for thinking; -1 = dynamic (model self-regulates depth). */
25
26
  thinkingBudget?: number;
27
+ /** Semantic depth dial for Gemini 3.x+; replaces numeric budgets. */
28
+ thinkingLevel?: GeminiThinkingLevel;
26
29
  }
27
30
  export interface GeminiGenerationConfig {
28
31
  temperature?: number;
@@ -57,12 +60,19 @@ export declare class GeminiProvider extends AIProvider {
57
60
  protected readonly providerName = "Gemini";
58
61
  readonly defaultBaseUrl = "https://generativelanguage.googleapis.com";
59
62
  readonly path = "/v1beta/models";
63
+ private readonly budgetMap;
60
64
  getPath(model: string, stream: boolean): string;
61
65
  buildHeaders(apiKey: string): Record<string, string>;
62
- buildPayload(messages: ChatMessageDto[], _model: string, opts: ChatRequestOpts, _stream: boolean): GeminiRequestPayload;
66
+ buildPayload(messages: ChatMessageDto[], model: string, opts: ChatRequestOpts, _stream: boolean): GeminiRequestPayload;
63
67
  parseError(errorText: string, status: number): UpstreamErrorDto;
64
68
  parseNonStreamingResponse(json: ProviderResponseDto): ChatResponseDto;
65
69
  protected parseProviderStreamChunk(json: ProviderStreamEventDto): ChatStreamPieceDto | null;
70
+ /** Major.minor from a versioned model name (`gemini-3.5-flash` → 3.5); null for aliases. */
71
+ private geminiVersion;
72
+ /** Dial → level, clamped to the family's supported enum: `minimal` is 3.5+; earlier 3.x floors at
73
+ * `low`. (gemini-3-pro-preview's low|high-only enum would need a wider clamp, but Google retired
74
+ * the model — 404 verified 2026-07-15.) */
75
+ private thinkingLevelFor;
66
76
  private isGeminiResponse;
67
77
  /** Split a candidate's parts into answer text and thought (reasoning) summaries — Gemini marks
68
78
  * thought parts with `thought: true`. Returns the `{ text?, reasoning? }` stream-piece shape. */
@@ -1 +1 @@
1
- {"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../../ai/src/providers/gemini.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../../ai/src/providers/gemini.ts"],"names":[],"mappings":"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"}