@hyperez/regna-code 0.2.6 → 0.4.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/README.md CHANGED
@@ -50,6 +50,7 @@ For CI or scripted use, set `REGNA_API_KEY` directly; it takes priority over the
50
50
  | `REGNA_API_KEY` | (none) | Regna API key. Optional once you have run `regna login`. When set, it overrides the stored credential (use for CI). |
51
51
  | `REGNA_BASE_URL` | `https://regnax.ai/v1` | Regna API base URL (OpenAI-compatible). Point this at a self-hosted endpoint for on-premise use. |
52
52
  | `REGNA_MODEL` | (auto) | Starting model. By default the current single cloud model is detected from the gateway automatically; set this to pin a specific id. |
53
+ | `REGNA_WEB_SEARCH` | (auto) | Gateway-executed web search. `1` on, `0` off. Default: on for the Regna cloud, off for self-hosted endpoints. When on, the model can search the web; the search runs on the gateway (this machine makes no extra network calls), and each successful search is billed as a small credit surcharge. |
53
54
  | `REGNA_EXPOSE_ALIASES` | (unset) | `1` also exposes path-style (slash) model ids. Hidden by default. The id pinned via `REGNA_MODEL` is always shown. |
54
55
  | `REGNA_POLICY` | `off` | Network egress guard: `off` / `warn` (notify, allow) / `enforce` (block external network tools). Set `enforce` for locked-down or air-gapped use. |
55
56
  | `REGNA_OFFLINE` | (unset) | `1` runs fully offline: the runtime skips all self-network, including the one-time download of search helpers (`fd`/`ripgrep`). They fall back to the built-in search. Use for air-gapped installs. |
@@ -75,6 +76,31 @@ For CI or scripted use, set `REGNA_API_KEY` directly; it takes priority over the
75
76
  | `/regna-docs <question>` | Document-grounded query. Searches indexed documents with `regna_docs_search`, answers using only retrieved evidence with `[source n]` citations, and says it does not know when there is no evidence. Requires `REGNA_DOCS_ENABLED=1`. |
76
77
  | `/mcp` | List configured MCP servers, their connection status, and tool counts. |
77
78
 
