Spaces:
Running
Running
| // core/code-tools.js — NATIVE agentic-coding tools for Holo Q's Code mode. Self-contained over the | |
| // browser's OPFS (navigator.storage.getDirectory) — no external VFS, works in any browser, 100% | |
| // serverless. Each tool returns Holo Q's agent-tool shape { def, serverName:"code", call }, so the | |
| // Coder-7B brain drives real file work through the existing agentic loop + conscience gate + receipts. | |
| // The workspace is an OPFS "workspace" dir = the agent's writable home; every result is content-addressable. | |
| // | |
| // C2 semantic skin (extended to all κ-objects): build_app emits a schema:SoftwareApplication node and | |
| // verify_object returns the file's schema.org @type — so every object the agent makes is W3C-legible. | |
| import { appAsSoftware, fileAsDocument } from "./semantic.js"; | |
| const te = new TextEncoder(), td = new TextDecoder(); | |
| const sha256Hex = async (bytes) => [...new Uint8Array(await crypto.subtle.digest("SHA-256", bytes))].map((b) => b.toString(16).padStart(2, "0")).join(""); | |
| const norm = (p) => ("/" + String(p || "").replace(/^\/+/, "").replace(/\/+/g, "/")).replace(/\/$/, "") || "/"; | |
| async function root() { const d = await navigator.storage.getDirectory(); return d.getDirectoryHandle("workspace", { create: true }); } | |
| async function dirOf(parts, create = false) { | |
| let h = await root(); | |
| for (const p of parts) if (p) h = await h.getDirectoryHandle(p, { create }); | |
| return h; | |
| } | |
| function split(path) { const parts = norm(path).split("/").filter(Boolean); const name = parts.pop(); return { parts, name }; } | |
| async function readFile(path) { | |
| const { parts, name } = split(path); | |
| const dir = await dirOf(parts); | |
| const fh = await dir.getFileHandle(name); | |
| const f = await fh.getFile(); | |
| return new Uint8Array(await f.arrayBuffer()); | |
| } | |
| async function writeFile(path, content) { | |
| const { parts, name } = split(path); | |
| const dir = await dirOf(parts, true); | |
| const fh = await dir.getFileHandle(name, { create: true }); | |
| const w = await fh.createWritable(); await w.write(te.encode(String(content ?? ""))); await w.close(); | |
| } | |
| async function walk(dirHandle, prefix, out) { | |
| for await (const [n, h] of dirHandle.entries()) { | |
| const p = prefix + "/" + n; | |
| if (h.kind === "file") out.push(p); | |
| else await walk(h, p, out); | |
| } | |
| } | |
| async function listAll() { const out = []; await walk(await root(), "", out); return out.sort(); } | |
| function globToRe(glob) { | |
| let re = "^"; | |
| for (let i = 0; i < glob.length; i++) { const c = glob[i]; | |
| if (c === "*") { if (glob[i + 1] === "*") { re += ".*"; i++; if (glob[i + 1] === "/") i++; } else re += "[^/]*"; } | |
| else if (c === "?") re += "[^/]"; else if ("\\^$.|+()[]{}".includes(c)) re += "\\" + c; else re += c; } | |
| return new RegExp(re + "$"); | |
| } | |
| export function codeTools() { | |
| return [ | |
| { | |
| def: { name: "read_file", description: "Read a text file from the workspace. Returns its content.", inputSchema: { type: "object", properties: { path: { type: "string" } }, required: ["path"] } }, | |
| serverName: "code", call: async ({ path }) => { | |
| try { const bytes = await readFile(path); return { text: td.decode(bytes), isError: false }; } | |
| catch (e) { return { text: "read error: " + (e.message || e), isError: true }; } | |
| }, | |
| }, | |
| { | |
| def: { name: "write_file", description: "Create or overwrite a file in the workspace with the given content.", inputSchema: { type: "object", properties: { path: { type: "string" }, content: { type: "string" } }, required: ["path", "content"] } }, | |
| serverName: "code", call: async ({ path, content }) => { | |
| try { await writeFile(path, content); const k = await sha256Hex(te.encode(String(content ?? ""))); return { text: `wrote ${norm(path)} (${String(content ?? "").length} bytes) · did:holo:sha256:${k.slice(0, 16)}`, isError: false }; } | |
| catch (e) { return { text: "write error: " + (e.message || e), isError: true }; } | |
| }, | |
| }, | |
| { | |
| def: { name: "edit_file", description: "Replace the first exact occurrence of old_text with new_text in a file.", inputSchema: { type: "object", properties: { path: { type: "string" }, old_text: { type: "string" }, new_text: { type: "string" } }, required: ["path", "old_text", "new_text"] } }, | |
| serverName: "code", call: async ({ path, old_text, new_text }) => { | |
| try { const cur = td.decode(await readFile(path)); if (!cur.includes(old_text)) return { text: "edit error: old_text not found", isError: true }; | |
| const next = cur.replace(old_text, new_text); await writeFile(path, next); return { text: `edited ${norm(path)} (${cur.length}→${next.length} bytes)`, isError: false }; } | |
| catch (e) { return { text: "edit error: " + (e.message || e), isError: true }; } | |
| }, | |
| }, | |
| { | |
| def: { name: "list_files", description: "List all files in the workspace, optionally filtered by a glob (e.g. **/*.py).", inputSchema: { type: "object", properties: { glob: { type: "string" } }, required: [] } }, | |
| serverName: "code", call: async ({ glob }) => { | |
| try { let files = await listAll(); if (glob) { const re = globToRe(glob); files = files.filter((f) => re.test(f)); } | |
| return { text: files.length ? files.join("\n") : "(workspace empty)", isError: false }; } | |
| catch (e) { return { text: "list error: " + (e.message || e), isError: true }; } | |
| }, | |
| }, | |
| { | |
| def: { name: "grep", description: "Search file contents for a regular expression. Returns matching path:line: text.", inputSchema: { type: "object", properties: { pattern: { type: "string" }, glob: { type: "string" } }, required: ["pattern"] } }, | |
| serverName: "code", call: async ({ pattern, glob }) => { | |
| try { const re = new RegExp(pattern); let files = await listAll(); if (glob) { const g = globToRe(glob); files = files.filter((f) => g.test(f)); } | |
| const hits = []; | |
| for (const f of files) { let text; try { text = td.decode(await readFile(f)); } catch { continue; } | |
| text.split("\n").forEach((ln, i) => { if (re.test(ln) && hits.length < 100) hits.push(`${f}:${i + 1}: ${ln.trim().slice(0, 160)}`); }); } | |
| return { text: hits.length ? hits.join("\n") : "(no matches)", isError: false }; } | |
| catch (e) { return { text: "grep error: " + (e.message || e), isError: true }; } | |
| }, | |
| }, | |
| // ── κ-NATIVE: build a RENDERABLE app object, sealed (the neural-computer flagship: an agent | |
| // produces a real app, content-addressed, that renders + re-derives — serverless, verifiable) ── | |
| { | |
| def: { name: "build_app", description: "Build a complete self-contained HTML app (one file, inline CSS/JS) and seal it as a content-addressed object. Returns its did:holo κ; the app renders live in the preview pane. Use for 'build me an app/page/tool' requests.", inputSchema: { type: "object", properties: { name: { type: "string" }, html: { type: "string" } }, required: ["name", "html"] } }, | |
| serverName: "code", call: async ({ name, html }) => { | |
| try { | |
| const path = (name.endsWith(".html") ? name : name + ".html"); | |
| await writeFile(path, html); | |
| const bytes = te.encode(String(html)); | |
| const kappa = "did:holo:sha256:" + await sha256Hex(bytes); | |
| // semantic skin: the app object carries a W3C @type (schema:SoftwareApplication + prov:Entity), | |
| // written as a sidecar .jsonld so the object is self-describing to any agent / RDF tool. | |
| const ld = appAsSoftware({ name: path, kappa, bytes: bytes.length }); | |
| await writeFile(path.replace(/\.html$/i, "") + ".app.jsonld", JSON.stringify(ld, null, 1)); | |
| return { text: `built app "${path}" (${html.length} bytes), sealed ${kappa.slice(0, 30)}… · typed ${ld["@type"].join("+")} — renders in the preview, re-derivable (Law L5).`, isError: false, render: { kind: "app", path: norm(path), kappa, html: String(html), ld } }; | |
| } catch (e) { return { text: "build_app error: " + (e.message || e), isError: true }; } | |
| }, | |
| }, | |
| { | |
| def: { name: "verify_object", description: "Re-derive a workspace file's content address and confirm it matches (Law L5 — verify every byte). Returns whether the bytes are authentic.", inputSchema: { type: "object", properties: { path: { type: "string" }, kappa: { type: "string" } }, required: ["path"] } }, | |
| serverName: "code", call: async ({ path, kappa }) => { | |
| try { | |
| const bytes = await readFile(path); | |
| const got = "did:holo:sha256:" + await sha256Hex(bytes); | |
| const ok = !kappa || got === kappa || got.startsWith(kappa) || kappa.startsWith(got.slice(0, kappa.length)); | |
| // verify = re-derive κ (Law L5) AND emit the W3C @type — apps are SoftwareApplication, all else DigitalDocument. | |
| const ld = /\.html$/i.test(path) ? appAsSoftware({ name: norm(path), kappa: got, bytes: bytes.length }) | |
| : fileAsDocument({ path: norm(path), kappa: got, bytes: bytes.length }); | |
| return { text: `${norm(path)} re-derives to ${got.slice(0, 34)}…${kappa ? (ok ? " ✓ matches (authentic)" : " ✗ MISMATCH") : ""} · @type ${ld["@type"].join("+")}`, isError: false, render: { kind: "linked-data", ld } }; | |
| } catch (e) { return { text: "verify error: " + (e.message || e), isError: true }; } | |
| }, | |
| }, | |
| ]; | |
| } | |