typebulb 0.58.0 → 0.58.2

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.
@@ -9,312 +9,315 @@
9
9
  * TypeChecker, and the CLI's emitted typecheck dirs.
10
10
  */
11
11
  import { modeUnion } from 'typebulb/format';
12
- const dataAndJson = `
13
- /**
14
- * Get raw data chunk from the Data tab.
15
- * @param index - Chunk index (0-based). Separate chunks with 2 blank lines.
16
- */
17
- data(index: number): string;
18
- /**
19
- * Get data chunk parsed as JSON (handles JSON-ish with unquoted keys).
20
- * @param index - Chunk index (0-based)
21
- * @throws If chunk is not valid JSON/JSON-ish
22
- */
12
+ const dataAndJson = `
13
+ /**
14
+ * Get raw data chunk from the Data tab.
15
+ * @param index - Chunk index (0-based). Separate chunks with 2 blank lines.
16
+ */
17
+ data(index: number): string;
18
+ /**
19
+ * Get data chunk parsed as JSON (handles JSON-ish with unquoted keys).
20
+ * @param index - Chunk index (0-based)
21
+ * @throws If chunk is not valid JSON/JSON-ish
22
+ */
23
23
  json<T = unknown>(index: number): T;`;
24
- const insight = `
25
- /**
26
- * Get the insight data produced by the inference layer.
27
- *
28
- * Returns the parsed JSON from insight.json, populated by the inference LLM.
29
- * Use a type parameter to get typed access to the insight data.
30
- *
31
- * @returns The parsed insight JSON, or undefined if no insight is available
32
- */
24
+ const insight = `
25
+ /**
26
+ * Get the insight data produced by the inference layer.
27
+ *
28
+ * Returns the parsed JSON from insight.json, populated by the inference LLM.
29
+ * Use a type parameter to get typed access to the insight data.
30
+ *
31
+ * @returns The parsed insight JSON, or undefined if no insight is available
32
+ */
33
33
  insight<T = unknown>(): T | undefined;`;
34
34
  // Runtime-state writers — duals of tb.data()/tb.json() and tb.insight() (TB-State.md).
35
- const runtimeStateWriters = `
36
- /**
37
- * Replace the data this run is working on, and get back a link that carries it.
38
- *
39
- * Updates what \`tb.data()\` / \`tb.json()\` return for the rest of this page, and writes the
40
- * result into the URL fragment so the address bar addresses this run. The bulb's source
41
- * \`data.txt\` is never touched: a reload without the fragment goes back to the file.
42
- *
43
- * @param chunks - The new data chunks (a bare string is treated as one chunk)
44
- * @returns The shareable URL, or undefined when there is no address bar (inline bulbs) or the
45
- * data is too large to fit a URL. Pass only what a share needs, not necessarily everything.
46
- */
47
- setData(chunks: string | string[]): Promise<string | undefined>;
48
- /**
49
- * Replace the insight this run is working on, and get back a link that carries it.
50
- *
51
- * The \`tb.insight()\` counterpart of \`setData\`, with the same fragment behavior and the same
52
- * rule: runtime only, never the bulb's source \`insight.json\`.
53
- *
54
- * @param value - Any JSON-serializable value
55
- * @returns The shareable URL, or undefined (see \`setData\`)
56
- */
57
- setInsight(value: unknown): Promise<string | undefined>;`;
35
+ const runtimeStateWriters = `
36
+ /**
37
+ * Replace the data this run is working on.
38
+ *
39
+ * Updates what \`tb.data()\` / \`tb.json()\` return for the rest of this page, and writes the
40
+ * result into the URL fragment, so the address bar addresses this run and \`tb.url()\` carries
41
+ * it. The bulb's source \`data.txt\` is never touched: a reload without the fragment goes back
42
+ * to the file.
43
+ *
44
+ * @param chunks - The new data chunks (a bare string is treated as one chunk)
45
+ * @returns Resolves once the address bar reflects the write. Data too large to fit a URL
46
+ * (~60KB encoded) still swaps, but carries no fragment: pass what a share needs, not
47
+ * necessarily everything.
48
+ */
49
+ setData(chunks: string | string[]): Promise<void>;
50
+ /**
51
+ * Replace the insight this run is working on.
52
+ *
53
+ * The \`tb.insight()\` counterpart of \`setData\`, with the same fragment behavior and the same
54
+ * rule: runtime only, never the bulb's source \`insight.json\`.
55
+ *
56
+ * @param value - Any JSON-serializable value
57
+ */
58
+ setInsight(value: unknown): Promise<void>;`;
58
59
  // One options shape, reused by tb.ai() and tb.ai.stream().