79
+ ## Subagents (`regna_task`)
80
+
81
+ The model can delegate self-contained subtasks to separate Regna agents with the built-in
82
+ `regna_task` tool. Each subagent runs as a child `regna` process in print mode with a fresh
83
+ context, the same working directory, the same gateway key, and the same policy gates. Sibling
84
+ tool calls run in parallel, so asking for several independent investigations in one message
85
+ fans them out concurrently. Subagents cannot spawn further subagents.
86
+
87
+ | Variable | Meaning |
88
+ |---|---|
89
+ | `REGNA_TASK_DISABLED=1` | Do not register the tool. |
90
+ | `REGNA_TASK_TIMEOUT_MS` | Per-subagent time limit (default 300000, clamped 30s to 30m). |
91
+ | `REGNA_TASK_MAX_CONCURRENCY` | Concurrent subagent cap (default 4, clamped 1 to 8). |
92
+
93
+ ## Project configuration (`.regna/`)
94
+
95
+ Project-level settings, skills, and prompt templates live in a `.regna/` directory at the
96
+ project root (loaded after the one-time project trust prompt):
97
+
98
+ - `.regna/settings.json` — project settings
99
+ - `.regna/skills/<name>/SKILL.md` — project skills ([Agent Skills](https://agentskills.io) format; `.agents/skills/` is also read)
100
+ - `.regna/prompts/*.md` — prompt templates (`/name` from inside a session)
101
+
102
+ Global state stays under `~/.regna/`.
103
+
78
104
  ## MCP servers
79
105
 
80
106
  Regna Code connects to [Model Context Protocol](https://modelcontextprotocol.io) servers and exposes their tools to the agent, named `mcp__<server>__<tool>`. This gives you the whole MCP ecosystem (filesystem, GitHub, databases, browsers, and more) on top of the built-in `read`/`write`/`edit`/`bash`/`grep`/`find`/`ls` tools.
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import{spawn as I}from"node:child_process";import{fileURLToPath as M}from"node:url";import{dirname as v,join as a}from"node:path";import{existsSync as m,readFileSync as b,writeFileSync as j,mkdirSync as P,unlinkSync as B,chmodSync as K}from"node:fs";import{homedir as Y}from"node:os";import{createInterface as q}from"node:readline";var z=v(M(import.meta.url)),g=v(z),A=a(g,"extensions"),$=a(g,"themes","regna.json"),R=a(g,"APPEND_SYSTEM.md"),k="https://regnax.ai/v1",H="regna/regna-1",N=a(Y(),".regna"),E=a(N,"auth.json"),O=a(N,"engine"),u=process.argv.slice(2),h=(...e)=>u.some(t=>e.some(n=>!!(t===n||t.startsWith(`${n}=`)||/^-[a-z]$/i.test(n)&&t.startsWith(n)&&t.length>n.length)));function _(){for(let e of[a(g,"package.json"),a(g,"..","package.json")])try{let t=JSON.parse(b(e,"utf8")).version;if(t)return`v${t}`}catch{}return""}var J=`Regna Code ${_()} - a terminal coding agent on Regna
2
+ import{spawn as I}from"node:child_process";import{fileURLToPath as M}from"node:url";import{dirname as v,join as a}from"node:path";import{existsSync as m,readFileSync as b,writeFileSync as j,mkdirSync as k,unlinkSync as B,chmodSync as K}from"node:fs";import{homedir as Y}from"node:os";import{createInterface as q}from"node:readline";var z=v(M(import.meta.url)),g=v(z),A=a(g,"extensions"),$=a(g,"themes","regna.json"),R=a(g,"APPEND_SYSTEM.md"),P="https://regnax.ai/v1",H="regna/regna-1",N=a(Y(),".regna"),E=a(N,"auth.json"),O=a(N,"engine"),u=process.argv.slice(2),h=(...e)=>u.some(t=>e.some(n=>!!(t===n||t.startsWith(`${n}=`)||/^-[a-z]$/i.test(n)&&t.startsWith(n)&&t.length>n.length)));function _(){for(let e of[a(g,"package.json"),a(g,"..","package.json")])try{let t=JSON.parse(b(e,"utf8")).version;if(t)return`v${t}`}catch{}return""}var J=`Regna Code ${_()} - a terminal coding agent on Regna
3
3
 
4
4
  Usage:
5
5
  regna [message...] start interactive, optionally with a first message
@@ -25,7 +25,7 @@ Environment:
25
25
  REGNA_POLICY network egress guard: off | warn | enforce
26
26
 
27
27
  Docs: https://github.com/HyperEZ/regna-code
28
- `;function V(){try{let e=JSON.parse(b(E,"utf8"));return e&&typeof e.apiKey=="string"?e:null}catch{return null}}function W(e){P(N,{recursive:!0}),j(E,`${JSON.stringify(e,null,2)}
28
+ `;function V(){try{let e=JSON.parse(b(E,"utf8"));return e&&typeof e.apiKey=="string"?e:null}catch{return null}}function W(e){k(N,{recursive:!0}),j(E,`${JSON.stringify(e,null,2)}
29
29
  `);try{K(E,384)}catch{}}function Z(){try{return B(E),!0}catch{return!1}}function Q(e){try{return`${new URL(e).origin}/console`}catch{return"https://regnax.ai/console"}}function X(e){try{let[t,n]=process.platform==="darwin"?["open",[e]]:process.platform==="win32"?["cmd",["/c","start","",e]]:["xdg-open",[e]];I(t,n,{stdio:"ignore",detached:!0}).unref()}catch{}}async function S(e,t){try{let n=new AbortController,r=setTimeout(()=>n.abort(),8e3),s=await fetch(`${e.replace(/\/+$/,"")}/models`,{headers:{Authorization:`Bearer ${t}`},signal:n.signal});if(clearTimeout(r),s.status===401||s.status===403)return{status:"invalid",ids:[]};if(!s.ok)return{status:"unknown",ids:[]};let o=await s.json().catch(()=>({}));return{status:"ok",ids:Array.isArray(o?.data)?o.data.map(d=>d&&typeof d.id=="string"?d.id:"").filter(Boolean):[]}}catch{return{status:"unknown",ids:[]}}}function ee(e){let t=(e||"").trim();if(!t)return"";/^https?:\/\//i.test(t)||(t=`http://${t}`);try{let n=new URL(t),r=`${n.origin}${n.pathname}`.replace(/\/+$/,"");return/\/v\d+$/.test(r)||(r=`${r}/v1`),r}catch{return""}}function te(){let e=q({input:process.stdin}),t=[],n=[],r=!1;return e.on("line",o=>{n.length?n.shift()(o):t.push(o)}),e.on("close",()=>{for(r=!0;n.length;)n.shift()(null)}),{ask:o=>(process.stdout.write(o),new Promise(i=>{t.length?i(t.shift()):r?i(null):n.push(i)})),close:()=>e.close()}}async function ne(e){return process.stdout.write(`
30
30
  Regna Code ${_()}
31
31
  Choose how to connect:
@@ -33,7 +33,7 @@ Docs: https://github.com/HyperEZ/regna-code
33
33
  1) Online - Regna cloud (regnax.ai)
34
34
  2) Offline - air-gapped / self-hosted gateway
35
35
 
36
- `),(await e(" Select [1]: ")||"").trim()==="2"?"offline":"online"}async function se(e){let t=k,n=Q(t);process.stdout.write(`
36
+ `),(await e(" Select [1]: ")||"").trim()==="2"?"offline":"online"}async function se(e){let t=P,n=Q(t);process.stdout.write(`
37
37
  Online mode (Regna cloud).
38
38
  1) Get an API key at ${n}
