kart-code 0.0.0-stage → 0.1.0
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/dist/bundle.js +69 -0
- package/package.json +37 -4
- package/README.md +0 -3
package/dist/bundle.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import E from"axios";import m from"picocolors";var O=`
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
\x1B[38;2;0;0;0m\x1B[48;2;0;0;0m\u2580\x1B[0m \x1B[38;2;0;0;0m\x1B[48;2;0;0;0m\u2580\x1B[0m
|
|
8
|
+
\x1B[38;2;0;0;0m\x1B[48;2;0;0;0m\u2580\x1B[0m\x1B[38;2;0;0;0m\x1B[48;2;231;148;37m\u2580\x1B[0m\x1B[38;2;0;0;0m\x1B[48;2;231;148;37m\u2580\x1B[0m\x1B[38;2;0;0;0m\x1B[48;2;231;148;37m\u2580\x1B[0m\x1B[38;2;0;0;0m\x1B[48;2;0;0;0m\u2580\x1B[0m\x1B[38;2;0;0;0m\u2584\x1B[0m \x1B[38;2;0;0;0m\u2584\x1B[0m\x1B[38;2;0;0;0m\u2584\x1B[0m\x1B[38;2;0;0;0m\u2584\x1B[0m\x1B[38;2;0;0;0m\u2584\x1B[0m\x1B[38;2;0;0;0m\u2584\x1B[0m\x1B[38;2;0;0;0m\u2584\x1B[0m\x1B[38;2;0;0;0m\u2584\x1B[0m
|
|
9
|
+
\x1B[38;2;0;0;0m\x1B[48;2;0;0;0m\u2580\x1B[0m\x1B[38;2;231;148;37m\x1B[48;2;231;148;37m\u2580\x1B[0m\x1B[38;2;0;0;0m\x1B[48;2;231;148;37m\u2580\x1B[0m\x1B[38;2;231;148;37m\x1B[48;2;231;148;37m\u2580\x1B[0m\x1B[38;2;231;148;37m\x1B[48;2;231;148;37m\u2580\x1B[0m\x1B[38;2;0;0;0m\x1B[48;2;231;148;37m\u2580\x1B[0m\x1B[38;2;0;0;0m\x1B[48;2;0;0;0m\u2580\x1B[0m \x1B[38;2;0;0;0m\u2584\x1B[0m\x1B[38;2;0;0;0m\x1B[48;2;0;0;0m\u2580\x1B[0m\x1B[38;2;0;0;0m\x1B[48;2;128;92;22m\u2580\x1B[0m\x1B[38;2;128;92;22m\x1B[48;2;128;92;22m\u2580\x1B[0m\x1B[38;2;128;92;22m\x1B[48;2;0;0;0m\u2580\x1B[0m\x1B[38;2;128;92;22m\x1B[48;2;0;0;0m\u2580\x1B[0m\x1B[38;2;128;92;22m\x1B[48;2;0;0;0m\u2580\x1B[0m\x1B[38;2;128;92;22m\x1B[48;2;128;92;22m\u2580\x1B[0m\x1B[38;2;0;0;0m\x1B[48;2;128;92;22m\u2580\x1B[0m\x1B[38;2;0;0;0m\x1B[48;2;0;0;0m\u2580\x1B[0m\x1B[38;2;0;0;0m\u2584\x1B[0m
|
|
10
|
+
\x1B[38;2;0;0;0m\u2580\x1B[0m\x1B[38;2;0;0;0m\u2580\x1B[0m\x1B[38;2;0;0;0m\x1B[48;2;0;0;0m\u2580\x1B[0m\x1B[38;2;231;148;37m\x1B[48;2;0;0;0m\u2580\x1B[0m\x1B[38;2;231;148;37m\x1B[48;2;231;148;37m\u2580\x1B[0m\x1B[38;2;231;148;37m\x1B[48;2;231;148;37m\u2580\x1B[0m\x1B[38;2;0;0;0m\x1B[48;2;231;148;37m\u2580\x1B[0m\x1B[38;2;0;0;0m\x1B[48;2;0;0;0m\u2580\x1B[0m\x1B[38;2;0;0;0m\x1B[48;2;0;0;0m\u2580\x1B[0m\x1B[38;2;128;92;22m\x1B[48;2;128;92;22m\u2580\x1B[0m\x1B[38;2;128;92;22m\x1B[48;2;128;92;22m\u2580\x1B[0m\x1B[38;2;128;92;22m\x1B[48;2;128;92;22m\u2580\x1B[0m\x1B[38;2;0;0;0m\x1B[48;2;0;0;0m\u2580\x1B[0m\x1B[38;2;128;92;22m\x1B[48;2;128;92;22m\u2580\x1B[0m\x1B[38;2;0;0;0m\x1B[48;2;0;0;0m\u2580\x1B[0m\x1B[38;2;128;92;22m\x1B[48;2;0;0;0m\u2580\x1B[0m\x1B[38;2;128;92;22m\x1B[48;2;128;92;22m\u2580\x1B[0m\x1B[38;2;128;92;22m\x1B[48;2;128;92;22m\u2580\x1B[0m\x1B[38;2;0;0;0m\x1B[48;2;0;0;0m\u2580\x1B[0m
|
|
11
|
+
\x1B[38;2;0;0;0m\u2580\x1B[0m\x1B[38;2;0;0;0m\x1B[48;2;0;0;0m\u2580\x1B[0m\x1B[38;2;231;148;37m\x1B[48;2;231;148;37m\u2580\x1B[0m\x1B[38;2;231;148;37m\x1B[48;2;231;148;37m\u2580\x1B[0m\x1B[38;2;231;148;37m\x1B[48;2;231;148;37m\u2580\x1B[0m\x1B[38;2;0;0;0m\x1B[48;2;231;148;37m\u2580\x1B[0m\x1B[38;2;0;0;0m\x1B[48;2;0;0;0m\u2580\x1B[0m\x1B[38;2;128;92;22m\x1B[48;2;0;0;0m\u2580\x1B[0m\x1B[38;2;128;92;22m\x1B[48;2;128;92;22m\u2580\x1B[0m\x1B[38;2;0;0;0m\x1B[48;2;128;92;22m\u2580\x1B[0m\x1B[38;2;0;0;0m\x1B[48;2;128;92;22m\u2580\x1B[0m\x1B[38;2;0;0;0m\x1B[48;2;128;92;22m\u2580\x1B[0m\x1B[38;2;0;0;0m\x1B[48;2;128;92;22m\u2580\x1B[0m\x1B[38;2;128;92;22m\x1B[48;2;128;92;22m\u2580\x1B[0m\x1B[38;2;128;92;22m\x1B[48;2;128;92;22m\u2580\x1B[0m\x1B[38;2;0;0;0m\x1B[48;2;0;0;0m\u2580\x1B[0m
|
|
12
|
+
\x1B[38;2;0;0;0m\u2580\x1B[0m\x1B[38;2;0;0;0m\u2580\x1B[0m\x1B[38;2;0;0;0m\u2580\x1B[0m\x1B[38;2;0;0;0m\u2580\x1B[0m\x1B[38;2;0;0;0m\u2580\x1B[0m\x1B[38;2;0;0;0m\u2580\x1B[0m\x1B[38;2;0;0;0m\u2580\x1B[0m\x1B[38;2;0;0;0m\u2580\x1B[0m\x1B[38;2;0;0;0m\u2580\x1B[0m\x1B[38;2;0;0;0m\u2580\x1B[0m\x1B[38;2;0;0;0m\u2580\x1B[0m\x1B[38;2;0;0;0m\u2580\x1B[0m\x1B[38;2;0;0;0m\u2580\x1B[0m\x1B[38;2;0;0;0m\u2580\x1B[0m\x1B[38;2;0;0;0m\u2580\x1B[0m
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
`;import q from"prompt-sync";import l from"node:fs";import A from"node:os";import c from"node:path";import{spawnSync as D}from"node:child_process";var N=q({sigint:!0}),L="0.1.0",T="https://mkap-api.onrender.com/",B="bonnet-2.6",_=10,S=8e3,R="Commands: /models, /model <name>, /tools, /clear, /exit",g=B,v=[],b=l.realpathSync(process.cwd()),x=1024*1024;function C(e){let t=c.relative(b,e);return t===""||t!==".."&&!t.startsWith(".."+c.sep)&&!c.isAbsolute(t)}function f(e="."){if(typeof e!="string"||e.includes("\0"))throw new Error("Invalid path");let t=c.resolve(b,e);if(!C(t))throw new Error("Path is outside the working directory");let n=t,o=[];for(;;)try{l.lstatSync(n);break}catch(s){if(s.code!=="ENOENT")throw s;let r=c.dirname(n);if(r===n)break;o.unshift(c.basename(n)),n=r}let u;try{u=l.realpathSync(n)}catch{throw new Error("Cannot resolve path (broken symlink?)")}let i=c.join(u,...o);if(!C(i))throw new Error("Path is outside the working directory (symlink)");return i}var $=e=>c.relative(b,e)||".",h={list_dir:{description:"List the files and folders in a directory",params:{path:"directory path, defaults to ."},run:({path:e})=>l.readdirSync(f(e),{withFileTypes:!0}).map(n=>n.name+(n.isDirectory()?"/":n.isSymbolicLink()?" (symlink)":"")).join(`
|
|
19
|
+
`)||"(empty)"},read_file:{description:"Read a text file and return its contents",params:{path:"file path"},run:({path:e})=>{let t=f(e),n=l.statSync(t);if(!n.isFile())throw new Error("Not a file");if(n.size>x)throw new Error("File too large (max 1MB)");return l.readFileSync(t,"utf8")}},write_file:{description:"Create or overwrite a file with the given content, parent folders are created automatically",params:{path:"file path",content:"the full new file content"},run:({path:e,content:t})=>{let n=f(e),o=String(t??"");if(o.length>x)throw new Error("Content too large (max 1MB)");return l.mkdirSync(c.dirname(n),{recursive:!0}),l.writeFileSync(n,o),`Wrote ${o.length} chars to ${$(n)}`}},make_dir:{description:"Create a directory, including any missing parents",params:{path:"directory path"},run:({path:e})=>{let t=f(e);return l.mkdirSync(t,{recursive:!0}),`Created ${$(t)}`}},delete_file:{description:"Delete a single file (not a directory)",params:{path:"file path"},run:({path:e})=>{let t=f(e);if(!l.statSync(t).isFile())throw new Error("Not a file");return l.unlinkSync(t),`Deleted ${$(t)}`}},search_text:{description:"Search files for a piece of text (case insensitive), returns file:line matches",params:{text:"the text to look for",path:"directory to search, defaults to ."},run:({text:e,path:t})=>{if(!e)throw new Error("text is required");let n=String(e).toLowerCase(),o=[],u=i=>{for(let s of l.readdirSync(i,{withFileTypes:!0})){if(o.length>=50)return;if(s.isSymbolicLink()||s.name==="node_modules"||s.name===".git")continue;let r=c.join(i,s.name);if(s.isDirectory()){u(r);continue}if(!s.isFile()||l.statSync(r).size>x)continue;let a=l.readFileSync(r,"utf8");a.includes("\0")||a.split(`
|
|
20
|
+
`).forEach((y,p)=>{o.length<50&&y.toLowerCase().includes(n)&&o.push(`${$(r)}:${p+1}: ${y.trim().slice(0,200)}`)})}};return u(f(t)),o.join(`
|
|
21
|
+
`)||"No matches"}}};h.run_command={description:"Run a shell command in the project folder and return its output. The user must approve every command",params:{command:"the exact shell command to run"},preview:({command:e})=>`
|
|
22
|
+
${m.yellow("The model wants to run this command in")} ${b}
|
|
23
|
+
|
|
24
|
+
${m.bold("$ "+e)}
|
|
25
|
+
`,needsConfirm:()=>"Run it?",run:({command:e})=>{if(typeof e!="string"||!e.trim())throw new Error("command is required");let t=D(e,{shell:!0,cwd:b,encoding:"utf8",timeout:3e4,maxBuffer:1024*1024});return t.error?`Failed to run: ${t.error.code==="ETIMEDOUT"?"timed out after 30s":t.error.message}`:`exit code ${t.status}
|
|
26
|
+
${t.stdout??""}${t.stderr??""}`}};function K(){return["You are Kart Code, a coding assistant running in the user's terminal.","You work inside one project folder. All file tools use paths relative to it and cannot reach outside it.","run_command is different: the user sees the exact command and must approve it, and they may say no. Keep commands short, simple and safe, and never chain unrelated things together.","","You can use tools. To call one, reply with a block in exactly this format:",'<tool_call>{"name": "tool_name", "args": {"param": "value"}}</tool_call>',"","Rules:","- Call one tool per message, put the tool_call at the end, then stop and wait.","- The result arrives in the next message inside <tool_result> tags.","- Only use the tools listed below and give args as valid JSON.","- When you have what you need, answer normally with no tool_call block.","","Available tools:",Object.entries(h).map(([t,n])=>{let o=Object.entries(n.params).map(([u,i])=>` ${u}: ${i}`).join(`
|
|
27
|
+
`);return`- ${t}: ${n.description}
|
|
28
|
+
${o}`}).join(`
|
|
29
|
+
`)].join(`
|
|
30
|
+
`)}async function W(){return(await E.get(`${T}models/`,{timeout:3e4})).data.models.map(n=>typeof n=="string"?n:n.name??n.id??JSON.stringify(n))}async function M(e){try{return(await E.post(`${T}chat/`,{model:g,system:K(),prompt:e,messages:v},{timeout:12e4})).data.content}catch(t){if(t.response){let n=typeof t.response.data=="string"?t.response.data:JSON.stringify(t.response.data);console.log(m.red(`
|
|
31
|
+
Kart returned ${t.response.status}: ${n}
|
|
32
|
+
`))}else t.code==="ECONNABORTED"?console.log(m.red(`
|
|
33
|
+
Request timed out, try again
|
|
34
|
+
`)):console.log(m.red(`
|
|
35
|
+
Request failed: ${t.message}
|
|
36
|
+
`));return null}}function U(e){let t=e.lastIndexOf("</think>");return(t===-1?e:e.slice(t+8)).replace(/<\/?think>/g,"").trim()}function j(e,t){let n=0,o=!1,u=!1;for(let i=t;i<e.length;i++){let s=e[i];if(o){u?u=!1:s==="\\"?u=!0:s==='"'&&(o=!1);continue}if(s==='"')o=!0;else if(s==="{")n++;else if(s==="}"&&--n===0)return e.slice(t,i+1)}return null}var F=/<tool_call>\s*([\s\S]*?)\s*(?:<\/tool_call>|$)/;function Y(e){let t=e.match(F),n=null;if(t){let o=t[1].indexOf("{");n=o===-1?t[1]:j(t[1],o)??t[1]}else{let o=e.search(/\{\s*"name"\s*:/);if(o===-1||(n=j(e,o),!n))return null}try{let o=JSON.parse(n);if(typeof o.name!="string")throw new Error("no name");return{name:o.name,args:o.args??{},raw:n}}catch{return{error:"The tool_call was not valid JSON. Use the exact format from the instructions."}}}function I(e){if(e.error)return e.error;let t=Object.hasOwn(h,e.name)?h[e.name]:null;if(!t)return`Unknown tool "${e.name}". Available: ${Object.keys(h).join(", ")}`;try{if(t.needsConfirm){let n=t.needsConfirm(e.args);t.preview&&console.log(t.preview(e.args));let o=N(m.yellow(`${n} [y/N] `));if(!o||o.trim().toLowerCase()!=="y")return"The user denied this action."}return String(t.run(e.args))}catch(n){return`Error: ${n.message}`}}var P=e=>e.length>S?e.slice(0,S)+`
|
|
37
|
+
...[truncated ${e.length-S} chars]`:e;async function z(e){let t=e,n=null,o=null;for(let u=0;u<_;u++){let i=await M(t);if(i===null)return;let s=U(i),r=Y(s),a=s.replace(F,"");r&&r.raw&&(a=a.replace(r.raw,"")),a=a.trim(),a&&console.log(`
|
|
38
|
+
`+a);let y=r&&!r.error?(a?a+`
|
|
39
|
+
`:"")+`<tool_call>${JSON.stringify({name:r.name,args:r.args})}</tool_call>`:s;if(v.push({role:"user",content:t},{role:"assistant",content:y}),!r){console.log();return}let p=JSON.stringify(r.args??{});console.log(m.dim(`
|
|
40
|
+
\u2699 ${r.name??"invalid call"} ${p.length>120?p.slice(0,120)+"...":p}`));let w,k=r.error?null:r.name+JSON.stringify(r.args);k&&k===n?(console.log(m.dim("(same call as before, skipped)")),w=`You already made this exact tool call. The result was:
|
|
41
|
+
${o}
|
|
42
|
+
Do not repeat it. Answer the user now.`):(w=P(I(r)),n=k,o=w),t=`<tool_result>
|
|
43
|
+
${w}
|
|
44
|
+
</tool_result>
|
|
45
|
+
Use this result to answer the user. Only call another tool if you still need more information.`}console.log(m.yellow(`
|
|
46
|
+
Stopped after ${_} tool calls
|
|
47
|
+
`))}async function G(e){let[t,...n]=e.split(/\s+/);switch(t){case"/models":try{console.log(`
|
|
48
|
+
`+(await W()).join(`
|
|
49
|
+
`)+`
|
|
50
|
+
`)}catch(o){console.log(m.red(`
|
|
51
|
+
Could not fetch models: ${o.message}
|
|
52
|
+
`))}break;case"/model":n[0]?(g=n[0],console.log(`
|
|
53
|
+
Switched to ${g}
|
|
54
|
+
`)):console.log(`
|
|
55
|
+
Current model: ${g}
|
|
56
|
+
`);break;case"/tools":console.log(`
|
|
57
|
+
`+Object.entries(h).map(([o,u])=>`${o}: ${u.description}`).join(`
|
|
58
|
+
`)+`
|
|
59
|
+
`);break;case"/clear":v=[],console.log(`
|
|
60
|
+
Chat history cleared
|
|
61
|
+
`);break;default:console.log(m.dim(`
|
|
62
|
+
${R}
|
|
63
|
+
`))}}console.clear();console.log("");var d=O.split(`
|
|
64
|
+
`),J=e=>e.trim()==="";for(;d.length&&J(d[0]);)d.shift();for(;d.length&&J(d[d.length-1]);)d.pop();console.log(d.join(`
|
|
65
|
+
`));console.log(m.bold(" Kart Code ")+L);console.log(m.dim(`
|
|
66
|
+
Sandbox: ${b}`));console.log(m.dim(`${R}
|
|
67
|
+
`));b===c.parse(b).root&&(console.log(m.red(`Refusing to run in the filesystem root, cd into a project folder first
|
|
68
|
+
`)),process.exit(1));b===l.realpathSync(A.homedir())&&console.log(m.yellow(`Warning: you started in your home folder, the model can reach everything in it
|
|
69
|
+
`));for(;;){let e=N(`=====> Ask ${g}> `);if(e===null)break;if(e=e.trim(),e!==""){if(e==="/exit"||e==="/quit")break;if(e.startsWith("/")){await G(e);continue}await z(e)}}
|
package/package.json
CHANGED
|
@@ -1,6 +1,39 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kart-code",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A simple CLI that allows you to write code using the Kart API",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"code",
|
|
7
|
+
"ai"
|
|
8
|
+
],
|
|
9
|
+
"license": "ISC",
|
|
10
|
+
"author": "solhost",
|
|
11
|
+
"type": "module",
|
|
12
|
+
"main": "dist/bundle.js",
|
|
13
|
+
"bin": {
|
|
14
|
+
"kart-code": "dist/bundle.js"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"engines": {
|
|
20
|
+
"node": ">=18"
|
|
21
|
+
},
|
|
22
|
+
"scripts": {
|
|
23
|
+
"start": "node dist/bundle.js",
|
|
24
|
+
"build": "esbuild main.js --bundle --minify --platform=node --format=esm --packages=external --outfile=dist/bundle.js",
|
|
25
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"axios": "^1.20.0",
|
|
29
|
+
"picocolors": "^1.1.1",
|
|
30
|
+
"prompt-sync": "^4.2.0"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"esbuild": "^0.28.2",
|
|
34
|
+
"pngjs": "^7.0.0"
|
|
35
|
+
},
|
|
36
|
+
"allowScripts": {
|
|
37
|
+
"esbuild@0.28.2": true
|
|
38
|
+
}
|
|
39
|
+
}
|
package/README.md
DELETED