typebulb 0.9.4 → 0.9.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -1
- package/dist/bulbs/claude.bulb.md +3260 -0
- package/dist/index.js +85 -56
- package/dist/render.js +23 -4
- package/dist/servers.d.ts +7 -0
- package/dist/servers.js +3 -1
- package/package.json +1 -1
package/dist/render.js
CHANGED
|
@@ -439,17 +439,36 @@ ${A(s)}
|
|
|
439
439
|
// viewport for a short bulb (so the frame shrinks to it), tracking the frame for a
|
|
440
440
|
// full-bleed one (so it self-stabilises at the host's initial height).
|
|
441
441
|
//
|
|
442
|
+
// Showing the Y scrollbar is DEFERRED; hiding it stays eager. Content grows (a new
|
|
443
|
+
// row, an expanded panel) synchronously, but the frame only grows a beat later, after
|
|
444
|
+
// the host receives the height message and resizes the iframe. In that gap body is
|
|
445
|
+
// taller than the still-old frame, so an eager overflow:auto flashes a scrollbar for
|
|
446
|
+
// exactly the round-trip. So when Y overflows we post the height and re-check after a
|
|
447
|
+
// short delay instead of flipping immediately: if the frame caught up the overflow is
|
|
448
|
+
// gone (no bar), and only an overflow that SURVIVES \u2014 a genuine host cap \u2014 gets auto.
|
|
449
|
+
// The host can't tell the iframe its cap (no host\u2192iframe channel), so this round-trip
|
|
450
|
+
// is how the embed distinguishes "frame about to grow" from "frame capped". X has no
|
|
451
|
+
// async resize (the host never grows width on content), so it flips inline.
|
|
452
|
+
//
|
|
442
453
|
// Coalesce to one rAF and only write an overflow value that actually changed: setting
|
|
443
454
|
// overflow adds/removes a scrollbar, which resizes the element and re-fires the
|
|
444
455
|
// observer \u2014 writing unconditionally ping-pongs (the "ResizeObserver loop" warning).
|
|
445
|
-
// The rAF + equality guard let it settle within a frame instead.
|
|
446
456
|
var raf = 0;
|
|
457
|
+
var confirm = 0;
|
|
458
|
+
var showYScroll = function () {
|
|
459
|
+
confirm = 0;
|
|
460
|
+
if (de.scrollHeight > de.clientHeight + 1 && de.style.overflowY !== 'auto') de.style.overflowY = 'auto';
|
|
461
|
+
};
|
|
447
462
|
var apply = function () {
|
|
448
463
|
raf = 0;
|
|
449
|
-
var
|
|
450
|
-
var ox = de.scrollWidth > de.clientWidth + 1 ? 'auto' : 'hidden';
|
|
451
|
-
if (de.style.overflowY !== oy) de.style.overflowY = oy;
|
|
464
|
+
var ox = de.scrollWidth > de.clientWidth + 1 ? 'auto' : 'hidden';
|
|
452
465
|
if (de.style.overflowX !== ox) de.style.overflowX = ox;
|
|
466
|
+
if (de.scrollHeight > de.clientHeight + 1) {
|
|
467
|
+
if (de.style.overflowY !== 'auto' && !confirm) confirm = setTimeout(showYScroll, 100);
|
|
468
|
+
} else {
|
|
469
|
+
if (confirm) { clearTimeout(confirm); confirm = 0; }
|
|
470
|
+
if (de.style.overflowY !== 'hidden') de.style.overflowY = 'hidden';
|
|
471
|
+
}
|
|
453
472
|
post({ __typebulbEmbed: true, kind: 'height', height: Math.ceil(document.body.scrollHeight) });
|
|
454
473
|
};
|
|
455
474
|
var update = function () { if (!raf) raf = requestAnimationFrame(apply); };
|
package/dist/servers.d.ts
CHANGED
|
@@ -11,6 +11,9 @@ export interface BulbServer {
|
|
|
11
11
|
startedAt: number
|
|
12
12
|
/** Launched with --trust (filesystem / AI / server.ts enabled)? */
|
|
13
13
|
trust?: boolean
|
|
14
|
+
/** Human label of a capability the proactive scan predicts this untrusted bulb will need
|
|
15
|
+
* (set at register time; probabilistic, not enforcement). */
|
|
16
|
+
predicted?: string
|
|
14
17
|
/** Human label of a privileged capability this untrusted server denied (set by the gate). */
|
|
15
18
|
denied?: string
|
|
16
19
|
}
|
|
@@ -46,6 +49,10 @@ export interface BulbFileInfo {
|
|
|
46
49
|
* each with its frontmatter name (or filename stem) and mtime. */
|
|
47
50
|
export declare function listBulbFiles(cwd: string): BulbFileInfo[]
|
|
48
51
|
|
|
52
|
+
/** Scan a `.bulb.md` and return the privileged capability it probably needs (or undefined),
|
|
53
|
+
* so a host can offer --trust before launching. Probabilistic hint, never enforcement. */
|
|
54
|
+
export declare function predictBulbTrust(file: string): Promise<string | undefined>
|
|
55
|
+
|
|
49
56
|
/** The bulb's `name:` from its leading frontmatter, or undefined if absent. */
|
|
50
57
|
export declare function bulbName(source: string): string | undefined
|
|
51
58
|
|
package/dist/servers.js
CHANGED
|
@@ -1 +1,3 @@
|
|
|
1
|
-
import{spawn as
|
|
1
|
+
import{spawn as v}from"child_process";import{readdir as L,readFile as N,writeFile as pt,unlink as c,mkdir as mt}from"fs/promises";import{mkdirSync as gt,writeFileSync as bt,appendFileSync as ht,readFileSync as k}from"fs";import*as o from"path";import{join as g,resolve as _}from"path";import{homedir as E}from"os";function p(){let e=process.env.TYPEBULB_SERVERS_DIR;return e?g(e,".."):g(E(),".typebulb")}function u(){return process.env.TYPEBULB_SERVERS_DIR||g(p(),"servers")}function b(e){let t=_(e);return(process.platform==="win32"?t.toLowerCase():t).replace(/\\/g,"/")}function $(e){return o.join(u(),`${e}.json`)}function m(e){return o.join(u(),`${e}.log`)}function O(e,t=0){try{let r=k(m(e)),n=t>=0&&t<=r.length?t:0;return{text:r.subarray(n).toString("utf8"),offset:r.length}}catch{return{text:"",offset:0}}}function R(e){try{return process.kill(e,0),!0}catch(t){return t.code==="EPERM"}}async function A(e){await c($(e)).catch(()=>{}),await c(m(e)).catch(()=>{})}async function h(){let e;try{e=await L(u())}catch{return[]}let t=[];return await Promise.all(e.map(async r=>{if(!r.endsWith(".json"))return;let n=o.join(u(),r),s;try{s=JSON.parse(await N(n,"utf8"))}catch{await c(n).catch(()=>{});return}s&&typeof s.pid=="number"&&R(s.pid)?t.push(s):(await c(n).catch(()=>{}),s?.pid&&await c(m(s.pid)).catch(()=>{}))})),t.sort((r,n)=>r.startedAt-n.startedAt)}async function I(e){try{process.kill(e,"SIGTERM")}catch{}await A(e)}var J=e=>new Promise(t=>setTimeout(t,e));async function M(e,t={}){let r=t.cwd??process.cwd(),n=o.resolve(r,e),s=(await h()).find(a=>a.file===n);if(s)return s;let i=["typebulb",...t.trust?["--trust"]:[],e,...t.open===!1?["--no-open"]:[]];(process.platform==="win32"?v("cmd",["/c","start","","/b","npx",...i],{cwd:r,stdio:"ignore",windowsHide:!0}):v("npx",i,{cwd:r,detached:!0,stdio:"ignore"})).unref();let l=Date.now()+2e4;for(;Date.now()<l;){await J(150);let a=(await h()).find(f=>f.file===n);if(a)return a}throw new Error(`Launched ${o.basename(e)} but it did not register within 20s.`)}import{readdirSync as K,readFileSync as z,statSync as H}from"fs";import{join as S,basename as U}from"path";function d(e){let t=/^---[^\n]*\n([\s\S]*?)\n---/.exec(e),r=t?/^\s*name:\s*(.+?)\s*$/m.exec(t[1]):null;return r?r[1].replace(/^["']|["']$/g,""):void 0}function W(e){return(d(e)??"bulb").toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"bulb"}function C(e){return e.replace(/^---[^\n]*\r?\n[\s\S]*?\r?\n---[^\n]*\r?\n?/,"").replace(/^\r?\n+/,"")}function x(e,t,r){if(t>8)return r;let n;try{n=K(e,{withFileTypes:!0})}catch{return r}for(let s of n)if(s.isDirectory()){if(s.name.startsWith(".")||s.name==="node_modules")continue;x(S(e,s.name),t+1,r)}else s.isFile()&&s.name.endsWith(".bulb.md")&&r.push(S(e,s.name));return r}function Y(e){return x(e,0,[]).map(t=>{let r=0;try{r=H(t).mtimeMs}catch{}let n;try{n=d(z(t,"utf8").slice(0,1024))}catch{}return{path:t,name:n??U(t).replace(/\.bulb\.md$/,""),mtime:r}})}import{readFile as Q}from"fs/promises";var G={code:{path:"code.tsx",language:"typescript"},css:{path:"styles.css",language:"css"},html:{path:"index.html",language:"html"},config:{path:"config.json",language:"json"},notes:{path:"notes.md",language:"markdown"},data:{path:"data.txt",language:"text"},infer:{path:"infer.md",language:"markdown"},insight:{path:"insight.json",language:"json"},server:{path:"server.ts",language:"typescript"}};function B(e){try{let t=e.split(`
|
|
2
|
+
`),r=0;if(t[r]?.trim()!=="---")return null;r++;let n=[];for(;r<t.length&&t[r]?.trim()!=="---";)n.push(t[r]),r++;if(t[r]?.trim()!=="---")return null;r++;let s=V(n);if(!s)return null;let i=new Map;for(;r<t.length;){let l=t[r]?.trim()?.match(/^\*\*(.+)\*\*$/);if(l){let a=l[1].trim();for(r++;r<t.length&&t[r]?.trim()==="";)r++;let f=t[r]?.match(/^(`{3,})(\w*)\s*$/);if(!f){r++;continue}let T=f[1];r++;let w=[];for(;r<t.length&&!t[r]?.match(new RegExp(`^${T}\\s*$`));)w.push(t[r]),r++;r++,i.set(a,w.join(`
|
|
3
|
+
`))}else r++}return{frontmatter:s,files:i}}catch{return null}}function V(e){let t={};for(let r of e){let n=r.indexOf(":");if(n===-1)continue;let s=r.slice(0,n).trim(),i=r.slice(n+1).trim();switch(s){case"format":t.format=i;break;case"name":t.name=q(i);break}}return!t.format?.startsWith("typebulb")||!t.name?null:t}function q(e){return e.startsWith('"')&&e.endsWith('"')?e.slice(1,-1).replace(/\\"/g,'"'):e.startsWith("'")&&e.endsWith("'")?e.slice(1,-1):e}function F(e){let t=r=>e.files.get(G[r].path)||"";return{name:e.frontmatter.name,code:t("code"),css:t("css"),html:t("html"),config:t("config"),notes:t("notes"),data:t("data"),infer:t("infer"),insight:t("insight"),server:t("server")}}function P(e){if(e.server.trim())return"server-side code (server.ts)";let t=e.code;if(/\btb\s*\.\s*fs\b/.test(t)||t.includes("/__fs"))return"the filesystem";if(/\btb\s*\.\s*ai\b/.test(t)||t.includes("/__ai"))return"AI (your API keys)";if(/\btb\s*\.\s*server\s*\.\s*(?!log\b)\w/.test(t)||t.includes("/__api"))return"server-side code (server.ts)"}async function X(e){try{let t=B(await Q(e,"utf-8"));return t?P(F(t)):void 0}catch{return}}import{readFileSync as Z,writeFileSync as tt,mkdirSync as et}from"fs";import{join as rt}from"path";function j(){return rt(p(),"trust.json")}function y(){try{let e=JSON.parse(Z(j(),"utf8"));return new Set(Array.isArray(e)?e:[])}catch{return new Set}}function nt(e){et(p(),{recursive:!0}),tt(j(),JSON.stringify([...e]))}function st(e){return y().has(b(e))}function it(e,t){let r=y(),n=b(e);(t?r.has(n):!r.has(n))||(t?r.add(n):r.delete(n),nt(r))}function ot(){return[...y()]}export{d as bulbName,st as isBulbTrusted,M as launchBulbServer,Y as listBulbFiles,h as listBulbServers,ot as listTrustedBulbs,X as predictBulbTrust,O as readServerLog,m as serverLogPath,it as setBulbTrusted,W as slugifyBulbName,I as stopBulbServer,C as stripFrontmatter};
|