39
39
  2) Paste it below.
@@ -58,9 +58,9 @@ Docs: https://github.com/HyperEZ/regna-code
58
58
  `),process.exit(0));if(u[0]==="login"){let e=u[1]==="online"||u[1]==="offline"?u[1]:void 0;await G(e),process.exit(0)}u[0]==="logout"&&(process.stdout.write(Z()?`Logged out.
59
59
  `:`Not logged in.
60
60
  `),process.exit(0));var l=null,f=(process.env.REGNA_API_KEY||"").trim();f?l={mode:process.env.REGNA_OFFLINE==="1"?"offline":"online",apiKey:f}:(l=V(),l?.apiKey?f=l.apiKey.trim():process.stdin.isTTY&&process.stdout.isTTY?(l=await G(),f=l.apiKey.trim()):(process.stderr.write(`[regna] Not logged in. Run: regna login
61
- `),process.exit(1)));async function oe(e,t){try{let n=new AbortController,r=setTimeout(()=>n.abort(),4e3),s;try{s=await fetch(`${e.replace(/\/+$/,"")}/models`,{headers:{Authorization:`Bearer ${t}`},signal:n.signal})}finally{clearTimeout(r)}if(!s.ok)return null;let o=await s.json(),d=(Array.isArray(o?.data)?o.data:[]).map(c=>c&&typeof c.id=="string"?c.id:"").filter(c=>/^regna-\d+$/.test(c)).sort();return d.length>0?`regna/${d[0]}`:null}catch{return null}}var L=process.env.REGNA_OFFLINE==="1"||l?.mode==="offline",C=(process.env.REGNA_BASE_URL||"").trim()||l?.baseUrl||k,w=(process.env.REGNA_MODEL||"").trim();w||(L?w=l?.model||"regna/default":w=await oe(C,f)||l?.model||H);process.env.REGNA_API_KEY=f;process.env.REGNA_BASE_URL=C;L&&(process.env.REGNA_OFFLINE||(process.env.REGNA_OFFLINE="1"),process.env.REGNA_POLICY||(process.env.REGNA_POLICY="enforce"));var p=[],ie=process.env.REGNA_DISCOVER==="1";if(!ie){p.push("--no-extensions");let e=["provider","policy","branding","context","exit","docs-search","docs-analysis","mcp"],t=s=>{let o=a(A,`${s}.js`);if(m(o))return o;let i=a(A,`${s}.ts`);return m(i)?i:null},n=e.map(s=>[s,t(s)]),r=n.filter(([,s])=>!s).map(([s])=>s);r.length>0&&(process.stderr.write(`[regna] Missing required extensions: ${r.join(", ")} (in ${A}). Install is corrupted. Aborting.
61
+ `),process.exit(1)));async function oe(e,t){try{let n=new AbortController,r=setTimeout(()=>n.abort(),4e3),s;try{s=await fetch(`${e.replace(/\/+$/,"")}/models`,{headers:{Authorization:`Bearer ${t}`},signal:n.signal})}finally{clearTimeout(r)}if(!s.ok)return null;let o=await s.json(),d=(Array.isArray(o?.data)?o.data:[]).map(c=>c&&typeof c.id=="string"?c.id:"").filter(c=>/^regna-\d+$/.test(c)).sort();return d.length>0?`regna/${d[0]}`:null}catch{return null}}var L=process.env.REGNA_OFFLINE==="1"||l?.mode==="offline",C=(process.env.REGNA_BASE_URL||"").trim()||l?.baseUrl||P,w=(process.env.REGNA_MODEL||"").trim();w||(L?w=l?.model||"regna/default":w=await oe(C,f)||l?.model||H);process.env.REGNA_API_KEY=f;process.env.REGNA_BASE_URL=C;L&&(process.env.REGNA_OFFLINE||(process.env.REGNA_OFFLINE="1"),process.env.REGNA_POLICY||(process.env.REGNA_POLICY="enforce"));var p=[],ie=process.env.REGNA_DISCOVER==="1";if(!ie){p.push("--no-extensions");let e=["provider","policy","branding","context","exit","docs-search","docs-analysis","mcp","task"],t=s=>{let o=a(A,`${s}.js`);if(m(o))return o;let i=a(A,`${s}.ts`);return m(i)?i:null},n=e.map(s=>[s,t(s)]),r=n.filter(([,s])=>!s).map(([s])=>s);r.length>0&&(process.stderr.write(`[regna] Missing required extensions: ${r.join(", ")} (in ${A}). Install is corrupted. Aborting.
62
62
  `),process.exit(1));for(let[,s]of n)p.push("-e",s)}!h("--theme")&&m($)&&p.push("--theme",$);h("--system-prompt")||(m(R)||(process.stderr.write(`[regna] Missing required prompt: APPEND_SYSTEM.md (${R}). Install is corrupted. Aborting.