59
- const aiOptions = `options: {
60
- messages: Array<{ role: "user" | "assistant"; content: string }>;
61
- system?: string;
62
- /** Reasoning effort: 0=minimal, 1=low, 2=med, 3=high, 4=xhigh. Mapped to each provider's native mechanism (OpenAI/OpenRouter reasoning effort, Gemini thinking level, Anthropic adaptive thinking). 0 reaches the vendor's explicit off switch, and floors to a little thinking only on always-thinking models. 4 reaches the rung above high where the vendor has one (OpenAI/OpenRouter xhigh, Anthropic max) and clamps to high where it doesn't (Gemini) — never an error. Pin 1 (low) for most work; pick 0 deliberately, when you want the raw model or latency is the constraint. Omitting is NOT off — it buys the model's own default (medium on GPT-5.6), which reasons and bills invisibly. Ignored on the courtesy model, which runs at the level Typebulb sets. */
63
- effort?: 0 | 1 | 2 | 3 | 4;
64
- provider?: string;
65
- model?: string;
66
- /** Give the model a web-search tool, billed to the user's key. Off by default; the free model never searches. */
67
- webSearch?: boolean;
68
- /** Abort the request. On abort the promise rejects / the stream ends. */
69
- signal?: AbortSignal;
60
+ const aiOptions = `options: {
61
+ messages: Array<{ role: "user" | "assistant"; content: string }>;
62
+ system?: string;
63
+ /** Reasoning effort: 0=minimal, 1=low, 2=med, 3=high, 4=xhigh. Mapped to each provider's native mechanism (OpenAI/OpenRouter reasoning effort, Gemini thinking level, Anthropic adaptive thinking). 0 reaches the vendor's explicit off switch, and floors to a little thinking only on always-thinking models. 4 reaches the rung above high where the vendor has one (OpenAI/OpenRouter xhigh, Anthropic max) and clamps to high where it doesn't (Gemini) — never an error. Pin 1 (low) for most work; pick 0 deliberately, when you want the raw model or latency is the constraint. Omitting is NOT off — it buys the model's own default (medium on GPT-5.6), which reasons and bills invisibly. Ignored on the courtesy model, which runs at the level Typebulb sets. */
64
+ effort?: 0 | 1 | 2 | 3 | 4;
65
+ provider?: string;
66
+ model?: string;
67
+ /** Give the model a web-search tool, billed to the user's key. Off by default; the free model never searches. */
68
+ webSearch?: boolean;
69
+ /** Abort the request. On abort the promise rejects / the stream ends. */
70
+ signal?: AbortSignal;
70
71
  }`;
71
72
  /** A streamed delta from \`tb.ai.stream()\` — a discriminated union, exactly one kind per chunk. */
72
- const aiChunkType = `
73
- /** Provider-reported token counts for one call — real usage from the API, never an estimate.
74
- * \`output\` is total billed output (reasoning included); \`reasoning\` is the itemized subset where
75
- * the provider splits it (OpenAI, Gemini, OpenRouter — Anthropic doesn't); \`cacheRead\` is the
76
- * cached subset of \`input\`. */
77
- type AiUsage = { input: number; output: number; reasoning?: number; cacheRead?: number };
78
-
79
- /** A single streamed delta from \`tb.ai.stream()\`. Discriminated by \`kind\`. */
80
- type AiChunk =
81
- | { kind: "text"; text: string }
82
- | { kind: "reasoning"; text: string }
83
- | { kind: "usage"; usage: AiUsage };
73
+ const aiChunkType = `
74
+ /** Provider-reported token counts for one call — real usage from the API, never an estimate.
75
+ * \`output\` is total billed output (reasoning included); \`reasoning\` is the itemized subset where
76
+ * the provider splits it (OpenAI, Gemini, OpenRouter — Anthropic doesn't); \`cacheRead\` is the
77
+ * cached subset of \`input\`. */
78
+ type AiUsage = { input: number; output: number; reasoning?: number; cacheRead?: number };
79
+
80
+ /** A single streamed delta from \`tb.ai.stream()\`. Discriminated by \`kind\`. */
81
+ type AiChunk =
82
+ | { kind: "text"; text: string }
83
+ | { kind: "reasoning"; text: string }
84
+ | { kind: "usage"; usage: AiUsage };
84
85
  `;
85
86
  /** What \`tb.aiAccess()\` answers. Named so bulbs can hold it in state without respelling the union. */
