novacode 0.8.2 → 0.9.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/app-CBs69waM.mjs +33 -0
- package/dist/app-CBs69waM.mjs.map +1 -0
- package/dist/main.mjs +30 -31
- package/dist/main.mjs.map +1 -1
- package/dist/reset-C2XGbjKJ.mjs +4 -0
- package/dist/reset-C2XGbjKJ.mjs.map +1 -0
- package/package.json +1 -2
- package/dist/app-DUkzQ-1g.mjs +0 -32
- package/dist/app-DUkzQ-1g.mjs.map +0 -1
package/dist/main.mjs
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{parseArgs as e}from"node:util";import t from"chalk";import
|
|
3
|
-
`)
|
|
4
|
-
`);
|
|
5
|
-
`)}}},r=t[t.length-1];r&&r.role===`user`&&r.parts.some(e=>e.function_response)?r.parts.push(e):t.push({role:`user`,parts:[e]})}return t}function
|
|
6
|
-
`)
|
|
7
|
-
`)
|
|
8
|
-
`);l=n.pop()??``;for(let e of n){let n=e.trim();if(!n?.startsWith(`data: `))continue;let o=n.slice(6);if(o!==`[DONE]`)try{let e=JSON.parse(o),n=e.choices?.[0]?.delta;if(!n)continue;n.content&&(t.push({type:`text_delta`,text:n.content}),r+=n.content);let s=n.reasoning_content||n.reasoning||n.thinking;if(s&&t.push({type:`thinking_delta`,text:s}),n.tool_calls)for(let e of n.tool_calls){let t=e.index??0;i.has(t)||i.set(t,{id:e.id??``,name:e.function?.name??``,args:``});let n=i.get(t);e.id&&(n.id=e.id),e.function?.name&&(n.name=e.function.name),e.function?.arguments&&(n.args+=e.function.arguments)}e.usage&&(a={in:e.usage.prompt_tokens??0,out:e.usage.completion_tokens??0},t.push({type:`usage`,usage:a}));let c=e.choices?.[0]?.finish_reason;c&&(u=c)}catch{}}}let d=[];r&&d.push({type:`text`,text:r});for(let[,e]of i)d.push({type:`tool_call`,id:e.id,name:e.name,args:JSON.parse(e.args||`{}`)}),t.push({type:`tool_call`,call:{type:`tool_call`,id:e.id,name:e.name,args:JSON.parse(e.args||`{}`)}}),u=`tool_use`;t.finish({content:d,usage:a,stop:u})}catch(n){if(e.signal?.aborted){let e=[];r&&e.push({type:`text`,text:r});for(let[,t]of i)try{e.push({type:`tool_call`,id:t.id,name:t.name,args:JSON.parse(t.args||`{}`)})}catch{}t.finish({content:e,usage:a,stop:`aborted`});return}let o=`Unexpected error: ${n instanceof Error?n.message:String(n)}`;t.push({type:`text_delta`,text:o}),t.finish({content:[{type:`text`,text:o}],usage:{in:0,out:0},stop:`error`})}})(),t};var T=class{#e=[];#t=!1;#n;#r;#i;#a=!1;push(e){if(!this.#a)if(this.#r){let t=this.#r;this.#r=void 0,t(e)}else this.#e.push(e)}finish(e){this.#t=!0,this.#n=e,this.#r&&this.#r(void 0),this.#i&&this.#i(e)}abort(){this.#a=!0,this.#t=!0,this.#r&&this.#r(void 0),this.#i&&this.#i(void 0)}async*[Symbol.asyncIterator](){for(;!this.#t||this.#e.length>0;){if(this.#e.length>0){yield this.#e.shift();continue}if(this.#t)break;let e=await new Promise(e=>{this.#r=e});e!==void 0&&(yield e)}}get result(){return this.#n}get isDone(){return this.#t}};const me=new Map([[`openai`,pe],[`gemini`,ue],[`anthropic`,se]]);function he(e){let t=me.get(e.apiFormat);if(!t)throw Error(`No provider registered for API format: ${e.apiFormat}`);let n=t(e),r=new T;return(async()=>{for await(let e of n)e.type===`text_delta`?r.push({type:`text_delta`,text:e.text??``}):e.type===`thinking_delta`?r.push({type:`thinking_delta`,text:e.text??``}):e.type===`tool_call`&&e.call?r.push({type:`tool_call`,call:{type:`tool_call`,id:e.call.id,name:e.call.name,args:e.call.args}}):e.type===`usage`&&e.usage&&r.push({type:`usage`,usage:e.usage});let e=n.result;e?r.finish(e):r.finish({content:[],usage:{in:0,out:0},stop:`stop`})})(),r}function ge(e){let t=0;for(let n of e)if(typeof n.content==`string`)t+=n.content.length;else if(Array.isArray(n.content))for(let e of n.content)e.type===`text`&&(t+=e.text.length);return Math.ceil(t/4)}function E(e){return{type:`text`,text:e}}function D(e,t){return t===e||t.startsWith(`${e}/`)?s(e,t)||`.`:t}function _e(e){if(typeof e!=`string`)return e;let t=e,n=``;if(e.startsWith(`file://`)&&(t=e.slice(7),n=`file://`),a(t)){let e=process.cwd();return n+D(e,t)}return e}function ve(e,n=!1){return e?Object.entries(e).map(([e,r])=>{let i=typeof r==`string`?_e(r):JSON.stringify(r),a=i.length>40?`${i.slice(0,40)}…`:i;return`${n?t.dim(`${e}:`):`${e}:`} ${a}`}).join(` `):``}function O(e){let t=Date.now()-e,n=Math.floor(t/1e3),r=Math.floor(n/60),i=Math.floor(r/60);return n<60?`just now`:r<60?`${r}m ago`:i<24?`${i}h ago`:new Date(e).toLocaleDateString()}const ye=e=>typeof e==`object`&&!!e&&e.type===`tool_call`;function be(e,t,n){let r=new T,i=[],a=t.maxTurns??50,o=e;return(async()=>{r.push({type:`start`});try{let e=0;for(;e<a&&!n?.aborted;){e++,r.push({type:`turn`});let a=ge(o.messages);a>t.model.contextWindow*.9&&r.push({type:`text_delta`,text:`[warning] Approaching context limit (~${Math.round(a/1e3)}k / ${Math.round(t.model.contextWindow/1e3)}k tokens)`});let s=await xe(o,t,r,n);if(i.push(s),o={...o,messages:[...o.messages,s]},r.push({type:`assistant_msg`,msg:s}),s.stop===`error`||s.stop===`aborted`){r.push({type:`turn_end`,msg:s,results:[]});break}let c=s.content.filter(ye);if(c.length===0){r.push({type:`turn_end`,msg:s,results:[]});break}let l=[];for(let e of c){if(n?.aborted)break;let a=o.tools.find(t=>t.def.name===e.name);if(!a){let t={role:`tool_result`,callId:e.id,tool:e.name,content:[E(`Unknown tool: ${e.name}`)],isError:!0,ts:Date.now()};l.push(t),o={...o,messages:[...o.messages,t]},i.push(t);continue}let s=await t.beforeTool?.(e,e.args,o);if(s?.block){let t={role:`tool_result`,callId:e.id,tool:e.name,content:[E(s.reason??`Blocked`)],isError:!0,ts:Date.now()};l.push(t),o={...o,messages:[...o.messages,t]},i.push(t);continue}let c=await a.execute(e.args,n),u={role:`tool_result`,callId:e.id,tool:e.name,args:e.args,content:c.content,isError:c.isError,ts:Date.now()};l.push(u),o={...o,messages:[...o.messages,u]},i.push(u),r.push({type:`tool_result`,callId:e.id,result:u,args:e.args}),await t.afterTool?.(e,u,o)}r.push({type:`turn_end`,msg:s,results:l})}e>=a&&r.push({type:`text_delta`,text:`[max turns reached (${a})]`})}catch(e){if(e.name===`AbortError`){r.finish(i);return}throw e}r.finish(i)})(),r}async function xe(e,t,n,r){let i=he({apiFormat:t.apiFormat,model:t.model,apiKey:t.apiKey,baseUrl:t.baseUrl,system:e.system,messages:e.messages,tools:e.tools.map(e=>e.def),signal:r}),a=[],o={in:0,out:0};for await(let e of i)if(e.type===`text_delta`&&e.text){let t=a[a.length-1];t?.type===`text`?t.text+=e.text:a.push(E(e.text)),n.push({type:`text_delta`,text:e.text})}else e.type===`thinking_delta`&&e.text?n.push({type:`thinking_delta`,text:e.text}):e.type===`tool_call`&&e.call?(a.push(e.call),n.push({type:`tool_call`,call:e.call})):e.type===`usage`&&e.usage&&(o=e.usage,n.push({type:`usage`,usage:o}));let s=i.result?.content&&i.result.content.length>0?i.result.content:a,c=s.some(e=>e.type===`tool_call`)?s.filter(e=>e.type!==`text`||e.text.trim().length>0):s,l=i.result;return l?{role:`assistant`,content:c,model:t.model.id,provider:t.model.provider,usage:l.usage,stop:l.stop,ts:Date.now()}:{role:`assistant`,content:c,model:t.model.id,provider:t.model.provider,usage:o,stop:c.some(e=>e.type===`tool_call`)?`tool_use`:`stop`,ts:Date.now()}}var Se=class{#e;#t;#n;#r=[];#i;#a;#o;constructor(e){this.#e=e.apiFormat,this.#t=e.model,this.#a=e.apiKey,this.#o=e.baseUrl,this.#n=e.system,this.#i=e.tools,this.#r=e.messages??[]}get model(){return this.#t}get messages(){return this.#r}get tools(){return this.#i}get apiKey(){return this.#a}get baseUrl(){return this.#o}updateConfig(e){this.#e=e.apiFormat,this.#t=e.model,this.#a=e.apiKey,this.#o=e.baseUrl}setTools(e){this.#i=e}setMessages(e){this.#r=e}setModel(e){this.#t=e}prompt(e){return be({system:this.#n,messages:this.#r,tools:this.#i},{apiFormat:this.#e,model:this.#t,apiKey:this.#a,baseUrl:this.#o},e)}};function Ce(e,t,n=[],r){let i=t.map(e=>`- ${e.def.name}: ${e.def.description}`).join(`
|
|
9
|
-
`),a=l.platform(),o=l.arch();return`You are Nova, an expert coding assistant. Help users with coding tasks using the tools available.
|
|
2
|
+
import{parseArgs as e}from"node:util";import t from"chalk";import{dirname as n,extname as r,isAbsolute as i,join as a,relative as o,resolve as s}from"node:path";import c,{homedir as l}from"node:os";import{chmod as u,mkdir as d,readFile as f,readdir as p,stat as m,writeFile as h}from"node:fs/promises";import{Box as g,Text as _,render as v,useInput as y}from"ink";import{useState as b}from"react";import{jsx as x,jsxs as S}from"react/jsx-runtime";import{DatabaseSync as C}from"node:sqlite";import{mkdirSync as ee}from"node:fs";import{spawn as w}from"node:child_process";import{glob as te}from"glob";import{fileURLToPath as ne}from"node:url";import re from"semver";var ie=class{#e;#t;constructor(e,t){this.#e=e,this.#t=t}get ok(){return this.#e>=200&&this.#e<300}get status(){return this.#e}async text(){let e=[],t=new TextDecoder;for await(let n of this.#t)e.push(t.decode(n,{stream:!0}));return e.join(``)}async*events(){let e=new TextDecoder,t=``;for await(let n of this.#t){t+=e.decode(n,{stream:!0});let r=t.split(`
|
|
3
|
+
`);t=r.pop()??``;for(let e of r){let t=e.trim();if(!t?.startsWith(`data: `))continue;let n=t.slice(6);n!==`[DONE]`&&(yield n)}}}};async function T(e,t,n,r){let i=await fetch(e,{method:`POST`,headers:{"Content-Type":`application/json`,...t},body:JSON.stringify(n),signal:r});if(!i.body)throw Error(`No response body from ${e}`);return new ie(i.status,i.body)}function ae(e){let t=[];for(let n of e)if(n.role===`user`){let e=typeof n.content==`string`?[{type:`text`,text:n.content}]:n.content.map(e=>e.type===`text`?{type:`text`,text:e.text}:e.type===`image`?{type:`image`,source:{type:`base64`,media_type:e.mime,data:e.data}}:{type:`text`,text:``});t.push({role:`user`,content:e})}else if(n.role===`assistant`){let e=n.content.map(e=>e.type===`text`?{type:`text`,text:e.text}:e.type===`thinking`?{type:`thinking`,thinking:e.text,signature:e.signature}:e.type===`tool_call`?{type:`tool_use`,id:e.id,name:e.name,input:e.args}:{type:`text`,text:``});t.push({role:`assistant`,content:e})}else if(n.role===`tool_result`){let e={type:`tool_result`,tool_use_id:n.callId,content:n.content.map(e=>e.type===`text`?e.text:JSON.stringify(e)).join(`
|
|
4
|
+
`),is_error:n.isError?!0:void 0},r=t[t.length-1];r&&r.role===`user`&&Array.isArray(r.content)&&r.content.some(e=>e.type===`tool_result`)?r.content.push(e):t.push({role:`user`,content:[e]})}return t}function oe(e){return e.map((t,n)=>{let r={name:t.name,description:t.description,input_schema:t.parameters};return n===e.length-1&&(r.cache_control={type:`ephemeral`}),r})}function se(e){if(e.supportsThinking)return e.id===`claude-opus-4-5`||e.id===`claude-sonnet-4-5`?{type:`enabled`,budget_tokens:1e4}:{type:`adaptive`}}const ce=e=>{let t=new E;return(async()=>{let n={in:0,out:0},r=[],i=new Map;try{let a=`${e.baseUrl||`https://api.anthropic.com`}/v1/messages`,o={model:e.model.id,messages:ae(e.messages),system:e.system?[{type:`text`,text:e.system,cache_control:{type:`ephemeral`}}]:void 0,max_tokens:e.model.maxTokens||16384,stream:!0};e.tools.length>0&&(o.tools=oe(e.tools));let s=se(e.model);s&&(o.thinking=s);let c=e.model.effort;c&&(o.output_config={effort:c});let l=await T(a,{"x-api-key":e.apiKey,"anthropic-version":`2023-06-01`},o,e.signal);if(!l.ok){let e=await l.text(),n=e;try{let t=JSON.parse(e);n=t.error?.message||t.message||e}catch{}let r=`Anthropic Error (${l.status}): ${n}`;t.push({type:`text_delta`,text:r}),t.finish({content:[{type:`text`,text:r}],usage:{in:0,out:0},stop:`error`});return}let u=`stop`;for await(let e of l.events())try{let a=JSON.parse(e);if(a.type===`message_start`){let e=a.message?.usage;e&&(n={in:(e.input_tokens??0)+(e.cache_creation_input_tokens??0)+(e.cache_read_input_tokens??0),out:e.output_tokens??0},t.push({type:`usage`,usage:n}))}if(a.type===`content_block_start`){let e=a.index,t=a.content_block;i.set(e,{type:t.type,id:t.id??``,name:t.name??``,text:``,thinking:``,partialJson:``,signature:``})}if(a.type===`content_block_delta`){let e=a.index,n=a.delta,r=i.get(e);r&&(n.type===`text_delta`&&n.text?(r.text+=n.text,t.push({type:`text_delta`,text:n.text})):n.type===`thinking_delta`&&n.thinking?(r.thinking+=n.thinking,t.push({type:`thinking_delta`,text:n.thinking})):n.type===`input_json_delta`&&n.partial_json?r.partialJson+=n.partial_json:n.type===`signature_delta`&&n.signature&&(r.signature+=n.signature))}if(a.type===`content_block_stop`){let e=a.index,n=i.get(e);if(n){if(n.type===`text`&&n.text)r.push({type:`text`,text:n.text});else if(n.type===`thinking`&&(n.thinking||n.signature))r.push({type:`thinking`,text:n.thinking,signature:n.signature||void 0});else if(n.type===`tool_use`){let e={};try{e=JSON.parse(n.partialJson||`{}`)}catch(t){e={_raw:n.partialJson,_parseError:t.message}}let i={type:`tool_call`,id:n.id,name:n.name,args:e};r.push(i),t.push({type:`tool_call`,call:i}),u=`tool_use`}}}if(a.type===`message_delta`&&(a.usage&&(n={in:n.in,out:a.usage.output_tokens??n.out},t.push({type:`usage`,usage:n})),a.delta?.stop_reason)){let e=a.delta.stop_reason;e===`end_turn`||e===`stop_sequence`?u=`stop`:e===`max_tokens`?u=`length`:e===`tool_use`?u=`tool_use`:e===`refusal`&&(u=`refusal`)}if(a.type===`error`){let e=a.error?.message??`Unknown stream error`;t.push({type:`text_delta`,text:`\n[Stream error: ${e}]`})}}catch{}t.finish({content:r,usage:n,stop:u})}catch(i){if(e.signal?.aborted){t.finish({content:r,usage:n,stop:`aborted`});return}let a=`Anthropic Network/Request Error: ${i instanceof Error?i.message:String(i)}`;t.push({type:`text_delta`,text:a}),t.finish({content:[{type:`text`,text:a}],usage:{in:0,out:0},stop:`error`})}})(),t};function le(e){let t=[];for(let n of e)if(n.role===`user`){let e=typeof n.content==`string`?[{text:n.content}]:n.content.map(e=>e.type===`text`?{text:e.text}:e.type===`image`?{inline_data:{mime_type:e.mime,data:e.data}}:{text:``});t.push({role:`user`,parts:e})}else if(n.role===`assistant`){let e=n.content.map(e=>e.type===`text`?{text:e.text,thought_signature:e.signature}:e.type===`thinking`?{thought:!0,text:e.text,thought_signature:e.signature}:e.type===`tool_call`?{function_call:{name:e.name,args:e.args}}:{text:``});t.push({role:`model`,parts:e})}else if(n.role===`tool_result`){let e={function_response:{name:n.tool,response:{content:n.content.map(e=>e.type===`text`?e.text:JSON.stringify(e)).join(`
|
|
5
|
+
`)}}},r=t[t.length-1];r&&r.role===`user`&&r.parts.some(e=>e.function_response)?r.parts.push(e):t.push({role:`user`,parts:[e]})}return t}function ue(e){return e.length===0?[]:[{function_declarations:e.map(e=>({name:e.name,description:e.description,parameters:e.parameters}))}]}function de(e){if(e.supportsThinking)return{thinkingLevel:`adaptive`}}function fe(e){return e===`STOP`?`stop`:e===`MAX_TOKENS`?`length`:e===`SAFETY`||e===`RECITATION`||e===`BLOCKLIST`||e===`PROHIBITED_CONTENT`||e===`OTHER`?`error`:`stop`}const pe=e=>{let t=new E;return(async()=>{let n={in:0,out:0},r=[],i=``,a=``,o=``,s=``;try{let c=`${e.baseUrl||`https://generativelanguage.googleapis.com`}/v1beta/models/${e.model.id}:streamGenerateContent?alt=sse&key=${e.apiKey}`,l={contents:le(e.messages),system_instruction:e.system?{parts:[{text:e.system}]}:void 0,tools:e.tools.length>0?ue(e.tools):void 0},u=de(e.model);u&&(l.generationConfig={thinkingConfig:u});let d=await T(c,{"Api-Revision":`2026-05-20`},l,e.signal);if(!d.ok){let e=await d.text(),n=e;try{let t=JSON.parse(e);n=t.error?.message||t.message||e}catch{}let r=`Gemini Error (${d.status}): ${n}`;t.push({type:`text_delta`,text:r}),t.finish({content:[{type:`text`,text:r}],usage:{in:0,out:0},stop:`error`});return}let f=`stop`;for await(let e of d.events())try{let c=JSON.parse(e),l=c.candidates?.[0];if(c.usageMetadata&&(n={in:c.usageMetadata.promptTokenCount||n.in,out:c.usageMetadata.candidatesTokenCount||n.out},t.push({type:`usage`,usage:n})),!l)continue;l.finishReason&&(f=fe(l.finishReason));let u=l.content?.parts;if(!u)continue;for(let e of u){let n=e.thought_signature;if(e.thought===!0&&e.text){a+=e.text,n&&(o=n),t.push({type:`thinking_delta`,text:e.text});continue}if(e.text){i+=e.text,n&&(s=n),t.push({type:`text_delta`,text:e.text});continue}if(e.function_call){let n=e.function_call,i={type:`tool_call`,id:`call_${Math.random().toString(36).slice(2,9)}`,name:n.name,args:n.args||{}};r.push(i),t.push({type:`tool_call`,call:i}),f=`tool_use`}}}catch{}if(a&&r.unshift({type:`thinking`,text:a,signature:o||void 0}),i){let e=r.findIndex(e=>e.type===`tool_call`),t={type:`text`,text:i,signature:s||void 0};e===-1?r.push(t):r.splice(e,0,t)}t.finish({content:r,usage:n,stop:f})}catch(i){if(e.signal?.aborted){t.finish({content:r,usage:n,stop:`aborted`});return}let a=`Gemini Network/Request Error: ${i instanceof Error?i.message:String(i)}`;t.push({type:`text_delta`,text:a}),t.finish({content:[{type:`text`,text:a}],usage:{in:0,out:0},stop:`error`})}})(),t};function me(e){return e===`stop`?`stop`:e===`length`?`length`:e===`tool_calls`?`tool_use`:e===`content_filter`?`error`:`stop`}function he(e){if(e.role===`user`)return{role:`user`,content:typeof e.content==`string`?e.content:e.content.map(e=>e.type===`text`?{type:`text`,text:e.text}:e.type===`image`?{type:`image_url`,image_url:{url:`data:${e.mime};base64,${e.data}`}}:{type:`text`,text:``})};if(e.role===`assistant`){let t=[],n=[];for(let r of e.content)r.type===`text`&&t.push(r.text),r.type===`tool_call`&&n.push({type:`function`,id:r.id,function:{name:r.name,arguments:JSON.stringify(r.args)}});let r={role:`assistant`,content:t.length>0?t.join(``):null};return n.length>0&&(r.tool_calls=n),r}return e.role===`tool_result`?{role:`tool`,tool_call_id:e.callId,content:e.content.map(e=>e.type===`text`?e.text:JSON.stringify(e)).join(`
|
|
6
|
+
`)}:{role:`user`,content:``}}function ge(e){return e.map(e=>({type:`function`,function:{name:e.name,description:e.description,parameters:e.parameters}}))}const _e=e=>{let t=new E;return(async()=>{let n=``,r=new Map,i={in:0,out:0};try{let a={model:e.model.id,messages:[{role:`system`,content:e.system},...e.messages.map(he)],tools:e.tools.length>0?ge(e.tools):void 0,max_completion_tokens:e.model.maxTokens||void 0,stream:!0,stream_options:{include_usage:!0}},o=await T(`${e.baseUrl}/chat/completions`,{Authorization:`Bearer ${e.apiKey}`},a,e.signal);if(!o.ok){let e=await o.text(),n=e;try{let t=JSON.parse(e);n=t.error?.message||t.message||e}catch{}let r=`OpenAI Error (${o.status}): ${n}`;t.push({type:`text_delta`,text:r}),t.finish({content:[{type:`text`,text:r}],usage:{in:0,out:0},stop:`error`});return}let s=`stop`;for await(let e of o.events())try{let a=JSON.parse(e),o=a.choices?.[0]?.delta;if(!o)continue;o.content&&(t.push({type:`text_delta`,text:o.content}),n+=o.content);let c=o.reasoning_content||o.reasoning||o.thinking;if(c&&t.push({type:`thinking_delta`,text:c}),o.tool_calls)for(let e of o.tool_calls){let t=e.index??0;r.has(t)||r.set(t,{id:e.id??``,name:e.function?.name??``,args:``});let n=r.get(t);e.id&&(n.id=e.id),e.function?.name&&(n.name=e.function.name),e.function?.arguments&&(n.args+=e.function.arguments)}a.usage&&(i={in:a.usage.prompt_tokens??0,out:a.usage.completion_tokens??0},t.push({type:`usage`,usage:i}));let l=a.choices?.[0]?.finish_reason;l&&(s=me(l)),o.refusal&&(s=`refusal`)}catch{}let c=[];n&&c.push({type:`text`,text:n});for(let[,e]of r){let n={};try{n=JSON.parse(e.args||`{}`)}catch{n={_raw:e.args}}c.push({type:`tool_call`,id:e.id,name:e.name,args:n}),t.push({type:`tool_call`,call:{type:`tool_call`,id:e.id,name:e.name,args:n}}),s=`tool_use`}t.finish({content:c,usage:i,stop:s})}catch(a){if(e.signal?.aborted){let e=[];n&&e.push({type:`text`,text:n});for(let[,t]of r)try{e.push({type:`tool_call`,id:t.id,name:t.name,args:JSON.parse(t.args||`{}`)})}catch{}t.finish({content:e,usage:i,stop:`aborted`});return}let o=`OpenAI Error: ${a instanceof Error?a.message:String(a)}`;t.push({type:`text_delta`,text:o}),t.finish({content:[{type:`text`,text:o}],usage:{in:0,out:0},stop:`error`})}})(),t};var E=class{#e=[];#t=!1;#n;#r;#i;#a=!1;push(e){if(!this.#a)if(this.#r){let t=this.#r;this.#r=void 0,t(e)}else this.#e.push(e)}finish(e){this.#t=!0,this.#n=e,this.#r&&this.#r(void 0),this.#i&&this.#i(e)}abort(){this.#a=!0,this.#t=!0,this.#r&&this.#r(void 0),this.#i&&this.#i(void 0)}async*[Symbol.asyncIterator](){for(;!this.#t||this.#e.length>0;){if(this.#e.length>0){yield this.#e.shift();continue}if(this.#t)break;let e=await new Promise(e=>{this.#r=e});e!==void 0&&(yield e)}}get result(){return this.#n}get isDone(){return this.#t}};const ve=new Map([[`openai`,_e],[`gemini`,pe],[`anthropic`,ce]]);function ye(e){let t=ve.get(e.apiFormat);if(!t)throw Error(`No provider registered for API format: ${e.apiFormat}`);let n=t(e),r=new E;return(async()=>{for await(let e of n)e.type===`text_delta`?r.push({type:`text_delta`,text:e.text??``}):e.type===`thinking_delta`?r.push({type:`thinking_delta`,text:e.text??``}):e.type===`tool_call`&&e.call?r.push({type:`tool_call`,call:{type:`tool_call`,id:e.call.id,name:e.call.name,args:e.call.args}}):e.type===`usage`&&e.usage&&r.push({type:`usage`,usage:e.usage});let e=n.result;e?r.finish(e):r.finish({content:[],usage:{in:0,out:0},stop:`stop`})})(),r}function be(e){let t=0;for(let n of e)if(typeof n.content==`string`)t+=n.content.length;else if(Array.isArray(n.content))for(let e of n.content)e.type===`text`&&(t+=e.text.length);return Math.ceil(t/4)}function D(e){return{type:`text`,text:e}}function O(e,t){return t===e||t.startsWith(`${e}/`)?o(e,t)||`.`:t}function xe(e){if(typeof e!=`string`)return e;let t=e,n=``;if(e.startsWith(`file://`)&&(t=e.slice(7),n=`file://`),i(t)){let e=process.cwd();return n+O(e,t)}return e}function Se(e,n=!1){return e?Object.entries(e).map(([e,r])=>{let i=typeof r==`string`?xe(r):JSON.stringify(r),a=i.length>40?`${i.slice(0,40)}…`:i;return`${n?t.dim(`${e}:`):`${e}:`} ${a}`}).join(` `):``}function k(e){let t=Date.now()-e,n=Math.floor(t/1e3),r=Math.floor(n/60),i=Math.floor(r/60);return n<60?`just now`:r<60?`${r}m ago`:i<24?`${i}h ago`:new Date(e).toLocaleDateString()}const Ce=e=>typeof e==`object`&&!!e&&e.type===`tool_call`;function we(e,t,n){let r=new E,i=[],a=t.maxTurns??50,o=e;return(async()=>{r.push({type:`start`});try{let e=0;for(;e<a&&!n?.aborted;){e++,r.push({type:`turn`});let a=be(o.messages);a>t.model.contextWindow*.9&&r.push({type:`text_delta`,text:`[warning] Approaching context limit (~${Math.round(a/1e3)}k / ${Math.round(t.model.contextWindow/1e3)}k tokens)`});let s=await Te(o,t,r,n);if(i.push(s),o={...o,messages:[...o.messages,s]},r.push({type:`assistant_msg`,msg:s}),s.stop===`error`||s.stop===`aborted`){r.push({type:`turn_end`,msg:s,results:[]});break}let c=s.content.filter(Ce);if(c.length===0){r.push({type:`turn_end`,msg:s,results:[]});break}let l=[];for(let e of c){if(n?.aborted)break;let a=o.tools.find(t=>t.def.name===e.name);if(!a){let t={role:`tool_result`,callId:e.id,tool:e.name,content:[D(`Unknown tool: ${e.name}`)],isError:!0,ts:Date.now()};l.push(t),o={...o,messages:[...o.messages,t]},i.push(t);continue}let s=await t.beforeTool?.(e,e.args,o);if(s?.block){let t={role:`tool_result`,callId:e.id,tool:e.name,content:[D(s.reason??`Blocked`)],isError:!0,ts:Date.now()};l.push(t),o={...o,messages:[...o.messages,t]},i.push(t);continue}let c=await a.execute(e.args,n),u={role:`tool_result`,callId:e.id,tool:e.name,args:e.args,content:c.content,isError:c.isError,ts:Date.now()};l.push(u),o={...o,messages:[...o.messages,u]},i.push(u),r.push({type:`tool_result`,callId:e.id,result:u,args:e.args}),await t.afterTool?.(e,u,o)}r.push({type:`turn_end`,msg:s,results:l})}e>=a&&r.push({type:`text_delta`,text:`[max turns reached (${a})]`})}catch(e){if(e.name===`AbortError`){r.finish(i);return}throw e}r.finish(i)})(),r}async function Te(e,t,n,r){let i=ye({apiFormat:t.apiFormat,model:t.model,apiKey:t.apiKey,baseUrl:t.baseUrl,system:e.system,messages:e.messages,tools:e.tools.map(e=>e.def),signal:r}),a=[],o={in:0,out:0};for await(let e of i)if(e.type===`text_delta`&&e.text){let t=a[a.length-1];t?.type===`text`?t.text+=e.text:a.push(D(e.text)),n.push({type:`text_delta`,text:e.text})}else e.type===`thinking_delta`&&e.text?n.push({type:`thinking_delta`,text:e.text}):e.type===`tool_call`&&e.call?(a.push(e.call),n.push({type:`tool_call`,call:e.call})):e.type===`usage`&&e.usage&&(o=e.usage,n.push({type:`usage`,usage:o}));let s=i.result?.content&&i.result.content.length>0?i.result.content:a,c=s.some(e=>e.type===`tool_call`)?s.filter(e=>e.type!==`text`||e.text.trim().length>0):s,l=i.result;return l?{role:`assistant`,content:c,model:t.model.id,provider:t.model.provider,usage:l.usage,stop:l.stop,ts:Date.now()}:{role:`assistant`,content:c,model:t.model.id,provider:t.model.provider,usage:o,stop:c.some(e=>e.type===`tool_call`)?`tool_use`:`stop`,ts:Date.now()}}var Ee=class{#e;#t;#n;#r=[];#i;#a;#o;constructor(e){this.#e=e.apiFormat,this.#t=e.model,this.#a=e.apiKey,this.#o=e.baseUrl,this.#n=e.system,this.#i=e.tools,this.#r=e.messages??[]}get model(){return this.#t}get messages(){return this.#r}get tools(){return this.#i}get apiKey(){return this.#a}get baseUrl(){return this.#o}updateConfig(e){this.#e=e.apiFormat,this.#t=e.model,this.#a=e.apiKey,this.#o=e.baseUrl}setTools(e){this.#i=e}setMessages(e){this.#r=e}setModel(e){this.#t=e}prompt(e){return we({system:this.#n,messages:this.#r,tools:this.#i},{apiFormat:this.#e,model:this.#t,apiKey:this.#a,baseUrl:this.#o},e)}};function De(e,t,n=[],r){let i=t.map(e=>`- ${e.def.name}: ${e.def.description}`).join(`
|
|
7
|
+
`),a=c.platform(),o=c.arch();return`You are Nova, an expert coding assistant. Help users with coding tasks using the tools available.
|
|
10
8
|
|
|
11
9
|
Format your responses with clean, standard markdown. Use headers (##, ###), bold text (**bold**), inline code (\`code\`), and code blocks (\`\`\`lang) to make your output clear and readable in the terminal.
|
|
12
10
|
|
|
@@ -17,7 +15,7 @@ ${i}
|
|
|
17
15
|
# Environment
|
|
18
16
|
|
|
19
17
|
- Working directory: ${e}
|
|
20
|
-
- Operating System: ${a} (${
|
|
18
|
+
- Operating System: ${a} (${c.release()})
|
|
21
19
|
- Architecture: ${o}
|
|
22
20
|
- Shell: ${process.env.SHELL||`unknown`}
|
|
23
21
|
- Date: ${new Date().toISOString().split(`T`)[0]}
|
|
@@ -51,12 +49,12 @@ ${n.length>0?n.map(e=>`- ${e.name}: ${e.description} (path: ${e.path}/SKILL.md)`
|
|
|
51
49
|
|
|
52
50
|
**IMPORTANT:** Before responding to a task that matches any skill above, you MUST first read the skill's SKILL.md file using the read tool with the full absolute path, then follow its instructions exactly. Do not skip this step.
|
|
53
51
|
|
|
54
|
-
${r?`\n<project_context>\nProject-specific instructions and guidelines:\n\n<project_instructions path="AGENTS.md">\n${r}\n</project_instructions>\n</project_context>`:``}`}function
|
|
52
|
+
${r?`\n<project_context>\nProject-specific instructions and guidelines:\n\n<project_instructions path="AGENTS.md">\n${r}\n</project_instructions>\n</project_context>`:``}`}function Oe(e){return e===0?`-`:e>=1e6?`${(e/1e6).toFixed(1)}M`:e>=1e3?`${(e/1e3).toFixed(1)}k`:String(e)}async function A(e,t,n={}){let[r,i]=t;if(r===`list`||r===`ls`){let t=n.limit??10,r=await e.list(t);if(r.length===0){console.log(`No sessions found.`);return}console.log(`ID`.padEnd(25),`TITLE / UPDATED`.padEnd(35),`TOKENS`),console.log(`-`.repeat(75));for(let e of r){let t=k(e.updated),n=e.title?`"${e.title}" (${t})`:t,r=Oe(e.inputTokens+e.outputTokens);console.log(e.id.padEnd(25),n.padEnd(35),r)}return}if(r===`delete`||r===`rm`){if(n.all){await e.deleteAll(),console.log(`All sessions deleted.`);return}i||(console.error(`Usage: nova --sessions rm <id> or --sessions rm --all`),process.exit(1)),await e.delete(i)?console.log(`Deleted session: ${i}`):(console.error(`Session not found: ${i}`),process.exit(1));return}console.error(`Unknown session subcommand.`),process.exit(1)}const j=[{id:`glm`,name:`GLM (Z.AI)`,apiFormat:`openai`,baseUrl:`https://api.z.ai/api/coding/paas/v4`,envKey:`GLM_API_KEY`},{id:`gemini`,name:`Gemini (Google)`,apiFormat:`gemini`,baseUrl:`https://generativelanguage.googleapis.com`,envKey:`GEMINI_API_KEY`},{id:`deepseek`,name:`DeepSeek`,apiFormat:`openai`,baseUrl:`https://api.deepseek.com`,envKey:`DEEPSEEK_API_KEY`},{id:`openai`,name:`OpenAI`,apiFormat:`openai`,baseUrl:`https://api.openai.com/v1`,envKey:`OPENAI_API_KEY`},{id:`anthropic`,name:`Anthropic`,apiFormat:`anthropic`,baseUrl:`https://api.anthropic.com`,envKey:`ANTHROPIC_API_KEY`}],M=[{id:`glm-5.1`,name:`GLM-5.1`,provider:`glm`,contextWindow:128e3,maxTokens:4096,supportsThinking:!1},{id:`glm-5`,name:`GLM-5`,provider:`glm`,contextWindow:128e3,maxTokens:4096,supportsThinking:!1},{id:`glm-5-turbo`,name:`GLM-5 Turbo`,provider:`glm`,contextWindow:128e3,maxTokens:4096,supportsThinking:!1},{id:`glm-4.7`,name:`GLM-4.7`,provider:`glm`,contextWindow:128e3,maxTokens:4096,supportsThinking:!1},{id:`glm-4.7-flash`,name:`GLM-4.7 Flash (Free)`,provider:`glm`,contextWindow:128e3,maxTokens:4096,supportsThinking:!1},{id:`glm-4.5-flash`,name:`GLM-4.5 Flash (Free)`,provider:`glm`,contextWindow:128e3,maxTokens:4096,supportsThinking:!1},{id:`gemini-3.5-flash`,name:`Gemini 3.5 Flash`,provider:`gemini`,contextWindow:1e6,maxTokens:65536,supportsThinking:!0},{id:`gemini-3.1-pro-preview`,name:`Gemini 3.1 Pro Preview`,provider:`gemini`,contextWindow:2e6,maxTokens:65536,supportsThinking:!0},{id:`gemini-3.1-pro-preview-customtools`,name:`Gemini 3.1 Pro (Custom Tools)`,provider:`gemini`,contextWindow:2e6,maxTokens:65536,supportsThinking:!0},{id:`gemini-3.1-flash-lite`,name:`Gemini 3.1 Flash-Lite`,provider:`gemini`,contextWindow:1e6,maxTokens:65536,supportsThinking:!0},{id:`gemini-3.1-flash-lite-preview`,name:`Gemini 3.1 Flash-Lite Preview`,provider:`gemini`,contextWindow:1e6,maxTokens:65536,supportsThinking:!0},{id:`gemini-3-flash-preview`,name:`Gemini 3 Flash Preview`,provider:`gemini`,contextWindow:1e6,maxTokens:65536,supportsThinking:!0},{id:`gemini-2.5-pro`,name:`Gemini 2.5 Pro`,provider:`gemini`,contextWindow:2e6,maxTokens:65536,supportsThinking:!1},{id:`gemini-2.5-flash`,name:`Gemini 2.5 Flash`,provider:`gemini`,contextWindow:1e6,maxTokens:65536,supportsThinking:!1},{id:`gemini-2.5-flash-lite`,name:`Gemini 2.5 Flash-Lite`,provider:`gemini`,contextWindow:1e6,maxTokens:65536,supportsThinking:!1},{id:`gemini-2.5-computer-use-preview-10-2025`,name:`Gemini 2.5 Computer Use`,provider:`gemini`,contextWindow:1e6,maxTokens:65536,supportsThinking:!1},{id:`deepseek-v4-flash`,name:`DeepSeek V4 Flash`,provider:`deepseek`,contextWindow:1e6,maxTokens:16384,supportsThinking:!0},{id:`deepseek-v4-pro`,name:`DeepSeek V4 Pro`,provider:`deepseek`,contextWindow:1e6,maxTokens:16384,supportsThinking:!0},{id:`gpt-5.5`,name:`GPT-5.5`,provider:`openai`,contextWindow:1e6,maxTokens:128e3,supportsThinking:!0,effort:`high`},{id:`gpt-5.5-pro`,name:`GPT-5.5 Pro`,provider:`openai`,contextWindow:1e6,maxTokens:128e3,supportsThinking:!0,effort:`xhigh`},{id:`gpt-5.4`,name:`GPT-5.4`,provider:`openai`,contextWindow:1e6,maxTokens:128e3,supportsThinking:!0,effort:`high`},{id:`gpt-5.4-pro`,name:`GPT-5.4 Pro`,provider:`openai`,contextWindow:1e6,maxTokens:128e3,supportsThinking:!0,effort:`xhigh`},{id:`gpt-5.4-mini`,name:`GPT-5.4 Mini`,provider:`openai`,contextWindow:4e5,maxTokens:128e3,supportsThinking:!0,effort:`medium`},{id:`gpt-5.4-nano`,name:`GPT-5.4 Nano`,provider:`openai`,contextWindow:4e5,maxTokens:128e3,supportsThinking:!0,effort:`low`},{id:`gpt-5.2`,name:`GPT-5.2`,provider:`openai`,contextWindow:1e6,maxTokens:128e3,supportsThinking:!0,effort:`high`},{id:`gpt-5.2-pro`,name:`GPT-5.2 Pro`,provider:`openai`,contextWindow:1e6,maxTokens:128e3,supportsThinking:!0,effort:`xhigh`},{id:`gpt-5.1`,name:`GPT-5.1`,provider:`openai`,contextWindow:1e6,maxTokens:128e3,supportsThinking:!0,effort:`high`},{id:`gpt-5`,name:`GPT-5`,provider:`openai`,contextWindow:4e5,maxTokens:128e3,supportsThinking:!0,effort:`medium`},{id:`gpt-5-mini`,name:`GPT-5 Mini`,provider:`openai`,contextWindow:4e5,maxTokens:128e3,supportsThinking:!0,effort:`medium`},{id:`gpt-5-nano`,name:`GPT-5 Nano`,provider:`openai`,contextWindow:4e5,maxTokens:128e3,supportsThinking:!0,effort:`low`},{id:`gpt-5-pro`,name:`GPT-5 Pro`,provider:`openai`,contextWindow:4e5,maxTokens:128e3,supportsThinking:!0,effort:`xhigh`},{id:`o4-mini`,name:`o4 Mini`,provider:`openai`,contextWindow:2e5,maxTokens:1e5,supportsThinking:!0,effort:`medium`},{id:`gpt-4.1`,name:`GPT-4.1`,provider:`openai`,contextWindow:1e6,maxTokens:32768,supportsThinking:!1},{id:`gpt-4.1-mini`,name:`GPT-4.1 Mini`,provider:`openai`,contextWindow:1e6,maxTokens:32768,supportsThinking:!1},{id:`gpt-4.1-nano`,name:`GPT-4.1 Nano`,provider:`openai`,contextWindow:1e6,maxTokens:32768,supportsThinking:!1},{id:`claude-opus-4-8`,name:`Claude 4.8 Opus`,provider:`anthropic`,contextWindow:2e5,maxTokens:64e3,supportsThinking:!0,effort:`xhigh`},{id:`claude-opus-4-7`,name:`Claude 4.7 Opus`,provider:`anthropic`,contextWindow:2e5,maxTokens:64e3,supportsThinking:!0,effort:`xhigh`},{id:`claude-opus-4-6`,name:`Claude 4.6 Opus`,provider:`anthropic`,contextWindow:2e5,maxTokens:32e3,supportsThinking:!0,effort:`high`},{id:`claude-opus-4-5`,name:`Claude 4.5 Opus`,provider:`anthropic`,contextWindow:2e5,maxTokens:32e3,supportsThinking:!0,effort:`high`},{id:`claude-sonnet-4-6`,name:`Claude 4.6 Sonnet`,provider:`anthropic`,contextWindow:2e5,maxTokens:32e3,supportsThinking:!0,effort:`medium`},{id:`claude-sonnet-4-5`,name:`Claude 4.5 Sonnet`,provider:`anthropic`,contextWindow:2e5,maxTokens:32e3,supportsThinking:!0,effort:`high`}];function N(e){return j.find(t=>t.id===e)}function ke(e){return M.filter(t=>t.provider===e)}const P=()=>a(process.env.HOME??`~`,`.novacode`),F=()=>a(P(),`config.json`),I=()=>a(P(),`auth.json`),L={provider:``,model:``},R={apiKeys:{}};async function Ae(){try{return await m(F()),!0}catch{return!1}}async function z(){try{let e=JSON.parse(await f(F(),`utf-8`));return{...L,...e}}catch{return{...L}}}async function B(){try{let e=JSON.parse(await f(I(),`utf-8`));return{...R,...e}}catch{return{...R}}}async function V(){await d(P(),{recursive:!0})}async function je(e){await V(),await h(F(),JSON.stringify(e,null,2))}async function Me(e){await V(),await h(I(),JSON.stringify(e,null,2));try{await u(I(),384)}catch{}}function Ne(){return P()}function Pe({message:e,options:t,header:n,footer:r,onSelect:i}){let[a,o]=b(0);return y((e,n)=>{if(n.escape){i(null);return}if(n.upArrow){o(e=>(e-1+t.length)%t.length);return}if(n.downArrow){o(e=>(e+1)%t.length);return}n.return&&i(t[a]?.value??null)}),S(g,{flexDirection:`column`,paddingX:1,children:[n&&x(g,{marginBottom:1,children:x(_,{children:n})}),x(g,{marginBottom:1,children:x(_,{bold:!0,children:e})}),t.map((e,t)=>S(g,{children:[S(_,{color:t===a?`green`:void 0,children:[t===a?`❯ `:` `,e.label]}),e.hint&&t===a&&S(_,{dimColor:!0,children:[` `,e.hint]})]},e.value)),x(g,{marginTop:1,children:x(_,{dimColor:!0,children:`↑↓ navigate · Enter select · Esc cancel`})}),r&&x(g,{marginTop:1,children:x(_,{children:r})})]})}function Fe({message:e,validate:t,onSubmit:n}){let[r,i]=b(``),[a,o]=b(``);return y((e,a)=>{if(a.escape){n(null);return}if(a.return){let e=t?.(r);if(e){o(e);return}n(r);return}if(a.backspace||a.delete){i(e=>e.slice(0,-1)),o(``);return}e&&(i(t=>t+e),o(``))}),S(g,{flexDirection:`column`,paddingX:1,children:[x(g,{marginBottom:1,children:x(_,{bold:!0,children:e})}),S(g,{children:[x(_,{color:`green`,children:`│ `}),x(_,{dimColor:!0,children:`*`.repeat(r.length)}),x(_,{color:`green`,children:`│`})]}),a&&x(g,{children:x(_,{color:`red`,children:a})}),x(g,{marginTop:1,children:x(_,{dimColor:!0,children:`Enter submit · Esc cancel`})})]})}function Ie({message:e,onConfirm:t}){let[n,r]=b(!0);return y((e,i)=>{if(i.escape){t(null);return}if(i.leftArrow||i.rightArrow||i.tab){r(e=>!e);return}i.return&&t(n)}),S(g,{flexDirection:`column`,paddingX:1,children:[x(g,{marginBottom:1,children:x(_,{bold:!0,children:e})}),x(g,{children:S(_,{color:n?`green`:void 0,children:[n?`❯ `:` `,`Yes`]})}),x(g,{children:S(_,{color:n?void 0:`red`,children:[n?` `:`❯ `,`No`]})}),x(g,{marginTop:1,children:x(_,{dimColor:!0,children:`←→ toggle · Enter confirm · Esc cancel`})})]})}function Le(e,t,n,r){return new Promise(i=>{let{unmount:a}=v(x(Pe,{message:e,options:t,header:n,footer:r,onSelect:e=>{a(),i(e)}}))})}function Re(e,t){return new Promise(n=>{let{unmount:r}=v(x(Fe,{message:e,validate:t,onSubmit:e=>{r(),n(e)}}))})}async function ze(){console.log(t.bold.cyan(`
|
|
55
53
|
⚡ Nova — your coding companion
|
|
56
|
-
`));let e=await
|
|
54
|
+
`));let e=await Le(`Pick a provider`,[...j].sort((e,t)=>e.name.localeCompare(t.name)).map(e=>({value:e.id,label:e.name})));e||(console.log(t.dim(`Cancelled`)),process.exit(0));let n=N(e);n||(console.log(t.red(`Unknown provider`)),process.exit(1));let r=await Re(`Enter ${n.name} API key`);r||(console.log(t.dim(`Cancelled`)),process.exit(0));let i=await Le(`Pick a default model`,ke(e).map(e=>({value:e.id,label:`${e.name} (${(e.contextWindow/1e3).toFixed(0)}k ctx)`})));i||(console.log(t.dim(`Cancelled`)),process.exit(0));let a={provider:e,model:i};return await je(a),await Me({apiKeys:{[e]:r}}),console.log(t.green(`
|
|
57
55
|
✓ Ready. Type your prompt or /help for commands
|
|
58
|
-
`)),a}const
|
|
59
|
-
`)){let t=e.match(/^name:\s*(.+)$/);t&&(r=t[1].trim());let n=e.match(/^description:\s*(.+)$/);n&&(i=n[1].trim())}return r?{name:r,description:i}:null}async function
|
|
56
|
+
`)),a}const Be=/^[a-z0-9]+(-[a-z0-9]+)*$/;function Ve(e){return e.length>64?{valid:!1,warning:`Skill name exceeds 64 characters: "${e}"`}:Be.test(e)?{valid:!0}:{valid:!1,warning:`Skill name contains invalid characters (use lowercase, numbers, hyphens): "${e}"`}}function He(e){let t=e.match(/^---\s*\n([\s\S]*?)\n---/);if(!t)return null;let n=t[1],r,i;for(let e of n.split(`
|
|
57
|
+
`)){let t=e.match(/^name:\s*(.+)$/);t&&(r=t[1].trim());let n=e.match(/^description:\s*(.+)$/);n&&(i=n[1].trim())}return r?{name:r,description:i}:null}async function Ue(e,t){let n=a(e,`SKILL.md`);try{let{readFile:r}=await import(`node:fs/promises`),i=He(await r(n,`utf-8`));return i?.name?i.description?{name:i.name,description:i.description,path:e,source:t}:(console.warn(`Skill missing description, skipping: ${e}`),null):null}catch{return null}}async function We(e,t){let n=[];try{let r=await p(e,{withFileTypes:!0});for(let i of r){if(!i.isDirectory())continue;let r=await Ue(a(e,i.name),t);r&&n.push(r)}}catch{}return n}async function Ge(e){let t=[a(l(),`.agents`,`skills`),a(l(),`.novacode`,`skills`)],n=[s(e,`.agents`,`skills`),s(e,`.novacode`,`skills`)],r=[];for(let e of t)r.push(...await We(e,`global`));for(let e of n)r.push(...await We(e,`project`));let i=new Set,o=[];for(let e of r){let t=Ve(e.name);if(t.valid||console.warn(t.warning),i.has(e.name)){console.warn(`Duplicate skill name "${e.name}", keeping first occurrence`);continue}i.add(e.name),e.description.length>1024&&console.warn(`Skill description exceeds 1024 characters: "${e.name}"`),o.push({name:e.name,description:e.description,path:e.path,source:e.source})}return o}async function Ke(e){let[t,n]=await Promise.all([Ge(e),qe(e)]);return{skills:t,agentsMd:n}}async function qe(e){try{return await f(a(e,`AGENTS.md`),`utf-8`)}catch{return null}}let H=null;function Je(e){if(H)return H;let t=e??a(process.env.HOME??`~`,`.novacode`,`state.db`);return ee(a(t,`..`),{recursive:!0}),H=new C(t,{enableForeignKeyConstraints:!0}),H.exec(`PRAGMA journal_mode = WAL`),H.exec(`
|
|
60
58
|
CREATE TABLE IF NOT EXISTS sessions (
|
|
61
59
|
id TEXT PRIMARY KEY,
|
|
62
60
|
cwd TEXT NOT NULL,
|
|
@@ -93,33 +91,34 @@ CREATE TABLE IF NOT EXISTS messages (
|
|
|
93
91
|
CREATE INDEX IF NOT EXISTS idx_sessions_updated ON sessions(updated DESC);
|
|
94
92
|
CREATE INDEX IF NOT EXISTS idx_sessions_parent ON sessions(parent_session_id);
|
|
95
93
|
CREATE INDEX IF NOT EXISTS idx_messages_session ON messages(session_id, seq);
|
|
96
|
-
`),
|
|
97
|
-
VALUES (?, ?, ?, ?, ?, ?, NULL, ?, ?, 0, 0, 0)`).run(e,t.cwd,t.model,t.provider,t.title,t.parentSessionId,t.created,t.created),this.#t.delete(e))}async create(e,t,n){let r=
|
|
98
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(e,m,r,i,a,o,s,c,l,u,d,f,p,t.ts??n),this.#e.prepare(`UPDATE sessions SET message_count = message_count + 1, updated = ?, input_tokens = input_tokens + ?, output_tokens = output_tokens + ? WHERE id = ?`).run(n,u,d,e)}async messages(e){return this.#e.prepare(`SELECT * FROM messages WHERE session_id = ? ORDER BY seq`).all(e).map(
|
|
94
|
+
`),H}function Ye(){H&&=(H.close(),null)}function Xe(){H=null}function Ze(){return`${Date.now().toString(36)}-${crypto.randomUUID().slice(0,8)}`}const Qe=`$json:`;function U(e){return e==null?null:typeof e==`string`?e:Qe+JSON.stringify(e)}function $e(e){return e===null?``:e.startsWith(Qe)?JSON.parse(e.slice(6)):e}function et(e){let t=e.role,n=$e(e.content),r=e.ts;return t===`user`?{role:`user`,content:n,ts:r}:t===`assistant`?{role:`assistant`,content:n||[],model:e.model??``,provider:e.provider??``,usage:{in:e.usage_input??0,out:e.usage_output??0},stop:e.stop_reason??`stop`,error:void 0,ts:r}:{role:`tool_result`,callId:e.tool_call_id??``,tool:e.tool_name??``,args:e.tool_args?JSON.parse(e.tool_args):void 0,content:n||[],isError:!!e.is_error,ts:r}}function W(e){return{id:e.id,cwd:e.cwd,model:e.model,provider:e.provider,title:e.title??null,parentSessionId:e.parent_session_id??null,endReason:e.end_reason??null,created:e.created,updated:e.updated,inputTokens:e.input_tokens??0,outputTokens:e.output_tokens??0,messageCount:e.message_count??0}}var tt=class{#e;#t=new Map;constructor(e){e instanceof C?this.#e=e:this.#e=Je(e)}#n(e){let t=this.#t.get(e);t&&(this.#e.prepare(`INSERT OR IGNORE INTO sessions (id, cwd, model, provider, title, parent_session_id, end_reason, created, updated, input_tokens, output_tokens, message_count)
|
|
95
|
+
VALUES (?, ?, ?, ?, ?, ?, NULL, ?, ?, 0, 0, 0)`).run(e,t.cwd,t.model,t.provider,t.title,t.parentSessionId,t.created,t.created),this.#t.delete(e))}async create(e,t,n){let r=Ze(),i=Date.now();return this.#t.set(r,{cwd:e,model:t,provider:n,title:null,parentSessionId:null,created:i}),{id:r,cwd:e,model:t,provider:n,title:null,parentSessionId:null,endReason:null,created:i,updated:i,inputTokens:0,outputTokens:0,messageCount:0}}async get(e){let t=this.#e.prepare(`SELECT * FROM sessions WHERE id = ?`).get(e);if(t)return W(t);let n=this.#t.get(e);return n?{id:e,cwd:n.cwd,model:n.model,provider:n.provider,title:n.title,parentSessionId:n.parentSessionId,endReason:null,created:n.created,updated:n.created,inputTokens:0,outputTokens:0,messageCount:0}:null}async list(e=10){return this.#e.prepare(`SELECT * FROM sessions WHERE end_reason IS NULL ORDER BY updated DESC LIMIT ?`).all(e).map(W)}async latest(){let e=this.#e.prepare(`SELECT * FROM sessions WHERE end_reason IS NULL ORDER BY updated DESC LIMIT 1`).get();return e?W(e):null}async delete(e){let t=this.#t.delete(e),n=this.#e.prepare(`DELETE FROM sessions WHERE id = ?`).run(e);return t||n.changes>0}async deleteAll(){this.#t.clear(),this.#e.exec(`DELETE FROM messages; DELETE FROM sessions`)}async append(e,t){this.#n(e);let n=Date.now(),r=t.role,i=null,a=null,o=null,s=null,c=null,l=null,u=0,d=0,f=null,p=0;r===`user`?i=U(t.content):r===`assistant`?(i=U(t.content),c=t.model??null,l=t.provider??null,u=t.usage?.in??0,d=t.usage?.out??0,f=t.stop??null,t.error&&(p=1)):r===`tool_result`&&(i=U(t.content),a=t.callId??null,o=t.tool??null,s=t.args?JSON.stringify(t.args):null,p=+!!t.isError);let m=this.#e.prepare(`SELECT COALESCE(MAX(seq), 0) + 1 AS next_seq FROM messages WHERE session_id = ?`).get(e)?.next_seq;this.#e.prepare(`INSERT INTO messages (session_id, seq, role, content, tool_call_id, tool_name, tool_args, model, provider, usage_input, usage_output, stop_reason, is_error, ts)
|
|
96
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(e,m,r,i,a,o,s,c,l,u,d,f,p,t.ts??n),this.#e.prepare(`UPDATE sessions SET message_count = message_count + 1, updated = ?, input_tokens = input_tokens + ?, output_tokens = output_tokens + ? WHERE id = ?`).run(n,u,d,e)}async messages(e){return this.#e.prepare(`SELECT * FROM messages WHERE session_id = ? ORDER BY seq`).all(e).map(et)}async history(e){let t=this.#r(e);if(t.length<=1)return this.messages(e);let n=t.map((e,t)=>`WHEN '${e}' THEN ${t}`).join(` `);return this.#e.prepare(`SELECT m.* FROM messages m
|
|
99
97
|
WHERE m.session_id IN (${t.map(()=>`?`).join(`,`)})
|
|
100
|
-
ORDER BY CASE m.session_id ${n} END ASC, m.seq ASC`).all(...t).map(
|
|
101
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(e,t,r,i,a,o,s,c,l,u,d,f,p,n.ts??Date.now())}async prune(){this.#e.exec(`DELETE FROM sessions WHERE message_count = 0`)}close(){
|
|
102
|
-
`),o=Math.max(0,(Number(t.offset??1)||1)-1),s=Number(t.limit??2e3)||2e3,c=a.slice(o,o+s),l=o+s<a.length;return{content:[
|
|
103
|
-
`)+(l?`\n…${a.length-o-s} more lines`:``))],isError:!1}}catch(e){return{content:[
|
|
98
|
+
ORDER BY CASE m.session_id ${n} END ASC, m.seq ASC`).all(...t).map(et)}async messageCount(e){return this.#e.prepare(`SELECT message_count FROM sessions WHERE id = ?`).get(e)?.message_count??0}async setTitle(e,t){this.#n(e),this.#e.prepare(`UPDATE sessions SET title = ?, updated = ? WHERE id = ?`).run(t,Date.now(),e)}async replaceMessages(e,t){t.length>0&&this.#n(e),this.#e.prepare(`DELETE FROM messages WHERE session_id = ?`).run(e),this.#e.prepare(`UPDATE sessions SET message_count = 0, updated = ? WHERE id = ?`).run(Date.now(),e);let n=0;for(let r of t)n++,await this.#i(e,n,r);this.#e.prepare(`UPDATE sessions SET message_count = ?, updated = ? WHERE id = ?`).run(n,Date.now(),e)}async endSession(e,t){this.#n(e),this.#e.prepare(`UPDATE sessions SET end_reason = ?, updated = ? WHERE id = ?`).run(t,Date.now(),e)}async createContinuation(e,t,n,r){let i=Ze(),a=Date.now();return this.#t.set(i,{cwd:t,model:n,provider:r,title:null,parentSessionId:e,created:a}),{id:i,cwd:t,model:n,provider:r,title:null,parentSessionId:e,endReason:null,created:a,updated:a,inputTokens:0,outputTokens:0,messageCount:0}}#r(e){let t=[],n=e,r=new Set;for(;n&&!r.has(n);){t.push(n),r.add(n);let e=this.#e.prepare(`SELECT parent_session_id FROM sessions WHERE id = ?`).get(n);n=e?e.parent_session_id??``:this.#t.get(n)?.parentSessionId??``}return t.reverse(),t}async#i(e,t,n){let r=n.role,i=null,a=null,o=null,s=null,c=null,l=null,u=0,d=0,f=null,p=0;r===`user`?i=U(n.content):r===`assistant`?(i=U(n.content),c=n.model??null,l=n.provider??null,u=n.usage?.in??0,d=n.usage?.out??0,f=n.stop??null,n.error&&(p=1)):r===`tool_result`&&(i=U(n.content),a=n.callId??null,o=n.tool??null,s=n.args?JSON.stringify(n.args):null,p=+!!n.isError),this.#e.prepare(`INSERT INTO messages (session_id, seq, role, content, tool_call_id, tool_name, tool_args, model, provider, usage_input, usage_output, stop_reason, is_error, ts)
|
|
99
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(e,t,r,i,a,o,s,c,l,u,d,f,p,n.ts??Date.now())}async prune(){try{this.#e.exec(`DELETE FROM sessions WHERE message_count = 0`)}catch{}}close(){Ye()}};let G=null;async function nt(e){return G||(G=new tt(e?`${e}/state.db`:void 0),G)}const rt=new Set([`.jpg`,`.jpeg`,`.png`,`.gif`,`.webp`]);function K(e,t){let n=s(e,t);if(n!==e&&!n.startsWith(`${e}/`))throw Error(`Path outside project: ${t}`);return n}function it(e){return{def:{name:`read`,description:`Read file contents. Supports text and images (jpg, png, gif, webp). Text output is truncated to 2000 lines.`,parameters:{type:`object`,properties:{path:{type:`string`,description:`Path to file (relative or absolute)`},offset:{type:`number`,description:`Start line (1-based, default 1)`},limit:{type:`number`,description:`Max lines to read (default 2000)`}},required:[`path`]}},async execute(t){try{let n=K(e,t.path),i=r(n).toLowerCase();if(rt.has(i))return{content:[{type:`image`,data:(await f(n)).toString(`base64`),mime:i===`.jpg`?`image/jpeg`:`image/${i.slice(1)}`}],isError:!1};let a=(await f(n,`utf-8`)).split(`
|
|
100
|
+
`),o=Math.max(0,(Number(t.offset??1)||1)-1),s=Number(t.limit??2e3)||2e3,c=a.slice(o,o+s),l=o+s<a.length;return{content:[D(c.join(`
|
|
101
|
+
`)+(l?`\n…${a.length-o-s} more lines`:``))],isError:!1}}catch(e){return{content:[D(`Error reading file: ${e.message}`)],isError:!0}}}}}function at(e){return{def:{name:`write`,description:`Write content to a file. Creates the file and parent directories if needed.`,parameters:{type:`object`,properties:{path:{type:`string`,description:`Path to file`},content:{type:`string`,description:`Content to write`}},required:[`path`,`content`]}},async execute(t){try{let r=K(e,t.path),i=t.content;await d(n(r),{recursive:!0}),await h(r,i);let a=O(e,r);return{content:[D(`Wrote ${i.length} bytes → ${a}`)],isError:!1}}catch(e){return{content:[D(`Error writing file: ${e.message}`)],isError:!0}}}}}function ot(e){return{def:{name:`edit`,description:`Edit a file using exact text replacement. Each edit's oldText must be unique in the file.`,parameters:{type:`object`,properties:{path:{type:`string`,description:`Path to file`},edits:{type:`array`,description:`Array of {oldText, newText} replacements. oldText must be unique. Non-overlapping.`,items:{type:`object`,properties:{oldText:{type:`string`,description:`Exact text to find (must be unique)`},newText:{type:`string`,description:`Replacement text`}},required:[`oldText`,`newText`]}}},required:[`path`,`edits`]}},async execute(t){try{let n=K(e,t.path),r;try{r=await f(n,`utf-8`)}catch{return{content:[D(`File not found: ${t.path}`)],isError:!0}}let i=t.edits;for(let e of i){let t=r.split(e.oldText).length-1;if(t===0)return{content:[D(`oldText not found: "${e.oldText.slice(0,80)}…"`)],isError:!0};if(t>1)return{content:[D(`oldText found ${t} times — add surrounding context to make it unique: "${e.oldText.slice(0,60)}…"`)],isError:!0}}for(let e of i)r=r.replace(e.oldText,e.newText);return await h(n,r),{content:[D(`Edited ${O(e,n)} (${i.length} replacement${i.length>1?`s`:``})`)],isError:!1}}catch(e){return{content:[D(`Error editing file: ${e.message}`)],isError:!0}}}}}function st(e){return{def:{name:`git`,description:`Execute safe, non-interactive git commands (status, diff, log, add, commit) in the repository.`,parameters:{type:`object`,properties:{action:{type:`string`,enum:[`status`,`diff`,`log`,`add`,`commit`],description:`The git action to execute`},args:{type:`array`,description:`Optional additional arguments or file paths for the git action`,items:{type:`string`}}},required:[`action`]}},async execute(t,n){let r=t.action,i=t.args||[];if(!new Set([`status`,`diff`,`log`,`add`,`commit`]).has(r))return{content:[D(`Error: Git action '${r}' is not supported.`)],isError:!0};try{let t=[`git`,r,...i],a=w(t[0],t.slice(1),{cwd:e,stdio:[`ignore`,`pipe`,`pipe`],env:{...process.env,PAGER:`cat`}}),o=``,s=``;a.stdout.on(`data`,e=>{o+=e.toString()}),a.stderr.on(`data`,e=>{s+=e.toString()});let c=()=>{a.kill(`SIGKILL`),a.stdout.destroy(),a.stderr.destroy()};n?.addEventListener(`abort`,c,{once:!0});let l;try{l=await new Promise((e,t)=>{a.on(`error`,t),a.on(`close`,t=>e(t??-1))})}finally{n?.removeEventListener(`abort`,c)}let u=5e4,d=``;return o&&(d+=o.slice(0,u)),s&&(d&&(d+=`
|
|
104
102
|
`),d+=s.slice(0,u-d.length)),d.length>=u&&(d+=`
|
|
105
|
-
…truncated`),{content:[
|
|
106
|
-
`):`No files found`)],isError:!1}}catch(e){return{content:[
|
|
103
|
+
…truncated`),{content:[D(d||`(no output)`)],isError:l!==0}}catch(e){return{content:[D(`Error running git: ${e.message}`)],isError:!0}}}}}function ct(e){return{def:{name:`glob`,description:`Find files by glob pattern (e.g. **/*.ts, src/**/*.test.ts).`,parameters:{type:`object`,properties:{pattern:{type:`string`,description:`Glob pattern (e.g. **/*.ts)`},path:{type:`string`,description:`Directory to search in (default .)`},nocase:{type:`boolean`,description:`Case-insensitive search (default false)`}},required:[`pattern`]}},async execute(t){try{let n=t.path||`.`,r=s(e,n);if(r!==e&&!r.startsWith(`${e}/`))throw Error(`Path outside project: ${n}`);let i=t.pattern,a=(await te(i,{cwd:r,nocase:!!t.nocase})).slice(0,500),c=o(e,r),l=c?`${c}/`:``,u=a.map(e=>l+e);return{content:[D(u.length>0?u.join(`
|
|
104
|
+
`):`No files found`)],isError:!1}}catch(e){return{content:[D(`Error: ${e.message}`)],isError:!0}}}}}function lt(e){return{def:{name:`grep`,description:`Search file contents with a regex pattern. Returns matching lines with file paths and line numbers.`,parameters:{type:`object`,properties:{pattern:{type:`string`,description:`Regex pattern to search for`},path:{type:`string`,description:`Directory or file to search in (default .)`},glob:{type:`string`,description:`File filter glob (e.g. *.ts)`}},required:[`pattern`]}},async execute(t,n){try{let r=t.path||`.`,i=s(e,r);if(i!==e&&!i.startsWith(`${e}/`))throw Error(`Path outside project: ${r}`);let a=t.pattern,c=t.glob,l=o(e,i)||`.`;try{let t=[`rg`,`--line-number`,`--max-count`,`200`];c&&t.push(`--glob=${c}`),t.push(`--`,a,l);let r=w(t[0],t.slice(1),{cwd:e,stdio:[`ignore`,`pipe`,`pipe`]}),i=()=>{r.kill(),r.stdout.destroy(),r.stderr.destroy()};n?.addEventListener(`abort`,i,{once:!0});let o=``;r.stdout.on(`data`,e=>{o+=e.toString()});let s;try{s=await new Promise((e,t)=>{r.on(`error`,t),r.on(`close`,t=>e(t??-1))})}finally{n?.removeEventListener(`abort`,i)}if(s===0)return{content:[D(o.split(`
|
|
107
105
|
`).slice(0,200).join(`
|
|
108
|
-
`)||`No matches`)],isError:!1}}catch{}let u=await
|
|
109
|
-
`);for(let n=0;n<t.length&&m.length<200;n++){let r=t[n];r&&
|
|
110
|
-
`)||`No matches`)],isError:!1}}catch(e){return{content:[
|
|
111
|
-
`)||`(empty)`)],isError:!1}}catch(e){return{content:[
|
|
106
|
+
`)||`No matches`)],isError:!1}}catch{}let u=await te(c||`**/*`,{cwd:i,ignore:[`**/node_modules/**`,`**/.git/**`]}),d=l===`.`?``:`${l}/`,p=new RegExp(a,`i`),m=[];for(let e of u.slice(0,500)){if(n?.aborted)break;try{let t=(await f(s(i,e),`utf-8`)).split(`
|
|
107
|
+
`);for(let n=0;n<t.length&&m.length<200;n++){let r=t[n];r&&p.test(r)&&m.push(`${d}${e}:${n+1}:${r}`)}}catch{}}return{content:[D(m.join(`
|
|
108
|
+
`)||`No matches`)],isError:!1}}catch(e){return{content:[D(`Error: ${e.message}`)],isError:!0}}}}}function ut(e){return{def:{name:`ls`,description:`List directory contents.`,parameters:{type:`object`,properties:{path:{type:`string`,description:`Directory to list (default .)`}},required:[]}},async execute(t){try{return{content:[D((await p(s(e,t.path||`.`),{withFileTypes:!0})).map(e=>{let t=e.isDirectory()?`/`:e.isSymbolicLink()?`@`:``;return`${e.name}${t}`}).join(`
|
|
109
|
+
`)||`(empty)`)],isError:!1}}catch(e){return{content:[D(`Error: ${e.message}`)],isError:!0}}}}}function dt(e){return{def:{name:`tree`,description:`Print a visual directory tree structure, ignoring common ignored folders like node_modules and .git.`,parameters:{type:`object`,properties:{path:{type:`string`,description:`Directory to start tree from (default .)`},depth:{type:`number`,description:`Maximum depth to traverse (default 3)`}},required:[]}},async execute(t){try{let n=s(e,t.path||`.`),r=Number(t.depth??3)||3,i=new Set([`.git`,`node_modules`,`dist`,`build`,`.svelte-kit`,`.next`,`out`,`.scannerwork`,`coverage`]);async function a(e,t,n){if(t>r)return``;let o=``,c=(await p(e,{withFileTypes:!0})).filter(e=>!i.has(e.name)).sort((e,t)=>e.isDirectory()&&!t.isDirectory()?-1:!e.isDirectory()&&t.isDirectory()?1:e.name.localeCompare(t.name));for(let r=0;r<c.length;r++){let i=c[r],l=r===c.length-1,u=l?`└── `:`├── `,d=n+(l?` `:`│ `);o+=`${n}${u}${i.name}${i.isDirectory()?`/`:``}\n`,i.isDirectory()&&(o+=await a(s(e,i.name),t+1,d))}return o}return{content:[D(await a(n,1,``)||`(empty)`)],isError:!1}}catch(e){return{content:[D(`Error: ${e.message}`)],isError:!0}}}}}function ft(e){return{def:{name:`bash`,description:`Execute a shell command. Returns stdout and stderr. Timeout after N seconds (default 120).`,parameters:{type:`object`,properties:{command:{type:`string`,description:`Shell command to run`},timeout:{type:`number`,description:`Timeout in seconds (default 120)`}},required:[`command`]}},async execute(t,n){let r=t.command,i=(Number(t.timeout)||120)*1e3;try{let t=w(`sh`,[`-c`,r],{cwd:e,stdio:[`ignore`,`pipe`,`pipe`]}),a=``,o=``;t.stdout.on(`data`,e=>{a+=e.toString()}),t.stderr.on(`data`,e=>{o+=e.toString()});let s=!1,c=setTimeout(()=>{s=!0,t.kill(`SIGKILL`),t.stdout.destroy(),t.stderr.destroy()},i),l=()=>{s=!0,t.kill(`SIGKILL`),t.stdout.destroy(),t.stderr.destroy()};n?.addEventListener(`abort`,l,{once:!0});let u;try{u=await new Promise((e,n)=>{t.on(`error`,n),t.on(`close`,t=>e(t??-1))})}finally{clearTimeout(c),n?.removeEventListener(`abort`,l)}let d=5e4,f=``;return a&&(f+=a.slice(0,d)),o&&(f&&(f+=`
|
|
112
110
|
`),f+=o.slice(0,d-f.length)),f.length>=d&&(f+=`
|
|
113
|
-
…truncated`),s&&(f+=`\n[timeout after ${i/1e3}s]`),f+=`\n[exit ${u}]`,{content:[
|
|
111
|
+
…truncated`),s&&(f+=`\n[timeout after ${i/1e3}s]`),f+=`\n[exit ${u}]`,{content:[D(f)],isError:u!==0||s}}catch(e){return{content:[D(`Error: ${e.message}`)],isError:!0}}}}}const q=5e4;function J(e,t,n){let r;do r=e,e=e.replace(t,n);while(e!==r);return e}function Y(e){let t=e;return t=J(t,/<!--[\s\S]*?-->/g,``),t=J(t,/<script[\s\S]*?<\/script[^>]*>/gi,``),t=J(t,/<style[\s\S]*?<\/style[^>]*>/gi,``),t=t.replace(/<a[^>]*href=["']?([^"'>\s]*)["']?[^>]*>([\s\S]*?)<\/a>/gi,`[$2]($1)`).replace(/<\/?(p|div|br|h[1-6]|li|tr|blockquote|pre|hr)[^>]*>/gi,`
|
|
114
112
|
`).replace(/<[^>]+>/g,``).replace(/</g,`<`).replace(/>/g,`>`).replace(/"/g,`"`).replace(/"/g,`"`).replace(/"/g,`"`).replace(/'/g,`'`).replace(/'/g,`'`).replace(/'/g,`'`).replace(/“/g,`"`).replace(/”/g,`"`).replace(/‘/g,`'`).replace(/’/g,`'`).replace(/ /g,` `).replace(/&/g,`&`).replace(/[ \t]+/g,` `).replace(/\n{3,}/g,`
|
|
115
113
|
|
|
116
|
-
`).trim(),t.length>
|
|
114
|
+
`).trim(),t.length>q&&(t=`${t.slice(0,q)}\n…truncated`),t}function pt(){return{def:{name:`web_search`,description:`Search the web using DuckDuckGo. Returns up to 10 results with titles, URLs, and snippets. Use this when you need information from the internet.`,parameters:{type:`object`,properties:{query:{type:`string`,description:`Search query`}},required:[`query`]}},async execute(e,t){let n=e.query;if(!n.trim())return{content:[D(`Error: empty search query`)],isError:!0};try{let e=`https://html.duckduckgo.com/html/?q=${encodeURIComponent(n)}`,r=await fetch(e,{signal:t??void 0,headers:{"User-Agent":`Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36`}});if(!r.ok)return{content:[D(`Search failed: HTTP ${r.status}`)],isError:!0};let i=await r.text(),a=[],o=/<div[^>]*class="[^"]*result__body[^"]*"[^>]*>/gi,s=[];for(let e of i.matchAll(o))e.index!==void 0&&s.push(e.index);if(s.length>0)for(let e=0;e<s.length;e++){let t=s[e],n=s[e+1]??i.length;a.push(i.slice(t,n))}let c=[],l=/<a[^>]*class="result__a"[^>]*href="([^"]*)"[^>]*>([\s\S]*?)<\/a>/i,u=/<a[^>]*class="result__snippet"[^>]*>([\s\S]*?)<\/a>/i;for(let e of a){if(c.length>=10)break;let t=l.exec(e);if(!t)continue;let n=t[1],r=Y(t[2]),i=u.exec(e),a=i?Y(i[1]):``,o=n;try{let e=n.startsWith(`//`)?`https:${n}`:n.startsWith(`/`)?`https://duckduckgo.com${n}`:n,t=new URL(e).searchParams.get(`uddg`);t&&(o=t)}catch{}c.push(`## ${r}\n${o}\n${a}`)}return c.length===0?{content:[D(`No results found.`)],isError:!1}:{content:[D(c.join(`
|
|
117
115
|
|
|
118
|
-
`))],isError:!1}}catch(e){let t=e.message;return t.includes(`abort`)?{content:[
|
|
116
|
+
`))],isError:!1}}catch(e){let t=e.message;return t.includes(`abort`)?{content:[D(`Search aborted.`)],isError:!0}:{content:[D(`Search error: ${t}`)],isError:!0}}}}}function mt(){return{def:{name:`web_fetch`,description:`Fetch and read the content of a web page. Returns the page text with HTML tags stripped. Useful for reading documentation, articles, or API references.`,parameters:{type:`object`,properties:{url:{type:`string`,description:`URL to fetch`}},required:[`url`]}},async execute(e,t){let n=e.url;if(!n.trim())return{content:[D(`Error: empty URL`)],isError:!0};try{new URL(n)}catch{return{content:[D(`Error: invalid URL: ${n}`)],isError:!0}}try{let e=await fetch(n,{signal:t??void 0,headers:{"User-Agent":`Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36`,Accept:`text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8`},redirect:`follow`});if(!e.ok)return{content:[D(`Fetch failed: HTTP ${e.status} ${e.statusText}`)],isError:!0};let r=(e.headers.get(`content-type`)??``).toLowerCase(),i=await e.text();return r.includes(`text/html`)||r.includes(`application/xhtml+xml`)||i.trim().toLowerCase().startsWith(`<!doctype html`)||i.trim().toLowerCase().startsWith(`<html`)?{content:[D(Y(i))],isError:!1}:{content:[D(i.length>q?`${i.slice(0,q)}\n…truncated`:i)],isError:!1}}catch(e){let t=e.message;return t.includes(`abort`)?{content:[D(`Fetch aborted.`)],isError:!0}:{content:[D(`Fetch error: ${t}`)],isError:!0}}}}}function ht(e){return[it(e),at(e),ot(e),ft(e),ct(e),lt(e),ut(e),dt(e),st(e),pt(),mt()]}const gt=n(ne(import.meta.url));let X=null,Z=null;async function Q(){if(Z)return Z;try{let e=await f(a(gt,`..`,`package.json`),`utf-8`);return Z=JSON.parse(e).version??`0.0.0`,Z}catch{return`0.0.0`}}async function _t(){if(X)return X;try{let e=w(`npm`,[`info`,`novacode`,`version`],{stdio:[`ignore`,`pipe`,`ignore`]}),t=await new Promise((t,n)=>{let r=``;e.stdout.on(`data`,e=>{r+=e.toString()}),e.on(`error`,n),e.on(`close`,()=>t(r.trim()))});if(t)return X=t,t}catch{}return null}async function vt(){let e=await Q(),t=await _t();return t?{hasUpdate:re.gt(t,e),current:e,latest:t}:null}async function $(e=!1){try{let t=w(`npm`,[`update`,`-g`,`novacode`],{stdio:e?`ignore`:`inherit`}),n=await new Promise((e,n)=>{t.on(`error`,n),t.on(`close`,t=>e(t??-1))});return n===0?(e||console.log(`✓ novacode updated to latest version successfully.`),!0):(e||(console.error(`Update failed (exit code ${n})`),process.exit(1)),!1)}catch(t){return e||(console.error(`Update failed: ${t.message}`),process.exit(1)),!1}}function yt(){let{values:t,positionals:n}=e({options:{help:{type:`boolean`,short:`h`},version:{type:`boolean`,short:`v`},provider:{type:`string`},model:{type:`string`},"api-key":{type:`string`},sessions:{type:`string`,short:`s`},resume:{type:`boolean`,short:`r`},all:{type:`boolean`}},strict:!1,allowPositionals:!0});return{flags:t,args:n}}function bt(e,t){return M.find(n=>t?n.provider===t&&n.id===e:n.id===e)}async function xt(){let e=Number(process.versions.node.split(`.`)[0]);(!e||e<24)&&(console.error(`novacode requires Node.js >= 24. You have ${process.version}.`),console.error(`Upgrade: https://nodejs.org/`),process.exit(1));let{flags:n,args:r}=yt();if(n.version){let e=await Q();console.log(`nova ${e}`),process.exit(0)}if(n.help&&(console.log(`nova — open-source coding agent
|
|
119
117
|
|
|
120
118
|
Usage:
|
|
121
119
|
nova Interactive mode
|
|
122
120
|
nova update Update to latest version
|
|
121
|
+
nova reset Delete all nova data and exit
|
|
123
122
|
nova -s ls [limit] List sessions (last 10 by default)
|
|
124
123
|
nova -s rm <id> Delete a specific session
|
|
125
124
|
nova -s rm --all Delete all sessions
|
|
@@ -133,7 +132,7 @@ Options:
|
|
|
133
132
|
--model <id> Model to use
|
|
134
133
|
--api-key <key> API key override
|
|
135
134
|
-s, --sessions <id> Resume/manage sessions
|
|
136
|
-
-r, --resume Resume the most recent session`),process.exit(0)),r[0]===`update`){await
|
|
135
|
+
-r, --resume Resume the most recent session`),process.exit(0)),r[0]===`update`){await $();return}if(r[0]===`reset`){let{handleCliReset:e}=await import(`./reset-C2XGbjKJ.mjs`).then(e=>e.n);await e();return}r.length>0&&!n.sessions&&(console.error(t.yellow(`Unknown command: ${r.join(` `)}`)),console.error("Run `nova --help` for usage."),process.exit(1));let i=new AbortController,a=()=>{i.abort(),process.stderr.write(`
|
|
137
136
|
Aborted.
|
|
138
|
-
`),process.exit(130)};process.on(`SIGINT`,a),process.on(`SIGTERM`,a);let o=await(await
|
|
137
|
+
`),process.exit(130)};process.on(`SIGINT`,a),process.on(`SIGTERM`,a);let o=await(await Ae()?z():ze()),s=await B(),c=await nt();if(await c.prune(),n.sessions){let e=n.sessions;if(e===`ls`||e===`list`){let e=r[0]?parseInt(r[0],10):10;await A(c,[`ls`],{limit:Number.isNaN(e)?10:e});return}if(e===`rm`||e===`delete`){let e=r[0],t=!!n.all;await A(c,[`rm`,e??``],{all:t});return}}let l=null;n.resume?(l=await c.latest(),l||(console.error(`No recent session found to resume.`),process.exit(1))):n.sessions&&(l=await c.get(n.sessions),l||(console.error(`Session not found: ${n.sessions}`),process.exit(1)));let u=n.provider||l?.provider||o.provider,d=n.model||l?.model||o.model,f=n[`api-key`]||s.apiKeys[u],p=N(u);p||(console.error(`Unknown provider: ${u}`),console.error(`Available: ${N(`glm`)?`glm, `:``}gemini, deepseek, openai, anthropic`),process.exit(1)),f||(console.error(`No API key for ${p.name}. Set ${p.envKey} or run nova for onboarding.`),process.exit(1));let m=bt(d,u);if(!m){console.error(`Unknown model: ${d}`),console.error(`Available models:`);for(let e of M.filter(e=>e.provider===u))console.error(` ${e.id} — ${e.name}`);process.exit(1)}let h=process.cwd(),g=ht(h),{skills:_,agentsMd:v}=await Ke(h),y=De(h,g,_,v??void 0);l||=await c.create(h,m.id,u);let b=l.id,x=await c.messages(b),S=new Ee({apiFormat:p.apiFormat,model:m,apiKey:f,baseUrl:p.baseUrl,system:y,tools:g,messages:x});process.off(`SIGINT`,a),process.off(`SIGTERM`,a);let{interactive:C}=await import(`./app-CBs69waM.mjs`);await C(S,c,b,_,!!v)}process.on(`unhandledRejection`,e=>{console.error(`Unhandled rejection:`,e),process.exit(1)}),xt().catch(e=>{console.error(`Fatal:`,e),process.exit(1)});export{be as _,Xe as a,ye as b,Pe as c,z as d,Me as f,N as g,j as h,Ye as i,Ne as l,M as m,Q as n,Ie as o,je as p,$ as r,Fe as s,vt as t,B as u,k as v,Se as y};
|
|
139
138
|
//# sourceMappingURL=main.mjs.map
|