63
63
  (To set the prompt yourself on purpose, run with --system-prompt.)
64
- `),process.exit(1)),p.push("--append-system-prompt",`@${R}`));h("--model","-m")||p.push("--model",w);p.push(...u);try{P(O,{recursive:!0})}catch{}var x={...process.env,PI_CODING_AGENT_DIR:O};process.env.REGNA_OFFLINE==="1"&&(x.PI_OFFLINE="1");x.PI_SKIP_VERSION_CHECK="1";function ae(){let e=a("node_modules","@earendil-works","pi-coding-agent","dist","cli.js"),t=g;for(let n=0;n<10;n++){let r=a(t,e);if(m(r))return r;let s=v(t);if(s===t)break;t=s}return null}function ce(){let e=process.env.REGNA_ENGINE;if(e)return{cmd:e,prefix:[],label:e};let t=ae();return t?{cmd:process.execPath,prefix:[t],label:t}:{cmd:"pi",prefix:[],label:"runtime (PATH)"}}var{cmd:le,prefix:de,label:ue}=ce(),T=I(le,[...de,...p],{stdio:"inherit",env:x});T.on("error",e=>{e&&e.code==="ENOENT"&&(process.stderr.write(`[regna] Runtime executable not found (${ue}). Reinstall (npm i -g @hyperez/regna-code) or set REGNA_ENGINE.
64
+ `),process.exit(1)),p.push("--append-system-prompt",`@${R}`));h("--model","-m")||p.push("--model",w);p.push(...u);try{k(O,{recursive:!0})}catch{}var x={...process.env,PI_CODING_AGENT_DIR:O};process.env.REGNA_OFFLINE==="1"&&(x.PI_OFFLINE="1");x.PI_SKIP_VERSION_CHECK="1";function ae(){let e=a("node_modules","@earendil-works","pi-coding-agent","dist","cli.js"),t=g;for(let n=0;n<10;n++){let r=a(t,e);if(m(r))return r;let s=v(t);if(s===t)break;t=s}return null}function ce(){let e=process.env.REGNA_ENGINE;if(e)return{cmd:e,prefix:[],label:e};let t=ae();return t?{cmd:process.execPath,prefix:[t],label:t}:{cmd:"pi",prefix:[],label:"runtime (PATH)"}}var{cmd:le,prefix:de,label:ue}=ce(),T=I(le,[...de,...p],{stdio:"inherit",env:x});T.on("error",e=>{e&&e.code==="ENOENT"&&(process.stderr.write(`[regna] Runtime executable not found (${ue}). Reinstall (npm i -g @hyperez/regna-code) or set REGNA_ENGINE.
65
65
  `),process.exit(127)),process.stderr.write(`[regna] Failed to start the runtime: ${e?.message??String(e)}
