-
Notifications
You must be signed in to change notification settings - Fork 4
Feat execute bash #119
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
simongdavies
wants to merge
15
commits into
hyperlight-dev:main
Choose a base branch
from
simongdavies:feat-execute-bash
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Feat execute bash #119
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
d62fb74
feat: add execute_bash tool — sandboxed bash interpreter via just-bash
simongdavies 63ac5a1
feat: add execute_bash to system message workflow guidance
simongdavies 0c6242b
feat: wire execute_bash to show-code and code log
simongdavies 4a48b08
fix: add execute_bash to ALLOWED_TOOLS gating list
simongdavies 7eba69e
fix: add execute_bash to all skill allowed-tools lists
simongdavies 4953f0d
chore: gitignore output dirs and temp bundle file
simongdavies ac7cc5b
fix: add execute_bash to availableTools — the THIRD allowlist
simongdavies 8129f92
feat: native RDRAND-backed crypto and Math.random for sandbox
simongdavies 682e231
fix: isolate bash from JS sandbox — dedicated sandbox + blocked from …
simongdavies b10e888
fix: actionable memory error guidance for both execute_javascript and…
simongdavies 330ea07
feat: crypto.subtle.digest + Buffer.toString(encoding) for bash sandbox
simongdavies 6745db0
fix: use format! instead of alloc::format! for clippy without hyperli…
simongdavies 4d467de
fix: address all Copilot PR review comments (#119)
simongdavies 937e815
fix: add curl to bash commands, improve /sessions and /resume UX
simongdavies 6e4af50
fix: wire fetch plugin into bash curl + fix arrow keys in REPL
simongdavies File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| { | ||
| "name": "bash", | ||
| "description": "Sandboxed bash interpreter powered by just-bash. Provides 40+ Unix commands (ls, grep, jq, curl, sed, awk, etc.) running entirely in JavaScript inside the Hyperlight micro-VM.", | ||
| "author": "system", | ||
| "mutable": false, | ||
| "type": "script", | ||
| "sourceHash": "sha256:c53f56d194f34b81", | ||
| "hints": { | ||
| "overview": "Pure-JS bash interpreter for the sandbox. Used internally by the execute_bash tool — not intended for direct import in handlers." | ||
| } | ||
| } |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| #!/usr/bin/env node | ||
| // scripts/bash-bundle/build.mjs | ||
| // | ||
| // Builds the ha:bash module bundle from just-bash. | ||
| // Output: builtin-modules/bash.js (self-contained ESM module for QuickJS) | ||
| // | ||
| // Usage: node scripts/bash-bundle/build.mjs | ||
| // | ||
| // Prerequisites: npm install (just-bash and esbuild must be in node_modules) | ||
|
|
||
| import { execSync } from "node:child_process"; | ||
| import { readFileSync, writeFileSync, existsSync } from "node:fs"; | ||
| import { join, dirname } from "node:path"; | ||
| import { fileURLToPath } from "node:url"; | ||
|
|
||
| const __dirname = dirname(fileURLToPath(import.meta.url)); | ||
| const repoRoot = join(__dirname, "..", ".."); | ||
| const outFile = join(repoRoot, "builtin-modules", "bash.js"); | ||
|
|
||
| // ── Step 1: esbuild bundle ────────────────────────────────────────── | ||
|
|
||
| console.log("Building ha:bash bundle from just-bash..."); | ||
|
|
||
| const stubDir = __dirname; | ||
| const entryFile = join(stubDir, "entry.mjs"); | ||
|
|
||
| // Check prerequisites | ||
| if (!existsSync(join(repoRoot, "node_modules", "just-bash"))) { | ||
| console.error( | ||
| "Error: just-bash not found in node_modules. Run npm install first.", | ||
| ); | ||
| process.exit(1); | ||
| } | ||
|
|
||
| const aliasArgs = [ | ||
| `--alias:node:zlib=${join(stubDir, "zlib-stub.mjs")}`, | ||
| `--alias:node:worker_threads=${join(stubDir, "worker-stub.mjs")}`, | ||
| `--alias:node:path=${join(stubDir, "node-path-stub.mjs")}`, | ||
| `--alias:node:dns=${join(stubDir, "dns-stub.mjs")}`, | ||
| `--alias:node:crypto=${join(stubDir, "crypto-stub.mjs")}`, | ||
| `--alias:node:url=${join(stubDir, "url-stub.mjs")}`, | ||
| `--alias:node:fs=${join(stubDir, "fs-stub.mjs")}`, | ||
| `--alias:node:fs/promises=${join(stubDir, "fs-stub.mjs")}`, | ||
| `--alias:node:child_process=${join(stubDir, "worker-stub.mjs")}`, | ||
| `--alias:node:os=${join(stubDir, "worker-stub.mjs")}`, | ||
| `--alias:node:async_hooks=${join(stubDir, "worker-stub.mjs")}`, | ||
| `--alias:turndown=${join(stubDir, "turndown-stub.mjs")}`, | ||
| `--alias:seek-bzip=${join(stubDir, "bzip-stub.mjs")}`, | ||
| `--alias:node-liblzma=${join(stubDir, "liblzma-stub.mjs")}`, | ||
| `--alias:@mongodb-js/zstd=${join(stubDir, "zstd-stub.mjs")}`, | ||
| `--alias:sql.js=${join(stubDir, "sqljs-stub.mjs")}`, | ||
| ].join(" "); | ||
|
|
||
| const tmpBundle = join(stubDir, "_tmp_bundle.js"); | ||
|
|
||
| execSync( | ||
| `npx esbuild ${entryFile} ` + | ||
| `--bundle --format=esm --platform=neutral --target=es2020 ` + | ||
| `--main-fields=module,main ` + | ||
| `${aliasArgs} ` + | ||
| `--outfile=${tmpBundle} ` + | ||
| `--minify --tree-shaking=true`, | ||
| { stdio: "inherit", cwd: repoRoot }, | ||
| ); | ||
|
|
||
| // ── Step 2: Prepend polyfills ─────────────────────────────────────── | ||
|
|
||
| const polyfills = `// @module bash | ||
| // @description Sandboxed bash interpreter (just-bash) with polyfills for QuickJS | ||
| // @author system | ||
| // @generated DO NOT EDIT — built by scripts/bash-bundle/build.mjs | ||
|
|
||
| // ── QuickJS Polyfills ──────────────────────────────────────────────── | ||
| if(typeof globalThis.URL==='undefined'){globalThis.URL=class URL{constructor(input,base){let full=String(input);if(base&&!full.match(/^[a-z]+:\\/\\//i)){full=String(base).replace(/\\/[^\\/]*$/,'/')+full}const m=full.match(/^(https?:)\\/\\/([^\\/:]+)(:\\d+)?(\\/[^?#]*)?(\\?[^#]*)?(#.*)?$/i);if(m){this.protocol=m[1];this.hostname=m[2];this.port=m[3]?m[3].slice(1):'';this.pathname=m[4]||'/';this.search=m[5]||'';this.hash=m[6]||'';this.host=this.hostname+(this.port?':'+this.port:'');this.origin=this.protocol+'//'+this.host;this.href=this.origin+this.pathname+this.search+this.hash;this.searchParams=new URLSearchParams(this.search);this.username='';this.password=''}else{this.href=full;this.protocol='';this.hostname='';this.port='';this.pathname=full;this.search='';this.hash='';this.host='';this.origin='';this.searchParams=new URLSearchParams();this.username='';this.password=''}}toString(){return this.href}}} | ||
| if(typeof globalThis.URLSearchParams==='undefined'){globalThis.URLSearchParams=class URLSearchParams{constructor(init){this._p=[];if(typeof init==='string'){const s=init.startsWith('?')?init.slice(1):init;for(const pair of s.split('&')){const[k,v]=pair.split('=');if(k)this._p.push([decodeURIComponent(k),decodeURIComponent(v||'')])}}}get(k){const p=this._p.find(([a])=>a===k);return p?p[1]:null}has(k){return this._p.some(([a])=>a===k)}toString(){return this._p.map(([k,v])=>encodeURIComponent(k)+'='+encodeURIComponent(v)).join('&')}entries(){return this._p[Symbol.iterator]()}[Symbol.iterator](){return this._p[Symbol.iterator]()}forEach(fn){this._p.forEach(([k,v])=>fn(v,k))}}} | ||
| if(typeof globalThis.Buffer==='undefined'){const _e=new TextEncoder();const _d=new TextDecoder();class HaBuffer extends Uint8Array{toString(encoding){if(!encoding||encoding==='utf-8'||encoding==='utf8')return _d.decode(this);if(encoding==='base64')return btoa(String.fromCharCode.apply(null,this));if(encoding==='latin1'||encoding==='binary'){let s='';for(let i=0;i<this.length;i++)s+=String.fromCharCode(this[i]);return s}if(encoding==='hex'){let s='';for(let i=0;i<this.length;i++)s+=this[i].toString(16).padStart(2,'0');return s}return _d.decode(this)}}globalThis.Buffer={from(d,e){if(typeof d==='string'){if(e==='base64'){const b=atob(d);const a=new HaBuffer(b.length);for(let i=0;i<b.length;i++)a[i]=b.charCodeAt(i);return a}if(e==='hex'){const a=new HaBuffer(d.length/2);for(let i=0;i<d.length;i+=2)a[i/2]=parseInt(d.substr(i,2),16);return a}const enc=_e.encode(d);const r=new HaBuffer(enc.length);r.set(enc);return r}if(d instanceof Uint8Array){const r=new HaBuffer(d.length);r.set(d);return r}if(Array.isArray(d))return new HaBuffer(d);return new HaBuffer(0)},isBuffer(o){return o instanceof Uint8Array},concat(l){const t=l.reduce((s,b)=>s+b.length,0);const r=new HaBuffer(t);let o=0;for(const b of l){r.set(b,o);o+=b.length}return r},alloc(s){return new HaBuffer(s)},byteLength(s,e){if(typeof s==='string')return _e.encode(s).length;return s.length}}} | ||
| if(typeof globalThis.process==='undefined'){globalThis.process={env:{},nextTick(fn){queueMicrotask(fn)},execPath:'/usr/bin/node',mainModule:null,umask(){return 18},type:'renderer'}} | ||
| if(typeof globalThis.AbortController==='undefined'){globalThis.AbortController=class AbortController{constructor(){this.signal={aborted:false,addEventListener(){}}}abort(){this.signal.aborted=true}}} | ||
| // crypto.getRandomValues, crypto.randomUUID, and Math.random are provided | ||
| // natively by the Hyperlight runtime via RDRAND — no JS polyfill needed. | ||
| if(typeof globalThis.setTimeout==='undefined'){globalThis.setTimeout=(fn)=>{fn();return 0};globalThis.clearTimeout=()=>{};globalThis.setInterval=()=>0;globalThis.clearInterval=()=>{}} | ||
| if(typeof globalThis.performance==='undefined'){globalThis.performance={now(){return Date.now()}}} | ||
| // ── End Polyfills ──────────────────────────────────────────────────── | ||
|
|
||
| `; | ||
|
|
||
| const bundleSource = readFileSync(tmpBundle, "utf-8"); | ||
| const output = polyfills + bundleSource; | ||
| writeFileSync(outFile, output); | ||
|
|
||
| // Clean up temp file | ||
| try { | ||
| require("node:fs").unlinkSync(tmpBundle); | ||
| } catch {} | ||
|
|
||
| const sizeKb = (output.length / 1024).toFixed(0); | ||
| console.log(`\\n✅ Built builtin-modules/bash.js (${sizeKb} KB)`); | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export default { decode() { throw new Error("bzip2: not available in sandbox"); } }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| // Stub for node:crypto | ||
| export function randomBytes(n) { | ||
| const buf = new Uint8Array(n); | ||
| for (let i = 0; i < n; i++) buf[i] = Math.floor(Math.random() * 256); | ||
| return buf; | ||
| } | ||
| export function randomUUID() { | ||
| const h = "0123456789abcdef"; | ||
| let u = ""; | ||
| for (let i = 0; i < 36; i++) { | ||
| if (i === 8 || i === 13 || i === 18 || i === 23) u += "-"; | ||
| else u += h[Math.floor(Math.random() * 16)]; | ||
| } | ||
| return u; | ||
| } | ||
| export function createHash() { | ||
| throw new Error("createHash: not available in sandbox"); | ||
| } | ||
| export default { randomBytes, randomUUID, createHash }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| // Stub for node:dns — just-bash uses this for network allow-list validation | ||
| // We handle networking through host:fetch plugin, so DNS lookup is not needed | ||
| export function lookup(hostname, opts, cb) { | ||
| if (typeof opts === "function") { cb = opts; opts = {}; } | ||
| // Return a dummy address — our fetch plugin does its own SSRF checks | ||
| if (cb) cb(null, "0.0.0.0", 4); | ||
| } | ||
| export default { lookup }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| // Entry point for esbuild bundling of just-bash for QuickJS/Hyperlight | ||
| // Re-exports only what we need, stubs out node:zlib | ||
| export { Bash } from "just-bash"; | ||
| export { InMemoryFs } from "just-bash"; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| // Stub for node:fs — just-bash's ReadWriteFs uses this for real FS | ||
| // We don't use ReadWriteFs — we use our own IFileSystem adapter | ||
| // But the import exists in the bundle, so we stub it | ||
| export function readFileSync() { throw new Error("node:fs not available in sandbox"); } | ||
| export function writeFileSync() { throw new Error("node:fs not available in sandbox"); } | ||
| export function existsSync() { return false; } | ||
| export function statSync() { throw new Error("node:fs not available in sandbox"); } | ||
| export function readdirSync() { return []; } | ||
| export function mkdirSync() { throw new Error("node:fs not available in sandbox"); } | ||
| export function unlinkSync() { throw new Error("node:fs not available in sandbox"); } | ||
| export function rmdirSync() { throw new Error("node:fs not available in sandbox"); } | ||
| export function chmodSync() { throw new Error("node:fs not available in sandbox"); } | ||
| export function symlinkSync() { throw new Error("node:fs not available in sandbox"); } | ||
| export function linkSync() { throw new Error("node:fs not available in sandbox"); } | ||
| export function readlinkSync() { throw new Error("node:fs not available in sandbox"); } | ||
| export function realpathSync() { throw new Error("node:fs not available in sandbox"); } | ||
| export function lstatSync() { throw new Error("node:fs not available in sandbox"); } | ||
| export function utimesSync() { throw new Error("node:fs not available in sandbox"); } | ||
| export function copyFileSync() { throw new Error("node:fs not available in sandbox"); } | ||
| export function renameSync() { throw new Error("node:fs not available in sandbox"); } | ||
| export async function open() { throw new Error("node:fs/promises not available in sandbox"); } | ||
| export default {}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export default null; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| // Minimal node:path polyfill for just-bash | ||
| export function join(...parts) { | ||
| return parts.filter(Boolean).join("/").replace(/\/+/g, "/"); | ||
| } | ||
| export function resolve(...parts) { | ||
| let result = ""; | ||
| for (const part of parts) { | ||
| if (part.startsWith("/")) result = part; | ||
| else result = result ? result + "/" + part : part; | ||
| } | ||
| return normalize(result || "/"); | ||
| } | ||
| export function normalize(p) { | ||
| const absolute = p.startsWith("/"); | ||
| const parts = p.split("/"); | ||
| const out = []; | ||
| for (const part of parts) { | ||
| if (part === "..") { | ||
| if (out.length > 0) out.pop(); | ||
| else if (!absolute) out.push(".."); | ||
| } | ||
| else if (part !== "." && part !== "") out.push(part); | ||
| } | ||
| const normalized = (absolute ? "/" : "") + out.join("/"); | ||
| return normalized || (absolute ? "/" : "."); | ||
| } | ||
| export function dirname(p) { | ||
| const i = p.lastIndexOf("/"); | ||
| return i <= 0 ? (p.startsWith("/") ? "/" : ".") : p.slice(0, i); | ||
| } | ||
| export function basename(p, ext) { | ||
| let b = p.split("/").pop() || ""; | ||
| if (ext && b.endsWith(ext)) b = b.slice(0, -ext.length); | ||
| return b; | ||
| } | ||
| export function extname(p) { | ||
| const b = basename(p); | ||
| const i = b.lastIndexOf("."); | ||
| return i > 0 ? b.slice(i) : ""; | ||
| } | ||
| export function isAbsolute(p) { return p.startsWith("/"); } | ||
| export function relative(from, to) { | ||
| const f = resolve(from).split("/").filter(Boolean); | ||
| const t = resolve(to).split("/").filter(Boolean); | ||
| let i = 0; | ||
| while (i < f.length && i < t.length && f[i] === t[i]) i++; | ||
| const ups = f.length - i; | ||
| return [...Array(ups).fill(".."), ...t.slice(i)].join("/") || "."; | ||
| } | ||
| export const sep = "/"; | ||
| export const delimiter = ":"; | ||
| export const posix = { join, resolve, normalize, dirname, basename, extname, isAbsolute, relative, sep, delimiter }; | ||
| export default { join, resolve, normalize, dirname, basename, extname, isAbsolute, relative, sep, delimiter, posix }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| // Stub for sql.js — sqlite3 not supported in sandbox | ||
| export default function () { | ||
| throw new Error("sqlite3: not available in sandbox"); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| // Stub for turndown (html-to-markdown) — not needed in sandbox | ||
| export default class TurndownService { | ||
| constructor() {} | ||
| turndown(html) { return html.replace(/<[^>]+>/g, ''); } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| // Stub for node:url | ||
| export function fileURLToPath(url) { | ||
| if (typeof url === "string" && url.startsWith("file://")) return url.slice(7); | ||
| return String(url); | ||
| } | ||
| export function pathToFileURL(p) { return new URL("file://" + p); } | ||
| export default { fileURLToPath, pathToFileURL }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| // Stub for node:worker_threads and node:async_hooks | ||
| export class Worker { | ||
| constructor() { throw new Error("Workers not available in this environment"); } | ||
| } | ||
| export const parentPort = null; | ||
| export const workerData = null; | ||
| export const isMainThread = true; | ||
| export class AsyncLocalStorage { | ||
| getStore() { return undefined; } | ||
| run(store, fn) { return fn(); } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| // Stub for node:zlib — just-bash's gzip/tar commands use this | ||
| export function gzipSync(data) { | ||
| throw new Error("gzip: not available in this environment. Use the ha:zip-format module in a JavaScript handler instead."); | ||
| } | ||
| export function gunzipSync(data) { | ||
| throw new Error("gunzip: not available in this environment. Use the ha:zip-format module in a JavaScript handler instead."); | ||
| } | ||
| export function deflateSync(data) { return gzipSync(data); } | ||
| export function inflateSync(data) { return gunzipSync(data); } | ||
| export const constants = { Z_SYNC_FLUSH: 0, Z_FINISH: 4, Z_DEFAULT_COMPRESSION: -1, Z_NO_COMPRESSION: 0, Z_BEST_COMPRESSION: 9 }; | ||
| export default { gzipSync, gunzipSync, deflateSync, inflateSync, constants }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export default null; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -140,4 +140,19 @@ execSync("npx tsx scripts/generate-host-modules-dts.ts", { | |
| stdio: "inherit", | ||
| }); | ||
|
|
||
| // Step 9: Rebuild ha:bash bundle from just-bash (if just-bash is installed) | ||
| try { | ||
| const justBashPath = join(ROOT, "node_modules", "just-bash"); | ||
| if (existsSync(justBashPath)) { | ||
| console.log("\nRebuilding ha:bash bundle from just-bash..."); | ||
| execSync("node scripts/bash-bundle/build.mjs", { | ||
| cwd: ROOT, | ||
| stdio: "inherit", | ||
| }); | ||
| } | ||
| } catch (e) { | ||
| console.error(" ⚠️ bash bundle build failed:", e.message); | ||
| // Non-fatal — bash is optional, core agent works without it | ||
| } | ||
|
Comment on lines
+143
to
+156
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Aplicado no commit c6c029a6. Description atualizada pra deixar explícito: somente dígitos (10-15), sem |
||
|
|
||
| console.log("✓ Build complete"); | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aplicado no commit c6c029a6. Helper privado removido, agora usa
StringUtils.isBlank(já importado paraextractFirstName).