86
- const aiAccessType = `
87
- /** What backs \`tb.ai\`: the user's own keys, the quota-limited courtesy model, or nothing. */
88
- type AiAccess = "own" | "courtesy" | "none";
87
+ const aiAccessType = `
88
+ /** What backs \`tb.ai\`: the user's own keys, the quota-limited courtesy model, or nothing. */
89
+ type AiAccess = "own" | "courtesy" | "none";
89
90
  `;
90
- const ai = `
91
- /**
92
- * General-purpose AI call. \`tb.ai(opts)\` resolves with the full text; \`tb.ai.stream(opts)\`
93
- * returns an async iterable of {@link AiChunk} deltas you consume with \`for await\`.
94
- *
95
- * @returns Promise resolving to { text, usage? } — \`usage\` is the provider-reported token
96
- * counts ({@link AiUsage}), absent when the provider reported none
97
- * @throws On rate limit, network error, or provider error
98
- */
99
- ai: {
100
- (${aiOptions}): Promise<{ text: string; usage?: AiUsage }>;
101
- /**
102
- * Streaming counterpart of \`tb.ai()\`. Yields \`{ kind: "text" | "reasoning", text }\` deltas
103
- * as they arrive, then one final \`{ kind: "usage", usage }\` chunk with the call's token
104
- * counts (when the provider reported them); break the loop (or abort \`signal\`) to cancel
105
- * and stop the upstream. Match \`kind\` positively — a bare \`else\` branch that assumes
106
- * "not reasoning means text" will misread the usage chunk.
107
- *
108
- * \`kind: "reasoning"\` deltas only arrive when you pass \`effort: 1-4\` AND use a
109
- * thinking-capable model; otherwise the stream is \`text\`-only.
110
- *
111
- * @example
112
- * let answer = "";
113
- * for await (const c of tb.ai.stream({ messages })) {
114
- * if (c.kind === "text") answer += c.text;
115
- * }
116
- */
117
- stream(${aiOptions}): AsyncIterable<AiChunk>;
91
+ const ai = `
92
+ /**
93
+ * General-purpose AI call. \`tb.ai(opts)\` resolves with the full text; \`tb.ai.stream(opts)\`
94
+ * returns an async iterable of {@link AiChunk} deltas you consume with \`for await\`.
95
+ *
96
+ * @returns Promise resolving to { text, usage? } — \`usage\` is the provider-reported token
97
+ * counts ({@link AiUsage}), absent when the provider reported none
98
+ * @throws On rate limit, network error, or provider error
99
+ */
100
+ ai: {
101
+ (${aiOptions}): Promise<{ text: string; usage?: AiUsage }>;
102
+ /**
103
+ * Streaming counterpart of \`tb.ai()\`. Yields \`{ kind: "text" | "reasoning", text }\` deltas
104
+ * as they arrive, then one final \`{ kind: "usage", usage }\` chunk with the call's token
105
+ * counts (when the provider reported them); break the loop (or abort \`signal\`) to cancel
106
+ * and stop the upstream. Match \`kind\` positively — a bare \`else\` branch that assumes
107
+ * "not reasoning means text" will misread the usage chunk.
108
+ *
109
+ * \`kind: "reasoning"\` deltas only arrive when you pass \`effort: 1-4\` AND use a
110
+ * thinking-capable model; otherwise the stream is \`text\`-only.
111
+ *
112
+ * @example
113
+ * let answer = "";
114
+ * for await (const c of tb.ai.stream({ messages })) {
115
+ * if (c.kind === "text") answer += c.text;
116
+ * }
117
+ */
118
+ stream(${aiOptions}): AsyncIterable<AiChunk>;
118
119
  };`;
119
- const models = `
120
- /**
121
- * Returns AI models available to the current user.
122
- * Models are filtered by the user's configured API keys.
123
- * If no keys are configured, returns only the courtesy model.
124
- */
125
- models(): Promise<Array<{
126
- /** Provider protocol: "anthropic", "openai", "gemini", "openrouter" */
127
- provider: string;
128
- /** Model identifier, e.g. "claude-sonnet-4-6" */
129
- name: string;
130
- /** Human-readable display name, e.g. "Sonnet 4.6" */
131
- friendlyName: string;
132
- /** Provider display name, e.g. "Anthropic" */
133
- providerName: string;
134
- /** True on the .env-configured default model (TB_AI_PROVIDER + TB_AI_MODEL); absent otherwise */
135
- default?: boolean;
136
- }>>;
137
- /**
138
- * What backs \`tb.ai\` right now:
139
- *
140
- * - \`'own'\` — the user's own API keys (or their own local model server)
141
- * - \`'courtesy'\` — the quota-limited courtesy model, fine for a call or two
142
- * - \`'none'\` — no AI at all (the CLI with no keys, an inline bulb)
143
- *
144
- * A bulb making many AI calls should show a "use your own keys" notice
145
- * instead of running unless this is \`'own'\`. Never derive it from
146
- * \`tb.mode\` or the length of \`tb.models()\` — which hosts offer a courtesy
147
- * model is the host's business and changes without your bulb changing.
148
- */
120
+ const models = `
121
+ /**
122
+ * Returns AI models available to the current user.
123
+ * Models are filtered by the user's configured API keys.
124
+ * If no keys are configured, returns only the courtesy model.
125
+ */
126
+ models(): Promise<Array<{
127
+ /** Provider protocol: "anthropic", "openai", "gemini", "openrouter" */
128
+ provider: string;
129
+ /** Model identifier, e.g. "claude-sonnet-4-6" */
130
+ name: string;
131
+ /** Human-readable display name, e.g. "Sonnet 4.6" */
132
+ friendlyName: string;
133
+ /** Provider display name, e.g. "Anthropic" */
134
+ providerName: string;
135
+ /** True on the .env-configured default model (TB_AI_PROVIDER + TB_AI_MODEL); absent otherwise */
136
+ default?: boolean;
137
+ }>>;
138
+ /**
139
+ * What backs \`tb.ai\` right now:
140
+ *
141
+ * - \`'own'\` — the user's own API keys (or their own local model server)
142
+ * - \`'courtesy'\` — the quota-limited courtesy model, fine for a call or two
143
+ * - \`'none'\` — no AI at all (the CLI with no keys, an inline bulb)
144
+ *
145
+ * A bulb making many AI calls should show a "use your own keys" notice
146
+ * instead of running unless this is \`'own'\`. Never derive it from
147
+ * \`tb.mode\` or the length of \`tb.models()\` — which hosts offer a courtesy
148
+ * model is the host's business and changes without your bulb changing.
149
+ */
149
150
  aiAccess(): Promise<AiAccess>;`;
150
- const theme = `
151
- /**
152
- * The bulb's theme override (\`<html data-theme>\`).
153
- *
154
- * - Get: the current override — \`'dark'\` | \`'light'\`, or \`undefined\` when
155
- * following the OS preference.
156
- * - Set \`'dark'\`/\`'light'\` to force and persist it (per-bulb); set
157
- * \`undefined\` to clear the override and follow the OS again.
158
- *
159
- * Drives \`<html data-theme>\`, so render off \`html[data-theme="…"]\` selectors
160
- * (or observe the attribute) rather than reading \`tb.theme\`.
161
- */
151
+ const theme = `
152
+ /**
153
+ * The bulb's theme override (\`<html data-theme>\`).
154
+ *
155
+ * - Get: the current override — \`'dark'\` | \`'light'\`, or \`undefined\` when
156
+ * following the OS preference.
157
+ * - Set \`'dark'\`/\`'light'\` to force and persist it (per-bulb); set
158
+ * \`undefined\` to clear the override and follow the OS again.
159
+ *
160
+ * Drives \`<html data-theme>\`, so render off \`html[data-theme="…"]\` selectors
161
+ * (or observe the attribute) rather than reading \`tb.theme\`.
162
+ */
162
163
  theme: 'light' | 'dark' | undefined;`;
163
- const mode = `
164
- /**
165
- * The mode this bulb is running in.
166
- *
167
- * - \`'local'\` — Running via the typebulb CLI
168
- * - \`'ide'\` — Running in the typebulb.com editor
169
- * - \`'published'\` — Running as a published/standalone bulb on typebulb.com
170
- * - \`'inline'\` — Running inline in an agent's transcript, rendered by the mirror
171
- * (sandboxed, client-only: AI, filesystem, and server RPC are unavailable)
172
- */
164
+ const mode = `
165
+ /**
166
+ * The mode this bulb is running in.
167
+ *
168
+ * - \`'local'\` — Running via the typebulb CLI
169
+ * - \`'ide'\` — Running in the typebulb.com editor
170
+ * - \`'published'\` — Running as a published/standalone bulb on typebulb.com
171
+ * - \`'inline'\` — Running inline in an agent's transcript, rendered by the mirror
172
+ * (sandboxed, client-only: AI, filesystem, and server RPC are unavailable)
173
+ */
173
174
  mode: ${modeUnion};`;
174
- const fs = `
175
- /**
176
- * Local filesystem access (CLI only).
177
- *
178
- * Relative paths resolve against the bulb's folder (\`tb.dir\` —
179
- * \`<bulb-dir>/<filename-stem>/\`, created on demand), so
180
- * \`tb.fs.write('results.json')\` lands beside the bulb. \`../\` reaches sibling
181
- * bulbs' folders; everything stays confined to the project (the launch cwd).
182
- * Throws in ide/published mode.
183
- */
184
- fs: {
185
- /** Read a file as UTF-8 text. Throws if the file is not valid UTF-8 — use readBytes for binary. */
186
- read(path: string): Promise<string>;
187
- /** Read a file as raw bytes. */
188
- readBytes(path: string): Promise<Uint8Array>;
189
- /** Write text or raw bytes to a file. Creates parent directories if needed. */
190
- write(path: string, content: string | Uint8Array): Promise<boolean>;
175
+ const fs = `
176
+ /**
177
+ * Local filesystem access (CLI only).
178
+ *
179
+ * Relative paths resolve against the bulb's folder (\`tb.dir\` —
180
+ * \`<bulb-dir>/<filename-stem>/\`, created on demand), so
181
+ * \`tb.fs.write('results.json')\` lands beside the bulb. \`../\` reaches sibling
182
+ * bulbs' folders; everything stays confined to the project (the launch cwd).
183
+ * Throws in ide/published mode.
184
+ */
185
+ fs: {
186
+ /** Read a file as UTF-8 text. Throws if the file is not valid UTF-8 — use readBytes for binary. */
187
+ read(path: string): Promise<string>;
188
+ /** Read a file as raw bytes. */
189
+ readBytes(path: string): Promise<Uint8Array>;
190
+ /** Write text or raw bytes to a file. Creates parent directories if needed. */
191
+ write(path: string, content: string | Uint8Array): Promise<boolean>;
191
192
  };`;
192
- const dir = `
193
- /**
194
- * The bulb's folder — absolute path to \`<bulb-dir>/<filename-stem>/\`
195
- * (or its \`batches/<name>/\` folder when the run is scoped with \`--batch\`).
196
- *
197
- * For interop only (handing a path to \`server.ts\` or a spawned tool):
198
- * \`tb.fs\` already resolves relative paths against it, so bulb code writing
199
- * its own files never needs it. CLI only — throws in ide/published/inline mode.
200
- */
193
+ const dir = `
194
+ /**
195
+ * The bulb's folder — absolute path to \`<bulb-dir>/<filename-stem>/\`
196
+ * (or its \`batches/<name>/\` folder when the run is scoped with \`--batch\`).
197
+ *
198
+ * For interop only (handing a path to \`server.ts\` or a spawned tool):
199
+ * \`tb.fs\` already resolves relative paths against it, so bulb code writing
200
+ * its own files never needs it. CLI only — throws in ide/published/inline mode.
201
+ */
201
202
  readonly dir: string;`;
202
- const clientOnlyMembers = `
203
- /**
204
- * Async value inspector for tensor-like objects.
205
- *
206
- * Materializes lazy values (like GPU tensors) and logs them with metadata.
207
- * Handles objects with \`.js()\`, \`.data()\`, \`.array()\`, \`.arraySync()\`, etc.
208
- *
209
- * @remarks
210
- * - Always use \`await\` - materialization may be async (GPU→CPU readback)
211
- * - Large values are truncated (max 1000 elements)
212
- * - Promises are logged as \`[Promise]\` (not awaited - could hang)
213
- */
214
- dump(...args: any[]): Promise<void>;
215
- /**
216
- * Trigger inference to generate new insight data.
217
- *
218
- * Opens a confirmation modal showing the data to be analyzed, then streams
219
- * the inference result. On success, updates the insight so subsequent
220
- * \`tb.insight()\` calls return the new value.
221
- *
222
- * @param opts - Options for inference
223
- * @param opts.data - Data to pre-populate in the modal (string or array of strings). If omitted, modal opens with empty textarea for user to paste.
224
- * @returns Promise that resolves with the parsed insight JSON
225
- * @throws If inference is already in progress, or on network/parse/rate limit errors
226
- */
227
- infer<T = unknown>(opts?: { data?: string | string[] }): Promise<T>;
228
- /**
229
- * Proxy a CDN URL through the sandbox origin for Web Worker/WASM same-origin loading.
230
- *
231
- * In the sandbox, prepends \`/proxy/\` so the URL is served from the same origin.
232
- * Outside the sandbox (exported HTML, CLI), returns the URL unchanged.
233
- *
234
- * @param url - Full HTTPS URL to an allowlisted CDN (esm.sh, unpkg.com, cdn.jsdelivr.net, cdnjs.cloudflare.com)
235
- * @returns The proxied URL (sandbox) or the original URL (standalone/CLI)
236
- */
237
- proxy(url: string): string;
238
- /**
239
- * Copy text to clipboard.
240
- * Must be called synchronously within a user gesture (click/keydown).
241
- * @returns true if successful, false otherwise
242
- */
243
- copy(text: string): Promise<boolean>;
244
- /**
245
- * Get the canonical URL of this bulb.
246
- *
247
- * Returns the parent typebulb.com URL (including path, query, and \`#tb=\` fragment),
248
- * resolving correctly from inside the cross-origin sandbox iframe.
249
- * Use this instead of \`location.href\` or \`document.referrer\`.
250
- *
251
- * @returns The full canonical URL
252
- */
203
+ const clientOnlyMembers = `
204
+ /**
205
+ * Async value inspector for tensor-like objects.
206
+ *
207
+ * Materializes lazy values (like GPU tensors) and logs them with metadata.
208
+ * Handles objects with \`.js()\`, \`.data()\`, \`.array()\`, \`.arraySync()\`, etc.
209
+ *
210
+ * @remarks
211
+ * - Always use \`await\` - materialization may be async (GPU→CPU readback)
212
+ * - Large values are truncated (max 1000 elements)
213
+ * - Promises are logged as \`[Promise]\` (not awaited - could hang)
214
+ */
215
+ dump(...args: any[]): Promise<void>;
216
+ /**
217
+ * Trigger inference to generate new insight data.
218
+ *
219
+ * Opens a confirmation modal showing the data to be analyzed, then streams
220
+ * the inference result. On success, updates the insight so subsequent
221
+ * \`tb.insight()\` calls return the new value.
222
+ *
223
+ * @param opts - Options for inference
224
+ * @param opts.data - Data to pre-populate in the modal (string or array of strings). If omitted, modal opens with empty textarea for user to paste.
225
+ * @returns Promise that resolves with the parsed insight JSON
226
+ * @throws If inference is already in progress, or on network/parse/rate limit errors
227
+ */
228
+ infer<T = unknown>(opts?: { data?: string | string[] }): Promise<T>;
229
+ /**
230
+ * Proxy a CDN URL through the sandbox origin for Web Worker/WASM same-origin loading.
231
+ *
232
+ * In the sandbox, prepends \`/proxy/\` so the URL is served from the same origin.
233
+ * Outside the sandbox (exported HTML, CLI), returns the URL unchanged.
234
+ *
235
+ * @param url - Full HTTPS URL to an allowlisted CDN (esm.sh, unpkg.com, cdn.jsdelivr.net, cdnjs.cloudflare.com)
236
+ * @returns The proxied URL (sandbox) or the original URL (standalone/CLI)
237
+ */
238
+ proxy(url: string): string;
239
+ /**
240
+ * Copy text to clipboard.
241
+ * Must be called synchronously within a user gesture (click/keydown).
242
+ * @returns true if successful, false otherwise
243
+ */
244
+ copy(text: string): Promise<boolean>;
245
+ /**
246
+ * Get the canonical URL of this bulb.
247
+ *
248
+ * Returns the parent typebulb.com URL (including query and \`#tb=\` fragment), resolving
249
+ * correctly from inside the cross-origin sandbox iframe. That is the published \`/full\` page
250
+ * even while authoring in the IDE, because it is the link someone you send it to can open.
251
+ * Locally it is the served localhost URL. Use this instead of \`location.href\` or
252
+ * \`document.referrer\`.
253
+ *
254
+ * @returns The full canonical URL
255
+ */
253
256
  url(): Promise<string>;`;
254
- const onMessage = `
255
- /**
256
- * Subscribe to a value pushed from the terminal via \`typebulb send <file> [message]\`.
257
- *
258
- * The dual of \`tb.log\` (data out): a value sent *in* from the CLI, no \`--trust\` required.
259
- * Use it to start expensive work on demand instead of on load — e.g. \`tb.onMessage(() => start())\`
260
- * — so hot reloads don't re-trigger it while you edit, and an agent kicks off one run when ready.
261
- *
262
- * The message is the JSON-parsed value of what \`send\` was given (or the raw string if it isn't
263
- * JSON; \`undefined\` for a bare \`typebulb send <file>\`). A non-\`undefined\` return value (awaited)
264
- * becomes the reply \`send --wait\` prints on stdout — JSON-serializable, at most one handler
265
- * replying — the structured read-back for self-tests. Returns an unsubscribe function. Inert in
266
- * an inline bulb (no sender) — the handler is registered but never fires.
267
- *
268
- * @param handler - Called with each pushed message; may return a JSON-serializable reply.
269
- * @returns An unsubscribe function.
270
- */
257
+ const onMessage = `
258
+ /**
259
+ * Subscribe to a value pushed from the terminal via \`typebulb send <file> [message]\`.
260
+ *
261
+ * The dual of \`tb.log\` (data out): a value sent *in* from the CLI, no \`--trust\` required.
262
+ * Use it to start expensive work on demand instead of on load — e.g. \`tb.onMessage(() => start())\`
263
+ * — so hot reloads don't re-trigger it while you edit, and an agent kicks off one run when ready.
264
+ *
265
+ * The message is the JSON-parsed value of what \`send\` was given (or the raw string if it isn't
266
+ * JSON; \`undefined\` for a bare \`typebulb send <file>\`). A non-\`undefined\` return value (awaited)
267
+ * becomes the reply \`send --wait\` prints on stdout — JSON-serializable, at most one handler
268
+ * replying — the structured read-back for self-tests. Returns an unsubscribe function. Inert in
269
+ * an inline bulb (no sender) — the handler is registered but never fires.
270
+ *
271
+ * @param handler - Called with each pushed message; may return a JSON-serializable reply.
272
+ * @returns An unsubscribe function.
273
+ */
271
274
  onMessage(handler: (message: any) => unknown): () => void;`;
272
- const log = `
273
- /**
274
- * Print to the CLI's stdout — the bulb's log channel, read back with \`typebulb logs <file>\`.
275
- *
276
- * Ungated: needs no \`server.ts\` block and no \`--trust\`, so a Restricted client-only bulb can
277
- * instrument itself. Args cross to the CLI as JSON; where no CLI serves the page (web, inline,
278
- * or a transport failure) it falls back to the browser console. Works in \`server.ts\` too (same
279
- * as \`console.log\` there).
280
- */
275
+ const log = `
276
+ /**
277
+ * Print to the CLI's stdout — the bulb's log channel, read back with \`typebulb logs <file>\`.
278
+ *
279
+ * Ungated: needs no \`server.ts\` block and no \`--trust\`, so a Restricted client-only bulb can
280
+ * instrument itself. Args cross to the CLI as JSON; where no CLI serves the page (web, inline,
281
+ * or a transport failure) it falls back to the browser console. Works in \`server.ts\` too (same
282
+ * as \`console.log\` there).
283
+ */
281
284
  log(...args: any[]): void;`;
282
- const clientServerProxy = `
283
- /**
284
- * Server-side function proxy.
285
- *
286
- * In the CLI, calls exported functions from the \`**server.ts**\` section.
287
- *
288
- * A normal export is awaited for its result (\`await tb.server.fn()\`). An \`async function*\`
289
- * export streams: \`for await (const chunk of tb.server.gen())\`. The call object supports both;
290
- * break the \`for await\` to cancel and tear down the server generator.
291
- */
285
+ const clientServerProxy = `
286
+ /**
287
+ * Server-side function proxy.
288
+ *
289
+ * In the CLI, calls exported functions from the \`**server.ts**\` section.
290
+ *
291
+ * A normal export is awaited for its result (\`await tb.server.fn()\`). An \`async function*\`
292
+ * export streams: \`for await (const chunk of tb.server.gen())\`. The call object supports both;
293
+ * break the \`for await\` to cancel and tear down the server generator.
294
+ */
292
295
  server: Record<string, (...args: any[]) => Promise<any> & AsyncIterable<any>>;`;
293
296
  /** Typebulb globals available in browser-side code (code.tsx). */
294
- export const clientTbTypings = `${aiChunkType}${aiAccessType}
295
- /**
296
- * Typebulb utilities namespace.
297
- * Type \`tb.\` to discover available helpers.
298
- */
299
- declare const tb: {${dataAndJson}${clientOnlyMembers}${insight}${runtimeStateWriters}${log}${clientServerProxy}${onMessage}${ai}${fs}${dir}${models}${theme}${mode}
300
- };
297
+ export const clientTbTypings = `${aiChunkType}${aiAccessType}
298
+ /**
299
+ * Typebulb utilities namespace.
300
+ * Type \`tb.\` to discover available helpers.
301
+ */
302
+ declare const tb: {${dataAndJson}${clientOnlyMembers}${insight}${runtimeStateWriters}${log}${clientServerProxy}${onMessage}${ai}${fs}${dir}${models}${theme}${mode}
303
+ };
301
304
  `;
302
- const serverLog = `
303
- /**
304
- * Print to the CLI's stdout — the same channel as \`console.log\` here (the server's console IS
305
- * the bulb's log). One log verb across blocks: page-side \`tb.log\` reaches this same stdout.
306
- */
305
+ const serverLog = `
306
+ /**
307
+ * Print to the CLI's stdout — the same channel as \`console.log\` here (the server's console IS
308
+ * the bulb's log). One log verb across blocks: page-side \`tb.log\` reaches this same stdout.
309
+ */
307
310
  log(...args: any[]): void;`;
308
311
  /** Typebulb globals available in Node-side code (server.ts).
309
312
  * Only what carries a bulb-specific rule Node can't know — tb.ai, tb.fs, tb.dir (TB-FS.md);
310
313
  * plus the tb.log uniformity exception (serverTb.ts). The browser-only helpers are intentionally
311
314
  * absent. Must match serverTb.ts's runtime surface. */
312
- export const serverTbTypings = `${aiChunkType}${aiAccessType}
313
- /**
314
- * Typebulb utilities namespace (server-side).
315
- * Type \`tb.\` to discover available helpers.
316
- */
317
- declare const tb: {${serverLog}${ai}${fs}${dir}${models}${mode}
318
- };
315
+ export const serverTbTypings = `${aiChunkType}${aiAccessType}
316
+ /**
317
+ * Typebulb utilities namespace (server-side).
318
+ * Type \`tb.\` to discover available helpers.
319
+ */
320
+ declare const tb: {${serverLog}${ai}${fs}${dir}${models}${mode}
321
+ };
319
322
  `;
320
323
  //# sourceMappingURL=tbTypings.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tbTypings.js","sourceRoot":"","sources":["../../dts/src/tbTypings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAE3C,MAAM,WAAW,GAAG;;;;;;;;;;;uCAWmB,CAAA;AAEvC,MAAM,OAAO,GAAG;;;;;;;;;yCASyB,CAAA;AAEzC,uFAAuF;AACvF,MAAM,mBAAmB,GAAG;;;;;;;;;;;;;;;;;;;;;;2DAsB+B,CAAA;AAE3D,2DAA2D;AAC3D,MAAM,SAAS,GAAG;;;;;;;;;;;IAWd,CAAA;AAEJ,oGAAoG;AACpG,MAAM,WAAW,GAAG;;;;;;;;;;;;CAYnB,CAAA;AAED,wGAAwG;AACxG,MAAM,YAAY,GAAG;;;CAGpB,CAAA;AAED,MAAM,EAAE,GAAG;;;;;;;;;;OAUJ,SAAS;;;;;;;;;;;;;;;;;aAiBH,SAAS;KACjB,CAAA;AAEL,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iCA8BkB,CAAA;AAEjC,MAAM,KAAK,GAAG;;;;;;;;;;;;uCAYyB,CAAA;AAEvC,MAAM,IAAI,GAAG;;;;;;;;;;UAUH,SAAS,GAAG,CAAA;AAEtB,MAAM,EAAE,GAAG;;;;;;;;;;;;;;;;;KAiBN,CAAA;AAEL,MAAM,GAAG,GAAG;;;;;;;;;wBASY,CAAA;AAExB,MAAM,iBAAiB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0BAmDA,CAAA;AAE1B,MAAM,SAAS,GAAG;;;;;;;;;;;;;;;;;6DAiB2C,CAAA;AAE7D,MAAM,GAAG,GAAG;;;;;;;;;6BASiB,CAAA;AAE7B,MAAM,iBAAiB,GAAG;;;;;;;;;;iFAUuD,CAAA;AAEjF,kEAAkE;AAClE,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,WAAW,GAAG,YAAY;;;;;qBAKvC,WAAW,GAAG,iBAAiB,GAAG,OAAO,GAAG,mBAAmB,GAAG,GAAG,GAAG,iBAAiB,GAAG,SAAS,GAAG,EAAE,GAAG,EAAE,GAAG,GAAG,GAAG,MAAM,GAAG,KAAK,GAAG,IAAI;;CAEjK,CAAA;AAED,MAAM,SAAS,GAAG;;;;;6BAKW,CAAA;AAE7B;;;wDAGwD;AACxD,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,WAAW,GAAG,YAAY;;;;;qBAKvC,SAAS,GAAG,EAAE,GAAG,EAAE,GAAG,GAAG,GAAG,MAAM,GAAG,IAAI;;CAE7D,CAAA"}
1
+ {"version":3,"file":"tbTypings.js","sourceRoot":"","sources":["../../dts/src/tbTypings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAE3C,MAAM,WAAW,GAAG;;;;;;;;;;;uCAWmB,CAAA;AAEvC,MAAM,OAAO,GAAG;;;;;;;;;yCASyB,CAAA;AAEzC,uFAAuF;AACvF,MAAM,mBAAmB,GAAG;;;;;;;;;;;;;;;;;;;;;;;6CAuBiB,CAAA;AAE7C,2DAA2D;AAC3D,MAAM,SAAS,GAAG;;;;;;;;;;;IAWd,CAAA;AAEJ,oGAAoG;AACpG,MAAM,WAAW,GAAG;;;;;;;;;;;;CAYnB,CAAA;AAED,wGAAwG;AACxG,MAAM,YAAY,GAAG;;;CAGpB,CAAA;AAED,MAAM,EAAE,GAAG;;;;;;;;;;OAUJ,SAAS;;;;;;;;;;;;;;;;;aAiBH,SAAS;KACjB,CAAA;AAEL,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iCA8BkB,CAAA;AAEjC,MAAM,KAAK,GAAG;;;;;;;;;;;;uCAYyB,CAAA;AAEvC,MAAM,IAAI,GAAG;;;;;;;;;;UAUH,SAAS,GAAG,CAAA;AAEtB,MAAM,EAAE,GAAG;;;;;;;;;;;;;;;;;KAiBN,CAAA;AAEL,MAAM,GAAG,GAAG;;;;;;;;;wBASY,CAAA;AAExB,MAAM,iBAAiB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0BAqDA,CAAA;AAE1B,MAAM,SAAS,GAAG;;;;;;;;;;;;;;;;;6DAiB2C,CAAA;AAE7D,MAAM,GAAG,GAAG;;;;;;;;;6BASiB,CAAA;AAE7B,MAAM,iBAAiB,GAAG;;;;;;;;;;iFAUuD,CAAA;AAEjF,kEAAkE;AAClE,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,WAAW,GAAG,YAAY;;;;;qBAKvC,WAAW,GAAG,iBAAiB,GAAG,OAAO,GAAG,mBAAmB,GAAG,GAAG,GAAG,iBAAiB,GAAG,SAAS,GAAG,EAAE,GAAG,EAAE,GAAG,GAAG,GAAG,MAAM,GAAG,KAAK,GAAG,IAAI;;CAEjK,CAAA;AAED,MAAM,SAAS,GAAG;;;;;6BAKW,CAAA;AAE7B;;;wDAGwD;AACxD,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,WAAW,GAAG,YAAY;;;;;qBAKvC,SAAS,GAAG,EAAE,GAAG,EAAE,GAAG,GAAG,GAAG,MAAM,GAAG,IAAI;;CAE7D,CAAA"}