oioxo-mcp 0.5.90 → 0.5.91
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/bundle/cli.js +3 -3
- package/package.json +2 -2
package/bundle/cli.js
CHANGED
|
@@ -667,8 +667,8 @@ ${h.map((b,_)=>`${_+1}. [${b.done?"x":" "}] ${b.title}`).join(`
|
|
|
667
667
|
${y} left.`},files:a,plan:h}}case"shell":{let c=String(s.command??s.cmd??"").trim();if(!c)return{result:{ok:!1,output:'shell needs a "command".'},files:a};if(!r.shell)return{result:{ok:!1,output:"No shell here (this surface is sandboxed). Use writeFile/editFile to change code and runTests/typecheck to verify. On the CLI/desktop, shell runs real commands."},files:a};if(/\brm\s+-rf\s+[~/]|:\(\)\s*\{|\bmkfs\b|\bdd\s+if=|\bshutdown\b|\bformat\s+[A-Za-z]:|\b>\s*\/dev\/sd/.test(c))return{result:{ok:!1,output:"Refused \u2014 that command looks destructive to the system. Run commands scoped to this project only."},files:a};try{let{code:d,output:h}=await r.shell(c),p=h.length>4e3?`\u2026
|
|
668
668
|
`+h.slice(-4e3):h;return{result:{ok:d===0,output:`$ ${c}
|
|
669
669
|
(exit ${d})
|
|
670
|
-
${p||"(no output)"}`},files:a}}catch(d){return{result:{ok:!1,output:`shell failed: ${d instanceof Error?d.message:String(d)}`},files:a}}}case"spawn":{let c=String(s.task??s.prompt??"").trim();if(!c)return{result:{ok:!1,output:'spawn needs a "task" \u2014 one clear, bounded job with a definite deliverable.'},files:a};if(!r.spawn)return{result:{ok:!1,output:"No sub-agents on this surface \u2014 just do the work yourself with writeFile/editFile/shell."},files:a};try{let d=await r.spawn(c,a),h=d.files&&d.files.length?IO(a,d.files.map(y=>({path:y.path,content:y.content}))):a,p=h.length-a.length;return{result:{ok:!0,output:`Sub-agent finished${p>0?` (+${p} file${p===1?"":"s"})`:""}: ${(d.result||"(no summary)").slice(0,1500)}`},files:h}}catch(d){return{result:{ok:!1,output:`Sub-agent failed: ${d instanceof Error?d.message:String(d)}. Do this part yourself.`},files:a}}}case"ask":{let c=String(s.question??"").trim();return c?{result:{ok:!0,output:`(asked the user: ${c})`},files:a,control:{kind:"ask",question:c}}:{result:{ok:!1,output:'ask needs a "question".'},files:a}}case"done":{let c=(e.doneAttempts??0)+1,d=a.some(
|
|
671
|
-
${
|
|
670
|
+
${p||"(no output)"}`},files:a}}catch(d){return{result:{ok:!1,output:`shell failed: ${d instanceof Error?d.message:String(d)}`},files:a}}}case"spawn":{let c=String(s.task??s.prompt??"").trim();if(!c)return{result:{ok:!1,output:'spawn needs a "task" \u2014 one clear, bounded job with a definite deliverable.'},files:a};if(!r.spawn)return{result:{ok:!1,output:"No sub-agents on this surface \u2014 just do the work yourself with writeFile/editFile/shell."},files:a};try{let d=await r.spawn(c,a),h=d.files&&d.files.length?IO(a,d.files.map(y=>({path:y.path,content:y.content}))):a,p=h.length-a.length;return{result:{ok:!0,output:`Sub-agent finished${p>0?` (+${p} file${p===1?"":"s"})`:""}: ${(d.result||"(no summary)").slice(0,1500)}`},files:h}}catch(d){return{result:{ok:!1,output:`Sub-agent failed: ${d instanceof Error?d.message:String(d)}. Do this part yourself.`},files:a}}}case"ask":{let c=String(s.question??"").trim();return c?{result:{ok:!0,output:`(asked the user: ${c})`},files:a,control:{kind:"ask",question:c}}:{result:{ok:!1,output:'ask needs a "question".'},files:a}}case"done":{let c=(e.doneAttempts??0)+1,d=a.some(b=>/(^|\/)(test_|tests?\/)|\.(test|spec)\./i.test(b.path)||/(^|\/)test/i.test(b.path)),h=b=>{if(b.done)return!0;let _=b.title.toLowerCase().replace(/^(build|write|create|add|implement)\s+/,"").trim();return!!(/\b(test|spec)\b/.test(b.title.toLowerCase())&&d||/[\w./-]+\.[a-z0-9]{1,4}$/i.test(_)&&a.some(A=>A.path.toLowerCase().includes(_)))},p=(e.plan??[]).filter(b=>/\b(build|write|create|add|implement)\b/i.test(b.title)&&!/verify|run tests|run \+/i.test(b.title)&&!h(b));if(p.length&&c<=3){let b=p[0];return{result:{ok:!1,output:`Not done yet \u2014 ${p.length} planned file(s) still missing. Do the NEXT one now: "${b.title}". (If it's genuinely covered already, check it off with plan {"check":"${b.title.replace(/^build\s+/,"").slice(0,20)}"}.)`},files:a,doneAttempts:c}}let x=/builds your app here|Design and structure are yours|Scaffolded by OIOXO/i;if(!a.some(b=>/\.(html|js|jsx|ts|tsx|css|py|php|lua|sql|c|cpp|h|go|rs|rb|java|vue|svelte)$/i.test(b.path)?(b.content||"").replace(x,"").replace(/<!--[\s\S]*?-->|\/\*[\s\S]*?\*\//g,"").replace(/<!doctype html>|<\/?html[^>]*>|<\/?head>|<\/?body>|<meta[^>]*>|<title>[^<]*<\/title>/gi,"").trim().length>40:!1)&&c<=4)return{result:{ok:!1,output:`Not done \u2014 no real code was written yet; the project is still the empty starter. WRITE the actual app now: use writeFile with the full working code for "${e.goal}". Put the complete code in the right file, not a placeholder.`},files:a,doneAttempts:c};if(r.review&&!e.reviewed){let b=await r.review(e.goal,a).catch(()=>[]);if(b.length)return{result:{ok:!1,output:`Not done yet \u2014 a review found issues to fix first:
|
|
671
|
+
${b.slice(0,6).map((_,A)=>`${A+1}. ${_}`).join(`
|
|
672
672
|
`)}
|
|
673
673
|
Fix these, then call done again.`},files:a,reviewed:!0}}return{result:{ok:!0,output:"done"},files:a,control:{kind:"done",summary:String(s.summary??"Done.")}}}default:{let c=String(i).toLowerCase();if(/folder|dir|mkdir|directory/.test(c)){let d=String(s.path??s.name??"pkg");return{result:{ok:!1,output:`There is no folder tool \u2014 folders are created automatically from file paths. Don't create "${d}" as a folder; just writeFile a file inside it, e.g. {"tool":"writeFile","args":{"path":"${d.replace(/\/$/,"")}/__init__.py"}} (or your first real module). Go ahead and write the first file now.`},files:a}}return/^(create|new|add|make)file$/.test(c)||c==="create"||c==="write"?{result:{ok:!1,output:`Use "writeFile" (not "${i}") to create a file, with the full contents in a fenced block right after the tool JSON.`},files:a}:/shell|bash|exec|run(command|cmd)|terminal/.test(c)?{result:{ok:!1,output:r.shell?'Use the "shell" tool: {"tool":"shell","args":{"command":"..."}}.':"No shell on this surface. To verify use runTests {} / typecheck {}; to change files use writeFile / editFile."},files:a}:{result:{ok:!1,output:`unknown tool: ${i}. Use one of: listFiles, readFile, writeFile, editFile, search, typecheck, runTests, updateProgress, ask, done. Folders are implicit \u2014 writeFile a path like "taskflow/storage.py" to create the folder.`},files:a}}}}function rht(t,e,r,n){let i=t.files.map(E=>E.path).join(", ")||"(no files yet)",s=t.turns.find(E=>E.role==="summary"),a=n&&(n.projectMemory||n.memories.length)?[n.projectMemory?`Project memory (OIOXO.md \u2014 what you know about THIS project; honor it):
|
|
674
674
|
${n.projectMemory.slice(0,1500)}`:"",n.memories.length?`You remember (from earlier work with this user):
|
|
@@ -1461,7 +1461,7 @@ ${C.snippet}`:""}`).join(`
|
|
|
1461
1461
|
`);return Zs(A||"No results.")}catch(b){return Zs(`web_search failed: ${b instanceof Error?b.message:"error"}`)}}),e.tool("fetch_url","Fetch a web page (http/https only) and return its readable text. Use to read a doc/article \u2014 typically a URL found via web_search.",{url:lo.string().describe("The full http(s) URL.")},async({url:x})=>{let y=await yA();if(!y.ok)return xA(y.message);try{let _=await(await fetch(`${Ci}/tools/fetch?url=${encodeURIComponent(x)}`,{signal:AbortSignal.timeout(12e3)})).json();return Zs(_.error?`fetch_url failed: ${_.error}`:_.text??"(empty)")}catch(b){return Zs(`fetch_url failed: ${b instanceof Error?b.message:"error"}`)}});let c=null,d=!1,h=async x=>{if(d=x,c)return c;let{makePlaywrightBackend:y}=await Promise.resolve().then(()=>($O(),LO)),{BrowserController:b}=await Promise.resolve().then(()=>($k(),pK)),_=await y({headless:!1});return c=new b(_,{confirmNavigate:async()=>d,allowEvaluate:!1}),c};e.tool("browser",'Drive a REAL browser on this machine to see and test web pages \u2014 navigate, read a numbered snapshot of clickable elements, click/type by ref, screenshot. Runs LOCALLY (the page never leaves the device). Local URLs (localhost) are always allowed; set allow_external:true to permit other sites. Call one verb at a time; after navigate the result lists elements like [3] button "Sign in" \u2014 click by that ref.',{verb:lo.enum(["navigate","snapshot","screenshot","click","type","waitFor","scrollTo","back","reload","close"]).describe("The action."),url:lo.string().optional().describe("For navigate: the URL."),ref:lo.number().optional().describe("For click/type/scrollTo: element number from the latest snapshot."),text:lo.string().optional().describe("For type: text to enter. For click: visible text to match. For waitFor: text to wait for."),selector:lo.string().optional().describe("Optional CSS selector (prefer ref)."),submit:lo.boolean().optional().describe("For type: press Enter after typing."),allow_external:lo.boolean().optional().describe("Permit navigating to non-local sites (privacy gate; default false).")},async({verb:x,url:y,ref:b,text:_,selector:A,submit:C,allow_external:k})=>{let T=await yA();if(!T.ok)return xA(T.message);try{let E=await h(!!k);if(x==="close")return await E.dispose(),c=null,Zs("Browser closed.");let I=await E.run({verb:x,url:y,ref:b,text:_,selector:A,submit:C});if(!I.ok)return Zs(`browser ${x} failed: ${I.error??"unknown error"}`);let O=`${I.title||""} \u2014 ${I.url}`.trim(),U=I.snapshot?`
|
|
1462
1462
|
${I.snapshot}`:"",L=I.consoleErrors?.length?`
|
|
1463
1463
|
console errors: ${I.consoleErrors.slice(0,3).join(" | ")}`:"",V=`${O}${U}${L}`.trim()||"OK";if(I.screenshot){let G=aFt(I.screenshot);return{content:[{type:"text",text:`${V}
|
|
1464
|
-
(screenshot attached${G?` \u2014 ${G.width}x${G.height}px`:""}, ${I.screenshot.length} bytes)`},{type:"image",data:Buffer.from(I.screenshot).toString("base64"),mimeType:"image/png"}]}}return Zs(V)}catch(E){return Zs(`browser failed: ${E instanceof Error?E.message:"error"}`)}});let p=new xL;await e.connect(p)}w5();iE();Ao();var Oue=(()=>{try{return"0.5.
|
|
1464
|
+
(screenshot attached${G?` \u2014 ${G.width}x${G.height}px`:""}, ${I.screenshot.length} bytes)`},{type:"image",data:Buffer.from(I.screenshot).toString("base64"),mimeType:"image/png"}]}}return Zs(V)}catch(E){return Zs(`browser failed: ${E instanceof Error?E.message:"error"}`)}});let p=new xL;await e.connect(p)}w5();iE();Ao();var Oue=(()=>{try{return"0.5.91"}catch{}try{return Q$e(import.meta.url)("../../package.json").version}catch{return"0.0.0"}})(),cOt=`OIOXO ${Oue} \u2014 context engine + terminal coding agent (https://oioxo.com)
|
|
1465
1465
|
|
|
1466
1466
|
Private, on your device. Cut your AI bill by up to ~90% in Copilot, Cursor & Claude,
|
|
1467
1467
|
and code from your terminal \u2014 nothing leaves your machine.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oioxo-mcp",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.91",
|
|
4
4
|
"description": "OIOXO — cut your AI bill by up to ~90%: it feeds Claude Code, Copilot, Cursor and any MCP agent only the relevant slice of your codebase instead of whole files. Also a private terminal coding agent (`oioxo code`, on-device with --local or any key). Runs on your device; your own devices can build together over Wi-Fi.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
6
6
|
"type": "module",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"build": "npm run clean && tsc -p tsconfig.json",
|
|
27
27
|
"bundle": "npm run build && node scripts/bundle.mjs",
|
|
28
28
|
"setup-engine": "node scripts/setup-engine.mjs",
|
|
29
|
-
"test": "npm run build && node --test dist/test/core.test.js dist/test/e2e.test.js dist/test/coder.test.js dist/test/discovery.test.js dist/test/crew.test.js dist/test/browser.test.js dist/test/cascade.test.js dist/test/mentions.test.js dist/test/memory.test.js",
|
|
29
|
+
"test": "node scripts/check-agent-core-parity.mjs && npm run build && node --test dist/test/core.test.js dist/test/e2e.test.js dist/test/coder.test.js dist/test/discovery.test.js dist/test/crew.test.js dist/test/browser.test.js dist/test/cascade.test.js dist/test/mentions.test.js dist/test/memory.test.js",
|
|
30
30
|
"serve": "node dist/cli/index.js serve"
|
|
31
31
|
},
|
|
32
32
|
"keywords": [
|