66
66
  `),process.exit(1)});T.on("exit",(e,t)=>{if(t){process.kill(process.pid,t);return}process.exit(e??0)});
@@ -1 +1 @@
1
- var E="regna",_="https://regnax.ai/v1";var p=/^regna-\d+$/,A=["regna-1"],R={"regna-1":"Regna 1"},m={"regna-1":1e6},h={"regna-1":32768},v=1e6,x=32768;function M(o){let s=/^regna-(\d+)$/.exec(o.toLowerCase());return s?`Regna ${s[1]}`:`Regna \xB7 ${o}`}var T=512*1024,I=24,L=200;function P(){let o=(process.env.REGNA_BASE_URL??"").trim(),s=o===""?_:o,n;try{n=new URL(s)}catch{return _}if(n.protocol!=="http:"&&n.protocol!=="https:")return _;let c=`${n.origin}${n.pathname}`.replace(/\/+$/,"");return/\/v\d+$/.test(c)?c:`${c}/v1`}function S(o){try{return/(^|\.)regnax\.ai$/i.test(new URL(o).hostname)}catch{return!1}}function N(o){let s=o.id,n=s.toLowerCase(),c=n==="default"||n==="current"||n==="auto",a=p.test(n),u=/qwq|qwen3|think|reason/.test(n),t=parseInt((process.env.REGNA_CONTEXT_WINDOW??"").trim(),10),d=typeof o.contextWindow=="number"&&o.contextWindow>0?o.contextWindow:void 0,g=Number.isFinite(t)&&t>0?t:d??m[n]??(a?v:32768),l=h[n]??(a?x:8192);return{id:s,name:R[n]??(a?M(s):c?"Regna (active model)":`Regna \xB7 ${s}`),reasoning:u,input:["text"],cost:{input:0,output:0,cacheRead:0,cacheWrite:0},contextWindow:g,maxTokens:l}}async function y(o,s){let n=new AbortController,c=setTimeout(()=>n.abort(),4e3);try{let a=await fetch(`${o}/models`,{headers:{Authorization:`Bearer ${s}`},signal:n.signal});if(!a.ok)return[];let u=await a.text();if(u.length>T)return[];let t;try{t=JSON.parse(u)}catch{return[]}let d=Array.isArray(t.data)?t.data:[],g=new Set,l=[];for(let i of d){let r=i&&typeof i.id=="string"?i.id:"";if(r.length===0||r.length>L||g.has(r))continue;g.add(r);let w=i&&typeof i.context_window=="number"&&i.context_window>0?i.context_window:void 0;if(l.push({id:r,contextWindow:w}),l.length>=I)break}return l}catch{return[]}finally{clearTimeout(c)}}async function O(o){let s=P(),n=(process.env.REGNA_API_KEY??"").trim(),c=(process.env.REGNA_EXPOSE_ALIASES??"").trim()==="1",a=n?await y(s,n):[],u=new Map(a.map(e=>[e.id,e.contextWindow])),t=a.map(e=>e.id),d=new Set;(e=>{let f=(e??"").trim();f&&d.add(f.startsWith(`${E}/`)?f.slice(E.length+1):f)})(process.env.REGNA_MODEL),c||(t=t.filter(e=>e==="default"||!e.includes("/")||d.has(e)));let l=S(s),i=t.filter(e=>p.test(e)).sort(),r;if(l){r=i.length>0?i.slice():[...A];for(let e of d)t.includes(e)&&!r.includes(e)&&r.push(e)}else if(i.length>0){r=i.slice();for(let e of d)t.includes(e)&&!r.includes(e)&&r.push(e)}else t.includes("default")||t.unshift("default"),r=t;!t.some(e=>e!=="default")&&!l&&console.warn(`[regna] Model discovery failed or REGNA_API_KEY is unset. Set REGNA_API_KEY and run /reload. (base=${s})`),o.registerProvider(E,{name:"Regna",baseUrl:s,apiKey:"$REGNA_API_KEY",api:"openai-completions",models:r.map(e=>N({id:e,contextWindow:u.get(e)}))})}export{O as default};
1
+ var E="regna",w="https://regnax.ai/v1";var p=/^regna-\d+$/,A=["regna-1"],R={"regna-1":"Regna 1"},h={"regna-1":1e6},m={"regna-1":32768},v=1e6,S=32768;function x(o){let n=/^regna-(\d+)$/.exec(o.toLowerCase());return n?`Regna ${n[1]}`:`Regna \xB7 ${o}`}var M=512*1024,T=24,I=200;function L(){let o=(process.env.REGNA_BASE_URL??"").trim(),n=o===""?w:o,t;try{t=new URL(n)}catch{return w}if(t.protocol!=="http:"&&t.protocol!=="https:")return w;let c=`${t.origin}${t.pathname}`.replace(/\/+$/,"");return/\/v\d+$/.test(c)?c:`${c}/v1`}function N(o){try{return/(^|\.)regnax\.ai$/i.test(new URL(o).hostname)}catch{return!1}}function P(o){let n=(process.env.REGNA_WEB_SEARCH??"").trim().toLowerCase();return n==="0"||n==="false"||n==="off"?!1:n==="1"||n==="true"||n==="on"?!0:o}function b(o){let n=o.id,t=n.toLowerCase(),c=t==="default"||t==="current"||t==="auto",a=p.test(t),u=/qwq|qwen3|think|reason/.test(t),r=parseInt((process.env.REGNA_CONTEXT_WINDOW??"").trim(),10),l=typeof o.contextWindow=="number"&&o.contextWindow>0?o.contextWindow:void 0,f=Number.isFinite(r)&&r>0?r:l??h[t]??(a?v:32768),d=m[t]??(a?S:8192);return{id:n,name:R[t]??(a?x(n):c?"Regna (active model)":`Regna \xB7 ${n}`),reasoning:u,input:["text"],cost:{input:0,output:0,cacheRead:0,cacheWrite:0},contextWindow:f,maxTokens:d}}async function y(o,n){let t=new AbortController,c=setTimeout(()=>t.abort(),4e3);try{let a=await fetch(`${o}/models`,{headers:{Authorization:`Bearer ${n}`},signal:t.signal});if(!a.ok)return[];let u=await a.text();if(u.length>M)return[];let r;try{r=JSON.parse(u)}catch{return[]}let l=Array.isArray(r.data)?r.data:[],f=new Set,d=[];for(let i of l){let s=i&&typeof i.id=="string"?i.id:"";if(s.length===0||s.length>I||f.has(s))continue;f.add(s);let _=i&&typeof i.context_window=="number"&&i.context_window>0?i.context_window:void 0;if(d.push({id:s,contextWindow:_}),d.length>=T)break}return d}catch{return[]}finally{clearTimeout(c)}}async function C(o){let n=L(),t=(process.env.REGNA_API_KEY??"").trim(),c=(process.env.REGNA_EXPOSE_ALIASES??"").trim()==="1",a=t?await y(n,t):[],u=new Map(a.map(e=>[e.id,e.contextWindow])),r=a.map(e=>e.id),l=new Set;(e=>{let g=(e??"").trim();g&&l.add(g.startsWith(`${E}/`)?g.slice(E.length+1):g)})(process.env.REGNA_MODEL),c||(r=r.filter(e=>e==="default"||!e.includes("/")||l.has(e)));let d=N(n),i=r.filter(e=>p.test(e)).sort(),s;if(d){s=i.length>0?i.slice():[...A];for(let e of l)r.includes(e)&&!s.includes(e)&&s.push(e)}else if(i.length>0){s=i.slice();for(let e of l)r.includes(e)&&!s.includes(e)&&s.push(e)}else r.includes("default")||r.unshift("default"),s=r;!r.some(e=>e!=="default")&&!d&&console.warn(`[regna] Model discovery failed or REGNA_API_KEY is unset. Set REGNA_API_KEY and run /reload. (base=${n})`),o.registerProvider(E,{name:"Regna",baseUrl:n,apiKey:"$REGNA_API_KEY",api:"openai-completions",...P(d)?{headers:{"X-Regna-Web-Search":"on"}}:{},models:s.map(e=>b({id:e,contextWindow:u.get(e)}))})}export{C as default};
@@ -0,0 +1,4 @@
1
+ import{spawn as y}from"node:child_process";import{existsSync as C}from"node:fs";import{dirname as R,join as N}from"node:path";import{fileURLToPath as I}from"node:url";import{Type as l}from"typebox";var h=100*1024,v=32*1024,P=3e5,L=3e4,U=18e5,O=4,G=5e3;function x(e){let t=Number.parseInt((e??"").trim(),10);return Number.isFinite(t)&&t>0?t:0}function K(e){let t=Number.parseInt((e??"").trim(),10);return!Number.isFinite(t)||t<=0?P:Math.min(U,Math.max(L,t))}function $(e){let t=Number.parseInt((e??"").trim(),10);return!Number.isFinite(t)||t<=0?O:Math.min(8,Math.max(1,t))}function c(e,t){return e.length<=t?e:`[... first ${e.length-t} chars truncated ...]
2
+ ${e.slice(e.length-t)}`}function F(){let e=R(I(import.meta.url)),t=N(R(e),"bin","regna.mjs");return C(t)?t:null}function m(e,t){return{content:[{type:"text",text:e}],details:t}}function J(e){if((process.env.REGNA_TASK_DISABLED??"").trim()==="1"||x(process.env.REGNA_TASK_DEPTH)>=1)return;let t=F();if(!t)return;let p=0;e.registerTool({name:"regna_task",label:"Subagent task",description:"Delegate a self-contained subtask to a separate Regna agent and get its final report. The subagent starts with a fresh context (it does not see this conversation), works in the same directory with the same tools, and cannot spawn further subagents. Include every fact it needs in the prompt. Call regna_task multiple times in ONE message to run subtasks in parallel (e.g. investigating independent modules, running broad searches). Prefer doing quick single-file work yourself.",promptSnippet:"regna_task: delegate a subtask to a parallel subagent with fresh context",parameters:l.Object({prompt:l.String({description:"complete, self-contained task description for the subagent",maxLength:v}),name:l.Optional(l.String({description:"short label for logs (default: task)",maxLength:64}))}),async execute(H,i,d,X,j){let a=(i.name??"task").trim()||"task",g=Date.now(),o=f=>m(f,{name:a,exitCode:null,durationMs:Date.now()-g});if(typeof i.prompt!="string"||i.prompt.trim()==="")return o("Subagent failed: empty prompt.");if(d?.aborted)return o("Subagent was cancelled.");let A=$(process.env.REGNA_TASK_MAX_CONCURRENCY);if(p>=A)return o(`Subagent limit reached (${A} running). Wait for current subagents to finish, then launch the rest.`);p+=1;try{return await new Promise(f=>{let r=y(process.execPath,[t,"-p","--no-session",i.prompt],{cwd:process.cwd(),env:{...process.env,REGNA_TASK_DEPTH:String(x(process.env.REGNA_TASK_DEPTH)+1)},stdio:["ignore","pipe","pipe"]}),u="",T="",S=!1,_=null,s=n=>{S||(S=!0,_&&clearTimeout(_),clearTimeout(w),d?.removeEventListener("abort",E),f(n))},k=()=>{r.kill("SIGTERM"),_=setTimeout(()=>r.kill("SIGKILL"),G)},E=()=>{k(),s(o("Subagent was cancelled."))},w=setTimeout(()=>{k(),s(m(`Subagent timed out. Partial output:
3
+ ${c(u,h)||"(none)"}`,{name:a,exitCode:null,durationMs:Date.now()-g}))},K(process.env.REGNA_TASK_TIMEOUT_MS));d?.addEventListener("abort",E),r.stdout.on("data",n=>{u=c(u+n.toString("utf8"),h*2)}),r.stderr.on("data",n=>{T=c(T+n.toString("utf8"),4*1024)}),r.on("error",n=>s(o(`Subagent failed to start: ${n.message}`))),r.on("close",n=>{let M=Date.now()-g,b=c(u.trim(),h);if(n===0&&b!=="")return s(m(b,{name:a,exitCode:n,durationMs:M}));let D=b||T.trim()||"(no output)";s(m(`Subagent exited with code ${n??"unknown"}:
4
+ ${D}`,{name:a,exitCode:n,durationMs:M}))})})}finally{p-=1}}})}export{c as capTail,J as default,$ as normalizeTaskConcurrency,K as normalizeTaskTimeout,x as parseTaskDepth};
@@ -136,6 +136,24 @@ patchEngineFile(
136
136
  "",
137
137
  );
138
138
 
139
+ // 7) Project config dir: ".pi" -> ".regna". CONFIG_DIR_NAME (dist/config.js) reads the engine
140
+ // package.json's piConfig.configDir, and every project-level path (settings, skills, prompts,
141
+ // extensions, packages, project-trust wording) derives from it. Without this, users are told
142
+ // to create `.pi/` directories, leaking the hidden engine. Global state is unaffected
143
+ // (the launcher pins PI_CODING_AGENT_DIR to ~/.regna/engine).
144
+ try {
145
+ const pjPath = findEngineFile("package.json");
146
+ if (pjPath) {
147
+ const pj = JSON.parse(readFileSync(pjPath, "utf8"));
148
+ if (pj?.piConfig && pj.piConfig.configDir !== ".regna") {
149
+ pj.piConfig.configDir = ".regna";
150
+ writeFileSync(pjPath, `${JSON.stringify(pj, null, 2)}\n`);
151
+ }
152
+ }
153
+ } catch {
154
+ /* best effort; never fail the install */
155
+ }
156
+
139
157
  // The engine version these patches are written against. The package pins this exact version,
140
158
  // so a mismatch means something forced a different engine in. We verify and warn rather than
141
159
  // fail silently: if the engine's compiled shape changed, the patches above become no-ops.
@@ -152,6 +170,7 @@ try {
152
170
  { file: IM, label: "Themes section hidden", absent: /addLoadedSection\("Themes"/ },
153
171
  { file: join("dist", "core", "system-prompt.js"), label: "system-prompt de-branded", absent: /operating inside pi,/ },
154
172
  { file: join("dist", "core", "system-prompt.js"), label: "pi docs block removed", absent: /Pi documentation \(read only/ },
173
+ { file: "package.json", label: "project config dir .regna", want: /"configDir":\s*"\.regna"/ },
155
174
  ];
156
175
  const failed = [];
157
176
  for (const c of checks) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyperez/regna-code",
3
- "version": "0.2.6",
3
+ "version": "0.4.0",
4
4
  "description": "Regna Code. A terminal coding agent on Regna. Install with `npm i -g @hyperez/regna-code` and run `regna`. Works with the Regna cloud API and on-premise deployments.",
5
5
  "license": "PolyForm-Noncommercial-1.0.0",
6
6
  "private": false,