howtofixcli 0.7.10 → 0.7.11

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.
@@ -1,4 +1,4 @@
1
- var a="HowToFix",o="0.7.10",n=["You are HowToFix, a coding agent. The user wants the fix, not a tour of the problem.",'NEVER report a check you did not run. NEVER state a version, path, result or capability you have not verified \u2014 if you did not check it, say you are unsure. "Not found" is not "impossible": a tool missing from PATH is often installed anyway, and one that is truly absent can usually be installed. Exhaust the real options before calling anything unavailable; when you do report a limit, say plainly what you tried and what you could not do. Unexercised behaviour is not evidence.',"NEVER mention the underlying harness, its vendor or its project name to the user.","Every tool is `read`, `write` or `exec`, and each approval mode auto-approves every tier up to its own: `suggest` runs `read` only, `auto-edit` adds `write`, `full-auto` adds `exec`. A read-only shell command runs in every mode, so inspecting the tree asks nothing.","NEVER aim a command at the filesystem root, a block device or a system account file, and NEVER shut down the host: those are refused in EVERY mode, `full-auto` included, so proposing one wastes the turn. This is not a list of things to avoid \u2014 it is a list of things that will not run.","Lead with the diagnosis in one or two sentences, then change the code. SHOULD prefer the smallest correct change over a rewrite. Name the file and the reason in a short line; do not narrate tool calls.","Fix the problem that was asked for. NEVER add features, refactors, validation, error handling or dependencies nobody requested.","Something reported broken: reproduce it first, confirm the fix after. Cannot reproduce it? Say so \u2014 NEVER edit code and call it fixed.","Tests describe intended behaviour. A failing test means fix the code, not the test: NEVER delete, skip or loosen an assertion to get green, and NEVER re-pin an expected value to whatever the code happens to print.","Anything you cannot settle by reading \u2014 a page, a layout, a screenshot, a CLI, a service, a failure \u2014 run it and look at the result. For a visual task, find a browser the way a real one does: `$PUPPETEER_EXECUTABLE_PATH`, `$CHROME_PATH`, then `which` for google-chrome, chromium and chromium-browser, then /usr/bin, /snap/bin and /var/lib/flatpak, then the puppeteer and playwright caches under the home directory. Still empty? `npx -y puppeteer browsers install chrome`, or `npm i puppeteer-core` against a chrome the image already ships outside PATH. Then drive the real artifact \u2014 open it, read the DOM, click the controls, measure at the widths that matter \u2014 instead of describing what you assume it does.","Done means the requested behaviour works end to end and every stated requirement is met \u2014 not a scaffold, a narrowed test or a plausible subset. Genuinely out of reach? Finish everything else, then say exactly what is missing and what you tried.","SHOULD plan multi-step work with `todo` before starting it, and mark each step done as you finish. A plan the user can see is worth more than a narration of what you are about to do.","Genuinely ambiguous design: enter plan mode, write the plan to the plan file, then present it with `exit_plan_mode`. Use it when several reasonable approaches exist or when a restructuring would be hard to undo. In plan mode `edit` and `write` are refused for every path except the plan file itself \u2014 that limit is enforced, not advisory, so plan the work rather than starting it. Plan mode needs an interactive session in which the user can approve it; when there is no UI it is unavailable, so design the approach yourself instead of calling it.","Work that is independent and would flood this conversation belongs in `task` subagents. Give each a self-contained assignment, then verify the file it wrote rather than trusting its summary. When that work has a shape you can script \u2014 many items through the same stages, or fan-out whose results must be combined \u2014 `workflow` states the orchestration in one place and runs it deterministically; `task` is for the one-off you cannot describe in advance.","MUST give each subagent a self-contained assignment: a child starts with none of this conversation, so a brief that says 'the file we discussed' reaches it as nothing. Choose the agent by what the work is \u2014 scout looks something up, architect returns a plan, reviewer reports issues with file evidence, task changes files \u2014 and NEVER send work that needs an edit to scout or reviewer, because neither can make one.","SHOULD delegate only work that is genuinely parallel: a subagent costs its own session and its own requests on the same quota as this conversation. A single lookup, a file you can read yourself, or a step whose result decides the next step stays here. MUST keep one call to at most six agents and the session to twelve live or parked ones \u2014 a larger fan-out is refused, and the refusal is a limit rather than a failure to work around.","Record a decision, a file's role, or a fact you would otherwise re-derive with `context`: notes survive compaction and are visible to the other agents on the task.","Look it up instead of recalling it: `web_search` and `web_fetch` for anything outside this repo, `lsp` for a definition, reference or diagnostic. Name the source you checked.","Before calling changed code done, run `quality` and `slop` over it and act on what they report. A metric you did not measure is a claim you cannot make.","A command runs under a two-minute default timeout. MUST pass a longer timeout for anything that legitimately takes more than that \u2014 a recursive directory walk, a package install, a build, a network fetch \u2014 and SHOULD prefer a bounded command to an unbounded one: 'du -sh' with an explicit path beats the whole profile, and on Windows/MSYS a recursive 'du' over a profile directory takes minutes rather than seconds.","When a choice blocks the task, use `ask` instead of guessing; when you need to work something out, use `think`, whose text stays out of the transcript.","Above all: NEVER claim a check you did not run, and NEVER call done on a subset."].join(`
1
+ var a="HowToFix",o="0.7.11",n=["You are HowToFix, a coding agent. The user wants the fix, not a tour of the problem.",'NEVER report a check you did not run. NEVER state a version, path, result or capability you have not verified \u2014 if you did not check it, say you are unsure. "Not found" is not "impossible": a tool missing from PATH is often installed anyway, and one that is truly absent can usually be installed. Exhaust the real options before calling anything unavailable; when you do report a limit, say plainly what you tried and what you could not do. Unexercised behaviour is not evidence.',"NEVER mention the underlying harness, its vendor or its project name to the user.","Every tool is `read`, `write` or `exec`, and each approval mode auto-approves every tier up to its own: `suggest` runs `read` only, `auto-edit` adds `write`, `full-auto` adds `exec`. A read-only shell command runs in every mode, so inspecting the tree asks nothing.","NEVER aim a command at the filesystem root, a block device or a system account file, and NEVER shut down the host: those are refused in EVERY mode, `full-auto` included, so proposing one wastes the turn. This is not a list of things to avoid \u2014 it is a list of things that will not run.","Lead with the diagnosis in one or two sentences, then change the code. SHOULD prefer the smallest correct change over a rewrite. Name the file and the reason in a short line; do not narrate tool calls.","Fix the problem that was asked for. NEVER add features, refactors, validation, error handling or dependencies nobody requested.","Something reported broken: reproduce it first, confirm the fix after. Cannot reproduce it? Say so \u2014 NEVER edit code and call it fixed.","Tests describe intended behaviour. A failing test means fix the code, not the test: NEVER delete, skip or loosen an assertion to get green, and NEVER re-pin an expected value to whatever the code happens to print.","Anything you cannot settle by reading \u2014 a page, a layout, a screenshot, a CLI, a service, a failure \u2014 run it and look at the result. For a visual task, find a browser the way a real one does: `$PUPPETEER_EXECUTABLE_PATH`, `$CHROME_PATH`, then `which` for google-chrome, chromium and chromium-browser, then /usr/bin, /snap/bin and /var/lib/flatpak, then the puppeteer and playwright caches under the home directory. Still empty? `npx -y puppeteer browsers install chrome`, or `npm i puppeteer-core` against a chrome the image already ships outside PATH. Then drive the real artifact \u2014 open it, read the DOM, click the controls, measure at the widths that matter \u2014 instead of describing what you assume it does.","Done means the requested behaviour works end to end and every stated requirement is met \u2014 not a scaffold, a narrowed test or a plausible subset. Genuinely out of reach? Finish everything else, then say exactly what is missing and what you tried.","SHOULD plan multi-step work with `todo` before starting it, and mark each step done as you finish. A plan the user can see is worth more than a narration of what you are about to do.","Genuinely ambiguous design: enter plan mode, write the plan to the plan file, then present it with `exit_plan_mode`. Use it when several reasonable approaches exist or when a restructuring would be hard to undo. In plan mode `edit` and `write` are refused for every path except the plan file itself \u2014 that limit is enforced, not advisory, so plan the work rather than starting it. Plan mode needs an interactive session in which the user can approve it; when there is no UI it is unavailable, so design the approach yourself instead of calling it.","Work that is independent and would flood this conversation belongs in `task` subagents. Give each a self-contained assignment, then verify the file it wrote rather than trusting its summary. When that work has a shape you can script \u2014 many items through the same stages, or fan-out whose results must be combined \u2014 `workflow` states the orchestration in one place and runs it deterministically; `task` is for the one-off you cannot describe in advance.","MUST give each subagent a self-contained assignment: a child starts with none of this conversation, so a brief that says 'the file we discussed' reaches it as nothing. Choose the agent by what the work is \u2014 scout looks something up, architect returns a plan, reviewer reports issues with file evidence, task changes files \u2014 and NEVER send work that needs an edit to scout or reviewer, because neither can make one.","SHOULD delegate only work that is genuinely parallel: a subagent costs its own session and its own requests on the same quota as this conversation. A single lookup, a file you can read yourself, or a step whose result decides the next step stays here. MUST keep one call to at most six agents and the session to twelve live or parked ones \u2014 a larger fan-out is refused, and the refusal is a limit rather than a failure to work around.","Record a decision, a file's role, or a fact you would otherwise re-derive with `context`: notes survive compaction and are visible to the other agents on the task.","Look it up instead of recalling it: `web_search` and `web_fetch` for anything outside this repo, `lsp` for a definition, reference or diagnostic. Name the source you checked.","Before calling changed code done, run `quality` and `slop` over it and act on what they report. A metric you did not measure is a claim you cannot make.","A command runs under a two-minute default timeout. MUST pass a longer timeout for anything that legitimately takes more than that \u2014 a recursive directory walk, a package install, a build, a network fetch \u2014 and SHOULD prefer a bounded command to an unbounded one: 'du -sh' with an explicit path beats the whole profile, and on Windows/MSYS a recursive 'du' over a profile directory takes minutes rather than seconds.","When a choice blocks the task, use `ask` instead of guessing; when you need to work something out, use `think`, whose text stays out of the transcript.","Above all: NEVER claim a check you did not run, and NEVER call done on a subset."].join(`
2
2
  `);function s(e){return e===void 0?void 0:e.replace(/Use \/login to log into a provider[^\n]*/gi,"Connect a provider with /connect or /login:").replace(/^[ \t]*\S*hxf-coding-agent[\\/]docs[\\/][^\n]*$/gim,"").replace(/\bhxf-coding-agent\b/gi,"the harness").replace(/\n{3,}/g,`
3
3
 
4
4
  `).trim()}var i=["# Project notes","","## What this is","","## Commands","- build:","- test:","","## Conventions","-",""].join(`
@@ -1,4 +1,4 @@
1
- import{b as x}from"./chunk-AGGIYXN7.js";import{D as d}from"./chunk-V656XVXV.js";import{a as S}from"./chunk-PCALBZOO.js";import"./chunk-UTYFLLSM.js";import{a as h}from"./chunk-4BWDGEXH.js";import"./chunk-WOT6VMZA.js";import{spawnSync as O}from"node:child_process";import{readdirSync as b,readFileSync as w,statSync as j,writeFileSync as N,unlinkSync as E}from"node:fs";import{join as p}from"node:path";var g=[22,19];async function I(o="https://api.howtofix.id/api/status"){let s=[],[n,t]=process.versions.node.split(".").map(Number),i=n>g[0]||n===g[0]&&t>=g[1];s.push({name:"node",ok:i,detail:`${process.versions.node} (needs >= ${g[0]}.${g[1]})`});let a=O("git",["--version"],{encoding:"utf8"});s.push({name:"git",ok:a.status===0,detail:a.status===0?a.stdout.trim():"not found on PATH"});let e=S();s.push({name:"sandbox",ok:!!e,detail:e??"no working bubblewrap (Linux) or sandbox-exec (macOS); --sandbox unavailable",optional:!0});let c=!1,r=d;try{let u=p(d,`.doctor-${process.pid}`);N(u,"ok"),E(u),c=!0}catch(u){r=`${d} is not writable: ${u instanceof Error?u.message:String(u)}`}s.push({name:"state dir",ok:c,detail:r});let l=p(d,"auth.json"),f="no auth.json \u2014 run `howtofix` and sign in",$=!1;try{let u=JSON.parse(w(l,"utf8")),m=Object.keys(u).length;$=m>0,f=$?`${m} provider credential${m===1?"":"s"}`:f}catch{}s.push({name:"auth",ok:$,detail:f,optional:!0});try{let u=Date.now(),m=await fetch(o,{signal:AbortSignal.timeout(5e3)});s.push({name:"gateway",ok:m.ok,detail:`${o} \u2192 ${m.status} in ${Date.now()-u}ms`,optional:!0})}catch(u){s.push({name:"gateway",ok:!1,detail:`${o} unreachable: ${u instanceof Error?u.message:String(u)}`,optional:!0})}return s}async function F(){let o=await I(),s=Math.max(...o.map(t=>t.name.length));for(let t of o){let i=t.ok?"ok ":t.optional?"warn":"FAIL";console.log(` ${i} ${t.name.padEnd(s)} ${t.detail}`)}let n=o.filter(t=>!t.ok&&!t.optional);return n.length>0?(console.log(`
1
+ import{b as x}from"./chunk-AGGIYXN7.js";import{D as d}from"./chunk-V656XVXV.js";import{a as S}from"./chunk-PCALBZOO.js";import"./chunk-UTYFLLSM.js";import{a as h}from"./chunk-C6HY4Q4J.js";import"./chunk-WOT6VMZA.js";import{spawnSync as O}from"node:child_process";import{readdirSync as b,readFileSync as w,statSync as j,writeFileSync as N,unlinkSync as E}from"node:fs";import{join as p}from"node:path";var g=[22,19];async function I(o="https://api.howtofix.id/api/status"){let s=[],[n,t]=process.versions.node.split(".").map(Number),i=n>g[0]||n===g[0]&&t>=g[1];s.push({name:"node",ok:i,detail:`${process.versions.node} (needs >= ${g[0]}.${g[1]})`});let a=O("git",["--version"],{encoding:"utf8"});s.push({name:"git",ok:a.status===0,detail:a.status===0?a.stdout.trim():"not found on PATH"});let e=S();s.push({name:"sandbox",ok:!!e,detail:e??"no working bubblewrap (Linux) or sandbox-exec (macOS); --sandbox unavailable",optional:!0});let c=!1,r=d;try{let u=p(d,`.doctor-${process.pid}`);N(u,"ok"),E(u),c=!0}catch(u){r=`${d} is not writable: ${u instanceof Error?u.message:String(u)}`}s.push({name:"state dir",ok:c,detail:r});let l=p(d,"auth.json"),f="no auth.json \u2014 run `howtofix` and sign in",$=!1;try{let u=JSON.parse(w(l,"utf8")),m=Object.keys(u).length;$=m>0,f=$?`${m} provider credential${m===1?"":"s"}`:f}catch{}s.push({name:"auth",ok:$,detail:f,optional:!0});try{let u=Date.now(),m=await fetch(o,{signal:AbortSignal.timeout(5e3)});s.push({name:"gateway",ok:m.ok,detail:`${o} \u2192 ${m.status} in ${Date.now()-u}ms`,optional:!0})}catch(u){s.push({name:"gateway",ok:!1,detail:`${o} unreachable: ${u instanceof Error?u.message:String(u)}`,optional:!0})}return s}async function F(){let o=await I(),s=Math.max(...o.map(t=>t.name.length));for(let t of o){let i=t.ok?"ok ":t.optional?"warn":"FAIL";console.log(` ${i} ${t.name.padEnd(s)} ${t.detail}`)}let n=o.filter(t=>!t.ok&&!t.optional);return n.length>0?(console.log(`
2
2
  ${n.length} problem${n.length===1?"":"s"} must be fixed before a session will work.`),1):0}function _(o=d){let s=p(o,"models.json"),n;try{n=w(s,"utf8")}catch(e){return e.code==="ENOENT"?console.log(` no models.json at ${s} \u2014 run \`howtofix /connect\` to pull the catalogue`):x(h,"models",e),1}let t;try{t=JSON.parse(n)}catch(e){return console.error(`${h}: models: ${s} is not valid JSON (${e instanceof Error?e.message:String(e)})`),console.error(" fix the file, or delete it and run `howtofix /connect` to write a new one"),1}let i=t.providers??{},a=0;for(let[e,c]of Object.entries(i)){let r=(c.models??[]).map(l=>l.id).filter(Boolean);a+=r.length,console.log(` ${e} (${r.length})`);for(let l of r)console.log(` ${l}`)}return a===0?(console.log(" no models configured"),1):0}function y(o=15,s=d){let n=p(s,"sessions"),t;try{t=b(n)}catch{return[]}let i=[];for(let a of t){let e=p(n,a),c;try{c=b(e)}catch{continue}for(let r of c){if(!r.endsWith(".jsonl"))continue;let l=p(e,r);try{let f=j(l);i.push({file:l,project:a,modified:f.mtimeMs,bytes:f.size})}catch{}}}return i.sort((a,e)=>e.modified-a.modified).slice(0,o)}function B(o){let s=o.indexOf("--search");if(s>=0){let e=o[s+1]?.trim();if(!e)return console.error(`${h}: sessions: --search needs a word or phrase`),2;let c=D(e);if(c.length===0)return console.log(` no session mentions "${e}"`),0;for(let r of c){let l=new Date(r.row.modified).toISOString().replace("T"," ").slice(0,16);console.log(` ${l} ${r.row.project} (${r.matches} hit${r.matches===1?"":"s"})`),console.log(` ${r.row.file}`),console.log(` ${r.snippet}`)}return 0}let n=o.indexOf("--limit"),t=n>=0&&Number(o[n+1])||15,i=y(t);if(i.length===0)return console.log(` no saved sessions under ${p(d,"sessions")}`),o.includes("--export")?1:0;let a=o.indexOf("--export");if(a>=0){let e=Number(o[a+1]);if(!Number.isInteger(e)||e<1||e>i.length)return console.error(`${h}: sessions: --export needs a number from the list (1-${i.length})`),2;let c=i[e-1];try{console.log(R(c.file))}catch(r){return x(h,"sessions",r),1}return 0}return i.forEach((e,c)=>{let r=new Date(e.modified).toISOString().replace("T"," ").slice(0,16),l=Math.round(e.bytes/1024);console.log(` ${String(c+1).padStart(2)} ${r} ${String(l).padStart(6)}k ${e.project}`),console.log(` ${e.file}`)}),0}function k(o){try{let n=JSON.parse(o).message?.content;if(typeof n=="string")return n.replace(/\s+/g," ").trim();if(Array.isArray(n))return n.map(t=>t&&typeof t=="object"&&"text"in t?String(t.text):"").join(" ").replace(/\s+/g," ").trim()}catch{}return o.replace(/\s+/g," ").trim()}function D(o,s=10,n=d){let t=o.toLowerCase(),i=[];for(let a of y(500,n)){let e;try{e=w(a.file,"utf8")}catch{continue}let c=0,r="";for(let l of e.split(`
3
3
  `))l.toLowerCase().includes(t)&&(c++,r||(r=k(l).slice(0,160)));if(c>0&&i.push({row:a,matches:c,snippet:r}),i.length>=s)break}return i}function R(o){let s=[`# Session ${o.split(/[\\/]/).pop()??o}`,""];for(let n of w(o,"utf8").split(`
4
4
  `)){if(!n.trim())continue;let t;try{t=JSON.parse(n)}catch{continue}if(t.type!=="message")continue;let i=k(n);i&&s.push(`## ${t.message?.role??"unknown"}`,"",i,"")}return s.join(`
@@ -1,2 +1,2 @@
1
- import{b as o}from"./chunk-4BWDGEXH.js";import{createPrivateKey as p,createPublicKey as f,createHash as l,randomBytes as y,sign as m}from"node:crypto";import{arch as s,cpus as I,hostname as d,platform as c}from"node:os";var a="hf-cli-1",x="MC4CAQAwBQYDK2VwBCIEIDmKoNgInS7oDpncee1d1+Mnci1R/q4aE5xxHeCKq4Dc",C="howtofix-cli-auth-v1",i;function u(){return i||(i=p({key:Buffer.from(x,"base64"),format:"der",type:"pkcs8"})),i}function g(){return f(u())}function K(t,e,n,r){return Buffer.from([C,t,e,n,r].join(`
1
+ import{b as o}from"./chunk-C6HY4Q4J.js";import{createPrivateKey as p,createPublicKey as f,createHash as l,randomBytes as y,sign as m}from"node:crypto";import{arch as s,cpus as I,hostname as d,platform as c}from"node:os";var a="hf-cli-1",x="MC4CAQAwBQYDK2VwBCIEIDmKoNgInS7oDpncee1d1+Mnci1R/q4aE5xxHeCKq4Dc",C="howtofix-cli-auth-v1",i;function u(){return i||(i=p({key:Buffer.from(x,"base64"),format:"der",type:"pkcs8"})),i}function g(){return f(u())}function K(t,e,n,r){return Buffer.from([C,t,e,n,r].join(`
2
2
  `),"utf8")}function h(){return y(16).toString("hex")}var E="tQ91uspGl0sw5Y8x+soLYnFNX6a9vEzSzCuuvalzdKk=";function P(){let t=g().export({format:"der",type:"spki"});return t.subarray(t.length-32).toString("base64")===E}function N(){let t=g().export({format:"der",type:"spki"});return l("sha256").update(t).digest("hex").slice(0,16)}function $(){let e=(I()[0]?.model??"").replace(/\s+/g," ").trim(),n=d(),r=e?`${n} (${c()}/${s()}, ${e})`:`${n} (${c()}/${s()})`;return`CLI (${o}, ${r})`}var k="X-HowToFix-Client";function A(){return`CLI (${o})`}function B(t,e){let n=h(),r=m(null,K(a,t,e,n),u());return{keyId:a,nonce:n,signature:r.toString("base64")}}export{a,g as b,K as c,h as d,P as e,N as f,$ as g,k as h,A as i,B as j};
@@ -0,0 +1 @@
1
+ import{A,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z}from"./chunk-T5YJVQXI.js";import"./chunk-UTYFLLSM.js";import"./chunk-DMNE4TU6.js";import"./chunk-C6HY4Q4J.js";import"./chunk-WOT6VMZA.js";export{g as CATALOG_CACHE_TTL_MS,m as DEFAULT_CONTEXT_WINDOW,a as HOWTOFIX_BASE_URL,b as HOWTOFIX_CONSOLE_URL,l as HOWTOFIX_MODEL_COMPAT,c as HOWTOFIX_PROVIDERS,j as HTTP_IDLE_TIMEOUT_MS,r as UNLIMITED_SENTINEL,v as applyCatalog,w as applyCompat,A as checkAccount,s as checkUsage,d as configuredProviderIds,x as countNewModels,k as ensureGatewaySettings,z as findLiveModels,q as isHowtofixProvider,h as loadCatalog,o as looksLikeToken,n as maskToken,u as mergeModels,e as newProviderEntry,p as parseModelIds,y as probeModel,f as repairGatewayModels,i as repairModelFacts,t as syncGatewayModelsOnStart};
@@ -1,2 +1,2 @@
1
- import{b as c,d as l}from"./chunk-27TRKD65.js";import{D as s}from"./chunk-V656XVXV.js";import"./chunk-UTYFLLSM.js";import{a as i,b as r}from"./chunk-4BWDGEXH.js";import"./chunk-WOT6VMZA.js";var d=[["/connect","sign in with your howtofix.id email:password \u2014 no browser needed"],["/model","choose which model answers"],["/help","list every command"],["/quit","leave"]],u=[" \u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557"," \u2588\u2588\u2551 \u2588\u2588\u2551\u255A\u2588\u2588\u2557\u2588\u2588\u2554\u255D\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D"," \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2588\u2588\u2588\u2557 "," \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551 \u2588\u2588\u2554\u2588\u2588\u2557 \u2588\u2588\u2554\u2550\u2550\u255D "," \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u255D \u2588\u2588\u2557\u2588\u2588\u2551 "," \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D "],m=[" _ _ _____ ","| | | | __ __ | ___|","| |_| | \\ \\/ / | |_ ","| _ | > < | _| ","|_| |_| /_/\\_\\ |_| "];function g(){if(process.platform==="win32")return!1;let e=(process.env.LC_ALL||process.env.LC_CTYPE||process.env.LANG||"").toLowerCase();return e===""||e==="c"||e==="posix"||!e.includes("utf-8")&&!e.includes("utf8")?!1:!/ja|ko|zh|_kr|_jp|_cn|_tw|_hk/.test(e)}function h(){return g()?u:m}var _="https://howtofix.id/cli";function p(e){let n=process.env.HOME??"",t=n!==""&&e.startsWith(n)?`~${e.slice(n.length)}`:e,o=t.split("/").filter(Boolean);return o.length>3?`\u2026/${o.slice(-2).join("/")}`:t}function f(e){let n=e.signedIn?d.filter(([t])=>t!=="/connect"):d;return[...h(),"",`${i} ${r} \u2014 a terminal coding agent. Describe the change you want and it reads, edits and runs the code in front of you.`,"",` working in ${p(e.cwd)}`,...e.note?[` session ${e.note}`]:[],"",...e.signedIn?[" already signed in to howtofix.id",""]:[],...n.map(([t,o])=>` ${t.padEnd(11)}${o}`),"",' Or just start typing. Every message goes to the model; anything beginning with "/" stays local.'].join(`
1
+ import{b as c,d as l}from"./chunk-27TRKD65.js";import{D as s}from"./chunk-V656XVXV.js";import"./chunk-UTYFLLSM.js";import{a as i,b as r}from"./chunk-C6HY4Q4J.js";import"./chunk-WOT6VMZA.js";var d=[["/connect","sign in with your howtofix.id email:password \u2014 no browser needed"],["/model","choose which model answers"],["/help","list every command"],["/quit","leave"]],u=[" \u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557"," \u2588\u2588\u2551 \u2588\u2588\u2551\u255A\u2588\u2588\u2557\u2588\u2588\u2554\u255D\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D"," \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2588\u2588\u2588\u2557 "," \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551 \u2588\u2588\u2554\u2588\u2588\u2557 \u2588\u2588\u2554\u2550\u2550\u255D "," \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u255D \u2588\u2588\u2557\u2588\u2588\u2551 "," \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D "],m=[" _ _ _____ ","| | | | __ __ | ___|","| |_| | \\ \\/ / | |_ ","| _ | > < | _| ","|_| |_| /_/\\_\\ |_| "];function g(){if(process.platform==="win32")return!1;let e=(process.env.LC_ALL||process.env.LC_CTYPE||process.env.LANG||"").toLowerCase();return e===""||e==="c"||e==="posix"||!e.includes("utf-8")&&!e.includes("utf8")?!1:!/ja|ko|zh|_kr|_jp|_cn|_tw|_hk/.test(e)}function h(){return g()?u:m}var _="https://howtofix.id/cli";function p(e){let n=process.env.HOME??"",t=n!==""&&e.startsWith(n)?`~${e.slice(n.length)}`:e,o=t.split("/").filter(Boolean);return o.length>3?`\u2026/${o.slice(-2).join("/")}`:t}function f(e){let n=e.signedIn?d.filter(([t])=>t!=="/connect"):d;return[...h(),"",`${i} ${r} \u2014 a terminal coding agent. Describe the change you want and it reads, edits and runs the code in front of you.`,"",` working in ${p(e.cwd)}`,...e.note?[` session ${e.note}`]:[],"",...e.signedIn?[" already signed in to howtofix.id",""]:[],...n.map(([t,o])=>` ${t.padEnd(11)}${o}`),"",' Or just start typing. Every message goes to the model; anything beginning with "/" stays local.'].join(`
2
2
  `)}function w(){return[{value:"connect",label:"Sign in to howtofix.id",description:"opens the browser, or paste a key from the panel"},{value:"ready",label:"I have a key \u2014 just give me the prompt",description:"drops you at the prompt; run /connect whenever you like"},{value:"release",label:"What's in this release",description:`opens the ${r} notes in your browser`}]}async function E(e,n,t){c(s).welcomeSeen||(l(s),t(`welcome to ${i}`,f(e)),!e.signedIn&&await new Promise(o=>{n("First run \u2014 how do you want to begin?",w(),a=>{a==="connect"&&e.runSlash("/connect"),a==="release"&&e.openExternal(_),o()},()=>o())}))}export{E as maybeShowWelcome};
@@ -1,4 +1,4 @@
1
- import{$ as De,A as _e,B as Te,D as E,E as L,Ea as Ke,G as F,H as $e,P as Ee,Pa as Xe,Q as Ae,Qa as Ye,R as ve,S as je,T as Oe,V as Pe,W as Re,Y as Ce,_ as H,a as C,b as D,ba as Ne,c as re,ca as Fe,d as ie,da as Me,e as ae,ea as Ie,f as ce,fa as Le,g as T,i as le,ia as Ge,j as pe,k as ue,ka as Ue,l as fe,la as G,m as me,ma as Be,na as He,o as ge,p as he,pa as W,q as we,r as ye,s as be,t as $,ta as We,u as ke,ua as ze,v as xe,w as I,wa as qe,x as Se,xa as Ze}from"./chunk-ACOMNDUL.js";import{r as se}from"./chunk-JFYVRWJI.js";import{b as de}from"./chunk-27TRKD65.js";import{D as x,G as ee,r as J,s as Q}from"./chunk-V656XVXV.js";import{c as te}from"./chunk-MTNY7MFG.js";import{g as ne,k as oe}from"./chunk-VICEM5Y2.js";import"./chunk-UTYFLLSM.js";import"./chunk-WZKWT757.js";import{b as M,c as Y,d as V}from"./chunk-4BWDGEXH.js";import"./chunk-WOT6VMZA.js";import{join as St}from"node:path";import{hostname as Nn}from"node:os";import{createAgentSession as Fn,createCodemodeExtension as Mn,createMcpExtension as In,DefaultResourceLoader as Ln,SessionManager as U,SettingsManager as Gn}from"@netrodev/hxf-coding-agent";import{existsSync as Tt,readFileSync as $t}from"node:fs";import{join as Et}from"node:path";var Ve=Et(x,"APPEND_SYSTEM.md"),At=["<non-interactive>","This run has no user attached: it was started with --print, and there is nobody to answer a question. Anything that stops and waits for a reply \u2014 `ask`, a confirmation, a skill that resolves a mode by asking which mode to use \u2014 will simply end the run with the task unfinished.","So do not ask. Where an instruction tells you to ask the user and wait, take the default it describes and continue, and say which default you took and why in your final answer. The user reads that answer; they cannot answer mid-run.","Where a skill offers a choice of modes, prefer the one that applies the rules while you work over the one that audits afterwards: this is the mode for building something now, and the audit mode can still be run later by the same person who reads your answer.","</non-interactive>"].join(`
1
+ import{$ as De,A as _e,B as Te,D as E,E as L,Ea as Ke,G as F,H as $e,P as Ee,Pa as Xe,Q as Ae,Qa as Ye,R as ve,S as je,T as Oe,V as Pe,W as Re,Y as Ce,_ as H,a as C,b as D,ba as Ne,c as re,ca as Fe,d as ie,da as Me,e as ae,ea as Ie,f as ce,fa as Le,g as T,i as le,ia as Ge,j as pe,k as ue,ka as Ue,l as fe,la as G,m as me,ma as Be,na as He,o as ge,p as he,pa as W,q as we,r as ye,s as be,t as $,ta as We,u as ke,ua as ze,v as xe,w as I,wa as qe,x as Se,xa as Ze}from"./chunk-ACOMNDUL.js";import{r as se}from"./chunk-JFYVRWJI.js";import{b as de}from"./chunk-27TRKD65.js";import{D as x,G as ee,r as J,s as Q}from"./chunk-V656XVXV.js";import{c as te}from"./chunk-T5YJVQXI.js";import{g as ne,k as oe}from"./chunk-VXTUPGAD.js";import"./chunk-UTYFLLSM.js";import"./chunk-DMNE4TU6.js";import{b as M,c as Y,d as V}from"./chunk-C6HY4Q4J.js";import"./chunk-WOT6VMZA.js";import{join as St}from"node:path";import{hostname as Nn}from"node:os";import{createAgentSession as Fn,createCodemodeExtension as Mn,createMcpExtension as In,DefaultResourceLoader as Ln,SessionManager as U,SettingsManager as Gn}from"@netrodev/hxf-coding-agent";import{existsSync as Tt,readFileSync as $t}from"node:fs";import{join as Et}from"node:path";var Ve=Et(x,"APPEND_SYSTEM.md"),At=["<non-interactive>","This run has no user attached: it was started with --print, and there is nobody to answer a question. Anything that stops and waits for a reply \u2014 `ask`, a confirmation, a skill that resolves a mode by asking which mode to use \u2014 will simply end the run with the task unfinished.","So do not ask. Where an instruction tells you to ask the user and wait, take the default it describes and continue, and say which default you took and why in your final answer. The user reads that answer; they cannot answer mid-run.","Where a skill offers a choice of modes, prefer the one that applies the rules while you work over the one that audits afterwards: this is the mode for building something now, and the audit mode can still be run later by the same person who reads your answer.","</non-interactive>"].join(`
2
2
  `),vt=16*1024;function jt(e){try{if(!Tt(e))return;let o=$t(e,"utf8").trim();return!o||Buffer.byteLength(o,"utf8")>vt?void 0:o}catch{return}}function Je(e,o){let s=[o?e:`${e}
3
3
 
4
4
  ${At}`],t=jt(Ve);return t&&s.push(`# Standing instructions from ${Ve}
@@ -1 +1 @@
1
- import{c as a,d as b,e as c,f as d,g as e,h as f,i as g,j as h,k as i}from"./chunk-VICEM5Y2.js";import"./chunk-UTYFLLSM.js";import"./chunk-WZKWT757.js";import"./chunk-4BWDGEXH.js";import"./chunk-WOT6VMZA.js";export{b as CLI_REFRESH_SKEW_MS,c as accessTokenIsFresh,g as clearCliCredential,a as cliCredentialsPath,e as readCliCredential,h as refreshCliCredential,d as refreshTokenIsUsable,i as renewCliCredentialIfNeeded,f as writeCliCredential};
1
+ import{c as a,d as b,e as c,f as d,g as e,h as f,i as g,j as h,k as i}from"./chunk-VXTUPGAD.js";import"./chunk-UTYFLLSM.js";import"./chunk-DMNE4TU6.js";import"./chunk-C6HY4Q4J.js";import"./chunk-WOT6VMZA.js";export{b as CLI_REFRESH_SKEW_MS,c as accessTokenIsFresh,g as clearCliCredential,a as cliCredentialsPath,e as readCliCredential,h as refreshCliCredential,d as refreshTokenIsUsable,i as renewCliCredentialIfNeeded,f as writeCliCredential};
@@ -1,109 +1,109 @@
1
- import{u as Cr}from"./chunk-WUPU6LTD.js";import{a as Ar}from"./chunk-ORJ2QZBG.js";import{Aa as ei,Ba as ti,C as ht,Ca as ni,D as Dr,Da as oi,F as Wr,Fa as ae,Ga as T,Ha as O,I as Ur,Ia as ri,J as Kr,Ja as ii,K as gt,Ka as si,L as Hr,La as ai,M as Br,Ma as kn,N as Gr,Na as li,O as gn,Oa as ci,Ra as di,Sa as ui,Ta as fi,U as De,Ua as mi,Va as pi,Wa as hi,X as bn,Xa as gi,Z as wn,aa as We,c as Er,e as Pr,g as Ir,ga as qr,h as _r,ha as Ue,ja as bt,n as Nr,na as Vr,oa as zr,qa as Yr,ra as Xr,sa as Jr,va as Zr,w as Fr,y as hn,ya as yn,z as jr,za as Qr}from"./chunk-ACOMNDUL.js";import{a as Tr,c as mt,d as un,j as Mr,l as fn,m as mn,n as Rr}from"./chunk-JFYVRWJI.js";import{b as ke,c as je,e as Or,f as pn,g as Lr,h as pt}from"./chunk-27TRKD65.js";import{b as bi,c as wi}from"./chunk-WX3V5P7U.js";import{a as yi,b as ki}from"./chunk-BHVBO4SC.js";import{a as rr,b as ir}from"./chunk-6FUWMLWO.js";import{A as on,B as rn,C as tr,D as P,I as nr,J as or,b as tn,c as st,d as at,e as Ko,f as Ho,g as Bo,h as Go,i as lt,j as qo,k as nn,l as Vo,o as ee,p as zo,q as Yo,t as Xo,u as Jo,v as Zo,w as Qo,x as ct,y as dt,z as er}from"./chunk-V656XVXV.js";import{b as sn,c as ye,d as lr,g as cr,m as an,n as dr,p as se,r as Ae,t as ur,v as fr,w as mr,x as pr,y as hr,z as ln}from"./chunk-MTNY7MFG.js";import{a as gr,b as br,c as wr,e as yr,f as kr,g as $r,h as vr,k as xr}from"./chunk-VICEM5Y2.js";import{a as ie}from"./chunk-UTYFLLSM.js";import{h as sr,i as ar}from"./chunk-WZKWT757.js";import{a as en,b as it,e as Uo}from"./chunk-4BWDGEXH.js";import{a as ut,b as cn,c as dn,d as Sr,e as ft}from"./chunk-3FYCFLNK.js";import"./chunk-WOT6VMZA.js";import{execFile as Rl}from"node:child_process";import{promisify as El}from"node:util";import{appendFileSync as Pl,existsSync as Rt,mkdirSync as js,readFileSync as Bn,rmSync as Il,writeFileSync as Gn}from"node:fs";import{basename as _l,join as le,resolve as Ol}from"node:path";function $i(e){if(e==="")return!0;let t=/^\x1b\[(\d+);(\d+)u$/.exec(e);if(t&&Number(t[1])===99&&(Number(t[2])&5)!==0)return!0;let n=/^\x1b\[27;(\d+);(\d+)~$/.exec(e);return!!(n&&Number(n[2])===99&&(Number(n[1])&5)!==0)}function vi(e){let t=!1;process.on("SIGINT",()=>{t||(t=!0,e())})}function ua(e){if(!e||typeof e!="object")return;let t=e;if(!(typeof t.input!="number"&&typeof t.cacheRead!="number"&&typeof t.cacheWrite!="number"))return t}function fa(e){let t=e?.input??0,n=e?.cacheRead??0,r=e?.cacheWrite??0;return{input:t,cacheRead:n,cacheWrite:r,prompt:t+n+r}}function ma(e){if(typeof e!="string")return null;let t=Date.parse(e);return Number.isNaN(t)?null:t}function pa(e){if(!e||typeof e!="object")return;let t=e,r=(t.message&&typeof t.message=="object"?t.message:void 0)??t,i=ua(r.usage);if(!i)return;let u=typeof r.provider=="string"?r.provider:"",f=typeof r.model=="string"?r.model:"";return{usage:i,model:[u,f].filter(Boolean).join("/")}}function xi(e){let t=0,n=0,r=[],i=0,u=null;for(let h of e){let w=pa(h);if(!w)continue;let{input:x,cacheRead:M,cacheWrite:j,prompt:D}=fa(w.usage);if(D===0)continue;t+=M,n+=x+j;let W=ma(h.timestamp),I=u,U=I?I.at:null;if(I!==null&&M===0&&x>=1e3){let L=W!==null&&U!==null?Math.max(0,W-U):0;r.push({missedTokens:x,idleMs:L,modelChanged:w.model!==""&&I.model!==""&&w.model!==I.model}),i+=x}u={prompt:D,at:W??U??null,model:w.model}}let f=t+n;return{cachedTokens:t,billedTokens:n,hitRate:f>0?t/f*100:null,misses:r,missedTokens:i}}function Si(e){return e.modelChanged?"model changed, so its cache had to be built":e.idleMs>=3e5?`cache expired after ${Math.round(e.idleMs/1e3)}s idle`:e.idleMs>0?"prompt changed too early in the prefix to hit":"reason not recorded"}import{copyToClipboard as Ll,SessionManager as Nl}from"@netrodev/hxf-coding-agent";import{CombinedAutocompleteProvider as Ds,Container as Fl,Editor as jl,matchesKey as V,ProcessTerminal as Dl,ScrollView as Wl,KeybindingsManager as Hs,setKeybindings as Bs,TUI_KEYBINDINGS as Gs,SelectList as Ul,TuiAltScreen as Kl,truncateToWidth as Re,VStack as Hl,visibleWidth as Pt,wrapTextWithAnsi as Bl}from"@netrodev/hxf-tui";import{spawn as ha}from"node:child_process";function ga(e,t,n=2e3){return new Promise(r=>{let i=!1,u,f=x=>{i||(i=!0,u!==void 0&&clearTimeout(u),r(x))},h;try{h=ha(e,[...t],{stdio:["ignore","pipe","ignore"]})}catch{f({ok:!1,stdout:""});return}u=setTimeout(()=>{h.kill("SIGKILL"),f({ok:!1,stdout:""})},n);let w=[];h.stdout?.on("data",x=>w.push(x)),h.on("error",()=>f({ok:!1,stdout:""})),h.on("close",x=>{f({ok:x===0,stdout:Buffer.concat(w).toString("utf8")})})})}function $n(){return process.env.XDG_SESSION_TYPE==="wayland"||(process.env.WAYLAND_DISPLAY?.length??0)>0}async function ba(){let e=[];process.platform==="darwin"?e.push({command:"pbpaste",args:[]}):process.platform==="win32"?e.push({command:"powershell.exe",args:["-NoProfile","-Command","Get-Clipboard -Raw"]}):($n()&&(e.push({command:"wl-paste",args:["--no-newline","--type","text/plain;charset=utf-8"]}),e.push({command:"wl-paste",args:["--no-newline","--type","text/plain"]}),e.push({command:"wl-paste",args:["--no-newline"]})),((process.env.DISPLAY?.length??0)>0||!$n())&&(e.push({command:"xclip",args:["-selection","clipboard","-o"]}),e.push({command:"xsel",args:["--clipboard","--output"]})),e.push({command:"termux-clipboard-get",args:[]}));for(let t of e){let n=await ga(t.command,t.args);if(n.ok&&n.stdout.length>0)return n.stdout}}async function Ci(){let e;try{let{getNativeClipboard:r}=await import("@netrodev/hxf-tui");e=r()}catch{e=void 0}if(e)try{let r=await e.getText();if(typeof r=="string"&&r.length>0)return{ok:!0,text:r}}catch{}let t=await ba();return t!==void 0?{ok:!0,text:t}:{ok:!1,reason:`no clipboard tool could read it \u2014 ${$n()?"install wl-clipboard (wl-paste)":process.platform==="darwin"?"pbpaste should be present on macOS":process.platform==="win32"?"Get-Clipboard should be present on Windows":"install xclip or xsel, or run under a display"}`}}import{TreeSelectorComponent as Gl,initTheme as ql}from"@netrodev/hxf-coding-agent";import{getKeybindings as Ws}from"@netrodev/hxf-tui";import{mixColors as wa,parseColor as ya,styleText as de}from"@netrodev/hxf-tui";var ue=process.env.HOWTOFIX_NO_MOTION!=="1",ka=45,Ai=5,Ti=8,vn=1e4,Mi=6e4,Ri=3,Ei=4,xn=e=>e<0?0:e>1?1:e;function fe(e,t,n){let r=xn(n);return r>=1?t:r<=0?e:wa(e,t,r)}var wt=class{value;velocity=0;last=Date.now();target;constructor(t,n=t){this.value=t,this.target=n}set(t){this.target=t}get moving(){return Math.abs(this.target-this.value)>.15}snap(t){this.value=t,this.target=t,this.velocity=0,this.last=Date.now()}step(t=Date.now()){let n=Math.max(0,t-this.last),r=Math.min(250,n)/1e3;if(this.last=t,!ue)return this.value=this.target,this.velocity=0,this.value;n>250&&(this.velocity=0);let i=150,u=2*Math.sqrt(i),f=Math.max(1,Math.ceil(r/.008)),h=r/f;for(let w=0;w<f;w+=1)this.velocity+=(this.target-this.value)*i*h-this.velocity*u*h,this.value+=this.velocity*h;return this.moving||(this.value=this.target,this.velocity=0),this.value}};function Sn(e,t,n,r){return!ue||e<=vn?t:e>=Mi?r:fe(n,r,(e-vn)/(Mi-vn))}function Pi(e,t){return!ue||t<=0||e<0?1:1-(1-xn(e/t))**3}function Ii(e,t){return ue&&e>=0&&e<t}var Cn=260,$a=45;function An(e,t,n=$a,r=400){return!ue||n<=0||e<0||e>=r?t:Math.min(t,Math.floor(e/n)+1)}function _i(e,t,n=Date.now(),r=1400){if(!ue||r<=0)return e;let i=n%r/r;return fe(e,t,i<.5?i*2:(1-i)*2)}function Oi(e,t,n){let r=de(e,{fg:t.rest},ae);if(!ue||e.length===0)return r;let i=xn(n);if(i>=1)return r;let u=t.band??1,f=e.length+Ei*2,w=Math.min(f-1,Math.floor(i*f))-Ei,x=U=>{let L=Math.abs(U-w);return L>u?0:1-L/(u+1)},M="",j=0,D=null,W=0,I=0;for(let U of e){let L=x(I);D===null?D=L:L!==D&&(M+=de(e.slice(j,W),{fg:fe(t.rest,t.lit,D)},ae),j=W,D=L),W+=U.length,I+=1}return M+de(e.slice(j),{fg:fe(t.rest,t.lit,D??0)},ae)}function Li(e,t,n=Date.now(),r=90){let i=t[0]??ya("#e6e6e6");if(t.length===0||e.length===0)return de(e,{fg:i},ae);if(!ue||r<=0)return de(e,{fg:t[t.length-1]??i},ae);let u=t.length*r,f=(n%u+u)%u,h="",w=0,x=null,M=0,j=0,D=W=>{let I=(f+W*r)/u%1*t.length,U=Math.floor(I)%t.length,L=(U+1)%t.length;return fe(t[U]??i,t[L]??i,I-Math.floor(I))};for(let W of e){let I=D(j);x===null?x=I:I!==x&&(h+=de(e.slice(w,M),{fg:x},ae),w=M,x=I),M+=W.length,j+=1}return h+de(e.slice(w),{fg:x??i},ae)}function va(e,t){let n=Math.abs(e-t);return n>=Ai?0:Math.ceil((1-n/Ai)*Ri)/Ri}function Ni(e,t,n=Date.now()){let r=t.charMs??ka;if(!ue||e.length===0||r<=0)return de(e,{fg:t.base},ae);let i=e.length+Ti*2,u=n/r%i-Ti,f=(D,W)=>de(D,{fg:fe(t.base,t.bright,W)},ae),h="",w=0,x=null,M=0,j=0;for(let D of e){let W=va(j,u);x===null?x=W:W!==x&&(h+=f(e.slice(w,M),x),w=M,x=W),M+=D.length,j+=1}return h+f(e.slice(w),x??0)}import{Markdown as Wa,wrapTextWithAnsi as Ua}from"@netrodev/hxf-tui";import{homedir as xa}from"node:os";import{isAbsolute as Sa,relative as Ca,resolve as Aa,sep as Fi}from"node:path";var Ta="\u25CF",Rn="\u2514",kt="\u22EF",Tn=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"];function Be(e=90){let t=Math.floor(Date.now()/e)%Tn.length;return Tn[t]??Tn[0]}var Ma="\u25B2";var Ra="\u25CB",Ea=["create_object","set_properties","delete_object","clone_instance","reparent_instance","set_script_source","edit_script_lines","insert_script_lines","execute_luau","generate_mesh","generate_material","generate_procedural_model"];function En(e){return e.includes("__")?e.slice(e.lastIndexOf("__")+2):e}function Ui(e){return Ea.includes(En(e))}function Ke(e,t=process.cwd()){if(!e||!Sa(e))return e;let n=Aa(e),r=Ca(t,n);if(r==="")return".";if(r&&!r.startsWith(`..${Fi}`)&&r!=="..")return r;let i=xa();return i&&(n===i||n.startsWith(i+Fi))?`~${n.slice(i.length)}`:n}function te(e,t){let n=e.replace(/\s+/g," ").trim();return n.length>t?`${n.slice(0,Math.max(1,t-1))}\u2026`:n}function N(e,t){if(e&&typeof e=="object"){let n=e[t];if(typeof n=="string"&&n.length>0)return n;if(typeof n=="number")return String(n)}}function Pa(e,t=160){if(!e||typeof e!="object")return"";try{let n=JSON.stringify(e);return n&&n!=="{}"?te(n,t):""}catch{return""}}function Ia(e,t){switch(e){case"read":{let n=Ke(N(t,"path")??""),r=[N(t,"offset"),N(t,"limit")].filter(Boolean);return r.length>0?`${n} ${r.length===1?`offset=${r[0]}`:`offset=${r[0]}, limit=${r[1]}`}`:n}case"edit":case"write":return Ke(N(t,"path")??"");case"bash":case"powershell":{let n=N(t,"command")??"";return t?.run_in_background===!0?`${n} [background]`:n}case"bash_output":{let n=N(t,"task_id"),r=N(t,"filter");return n?r?`${n} filter=${r}`:n:"all tasks"}case"kill_shell":return N(t,"task_id")??"";case"compress":{let n=N(t,"topic")??"",r=Array.isArray(t.content)?t.content.length:0;return r>1?`${n} (${r} ranges)`:n}case"grep":{let n=N(t,"pattern")??"",r=N(t,"path");return r?`${n} in ${Ke(r)}`:n}case"find":case"glob":{let n=N(t,"pattern")??N(t,"glob")??"",r=N(t,"path");return r?`${n} in ${Ke(r)}`:n}case"ls":return Ke(N(t,"path")??".");case"task":return N(t,"agent")??"task";case"ask":return N(t,"question")??"";case"web_search":return N(t,"query")??"";case"web_fetch":return N(t,"url")??"";case"lsp":{let n=N(t,"action")??"lsp",r=N(t,"file")??"",i=N(t,"line");return i?`${n} ${r}:${i}`:`${n} ${r}`}case"quality":return N(t,"path")??"changed files";case"think":return"private";case"todo":{let n=N(t,"op")??"view",r=N(t,"task"),i=t?.items;return n==="init"&&Array.isArray(i)?`init ${i.length} task${i.length===1?"":"s"}`:r?`${n} ${r}`:n}case"context":{let n=N(t,"op")??"list",r=N(t,"key");return r?`${n} ${r}`:n}case"workflow":{let n=N(t,"path");if(n)return n;let r=N(t,"code")??"",i=/export\s+const\s+meta\s*=\s*\{[\s\S]*?name\s*:\s*["'`]([^"'`]+)/.exec(r)?.[1];if(i)return i;let u=r.trim().split(`
2
- `)[0]??"";return u.length>40?`${u.slice(0,40)}\u2026`:u}default:return Pa(t)}}function $e(e,t,n=100){let r=En(e),u=r!==e?r:r.charAt(0).toUpperCase()+r.slice(1),f=Ui(e)?Ma:Ta,h=te(Ia(r,t),n);return h?`${f} ${u}(${h})`:`${f} ${u}`}function _a(e){let t=0,n=0;for(let r of e.split(`
3
- `))r.startsWith("+")&&!r.startsWith("+++")?t+=1:r.startsWith("-")&&!r.startsWith("---")&&(n+=1);return{additions:t,removals:n}}function Te(e){let t=e?.content;return typeof t=="string"?t:Array.isArray(t)?t.map(n=>n&&typeof n=="object"&&n.type==="text"?String(n.text??""):"").join(""):""}function Ge(e){let t=e?.details;return t&&typeof t=="object"?t:{}}function Pn(e){let t=e?.structuredContent;return t&&typeof t=="object"?t:{}}function ji(e){let t=e.exit_code;return typeof t=="number"&&Number.isFinite(t)?t:void 0}function Oa(e){let t=[];if(e&&typeof e=="object"){t.push(e);let r=e.content;if(Array.isArray(r))for(let i of r){let u=i?.text;if(typeof u=="string")try{let f=JSON.parse(u);f&&typeof f=="object"&&t.push(f)}catch{}}}let n=[];for(let r of t){let i=["instances","instanceCount","count","parts","partsCreated"].map(w=>r[w]).find(w=>typeof w=="number"&&Number.isFinite(w));typeof i=="number"&&n.push(`${i} instance${i===1?"":"s"}`);let u=Mn(r,["files","written","paths"]);u&&n.push(u.join(", "));let f=Mn(r,["images","renders","screenshots"]);f&&n.push(`renders ${Ra} ${f.join(", ")}`);let h=Mn(r,["findings","warnings","errors"]);if(h&&n.push(`${h.length} finding${h.length===1?"":"s"}`),n.length>0)break}return n.length>0?n.join(" \xB7 "):void 0}function Mn(e,t){for(let n of t){let r=e[n];if(!Array.isArray(r))continue;let i=r.filter(u=>typeof u=="string"&&u!=="");if(i.length>0)return i}}function Di(e){return e.trim().split(`
4
- `).find(t=>t.trim())??""}function La(e,t){let n=typeof e.output=="string"?e.output:t.replace(/\n*Command exited with code \d+\s*$/,""),r=He(n);return r>0?` (${r} line${r===1?"":"s"})`:""}function Na(e,t,n){return e===1?t:n}function He(e){let t=e.trim();return t?t.split(`
5
- `).length:0}function Wi(e){return e<1e3?`${e} tokens`:`${(e/1e3).toFixed(1)}k tokens`}function $t(e,t,n){let r=Te(t),i=Ge(t),u=Pn(t);if(n){let f=ji(u);if(f!==void 0&&(e==="bash"||e==="powershell"))return`exit ${f}`;let h=r.trim().split(`
6
- `).find(w=>w.trim());return te(h??"failed",120)}if(Ui(e)){let f=Oa(t);if(f)return f;let h=En(e);return h==="execute_luau"?"ran":te(h.replace(/_/g," "),120)}switch(e){case"task":{let f=r.split(`
1
+ import{u as Ar}from"./chunk-WUPU6LTD.js";import{a as Tr}from"./chunk-ORJ2QZBG.js";import{Aa as ti,Ba as ni,C as ht,Ca as oi,D as Wr,Da as ri,F as Ur,Fa as ae,Ga as T,Ha as O,I as Kr,Ia as ii,J as Hr,Ja as si,K as gt,Ka as ai,L as Br,La as li,M as Gr,Ma as kn,N as qr,Na as ci,O as gn,Oa as di,Ra as ui,Sa as fi,Ta as pi,U as De,Ua as mi,Va as hi,Wa as gi,X as bn,Xa as bi,Z as wn,aa as We,c as Pr,e as Ir,g as _r,ga as Vr,h as Or,ha as Ue,ja as bt,n as Fr,na as zr,oa as Yr,qa as Xr,ra as Jr,sa as Zr,va as Qr,w as jr,y as hn,ya as yn,z as Dr,za as ei}from"./chunk-ACOMNDUL.js";import{a as Mr,c as pt,d as un,j as Rr,l as fn,m as pn,n as Er}from"./chunk-JFYVRWJI.js";import{b as ke,c as je,e as Lr,f as mn,g as Nr,h as mt}from"./chunk-27TRKD65.js";import{b as wi,c as yi}from"./chunk-WX3V5P7U.js";import{a as ki,b as $i}from"./chunk-BHVBO4SC.js";import{a as rr,b as ir}from"./chunk-6FUWMLWO.js";import{A as on,B as rn,C as tr,D as E,I as nr,J as or,b as tn,c as st,d as at,e as Ko,f as Ho,g as Bo,h as Go,i as lt,j as qo,k as nn,l as Vo,o as ee,p as zo,q as Yo,t as Xo,u as Jo,v as Zo,w as Qo,x as ct,y as dt,z as er}from"./chunk-V656XVXV.js";import{A as ln,b as sn,c as ye,d as lr,e as cr,h as dr,n as an,o as ur,q as re,s as Ae,u as fr,w as pr,x as mr,y as hr,z as gr}from"./chunk-T5YJVQXI.js";import{a as br,b as wr,c as yr,e as kr,f as $r,g as vr,h as xr,k as Sr}from"./chunk-VXTUPGAD.js";import{a as se}from"./chunk-UTYFLLSM.js";import{h as sr,i as ar}from"./chunk-DMNE4TU6.js";import{a as en,b as it,e as Uo}from"./chunk-C6HY4Q4J.js";import{a as ut,b as cn,c as dn,d as Cr,e as ft}from"./chunk-3FYCFLNK.js";import"./chunk-WOT6VMZA.js";import{execFile as El}from"node:child_process";import{promisify as Pl}from"node:util";import{appendFileSync as Il,existsSync as Rt,mkdirSync as Ds,readFileSync as Bn,rmSync as _l,writeFileSync as Gn}from"node:fs";import{basename as Ol,join as le,resolve as Ll}from"node:path";function vi(e){if(e==="")return!0;let t=/^\x1b\[(\d+);(\d+)u$/.exec(e);if(t&&Number(t[1])===99&&(Number(t[2])&5)!==0)return!0;let n=/^\x1b\[27;(\d+);(\d+)~$/.exec(e);return!!(n&&Number(n[2])===99&&(Number(n[1])&5)!==0)}function xi(e){let t=!1;process.on("SIGINT",()=>{t||(t=!0,e())})}function fa(e){if(!e||typeof e!="object")return;let t=e;if(!(typeof t.input!="number"&&typeof t.cacheRead!="number"&&typeof t.cacheWrite!="number"))return t}function pa(e){let t=e?.input??0,n=e?.cacheRead??0,r=e?.cacheWrite??0;return{input:t,cacheRead:n,cacheWrite:r,prompt:t+n+r}}function ma(e){if(typeof e!="string")return null;let t=Date.parse(e);return Number.isNaN(t)?null:t}function ha(e){if(!e||typeof e!="object")return;let t=e,r=(t.message&&typeof t.message=="object"?t.message:void 0)??t,i=fa(r.usage);if(!i)return;let u=typeof r.provider=="string"?r.provider:"",f=typeof r.model=="string"?r.model:"";return{usage:i,model:[u,f].filter(Boolean).join("/")}}function Si(e){let t=0,n=0,r=[],i=0,u=null;for(let h of e){let w=ha(h);if(!w)continue;let{input:x,cacheRead:M,cacheWrite:j,prompt:D}=pa(w.usage);if(D===0)continue;t+=M,n+=x+j;let W=ma(h.timestamp),I=u,U=I?I.at:null;if(I!==null&&M===0&&x>=1e3){let L=W!==null&&U!==null?Math.max(0,W-U):0;r.push({missedTokens:x,idleMs:L,modelChanged:w.model!==""&&I.model!==""&&w.model!==I.model}),i+=x}u={prompt:D,at:W??U??null,model:w.model}}let f=t+n;return{cachedTokens:t,billedTokens:n,hitRate:f>0?t/f*100:null,misses:r,missedTokens:i}}function Ci(e){return e.modelChanged?"model changed, so its cache had to be built":e.idleMs>=3e5?`cache expired after ${Math.round(e.idleMs/1e3)}s idle`:e.idleMs>0?"prompt changed too early in the prefix to hit":"reason not recorded"}import{copyToClipboard as Nl,SessionManager as Fl}from"@netrodev/hxf-coding-agent";import{CombinedAutocompleteProvider as Ws,Container as jl,Editor as Dl,matchesKey as V,ProcessTerminal as Wl,ScrollView as Ul,KeybindingsManager as Bs,setKeybindings as Gs,TUI_KEYBINDINGS as qs,SelectList as Kl,TuiAltScreen as Hl,truncateToWidth as Re,VStack as Bl,visibleWidth as Pt,wrapTextWithAnsi as Gl}from"@netrodev/hxf-tui";import{spawn as ga}from"node:child_process";function ba(e,t,n=2e3){return new Promise(r=>{let i=!1,u,f=x=>{i||(i=!0,u!==void 0&&clearTimeout(u),r(x))},h;try{h=ga(e,[...t],{stdio:["ignore","pipe","ignore"]})}catch{f({ok:!1,stdout:""});return}u=setTimeout(()=>{h.kill("SIGKILL"),f({ok:!1,stdout:""})},n);let w=[];h.stdout?.on("data",x=>w.push(x)),h.on("error",()=>f({ok:!1,stdout:""})),h.on("close",x=>{f({ok:x===0,stdout:Buffer.concat(w).toString("utf8")})})})}function $n(){return process.env.XDG_SESSION_TYPE==="wayland"||(process.env.WAYLAND_DISPLAY?.length??0)>0}async function wa(){let e=[];process.platform==="darwin"?e.push({command:"pbpaste",args:[]}):process.platform==="win32"?e.push({command:"powershell.exe",args:["-NoProfile","-Command","Get-Clipboard -Raw"]}):($n()&&(e.push({command:"wl-paste",args:["--no-newline","--type","text/plain;charset=utf-8"]}),e.push({command:"wl-paste",args:["--no-newline","--type","text/plain"]}),e.push({command:"wl-paste",args:["--no-newline"]})),((process.env.DISPLAY?.length??0)>0||!$n())&&(e.push({command:"xclip",args:["-selection","clipboard","-o"]}),e.push({command:"xsel",args:["--clipboard","--output"]})),e.push({command:"termux-clipboard-get",args:[]}));for(let t of e){let n=await ba(t.command,t.args);if(n.ok&&n.stdout.length>0)return n.stdout}}async function Ai(){let e;try{let{getNativeClipboard:r}=await import("@netrodev/hxf-tui");e=r()}catch{e=void 0}if(e)try{let r=await e.getText();if(typeof r=="string"&&r.length>0)return{ok:!0,text:r}}catch{}let t=await wa();return t!==void 0?{ok:!0,text:t}:{ok:!1,reason:`no clipboard tool could read it \u2014 ${$n()?"install wl-clipboard (wl-paste)":process.platform==="darwin"?"pbpaste should be present on macOS":process.platform==="win32"?"Get-Clipboard should be present on Windows":"install xclip or xsel, or run under a display"}`}}import{TreeSelectorComponent as ql,initTheme as Vl}from"@netrodev/hxf-coding-agent";import{getKeybindings as Us}from"@netrodev/hxf-tui";import{mixColors as ya,parseColor as ka,styleText as de}from"@netrodev/hxf-tui";var ue=process.env.HOWTOFIX_NO_MOTION!=="1",$a=45,Ti=5,Mi=8,vn=1e4,Ri=6e4,Ei=3,Pi=4,xn=e=>e<0?0:e>1?1:e;function fe(e,t,n){let r=xn(n);return r>=1?t:r<=0?e:ya(e,t,r)}var wt=class{value;velocity=0;last=Date.now();target;constructor(t,n=t){this.value=t,this.target=n}set(t){this.target=t}get moving(){return Math.abs(this.target-this.value)>.15}snap(t){this.value=t,this.target=t,this.velocity=0,this.last=Date.now()}step(t=Date.now()){let n=Math.max(0,t-this.last),r=Math.min(250,n)/1e3;if(this.last=t,!ue)return this.value=this.target,this.velocity=0,this.value;n>250&&(this.velocity=0);let i=150,u=2*Math.sqrt(i),f=Math.max(1,Math.ceil(r/.008)),h=r/f;for(let w=0;w<f;w+=1)this.velocity+=(this.target-this.value)*i*h-this.velocity*u*h,this.value+=this.velocity*h;return this.moving||(this.value=this.target,this.velocity=0),this.value}};function Sn(e,t,n,r){return!ue||e<=vn?t:e>=Ri?r:fe(n,r,(e-vn)/(Ri-vn))}function Ii(e,t){return!ue||t<=0||e<0?1:1-(1-xn(e/t))**3}function _i(e,t){return ue&&e>=0&&e<t}var Cn=260,va=45;function An(e,t,n=va,r=400){return!ue||n<=0||e<0||e>=r?t:Math.min(t,Math.floor(e/n)+1)}function Oi(e,t,n=Date.now(),r=1400){if(!ue||r<=0)return e;let i=n%r/r;return fe(e,t,i<.5?i*2:(1-i)*2)}function Li(e,t,n){let r=de(e,{fg:t.rest},ae);if(!ue||e.length===0)return r;let i=xn(n);if(i>=1)return r;let u=t.band??1,f=e.length+Pi*2,w=Math.min(f-1,Math.floor(i*f))-Pi,x=U=>{let L=Math.abs(U-w);return L>u?0:1-L/(u+1)},M="",j=0,D=null,W=0,I=0;for(let U of e){let L=x(I);D===null?D=L:L!==D&&(M+=de(e.slice(j,W),{fg:fe(t.rest,t.lit,D)},ae),j=W,D=L),W+=U.length,I+=1}return M+de(e.slice(j),{fg:fe(t.rest,t.lit,D??0)},ae)}function Ni(e,t,n=Date.now(),r=90){let i=t[0]??ka("#e6e6e6");if(t.length===0||e.length===0)return de(e,{fg:i},ae);if(!ue||r<=0)return de(e,{fg:t[t.length-1]??i},ae);let u=t.length*r,f=(n%u+u)%u,h="",w=0,x=null,M=0,j=0,D=W=>{let I=(f+W*r)/u%1*t.length,U=Math.floor(I)%t.length,L=(U+1)%t.length;return fe(t[U]??i,t[L]??i,I-Math.floor(I))};for(let W of e){let I=D(j);x===null?x=I:I!==x&&(h+=de(e.slice(w,M),{fg:x},ae),w=M,x=I),M+=W.length,j+=1}return h+de(e.slice(w),{fg:x??i},ae)}function xa(e,t){let n=Math.abs(e-t);return n>=Ti?0:Math.ceil((1-n/Ti)*Ei)/Ei}function Fi(e,t,n=Date.now()){let r=t.charMs??$a;if(!ue||e.length===0||r<=0)return de(e,{fg:t.base},ae);let i=e.length+Mi*2,u=n/r%i-Mi,f=(D,W)=>de(D,{fg:fe(t.base,t.bright,W)},ae),h="",w=0,x=null,M=0,j=0;for(let D of e){let W=xa(j,u);x===null?x=W:W!==x&&(h+=f(e.slice(w,M),x),w=M,x=W),M+=D.length,j+=1}return h+f(e.slice(w),x??0)}import{Markdown as Ua,wrapTextWithAnsi as Ka}from"@netrodev/hxf-tui";import{homedir as Sa}from"node:os";import{isAbsolute as Ca,relative as Aa,resolve as Ta,sep as ji}from"node:path";var Ma="\u25CF",Rn="\u2514",kt="\u22EF",Tn=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"];function Be(e=90){let t=Math.floor(Date.now()/e)%Tn.length;return Tn[t]??Tn[0]}var Ra="\u25B2";var Ea="\u25CB",Pa=["create_object","set_properties","delete_object","clone_instance","reparent_instance","set_script_source","edit_script_lines","insert_script_lines","execute_luau","generate_mesh","generate_material","generate_procedural_model"];function En(e){return e.includes("__")?e.slice(e.lastIndexOf("__")+2):e}function Ki(e){return Pa.includes(En(e))}function Ke(e,t=process.cwd()){if(!e||!Ca(e))return e;let n=Ta(e),r=Aa(t,n);if(r==="")return".";if(r&&!r.startsWith(`..${ji}`)&&r!=="..")return r;let i=Sa();return i&&(n===i||n.startsWith(i+ji))?`~${n.slice(i.length)}`:n}function te(e,t){let n=e.replace(/\s+/g," ").trim();return n.length>t?`${n.slice(0,Math.max(1,t-1))}\u2026`:n}function N(e,t){if(e&&typeof e=="object"){let n=e[t];if(typeof n=="string"&&n.length>0)return n;if(typeof n=="number")return String(n)}}function Ia(e,t=160){if(!e||typeof e!="object")return"";try{let n=JSON.stringify(e);return n&&n!=="{}"?te(n,t):""}catch{return""}}function _a(e,t){switch(e){case"read":{let n=Ke(N(t,"path")??""),r=[N(t,"offset"),N(t,"limit")].filter(Boolean);return r.length>0?`${n} ${r.length===1?`offset=${r[0]}`:`offset=${r[0]}, limit=${r[1]}`}`:n}case"edit":case"write":return Ke(N(t,"path")??"");case"bash":case"powershell":{let n=N(t,"command")??"";return t?.run_in_background===!0?`${n} [background]`:n}case"bash_output":{let n=N(t,"task_id"),r=N(t,"filter");return n?r?`${n} filter=${r}`:n:"all tasks"}case"kill_shell":return N(t,"task_id")??"";case"compress":{let n=N(t,"topic")??"",r=Array.isArray(t.content)?t.content.length:0;return r>1?`${n} (${r} ranges)`:n}case"grep":{let n=N(t,"pattern")??"",r=N(t,"path");return r?`${n} in ${Ke(r)}`:n}case"find":case"glob":{let n=N(t,"pattern")??N(t,"glob")??"",r=N(t,"path");return r?`${n} in ${Ke(r)}`:n}case"ls":return Ke(N(t,"path")??".");case"task":return N(t,"agent")??"task";case"ask":return N(t,"question")??"";case"web_search":return N(t,"query")??"";case"web_fetch":return N(t,"url")??"";case"lsp":{let n=N(t,"action")??"lsp",r=N(t,"file")??"",i=N(t,"line");return i?`${n} ${r}:${i}`:`${n} ${r}`}case"quality":return N(t,"path")??"changed files";case"think":return"private";case"todo":{let n=N(t,"op")??"view",r=N(t,"task"),i=t?.items;return n==="init"&&Array.isArray(i)?`init ${i.length} task${i.length===1?"":"s"}`:r?`${n} ${r}`:n}case"context":{let n=N(t,"op")??"list",r=N(t,"key");return r?`${n} ${r}`:n}case"workflow":{let n=N(t,"path");if(n)return n;let r=N(t,"code")??"",i=/export\s+const\s+meta\s*=\s*\{[\s\S]*?name\s*:\s*["'`]([^"'`]+)/.exec(r)?.[1];if(i)return i;let u=r.trim().split(`
2
+ `)[0]??"";return u.length>40?`${u.slice(0,40)}\u2026`:u}default:return Ia(t)}}function $e(e,t,n=100){let r=En(e),u=r!==e?r:r.charAt(0).toUpperCase()+r.slice(1),f=Ki(e)?Ra:Ma,h=te(_a(r,t),n);return h?`${f} ${u}(${h})`:`${f} ${u}`}function Oa(e){let t=0,n=0;for(let r of e.split(`
3
+ `))r.startsWith("+")&&!r.startsWith("+++")?t+=1:r.startsWith("-")&&!r.startsWith("---")&&(n+=1);return{additions:t,removals:n}}function Te(e){let t=e?.content;return typeof t=="string"?t:Array.isArray(t)?t.map(n=>n&&typeof n=="object"&&n.type==="text"?String(n.text??""):"").join(""):""}function Ge(e){let t=e?.details;return t&&typeof t=="object"?t:{}}function Pn(e){let t=e?.structuredContent;return t&&typeof t=="object"?t:{}}function Di(e){let t=e.exit_code;return typeof t=="number"&&Number.isFinite(t)?t:void 0}function La(e){let t=[];if(e&&typeof e=="object"){t.push(e);let r=e.content;if(Array.isArray(r))for(let i of r){let u=i?.text;if(typeof u=="string")try{let f=JSON.parse(u);f&&typeof f=="object"&&t.push(f)}catch{}}}let n=[];for(let r of t){let i=["instances","instanceCount","count","parts","partsCreated"].map(w=>r[w]).find(w=>typeof w=="number"&&Number.isFinite(w));typeof i=="number"&&n.push(`${i} instance${i===1?"":"s"}`);let u=Mn(r,["files","written","paths"]);u&&n.push(u.join(", "));let f=Mn(r,["images","renders","screenshots"]);f&&n.push(`renders ${Ea} ${f.join(", ")}`);let h=Mn(r,["findings","warnings","errors"]);if(h&&n.push(`${h.length} finding${h.length===1?"":"s"}`),n.length>0)break}return n.length>0?n.join(" \xB7 "):void 0}function Mn(e,t){for(let n of t){let r=e[n];if(!Array.isArray(r))continue;let i=r.filter(u=>typeof u=="string"&&u!=="");if(i.length>0)return i}}function Wi(e){return e.trim().split(`
4
+ `).find(t=>t.trim())??""}function Na(e,t){let n=typeof e.output=="string"?e.output:t.replace(/\n*Command exited with code \d+\s*$/,""),r=He(n);return r>0?` (${r} line${r===1?"":"s"})`:""}function Fa(e,t,n){return e===1?t:n}function He(e){let t=e.trim();return t?t.split(`
5
+ `).length:0}function Ui(e){return e<1e3?`${e} tokens`:`${(e/1e3).toFixed(1)}k tokens`}function $t(e,t,n){let r=Te(t),i=Ge(t),u=Pn(t);if(n){let f=Di(u);if(f!==void 0&&(e==="bash"||e==="powershell"))return`exit ${f}`;let h=r.trim().split(`
6
+ `).find(w=>w.trim());return te(h??"failed",120)}if(Ki(e)){let f=La(t);if(f)return f;let h=En(e);return h==="execute_luau"?"ran":te(h.replace(/_/g," "),120)}switch(e){case"task":{let f=r.split(`
7
7
  `).filter(h=>h.startsWith("## ")).map(h=>h.replace(/^##\s*/,"").trim());if(f.length===0){let h=r.trim().split(`
8
8
  `).find(w=>w.trim());return te(h??"done",120)}return f.map(h=>te(h,120)).join(`
9
- `)}case"read":{let f=i.truncation,h=He(r.replace(/\n*\[[^\]]*\]\s*$/,"")),w=h===0?"empty":`${h} line${h===1?"":"s"}`;return f?.truncated?`${w} (truncated from ${f.totalLines??"?"})`:w}case"compress":{let f=Array.isArray(i.blockIds)?i.blockIds:[],h=typeof i.compressedTokens=="number"?i.compressedTokens:0,w=typeof i.summaryTokens=="number"?i.summaryTokens:0,x=f.length===1?`b${String(f[0])}`:`${f.length} blocks`;if(h===0)return x;let M=h-w;return M<0?`${x} \xB7 ${Wi(-M)} LARGER than the range`:`${x} \xB7 ${Wi(M)} saved`}case"edit":{let f=typeof i.diff=="string"?i.diff:"";if(!f)return"applied";let{additions:h,removals:w}=_a(f);return`+${h} / -${w}`}case"write":{let f=He(r);return f===0?"written":`written (${f} ${Na(f,"line","lines")})`}case"bash":case"powershell":{let f=ji(u);if(f===void 0)return r.trim()?te(Di(r),120):"done";let h=La(u,r);return f===0?`exit 0${h}`:`exit ${f}`}case"grep":{let f=He(r);return f===0?"no matches":`${f} match${f===1?"":"es"}`}case"web_search":{let f=typeof i.count=="number"?i.count:He(r);return f===0?"no results":`${f} result${f===1?"":"s"}`}case"web_fetch":return`${typeof i.chars=="number"?i.chars:r.length} chars`;case"lsp":{let f=typeof i.count=="number"?i.count:void 0;return typeof i.error=="string"?te(i.error,120):f===void 0?te(Di(r),120):`${f} location${f===1?"":"s"}`}case"quality":{if(typeof i.error=="string")return te(i.error,120);if(i.off===!0)return"off";let f=typeof i.files=="number"?i.files:0,h=typeof i.functions=="number"?i.functions:0,w=typeof i.findings=="number"?i.findings:0,x=typeof i.score=="number"?` \xB7 ${Math.round(i.score)}`:"";return f===0?"no files":`${f} file${f===1?"":"s"} \xB7 ${h} fn \xB7 ${w} finding${w===1?"":"s"}${x}`}case"todo":{let f=i.todos??[];if(!Array.isArray(f)||f.length===0)return"list cleared";let h=f.filter(x=>x.status==="completed").length,w=f.filter(x=>x.status==="pending"||x.status==="in_progress").length;return`${h}/${f.length} done, ${w} open`}case"context":{let f=i.notes,h=f?Object.keys(f).length:0;return h===0?"no notes":`${h} note${h===1?"":"s"} held`}case"workflow":{let f=typeof i.agents=="number"?i.agents:0,h=typeof i.outputTokens=="number"?i.outputTokens:0,w=Array.isArray(i.steps)?i.steps.filter(M=>M.status==="failed").length:0;if(typeof i.error=="string")return`failed after ${f} agent(s)`;let x=typeof i.startedAt=="number"&&typeof i.endedAt=="number"?`, ${si(i.endedAt-i.startedAt)}`:"";return`${f} agent(s), ${h} tokens${x}${w>0?`, ${w} failed`:""}`}case"bash_output":{let f=r.trim().split(`
9
+ `)}case"read":{let f=i.truncation,h=He(r.replace(/\n*\[[^\]]*\]\s*$/,"")),w=h===0?"empty":`${h} line${h===1?"":"s"}`;return f?.truncated?`${w} (truncated from ${f.totalLines??"?"})`:w}case"compress":{let f=Array.isArray(i.blockIds)?i.blockIds:[],h=typeof i.compressedTokens=="number"?i.compressedTokens:0,w=typeof i.summaryTokens=="number"?i.summaryTokens:0,x=f.length===1?`b${String(f[0])}`:`${f.length} blocks`;if(h===0)return x;let M=h-w;return M<0?`${x} \xB7 ${Ui(-M)} LARGER than the range`:`${x} \xB7 ${Ui(M)} saved`}case"edit":{let f=typeof i.diff=="string"?i.diff:"";if(!f)return"applied";let{additions:h,removals:w}=Oa(f);return`+${h} / -${w}`}case"write":{let f=He(r);return f===0?"written":`written (${f} ${Fa(f,"line","lines")})`}case"bash":case"powershell":{let f=Di(u);if(f===void 0)return r.trim()?te(Wi(r),120):"done";let h=Na(u,r);return f===0?`exit 0${h}`:`exit ${f}`}case"grep":{let f=He(r);return f===0?"no matches":`${f} match${f===1?"":"es"}`}case"web_search":{let f=typeof i.count=="number"?i.count:He(r);return f===0?"no results":`${f} result${f===1?"":"s"}`}case"web_fetch":return`${typeof i.chars=="number"?i.chars:r.length} chars`;case"lsp":{let f=typeof i.count=="number"?i.count:void 0;return typeof i.error=="string"?te(i.error,120):f===void 0?te(Wi(r),120):`${f} location${f===1?"":"s"}`}case"quality":{if(typeof i.error=="string")return te(i.error,120);if(i.off===!0)return"off";let f=typeof i.files=="number"?i.files:0,h=typeof i.functions=="number"?i.functions:0,w=typeof i.findings=="number"?i.findings:0,x=typeof i.score=="number"?` \xB7 ${Math.round(i.score)}`:"";return f===0?"no files":`${f} file${f===1?"":"s"} \xB7 ${h} fn \xB7 ${w} finding${w===1?"":"s"}${x}`}case"todo":{let f=i.todos??[];if(!Array.isArray(f)||f.length===0)return"list cleared";let h=f.filter(x=>x.status==="completed").length,w=f.filter(x=>x.status==="pending"||x.status==="in_progress").length;return`${h}/${f.length} done, ${w} open`}case"context":{let f=i.notes,h=f?Object.keys(f).length:0;return h===0?"no notes":`${h} note${h===1?"":"s"} held`}case"workflow":{let f=typeof i.agents=="number"?i.agents:0,h=typeof i.outputTokens=="number"?i.outputTokens:0,w=Array.isArray(i.steps)?i.steps.filter(M=>M.status==="failed").length:0;if(typeof i.error=="string")return`failed after ${f} agent(s)`;let x=typeof i.startedAt=="number"&&typeof i.endedAt=="number"?`, ${ai(i.endedAt-i.startedAt)}`:"";return`${f} agent(s), ${h} tokens${x}${w>0?`, ${w} failed`:""}`}case"bash_output":{let f=r.trim().split(`
10
10
  `)[0]??"",h=/running/.test(f)?"running":/finished/.test(f)?"finished":"task",w=r.trim().split(`
11
11
  `).slice(2).filter(x=>x.trim()).length;return w===0?h:`${h} \xB7 ${w} line${w===1?"":"s"}`}case"kill_shell":{let f=r.trim().split(`
12
12
  `)[0]??"";return f.startsWith("Stopped")?"stopped":te(f,120)}default:{let f=r.trim().split(`
13
- `).find(h=>h.trim());return f?te(f,120):"done"}}}function Ki(e,t){let n=Ge(t);if(e==="edit"&&typeof n.diff=="string")return n.diff.split(`
13
+ `).find(h=>h.trim());return f?te(f,120):"done"}}}function Hi(e,t){let n=Ge(t);if(e==="edit"&&typeof n.diff=="string")return n.diff.split(`
14
14
  `).filter(r=>r.length>0).slice(0,12);if(e==="bash"||e==="powershell"){if(Te(t).startsWith("Started bash_"))return[];let i=Pn(t);return(typeof i.output=="string"?i.output:Te(t).replace(/\n*Command exited with code \d+\s*$/,"")).trimEnd().split(`
15
15
  `).filter(h=>h.trim()).slice(-4)}if(e==="bash_output")return Te(t).split(`
16
16
  `).slice(2).filter(i=>i.trim()).slice(-6);if(e==="todo"){let r=n.todos??[],i={pending:"[ ]",in_progress:"[>]",completed:"[x]",dropped:"[-]"};return r.slice(0,6).map(u=>`${i[u.status??"pending"]??"[ ]"} ${u.content??""}`)}return e==="task"?Te(t).split(`
17
- `).filter(r=>r.trim()&&!r.startsWith("## ")).slice(0,6):e==="workflow"?(n.steps??[]).map(u=>{let f=u.status==="running"?"\u25B8":u.status==="failed"?"\xD7":"\u2713",h=u.phase?`${u.phase} \xB7 `:"";return`${f} ${h}${u.label??"agent"}`}).slice(-6):[]}var yt=400;function Hi(e,t){let n=Ge(t);if(e==="edit"&&typeof n.diff=="string")return n.diff.split(`
17
+ `).filter(r=>r.trim()&&!r.startsWith("## ")).slice(0,6):e==="workflow"?(n.steps??[]).map(u=>{let f=u.status==="running"?"\u25B8":u.status==="failed"?"\xD7":"\u2713",h=u.phase?`${u.phase} \xB7 `:"";return`${f} ${h}${u.label??"agent"}`}).slice(-6):[]}var yt=400;function Bi(e,t){let n=Ge(t);if(e==="edit"&&typeof n.diff=="string")return n.diff.split(`
18
18
  `).filter(h=>h.length>0).slice(0,yt);let r=Pn(t),u=(typeof r.output=="string"?r.output:Te(t).replace(/\n*Command exited with code \d+\s*$/,"")).trimEnd().split(`
19
- `),f=u.slice(0,yt);return u.length>yt&&f.push(`\u2026 ${u.length-yt} more line(s)`),f}var Fa={read:{active:"Reading",done:"Read",one:"file",many:"files"},search:{active:"Searching for",done:"Searched for",one:"pattern",many:"patterns"},list:{active:"Listing",done:"Listed",one:"directory",many:"directories"}};function ja(e){if(e==="read")return"read";if(e==="grep"||e==="find"||e==="glob")return"search";if(e==="ls")return"list"}function Bi(e,t=!1){let n=[],r,i=()=>{if(!r||r.indices.length<2){r=void 0;return}n.push({start:r.indices[0],indices:r.indices,counts:r.counts,summary:Da(r.counts,t)}),r=void 0};for(let[u,f]of e.entries()){let h=ja(f.toolName);if(h===void 0){i();continue}r||(r={indices:[],counts:{}}),r.indices.push(u),r.counts[h]=(r.counts[h]??0)+1}return i(),n}function Da(e,t){let n=[];for(let r of["search","read","list"]){let i=e[r];if(i===void 0)continue;let u=Fa[r],f=t?u.active:u.done,h=i===1?u.one:u.many;n.push(`${n.length===0?f:f.toLowerCase()} ${i} ${h}`)}return n.join(", ")}function qi(e,t){let n=e[e.length-1];return n&&n.kind==="note"&&n.title===t.title?[...e.slice(0,-1),t]:[...e,t]}function In(e){return typeof e=="string"?De(e):De(e.map(t=>t.type==="text"?t.text:t.type==="thinking"?"":t.type==="image"?"[image]":(t.type==="toolCall","")).filter(Boolean).join(""))}function Vi(e){return e.role==="user"?In(e.content).trim():""}function zi(e,t,n){let r=t.trim();if(!r)return e;let i=e.findIndex(f=>f.kind==="user"&&f.body.trim()===r);if(i===-1)return[...e,{id:n,kind:"user",title:"you",body:r}];let u=[...e];return u[i]={id:n,kind:"user",title:"you",body:r},u}function Ka(e){return e.content.filter(t=>t.type==="toolCall").map(t=>({name:t.name,arguments:t.arguments}))}function Ha(e){return e.content.filter(t=>t.type==="toolCall").map(t=>t.id)}function Ba(e){let t=e.map(f=>({toolName:f.kind==="result"||f.kind==="tool"?f.title:"",line:f.call??f.body})),n=Bi(t);if(n.length===0)return e;let r=new Map(n.map(f=>[f.start,f])),i=new Set(n.flatMap(f=>f.indices)),u=[];for(let[f,h]of e.entries()){let w=r.get(f);if(w){let x=e[w.start];u.push({id:x?.id??`g-${w.start}`,kind:"collapsed",title:"collapsed",body:w.summary,full:w.indices.map(M=>e[M]?.call??e[M]?.body??"").filter(Boolean)});continue}i.has(f)||u.push(h)}return u}function xt(e){let t=[];for(let n of e)if(n.role==="user"){let r=In(n.content).trim();if(!r)continue;t.push({id:`u-${n.timestamp}`,kind:"user",title:"you",body:r})}else if(n.role==="assistant"){let r=In(n.content).trim(),i=Ka(n),u=Ha(n);r?t.push({id:`a-${n.timestamp}`,kind:n.stopReason==="error"?"error":"assistant",title:n.errorMessage?"failed":"fix",body:n.errorMessage?`${n.errorMessage}
19
+ `),f=u.slice(0,yt);return u.length>yt&&f.push(`\u2026 ${u.length-yt} more line(s)`),f}var ja={read:{active:"Reading",done:"Read",one:"file",many:"files"},search:{active:"Searching for",done:"Searched for",one:"pattern",many:"patterns"},list:{active:"Listing",done:"Listed",one:"directory",many:"directories"}};function Da(e){if(e==="read")return"read";if(e==="grep"||e==="find"||e==="glob")return"search";if(e==="ls")return"list"}function Gi(e,t=!1){let n=[],r,i=()=>{if(!r||r.indices.length<2){r=void 0;return}n.push({start:r.indices[0],indices:r.indices,counts:r.counts,summary:Wa(r.counts,t)}),r=void 0};for(let[u,f]of e.entries()){let h=Da(f.toolName);if(h===void 0){i();continue}r||(r={indices:[],counts:{}}),r.indices.push(u),r.counts[h]=(r.counts[h]??0)+1}return i(),n}function Wa(e,t){let n=[];for(let r of["search","read","list"]){let i=e[r];if(i===void 0)continue;let u=ja[r],f=t?u.active:u.done,h=i===1?u.one:u.many;n.push(`${n.length===0?f:f.toLowerCase()} ${i} ${h}`)}return n.join(", ")}function Vi(e,t){let n=e[e.length-1];return n&&n.kind==="note"&&n.title===t.title?[...e.slice(0,-1),t]:[...e,t]}function In(e){return typeof e=="string"?De(e):De(e.map(t=>t.type==="text"?t.text:t.type==="thinking"?"":t.type==="image"?"[image]":(t.type==="toolCall","")).filter(Boolean).join(""))}function zi(e){return e.role==="user"?In(e.content).trim():""}function Yi(e,t,n){let r=t.trim();if(!r)return e;let i=e.findIndex(f=>f.kind==="user"&&f.body.trim()===r);if(i===-1)return[...e,{id:n,kind:"user",title:"you",body:r}];let u=[...e];return u[i]={id:n,kind:"user",title:"you",body:r},u}function Ha(e){return e.content.filter(t=>t.type==="toolCall").map(t=>({name:t.name,arguments:t.arguments}))}function Ba(e){return e.content.filter(t=>t.type==="toolCall").map(t=>t.id)}function Ga(e){let t=e.map(f=>({toolName:f.kind==="result"||f.kind==="tool"?f.title:"",line:f.call??f.body})),n=Gi(t);if(n.length===0)return e;let r=new Map(n.map(f=>[f.start,f])),i=new Set(n.flatMap(f=>f.indices)),u=[];for(let[f,h]of e.entries()){let w=r.get(f);if(w){let x=e[w.start];u.push({id:x?.id??`g-${w.start}`,kind:"collapsed",title:"collapsed",body:w.summary,full:w.indices.map(M=>e[M]?.call??e[M]?.body??"").filter(Boolean)});continue}i.has(f)||u.push(h)}return u}function xt(e){let t=[];for(let n of e)if(n.role==="user"){let r=In(n.content).trim();if(!r)continue;t.push({id:`u-${n.timestamp}`,kind:"user",title:"you",body:r})}else if(n.role==="assistant"){let r=In(n.content).trim(),i=Ha(n),u=Ba(n);r?t.push({id:`a-${n.timestamp}`,kind:n.stopReason==="error"?"error":"assistant",title:n.errorMessage?"failed":"fix",body:n.errorMessage?`${n.errorMessage}
20
20
 
21
- ${r}`:r}):n.errorMessage&&t.push({id:`e-${n.timestamp}`,kind:"error",title:"failed",body:n.errorMessage}),i.forEach((f,h)=>{let w=u[h];t.push({id:w?`tool-${w}`:`c-${n.timestamp}-${h}`,kind:"tool",title:f.name,body:$e(f.name,f.arguments),...w?{call:$e(f.name,f.arguments)}:{}})})}else if(n.role==="toolResult"){let r=$t(n.toolName,{content:n.content},n.isError),i=t.find(u=>u.id===`tool-${n.toolCallId}`);i?(i.kind="result",i.body=r,i.title=n.toolName):t.push({id:`r-${n.toolCallId}`,kind:"result",title:n.toolName,body:r})}return Ba(t)}function Gi(e,t,n){return Ua(e,Math.max(8,t)).map(r=>O(r,n))}var qe=new Map;function Ga(e){let t=e.body||" ",n=qe.get(e.id);if(n)return n.text!==t&&(n.component.setText(t),n.text=t),n.component;let r=new Wa(t,0,0,ri);return qe.set(e.id,{text:t,component:r}),r}var _n=class{constructor(t){this.item=t}item;invalidate(){}shade(t){let n=Date.now()-(this.item.born??0);return fe(T.dim,t,Pi(n,Cn))}render(t){let n=this.item.body;if(this.item.kind==="user"){let i=this.item.pending?[O(" queued \u2014 the run reads this at its next step",T.dim)]:[];return["",...Gi(`> ${n}`,t,this.shade(T.user)),...i]}if(this.item.kind==="tool")return[O(`${Be()} ${n}`,this.shade(T.tool))];if(this.item.kind==="collapsed"){let i=[O(`${kt} ${n}`,this.shade(T.mute))],u=this.item.full??[];if(u.length>0)if(this.item.expanded===!0)for(let f of u)i.push(O(` ${f}`,this.shade(T.dim)));else i.push(O(` ${u.length} call(s) \xB7 ctrl+e to expand`,T.dim));return i}if(this.item.kind==="result"){let i=n.startsWith("exit ")&&n!=="exit 0";if(this.item.panel)return["",...this.item.panel(t),...n?[O(` ${Rn} ${n}`,i?T.bad:T.mute)]:[]];let u=[];this.item.call&&u.push(O(this.item.call,this.shade(T.tool)));let f=` ${Rn} ${n}`;if(u.push(O(f,i?T.bad:this.shade(T.mute))),this.item.expanded===!0&&(this.item.full?.length??0)>0){let M=O(` ${this.item.full.length} line(s) \xB7 ctrl+e to collapse`,T.dim);u.push(O(` ${kt}`,T.dim));for(let j of this.item.full){let D=j.startsWith("+")?T.tool:j.startsWith("-")?T.bad:T.dim;u.push(O(` ${j}`,D))}return u.push(M),u}let w=this.item.detail??[],x=An(Date.now()-(this.item.born??0),w.length);for(let M of w.slice(0,x)){let j=M.startsWith("+")?T.tool:M.startsWith("-")?T.bad:T.dim;u.push(O(` ${M}`,this.shade(j)))}return(this.item.full?.length??0)>0&&u.push(O(` ${kt} ${this.item.full.length} line(s) \xB7 ctrl+e to expand`,T.dim)),u}if(this.item.kind==="error"||this.item.kind==="note"){let i=this.item.kind==="error"?T.bad:T.mute;return["",...Gi(n,t,this.shade(i))]}return["",...Ga(this.item).render(Math.max(8,t-2))]}},vt=class{items=[];status="";scrollOffset=0;scrollAnchor;settledOffset=0;viewportHeight=0;invalidate(){}entering(){let t=Date.now();return this.items.some(n=>{if(n.born===void 0)return!1;let r=t-n.born;return Ii(r,Cn)?!0:(n.detail?.length??0)>An(r,n.detail?.length??0)})}render(t){if(qe.size>this.items.length){let i=new Set(this.items.map(u=>u.id));for(let u of qe.keys())i.has(u)||qe.delete(u)}let n=[];for(let i of this.items)i.born??=Date.now(),n.push(...new _n(i).render(t));this.status&&n.push(O(this.status,T.mute));let r=this.viewportHeight;if(r>0&&n.length>r){let i=n.length-r;this.scrollOffset!==this.settledOffset&&(this.scrollAnchor=void 0);let u=this.scrollAnchor,f;if(u!==void 0){let h=n.length-u;h>=0&&h<=i?f=h:f=Math.max(0,Math.min(this.scrollOffset,i))}else f=Math.max(0,Math.min(this.scrollOffset,i));return u===void 0&&(this.scrollOffset=f),this.settledOffset=this.scrollOffset,f===0?this.scrollAnchor=void 0:this.scrollAnchor===void 0&&(this.scrollAnchor=n.length-f),n.slice(i-f,i-f+r)}return n}};import{parseColor as Z}from"@netrodev/hxf-tui";var me={off:Z("okhsl(230 12% 46%)"),minimal:Z("okhsl(240 55% 49%)"),low:Z("okhsl(252 60% 55%)"),medium:Z("okhsl(270 64% 60%)"),high:Z("okhsl(298 70% 64%)"),xhigh:Z("okhsl(332 80% 66%)"),max:Z("okhsl(42 95% 64%)")},Yi={off:Z("okhsl(230 14% 64%)"),minimal:Z("okhsl(240 60% 64%)"),low:Z("okhsl(252 64% 68%)"),medium:Z("okhsl(270 68% 72%)"),high:Z("okhsl(298 74% 76%)"),xhigh:Z("okhsl(332 82% 78%)"),max:Z("okhsl(42 96% 76%)")};function St(e){return me[e]??me.medium}var Ji=[me.minimal,me.low,me.medium,me.high,me.xhigh,me.max];function Zi(e){return Yi[e]??Yi.medium}var Xi=460;function Ct(e){return!Number.isFinite(e)||e<0||e>=Xi?0:1-e/Xi}var B=["off","minimal","low","medium","high","xhigh","max"];function Qi(e){let t=e?.thinkingLevelMap;if(t===void 0)return B[B.length-1];for(let n=B.length-1;n>=0;n-=1)if(typeof t[B[n]]=="string")return B[n]}function es(e){let t=B.indexOf(e);return B[(t+1+B.length)%B.length]}function ts(e){let t=B.indexOf(e);return B[(t-1+B.length)%B.length]}import{mkdirSync as Ya,readFileSync as Xa}from"node:fs";import{dirname as Ja}from"node:path";var Ln="\x1B[0m",G="\x1B[2m",qa="\x1B[1m",Va="\x1B[31m",Nn="\x1B[32m",os="\x1B[33m",ns="\x1B[35m",On="\x1B[36m";function F(e,t){return`${t}${e}${Ln}`}function rs(e,t){return O(e,St(t))}function is(e){return e>=85?Va:e>=70?os:Nn}var za="\u2726";function ss(e,t,n,r){let i=F(`[${e}]`,On),u=`${F(za,G)} ${t}`,f=F(n,os),h=r?` ${F("git:(",ns)}${F(r.replace(/^git:\(/,"").replace(/\)$/,""),On)}${F(")",ns)}`:"";return`${i}${F(" \u2502 ",G)}${u}${F(" \u2502 ",G)}${f}${h}`}function as(e,t,n){if(!t)return e;let r=n===void 0?t:`${t} ${F(ai(n),G)}`;return`${F(r,On)} ${F("\u2502",G)} ${e}`}function ls(e,...t){let n=Number.isFinite(e)?Math.min(100,Math.max(0,e)):0,r=Math.round(n/10),i=is(n),u=`${i}${"\u2588".repeat(r)}${G}${"\u2591".repeat(10-r)}${Ln}`,f=F(`${Math.round(n)}%`,i),h=t.filter(Boolean).join(F(" \u2502 ",G));return`${F("Context",G)} ${u} ${f}${h?`${F(" \u2502 ",G)}${h}`:""}`}function cs(e){return!Number.isFinite(e)||e<=0?"":`${F("Spent",G)} ${F(`$${e.toFixed(3)}`,Nn)}`}function ds(e,t,n,r){let i=Number.isFinite(t)&&t>0?t:0,u=Number.isFinite(n)?Math.max(0,n):0,f=Math.max(0,i-u),h=i>0?Math.min(100,u/i*100):0,w=Math.round(h/10),x=is(h),M=`${x}${"\u2588".repeat(w)}${G}${"\u2591".repeat(10-w)}${Ln}`,j=D=>`${D.toFixed(2)} ${r}`;return[`${F(e,qa)}${F(" account",G)}`,` ${F("used",G)} ${M} ${F(`${h.toFixed(1)}%`,x)}`,` ${F("granted",G)} ${j(i)}`,` ${F("spent",G)} ${j(u)}`,` ${F("remaining",G)} ${F(j(f),x)}`]}function Fn(e,t,n){let r=n===null?"":F(` ${n}ms`,G),i=t&&t!=="USD"?`${t} `:"";return`${F("Balance",G)} ${F(`${i}${e}`,Nn)}${r}`}var jn=nr,Za=18e4;async function Qa(e){let t=new Set((await e.modelRuntime.getAvailable()).map(i=>i.provider).filter(i=>se(i))),n=ye.find(i=>t.has(i));return n?(await e.modelRuntime.getAuth(n))?.auth?.apiKey:void 0}function el(){try{let e=JSON.parse(Xa(jn,"utf8"));return!e.data||typeof e.cachedAt!="number"?void 0:{data:e.data,cachedAt:e.cachedAt}}catch{return}}function At(e){if(e.unlimited)return Fn("unlimited","",e.latencyMs);let n=e.unit==="USD"||e.unit==="CNY"?`$${e.remaining.toFixed(2)}`:`${e.remaining.toLocaleString()}`;return Fn(n,e.unit,e.latencyMs)}async function us(e){let t=el();if(t&&Date.now()-t.cachedAt<Za)return At(t.data);let n=await Qa(e);if(!n)return t?At(t.data):void 0;let r=Date.now(),i=await Ae(n,{timeoutMs:3e3});if(!i.ok)return t?At(t.data):void 0;let u={remaining:i.remaining??0,limit:i.limit??0,unit:i.unit,unlimited:i.unlimited,latencyMs:Date.now()-r};return Ya(Ja(jn),{recursive:!0}),ie(jn,JSON.stringify({data:u,cachedAt:Date.now()})),At(u)}import{chmodSync as tl,existsSync as nl,readFileSync as ol}from"node:fs";import{join as rl}from"node:path";function fs(e){return rl(e,"account-credential.json")}function ms(e,t){return Buffer.from(`${e}:${t}`,"utf8").toString("base64")}function Dn(e){let t=e.trim();if(!t)return null;let n=i=>{let u=i.indexOf(":");return u<=0||u===i.length-1?null:{username:i.slice(0,u),password:i.slice(u+1)}},r=n(t);if(r)return r;try{let i=Buffer.from(t,"base64").toString("utf8");return i.includes(":")?n(i):null}catch{return null}}function ps(e,t,n){try{let r={credential:ms(t,n),username:t,savedAt:Math.floor(Date.now()/1e3)},i=fs(e);return ie(i,JSON.stringify(r,null,2)),tl(i,384),!0}catch{return!1}}function hs(e){try{let t=fs(e);if(!nl(t))return null;let n=JSON.parse(ol(t,"utf8"));return!n?.credential||!n?.username?null:n}catch{return null}}async function il(e,t){let n=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t),signal:AbortSignal.timeout(2e4)}),r=await n.text(),i;try{i=JSON.parse(r)}catch{throw new Error(`the panel answered ${n.status} with something that is not JSON`)}let u=i;if(!n.ok||u.success===!1)throw new Error(u.message||`the panel answered ${n.status}`);return u.data}async function gs(e,t,n,r){let i=await il(`${e}/api/auth/cli/credential`,{credential:ms(t,n),client_info:r});if(!i?.token)throw new Error("the panel accepted the credential but returned no key");return{token:i.token}}import{execFileSync as sl}from"node:child_process";import{createHash as al}from"node:crypto";import{readFileSync as ll}from"node:fs";import{arch as cl,hostname as dl,platform as bs}from"node:os";function ul(e){try{return ll(e,"utf8").trim()}catch{return""}}function ws(e,t){try{return sl(e,t,{encoding:"utf8",timeout:3e3})}catch{return""}}function fl(){return ws("reg",["query","HKLM\\SOFTWARE\\Microsoft\\Cryptography","/v","MachineGuid"]).match(/MachineGuid\s+REG_SZ\s+([0-9a-fA-F-]+)/)?.[1]??""}function ml(){return ws("ioreg",["-rd1","-c","IOPlatformExpertDevice"]).match(/"IOPlatformUUID"\s*=\s*"([^"]+)"/)?.[1]??""}function pl(){return["/sys/class/dmi/id/product_uuid","/sys/class/dmi/id/board_serial","/sys/class/dmi/id/product_serial","/etc/machine-id","/var/lib/dbus/machine-id"].map(ul).filter(Boolean)}function hl(){switch(bs()){case"win32":{let e=fl();return e?[e]:[]}case"darwin":{let e=ml();return e?[e]:[]}default:return pl()}}var Tt;function ys(){if(Tt)return{id:Tt,weak:!1};let e=hl(),t=e.length===0,n=[bs(),cl(),...e,t?dl():""].join("|");return Tt=al("sha256").update(n).digest("hex").slice(0,32),{id:Tt,weak:t}}var gl="/cli/checkin",bl=["Bearer",""].join(" ").trim(),wl=5e5;function Wn(e){return`$${(e/wl).toFixed(2)}`}async function ks(e,t,n,r,i){let u=new AbortController,f=setTimeout(()=>u.abort(),i);try{let h=await r(`${n}${gl}`,{method:t,headers:{[sr]:ar(),"X-HowToFix-Device":ys().id,Authorization:`${bl} ${e}`},signal:u.signal}),w={};try{w=await h.json()}catch{}return{status:h.status,body:w}}finally{clearTimeout(f)}}async function Un(e,t){let n=(t?.baseUrl??"https://api.howtofix.id/v1").replace(/\/+$/,""),r=t?.fetchImpl??fetch,i=t?.timeoutMs??1e4,u=e.trim();if(!u)return{ok:!1,enabled:!1,checkedInToday:!1,quotaToday:0,message:"no token given"};try{let{status:f,body:h}=await ks(u,"GET",n,r,i);if(f===401||f===403)return{ok:!1,enabled:!1,checkedInToday:!1,quotaToday:0,message:"the gateway rejected that token for the check-in status"};if(f>=400||h.success!==!0)return{ok:!1,enabled:!1,checkedInToday:!1,quotaToday:0,message:typeof h.message=="string"?h.message:`the gateway answered ${f}`};let w=h.data??{};return{ok:!0,enabled:w.enabled===!0,checkedInToday:w.checked_in_today===!0,quotaToday:Number(w.quota_today??0)||0,message:""}}catch(f){return{ok:!1,enabled:!1,checkedInToday:!1,quotaToday:0,message:f instanceof Error&&f.name==="AbortError"?"the gateway did not answer the check-in in time":"could not reach the gateway"}}}async function $s(e,t){let n=(t?.baseUrl??"https://api.howtofix.id/v1").replace(/\/+$/,""),r=t?.fetchImpl??fetch,i=t?.timeoutMs??15e3,u=e.trim();if(!u)return{ok:!1,alreadyClaimed:!1,blocked:!1,quotaAwarded:0,message:"no token given"};try{let{status:f,body:h}=await ks(u,"POST",n,r,i);if(h.success===!0){let j=h.data??{};return{ok:!0,alreadyClaimed:!1,blocked:!1,quotaAwarded:Number(j.quota_awarded??0)||0,message:""}}let w=typeof h.message=="string"?h.message:`the gateway answered ${f}`,x=/device already claimed|account blocked|appeal/i.test(w);return{ok:!1,alreadyClaimed:!x&&/签到|check-?in|already|今日/.test(w)&&!/not enabled/i.test(w),blocked:x,quotaAwarded:0,message:w}}catch(f){return{ok:!1,alreadyClaimed:!1,blocked:!1,quotaAwarded:0,message:f instanceof Error&&f.name==="AbortError"?"the gateway did not answer the check-in in time":"could not reach the gateway"}}}function yl(e){return!e||!Number.isFinite(e)||e<=0?"":e>=1e6?`${Number((e/1e6).toFixed(1))}M`:e>=1e3?`${Math.round(e/1e3)}K`:String(e)}function kl(e){if(!e)return"";if(e.input<=0&&e.output<=0)return"free";let t=n=>n===0?"0":String(Number(n>=1?n.toFixed(2):n.toFixed(3)));return`$${t(e.input)}/$${t(e.output)} per M`}function vs(e){let t=yl(e.contextWindow),n=kl(e.cost);return[t?`${t} ctx`:"",n].filter(Boolean).join(" \xB7 ")}function xs(){return{}}function Ss(e,t,n,r=Date.now()){let i={...e};return t==="run"?(n===void 0||n===""?delete i.run:i.run={label:n,since:e.run?.since??r},i):(n===void 0||n===""?delete i[t]:i[t]=n,i)}function Cs(e,t){let n={...e};return t===void 0?delete n.retry:n.retry=t,n}function $l(e){let t=Math.max(0,Math.round(e/1e3)),n=Math.floor(t/60);return n>0?`${n}m ${String(t%60).padStart(2,"0")}s`:`${t}s`}function Kn(e,t=72){let n=e.split(`
22
- `).map(r=>r.trim()).find(r=>r!=="")??"";return n.length>t?`${n.slice(0,t-1)}\u2026`:n}function vl(e,t){let n=Math.max(0,Math.ceil((e.until-t)/1e3)),r=n>0?`in ${n}s`:"now",i=`retry ${e.attempt}/${e.maxAttempts} ${r}`,u=Kn(e.error);return u===""?i:`${i} \xB7 ${u}`}function As(e,t,n=Date.now()){return e.prompt?`? ${e.prompt}`:e.retry?`* ${vl(e.retry,n)}`:e.note?`* ${e.note}`:e.run?`${t} ${e.run.label} \xB7 ${$l(n-e.run.since)}`:e.tally?e.tally:""}import{spawn as xl}from"node:child_process";function Sl(e){switch(e){case"darwin":return{command:"open",args:[]};case"win32":return{command:"cmd",args:["/c","start",""]};case"linux":return{command:"xdg-open",args:[]};default:return}}async function Ve(e,t=process.platform){let n=Sl(t);return n?new Promise(r=>{try{let i=xl(n.command,[...n.args,e],{detached:!0,stdio:"ignore"});i.once("error",()=>r(!1)),i.once("spawn",()=>{i.unref(),r(!0)})}catch{r(!1)}}):!1}function Ts(e){return e instanceof Error?e.message:String(e)}var ze=class{active;apply;report;pending;running;constructor(t){this.active=new Set(t.initial??[]),this.apply=t.apply,this.report=t.report??(n=>console.error(n))}activeServers(){return[...this.active]}reconcile(t){return this.pending=new Set(t),this.running?this.running:(this.running=this.drain().finally(()=>{this.running=void 0}),this.running)}async drain(){let t={added:[],removed:[],unchanged:[],problems:[]};for(;this.pending!==void 0;){let r=this.pending;this.pending=void 0;let i=await this.applyOnce(r);t.added.push(...i.added),t.removed.push(...i.removed),t.unchanged.push(...i.unchanged),t.problems.push(...i.problems)}let n=this.active;return t.added=t.added.filter(r=>n.has(r)),t.removed=[...new Set(t.removed.filter(r=>!n.has(r)))],t.added=[...new Set(t.added)],t.unchanged=[...new Set(t.unchanged.filter(r=>n.has(r)))],t}async applyOnce(t){let n=[...t].filter(u=>!this.active.has(u)),r=[...this.active].filter(u=>!t.has(u)),i=[...t].filter(u=>this.active.has(u));if(n.length===0&&r.length===0)return{added:[],removed:[],unchanged:i,problems:[]};try{await this.apply(n,r)}catch(u){let f=`mcp reconciliation failed: ${Ts(u)}`;return this.report(f),{added:[],removed:[],unchanged:[],problems:[f]}}for(let u of n)this.active.add(u);for(let u of r)this.active.delete(u);return{added:n,removed:r,unchanged:i,problems:[]}}async dispose(){this.running&&await this.running.catch(()=>{});let t=[...this.active];if(t.length===0)return{added:[],removed:[],unchanged:[],problems:[]};try{return await this.apply([],t),this.active.clear(),{added:[],removed:t,unchanged:[],problems:[]}}catch(n){let r=`mcp teardown failed: ${Ts(n)}`;return this.report(r),{added:[],removed:[],unchanged:[],problems:[r]}}}};import{mkdirSync as Cl}from"node:fs";import{join as Al}from"node:path";import{matchesKey as Mt}from"@netrodev/hxf-tui";var Hn=["all","running","failed","done"];function Rs(){return{selectedPhase:0,filter:"all",paused:!1,expanded:!1,follow:!0}}function Es(e){if(Mt(e,"up"))return"up";if(Mt(e,"down"))return"down";if(Mt(e,"enter"))return"enter";if(Mt(e,"escape"))return"escape";if(e==="f")return"filter";if(e==="p")return"pause";if(e==="x")return"stop";if(e==="s")return"save"}function Ms(e,t,n){if(t.length===0)return e;let r=Math.max(0,Math.min(t.length-1,e.selectedPhase+n));return{...e,selectedPhase:r,follow:!1}}function Tl(e){let t=Hn.indexOf(e);return Hn[(t+1)%Hn.length]}function Ps(e,t,n){switch(t){case"up":return Ms(e,n,-1);case"down":return Ms(e,n,1);case"enter":return{...e,expanded:!e.expanded};case"filter":return{...e,filter:Tl(e.filter)};case"pause":return{...e,paused:!e.paused};default:return e}}function Is(e,t){switch(t){case"running":return e.filter(n=>n.status==="running");case"failed":return e.filter(n=>n.status==="failed");case"done":return e.filter(n=>n.status!=="running");default:return[...e]}}function _s(e){return e==="all"?"":` \xB7 ${e}`}var Os="ctrl+f";function Ls(e,t,n=!0){if(!n)return"Ctrl+F panel keys \xB7 Esc unpin";let r=["\u2191/\u2193 phase",e.expanded?"Enter collapse":"Enter drill in"];return r.push(e.expanded?"Esc back out":"Esc unpin"),r.push(`f filter${e.filter==="all"?"":` (${e.filter})`}`),t?(r.push(e.paused?"p resume":"p pause"),r.push("x stop")):e.paused&&r.push("p resume"),r.push("s save script"),e.paused&&r.unshift("paused"),r.join(" \xB7 ")}function Ml(e){let t=e.trim();if(!(!t||t.length>64)&&!(t==="."||t==="..")&&/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(t)&&!t.includes(".."))return t}function Ns(e,t){if(!e)return{ok:!1,reason:"this run was started from a file, so it is already saved where you pointed the tool"};let n=Ml(e.name);if(!n)return{ok:!1,reason:`"${e.name}" is not a usable filename, so the script was not written`};let r=Al(t,`${n}.js`);try{Cl(t,{recursive:!0}),ie(r,e.code)}catch(i){return{ok:!1,reason:i instanceof Error?i.message:String(i)}}return{ok:!0,path:r}}function Fs(e){let t=()=>{};return{select:(n,r)=>e.select(n,r),confirm:(n,r)=>e.confirm(n,r),input:n=>e.input(n),notify:(n,r)=>e.notify(n,r),onTerminalInput:()=>t,setStatus:(n,r)=>e.setStatus(n,r),setWorkingMessage:t,setWorkingVisible:t,setWorkingIndicator:t,setHiddenThinkingLabel:t,setWidget:(n,r,i)=>{r!==void 0&&!Array.isArray(r)||e.setWidget?.(n,r,i?.placement)},setFooter:t,setHeader:t,setTitle:t,custom:async()=>{throw new Error("this screen has no custom component host; use the text commands instead")},pasteToEditor:t,setEditorText:t,getEditorText:()=>"",editor:async()=>{},addAutocompleteProvider:t,setEditorComponent:t,getEditorComponent:()=>{},theme:void 0,getAllThemes:()=>[],getTheme:()=>{},setTheme:()=>({success:!1,error:"themes are not available in the workbench"}),getToolsExpanded:()=>!1,setToolsExpanded:t}}var Us={borderColor:()=>"",selectList:{selectedPrefix:e=>O(e,T.accent),selectedText:e=>O(e,T.text,{bold:!0}),description:e=>O(e,T.mute),scrollInfo:e=>O(e,T.dim),noMatch:e=>O(e,T.mute)}},qs=Symbol.for("@netrodev/hxf-tui/layout-node");function Vl(e){if(typeof e!="object"||e===null)return;let t=e[qs];return typeof t=="function"?t.call(e):void 0}var Vn=El(Rl);async function Ks(e){try{let{stdout:t}=await Vn("git",["-C",e,"rev-parse","--abbrev-ref","HEAD"],{encoding:"utf8"}),n=t.trim();if(!n||n==="HEAD")return"";let{stdout:r}=await Vn("git",["-C",e,"status","--porcelain"],{encoding:"utf8"});return`git:(${n}${r.trim()?"*":""})`}catch{return null}}var zn=class{folder;model;git;percent=0;meter=new wt(0);activity=xs();live=!1;activitySince=Date.now();thinking="medium";ceiling=void 0;usage="";cost=0;skipPermissions=!1;constructor(t,n){this.folder=_l(t),this.model=n.split("/").at(-1)||"no-model",this.git=""}invalidate(){}settling(){return this.meter.moving}atCeiling(){return this.ceiling!==void 0&&this.thinking===this.ceiling}levelChangedAt=0;setThinking(t){t!==this.thinking&&(this.thinking=t,this.levelChangedAt=Date.now())}levelFlashAmount(){return this.levelChangedAt===0?0:Ct(Date.now()-this.levelChangedAt)}flashing(){return this.levelFlashAmount()>0}levelText(t){if(this.atCeiling())return Li(this.thinking,Ji,t);let n=this.levelChangedAt===0?Number.POSITIVE_INFINITY:t-this.levelChangedAt;return Ct(n)<=0?rs(this.thinking,this.thinking):Oi(this.thinking,{rest:St(this.thinking),lit:Zi(this.thinking)},1-Ct(n))}meterValue(){return this.meter.value!==this.percent&&this.meter.set(this.percent),this.meter.step()}beginRun(){this.live=!0,this.activitySince=Date.now()}waitedMs(){return Date.now()-this.activitySince}abandonAnimations(){this.meter.snap(this.percent)}render(t){let n=Date.now(),r=this.percent===0&&this.meter.value===0?0:this.meterValue(),i=this.levelText(n),u=ss(this.model,i,this.folder,this.git),f=[Re(`${as(u,this.live?Be():"",this.live?this.waitedMs():void 0)} ${ls(r,this.usage,cs(this.cost))}`,t)];this.skipPermissions&&f.push(Re(O("Permissions OFF \u2014 critical commands and the repeat guard are not enforced",T.bad),t));let h=Gr();h&&f.push(Re(O(h,T.warn),t));let w=jr(ht());w&&f.push(Re(O(w,T.accent),t));let x=As(this.activity,Be(),n),M=this.live?Ni(x,{base:Sn(this.waitedMs(),T.mute,T.warn,T.bad),bright:T.text,charMs:45},n):O(x,Sn(this.waitedMs(),T.mute,T.warn,T.bad));return f.push(Re(M,t)),f}},Yn=class{constructor(t){this.draw=t}draw;render(t){return this.draw(t)}invalidate(){}},Xn=class{constructor(t,n){this.editor=t;this.hud=n}editor;hud;focused=!1;invalidate(){this.editor.invalidate()}render(t){let n=Math.max(10,t-4),r=this.editor.render(n).filter(h=>Pt(h)>0),i=r.length>0?r:[""],u="\u2500".repeat(Math.max(0,t-2)),f=i.map(h=>{let w=Math.max(0,n-Pt(h));return`\u2502 ${h}${" ".repeat(w)} \u2502`});return[`\u250C${u}\u2510`,...f,`\u2514${u}\u2518`,...this.hud.render(t)]}handleInput(t){this.editor.handleInput(t)}};function zl(e,t,n,r=!1,i=[]){let u=Math.max(24,n),f=u-4,h=(L,X)=>{let pe=Pt(L)>f?Re(L,f,"\u2026"):L,Q=`${pe}${" ".repeat(Math.max(0,f-Pt(pe)))}`;return`\u2502 ${X?X(Q):Q} \u2502`},w="\u2500".repeat(u-2),x=[h(` ${t}`),...e.render(f).map(L=>h(L))];x.push(h(" type to filter \xB7 \u2191\u2193 move \xB7 enter select \xB7 esc cancel"));let M=i.flatMap(L=>L===""?[""]:Bl(L,f)),j=M.length>0?[h(""),...M.map(L=>h(L,X=>O(X,T.mute)))]:[];if(!r)return["",`\u250C${w}\u2510`,...x,...j,`\u2514${w}\u2518`];let D=_i(T.line,T.warn,Date.now(),1400),W=O("\u2502",D),I=(L,X)=>O(`${L}${w}${X}`,D),U=[...x,...j].map(L=>`${W}${L.slice(1,-1)}${W}`);return["",I("\u250C","\u2510"),...U,I("\u2514","\u2518")]}function Yl(e,t){let n=t.split(`
23
- `).filter(Boolean),r=n.filter(f=>f.startsWith("Reason:")),i=n.filter(f=>!f.startsWith("Reason:")&&!f.startsWith("Allow tool:"));return[...e.endsWith(" wants to run")?[]:[e],...r,...i.length>0?["",...i]:[]]}function Me(e){let t=e.getContextUsage();if(t?.percent!==null&&t?.percent!==void 0)return Math.min(100,Math.round(t.percent));let n=e.model,i=[...e.state.messages].reverse().find(u=>u.role==="assistant")?.usage?.totalTokens;return!n||typeof i!="number"||!Number.isFinite(i)||n.contextWindow<=0?0:Math.min(100,Math.round(i/n.contextWindow*100))}function qn(e){let n=[["init","write project notes to AGENTS.md"],["model","choose a model"],["providers","list providers"],["thinking","set thinking level"],["approval","set what needs approval"],["settings","turn permission checks on or off"],["connect","sign in with email:password (or a base64 credential), or paste a key"],["sync","re-sync models from howtofix.id"],["usage","show the account's quota and what it has spent"],["update","install the newest release"],["login","save a provider API key"],["logout","remove a provider"],["new","start a new session"],["resume","resume another session"],["compact","compact the session"],["name","name this session"],["stats","session tokens and cost, cache hit rate and misses"],["rtk","compress long tool output before the model reads it"],["diff","show the working tree diff"],["commit","stage everything and commit"],["undo","undo the last commit"],["rewind","go back to an earlier message (Esc Esc)"],["review","ask the agent to review the diff"],["tools","list active tools"],["skills","list loaded skills"],["preset","browse, install and remove preset skill bundles"],["roblox","show RoToolbox activation, MCP and manager status"],["proxy","route requests through a proxy, or show the current one"],["export","write the transcript to a markdown file"],["copy","copy the last answer to the clipboard"],["agents","show spawned agents"],["goal","set or view this session's goal"],["plan","toggle plan mode (design before editing)"],["workflow","show or clear the pinned workflow panel"],["dcp","dynamic context pruning: on | off | status | blocks | stats | context | decompress <bN> | sweep"],["context","what the next request carries, and what pruning saved"],["decompress","reopen one compressed block, e.g. /decompress b2"],["sweep","close compressed blocks no ref resolves"],["session","show the current model"],["help","list commands"],["quit","quit"],["exit","quit (alias)"]].map(([r,i])=>({name:r,description:i}));for(let r of e.promptTemplates)n.push({name:r.name,description:r.description});for(let r of e.extensionRunner.getRegisteredCommands())n.push({name:r.invocationName,description:r.description});return n}function Jn(e,t){if(e!=="workflow")return;let n=Ge(t);if(!(typeof n.name!="string"||!Array.isArray(n.steps)))return n}function Xl(e,t){let n=Jn(e,t);return n?Et(n):void 0}function Et(e,t,n=!1){return r=>li(e,[],r,t?.selectedPhase,t?Jl(e,t,n):void 0)}function Jl(e,t,n){return{filter:r=>Is(r,t.filter),footerText:Ls(t,e.endedAt===void 0,n),filterLabel:_s(t.filter),drill:t.expanded}}function Zl(){let e=new Hs(Gs,{"tui.altScreen.pageUp":[],"tui.altScreen.pageDown":[],"tui.altScreen.halfPageUp":[],"tui.altScreen.halfPageDown":[],"tui.altScreen.top":[],"tui.altScreen.bottom":[]});Bs(e)}async function mu(e){let t=new Dl,n,r=new Kl(t,!0,void 0,{mouse:!0,onRightClickPaste:()=>n?.()}),i=new vt,u=new zn(e.cwd,e.modelLabel);u.skipPermissions=mn();let f=o=>{let s=Date.now();(async()=>{try{let a=Ye(),l=k.getSessionStats().sessionId;if(!io){io=!0;try{await hi(a,{keep:l})}catch{}}let d=await fi(a,l,o);d&&s>=jt&&(ro=d,jt=s)}catch{}})()},h=(o=!1)=>{!o&&!u.live||Ks(e.cwd).then(s=>{s!==null&&(u.git=s,$())})},w=new jl(r,Us,{paddingX:1}),x=new Map,M=(o,s)=>{s===void 0?x.delete(o):typeof s=="function"?x.set(o,s):x.set(o,()=>s)},j=()=>Math.max(20,t.columns),D,W=0,I=Rs(),U,L=null,X=!1,pe,Q=!1,Vs,It=()=>{!U||!X||M("workflow",o=>Et(U,I,Q)(o))},Zn=()=>{U&&(pe=U.name),X=!1,Q=!1,M("workflow",void 0)};ci({onStop:o=>{L=o},isPaused:()=>I.paused});let Qn=o=>{if(pe===o.name)return;D=o;let s=o.endedAt??Date.now();W=Math.max(W,s+ii),U=o,X=!0,M("workflow",a=>Et(o,I,Q)(a))},eo=new Xn(w,u),k=e.session,to=e.setCompressToolOutput,no=!1,_t=()=>{let o=k.getSessionStats().cost;return u.cost=o,o},Ot=rr(e.maxBudgetUsd),oo=!1,zs=()=>{let o=Ot.check(_t());o===void 0||oo||(oo=!0,k.isStreaming&&k.abort(),m("budget",ir(o.spent,o.limit)))},he=()=>{u.ceiling=Qi(k.model)},ge=$r(P),Lt,Ys=async()=>!ge||!kr(ge)||yr(ge)?!1:(Lt??=(async()=>{try{let o=await xr(P,ge);return o.renewed?(ge=o.credential,o.message&&m("connect",o.message),await k.modelRuntime.setRuntimeApiKey("howtofix",o.credential.accessToken),!0):(o.message&&m("connect",o.message),!1)}catch{return!1}finally{Lt=void 0}})(),await Lt),Nt,Ye=()=>Nt??=di(e.cwd),ro,Ft="",jt=0,io=!1,be,Xs=()=>{let o=new Set(["session_info","usage","label","context_edit","custom","model_change","thinking_level_change"]),s=[],a=l=>{for(let d of l)o.has(d.entry.type)||s.push(d.entry.id),a(d.children)};return a(k.sessionManager.getTree()),s},so=!1,Js=()=>{if(so)return;so=!0;let o=Ws().getResolvedBindings();Bs(new Hs(Gs,{...o,"app.tree.foldOrUp":["alt+left","ctrl+left"],"app.tree.unfoldOrDown":["alt+right","ctrl+right"],"app.tree.editLabel":["shift+l"],"app.tree.toggleLabelTimestamp":["shift+t"],"app.message.copy":["ctrl+x"],"app.tree.filter.default":["alt+0"],"app.tree.filter.noTools":["alt+1"],"app.tree.filter.userOnly":["alt+2"],"app.tree.filter.labeledOnly":["alt+3"],"app.tree.filter.all":["alt+4"],"app.tree.filter.cycleForward":["alt+f"],"app.tree.filter.cycleBackward":["alt+shift+f"]}))},ao=!1,Zs=()=>{ao||(ao=!0,ql())},lo=()=>{let o=k.sessionManager.getTree();if(o.length===0){m("rewind","nothing to rewind to yet");return}Ye().disabled&&m("rewind","conversation rewind only; this directory is not a git repository"),Zs(),Js();let s=Math.max(8,Math.floor(t.rows*.6)),a=new Gl(o,k.sessionManager.getLeafId(),s*2,l=>{Dt(),Qs(l)},()=>Dt());if(!a.getTreeList().getSelectedNode()){m("rewind","nothing to rewind to yet");return}be=a,be.focused=!0,M("rewind",l=>be?.render(l)??[]),$()},Dt=()=>{be=void 0,M("rewind",void 0),$()},Qs=async o=>{let s=Ye(),l=k.getUserMessagesForForking().findIndex(c=>c.entryId===o),d=l>=0?ui(s,k.getSessionStats().sessionId)[l]:void 0,y=d?(await pi(s,d)).length:0;if(y===0){await co(o,void 0,"conversation");return}_(`Rewind to this point? ${y} file(s) differ`,[{value:"both",label:"conversation and code",description:`drop the messages after this point and restore ${y} file(s)`},{value:"conversation",label:"conversation only",description:"drop the messages after this point, leave the files alone"},{value:"code",label:"code only",description:`restore ${y} file(s), keep the conversation`}],c=>{co(o,d,c)})},co=async(o,s,a)=>{let l=[];if((a==="both"||a==="conversation")&&!k.isStreaming)try{let d=await k.navigateTree(o);if(d.cancelled){m("rewind","conversation rewind cancelled");return}l.push("conversation rewound"),i.items=xt(k.state.messages),d.editorText&&(w.setText(d.editorText),l.push("prompt restored to the editor"))}catch(d){H(`conversation rewind failed: ${d instanceof Error?d.message:String(d)}`);return}if((a==="both"||a==="code")&&s){let d=await mi(Ye(),s);if(!d.ok){H(`code rewind failed: ${d.output}`);return}l.push(d.output),d.removed.length>0&&l.push(`removed ${d.removed.length} file(s)`),h()}m("rewind",l.join(`
24
- `)||"nothing to do"),$()};h(!0),f("session start"),e.note&&i.items.push({id:"note",kind:"note",title:"note",body:e.note}),i.items.push(...xt(k.state.messages)),u.percent=Me(k),_t(),u.abandonAnimations(),u.setThinking(k.thinkingLevel),he(),w.setAutocompleteProvider(new Ds(qn(k),e.cwd)),us(k).then(o=>{o&&(u.usage=o,r.requestRender())});let uo=async o=>{let{checkForUpdate:s,checkFailedNote:a,installUpdate:l}=await import("./chunk-7CHDNTH6.js"),d=await s(o.current);if(!d.available){let c=a(d);c?m("update",c):o.install&&m("update",d.message);return}if(!o.install){m("update",`${d.message}. run /update to install it.`);return}C("note",`installing HowToFix ${d.latest}\u2026`);let y=await l({version:d.latest});C("note",void 0),m("update",y.message),$()};e.update&&uo(e.update);let re=null,fo="",mo=!1,po=[],Ee,Wt=()=>{},$=()=>{Wt(),r.requestRender()},C=(o,s)=>{u.activity=Ss(u.activity,o,s)},Ut=o=>{u.activity=Cs(u.activity,o)},Xe=new Map,Kt=new Set,ea=()=>[...Xe].map(([o,s])=>`${Kt.has(o)?"!":"\u2713"} ${o} \xD7${s}`).join(" | "),ta=()=>{let o=ea();C("tally",o||void 0)},_=(o,s,a,l,d=!1,y=[])=>{let c=new Ul(s,8,Us.selectList);c.onSelect=p=>{re=null,Ee=void 0,a(p.value)},c.onCancel=()=>{re=null,Ee=void 0,l?.(),$()},Ee=()=>c.onCancel?.(),fo=o,mo=d,po=y,re=c,bo+=1,$()},m=(o,s)=>{i.items=qi(i.items,{id:`cmd-${Date.now()}-${i.items.length}`,kind:"note",title:o,body:s}),C("tally",void 0),$()};Zr(o=>{o.background&&m("agent",`${Vr(o)}
25
- read it with /agents ${o.id}`)});let Ht=!1,na=o=>{Ht||(Ht=!0,(async()=>{try{let s=(await k.modelRuntime.getAvailable()).filter(b=>se(b.provider)),a=new Set(s.map(b=>b.provider)),l=ye.find(b=>a.has(b)),d=l?(await k.modelRuntime.getAuth(l))?.auth?.apiKey:void 0;if(!d)return;let y=bt(s.map(b=>b.id)),{live:c,probed:p}=await hr(y,d,{exclude:o,limit:4});if(c.length===0)return;let g=re===null;m("gateway",`${c.length} of ${p.length} probed models answer right now (${c.join(", ")}); ${g?"the model picker is open below":"switch with /model"}.`),g&&Ne("/model")}catch{}finally{Ht=!1}})())},H=o=>{i.items.push({id:`err-${Date.now()}-${i.items.length}`,kind:"error",title:"failed",body:o});let s=ki(o);s!==void 0&&m("gateway",s);let a=yi(o);a!==void 0&&na(a),C("tally",void 0),$()},Pe=o=>{k.setThinkingLevel(o,{persist:!0}),u.setThinking(o),he(),C("note",`thinking ${o}`),$()};Rr((o,s)=>{let{promise:a,resolve:l}=Promise.withResolvers();return _(o,[{value:"allow",label:"allow"},{value:"deny",label:"deny"}],d=>l(d==="allow"),()=>l(!1),!0,Yl(o,s)),a});let Bt=new Map,ho=o=>{let s=Fs({select:(a,l)=>{let{promise:d,resolve:y}=Promise.withResolvers();return _(a,l.map(c=>({value:c,label:c})),y,()=>y(void 0)),d},confirm:(a,l)=>{let{promise:d,resolve:y}=Promise.withResolvers();return _(`${a} \u2014 ${l}`,[{value:"yes",label:"yes"},{value:"no",label:"no"}],c=>y(c==="yes"),()=>y(!1)),d},input:a=>{let{promise:l,resolve:d}=Promise.withResolvers();return C("prompt",a),$(),ne=y=>{ne=void 0,C("prompt",void 0),d(y),$()},l},notify:(a,l)=>{l==="error"?H(a):m("mcp",a)},setStatus:(a,l)=>{l===void 0?Bt.delete(a):Bt.set(a,l),C("note",[...Bt.values()].join(" | ")||void 0),$()},setWidget:(a,l)=>{M(a,l),$()}});o.bindExtensions({uiContext:s,mode:"print",onError:a=>H(`${a.event}: ${a.error}`)}).catch(a=>H(a instanceof Error?a.message:String(a)))};ho(k);let ve=new Fl,oa={invalidate:()=>i.invalidate(),render:o=>{let s=ve.render(Math.max(20,o)).length;return i.viewportHeight=Math.max(1,Math.max(8,t.rows)-s),i.render(o)},handleMouse:o=>{if(Mo(o))return tt(),{handled:!0};let s=o.type==="wheel"?o.wheelDelta??0:0;if(s!==0)return i.scrollOffset=Math.max(0,i.scrollOffset-s*3),$(),{handled:!0}}},ra=new Wl(oa,{follow:"none",overscroll:"contain"}),Je=new Hl([{component:ra,grow:1,shrink:1},{component:ve,grow:0,shrink:0,basis:"auto"}]),go="",bo=0,ia=()=>`${re?`picker:${bo}`:"dock"}|${[...x.keys()].join(",")}`;Wt=()=>{let o=ia();if(o===go)return;go=o,ve.clear();for(let a of x.values())ve.addChild(new Yn(a));let s=re;if(s){let a=fo,l=mo,d=po;ve.addChild({render:y=>zl(s,a,y,l,d),invalidate:()=>{}})}else ve.addChild(eo);Je.invalidate()},Wt();let wo={focused:!1,invalidate(){i.invalidate(),eo.invalidate(),re?.invalidate(),Je.invalidate()},[qs]:()=>Vl(Je),render:o=>Je.render(o),handleMouse(o){if(Mo(o))return tt(),{handled:!0}},handleInput(o){w.handleInput(o)}};r.setLayoutRoot(wo),r.setFocus(wo);let z=0,ce="",Gt=!1,we=!1,qt,xe="",yo=0,Ie=!1,Ze=Date.now(),Qe=!1,et=new Map,ko=()=>{let o=new Set(k.getSteeringMessages().map(s=>s.trim()).filter(Boolean));for(let s of i.items)s.kind!=="user"||!s.pending||o.has(s.body.trim())||(s.pending=void 0)},$o=o=>{if(o.type==="agent_start"&&ko(),o.type==="agent_start"||o.type==="turn_start")o.type==="agent_start"&&Tr(),u.live||u.beginRun(),ce="",we=!1,Ie=!1,Ze=Date.now(),xe="";else if(o.type==="message_update"&&o.assistantMessageEvent.type==="thinking_delta"){we=!0,xe===""&&(yo=Date.now()),xe+=o.assistantMessageEvent.delta;let s=`think-${z}`,a=i.items.find(d=>d.id===s),l=xe.split(`
21
+ ${r}`:r}):n.errorMessage&&t.push({id:`e-${n.timestamp}`,kind:"error",title:"failed",body:n.errorMessage}),i.forEach((f,h)=>{let w=u[h];t.push({id:w?`tool-${w}`:`c-${n.timestamp}-${h}`,kind:"tool",title:f.name,body:$e(f.name,f.arguments),...w?{call:$e(f.name,f.arguments)}:{}})})}else if(n.role==="toolResult"){let r=$t(n.toolName,{content:n.content},n.isError),i=t.find(u=>u.id===`tool-${n.toolCallId}`);i?(i.kind="result",i.body=r,i.title=n.toolName):t.push({id:`r-${n.toolCallId}`,kind:"result",title:n.toolName,body:r})}return Ga(t)}function qi(e,t,n){return Ka(e,Math.max(8,t)).map(r=>O(r,n))}var qe=new Map;function qa(e){let t=e.body||" ",n=qe.get(e.id);if(n)return n.text!==t&&(n.component.setText(t),n.text=t),n.component;let r=new Ua(t,0,0,ii);return qe.set(e.id,{text:t,component:r}),r}var _n=class{constructor(t){this.item=t}item;invalidate(){}shade(t){let n=Date.now()-(this.item.born??0);return fe(T.dim,t,Ii(n,Cn))}render(t){let n=this.item.body;if(this.item.kind==="user"){let i=this.item.pending?[O(" queued \u2014 the run reads this at its next step",T.dim)]:[];return["",...qi(`> ${n}`,t,this.shade(T.user)),...i]}if(this.item.kind==="tool")return[O(`${Be()} ${n}`,this.shade(T.tool))];if(this.item.kind==="collapsed"){let i=[O(`${kt} ${n}`,this.shade(T.mute))],u=this.item.full??[];if(u.length>0)if(this.item.expanded===!0)for(let f of u)i.push(O(` ${f}`,this.shade(T.dim)));else i.push(O(` ${u.length} call(s) \xB7 ctrl+e to expand`,T.dim));return i}if(this.item.kind==="result"){let i=n.startsWith("exit ")&&n!=="exit 0";if(this.item.panel)return["",...this.item.panel(t),...n?[O(` ${Rn} ${n}`,i?T.bad:T.mute)]:[]];let u=[];this.item.call&&u.push(O(this.item.call,this.shade(T.tool)));let f=` ${Rn} ${n}`;if(u.push(O(f,i?T.bad:this.shade(T.mute))),this.item.expanded===!0&&(this.item.full?.length??0)>0){let M=O(` ${this.item.full.length} line(s) \xB7 ctrl+e to collapse`,T.dim);u.push(O(` ${kt}`,T.dim));for(let j of this.item.full){let D=j.startsWith("+")?T.tool:j.startsWith("-")?T.bad:T.dim;u.push(O(` ${j}`,D))}return u.push(M),u}let w=this.item.detail??[],x=An(Date.now()-(this.item.born??0),w.length);for(let M of w.slice(0,x)){let j=M.startsWith("+")?T.tool:M.startsWith("-")?T.bad:T.dim;u.push(O(` ${M}`,this.shade(j)))}return(this.item.full?.length??0)>0&&u.push(O(` ${kt} ${this.item.full.length} line(s) \xB7 ctrl+e to expand`,T.dim)),u}if(this.item.kind==="error"||this.item.kind==="note"){let i=this.item.kind==="error"?T.bad:T.mute;return["",...qi(n,t,this.shade(i))]}return["",...qa(this.item).render(Math.max(8,t-2))]}},vt=class{items=[];status="";scrollOffset=0;scrollAnchor;settledOffset=0;viewportHeight=0;invalidate(){}entering(){let t=Date.now();return this.items.some(n=>{if(n.born===void 0)return!1;let r=t-n.born;return _i(r,Cn)?!0:(n.detail?.length??0)>An(r,n.detail?.length??0)})}render(t){if(qe.size>this.items.length){let i=new Set(this.items.map(u=>u.id));for(let u of qe.keys())i.has(u)||qe.delete(u)}let n=[];for(let i of this.items)i.born??=Date.now(),n.push(...new _n(i).render(t));this.status&&n.push(O(this.status,T.mute));let r=this.viewportHeight;if(r>0&&n.length>r){let i=n.length-r;this.scrollOffset!==this.settledOffset&&(this.scrollAnchor=void 0);let u=this.scrollAnchor,f;if(u!==void 0){let h=n.length-u;h>=0&&h<=i?f=h:f=Math.max(0,Math.min(this.scrollOffset,i))}else f=Math.max(0,Math.min(this.scrollOffset,i));return u===void 0&&(this.scrollOffset=f),this.settledOffset=this.scrollOffset,f===0?this.scrollAnchor=void 0:this.scrollAnchor===void 0&&(this.scrollAnchor=n.length-f),n.slice(i-f,i-f+r)}return n}};import{parseColor as Z}from"@netrodev/hxf-tui";var pe={off:Z("okhsl(230 12% 46%)"),minimal:Z("okhsl(240 55% 49%)"),low:Z("okhsl(252 60% 55%)"),medium:Z("okhsl(270 64% 60%)"),high:Z("okhsl(298 70% 64%)"),xhigh:Z("okhsl(332 80% 66%)"),max:Z("okhsl(42 95% 64%)")},Xi={off:Z("okhsl(230 14% 64%)"),minimal:Z("okhsl(240 60% 64%)"),low:Z("okhsl(252 64% 68%)"),medium:Z("okhsl(270 68% 72%)"),high:Z("okhsl(298 74% 76%)"),xhigh:Z("okhsl(332 82% 78%)"),max:Z("okhsl(42 96% 76%)")};function St(e){return pe[e]??pe.medium}var Zi=[pe.minimal,pe.low,pe.medium,pe.high,pe.xhigh,pe.max];function Qi(e){return Xi[e]??Xi.medium}var Ji=460;function Ct(e){return!Number.isFinite(e)||e<0||e>=Ji?0:1-e/Ji}var B=["off","minimal","low","medium","high","xhigh","max"];function es(e){let t=e?.thinkingLevelMap;if(t===void 0)return B[B.length-1];for(let n=B.length-1;n>=0;n-=1)if(typeof t[B[n]]=="string")return B[n]}function ts(e){let t=B.indexOf(e);return B[(t+1+B.length)%B.length]}function ns(e){let t=B.indexOf(e);return B[(t-1+B.length)%B.length]}import{mkdirSync as Xa,readFileSync as Ja}from"node:fs";import{dirname as Za}from"node:path";var Ln="\x1B[0m",G="\x1B[2m",Va="\x1B[1m",za="\x1B[31m",Nn="\x1B[32m",rs="\x1B[33m",os="\x1B[35m",On="\x1B[36m";function F(e,t){return`${t}${e}${Ln}`}function is(e,t){return O(e,St(t))}function ss(e){return e>=85?za:e>=70?rs:Nn}var Ya="\u2726";function as(e,t,n,r){let i=F(`[${e}]`,On),u=`${F(Ya,G)} ${t}`,f=F(n,rs),h=r?` ${F("git:(",os)}${F(r.replace(/^git:\(/,"").replace(/\)$/,""),On)}${F(")",os)}`:"";return`${i}${F(" \u2502 ",G)}${u}${F(" \u2502 ",G)}${f}${h}`}function ls(e,t,n){if(!t)return e;let r=n===void 0?t:`${t} ${F(li(n),G)}`;return`${F(r,On)} ${F("\u2502",G)} ${e}`}function cs(e,...t){let n=Number.isFinite(e)?Math.min(100,Math.max(0,e)):0,r=Math.round(n/10),i=ss(n),u=`${i}${"\u2588".repeat(r)}${G}${"\u2591".repeat(10-r)}${Ln}`,f=F(`${Math.round(n)}%`,i),h=t.filter(Boolean).join(F(" \u2502 ",G));return`${F("Context",G)} ${u} ${f}${h?`${F(" \u2502 ",G)}${h}`:""}`}function ds(e){return!Number.isFinite(e)||e<=0?"":`${F("Spent",G)} ${F(`$${e.toFixed(3)}`,Nn)}`}function us(e,t,n,r){let i=Number.isFinite(t)&&t>0?t:0,u=Number.isFinite(n)?Math.max(0,n):0,f=Math.max(0,i-u),h=i>0?Math.min(100,u/i*100):0,w=Math.round(h/10),x=ss(h),M=`${x}${"\u2588".repeat(w)}${G}${"\u2591".repeat(10-w)}${Ln}`,j=D=>`${D.toFixed(2)} ${r}`;return[`${F(e,Va)}${F(" account",G)}`,` ${F("used",G)} ${M} ${F(`${h.toFixed(1)}%`,x)}`,` ${F("granted",G)} ${j(i)}`,` ${F("spent",G)} ${j(u)}`,` ${F("remaining",G)} ${F(j(f),x)}`]}function Fn(e,t,n){let r=n===null?"":F(` ${n}ms`,G),i=t&&t!=="USD"?`${t} `:"";return`${F("Balance",G)} ${F(`${i}${e}`,Nn)}${r}`}var jn=nr,Qa=18e4;async function el(e){let t=new Set((await e.modelRuntime.getAvailable()).map(i=>i.provider).filter(i=>re(i))),n=ye.find(i=>t.has(i));return n?(await e.modelRuntime.getAuth(n))?.auth?.apiKey:void 0}function tl(){try{let e=JSON.parse(Ja(jn,"utf8"));return!e.data||typeof e.cachedAt!="number"?void 0:{data:e.data,cachedAt:e.cachedAt}}catch{return}}function At(e){if(e.unlimited)return Fn("unlimited","",e.latencyMs);let n=e.unit==="USD"||e.unit==="CNY"?`$${e.remaining.toFixed(2)}`:`${e.remaining.toLocaleString()}`;return Fn(n,e.unit,e.latencyMs)}async function fs(e){let t=tl();if(t&&Date.now()-t.cachedAt<Qa)return At(t.data);let n=await el(e);if(!n)return t?At(t.data):void 0;let r=Date.now(),i=await Ae(n,{timeoutMs:3e3});if(!i.ok)return t?At(t.data):void 0;let u={remaining:i.remaining??0,limit:i.limit??0,unit:i.unit,unlimited:i.unlimited,latencyMs:Date.now()-r};return Xa(Za(jn),{recursive:!0}),se(jn,JSON.stringify({data:u,cachedAt:Date.now()})),At(u)}import{chmodSync as nl,existsSync as ol,readFileSync as rl}from"node:fs";import{join as il}from"node:path";function ps(e){return il(e,"account-credential.json")}function ms(e,t){return Buffer.from(`${e}:${t}`,"utf8").toString("base64")}function Dn(e){let t=e.trim();if(!t)return null;let n=i=>{let u=i.indexOf(":");return u<=0||u===i.length-1?null:{username:i.slice(0,u),password:i.slice(u+1)}},r=n(t);if(r)return r;try{let i=Buffer.from(t,"base64").toString("utf8");return i.includes(":")?n(i):null}catch{return null}}function hs(e,t,n){try{let r={credential:ms(t,n),username:t,savedAt:Math.floor(Date.now()/1e3)},i=ps(e);return se(i,JSON.stringify(r,null,2)),nl(i,384),!0}catch{return!1}}function gs(e){try{let t=ps(e);if(!ol(t))return null;let n=JSON.parse(rl(t,"utf8"));return!n?.credential||!n?.username?null:n}catch{return null}}async function sl(e,t){let n=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t),signal:AbortSignal.timeout(2e4)}),r=await n.text(),i;try{i=JSON.parse(r)}catch{throw new Error(`the panel answered ${n.status} with something that is not JSON`)}let u=i;if(!n.ok||u.success===!1)throw new Error(u.message||`the panel answered ${n.status}`);return u.data}async function bs(e,t,n,r){let i=await sl(`${e}/api/auth/cli/credential`,{credential:ms(t,n),client_info:r});if(!i?.token)throw new Error("the panel accepted the credential but returned no key");return{token:i.token}}import{execFileSync as al}from"node:child_process";import{createHash as ll}from"node:crypto";import{readFileSync as cl}from"node:fs";import{arch as dl,hostname as ul,platform as ws}from"node:os";function fl(e){try{return cl(e,"utf8").trim()}catch{return""}}function ys(e,t){try{return al(e,t,{encoding:"utf8",timeout:3e3})}catch{return""}}function pl(){return ys("reg",["query","HKLM\\SOFTWARE\\Microsoft\\Cryptography","/v","MachineGuid"]).match(/MachineGuid\s+REG_SZ\s+([0-9a-fA-F-]+)/)?.[1]??""}function ml(){return ys("ioreg",["-rd1","-c","IOPlatformExpertDevice"]).match(/"IOPlatformUUID"\s*=\s*"([^"]+)"/)?.[1]??""}function hl(){return["/sys/class/dmi/id/product_uuid","/sys/class/dmi/id/board_serial","/sys/class/dmi/id/product_serial","/etc/machine-id","/var/lib/dbus/machine-id"].map(fl).filter(Boolean)}function gl(){switch(ws()){case"win32":{let e=pl();return e?[e]:[]}case"darwin":{let e=ml();return e?[e]:[]}default:return hl()}}var Tt;function ks(){if(Tt)return{id:Tt,weak:!1};let e=gl(),t=e.length===0,n=[ws(),dl(),...e,t?ul():""].join("|");return Tt=ll("sha256").update(n).digest("hex").slice(0,32),{id:Tt,weak:t}}var bl="/cli/checkin",wl=["Bearer",""].join(" ").trim(),yl=5e5;function Wn(e){return`$${(e/yl).toFixed(2)}`}async function $s(e,t,n,r,i){let u=new AbortController,f=setTimeout(()=>u.abort(),i);try{let h=await r(`${n}${bl}`,{method:t,headers:{[sr]:ar(),"X-HowToFix-Device":ks().id,Authorization:`${wl} ${e}`},signal:u.signal}),w={};try{w=await h.json()}catch{}return{status:h.status,body:w}}finally{clearTimeout(f)}}async function Un(e,t){let n=(t?.baseUrl??"https://api.howtofix.id/v1").replace(/\/+$/,""),r=t?.fetchImpl??fetch,i=t?.timeoutMs??1e4,u=e.trim();if(!u)return{ok:!1,enabled:!1,checkedInToday:!1,quotaToday:0,message:"no token given"};try{let{status:f,body:h}=await $s(u,"GET",n,r,i);if(f===401||f===403)return{ok:!1,enabled:!1,checkedInToday:!1,quotaToday:0,message:"the gateway rejected that token for the check-in status"};if(f>=400||h.success!==!0)return{ok:!1,enabled:!1,checkedInToday:!1,quotaToday:0,message:typeof h.message=="string"?h.message:`the gateway answered ${f}`};let w=h.data??{};return{ok:!0,enabled:w.enabled===!0,checkedInToday:w.checked_in_today===!0,quotaToday:Number(w.quota_today??0)||0,message:""}}catch(f){return{ok:!1,enabled:!1,checkedInToday:!1,quotaToday:0,message:f instanceof Error&&f.name==="AbortError"?"the gateway did not answer the check-in in time":"could not reach the gateway"}}}async function vs(e,t){let n=(t?.baseUrl??"https://api.howtofix.id/v1").replace(/\/+$/,""),r=t?.fetchImpl??fetch,i=t?.timeoutMs??15e3,u=e.trim();if(!u)return{ok:!1,alreadyClaimed:!1,blocked:!1,quotaAwarded:0,message:"no token given"};try{let{status:f,body:h}=await $s(u,"POST",n,r,i);if(h.success===!0){let j=h.data??{};return{ok:!0,alreadyClaimed:!1,blocked:!1,quotaAwarded:Number(j.quota_awarded??0)||0,message:""}}let w=typeof h.message=="string"?h.message:`the gateway answered ${f}`,x=/device already claimed|account blocked|appeal/i.test(w);return{ok:!1,alreadyClaimed:!x&&/签到|check-?in|already|今日/.test(w)&&!/not enabled/i.test(w),blocked:x,quotaAwarded:0,message:w}}catch(f){return{ok:!1,alreadyClaimed:!1,blocked:!1,quotaAwarded:0,message:f instanceof Error&&f.name==="AbortError"?"the gateway did not answer the check-in in time":"could not reach the gateway"}}}function kl(e){return!e||!Number.isFinite(e)||e<=0?"":e>=1e6?`${Number((e/1e6).toFixed(1))}M`:e>=1e3?`${Math.round(e/1e3)}K`:String(e)}function $l(e){if(!e)return"";if(e.input<=0&&e.output<=0)return"free";let t=n=>n===0?"0":String(Number(n>=1?n.toFixed(2):n.toFixed(3)));return`$${t(e.input)}/$${t(e.output)} per M`}function xs(e){let t=kl(e.contextWindow),n=$l(e.cost);return[t?`${t} ctx`:"",n].filter(Boolean).join(" \xB7 ")}function Ss(){return{}}function Cs(e,t,n,r=Date.now()){let i={...e};return t==="run"?(n===void 0||n===""?delete i.run:i.run={label:n,since:e.run?.since??r},i):(n===void 0||n===""?delete i[t]:i[t]=n,i)}function As(e,t){let n={...e};return t===void 0?delete n.retry:n.retry=t,n}function vl(e){let t=Math.max(0,Math.round(e/1e3)),n=Math.floor(t/60);return n>0?`${n}m ${String(t%60).padStart(2,"0")}s`:`${t}s`}function Kn(e,t=72){let n=e.split(`
22
+ `).map(r=>r.trim()).find(r=>r!=="")??"";return n.length>t?`${n.slice(0,t-1)}\u2026`:n}function xl(e,t){let n=Math.max(0,Math.ceil((e.until-t)/1e3)),r=n>0?`in ${n}s`:"now",i=`retry ${e.attempt}/${e.maxAttempts} ${r}`,u=Kn(e.error);return u===""?i:`${i} \xB7 ${u}`}function Ts(e,t,n=Date.now()){return e.prompt?`? ${e.prompt}`:e.retry?`* ${xl(e.retry,n)}`:e.note?`* ${e.note}`:e.run?`${t} ${e.run.label} \xB7 ${vl(n-e.run.since)}`:e.tally?e.tally:""}import{spawn as Sl}from"node:child_process";function Cl(e){switch(e){case"darwin":return{command:"open",args:[]};case"win32":return{command:"cmd",args:["/c","start",""]};case"linux":return{command:"xdg-open",args:[]};default:return}}async function Ve(e,t=process.platform){let n=Cl(t);return n?new Promise(r=>{try{let i=Sl(n.command,[...n.args,e],{detached:!0,stdio:"ignore"});i.once("error",()=>r(!1)),i.once("spawn",()=>{i.unref(),r(!0)})}catch{r(!1)}}):!1}function Ms(e){return e instanceof Error?e.message:String(e)}var ze=class{active;apply;report;pending;running;constructor(t){this.active=new Set(t.initial??[]),this.apply=t.apply,this.report=t.report??(n=>console.error(n))}activeServers(){return[...this.active]}reconcile(t){return this.pending=new Set(t),this.running?this.running:(this.running=this.drain().finally(()=>{this.running=void 0}),this.running)}async drain(){let t={added:[],removed:[],unchanged:[],problems:[]};for(;this.pending!==void 0;){let r=this.pending;this.pending=void 0;let i=await this.applyOnce(r);t.added.push(...i.added),t.removed.push(...i.removed),t.unchanged.push(...i.unchanged),t.problems.push(...i.problems)}let n=this.active;return t.added=t.added.filter(r=>n.has(r)),t.removed=[...new Set(t.removed.filter(r=>!n.has(r)))],t.added=[...new Set(t.added)],t.unchanged=[...new Set(t.unchanged.filter(r=>n.has(r)))],t}async applyOnce(t){let n=[...t].filter(u=>!this.active.has(u)),r=[...this.active].filter(u=>!t.has(u)),i=[...t].filter(u=>this.active.has(u));if(n.length===0&&r.length===0)return{added:[],removed:[],unchanged:i,problems:[]};try{await this.apply(n,r)}catch(u){let f=`mcp reconciliation failed: ${Ms(u)}`;return this.report(f),{added:[],removed:[],unchanged:[],problems:[f]}}for(let u of n)this.active.add(u);for(let u of r)this.active.delete(u);return{added:n,removed:r,unchanged:i,problems:[]}}async dispose(){this.running&&await this.running.catch(()=>{});let t=[...this.active];if(t.length===0)return{added:[],removed:[],unchanged:[],problems:[]};try{return await this.apply([],t),this.active.clear(),{added:[],removed:t,unchanged:[],problems:[]}}catch(n){let r=`mcp teardown failed: ${Ms(n)}`;return this.report(r),{added:[],removed:[],unchanged:[],problems:[r]}}}};import{mkdirSync as Al}from"node:fs";import{join as Tl}from"node:path";import{matchesKey as Mt}from"@netrodev/hxf-tui";var Hn=["all","running","failed","done"];function Es(){return{selectedPhase:0,filter:"all",paused:!1,expanded:!1,follow:!0}}function Ps(e){if(Mt(e,"up"))return"up";if(Mt(e,"down"))return"down";if(Mt(e,"enter"))return"enter";if(Mt(e,"escape"))return"escape";if(e==="f")return"filter";if(e==="p")return"pause";if(e==="x")return"stop";if(e==="s")return"save"}function Rs(e,t,n){if(t.length===0)return e;let r=Math.max(0,Math.min(t.length-1,e.selectedPhase+n));return{...e,selectedPhase:r,follow:!1}}function Ml(e){let t=Hn.indexOf(e);return Hn[(t+1)%Hn.length]}function Is(e,t,n){switch(t){case"up":return Rs(e,n,-1);case"down":return Rs(e,n,1);case"enter":return{...e,expanded:!e.expanded};case"filter":return{...e,filter:Ml(e.filter)};case"pause":return{...e,paused:!e.paused};default:return e}}function _s(e,t){switch(t){case"running":return e.filter(n=>n.status==="running");case"failed":return e.filter(n=>n.status==="failed");case"done":return e.filter(n=>n.status!=="running");default:return[...e]}}function Os(e){return e==="all"?"":` \xB7 ${e}`}var Ls="ctrl+f";function Ns(e,t,n=!0){if(!n)return"Ctrl+F panel keys \xB7 Esc unpin";let r=["\u2191/\u2193 phase",e.expanded?"Enter collapse":"Enter drill in"];return r.push(e.expanded?"Esc back out":"Esc unpin"),r.push(`f filter${e.filter==="all"?"":` (${e.filter})`}`),t?(r.push(e.paused?"p resume":"p pause"),r.push("x stop")):e.paused&&r.push("p resume"),r.push("s save script"),e.paused&&r.unshift("paused"),r.join(" \xB7 ")}function Rl(e){let t=e.trim();if(!(!t||t.length>64)&&!(t==="."||t==="..")&&/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(t)&&!t.includes(".."))return t}function Fs(e,t){if(!e)return{ok:!1,reason:"this run was started from a file, so it is already saved where you pointed the tool"};let n=Rl(e.name);if(!n)return{ok:!1,reason:`"${e.name}" is not a usable filename, so the script was not written`};let r=Tl(t,`${n}.js`);try{Al(t,{recursive:!0}),se(r,e.code)}catch(i){return{ok:!1,reason:i instanceof Error?i.message:String(i)}}return{ok:!0,path:r}}function js(e){let t=()=>{};return{select:(n,r)=>e.select(n,r),confirm:(n,r)=>e.confirm(n,r),input:n=>e.input(n),notify:(n,r)=>e.notify(n,r),onTerminalInput:()=>t,setStatus:(n,r)=>e.setStatus(n,r),setWorkingMessage:t,setWorkingVisible:t,setWorkingIndicator:t,setHiddenThinkingLabel:t,setWidget:(n,r,i)=>{r!==void 0&&!Array.isArray(r)||e.setWidget?.(n,r,i?.placement)},setFooter:t,setHeader:t,setTitle:t,custom:async()=>{throw new Error("this screen has no custom component host; use the text commands instead")},pasteToEditor:t,setEditorText:t,getEditorText:()=>"",editor:async()=>{},addAutocompleteProvider:t,setEditorComponent:t,getEditorComponent:()=>{},theme:void 0,getAllThemes:()=>[],getTheme:()=>{},setTheme:()=>({success:!1,error:"themes are not available in the workbench"}),getToolsExpanded:()=>!1,setToolsExpanded:t}}var Ks={borderColor:()=>"",selectList:{selectedPrefix:e=>O(e,T.accent),selectedText:e=>O(e,T.text,{bold:!0}),description:e=>O(e,T.mute),scrollInfo:e=>O(e,T.dim),noMatch:e=>O(e,T.mute)}},Vs=Symbol.for("@netrodev/hxf-tui/layout-node");function zl(e){if(typeof e!="object"||e===null)return;let t=e[Vs];return typeof t=="function"?t.call(e):void 0}var Vn=Pl(El);async function Hs(e){try{let{stdout:t}=await Vn("git",["-C",e,"rev-parse","--abbrev-ref","HEAD"],{encoding:"utf8"}),n=t.trim();if(!n||n==="HEAD")return"";let{stdout:r}=await Vn("git",["-C",e,"status","--porcelain"],{encoding:"utf8"});return`git:(${n}${r.trim()?"*":""})`}catch{return null}}var zn=class{folder;model;git;percent=0;meter=new wt(0);activity=Ss();live=!1;activitySince=Date.now();thinking="medium";ceiling=void 0;usage="";cost=0;skipPermissions=!1;constructor(t,n){this.folder=Ol(t),this.model=n.split("/").at(-1)||"no-model",this.git=""}invalidate(){}settling(){return this.meter.moving}atCeiling(){return this.ceiling!==void 0&&this.thinking===this.ceiling}levelChangedAt=0;setThinking(t){t!==this.thinking&&(this.thinking=t,this.levelChangedAt=Date.now())}levelFlashAmount(){return this.levelChangedAt===0?0:Ct(Date.now()-this.levelChangedAt)}flashing(){return this.levelFlashAmount()>0}levelText(t){if(this.atCeiling())return Ni(this.thinking,Zi,t);let n=this.levelChangedAt===0?Number.POSITIVE_INFINITY:t-this.levelChangedAt;return Ct(n)<=0?is(this.thinking,this.thinking):Li(this.thinking,{rest:St(this.thinking),lit:Qi(this.thinking)},1-Ct(n))}meterValue(){return this.meter.value!==this.percent&&this.meter.set(this.percent),this.meter.step()}beginRun(){this.live=!0,this.activitySince=Date.now()}waitedMs(){return Date.now()-this.activitySince}abandonAnimations(){this.meter.snap(this.percent)}render(t){let n=Date.now(),r=this.percent===0&&this.meter.value===0?0:this.meterValue(),i=this.levelText(n),u=as(this.model,i,this.folder,this.git),f=[Re(`${ls(u,this.live?Be():"",this.live?this.waitedMs():void 0)} ${cs(r,this.usage,ds(this.cost))}`,t)];this.skipPermissions&&f.push(Re(O("Permissions OFF \u2014 critical commands and the repeat guard are not enforced",T.bad),t));let h=qr();h&&f.push(Re(O(h,T.warn),t));let w=Dr(ht());w&&f.push(Re(O(w,T.accent),t));let x=Ts(this.activity,Be(),n),M=this.live?Fi(x,{base:Sn(this.waitedMs(),T.mute,T.warn,T.bad),bright:T.text,charMs:45},n):O(x,Sn(this.waitedMs(),T.mute,T.warn,T.bad));return f.push(Re(M,t)),f}},Yn=class{constructor(t){this.draw=t}draw;render(t){return this.draw(t)}invalidate(){}},Xn=class{constructor(t,n){this.editor=t;this.hud=n}editor;hud;focused=!1;invalidate(){this.editor.invalidate()}render(t){let n=Math.max(10,t-4),r=this.editor.render(n).filter(h=>Pt(h)>0),i=r.length>0?r:[""],u="\u2500".repeat(Math.max(0,t-2)),f=i.map(h=>{let w=Math.max(0,n-Pt(h));return`\u2502 ${h}${" ".repeat(w)} \u2502`});return[`\u250C${u}\u2510`,...f,`\u2514${u}\u2518`,...this.hud.render(t)]}handleInput(t){this.editor.handleInput(t)}};function Yl(e,t,n,r=!1,i=[]){let u=Math.max(24,n),f=u-4,h=(L,X)=>{let me=Pt(L)>f?Re(L,f,"\u2026"):L,Q=`${me}${" ".repeat(Math.max(0,f-Pt(me)))}`;return`\u2502 ${X?X(Q):Q} \u2502`},w="\u2500".repeat(u-2),x=[h(` ${t}`),...e.render(f).map(L=>h(L))];x.push(h(" type to filter \xB7 \u2191\u2193 move \xB7 enter select \xB7 esc cancel"));let M=i.flatMap(L=>L===""?[""]:Gl(L,f)),j=M.length>0?[h(""),...M.map(L=>h(L,X=>O(X,T.mute)))]:[];if(!r)return["",`\u250C${w}\u2510`,...x,...j,`\u2514${w}\u2518`];let D=Oi(T.line,T.warn,Date.now(),1400),W=O("\u2502",D),I=(L,X)=>O(`${L}${w}${X}`,D),U=[...x,...j].map(L=>`${W}${L.slice(1,-1)}${W}`);return["",I("\u250C","\u2510"),...U,I("\u2514","\u2518")]}function Xl(e,t){let n=t.split(`
23
+ `).filter(Boolean),r=n.filter(f=>f.startsWith("Reason:")),i=n.filter(f=>!f.startsWith("Reason:")&&!f.startsWith("Allow tool:"));return[...e.endsWith(" wants to run")?[]:[e],...r,...i.length>0?["",...i]:[]]}function Me(e){let t=e.getContextUsage();if(t?.percent!==null&&t?.percent!==void 0)return Math.min(100,Math.round(t.percent));let n=e.model,i=[...e.state.messages].reverse().find(u=>u.role==="assistant")?.usage?.totalTokens;return!n||typeof i!="number"||!Number.isFinite(i)||n.contextWindow<=0?0:Math.min(100,Math.round(i/n.contextWindow*100))}function qn(e){let n=[["init","write project notes to AGENTS.md"],["model","choose a model"],["providers","list providers"],["thinking","set thinking level"],["approval","set what needs approval"],["settings","turn permission checks on or off"],["connect","sign in with email:password (or a base64 credential), or paste a key"],["sync","re-sync models from howtofix.id"],["usage","show the account's quota and what it has spent"],["update","install the newest release"],["login","save a provider API key"],["logout","remove a provider"],["new","start a new session"],["resume","resume another session"],["compact","compact the session"],["name","name this session"],["stats","session tokens and cost, cache hit rate and misses"],["rtk","compress long tool output before the model reads it"],["diff","show the working tree diff"],["commit","stage everything and commit"],["undo","undo the last commit"],["rewind","go back to an earlier message (Esc Esc)"],["review","ask the agent to review the diff"],["tools","list active tools"],["skills","list loaded skills"],["preset","browse, install and remove preset skill bundles"],["roblox","show RoToolbox activation, MCP and manager status"],["proxy","route requests through a proxy, or show the current one"],["export","write the transcript to a markdown file"],["copy","copy the last answer to the clipboard"],["agents","show spawned agents"],["goal","set or view this session's goal"],["plan","toggle plan mode (design before editing)"],["workflow","show or clear the pinned workflow panel"],["dcp","dynamic context pruning: on | off | status | blocks | stats | context | decompress <bN> | sweep"],["context","what the next request carries, and what pruning saved"],["decompress","reopen one compressed block, e.g. /decompress b2"],["sweep","close compressed blocks no ref resolves"],["session","show the current model"],["help","list commands"],["quit","quit"],["exit","quit (alias)"]].map(([r,i])=>({name:r,description:i}));for(let r of e.promptTemplates)n.push({name:r.name,description:r.description});for(let r of e.extensionRunner.getRegisteredCommands())n.push({name:r.invocationName,description:r.description});return n}function Jn(e,t){if(e!=="workflow")return;let n=Ge(t);if(!(typeof n.name!="string"||!Array.isArray(n.steps)))return n}function Jl(e,t){let n=Jn(e,t);return n?Et(n):void 0}function Et(e,t,n=!1){return r=>ci(e,[],r,t?.selectedPhase,t?Zl(e,t,n):void 0)}function Zl(e,t,n){return{filter:r=>_s(r,t.filter),footerText:Ns(t,e.endedAt===void 0,n),filterLabel:Os(t.filter),drill:t.expanded}}function Ql(){let e=new Bs(qs,{"tui.altScreen.pageUp":[],"tui.altScreen.pageDown":[],"tui.altScreen.halfPageUp":[],"tui.altScreen.halfPageDown":[],"tui.altScreen.top":[],"tui.altScreen.bottom":[]});Gs(e)}async function mu(e){let t=new Wl,n,r=new Hl(t,!0,void 0,{mouse:!0,onRightClickPaste:()=>n?.()}),i=new vt,u=new zn(e.cwd,e.modelLabel);u.skipPermissions=pn();let f=o=>{let s=Date.now();(async()=>{try{let a=Ye(),l=k.getSessionStats().sessionId;if(!io){io=!0;try{await gi(a,{keep:l})}catch{}}let d=await pi(a,l,o);d&&s>=jt&&(ro=d,jt=s)}catch{}})()},h=(o=!1)=>{!o&&!u.live||Hs(e.cwd).then(s=>{s!==null&&(u.git=s,v())})},w=new Dl(r,Ks,{paddingX:1}),x=new Map,M=(o,s)=>{s===void 0?x.delete(o):typeof s=="function"?x.set(o,s):x.set(o,()=>s)},j=()=>Math.max(20,t.columns),D,W=0,I=Es(),U,L=null,X=!1,me,Q=!1,zs,It=()=>{!U||!X||M("workflow",o=>Et(U,I,Q)(o))},Zn=()=>{U&&(me=U.name),X=!1,Q=!1,M("workflow",void 0)};di({onStop:o=>{L=o},isPaused:()=>I.paused});let Qn=o=>{if(me===o.name)return;D=o;let s=o.endedAt??Date.now();W=Math.max(W,s+si),U=o,X=!0,M("workflow",a=>Et(o,I,Q)(a))},eo=new Xn(w,u),k=e.session,to=e.setCompressToolOutput,no=!1,_t=()=>{let o=k.getSessionStats().cost;return u.cost=o,o},Ot=rr(e.maxBudgetUsd),oo=!1,Ys=()=>{let o=Ot.check(_t());o===void 0||oo||(oo=!0,k.isStreaming&&k.abort(),p("budget",ir(o.spent,o.limit)))},he=()=>{u.ceiling=es(k.model)},ge=vr(E),Lt,Xs=async()=>!ge||!$r(ge)||kr(ge)?!1:(Lt??=(async()=>{try{let o=await Sr(E,ge);return o.renewed?(ge=o.credential,o.message&&p("connect",o.message),await k.modelRuntime.setRuntimeApiKey("howtofix",o.credential.accessToken),!0):(o.message&&p("connect",o.message),!1)}catch{return!1}finally{Lt=void 0}})(),await Lt),Nt,Ye=()=>Nt??=ui(e.cwd),ro,Ft="",jt=0,io=!1,be,Js=()=>{let o=new Set(["session_info","usage","label","context_edit","custom","model_change","thinking_level_change"]),s=[],a=l=>{for(let d of l)o.has(d.entry.type)||s.push(d.entry.id),a(d.children)};return a(k.sessionManager.getTree()),s},so=!1,Zs=()=>{if(so)return;so=!0;let o=Us().getResolvedBindings();Gs(new Bs(qs,{...o,"app.tree.foldOrUp":["alt+left","ctrl+left"],"app.tree.unfoldOrDown":["alt+right","ctrl+right"],"app.tree.editLabel":["shift+l"],"app.tree.toggleLabelTimestamp":["shift+t"],"app.message.copy":["ctrl+x"],"app.tree.filter.default":["alt+0"],"app.tree.filter.noTools":["alt+1"],"app.tree.filter.userOnly":["alt+2"],"app.tree.filter.labeledOnly":["alt+3"],"app.tree.filter.all":["alt+4"],"app.tree.filter.cycleForward":["alt+f"],"app.tree.filter.cycleBackward":["alt+shift+f"]}))},ao=!1,Qs=()=>{ao||(ao=!0,Vl())},lo=()=>{let o=k.sessionManager.getTree();if(o.length===0){p("rewind","nothing to rewind to yet");return}Ye().disabled&&p("rewind","conversation rewind only; this directory is not a git repository"),Qs(),Zs();let s=Math.max(8,Math.floor(t.rows*.6)),a=new ql(o,k.sessionManager.getLeafId(),s*2,l=>{Dt(),ea(l)},()=>Dt());if(!a.getTreeList().getSelectedNode()){p("rewind","nothing to rewind to yet");return}be=a,be.focused=!0,M("rewind",l=>be?.render(l)??[]),v()},Dt=()=>{be=void 0,M("rewind",void 0),v()},ea=async o=>{let s=Ye(),l=k.getUserMessagesForForking().findIndex(c=>c.entryId===o),d=l>=0?fi(s,k.getSessionStats().sessionId)[l]:void 0,y=d?(await hi(s,d)).length:0;if(y===0){await co(o,void 0,"conversation");return}_(`Rewind to this point? ${y} file(s) differ`,[{value:"both",label:"conversation and code",description:`drop the messages after this point and restore ${y} file(s)`},{value:"conversation",label:"conversation only",description:"drop the messages after this point, leave the files alone"},{value:"code",label:"code only",description:`restore ${y} file(s), keep the conversation`}],c=>{co(o,d,c)})},co=async(o,s,a)=>{let l=[];if((a==="both"||a==="conversation")&&!k.isStreaming)try{let d=await k.navigateTree(o);if(d.cancelled){p("rewind","conversation rewind cancelled");return}l.push("conversation rewound"),i.items=xt(k.state.messages),d.editorText&&(w.setText(d.editorText),l.push("prompt restored to the editor"))}catch(d){H(`conversation rewind failed: ${d instanceof Error?d.message:String(d)}`);return}if((a==="both"||a==="code")&&s){let d=await mi(Ye(),s);if(!d.ok){H(`code rewind failed: ${d.output}`);return}l.push(d.output),d.removed.length>0&&l.push(`removed ${d.removed.length} file(s)`),h()}p("rewind",l.join(`
24
+ `)||"nothing to do"),v()};h(!0),f("session start"),e.note&&i.items.push({id:"note",kind:"note",title:"note",body:e.note}),i.items.push(...xt(k.state.messages)),u.percent=Me(k),_t(),u.abandonAnimations(),u.setThinking(k.thinkingLevel),he(),w.setAutocompleteProvider(new Ws(qn(k),e.cwd)),fs(k).then(o=>{o&&(u.usage=o,r.requestRender())});let uo=async o=>{let{checkForUpdate:s,checkFailedNote:a,installUpdate:l}=await import("./chunk-7CHDNTH6.js"),d=await s(o.current);if(!d.available){let c=a(d);c?p("update",c):o.install&&p("update",d.message);return}if(!o.install){p("update",`${d.message}. run /update to install it.`);return}C("note",`installing HowToFix ${d.latest}\u2026`);let y=await l({version:d.latest});C("note",void 0),p("update",y.message),v()};e.update&&uo(e.update);let ie=null,fo="",po=!1,mo=[],Ee,Wt=()=>{},v=()=>{Wt(),r.requestRender()},C=(o,s)=>{u.activity=Cs(u.activity,o,s)},Ut=o=>{u.activity=As(u.activity,o)},Xe=new Map,Kt=new Set,ta=()=>[...Xe].map(([o,s])=>`${Kt.has(o)?"!":"\u2713"} ${o} \xD7${s}`).join(" | "),na=()=>{let o=ta();C("tally",o||void 0)},_=(o,s,a,l,d=!1,y=[])=>{let c=new Kl(s,8,Ks.selectList);c.onSelect=m=>{ie=null,Ee=void 0,a(m.value)},c.onCancel=()=>{ie=null,Ee=void 0,l?.(),v()},Ee=()=>c.onCancel?.(),fo=o,po=d,mo=y,ie=c,bo+=1,v()},p=(o,s)=>{i.items=Vi(i.items,{id:`cmd-${Date.now()}-${i.items.length}`,kind:"note",title:o,body:s}),C("tally",void 0),v()};Qr(o=>{o.background&&p("agent",`${zr(o)}
25
+ read it with /agents ${o.id}`)});let Ht=!1,oa=o=>{Ht||(Ht=!0,(async()=>{try{let s=(await k.modelRuntime.getAvailable()).filter(g=>re(g.provider)),a=new Set(s.map(g=>g.provider)),l=ye.find(g=>a.has(g)),d=l?(await k.modelRuntime.getAuth(l))?.auth?.apiKey:void 0;if(!d)return;let y=bt(s.map(g=>g.id)),{live:c,probed:m}=await gr(y,d,{exclude:o,limit:4});if(c.length===0)return;let b=ie===null;p("gateway",`${c.length} of ${m.length} probed models answer right now (${c.join(", ")}); ${b?"the model picker is open below":"switch with /model"}.`),b&&Ne("/model")}catch{}finally{Ht=!1}})())},H=o=>{i.items.push({id:`err-${Date.now()}-${i.items.length}`,kind:"error",title:"failed",body:o});let s=$i(o);s!==void 0&&p("gateway",s);let a=ki(o);a!==void 0&&oa(a),C("tally",void 0),v()},Pe=o=>{k.setThinkingLevel(o,{persist:!0}),u.setThinking(o),he(),C("note",`thinking ${o}`),v()};Er((o,s)=>{let{promise:a,resolve:l}=Promise.withResolvers();return _(o,[{value:"allow",label:"allow"},{value:"deny",label:"deny"}],d=>l(d==="allow"),()=>l(!1),!0,Xl(o,s)),a});let Bt=new Map,ho=o=>{let s=js({select:(a,l)=>{let{promise:d,resolve:y}=Promise.withResolvers();return _(a,l.map(c=>({value:c,label:c})),y,()=>y(void 0)),d},confirm:(a,l)=>{let{promise:d,resolve:y}=Promise.withResolvers();return _(`${a} \u2014 ${l}`,[{value:"yes",label:"yes"},{value:"no",label:"no"}],c=>y(c==="yes"),()=>y(!1)),d},input:a=>{let{promise:l,resolve:d}=Promise.withResolvers();return C("prompt",a),v(),ne=y=>{ne=void 0,C("prompt",void 0),d(y),v()},l},notify:(a,l)=>{l==="error"?H(a):p("mcp",a)},setStatus:(a,l)=>{l===void 0?Bt.delete(a):Bt.set(a,l),C("note",[...Bt.values()].join(" | ")||void 0),v()},setWidget:(a,l)=>{M(a,l),v()}});o.bindExtensions({uiContext:s,mode:"print",onError:a=>H(`${a.event}: ${a.error}`)}).catch(a=>H(a instanceof Error?a.message:String(a)))};ho(k);let ve=new jl,ra={invalidate:()=>i.invalidate(),render:o=>{let s=ve.render(Math.max(20,o)).length;return i.viewportHeight=Math.max(1,Math.max(8,t.rows)-s),i.render(o)},handleMouse:o=>{if(Mo(o))return tt(),{handled:!0};let s=o.type==="wheel"?o.wheelDelta??0:0;if(s!==0)return i.scrollOffset=Math.max(0,i.scrollOffset-s*3),v(),{handled:!0}}},ia=new Ul(ra,{follow:"none",overscroll:"contain"}),Je=new Bl([{component:ia,grow:1,shrink:1},{component:ve,grow:0,shrink:0,basis:"auto"}]),go="",bo=0,sa=()=>`${ie?`picker:${bo}`:"dock"}|${[...x.keys()].join(",")}`;Wt=()=>{let o=sa();if(o===go)return;go=o,ve.clear();for(let a of x.values())ve.addChild(new Yn(a));let s=ie;if(s){let a=fo,l=po,d=mo;ve.addChild({render:y=>Yl(s,a,y,l,d),invalidate:()=>{}})}else ve.addChild(eo);Je.invalidate()},Wt();let wo={focused:!1,invalidate(){i.invalidate(),eo.invalidate(),ie?.invalidate(),Je.invalidate()},[Vs]:()=>zl(Je),render:o=>Je.render(o),handleMouse(o){if(Mo(o))return tt(),{handled:!0}},handleInput(o){w.handleInput(o)}};r.setLayoutRoot(wo),r.setFocus(wo);let z=0,ce="",Gt=!1,we=!1,qt,xe="",yo=0,Ie=!1,Ze=Date.now(),Qe=!1,et=new Map,ko=()=>{let o=new Set(k.getSteeringMessages().map(s=>s.trim()).filter(Boolean));for(let s of i.items)s.kind!=="user"||!s.pending||o.has(s.body.trim())||(s.pending=void 0)},$o=o=>{if(o.type==="agent_start"&&ko(),o.type==="agent_start"||o.type==="turn_start")o.type==="agent_start"&&Mr(),u.live||u.beginRun(),ce="",we=!1,Ie=!1,Ze=Date.now(),xe="";else if(o.type==="message_update"&&o.assistantMessageEvent.type==="thinking_delta"){we=!0,xe===""&&(yo=Date.now()),xe+=o.assistantMessageEvent.delta;let s=`think-${z}`,a=i.items.find(d=>d.id===s),l=xe.split(`
26
26
  `).slice(-6).join(`
27
- `);a?a.body=l:i.items.push({id:s,kind:"note",title:"thinking",body:l})}else if(o.type==="message_update"&&o.assistantMessageEvent.type==="thinking_end"){let s=`think-${z}`,a=i.items.find(l=>l.id===s);if(a){let l=Math.max(1,Math.round((Date.now()-yo)/1e3));a.title="thought",a.body=`${l}s \xB7 ${xe.length} chars of reasoning`}xe=""}else if(o.type==="message_update"&&o.assistantMessageEvent.type==="text_delta"){we=!0,ce+=o.assistantMessageEvent.delta;let s=De(ce),a=`live-${z}`,l=i.items.find(d=>d.id===a);l?l.body=s:i.items.push({id:a,kind:"assistant",title:"HowToFix",body:s})}else if(o.type==="tool_execution_start"){et.set(o.toolCallId,o.args),we=!1,Ie=!1,Ze=Date.now();let s=`tool-${o.toolCallId}`,a=$e(o.toolName,o.args),l=i.items.find(d=>d.id===s);if(l?(l.kind="tool",l.title=o.toolName,l.body=a,l.live=!0):i.items.push({id:s,kind:"tool",title:o.toolName,body:a,live:!0}),qt=o.toolName,o.toolName==="task"){let d=zr.filter(y=>y.status==="queued"||y.status==="running");C("note",d.map(y=>`${y.agent} ${y.status}`).join(" | ")||"agent running")}}else if(o.type==="tool_execution_update"){let s=Xl(o.toolName,o.partialResult);if(s){let a=`tool-${o.toolCallId}`,l=i.items.find(y=>y.id===a);l?l.panel=s:i.items.push({id:a,kind:"tool",title:o.toolName,body:$e(o.toolName,et.get(o.toolCallId)),panel:s,live:!0});let d=Jn(o.toolName,o.partialResult);d&&pe!==d.name&&Qn(d),$()}}else if(o.type==="tool_execution_end"){u.percent=Me(k);let s=i.items.find(g=>g.id===`tool-${o.toolCallId}`);s&&(s.live=!1,s.body=$e(o.toolName,et.get(o.toolCallId))),et.delete(o.toolCallId),qt=void 0,we=!0,Ie=!1,Xe.set(o.toolName,(Xe.get(o.toolName)??0)+1),o.isError&&Kt.add(o.toolName),ta();let a=Ki(o.toolName,o.result),l=Hi(o.toolName,o.result),d=Jn(o.toolName,o.result),y=d?Et(d):void 0;d&&pe!==d.name&&Qn(d);let c=i.items.find(g=>g.id===`tool-${o.toolCallId}`),p=$t(o.toolName,o.result,o.isError);c?(c.kind="result",c.call=c.body,c.body=p,c.live=!1,a.length>0&&(c.detail=a),l.length>0&&(c.full=l),y&&(c.panel=y)):i.items.push({id:`tool-${o.toolCallId}`,kind:"result",title:o.toolName,body:p,...a.length>0?{detail:a}:{},...l.length>0?{full:l}:{},...y?{panel:y}:{}}),(o.toolName==="bash"||o.toolName==="powershell"||o.toolName==="edit"||o.toolName==="write")&&h()}else if(o.type==="compaction_start"){we=!0;let s=o.reason==="manual"?"on request":"context is nearly full",a=i.items.find(y=>y.id===`compact-${z}`),l="compacting context",d=`${s} \xB7 summarizing the older turns`;a?(a.title=l,a.body=d):i.items.push({id:`compact-${z}`,kind:"note",title:l,body:d,live:!0}),C("note","compacting context")}else if(o.type==="compaction_end"){let s=i.items.find(y=>y.id===`compact-${z}`),a=o.result,l="compacted",d;if(o.aborted)d="cancelled";else if(o.errorMessage)d=`failed: ${o.errorMessage}`;else if(a){let y=Math.round(a.tokensBefore/1e3),c=a.estimatedTokensAfter!==void 0?Math.round(a.estimatedTokensAfter/1e3):void 0,p=a.estimatedTokensAfter!==void 0?a.tokensBefore-a.estimatedTokensAfter:void 0,g=p!==void 0&&p<2e3;d=c!==void 0?`${y}k \u2192 ${c}k tokens \xB7 older turns summarized${g?`
28
- this freed almost nothing; the window may be too small for this work`:""}`:`${y}k tokens \xB7 older turns summarized`}else d="nothing to compact";s?(s.title=l,s.body=d,s.live=!1):i.items.push({id:`compact-${z}`,kind:"note",title:l,body:d}),u.percent=Me(k),C("note",void 0)}else if(o.type==="message_start"&&o.message.role==="user"){let s=Vi(o.message);s&&(i.items=zi(i.items,s,`u-${o.message.timestamp}`)),ko()}else if(o.type==="message_end"&&o.message.role==="assistant"){let s=i.items.find(l=>l.id===`live-${z}`);s&&(s.id=`done-${z}`);let a=o.message.errorMessage;a&&s?(s.title="failed",s.kind="error",s.body=ce.trim()?`${a}
27
+ `);a?a.body=l:i.items.push({id:s,kind:"note",title:"thinking",body:l})}else if(o.type==="message_update"&&o.assistantMessageEvent.type==="thinking_end"){let s=`think-${z}`,a=i.items.find(l=>l.id===s);if(a){let l=Math.max(1,Math.round((Date.now()-yo)/1e3));a.title="thought",a.body=`${l}s \xB7 ${xe.length} chars of reasoning`}xe=""}else if(o.type==="message_update"&&o.assistantMessageEvent.type==="text_delta"){we=!0,ce+=o.assistantMessageEvent.delta;let s=De(ce),a=`live-${z}`,l=i.items.find(d=>d.id===a);l?l.body=s:i.items.push({id:a,kind:"assistant",title:"HowToFix",body:s})}else if(o.type==="tool_execution_start"){et.set(o.toolCallId,o.args),we=!1,Ie=!1,Ze=Date.now();let s=`tool-${o.toolCallId}`,a=$e(o.toolName,o.args),l=i.items.find(d=>d.id===s);if(l?(l.kind="tool",l.title=o.toolName,l.body=a,l.live=!0):i.items.push({id:s,kind:"tool",title:o.toolName,body:a,live:!0}),qt=o.toolName,o.toolName==="task"){let d=Yr.filter(y=>y.status==="queued"||y.status==="running");C("note",d.map(y=>`${y.agent} ${y.status}`).join(" | ")||"agent running")}}else if(o.type==="tool_execution_update"){let s=Jl(o.toolName,o.partialResult);if(s){let a=`tool-${o.toolCallId}`,l=i.items.find(y=>y.id===a);l?l.panel=s:i.items.push({id:a,kind:"tool",title:o.toolName,body:$e(o.toolName,et.get(o.toolCallId)),panel:s,live:!0});let d=Jn(o.toolName,o.partialResult);d&&me!==d.name&&Qn(d),v()}}else if(o.type==="tool_execution_end"){u.percent=Me(k);let s=i.items.find(b=>b.id===`tool-${o.toolCallId}`);s&&(s.live=!1,s.body=$e(o.toolName,et.get(o.toolCallId))),et.delete(o.toolCallId),qt=void 0,we=!0,Ie=!1,Xe.set(o.toolName,(Xe.get(o.toolName)??0)+1),o.isError&&Kt.add(o.toolName),na();let a=Hi(o.toolName,o.result),l=Bi(o.toolName,o.result),d=Jn(o.toolName,o.result),y=d?Et(d):void 0;d&&me!==d.name&&Qn(d);let c=i.items.find(b=>b.id===`tool-${o.toolCallId}`),m=$t(o.toolName,o.result,o.isError);c?(c.kind="result",c.call=c.body,c.body=m,c.live=!1,a.length>0&&(c.detail=a),l.length>0&&(c.full=l),y&&(c.panel=y)):i.items.push({id:`tool-${o.toolCallId}`,kind:"result",title:o.toolName,body:m,...a.length>0?{detail:a}:{},...l.length>0?{full:l}:{},...y?{panel:y}:{}}),(o.toolName==="bash"||o.toolName==="powershell"||o.toolName==="edit"||o.toolName==="write")&&h()}else if(o.type==="compaction_start"){we=!0;let s=o.reason==="manual"?"on request":"context is nearly full",a=i.items.find(y=>y.id===`compact-${z}`),l="compacting context",d=`${s} \xB7 summarizing the older turns`;a?(a.title=l,a.body=d):i.items.push({id:`compact-${z}`,kind:"note",title:l,body:d,live:!0}),C("note","compacting context")}else if(o.type==="compaction_end"){let s=i.items.find(y=>y.id===`compact-${z}`),a=o.result,l="compacted",d;if(o.aborted)d="cancelled";else if(o.errorMessage)d=`failed: ${o.errorMessage}`;else if(a){let y=Math.round(a.tokensBefore/1e3),c=a.estimatedTokensAfter!==void 0?Math.round(a.estimatedTokensAfter/1e3):void 0,m=a.estimatedTokensAfter!==void 0?a.tokensBefore-a.estimatedTokensAfter:void 0,b=m!==void 0&&m<2e3;d=c!==void 0?`${y}k \u2192 ${c}k tokens \xB7 older turns summarized${b?`
28
+ this freed almost nothing; the window may be too small for this work`:""}`:`${y}k tokens \xB7 older turns summarized`}else d="nothing to compact";s?(s.title=l,s.body=d,s.live=!1):i.items.push({id:`compact-${z}`,kind:"note",title:l,body:d}),u.percent=Me(k),C("note",void 0)}else if(o.type==="message_start"&&o.message.role==="user"){let s=zi(o.message);s&&(i.items=Yi(i.items,s,`u-${o.message.timestamp}`)),ko()}else if(o.type==="message_end"&&o.message.role==="assistant"){let s=i.items.find(l=>l.id===`live-${z}`);s&&(s.id=`done-${z}`);let a=o.message.errorMessage;a&&s?(s.title="failed",s.kind="error",s.body=ce.trim()?`${a}
29
29
 
30
30
  ${ce.trim()}`:a):a&&i.items.push({id:`e-${o.message.timestamp}`,kind:"error",title:"failed",body:a}),z+=1,ce="",u.percent=Me(k)}else if(o.type==="agent_settled"){u.live=!1;let s=[...k.getSteeringMessages()].map(a=>a.trim()).filter(Boolean);if(s.length>0){let a=w.getText().trim();w.setText(a?`${s.join(`
31
31
  `)}
32
32
  ${a}`:s.join(`
33
- `));let l=new Set(s);for(let d of i.items)d.kind==="user"&&d.pending&&l.has(d.body.trim())&&(d.pending=void 0);m("queued",`${s.length} unread message${s.length===1?"":"s"} were never read and are back in the editor`)}for(let a of i.items)a.kind==="user"&&a.pending&&(a.pending=void 0);if(f(Ft),Ft="",C("run",void 0),Gt){let a=i.items.find(l=>l.id===`live-${z}`);a?(a.id=`stopped-${z}`,a.title="stopped",a.body=ce.trim()||"(no output)",a.live=!1):i.items.push({id:`stopped-${z}`,kind:"note",title:"stopped",body:"run cancelled"}),z+=1,ce="",m("stopped","run cancelled by Esc"),Gt=!1}u.percent=Me(k),C("note",void 0),Ut(void 0),Ks(e.cwd).then(a=>{a!==null&&(u.git=a,$())}),w.disableSubmit=!1}else o.type==="thinking_level_changed"?u.setThinking(o.level):o.type==="auto_retry_start"?(C("note",void 0),Ut({attempt:o.attempt,maxAttempts:o.maxAttempts,error:o.errorMessage,until:Date.now()+o.delayMs})):o.type==="auto_retry_end"&&(Ut(void 0),o.success?m("retry",`answered on attempt ${o.attempt} after a retry`):C("note",`retry ${o.attempt} gave up${o.finalError?` \xB7 ${Kn(o.finalError)}`:""}`));zs(),$()},Vt=k.subscribe($o),vo=setInterval(()=>{let o=D!==void 0&&Date.now()<W;if((Qe||k.isStreaming||u.settling()||i.entering()||re||o||u.atCeiling()||u.flashing()||u.activity.retry!==void 0)&&$(),(Qe||k.isStreaming)&&!we&&!Ie&&Date.now()-Ze>ec){Ie=!0;let s=qt,a=Math.round((Date.now()-Ze)/1e3);C("note",s?`${s} has been running for ${a}s \u2014 it may be blocked; esc cancels`:`no answer yet after ${a}s \u2014 the provider may be stalled; ctrl+c cancels`),$()}},Ql);vo.unref?.();let xo=async o=>{Ee?.(),Ee=void 0,Vt(),Nt&&gi(Nt,k.getSessionStats().sessionId),ro=void 0,jt=0;let s=k.getSessionStats().sessionId;bn(s),wn(s),await ot.dispose(),k.dispose(),k=o.session,to=o.setCompressToolOutput,ot=new ze({initial:Object.keys(Le().mcpServers),apply:async(a,l)=>{if(await Se(),a.length>0||l.length>0){let d=[];a.length>0&&d.push(`connected ${a.join(", ")}`),l.length>0&&d.push(`stopped ${l.join(", ")}`),m(a.length>0?"mcp connected":"mcp stopped",d.join("; "))}},report:a=>H(a)}),z=0,ce="",i.items=[],i.scrollOffset=0,o.note&&i.items.push({id:"note",kind:"note",title:"note",body:o.note}),i.items.push(...xt(k.state.messages)),u.model=o.modelLabel.split("/").at(-1)||"no-model",u.setThinking(k.thinkingLevel),he(),u.percent=Me(k),_t(),u.abandonAnimations(),C("tally",void 0),C("run",void 0),w.setAutocompleteProvider(new Ds(qn(k),e.cwd)),w.disableSubmit=!1,ho(k),Vt=k.subscribe($o),$()},_e=async()=>{if(no)return;no=!0,clearInterval(vo),Vt();try{let s=Pr(Er);if(s.config.hooks.SessionEnd){let{outcome:a}=await Ir(s.config,"SessionEnd",{hook_event_name:"SessionEnd",cwd:process.cwd(),reason:"quit"},{cwd:process.cwd()});a.error&&m("hooks",`SessionEnd hook: ${a.error}`)}}catch{}await ot.dispose();let o=k.getSessionStats().sessionId;Ot.close(k.getSessionStats().cost),bn(o),wn(o),k.dispose(),r.stop(),process.stdout.write("\x1B[0m"),process.exit(0)},So=0,Co=async(o=!1)=>{let s=Date.now();if(!o&&s-So<600*1e3)return;So=s;let a=d=>{if(process.env.HOWTOFIX_CHECKIN_DEBUG==="1")try{Pl(`${P}/checkin-debug.log`,`${new Date().toISOString()} ${d}
34
- `)}catch{}},l=async()=>{try{let d=new Set((await k.modelRuntime.getAvailable()).map(A=>A.provider).filter(A=>se(A))),y=ye.find(A=>d.has(A));if(a(`providers=${[...d].join(",")||"(none)"} target=${y??"(none)"}`),!y)return!1;let c=(await k.modelRuntime.getAuth(y))?.auth?.apiKey,p=c?.trim().match(/^\$\{?([A-Za-z_][A-Za-z0-9_]*)\}?$|^\{env:([A-Za-z_][A-Za-z0-9_]*)\}$/),g=A=>A?(process.env[A]??"").trim():"",b=p?g(p[1]??p[2])||void 0:c?.trim()||void 0;if(!b)for(let A of["HOWTOFIX_API_KEY","HOWTOFIX_VIP_API_KEY","HOWTOFIX_FREE_API_KEY"]){let R=g(A);if(R){b=R,a(`key dari fallback ${A}`);break}}if(a(`key=${b?`ada(${b.length})`:"(kosong)"}${p?" dari env":""}`),!b)return!1;let S=await Un(b);if(a(`status ok=${S.ok} enabled=${S.enabled} claimed=${S.checkedInToday} msg=${S.message}`),!S.ok||!S.enabled||S.checkedInToday)return!0;let v=await $s(b);return a(`claim ok=${v.ok} awarded=${v.quotaAwarded} msg=${v.message}`),v.ok?(m("check-in",`daily check-in claimed: +${Wn(v.quotaAwarded)} credited to your howtofix.id account`),$()):v.blocked&&m("check-in",v.message),!0}catch(d){return a(`error ${d.message}`),!1}};await l()||(await new Promise(d=>setTimeout(d,4e3)),await l())},Ao=async o=>{let s=Ot.check(k.getSessionStats().cost);if(s!==void 0){H(`budget reached: $${s.spent.toFixed(4)} of $${s.limit.toFixed(2)} \u2014 raise it with --max-budget-usd, or start without the flag`);return}let a=k.isStreaming,l=`you-${Date.now()}`;i.items.push({id:l,kind:"user",title:"you",body:o,pending:a?!0:void 0}),a||(C("tally",void 0),Xe.clear(),Kt.clear(),C("run","thinking"),u.beginRun()),$(),w.disableSubmit=!1;let d=Ar(o,e.cwd);Ft=o,await Ys(),Qe=!0;let y=a?k.prompt(d,{streamingBehavior:"steer"}):k.prompt(d);Qe=!1,y.then(()=>Co()).catch(c=>H(c instanceof Error?c.message:String(c)))},zt=o=>{let s=o.trim();if(s){if(ne){let a=ne;ne=void 0,w.setText(""),a(s);return}if(w.setText(""),w.addToHistory(s),s.startsWith("!")){let a=s.slice(1).trim();if(!a)return;i.items.push({id:`sh-${Date.now()}`,kind:"tool",title:"$",body:a}),C("run","shell"),$(),k.executeBash(a,l=>{C("run",`shell \xB7 ${l.length} bytes`),$()}).then(l=>{let d=l.output.trim();i.items.push({id:`sh-out-${Date.now()}`,kind:l.exitCode===0?"result":"error",title:`exit ${l.exitCode??"?"}`,body:d||"(no output)"}),C("tally",void 0),$()}).catch(l=>H(l instanceof Error?l.message:String(l)));return}if(s.startsWith("/")){Ne(s);return}Ao(s)}};w.onSubmit=zt;let Yt=0,To=0,tt=()=>{Ci().then(o=>{o.ok?w.insertTextAtCursor(o.text):m("paste",o.reason),$()}).catch(o=>{m("paste",`could not read the clipboard: ${o instanceof Error?o.message:String(o)}`),$()})};n=tt;let Mo=o=>pn(ke(P).rightClickPaste)&&o.type==="press"&&o.button==="right";r.addInputListener(o=>{if(be){if(V(o,"escape"))return Dt(),{consume:!0};let a=Ws(),l=a.matches(o,"tui.select.up"),d=a.matches(o,"tui.select.down");if(l||d){let c=be.getTreeList().getSelectedNode()?.entry.id,p=Xs(),g=c===void 0?-1:p.indexOf(c);if(l?g===0:g===p.length-1)return $(),{consume:!0}}return be.handleInput(o),$(),{consume:!0}}if(X&&U&&V(o,"escape"))return Q?(Q=!1,m("workflow","panel keys off; the editor has the keyboard")):I.expanded?(I.expanded=!1,m("workflow","collapsed the drill-in")):(Zn(),m("workflow","panel unpinned; the run is still in the transcript")),It(),$(),{consume:!0};if(re)return re.handleInput(o),$(),{consume:!0};if(V(o,"escape")){if(k.isStreaming){Gt=!0;let l=[...k.getSteeringMessages()].map(d=>d.trim()).filter(Boolean);if(l.length>0){let d=w.getText().trim();w.setText(d?`${l.join(`
33
+ `));let l=new Set(s);for(let d of i.items)d.kind==="user"&&d.pending&&l.has(d.body.trim())&&(d.pending=void 0);p("queued",`${s.length} unread message${s.length===1?"":"s"} were never read and are back in the editor`)}for(let a of i.items)a.kind==="user"&&a.pending&&(a.pending=void 0);if(f(Ft),Ft="",C("run",void 0),Gt){let a=i.items.find(l=>l.id===`live-${z}`);a?(a.id=`stopped-${z}`,a.title="stopped",a.body=ce.trim()||"(no output)",a.live=!1):i.items.push({id:`stopped-${z}`,kind:"note",title:"stopped",body:"run cancelled"}),z+=1,ce="",p("stopped","run cancelled by Esc"),Gt=!1}u.percent=Me(k),C("note",void 0),Ut(void 0),Hs(e.cwd).then(a=>{a!==null&&(u.git=a,v())}),w.disableSubmit=!1}else o.type==="thinking_level_changed"?u.setThinking(o.level):o.type==="auto_retry_start"?(C("note",void 0),Ut({attempt:o.attempt,maxAttempts:o.maxAttempts,error:o.errorMessage,until:Date.now()+o.delayMs})):o.type==="auto_retry_end"&&(Ut(void 0),o.success?p("retry",`answered on attempt ${o.attempt} after a retry`):C("note",`retry ${o.attempt} gave up${o.finalError?` \xB7 ${Kn(o.finalError)}`:""}`));Ys(),v()},Vt=k.subscribe($o),vo=setInterval(()=>{let o=D!==void 0&&Date.now()<W;if((Qe||k.isStreaming||u.settling()||i.entering()||ie||o||u.atCeiling()||u.flashing()||u.activity.retry!==void 0)&&v(),(Qe||k.isStreaming)&&!we&&!Ie&&Date.now()-Ze>tc){Ie=!0;let s=qt,a=Math.round((Date.now()-Ze)/1e3);C("note",s?`${s} has been running for ${a}s \u2014 it may be blocked; esc cancels`:`no answer yet after ${a}s \u2014 the provider may be stalled; ctrl+c cancels`),v()}},ec);vo.unref?.();let xo=async o=>{Ee?.(),Ee=void 0,Vt(),Nt&&bi(Nt,k.getSessionStats().sessionId),ro=void 0,jt=0;let s=k.getSessionStats().sessionId;bn(s),wn(s),await ot.dispose(),k.dispose(),k=o.session,to=o.setCompressToolOutput,ot=new ze({initial:Object.keys(Le().mcpServers),apply:async(a,l)=>{if(await Se(),a.length>0||l.length>0){let d=[];a.length>0&&d.push(`connected ${a.join(", ")}`),l.length>0&&d.push(`stopped ${l.join(", ")}`),p(a.length>0?"mcp connected":"mcp stopped",d.join("; "))}},report:a=>H(a)}),z=0,ce="",i.items=[],i.scrollOffset=0,o.note&&i.items.push({id:"note",kind:"note",title:"note",body:o.note}),i.items.push(...xt(k.state.messages)),u.model=o.modelLabel.split("/").at(-1)||"no-model",u.setThinking(k.thinkingLevel),he(),u.percent=Me(k),_t(),u.abandonAnimations(),C("tally",void 0),C("run",void 0),w.setAutocompleteProvider(new Ws(qn(k),e.cwd)),w.disableSubmit=!1,ho(k),Vt=k.subscribe($o),v()},_e=async()=>{if(no)return;no=!0,clearInterval(vo),Vt();try{let s=Ir(Pr);if(s.config.hooks.SessionEnd){let{outcome:a}=await _r(s.config,"SessionEnd",{hook_event_name:"SessionEnd",cwd:process.cwd(),reason:"quit"},{cwd:process.cwd()});a.error&&p("hooks",`SessionEnd hook: ${a.error}`)}}catch{}await ot.dispose();let o=k.getSessionStats().sessionId;Ot.close(k.getSessionStats().cost),bn(o),wn(o),k.dispose(),r.stop(),process.stdout.write("\x1B[0m"),process.exit(0)},So=0,Co=async(o=!1)=>{let s=Date.now();if(!o&&s-So<600*1e3)return;So=s;let a=d=>{if(process.env.HOWTOFIX_CHECKIN_DEBUG==="1")try{Il(`${E}/checkin-debug.log`,`${new Date().toISOString()} ${d}
34
+ `)}catch{}},l=async()=>{try{let d=new Set((await k.modelRuntime.getAvailable()).map(A=>A.provider).filter(A=>re(A))),y=ye.find(A=>d.has(A));if(a(`providers=${[...d].join(",")||"(none)"} target=${y??"(none)"}`),!y)return!1;let c=(await k.modelRuntime.getAuth(y))?.auth?.apiKey,m=c?.trim().match(/^\$\{?([A-Za-z_][A-Za-z0-9_]*)\}?$|^\{env:([A-Za-z_][A-Za-z0-9_]*)\}$/),b=A=>A?(process.env[A]??"").trim():"",g=m?b(m[1]??m[2])||void 0:c?.trim()||void 0;if(!g)for(let A of["HOWTOFIX_API_KEY","HOWTOFIX_VIP_API_KEY","HOWTOFIX_FREE_API_KEY"]){let R=b(A);if(R){g=R,a(`key dari fallback ${A}`);break}}if(a(`key=${g?`ada(${g.length})`:"(kosong)"}${m?" dari env":""}`),!g)return!1;let S=await Un(g);if(a(`status ok=${S.ok} enabled=${S.enabled} claimed=${S.checkedInToday} msg=${S.message}`),!S.ok||!S.enabled||S.checkedInToday)return!0;let $=await vs(g);return a(`claim ok=${$.ok} awarded=${$.quotaAwarded} msg=${$.message}`),$.ok?(p("check-in",`daily check-in claimed: +${Wn($.quotaAwarded)} credited to your howtofix.id account`),v()):$.blocked&&p("check-in",$.message),!0}catch(d){return a(`error ${d.message}`),!1}};await l()||(await new Promise(d=>setTimeout(d,4e3)),await l())},Ao=async o=>{let s=Ot.check(k.getSessionStats().cost);if(s!==void 0){H(`budget reached: $${s.spent.toFixed(4)} of $${s.limit.toFixed(2)} \u2014 raise it with --max-budget-usd, or start without the flag`);return}let a=k.isStreaming,l=`you-${Date.now()}`;i.items.push({id:l,kind:"user",title:"you",body:o,pending:a?!0:void 0}),a||(C("tally",void 0),Xe.clear(),Kt.clear(),C("run","thinking"),u.beginRun()),v(),w.disableSubmit=!1;let d=Tr(o,e.cwd);Ft=o,await Xs(),Qe=!0;let y=a?k.prompt(d,{streamingBehavior:"steer"}):k.prompt(d);Qe=!1,y.then(()=>Co()).catch(c=>H(c instanceof Error?c.message:String(c)))},zt=o=>{let s=o.trim();if(s){if(ne){let a=ne;ne=void 0,w.setText(""),a(s);return}if(w.setText(""),w.addToHistory(s),s.startsWith("!")){let a=s.slice(1).trim();if(!a)return;i.items.push({id:`sh-${Date.now()}`,kind:"tool",title:"$",body:a}),C("run","shell"),v(),k.executeBash(a,l=>{C("run",`shell \xB7 ${l.length} bytes`),v()}).then(l=>{let d=l.output.trim();i.items.push({id:`sh-out-${Date.now()}`,kind:l.exitCode===0?"result":"error",title:`exit ${l.exitCode??"?"}`,body:d||"(no output)"}),C("tally",void 0),v()}).catch(l=>H(l instanceof Error?l.message:String(l)));return}if(s.startsWith("/")){Ne(s);return}Ao(s)}};w.onSubmit=zt;let Yt=0,To=0,tt=()=>{Ai().then(o=>{o.ok?w.insertTextAtCursor(o.text):p("paste",o.reason),v()}).catch(o=>{p("paste",`could not read the clipboard: ${o instanceof Error?o.message:String(o)}`),v()})};n=tt;let Mo=o=>mn(ke(E).rightClickPaste)&&o.type==="press"&&o.button==="right";r.addInputListener(o=>{if(be){if(V(o,"escape"))return Dt(),{consume:!0};let a=Us(),l=a.matches(o,"tui.select.up"),d=a.matches(o,"tui.select.down");if(l||d){let c=be.getTreeList().getSelectedNode()?.entry.id,m=Js(),b=c===void 0?-1:m.indexOf(c);if(l?b===0:b===m.length-1)return v(),{consume:!0}}return be.handleInput(o),v(),{consume:!0}}if(X&&U&&V(o,"escape"))return Q?(Q=!1,p("workflow","panel keys off; the editor has the keyboard")):I.expanded?(I.expanded=!1,p("workflow","collapsed the drill-in")):(Zn(),p("workflow","panel unpinned; the run is still in the transcript")),It(),v(),{consume:!0};if(ie)return ie.handleInput(o),v(),{consume:!0};if(V(o,"escape")){if(k.isStreaming){Gt=!0;let l=[...k.getSteeringMessages()].map(d=>d.trim()).filter(Boolean);if(l.length>0){let d=w.getText().trim();w.setText(d?`${l.join(`
35
35
  `)}
36
36
  ${d}`:l.join(`
37
- `));let y=new Set(l);for(let c of i.items)c.kind==="user"&&c.pending&&y.has(c.body.trim())&&(c.pending=void 0);m("queued",`${l.length} unread message${l.length===1?"":"s"} returned to the editor`)}return k.abort(),C("note","stopping"),$(),{consume:!0}}let a=Date.now();if(w.getText().length===0&&a-Yt<600)return Yt=0,lo(),{consume:!0};Yt=a;return}if(V(o,"ctrl+c")||$i(o)){if(k.isStreaming)k.abort(),C("note","stopping"),$();else if(w.getText().length>0)w.setText(""),C("note","draft cleared; ctrl+c again quits"),$();else{let a=Date.now();a-To<2e3?_e():(To=a,C("note","press ctrl+c again to quit"),$())}return{consume:!0}}if(V(o,"ctrl+d")&&w.getText().length===0)return _e(),{consume:!0};let s=Math.max(1,i.viewportHeight-1);if(V(o,"pageUp"))return i.scrollOffset+=s,$(),{consume:!0};if(V(o,"pageDown"))return i.scrollOffset=Math.max(0,i.scrollOffset-s),$(),{consume:!0};if(V(o,"home"))return i.scrollOffset=Number.MAX_SAFE_INTEGER,$(),{consume:!0};if(V(o,"end"))return i.scrollOffset=0,$(),{consume:!0};if(V(o,"ctrl+v"))return tt(),{consume:!0};if(V(o,"ctrl+l"))return i.scrollOffset=0,r.scrollToBottom(),$(),{consume:!0};if(V(o,"ctrl+e")){let a=[...i.items].reverse().find(l=>(l.full?.length??0)>0);return a?(a.expanded=a.expanded!==!0,$(),{consume:!0}):(m("expand","nothing to expand in this transcript yet"),{consume:!0})}if(V(o,"ctrl+o")&&!k.isStreaming)return i.items=[{id:"cleared",kind:"note",title:"bench",body:"screen cleared. session history is still stored."}],$(),{consume:!0};if(V(o,"ctrl+t"))return Pe(es(u.thinking)),{consume:!0};if(V(o,"ctrl+shift+t"))return Pe(ts(u.thinking)),{consume:!0};if(V(o,Os)&&X&&U)return Q=!Q,m("workflow",Q?"panel keys active; Esc gives the keyboard back":"panel keys off; the editor has the keyboard"),It(),$(),{consume:!0};if(Q&&X&&U){let a=Es(o);if(a){let l=kn(U,Date.now());if(a==="stop")return L?(L(),L=null,m("workflow","stopping the run; in-flight agents resolve as null")):m("workflow","the run has already finished"),{consume:!0};if(a==="save"){let d=Ns(Vs,or);return m("workflow",d.ok?`saved ${d.path}`:d.reason),$(),{consume:!0}}return Object.assign(I,Ps(I,a,l)),It(),$(),{consume:!0}}}});let Xt=o=>{let s=a=>{C("prompt",`API key for ${a}. Paste it, then press enter.`),$();let l=ne;ne=d=>{ne=l;let y=d.trim();if(!y){C("prompt",void 0),$();return}k.modelRuntime.setRuntimeApiKey(a,y).then(()=>k.modelRuntime.login(a,"api_key",{prompt:async()=>y,notify:()=>{}}).then(()=>m("login",`saved API key for ${a}`),c=>m("login",`key set for this session, but it could not be saved (${c instanceof Error?c.message:String(c)}); run /login again after restarting`)),c=>m("login",c instanceof Error?c.message:String(c)))}};if(o){s(o);return}k.modelRuntime.getAvailable().then(a=>{let l=[...new Set(a.map(d=>d.provider))].sort();if(l.length===0){m("login","no providers are configured; pass one explicitly, e.g. /login nrimo");return}_("Login",l.map(d=>({value:d,label:d})),s)},a=>m("login",a instanceof Error?a.message:String(a)))},Ro=async(o,s)=>{let a=le(P,"models.json"),l,d=!1;try{l=JSON.parse(Bn(a,"utf8"))}catch(K){if(!(K instanceof Error&&"code"in K&&K.code==="ENOENT"))return`could not read ${a}; the models were not added`;l={providers:{}},d=!0}(!l.providers||typeof l.providers!="object")&&(l.providers={});let y=l.providers[o];y||(y=lr(),l.providers[o]=y,d=!0);let c=Array.isArray(y.models)?y.models:[],p=mr(c,s),g=await cr(P).catch(()=>({index:new Map})),b=fr(ur(c,s,g.index));y.models=b.models;try{js(P,{recursive:!0}),ie(a,`${JSON.stringify(l,null,2)}
38
- `)}catch{return`could not write ${a}; the models were not added`}let S=!1;try{await k.modelRuntime.refresh(),S=!0}catch{S=!1}let v=b.changed>0?`, repaired ${b.changed}`:"",A=S?"":"; restart the CLI to see them all",R=d?` (created ${a})`:"";return p===0?`all ${s.length} models were already configured${v}${R}${A}`:`added ${p} model(s) to "${o}"${v}${R}${A}`},Oe=(o,s)=>{(async()=>{if(!o){let b=await br({onProgress:v=>{let A="";try{let K=le(P,".howtofix");js(K,{recursive:!0,mode:448});let J=le(K,"connect-url.txt"),oe=v.kind==="browser"?[v.url]:[v.url,`code: ${v.code}`];Gn(J,oe.join(`
37
+ `));let y=new Set(l);for(let c of i.items)c.kind==="user"&&c.pending&&y.has(c.body.trim())&&(c.pending=void 0);p("queued",`${l.length} unread message${l.length===1?"":"s"} returned to the editor`)}return k.abort(),C("note","stopping"),v(),{consume:!0}}let a=Date.now();if(w.getText().length===0&&a-Yt<600)return Yt=0,lo(),{consume:!0};Yt=a;return}if(V(o,"ctrl+c")||vi(o)){if(k.isStreaming)k.abort(),C("note","stopping"),v();else if(w.getText().length>0)w.setText(""),C("note","draft cleared; ctrl+c again quits"),v();else{let a=Date.now();a-To<2e3?_e():(To=a,C("note","press ctrl+c again to quit"),v())}return{consume:!0}}if(V(o,"ctrl+d")&&w.getText().length===0)return _e(),{consume:!0};let s=Math.max(1,i.viewportHeight-1);if(V(o,"pageUp"))return i.scrollOffset+=s,v(),{consume:!0};if(V(o,"pageDown"))return i.scrollOffset=Math.max(0,i.scrollOffset-s),v(),{consume:!0};if(V(o,"home"))return i.scrollOffset=Number.MAX_SAFE_INTEGER,v(),{consume:!0};if(V(o,"end"))return i.scrollOffset=0,v(),{consume:!0};if(V(o,"ctrl+v"))return tt(),{consume:!0};if(V(o,"ctrl+l"))return i.scrollOffset=0,r.scrollToBottom(),v(),{consume:!0};if(V(o,"ctrl+e")){let a=[...i.items].reverse().find(l=>(l.full?.length??0)>0);return a?(a.expanded=a.expanded!==!0,v(),{consume:!0}):(p("expand","nothing to expand in this transcript yet"),{consume:!0})}if(V(o,"ctrl+o")&&!k.isStreaming)return i.items=[{id:"cleared",kind:"note",title:"bench",body:"screen cleared. session history is still stored."}],v(),{consume:!0};if(V(o,"ctrl+t"))return Pe(ts(u.thinking)),{consume:!0};if(V(o,"ctrl+shift+t"))return Pe(ns(u.thinking)),{consume:!0};if(V(o,Ls)&&X&&U)return Q=!Q,p("workflow",Q?"panel keys active; Esc gives the keyboard back":"panel keys off; the editor has the keyboard"),It(),v(),{consume:!0};if(Q&&X&&U){let a=Ps(o);if(a){let l=kn(U,Date.now());if(a==="stop")return L?(L(),L=null,p("workflow","stopping the run; in-flight agents resolve as null")):p("workflow","the run has already finished"),{consume:!0};if(a==="save"){let d=Fs(zs,or);return p("workflow",d.ok?`saved ${d.path}`:d.reason),v(),{consume:!0}}return Object.assign(I,Is(I,a,l)),It(),v(),{consume:!0}}}});let Xt=o=>{let s=a=>{C("prompt",`API key for ${a}. Paste it, then press enter.`),v();let l=ne;ne=d=>{ne=l;let y=d.trim();if(!y){C("prompt",void 0),v();return}k.modelRuntime.setRuntimeApiKey(a,y).then(()=>k.modelRuntime.login(a,"api_key",{prompt:async()=>y,notify:()=>{}}).then(()=>p("login",`saved API key for ${a}`),c=>p("login",`key set for this session, but it could not be saved (${c instanceof Error?c.message:String(c)}); run /login again after restarting`)),c=>p("login",c instanceof Error?c.message:String(c)))}};if(o){s(o);return}k.modelRuntime.getAvailable().then(a=>{let l=[...new Set(a.map(d=>d.provider))].sort();if(l.length===0){p("login","no providers are configured; pass one explicitly, e.g. /login nrimo");return}_("Login",l.map(d=>({value:d,label:d})),s)},a=>p("login",a instanceof Error?a.message:String(a)))},Ro=async(o,s)=>{let a=le(E,"models.json"),l,d=!1;try{l=JSON.parse(Bn(a,"utf8"))}catch(K){if(!(K instanceof Error&&"code"in K&&K.code==="ENOENT"))return`could not read ${a}; the models were not added`;l={providers:{}},d=!0}(!l.providers||typeof l.providers!="object")&&(l.providers={});let y=l.providers[o];y||(y=cr(),l.providers[o]=y,d=!0);let c=Array.isArray(y.models)?y.models:[],m=mr(c,s),b=await dr(E).catch(()=>({index:new Map})),g=pr(fr(c,s,b.index));y.models=g.models;try{Ds(E,{recursive:!0}),se(a,`${JSON.stringify(l,null,2)}
38
+ `)}catch{return`could not write ${a}; the models were not added`}let S=!1;try{await k.modelRuntime.refresh(),S=!0}catch{S=!1}let $=g.changed>0?`, repaired ${g.changed}`:"",A=S?"":"; restart the CLI to see them all",R=d?` (created ${a})`:"";return m===0?`all ${s.length} models were already configured${$}${R}${A}`:`added ${m} model(s) to "${o}"${$}${R}${A}`},Oe=(o,s)=>{(async()=>{if(!o){let g=await wr({onProgress:$=>{let A="";try{let K=le(E,".howtofix");Ds(K,{recursive:!0,mode:448});let J=le(K,"connect-url.txt"),oe=$.kind==="browser"?[$.url]:[$.url,`code: ${$.code}`];Gn(J,oe.join(`
39
39
  `)+`
40
- `,{mode:384}),A=J}catch{A=""}let R=A?[` saved to ${A}`]:[];v.kind==="browser"?(Ve(v.url),m("connect",["finish signing in to howtofix.id:"," a browser window is opening \u2014 approve the sign-in there",` if it did not open, visit ${v.url}`,...R].join(`
41
- `))):(Ve(v.url),m("connect",["finish signing in to howtofix.id:",` 1. go to ${v.url}`,` 2. enter the code: ${v.code}`," waiting\u2026",...R].join(`
42
- `))),$()}});if(b.ok){C("prompt",void 0),ne=void 0,Oe(b.token,b.credential);return}let S=await Ve(sn);m("connect",[`browser sign-in: ${b.message}`,"","connect with a token instead:",` 1. ${S?"the keys page is opening in your browser":`open ${sn}`}`," 2. sign in if asked, then create a key (starts with sk-)"," 3. run /connect <token>"," or /connect again, and paste the key when asked"].join(`
43
- `)),$();return}if(!dr(o)){m("connect","that does not look like a howtofix token; the Console issues tokens that start with sk-");return}C("note",`connecting to howtofix.id (${an(o)})`),$();let a=await ln(o);if(!a.ok){C("note",void 0),m("connect",a.message),$();return}let l=await Ro("howtofix",a.models);await k.modelRuntime.setRuntimeApiKey("howtofix",o);let d;try{await k.modelRuntime.login("howtofix","api_key",{prompt:async()=>o,notify:()=>{}})}catch(b){d=`this sign-in could not be saved (${b instanceof Error?b.message:String(b)}); run /connect again after restarting`}s&&(vr(P,s)?ge=s:d=`this sign-in renews itself, but the pair could not be saved to ${wr(P)}; it will expire in hours and need /connect again`);let y=!!k.model&&k.model?.provider!==void 0&&u.model!=="unknown",c,p;if(!y)try{let b=(await k.modelRuntime.getAvailable()).filter(A=>se(A.provider)),v=bt(b.map(A=>A.id)).slice(0,4);for(let A of v){if(!(await pr(A,o)).ok)continue;let K=b.find(J=>J.id===A);if(K){await k.setModel(K),u.model=K.id,he(),c=`${K.provider}/${K.id}`;break}}c||(p=v.length>0?`none of the first ${v.length} models answered (${v[0]} did not)`:"the account lists no chat model")}catch(b){p=b instanceof Error?b.message:String(b)}C("note",void 0);let g=await Ae(o);m("connect",[`connected ${an(o)} \u2014 ${a.message}`,l,nt("howtofix",g),c?`using ${c} (change it with /model)`:`pick a model with /model, then send a prompt${p?` (auto-select failed: ${p})`:""}`,d].filter(b=>!!b).join(`
44
- `)),$()})().catch(a=>{C("note",void 0),m("connect",a instanceof Error?a.message:String(a)),$()})},Eo=o=>{(async()=>{let s=Dn(o);if(!s){m("connect",["that is not an account credential."," /connect <email>:<password>"," /connect <base64 of email:password>"].join(`
45
- `)),$();return}C("note",`signing in as ${s.username}`),$();let{token:a}=await gs(gr,s.username,s.password,it),l=ps(P,s.username,s.password);C("note",void 0),m("connect",[`signed in as ${s.username}`,"using the CLI key this account owns \u2014 no new key was made",l?"credential stored \u2014 /connect will not ask again":"could not store the credential, so the next connect will ask again"].join(`
46
- `)),$(),Oe(a)})().catch(s=>{C("note",void 0),m("connect",s instanceof Error?s.message:String(s)),$()})},nt=(o,s)=>{if(!s.ok)return[`${o} account`,` ${s.message}`].join(`
40
+ `,{mode:384}),A=J}catch{A=""}let R=A?[` saved to ${A}`]:[];$.kind==="browser"?(Ve($.url),p("connect",["finish signing in to howtofix.id:"," a browser window is opening \u2014 approve the sign-in there",` if it did not open, visit ${$.url}`,...R].join(`
41
+ `))):(Ve($.url),p("connect",["finish signing in to howtofix.id:",` 1. go to ${$.url}`,` 2. enter the code: ${$.code}`," waiting\u2026",...R].join(`
42
+ `))),v()}});if(g.ok){C("prompt",void 0),ne=void 0,Oe(g.token,g.credential);return}let S=await Ve(sn);p("connect",[`browser sign-in: ${g.message}`,"","connect with a token instead:",` 1. ${S?"the keys page is opening in your browser":`open ${sn}`}`," 2. sign in if asked, then create a key (starts with sk-)"," 3. run /connect <token>"," or /connect again, and paste the key when asked"].join(`
43
+ `)),v();return}if(!ur(o)){p("connect","that does not look like a howtofix token; the Console issues tokens that start with sk-");return}C("note",`connecting to howtofix.id (${an(o)})`),v();let a=await ln(o);if(!a.ok){C("note",void 0),p("connect",a.message),v();return}let l=await Ro("howtofix",a.models);await k.modelRuntime.setRuntimeApiKey("howtofix",o);let d;try{await k.modelRuntime.login("howtofix","api_key",{prompt:async()=>o,notify:()=>{}})}catch(g){d=`this sign-in could not be saved (${g instanceof Error?g.message:String(g)}); run /connect again after restarting`}s&&(xr(E,s)?ge=s:d=`this sign-in renews itself, but the pair could not be saved to ${yr(E)}; it will expire in hours and need /connect again`);let y=!!k.model&&k.model?.provider!==void 0&&u.model!=="unknown",c,m;if(!y)try{let g=(await k.modelRuntime.getAvailable()).filter(A=>re(A.provider)),$=bt(g.map(A=>A.id)).slice(0,4);for(let A of $){if(!(await hr(A,o)).ok)continue;let K=g.find(J=>J.id===A);if(K){await k.setModel(K),u.model=K.id,he(),c=`${K.provider}/${K.id}`;break}}c||(m=$.length>0?`none of the first ${$.length} models answered (${$[0]} did not)`:"the account lists no chat model")}catch(g){m=g instanceof Error?g.message:String(g)}C("note",void 0);let b=await Ae(o);p("connect",[`connected ${an(o)} \u2014 ${a.message}`,l,nt("howtofix",b),c?`using ${c} (change it with /model)`:`pick a model with /model, then send a prompt${m?` (auto-select failed: ${m})`:""}`,d].filter(g=>!!g).join(`
44
+ `)),v()})().catch(a=>{C("note",void 0),p("connect",a instanceof Error?a.message:String(a)),v()})},Eo=o=>{(async()=>{let s=Dn(o);if(!s){p("connect",["that is not an account credential."," /connect <email>:<password>"," /connect <base64 of email:password>"].join(`
45
+ `)),v();return}C("note",`signing in as ${s.username}`),v();let{token:a}=await bs(br,s.username,s.password,it),l=hs(E,s.username,s.password);C("note",void 0),p("connect",[`signed in as ${s.username}`,"using the CLI key this account owns \u2014 no new key was made",l?"credential stored \u2014 /connect will not ask again":"could not store the credential, so the next connect will ask again"].join(`
46
+ `)),v(),Oe(a)})().catch(s=>{C("note",void 0),p("connect",s instanceof Error?s.message:String(s)),v()})},nt=(o,s)=>{if(!s.ok)return[`${o} account`,` ${s.message}`].join(`
47
47
  `);if(s.unlimited)return[`${o} account`," quota no limit on this token"].join(`
48
48
  `);if(s.limit===void 0||s.used===void 0){let a=[`${o} account`],l=d=>`${d.toFixed(2)} ${s.unit}`;return s.limit!==void 0&&a.push(` granted ${l(s.limit)}`),s.used!==void 0&&a.push(` spent ${l(s.used)}`),s.remaining!==void 0&&a.push(` remaining ${l(s.remaining)}`),a.join(`
49
- `)}return ds(o,s.limit,s.used,s.unit).join(`
50
- `)},Le=()=>({mcpServers:_r()}),sa=o=>{let s=Object.keys(o??{});return s.length===0?[]:s.map(a=>` mcp ${a} ${at(o[a])}`)},aa=o=>{let s=Xo(o.dir,o.manifest),a=o.manifest.skills.join(", ");return[o.manifest.description,` category ${o.manifest.category}`,` version ${o.manifest.version}`,` skills ${a}`,o.manifest.prompt?` prompt ${o.manifest.prompt}`:" prompt (none)",` size ${s} bytes of skill text`,` source ${o.source}`,...sa(o.manifest.mcp)].join(`
51
- `)},Po=o=>{let s=[aa(o),""];if(o.manifest.prompt){let a=le(o.dir,o.manifest.prompt);Rt(a)&&s.push(`--- ${o.manifest.prompt} ---`,Bn(a,"utf8").trim(),"")}for(let a of o.manifest.skills){let l=le(o.dir,"skills",a,"SKILL.md");Rt(l)&&s.push(`--- skills/${a}/SKILL.md ---`,Bn(l,"utf8").trim(),"")}return s.join(`
52
- `)},Se=async()=>{await k.reload()},Jt=!1,Io=async o=>{if(Jt){m("preset","an install is already running; wait for it to finish");return}Jt=!0;try{let s;try{s=await o()}catch(c){H(`preset not installed: ${c instanceof Error?c.message:String(c)}`);return}if(!s.ok||!s.name){H(`preset not installed:
49
+ `)}return us(o,s.limit,s.used,s.unit).join(`
50
+ `)},Le=()=>({mcpServers:Or()}),aa=o=>{let s=Object.keys(o??{});return s.length===0?[]:s.map(a=>` mcp ${a} ${at(o[a])}`)},la=o=>{let s=Xo(o.dir,o.manifest),a=o.manifest.skills.join(", ");return[o.manifest.description,` category ${o.manifest.category}`,` version ${o.manifest.version}`,` skills ${a}`,o.manifest.prompt?` prompt ${o.manifest.prompt}`:" prompt (none)",` size ${s} bytes of skill text`,` source ${o.source}`,...aa(o.manifest.mcp)].join(`
51
+ `)},Po=o=>{let s=[la(o),""];if(o.manifest.prompt){let a=le(o.dir,o.manifest.prompt);Rt(a)&&s.push(`--- ${o.manifest.prompt} ---`,Bn(a,"utf8").trim(),"")}for(let a of o.manifest.skills){let l=le(o.dir,"skills",a,"SKILL.md");Rt(l)&&s.push(`--- skills/${a}/SKILL.md ---`,Bn(l,"utf8").trim(),"")}return s.join(`
52
+ `)},Se=async()=>{await k.reload()},Jt=!1,Io=async o=>{if(Jt){p("preset","an install is already running; wait for it to finish");return}Jt=!0;try{let s;try{s=await o()}catch(c){H(`preset not installed: ${c instanceof Error?c.message:String(c)}`);return}if(!s.ok||!s.name){H(`preset not installed:
53
53
  ${s.problems.join(`
54
54
  `)}`);return}await Se();let a=ee(e.cwd).entries.find(c=>c.manifest.name===s.name),l=a?.manifest.integrates||a?.manifest.mcp,d=l?`
55
55
  integration disabled by default; run /preset enable ${s.name} when you want to use it`:await _o(s.name);l&&a&&Gn(le(a.dir,".disabled"),`installed
56
- `);let y=s.modelInvocable===!1?`its skill ${s.skill} is invoke-only (disable-model-invocation): the model cannot choose it, run /skill:${s.skill} yourself`:"its skill is in the model's catalogue from the next message";m("preset",`installed ${s.name} into ${s.target}
57
- ${y}${d}`)}finally{Jt=!1}},ot=new ze({initial:Object.keys(Le().mcpServers),apply:async(o,s)=>{if(await Se(),o.length>0||s.length>0){let a=[];o.length>0&&a.push(`connected ${o.join(", ")}`),s.length>0&&a.push(`stopped ${s.join(", ")}`),m(o.length>0?"mcp connected":"mcp stopped",a.join("; "))}},report:o=>H(o)}),rt=async()=>{let o=Object.keys(Le().mcpServers);return await ot.reconcile(o)},_o=async o=>{let{entries:s}=ee(e.cwd),l=s.find(c=>c.manifest.name===o)?.manifest.mcp;if(!l||Object.keys(l).length===0)return"";let d=tn(l);if(d.problems.length>0)return`
58
- MCP: ${d.problems.join("; ")}`;let y=[];if(d.added.length>0){let c=await rt(),p=d.added.filter(g=>c.added.includes(g));y.push(p.length>0?`MCP servers connected: ${p.join(", ")}`:`MCP servers added to mcp.json: ${d.added.join(", ")}`)}return d.skipped.length>0&&y.push(`MCP servers kept as they were (already configured): ${d.skipped.join(", ")}`),y.length>0?`
56
+ `);let y=s.modelInvocable===!1?`its skill ${s.skill} is invoke-only (disable-model-invocation): the model cannot choose it, run /skill:${s.skill} yourself`:"its skill is in the model's catalogue from the next message";p("preset",`installed ${s.name} into ${s.target}
57
+ ${y}${d}`)}finally{Jt=!1}},ot=new ze({initial:Object.keys(Le().mcpServers),apply:async(o,s)=>{if(await Se(),o.length>0||s.length>0){let a=[];o.length>0&&a.push(`connected ${o.join(", ")}`),s.length>0&&a.push(`stopped ${s.join(", ")}`),p(o.length>0?"mcp connected":"mcp stopped",a.join("; "))}},report:o=>H(o)}),rt=async()=>{let o=Object.keys(Le().mcpServers);return await ot.reconcile(o)},_o=async o=>{let{entries:s}=ee(e.cwd),l=s.find(c=>c.manifest.name===o)?.manifest.mcp;if(!l||Object.keys(l).length===0)return"";let d=tn(l);if(d.problems.length>0)return`
58
+ MCP: ${d.problems.join("; ")}`;let y=[];if(d.added.length>0){let c=await rt(),m=d.added.filter(b=>c.added.includes(b));y.push(m.length>0?`MCP servers connected: ${m.join(", ")}`:`MCP servers added to mcp.json: ${d.added.join(", ")}`)}return d.skipped.length>0&&y.push(`MCP servers kept as they were (already configured): ${d.skipped.join(", ")}`),y.length>0?`
59
59
  ${y.join(`
60
- `)}`:""},Oo=o=>Io(async()=>Zo(o,ct(e.cwd))),Lo=o=>{let s=o.sizeKb>=1024?`${(o.sizeKb/1024).toFixed(1)} MB`:`${o.sizeKb} KB`;return m("preset",[`downloading ${o.title}`,` from ${o.repo} @ ${o.sha.slice(0,7)}`,` skill ${o.skill}${o.modelInvocable===!1?" (invoke-only: the model cannot choose it)":""}`,` size ~${s} \xB7 ${o.license}`," checking the pinned commit and the contents the registry recorded\u2026"].join(`
61
- `)),Io(()=>tr(o,ct(e.cwd)))},Zt=(o,s)=>{_(s,o.map(a=>({value:a.name,label:a.title,description:a.description})),a=>{let l=o.find(y=>y.name===a);if(!l)return;let d=l.sizeKb>=1024?`${(l.sizeKb/1024).toFixed(1)} MB`:`${l.sizeKb} KB`;_(l.title,[{value:"install",label:"Install",description:`download ~${d} and add its skill to this project`},{value:"view",label:"View contents",description:"read what it contains before downloading"},{value:"back",label:"Back",description:"return to the menu"}],y=>{if(y==="install"){Lo(l);return}if(y==="view"){m(`preset ${l.name}`,[`${l.description}`,"",`skill ${l.skill}`,`source ${l.repo} @ ${l.sha.slice(0,7)}`,`licence ${l.license}`,`size ~${d}`,`category ${l.category}`,`model ${l.modelInvocable===!1?"invoke-only \u2014 the model cannot choose it, only /skill:"+l.skill:"the model can choose it from its catalogue"}`,"","Install downloads the skill and adds it to this project."].join(`
62
- `));return}Fo()})},()=>$())},Ce=(o,s)=>{_(s,o.map(a=>({value:a.manifest.name,label:a.manifest.title,description:a.manifest.skills.length>0?`${a.manifest.skills.join(", ")} \u2014 ${a.manifest.description}`:a.manifest.description})),a=>{let l=o.find(d=>d.manifest.name===a);l&&_(l.manifest.title,[{value:"install",label:"Install",description:"add its skills and rules to this project"},{value:"view",label:"View contents",description:"read the skills and prompt first"},{value:"back",label:"Back",description:"return to the menu"}],d=>{if(d==="install"){Oo(l.dir);return}if(d==="view"){m(`preset ${l.manifest.name}`,Po(l));return}Wo("")})},()=>$())},No=o=>o.filter(s=>s.manifest.integrates!==void 0),la=()=>{let{entries:o}=ee(e.cwd),s=No(o);if(s.length===0){m("integrations","nothing installed that drives another application. /preset lists the rest.");return}Ce(s,"Integrations")},Fo=()=>{let{entries:o}=ee(e.cwd),s=[{value:"skills",label:"Skills",description:"bundles of skills and prompt text, installed into the project"},{value:"mcp",label:"MCP",description:"Model Context Protocol servers, added to mcp.json"}],a=No(o).length;a>0&&s.push({value:"integrations",label:"Integrations",description:`${a} that drive another application, and need setup there first`}),_("Presets",s,l=>l==="mcp"?Qt():l==="integrations"?la():ca())},Qt=()=>{let{entries:o,problems:s}=Ko();if(s.length>0&&m("mcp problems",s.join(`
63
- `)),o.length===0){m("mcp catalogue","no servers in the catalogue. run /mcp to inspect the ones already configured.");return}let a=new Set(Object.keys(Le().mcpServers)),l=new Map,d=[];for(let y of Ho(o)){let c=Bo(o,y);l.set(y,()=>jo(c,y));let p=c.filter(g=>a.has(g.name)).length;d.push({value:y,label:y,description:`${c.map(g=>g.title).join(", ")}${p>0?` \xB7 ${p} configured`:""}`})}l.set("all-mcp",()=>jo(o,"All MCP servers")),d.push({value:"all-mcp",label:"All servers",description:`${o.length} available${a.size>0?`, ${a.size} already configured`:""}`}),_("MCP servers",d,y=>l.get(y)?.())},jo=(o,s)=>{let a=Le().mcpServers;_(s,o.map(l=>{let d=a[l.name]!==void 0?"configured \xB7 ":"";return{value:l.name,label:l.title,description:`${d}${l.description}`}}),l=>{let d=Go(o,l);if(!d)return;let y=a[d.name]!==void 0,c=qo(d),p=[d.description,"",`server ${d.name}`,`runs ${at(lt(d))}`,...d.needs&&d.needs.length>0?[`needs ${d.needs.join(", ")}`,c.length>0?` ${c.join(", ")} ${c.length===1?"is":"are"} not set in this shell \u2014 the value is read at connect time, so export it before the next session`:" all set in this shell"]:[],...d.docs?[`docs ${d.docs}`]:[],"",y?"already in mcp.json \u2014 removing it takes the entry out; nothing else changes":"install writes this server into mcp.json. nothing is downloaded, and it connects on the next session"].join(`
64
- `),g=y?[{value:"remove",label:"Remove",description:"take the server out of mcp.json"},{value:"view",label:"Details",description:"what it runs and what it needs"},{value:"back",label:"Back",description:"return to the list"}]:[{value:"install",label:"Install",description:"add the server to mcp.json"},{value:"view",label:"Details",description:"what it runs and what it needs"},{value:"back",label:"Back",description:"return to the list"}];_(d.title,g,b=>{if(b==="view"){m(`mcp ${d.name}`,p);return}if(b==="install"){let S=[];if(d.preset){let R=le(Vo(),"mcp",d.preset.replace(/^mcp-/,""));if(Rt(le(R,"preset.json"))){let K=Jo(R,ct(e.cwd));K.ok||S.push(...K.problems)}}let v=tn({[d.name]:lt(d)});if(S.push(...v.problems),S.length>0){H(`mcp not installed:
60
+ `)}`:""},Oo=o=>Io(async()=>Zo(o,ct(e.cwd))),Lo=o=>{let s=o.sizeKb>=1024?`${(o.sizeKb/1024).toFixed(1)} MB`:`${o.sizeKb} KB`;return p("preset",[`downloading ${o.title}`,` from ${o.repo} @ ${o.sha.slice(0,7)}`,` skill ${o.skill}${o.modelInvocable===!1?" (invoke-only: the model cannot choose it)":""}`,` size ~${s} \xB7 ${o.license}`," checking the pinned commit and the contents the registry recorded\u2026"].join(`
61
+ `)),Io(()=>tr(o,ct(e.cwd)))},Zt=(o,s)=>{_(s,o.map(a=>({value:a.name,label:a.title,description:a.description})),a=>{let l=o.find(y=>y.name===a);if(!l)return;let d=l.sizeKb>=1024?`${(l.sizeKb/1024).toFixed(1)} MB`:`${l.sizeKb} KB`;_(l.title,[{value:"install",label:"Install",description:`download ~${d} and add its skill to this project`},{value:"view",label:"View contents",description:"read what it contains before downloading"},{value:"back",label:"Back",description:"return to the menu"}],y=>{if(y==="install"){Lo(l);return}if(y==="view"){p(`preset ${l.name}`,[`${l.description}`,"",`skill ${l.skill}`,`source ${l.repo} @ ${l.sha.slice(0,7)}`,`licence ${l.license}`,`size ~${d}`,`category ${l.category}`,`model ${l.modelInvocable===!1?"invoke-only \u2014 the model cannot choose it, only /skill:"+l.skill:"the model can choose it from its catalogue"}`,"","Install downloads the skill and adds it to this project."].join(`
62
+ `));return}Fo()})},()=>v())},Ce=(o,s)=>{_(s,o.map(a=>({value:a.manifest.name,label:a.manifest.title,description:a.manifest.skills.length>0?`${a.manifest.skills.join(", ")} \u2014 ${a.manifest.description}`:a.manifest.description})),a=>{let l=o.find(d=>d.manifest.name===a);l&&_(l.manifest.title,[{value:"install",label:"Install",description:"add its skills and rules to this project"},{value:"view",label:"View contents",description:"read the skills and prompt first"},{value:"back",label:"Back",description:"return to the menu"}],d=>{if(d==="install"){Oo(l.dir);return}if(d==="view"){p(`preset ${l.manifest.name}`,Po(l));return}Wo("")})},()=>v())},No=o=>o.filter(s=>s.manifest.integrates!==void 0),ca=()=>{let{entries:o}=ee(e.cwd),s=No(o);if(s.length===0){p("integrations","nothing installed that drives another application. /preset lists the rest.");return}Ce(s,"Integrations")},Fo=()=>{let{entries:o}=ee(e.cwd),s=[{value:"skills",label:"Skills",description:"bundles of skills and prompt text, installed into the project"},{value:"mcp",label:"MCP",description:"Model Context Protocol servers, added to mcp.json"}],a=No(o).length;a>0&&s.push({value:"integrations",label:"Integrations",description:`${a} that drive another application, and need setup there first`}),_("Presets",s,l=>l==="mcp"?Qt():l==="integrations"?ca():da())},Qt=()=>{let{entries:o,problems:s}=Ko();if(s.length>0&&p("mcp problems",s.join(`
63
+ `)),o.length===0){p("mcp catalogue","no servers in the catalogue. run /mcp to inspect the ones already configured.");return}let a=new Set(Object.keys(Le().mcpServers)),l=new Map,d=[];for(let y of Ho(o)){let c=Bo(o,y);l.set(y,()=>jo(c,y));let m=c.filter(b=>a.has(b.name)).length;d.push({value:y,label:y,description:`${c.map(b=>b.title).join(", ")}${m>0?` \xB7 ${m} configured`:""}`})}l.set("all-mcp",()=>jo(o,"All MCP servers")),d.push({value:"all-mcp",label:"All servers",description:`${o.length} available${a.size>0?`, ${a.size} already configured`:""}`}),_("MCP servers",d,y=>l.get(y)?.())},jo=(o,s)=>{let a=Le().mcpServers;_(s,o.map(l=>{let d=a[l.name]!==void 0?"configured \xB7 ":"";return{value:l.name,label:l.title,description:`${d}${l.description}`}}),l=>{let d=Go(o,l);if(!d)return;let y=a[d.name]!==void 0,c=qo(d),m=[d.description,"",`server ${d.name}`,`runs ${at(lt(d))}`,...d.needs&&d.needs.length>0?[`needs ${d.needs.join(", ")}`,c.length>0?` ${c.join(", ")} ${c.length===1?"is":"are"} not set in this shell \u2014 the value is read at connect time, so export it before the next session`:" all set in this shell"]:[],...d.docs?[`docs ${d.docs}`]:[],"",y?"already in mcp.json \u2014 removing it takes the entry out; nothing else changes":"install writes this server into mcp.json. nothing is downloaded, and it connects on the next session"].join(`
64
+ `),b=y?[{value:"remove",label:"Remove",description:"take the server out of mcp.json"},{value:"view",label:"Details",description:"what it runs and what it needs"},{value:"back",label:"Back",description:"return to the list"}]:[{value:"install",label:"Install",description:"add the server to mcp.json"},{value:"view",label:"Details",description:"what it runs and what it needs"},{value:"back",label:"Back",description:"return to the list"}];_(d.title,b,g=>{if(g==="view"){p(`mcp ${d.name}`,m);return}if(g==="install"){let S=[];if(d.preset){let R=le(Vo(),"mcp",d.preset.replace(/^mcp-/,""));if(Rt(le(R,"preset.json"))){let K=Jo(R,ct(e.cwd));K.ok||S.push(...K.problems)}}let $=tn({[d.name]:lt(d)});if(S.push(...$.problems),S.length>0){H(`mcp not installed:
65
65
  ${S.join(`
66
- `)}`);return}if(v.skipped.length>0){m("mcp install",`${d.name} is already in mcp.json; it was left as it is.`);return}let A=c.length>0?`
67
- ${c.join(", ")} ${c.length===1?"is":"are"} not set in this shell \u2014 the value is read when the server connects, so export ${c.length===1?"it":"them"} and reload, or it will fail every call`:"";m("mcp installed",[`added ${d.name} to mcp.json${d.preset?" and installed its skill preset":""}`,` runs ${at(lt(d))}`,` connecting now; /mcp shows its state and its tools${A}`].join(`
68
- `)),rt().catch(R=>{H(`mcp installed but the session was not updated: ${R instanceof Error?R.message:String(R)}`)});return}if(b==="remove"){let S=st([d.name]);if(S.problems.length>0){H(`mcp not removed:
66
+ `)}`);return}if($.skipped.length>0){p("mcp install",`${d.name} is already in mcp.json; it was left as it is.`);return}let A=c.length>0?`
67
+ ${c.join(", ")} ${c.length===1?"is":"are"} not set in this shell \u2014 the value is read when the server connects, so export ${c.length===1?"it":"them"} and reload, or it will fail every call`:"";p("mcp installed",[`added ${d.name} to mcp.json${d.preset?" and installed its skill preset":""}`,` runs ${at(lt(d))}`,` connecting now; /mcp shows its state and its tools${A}`].join(`
68
+ `)),rt().catch(R=>{H(`mcp installed but the session was not updated: ${R instanceof Error?R.message:String(R)}`)});return}if(g==="remove"){let S=st([d.name]);if(S.problems.length>0){H(`mcp not removed:
69
69
  ${S.problems.join(`
70
- `)}`);return}rt().then(v=>{m("mcp remove",v.removed.length>0?`removed ${v.removed.join(", ")} from mcp.json and stopped ${v.removed.length===1?"it":"them"}`:S.removed.length>0?`removed ${d.name} from mcp.json`:`${d.name} was not in mcp.json`)}).catch(v=>{H(`mcp removed from config but the session was not updated: ${v instanceof Error?v.message:String(v)}`)});return}Qt()})},()=>Qt())},ca=()=>{let{entries:o,problems:s}=ee(e.cwd),{entries:a,problems:l}=dt();s.length>0&&m("preset problems",s.join(`
71
- `)),l.length>0&&m("preset problems",l.join(`
72
- `));let d=o.filter(p=>p.source==="installed"),y=new Map,c=[];d.length>0&&(y.set("installed",()=>Ce(d,"Installed presets")),c.push({value:"installed",label:"Installed",description:`${d.length} active`}));for(let p of zo(o)){let g=Yo(o,p),b=on(a,p);y.set(p,()=>b.length>0?Do(g,p,b):Ce(g,p));let S=g.map(v=>`${v.manifest.title} (${v.manifest.skills.join(", ")})`).join(", ");c.push({value:p,label:p,description:`${S}${b.length>0?` \xB7 ${b.length} more to download`:""}`})}for(let p of er(a)){if(o.some(b=>b.manifest.category===p))continue;let g=on(a,p);y.set(p,()=>Zt(g,p)),c.push({value:p,label:p,description:`${g.length} to download`})}if(y.set("all",()=>Ce(o,"All presets")),c.push({value:"all",label:"All presets",description:`${o.length} ready to install`}),a.length>0){y.set("hub",()=>Do([],"Community presets",a));let p=new Set(a.map(g=>g.repo)).size;c.push({value:"hub",label:"Community",description:`${a.length} to download, from ${p} projects`})}_("Skill presets",c,p=>y.get(p)?.())},Do=(o,s,a)=>{if(a.length===0){Ce(o,s);return}if(o.length===0){Zt(a,`${s} (download)`);return}_(s,[{value:"local",label:`Included (${o.length})`,description:"already on disk, no download"},{value:"hub",label:`Downloadable (${a.length})`,description:"fetched when installed"}],l=>l==="local"?Ce(o,s):Zt(a,s))},Wo=o=>{let[s,...a]=o.trim().split(/\s+/),l=a.join(" ").trim();if(!s){Fo();return}if(s==="list"){let{entries:d}=ee(e.cwd),y=d.filter(c=>c.source==="installed");if(y.length===0){m("preset list","nothing installed. run /preset to browse the catalogue.");return}m("preset list",y.map(c=>`${c.manifest.name} ${c.manifest.version} [${nn(c.dir)?"disabled":"active"}]
70
+ `)}`);return}rt().then($=>{p("mcp remove",$.removed.length>0?`removed ${$.removed.join(", ")} from mcp.json and stopped ${$.removed.length===1?"it":"them"}`:S.removed.length>0?`removed ${d.name} from mcp.json`:`${d.name} was not in mcp.json`)}).catch($=>{H(`mcp removed from config but the session was not updated: ${$ instanceof Error?$.message:String($)}`)});return}Qt()})},()=>Qt())},da=()=>{let{entries:o,problems:s}=ee(e.cwd),{entries:a,problems:l}=dt();s.length>0&&p("preset problems",s.join(`
71
+ `)),l.length>0&&p("preset problems",l.join(`
72
+ `));let d=o.filter(m=>m.source==="installed"),y=new Map,c=[];d.length>0&&(y.set("installed",()=>Ce(d,"Installed presets")),c.push({value:"installed",label:"Installed",description:`${d.length} active`}));for(let m of zo(o)){let b=Yo(o,m),g=on(a,m);y.set(m,()=>g.length>0?Do(b,m,g):Ce(b,m));let S=b.map($=>`${$.manifest.title} (${$.manifest.skills.join(", ")})`).join(", ");c.push({value:m,label:m,description:`${S}${g.length>0?` \xB7 ${g.length} more to download`:""}`})}for(let m of er(a)){if(o.some(g=>g.manifest.category===m))continue;let b=on(a,m);y.set(m,()=>Zt(b,m)),c.push({value:m,label:m,description:`${b.length} to download`})}if(y.set("all",()=>Ce(o,"All presets")),c.push({value:"all",label:"All presets",description:`${o.length} ready to install`}),a.length>0){y.set("hub",()=>Do([],"Community presets",a));let m=new Set(a.map(b=>b.repo)).size;c.push({value:"hub",label:"Community",description:`${a.length} to download, from ${m} projects`})}_("Skill presets",c,m=>y.get(m)?.())},Do=(o,s,a)=>{if(a.length===0){Ce(o,s);return}if(o.length===0){Zt(a,`${s} (download)`);return}_(s,[{value:"local",label:`Included (${o.length})`,description:"already on disk, no download"},{value:"hub",label:`Downloadable (${a.length})`,description:"fetched when installed"}],l=>l==="local"?Ce(o,s):Zt(a,s))},Wo=o=>{let[s,...a]=o.trim().split(/\s+/),l=a.join(" ").trim();if(!s){Fo();return}if(s==="list"){let{entries:d}=ee(e.cwd),y=d.filter(c=>c.source==="installed");if(y.length===0){p("preset list","nothing installed. run /preset to browse the catalogue.");return}p("preset list",y.map(c=>`${c.manifest.name} ${c.manifest.version} [${nn(c.dir)?"disabled":"active"}]
73
73
  ${c.manifest.description}
74
74
  ${c.dir}`).join(`
75
- `));return}if(s==="show"){if(!l){m("preset show","usage: /preset show <name>");return}let{entries:d}=ee(e.cwd),y=d.find(b=>b.manifest.name===l);if(y){m(`preset ${l}`,Po(y));return}let{entries:c}=dt(),p=rn(c,l);if(!p){m("preset show",`no preset named "${l}". run /preset to list them.`);return}let g=p.sizeKb>=1024?`${(p.sizeKb/1024).toFixed(1)} MB`:`${p.sizeKb} KB`;m(`preset ${l}`,[p.description,"",`skill ${p.skill}`,`source ${p.repo} @ ${p.sha.slice(0,7)}`,`licence ${p.license}`,`size ~${g}`,`category ${p.category}`,"","not installed. install it from /preset, or: /preset add-hub "+p.name].join(`
76
- `));return}if(s==="add"){if(!l){m("preset add","usage: /preset add <git-url | directory>");return}Oo(l);return}if(s==="add-hub"){if(!l){m("preset add-hub","usage: /preset add-hub <name> (see /preset for names)");return}let{entries:d}=dt(),y=rn(d,l);if(!y){m("preset add-hub",`"${l}" is not in the community registry. run /preset to browse it.`);return}Lo(y);return}if(s==="enable"||s==="disable"){if(!l){m(`preset ${s}`,`usage: /preset ${s} <name>`);return}let d=ee(e.cwd).entries.find(c=>c.manifest.name===l&&c.source==="installed");if(!d){m(`preset ${s}`,`no installed preset named "${l}"`);return}let y=le(d.dir,".disabled");if(s==="disable"){Gn(y,`disabled
77
- `);let c=d.manifest.mcp?st(Object.keys(d.manifest.mcp)):{removed:[],kept:[],problems:[]};rt().then(()=>Se()).then(()=>m("preset",`disabled ${l}${c.removed.length?`; stopped ${c.removed.join(", ")}`:""}`)).catch(p=>H(`preset disable failed: ${p instanceof Error?p.message:String(p)}`));return}Il(y,{force:!0}),_o(l).then(c=>Se().then(()=>m("preset",`enabled ${l}${c}`))).catch(c=>H(`preset enable failed: ${c instanceof Error?c.message:String(c)}`));return}if(s==="remove"){if(!l){m("preset remove","usage: /preset remove <name>");return}let d=Qo(l,e.cwd);if(d.problems.length>0){m("preset remove",d.problems.join(`
78
- `));return}let c=ee(e.cwd).entries.find(v=>v.manifest.name===l),p=new Set;for(let v of ee(e.cwd).entries)if(v.manifest.name!==l)for(let A of Object.keys(v.manifest.mcp??{}))p.add(A);let g=c?.manifest.mcp?st(Object.keys(c.manifest.mcp),p):{removed:[],kept:[],problems:[]},b=g.removed.length>0?`
79
- MCP servers removed from mcp.json: ${g.removed.join(", ")}`:g.kept.length>0?`
80
- MCP servers kept (still used by another preset): ${g.kept.join(", ")}`:"",S=g.problems.length>0?`
81
- MCP: ${g.problems.join("; ")}`:"";Se().then(()=>{m("preset",`removed ${l}
75
+ `));return}if(s==="show"){if(!l){p("preset show","usage: /preset show <name>");return}let{entries:d}=ee(e.cwd),y=d.find(g=>g.manifest.name===l);if(y){p(`preset ${l}`,Po(y));return}let{entries:c}=dt(),m=rn(c,l);if(!m){p("preset show",`no preset named "${l}". run /preset to list them.`);return}let b=m.sizeKb>=1024?`${(m.sizeKb/1024).toFixed(1)} MB`:`${m.sizeKb} KB`;p(`preset ${l}`,[m.description,"",`skill ${m.skill}`,`source ${m.repo} @ ${m.sha.slice(0,7)}`,`licence ${m.license}`,`size ~${b}`,`category ${m.category}`,"","not installed. install it from /preset, or: /preset add-hub "+m.name].join(`
76
+ `));return}if(s==="add"){if(!l){p("preset add","usage: /preset add <git-url | directory>");return}Oo(l);return}if(s==="add-hub"){if(!l){p("preset add-hub","usage: /preset add-hub <name> (see /preset for names)");return}let{entries:d}=dt(),y=rn(d,l);if(!y){p("preset add-hub",`"${l}" is not in the community registry. run /preset to browse it.`);return}Lo(y);return}if(s==="enable"||s==="disable"){if(!l){p(`preset ${s}`,`usage: /preset ${s} <name>`);return}let d=ee(e.cwd).entries.find(c=>c.manifest.name===l&&c.source==="installed");if(!d){p(`preset ${s}`,`no installed preset named "${l}"`);return}let y=le(d.dir,".disabled");if(s==="disable"){Gn(y,`disabled
77
+ `);let c=d.manifest.mcp?st(Object.keys(d.manifest.mcp)):{removed:[],kept:[],problems:[]};rt().then(()=>Se()).then(()=>p("preset",`disabled ${l}${c.removed.length?`; stopped ${c.removed.join(", ")}`:""}`)).catch(m=>H(`preset disable failed: ${m instanceof Error?m.message:String(m)}`));return}_l(y,{force:!0}),_o(l).then(c=>Se().then(()=>p("preset",`enabled ${l}${c}`))).catch(c=>H(`preset enable failed: ${c instanceof Error?c.message:String(c)}`));return}if(s==="remove"){if(!l){p("preset remove","usage: /preset remove <name>");return}let d=Qo(l,e.cwd);if(d.problems.length>0){p("preset remove",d.problems.join(`
78
+ `));return}let c=ee(e.cwd).entries.find($=>$.manifest.name===l),m=new Set;for(let $ of ee(e.cwd).entries)if($.manifest.name!==l)for(let A of Object.keys($.manifest.mcp??{}))m.add(A);let b=c?.manifest.mcp?st(Object.keys(c.manifest.mcp),m):{removed:[],kept:[],problems:[]},g=b.removed.length>0?`
79
+ MCP servers removed from mcp.json: ${b.removed.join(", ")}`:b.kept.length>0?`
80
+ MCP servers kept (still used by another preset): ${b.kept.join(", ")}`:"",S=b.problems.length>0?`
81
+ MCP: ${b.problems.join("; ")}`:"";Se().then(()=>{p("preset",`removed ${l}
82
82
  ${d.removed.join(`
83
- `)}${b}${S}`)});return}m("preset",`unknown subcommand "${s}". try: list, show, add, add-hub, remove.`)},Ne=async o=>{let[s,...a]=o.slice(1).split(/\s+/),l=a.join(" ");if(s==="quit"||s==="exit"){_e();return}if(s==="help"){m("help",qn(k).map(c=>`/${c.name} ${c.description??""}`).join(`
84
- `));return}if(s==="init"){let c=le(e.cwd,"AGENTS.md");if(Rt(c)&&l!=="force"){m("init",`AGENTS.md already exists at ${c}. run /init force to overwrite.`);return}ie(c,Uo),m("init",`wrote ${c}; asking the agent to fill it in`),await k.prompt("Read AGENTS.md, then fill it in with the real build, test, and layout facts of this repo. Keep it short.");return}if(s==="login"){Xt(l);return}if(s==="connect"){let c=l.trim();if(c&&!c.startsWith("sk-")&&Dn(c)){Eo(c);return}if(c){Oe(c);return}let p=hs(P);if(p){Eo(p.credential);return}Oe(""),C("prompt","paste your howtofix.id token, then press enter"),$();let g=ne;ne=b=>{ne=g,C("prompt",void 0),Oe(b.trim())};return}if(s==="sync"){let c=new Set((await k.modelRuntime.getAvailable()).map(R=>R.provider).filter(R=>se(R))),p=ye.find(R=>c.has(R));if(!p){m("sync","no howtofix.id account is connected; run /connect first");return}C("note",`re-syncing ${p} from howtofix.id`),$();let b=(await k.modelRuntime.getAuth(p))?.auth?.apiKey;if(!b){C("note",void 0),m("sync",`${p} has no usable key; run /connect to sign in again`),$();return}let S=await ln(b);if(!S.ok){C("note",void 0),m("sync",S.message),$();return}let v=await Ro(p,S.models),A=await Ae(b);C("note",void 0),m("sync",`${v}
85
- ${nt(p,A)}`),await k.modelRuntime.refresh(),$();return}if(s==="usage"){let c=new Set((await k.modelRuntime.getAvailable()).map(R=>R.provider).filter(R=>se(R))),p=ye.find(R=>c.has(R));if(!p){m("usage","no howtofix.id account is connected; run /connect first");return}C("note","asking howtofix.id for the account usage"),$();let b=(await k.modelRuntime.getAuth(p))?.auth?.apiKey;if(!b){C("note",void 0),m("usage",`${p} has no usable key; run /connect to sign in again`),$();return}let S=await Ae(b),v=await Un(b);C("note",void 0);let A=v.ok&&v.enabled?v.checkedInToday?`check-in: claimed today (+${Wn(v.quotaToday)})`:"check-in: not claimed yet today (it claims itself on the next start)":"";m("usage",A?`${nt(p,S)}
86
- ${A}`:nt(p,S)),$();return}if(s==="logout"){let c=await k.modelRuntime.getAvailable(),p=[...new Set(c.map(g=>g.provider))].sort();if(p.length===0){m("logout","no providers are configured");return}_("Logout",p.map(g=>({value:g,label:g})),g=>{k.modelRuntime.logout(g).then(()=>m("logout",`logged out ${g}`),b=>m("logout",b instanceof Error?b.message:String(b)))});return}if(s==="providers"){let c=await k.modelRuntime.getAvailable(),p=[...new Set(c.map(g=>g.provider))].sort();p.sort((g,b)=>Number(se(b))-Number(se(g))),_("Providers",p.map(g=>({value:g,label:g})),g=>{let b=k.modelRuntime.getModels(g);if(b.length===0){Xt(g);return}_(g,b.map(S=>({value:S.id,label:S.id})),S=>{let v=b.find(A=>A.id===S);v&&k.setModel(v,{persist:!0}).then(()=>{u.model=v.id,he(),m("providers",`${g}/${v.id}`)},()=>Xt(g))})});return}if(s==="name"){if(!l){m("name","usage: /name <session name>");return}k.setSessionName(l),m("name",`session name: ${l}`);return}if(s==="update"){C("note","checking for a newer release");try{await uo({current:it,install:!0})}finally{C("note",void 0)}return}if(s==="stats"){let c=k.getSessionStats(),p=k.getContextUsage(),g=v=>Number.isFinite(v)?String(v):";",b=xi(k.sessionManager.getEntries()),S=b.hitRate===null?"cache hit rate unknown (no prompt billed yet)":`cache hit ${b.hitRate.toFixed(1)}% of ${b.cachedTokens+b.billedTokens} prompt tokens`;m("stats",[`session ${c.sessionId}`,c.sessionFile?`file ${c.sessionFile}`:"not persisted",`messages ${g(c.totalMessages)} (user ${g(c.userMessages)}, assistant ${g(c.assistantMessages)}, tools ${g(c.toolCalls)})`,`tokens in ${g(c.tokens.input)} out ${g(c.tokens.output)} cache ${g(c.tokens.cacheRead)}/${g(c.tokens.cacheWrite)}`,S,b.misses.length>0?`cache misses ${b.misses.length} (${g(b.missedTokens)} tokens re-billed) \u2014 last: ${Si(b.misses[b.misses.length-1])}`:"cache misses none counted",`cost $${Number.isFinite(c.cost)?c.cost.toFixed(4):";"}`,p?`context ${p.percent===null||!Number.isFinite(p.percent)?"?":`${Math.round(p.percent)}%`} of ${p.contextWindow}`:"context unknown"].join(`
87
- `));return}if(s==="diff"){let c=async v=>{try{let{stdout:A}=await Vn("git",v,{cwd:e.cwd,encoding:"utf8"});return A.trim()}catch{return""}},p=await c(["diff","--stat"])+`
83
+ `)}${g}${S}`)});return}p("preset",`unknown subcommand "${s}". try: list, show, add, add-hub, remove.`)},Ne=async o=>{let[s,...a]=o.slice(1).split(/\s+/),l=a.join(" ");if(s==="quit"||s==="exit"){_e();return}if(s==="help"){p("help",qn(k).map(c=>`/${c.name} ${c.description??""}`).join(`
84
+ `));return}if(s==="init"){let c=le(e.cwd,"AGENTS.md");if(Rt(c)&&l!=="force"){p("init",`AGENTS.md already exists at ${c}. run /init force to overwrite.`);return}se(c,Uo),p("init",`wrote ${c}; asking the agent to fill it in`),await k.prompt("Read AGENTS.md, then fill it in with the real build, test, and layout facts of this repo. Keep it short.");return}if(s==="login"){Xt(l);return}if(s==="connect"){let c=l.trim();if(c&&!c.startsWith("sk-")&&Dn(c)){Eo(c);return}if(c){Oe(c);return}let m=gs(E);if(m){Eo(m.credential);return}Oe(""),C("prompt","paste your howtofix.id token, then press enter"),v();let b=ne;ne=g=>{ne=b,C("prompt",void 0),Oe(g.trim())};return}if(s==="sync"){let c=new Set((await k.modelRuntime.getAvailable()).map(R=>R.provider).filter(R=>re(R))),m=ye.find(R=>c.has(R));if(!m){p("sync","no howtofix.id account is connected; run /connect first");return}C("note",`re-syncing ${m} from howtofix.id`),v();let g=(await k.modelRuntime.getAuth(m))?.auth?.apiKey;if(!g){C("note",void 0),p("sync",`${m} has no usable key; run /connect to sign in again`),v();return}let S=await ln(g);if(!S.ok){C("note",void 0),p("sync",S.message),v();return}let $=await Ro(m,S.models),A=await Ae(g);C("note",void 0),p("sync",`${$}
85
+ ${nt(m,A)}`),await k.modelRuntime.refresh(),v();return}if(s==="usage"){let c=new Set((await k.modelRuntime.getAvailable()).map(R=>R.provider).filter(R=>re(R))),m=ye.find(R=>c.has(R));if(!m){p("usage","no howtofix.id account is connected; run /connect first");return}C("note","asking howtofix.id for the account usage"),v();let g=(await k.modelRuntime.getAuth(m))?.auth?.apiKey;if(!g){C("note",void 0),p("usage",`${m} has no usable key; run /connect to sign in again`),v();return}let S=await Ae(g),$=await Un(g);C("note",void 0);let A=$.ok&&$.enabled?$.checkedInToday?`check-in: claimed today (+${Wn($.quotaToday)})`:"check-in: not claimed yet today (it claims itself on the next start)":"";p("usage",A?`${nt(m,S)}
86
+ ${A}`:nt(m,S)),v();return}if(s==="logout"){let c=await k.modelRuntime.getAvailable(),m=[...new Set(c.map(b=>b.provider))].sort();if(m.length===0){p("logout","no providers are configured");return}_("Logout",m.map(b=>({value:b,label:b})),b=>{k.modelRuntime.logout(b).then(()=>p("logout",`logged out ${b}`),g=>p("logout",g instanceof Error?g.message:String(g)))});return}if(s==="providers"){let c=await k.modelRuntime.getAvailable(),m=[...new Set(c.map(b=>b.provider))].sort();m.sort((b,g)=>Number(re(g))-Number(re(b))),_("Providers",m.map(b=>({value:b,label:b})),b=>{let g=k.modelRuntime.getModels(b);if(g.length===0){Xt(b);return}_(b,g.map(S=>({value:S.id,label:S.id})),S=>{let $=g.find(A=>A.id===S);$&&k.setModel($,{persist:!0}).then(()=>{u.model=$.id,he(),p("providers",`${b}/${$.id}`)},()=>Xt(b))})});return}if(s==="name"){if(!l){p("name","usage: /name <session name>");return}k.setSessionName(l),p("name",`session name: ${l}`);return}if(s==="update"){C("note","checking for a newer release");try{await uo({current:it,install:!0})}finally{C("note",void 0)}return}if(s==="stats"){let c=k.getSessionStats(),m=k.getContextUsage(),b=$=>Number.isFinite($)?String($):";",g=Si(k.sessionManager.getEntries()),S=g.hitRate===null?"cache hit rate unknown (no prompt billed yet)":`cache hit ${g.hitRate.toFixed(1)}% of ${g.cachedTokens+g.billedTokens} prompt tokens`;p("stats",[`session ${c.sessionId}`,c.sessionFile?`file ${c.sessionFile}`:"not persisted",`messages ${b(c.totalMessages)} (user ${b(c.userMessages)}, assistant ${b(c.assistantMessages)}, tools ${b(c.toolCalls)})`,`tokens in ${b(c.tokens.input)} out ${b(c.tokens.output)} cache ${b(c.tokens.cacheRead)}/${b(c.tokens.cacheWrite)}`,S,g.misses.length>0?`cache misses ${g.misses.length} (${b(g.missedTokens)} tokens re-billed) \u2014 last: ${Ci(g.misses[g.misses.length-1])}`:"cache misses none counted",`cost $${Number.isFinite(c.cost)?c.cost.toFixed(4):";"}`,m?`context ${m.percent===null||!Number.isFinite(m.percent)?"?":`${Math.round(m.percent)}%`} of ${m.contextWindow}`:"context unknown"].join(`
87
+ `));return}if(s==="diff"){let c=async $=>{try{let{stdout:A}=await Vn("git",$,{cwd:e.cwd,encoding:"utf8"});return A.trim()}catch{return""}},m=await c(["diff","--stat"])+`
88
88
 
89
- `+await c(["diff","--","."]),[g="",b=""]=p.split(`
89
+ `+await c(["diff","--","."]),[b="",g=""]=m.split(`
90
90
 
91
- `,2),S=oi(b);m("diff",[g.trim(),S].filter(Boolean).join(`
91
+ `,2),S=ri(g);p("diff",[b.trim(),S].filter(Boolean).join(`
92
92
 
93
- `)||"working tree clean");return}if(s==="copy"){let c=[...k.state.messages].reverse().find(b=>b.role==="assistant"),g=(Array.isArray(c?.content)?c.content:[]).filter(b=>b.type==="text").map(b=>b.text).join("");if(!g){m("copy","nothing to copy");return}try{await Ll(g),m("copy",`copied ${g.length} characters`)}catch(b){m("copy",b instanceof Error?b.message:String(b))}return}if(s==="export"){let c=i.items.filter(b=>b.body.trim().length>0);if(c.length===0){m("export","nothing to export yet; the transcript is empty");return}let p=Ol(e.cwd,l||`howtofix-session-${Date.now()}.md`),g=[`# ${en} session`,"",`model ${u.model}`,""];for(let b of c)g.push(`## ${b.title||b.kind}`,"",b.body,"");try{ie(p,g.join(`
94
- `))}catch(b){m("export",`could not write ${p}: ${b instanceof Error?b.message:String(b)}`);return}m("export",`wrote ${p}`);return}if(s==="agents"){let[c="",...p]=l.split(/\s+/).filter(Boolean),g=p.join(" ").trim();if(c&&g){m("agents",await Jr(c,g));return}m("agents",c?Xr(c):Yr());return}if(s==="new"){let c=await e.reopen({noSession:!1});await xo(c),m("new","started a new session");return}if(s==="resume"){let c=await Nl.list(e.cwd);if(c.length===0){m("resume","no saved sessions for this folder");return}_("Resume session",c.slice(0,30).map(p=>({value:p.path,label:p.name||`${p.id.slice(0,8)} ${p.firstMessage.slice(0,40)}`,description:`${p.modified.toISOString().slice(0,16)} ${p.messageCount} messages`})),p=>{e.reopen({sessionPath:p}).then(xo,g=>H(g instanceof Error?g.message:String(g)))});return}if(s==="model"){let c=await k.modelRuntime.getAvailable(),p=l?c.find(g=>`${g.provider}/${g.id}`===l||g.id===l):void 0;if(!l){_("Select model",c.map(g=>({value:`${g.provider}/${g.id}`,label:g.id,description:[vs(g),g.provider].filter(Boolean).join(" \xB7 ")})),g=>{let b=c.find(S=>`${S.provider}/${S.id}`===g);b&&k.setModel(b,{persist:!0}).then(()=>{u.model=b.id,he(),m("model",`model ${g}`)})});return}if(!p){m("model",`unknown model ${l}`);return}await k.setModel(p,{persist:!0}),u.model=p.id,he(),m("model",`model ${p.provider}/${p.id}`);return}if(s==="thinking"){if(!l){_("Thinking level",B.map(c=>({value:c,label:c})),c=>Pe(c));return}if(!B.includes(l)){m("thinking",`thinking: ${B.join(", ")}`);return}Pe(l);return}if(s==="rtk"){let c=ke(P).compressToolOutput;if(!l){m("rtk",`compress tool output: ${c?"on":"off"}
95
- /rtk on | /rtk off`);return}let p=l.toLowerCase();if(p!=="on"&&p!=="off"){m("rtk","rtk: on | off");return}let g=p==="on";if(g===c){m("rtk",`already ${p}`);return}if(!je(P,"compressToolOutput",g)){m("rtk","could not write the setting");return}to(g),m("rtk",`compress tool output ${p}
96
- long results are ${g?"summarised before the model reads them":"sent in full"}`);return}if(s==="compact"){try{await k.compact(l||void 0),m("compact","session compacted")}catch(c){m("compact",c instanceof Error?c.message:String(c))}return}if(s==="approval"){let c=p=>{Mr(p),m("approval",un[p])};if(!l){_("Approval mode",mt.map(p=>({value:p,label:p,description:un[p]})),p=>c(p));return}if(!mt.includes(l)){m("approval",`modes: ${mt.join(", ")}`);return}c(l);return}if(s==="settings"){let c=()=>mn()?"off \u2014 everything runs":"on \u2014 critical commands are refused",p=()=>{_("Permission checks",[{value:"on",label:"on",description:"refuse critical commands and repeated calls (the default)"},{value:"off",label:"off",description:"run everything without asking \u2014 for unattended runs"}],E=>{let Y=E==="off",q=je(P,"skipPermissions",Y);if(fn(Y),u.skipPermissions=Y,$(),!q){m("settings","changed for this session, but settings.json could not be written (is it valid JSON?)");return}m("settings",Y?"permission checks are OFF \u2014 critical commands and the repeat guard will not stop anything. Stored for future sessions.":"permission checks are ON \u2014 critical commands and repeated calls are refused again.")},void 0,!1,[`Currently ${c()}.`])},g=()=>{_("Thinking level",B.map(E=>({value:E,label:E,description:E===u.thinking?"current":void 0})),E=>Pe(E),void 0,!1,[`Currently ${u.thinking}.`])},b=()=>{_("Auto-update",[{value:"on",label:"on",description:"install a newer release on start (the default)"},{value:"off",label:"off",description:"stay on this version until you update by hand"}],E=>{let Y=E!=="off",q=je(P,"autoUpdate",Y);m("settings",q?`auto-update ${Y?"on":"off"} \u2014 takes effect on the next start.`:"auto-update changed for this session, but settings.json could not be written (is it valid JSON?)")},void 0,!1,[`Currently ${Cr(`${P}/settings.json`)?"on":"off"}.`])},S=()=>{let E=We("status",e.cwd,k.getSessionStats().sessionId);_("Dynamic context pruning",[{value:"on",label:"on",description:"fold stale ranges so long sessions stay affordable"},{value:"off",label:"off",description:"send the full transcript, unpruned"},{value:"status",label:"status",description:"what it has pruned so far"}],Y=>m("dcp",We(Y,e.cwd,k.getSessionStats().sessionId)),void 0,!1,E.split(`
97
- `).slice(0,2))},v=()=>{Ne("/model")},A=()=>{Ne("/proxy")},R=()=>{let E=ke(P).rightClickPaste,Y=process.platform==="win32"?"off":"on";_("Right click",[{value:"auto",label:"auto",description:`follow the terminal (${Y} on ${process.platform})`},{value:"on",label:"on",description:"the CLI pastes the clipboard itself"},{value:"off",label:"off",description:"the terminal handles it, or the click does nothing"}],q=>{let Fe=Or(P,q);m("settings",Fe?q==="auto"?`right click follows the terminal \u2014 ${pn("auto")?"the CLI pastes":"the terminal pastes"} here.`:`right click ${q==="on"?"pastes from the CLI":"is left to the terminal"}.`:"right click changed for this session, but settings.json could not be written (is it valid JSON?)")},void 0,!1,[`Currently ${E}.`])},K=()=>{let E=ke(P).agents,Y=[1,2,3,4].map(q=>({value:String(q),label:String(q),description:q===1?"one child at a time":q===Ue()?"current \u2014 sized to this machine":`${q} children at once`}));_("Agent concurrency",[{value:"auto",label:"auto",description:`size it to the machine (now ${Ue()}, max ${qr})`},...Y],q=>{let Fe=q==="auto"?void 0:Number(q),da=Lr(P,Fe);m("settings",da?Fe===void 0?`agent concurrency follows the machine \u2014 ${Ue()} at a time.`:`agent concurrency set to ${Fe} \u2014 shared by task and workflow.`:"agent concurrency changed for this session, but settings.json could not be written (is it valid JSON?)"),$()},void 0,!1)},J=[{value:"permissions",label:"permissions",description:c()},{value:"thinking",label:"thinking",description:`${u.thinking} \u2014 how hard the model reasons`},{value:"model",label:"model",description:u.model},{value:"dcp",label:"context pruning",description:"fold stale ranges to save tokens"},{value:"proxy",label:"proxy",description:cn(P)??dn()??"none \u2014 direct to the API"},{value:"rightclick",label:"right click",description:`paste: ${ke(P).rightClickPaste}`},{value:"agents",label:"agents",description:`${ke(P).agents??`auto (${Ue()})`} at once, shared by task and workflow`},{value:"autoupdate",label:"auto-update",description:"install a newer release on start"}];if(!l){_("Settings",J,E=>{E==="permissions"?p():E==="thinking"?g():E==="dcp"?S():E==="autoupdate"?b():E==="model"?v():E==="proxy"?A():E==="rightclick"?R():E==="agents"&&K()});return}let oe=J.find(E=>E.value===l||E.label===l);if(oe){oe.value==="permissions"?p():oe.value==="thinking"?g():oe.value==="dcp"?S():oe.value==="autoupdate"?b():oe.value==="model"?v():oe.value==="proxy"?A():oe.value==="rightclick"?R():oe.value==="agents"&&K();return}if(l==="on"||l==="off"){let E=l==="off",Y=je(P,"skipPermissions",E);fn(E),u.skipPermissions=E,$(),m("settings",Y?E?"permission checks are OFF \u2014 critical commands and the repeat guard will not stop anything.":"permission checks are ON.":"changed for this session, but settings.json could not be written (is it valid JSON?)");return}m("settings",`settings: ${J.map(E=>E.value).join(", ")} | on, off (permission checks)
98
- usage: /settings <name>, or /settings to choose`);return}if(s==="proxy"){let c=cn(P),p=dn(),g=()=>c?`proxy: ${c} (set here, in settings.json)`:p?`proxy: ${p} (from the environment, not this file)`:"proxy: none \u2014 requests go straight to the API";if(!l){m("proxy",`${g()}
93
+ `)||"working tree clean");return}if(s==="copy"){let c=[...k.state.messages].reverse().find(g=>g.role==="assistant"),b=(Array.isArray(c?.content)?c.content:[]).filter(g=>g.type==="text").map(g=>g.text).join("");if(!b){p("copy","nothing to copy");return}try{await Nl(b),p("copy",`copied ${b.length} characters`)}catch(g){p("copy",g instanceof Error?g.message:String(g))}return}if(s==="export"){let c=i.items.filter(g=>g.body.trim().length>0);if(c.length===0){p("export","nothing to export yet; the transcript is empty");return}let m=Ll(e.cwd,l||`howtofix-session-${Date.now()}.md`),b=[`# ${en} session`,"",`model ${u.model}`,""];for(let g of c)b.push(`## ${g.title||g.kind}`,"",g.body,"");try{se(m,b.join(`
94
+ `))}catch(g){p("export",`could not write ${m}: ${g instanceof Error?g.message:String(g)}`);return}p("export",`wrote ${m}`);return}if(s==="agents"){let[c="",...m]=l.split(/\s+/).filter(Boolean),b=m.join(" ").trim();if(c&&b){p("agents",await Zr(c,b));return}p("agents",c?Jr(c):Xr());return}if(s==="new"){let c=await e.reopen({noSession:!1});await xo(c),p("new","started a new session");return}if(s==="resume"){let c=await Fl.list(e.cwd);if(c.length===0){p("resume","no saved sessions for this folder");return}_("Resume session",c.slice(0,30).map(m=>({value:m.path,label:m.name||`${m.id.slice(0,8)} ${m.firstMessage.slice(0,40)}`,description:`${m.modified.toISOString().slice(0,16)} ${m.messageCount} messages`})),m=>{e.reopen({sessionPath:m}).then(xo,b=>H(b instanceof Error?b.message:String(b)))});return}if(s==="model"){let c=await k.modelRuntime.getAvailable(),m=c.filter($=>re($.provider)),b=lr(E),g=m.length>0?m:b.size>0?c.filter($=>b.has($.provider)):c,S=l?g.find($=>`${$.provider}/${$.id}`===l||$.id===l):void 0;if(!l){_("Select model",g.map($=>({value:`${$.provider}/${$.id}`,label:$.id,description:[xs($),$.provider].filter(Boolean).join(" \xB7 ")})),$=>{let A=g.find(R=>`${R.provider}/${R.id}`===$);A&&k.setModel(A,{persist:!0}).then(()=>{u.model=A.id,he(),p("model",`model ${$}`)})});return}if(!S){p("model",`unknown model ${l}`);return}await k.setModel(S,{persist:!0}),u.model=S.id,he(),p("model",`model ${S.provider}/${S.id}`);return}if(s==="thinking"){if(!l){_("Thinking level",B.map(c=>({value:c,label:c})),c=>Pe(c));return}if(!B.includes(l)){p("thinking",`thinking: ${B.join(", ")}`);return}Pe(l);return}if(s==="rtk"){let c=ke(E).compressToolOutput;if(!l){p("rtk",`compress tool output: ${c?"on":"off"}
95
+ /rtk on | /rtk off`);return}let m=l.toLowerCase();if(m!=="on"&&m!=="off"){p("rtk","rtk: on | off");return}let b=m==="on";if(b===c){p("rtk",`already ${m}`);return}if(!je(E,"compressToolOutput",b)){p("rtk","could not write the setting");return}to(b),p("rtk",`compress tool output ${m}
96
+ long results are ${b?"summarised before the model reads them":"sent in full"}`);return}if(s==="compact"){try{await k.compact(l||void 0),p("compact","session compacted")}catch(c){p("compact",c instanceof Error?c.message:String(c))}return}if(s==="approval"){let c=m=>{Rr(m),p("approval",un[m])};if(!l){_("Approval mode",pt.map(m=>({value:m,label:m,description:un[m]})),m=>c(m));return}if(!pt.includes(l)){p("approval",`modes: ${pt.join(", ")}`);return}c(l);return}if(s==="settings"){let c=()=>pn()?"off \u2014 everything runs":"on \u2014 critical commands are refused",m=()=>{_("Permission checks",[{value:"on",label:"on",description:"refuse critical commands and repeated calls (the default)"},{value:"off",label:"off",description:"run everything without asking \u2014 for unattended runs"}],P=>{let Y=P==="off",q=je(E,"skipPermissions",Y);if(fn(Y),u.skipPermissions=Y,v(),!q){p("settings","changed for this session, but settings.json could not be written (is it valid JSON?)");return}p("settings",Y?"permission checks are OFF \u2014 critical commands and the repeat guard will not stop anything. Stored for future sessions.":"permission checks are ON \u2014 critical commands and repeated calls are refused again.")},void 0,!1,[`Currently ${c()}.`])},b=()=>{_("Thinking level",B.map(P=>({value:P,label:P,description:P===u.thinking?"current":void 0})),P=>Pe(P),void 0,!1,[`Currently ${u.thinking}.`])},g=()=>{_("Auto-update",[{value:"on",label:"on",description:"install a newer release on start (the default)"},{value:"off",label:"off",description:"stay on this version until you update by hand"}],P=>{let Y=P!=="off",q=je(E,"autoUpdate",Y);p("settings",q?`auto-update ${Y?"on":"off"} \u2014 takes effect on the next start.`:"auto-update changed for this session, but settings.json could not be written (is it valid JSON?)")},void 0,!1,[`Currently ${Ar(`${E}/settings.json`)?"on":"off"}.`])},S=()=>{let P=We("status",e.cwd,k.getSessionStats().sessionId);_("Dynamic context pruning",[{value:"on",label:"on",description:"fold stale ranges so long sessions stay affordable"},{value:"off",label:"off",description:"send the full transcript, unpruned"},{value:"status",label:"status",description:"what it has pruned so far"}],Y=>p("dcp",We(Y,e.cwd,k.getSessionStats().sessionId)),void 0,!1,P.split(`
97
+ `).slice(0,2))},$=()=>{Ne("/model")},A=()=>{Ne("/proxy")},R=()=>{let P=ke(E).rightClickPaste,Y=process.platform==="win32"?"off":"on";_("Right click",[{value:"auto",label:"auto",description:`follow the terminal (${Y} on ${process.platform})`},{value:"on",label:"on",description:"the CLI pastes the clipboard itself"},{value:"off",label:"off",description:"the terminal handles it, or the click does nothing"}],q=>{let Fe=Lr(E,q);p("settings",Fe?q==="auto"?`right click follows the terminal \u2014 ${mn("auto")?"the CLI pastes":"the terminal pastes"} here.`:`right click ${q==="on"?"pastes from the CLI":"is left to the terminal"}.`:"right click changed for this session, but settings.json could not be written (is it valid JSON?)")},void 0,!1,[`Currently ${P}.`])},K=()=>{let P=ke(E).agents,Y=[1,2,3,4].map(q=>({value:String(q),label:String(q),description:q===1?"one child at a time":q===Ue()?"current \u2014 sized to this machine":`${q} children at once`}));_("Agent concurrency",[{value:"auto",label:"auto",description:`size it to the machine (now ${Ue()}, max ${Vr})`},...Y],q=>{let Fe=q==="auto"?void 0:Number(q),ua=Nr(E,Fe);p("settings",ua?Fe===void 0?`agent concurrency follows the machine \u2014 ${Ue()} at a time.`:`agent concurrency set to ${Fe} \u2014 shared by task and workflow.`:"agent concurrency changed for this session, but settings.json could not be written (is it valid JSON?)"),v()},void 0,!1)},J=[{value:"permissions",label:"permissions",description:c()},{value:"thinking",label:"thinking",description:`${u.thinking} \u2014 how hard the model reasons`},{value:"model",label:"model",description:u.model},{value:"dcp",label:"context pruning",description:"fold stale ranges to save tokens"},{value:"proxy",label:"proxy",description:cn(E)??dn()??"none \u2014 direct to the API"},{value:"rightclick",label:"right click",description:`paste: ${ke(E).rightClickPaste}`},{value:"agents",label:"agents",description:`${ke(E).agents??`auto (${Ue()})`} at once, shared by task and workflow`},{value:"autoupdate",label:"auto-update",description:"install a newer release on start"}];if(!l){_("Settings",J,P=>{P==="permissions"?m():P==="thinking"?b():P==="dcp"?S():P==="autoupdate"?g():P==="model"?$():P==="proxy"?A():P==="rightclick"?R():P==="agents"&&K()});return}let oe=J.find(P=>P.value===l||P.label===l);if(oe){oe.value==="permissions"?m():oe.value==="thinking"?b():oe.value==="dcp"?S():oe.value==="autoupdate"?g():oe.value==="model"?$():oe.value==="proxy"?A():oe.value==="rightclick"?R():oe.value==="agents"&&K();return}if(l==="on"||l==="off"){let P=l==="off",Y=je(E,"skipPermissions",P);fn(P),u.skipPermissions=P,v(),p("settings",Y?P?"permission checks are OFF \u2014 critical commands and the repeat guard will not stop anything.":"permission checks are ON.":"changed for this session, but settings.json could not be written (is it valid JSON?)");return}p("settings",`settings: ${J.map(P=>P.value).join(", ")} | on, off (permission checks)
98
+ usage: /settings <name>, or /settings to choose`);return}if(s==="proxy"){let c=cn(E),m=dn(),b=()=>c?`proxy: ${c} (set here, in settings.json)`:m?`proxy: ${m} (from the environment, not this file)`:"proxy: none \u2014 requests go straight to the API";if(!l){p("proxy",`${b()}
99
99
  usage: /proxy <url> route requests through a proxy
100
100
  /proxy off stop using one
101
101
  /proxy env use HTTPS_PROXY / HTTP_PROXY / ALL_PROXY
102
- Only traffic to the HowToFix API goes through it; a change applies on the next start.`);return}let b=l.trim();if(b==="off"||b==="none"){let R=pt(P,ut,""),K=ft(P),J=K.source==="env"?`the environment still sets one (${K.url})`:"requests go straight to the API";m("proxy",R?`proxy off \u2014 ${J} from the next message.`:"proxy changed for this session, but settings.json could not be written (is it valid JSON?)");return}if(b==="env"){let R=pt(P,ut,""),K=ft(P),J=K.source==="env"?K.url:void 0;m("proxy",R?J?`using the environment from the next message: ${J}`:"settings cleared, but no HTTPS_PROXY / HTTP_PROXY / ALL_PROXY is set \u2014 requests go straight to the API.":"settings.json could not be written (is it valid JSON?)");return}let S=Sr(b);if(!S.ok){m("proxy",`not set: ${S.problem}`);return}if(!pt(P,ut,S.url)){m("proxy","settings.json could not be written (is it valid JSON?)");return}let A=ft(P);m("proxy",A.url?`proxy set to ${S.url} \u2014 requests go through it from the next message.`:`proxy saved as ${S.url}, but it could not be applied this session; it will be tried on the next start.`);return}if(s==="tools"){let c=k.getActiveToolNames().sort();m("tools",c.length?c.join(`
103
- `):"no tools enabled");return}if(s==="dcp"){m("dcp",We(l,e.cwd,k.getSessionStats().sessionId));return}if(s==="context"||s==="decompress"||s==="sweep"){m(s,We(`${s} ${l}`.trim(),e.cwd,k.getSessionStats().sessionId));return}if(s==="rewind"){lo();return}if(s==="undo"){if(!await yn(e.cwd)){m("undo","not a git repository");return}let c=await ti(e.cwd);m("undo",c.ok?`undone: ${c.output}`:`undo failed: ${c.output}`),h(!0);return}if(s==="commit"){if(!yn(e.cwd)){m("commit","not a git repository");return}if(!await Qr(e.cwd)){m("commit","nothing to commit");return}let c=l||`howtofix: session update ${new Date().toISOString().slice(0,16)}`,p=await ei(e.cwd,c);m("commit",p.ok?p.output:`commit failed: ${p.output}`),h(!0);return}if(s==="review"){if(!(await ni(e.cwd)).trim()){m("review","no changes to review");return}zt("Review the uncommitted changes. Report concrete issues with file evidence. Do not edit files.");return}if(s==="workflow"){if(l.trim()==="clear"){Zn(),m("workflow","cleared the pinned workflow panel");return}if(!U){m("workflow","no workflow run in this session yet");return}let c=kn(U,Date.now()),p=c[I.selectedPhase];m("workflow",[`panel ${X?"pinned above the editor":"unpinned"}`,`phase ${I.selectedPhase+1}/${c.length}: ${p?.title??"(none)"}`,`filter: ${I.filter}${I.paused?" \xB7 paused":""}`,"keys: \u2191/\u2193 phase \xB7 Enter drill in \xB7 Esc unpin \xB7 f filter \xB7 p pause \xB7 x stop \xB7 s save","clear it with /workflow clear"].join(`
104
- `));return}if(s==="plan"){if(Br()||gt().state==="pending"){gn(Kr(gt())),m("plan","plan mode off; edits are allowed again");return}gn(Ur(gt())),m("plan",`plan mode armed \u2014 send your next prompt to start planning
105
- plan file: ${Hr()??"(unknown)"}`);return}if(s==="goal"){let c=l.trim();if(!c){m("goal",hn(ht()));return}let{goal:p,error:g}=Wr(ht(),"set",c,void 0,void 0);if(g){H(g);return}Dr(p),await k.sendCustomMessage({customType:Fr,content:c,display:!1,details:p}),m("goal",`goal set
106
- ${hn(p)}`);return}if(s==="session"){let c=k.model;m("session",c?`${c.provider}/${c.id}`:"no model");return}if(s==="skills"){m("skills",wi(k.resourceLoader.getSkills().skills));return}if(s==="preset"){Wo(l);return}if(s==="roblox"){let c=ee(e.cwd).entries.find(S=>S.manifest.name==="rotoolbox");if(!c||c.source!=="installed"){m("roblox","RoToolbox is not installed. Run /preset and install RoToolbox first.");return}let p=nn(c.dir),g=k.getActiveToolNames().filter(S=>/roblox[-_]studio/i.test(S)),b=g.length>0;m("roblox",p?`RoToolbox: disabled
102
+ Only traffic to the HowToFix API goes through it; a change applies on the next start.`);return}let g=l.trim();if(g==="off"||g==="none"){let R=mt(E,ut,""),K=ft(E),J=K.source==="env"?`the environment still sets one (${K.url})`:"requests go straight to the API";p("proxy",R?`proxy off \u2014 ${J} from the next message.`:"proxy changed for this session, but settings.json could not be written (is it valid JSON?)");return}if(g==="env"){let R=mt(E,ut,""),K=ft(E),J=K.source==="env"?K.url:void 0;p("proxy",R?J?`using the environment from the next message: ${J}`:"settings cleared, but no HTTPS_PROXY / HTTP_PROXY / ALL_PROXY is set \u2014 requests go straight to the API.":"settings.json could not be written (is it valid JSON?)");return}let S=Cr(g);if(!S.ok){p("proxy",`not set: ${S.problem}`);return}if(!mt(E,ut,S.url)){p("proxy","settings.json could not be written (is it valid JSON?)");return}let A=ft(E);p("proxy",A.url?`proxy set to ${S.url} \u2014 requests go through it from the next message.`:`proxy saved as ${S.url}, but it could not be applied this session; it will be tried on the next start.`);return}if(s==="tools"){let c=k.getActiveToolNames().sort();p("tools",c.length?c.join(`
103
+ `):"no tools enabled");return}if(s==="dcp"){p("dcp",We(l,e.cwd,k.getSessionStats().sessionId));return}if(s==="context"||s==="decompress"||s==="sweep"){p(s,We(`${s} ${l}`.trim(),e.cwd,k.getSessionStats().sessionId));return}if(s==="rewind"){lo();return}if(s==="undo"){if(!await yn(e.cwd)){p("undo","not a git repository");return}let c=await ni(e.cwd);p("undo",c.ok?`undone: ${c.output}`:`undo failed: ${c.output}`),h(!0);return}if(s==="commit"){if(!yn(e.cwd)){p("commit","not a git repository");return}if(!await ei(e.cwd)){p("commit","nothing to commit");return}let c=l||`howtofix: session update ${new Date().toISOString().slice(0,16)}`,m=await ti(e.cwd,c);p("commit",m.ok?m.output:`commit failed: ${m.output}`),h(!0);return}if(s==="review"){if(!(await oi(e.cwd)).trim()){p("review","no changes to review");return}zt("Review the uncommitted changes. Report concrete issues with file evidence. Do not edit files.");return}if(s==="workflow"){if(l.trim()==="clear"){Zn(),p("workflow","cleared the pinned workflow panel");return}if(!U){p("workflow","no workflow run in this session yet");return}let c=kn(U,Date.now()),m=c[I.selectedPhase];p("workflow",[`panel ${X?"pinned above the editor":"unpinned"}`,`phase ${I.selectedPhase+1}/${c.length}: ${m?.title??"(none)"}`,`filter: ${I.filter}${I.paused?" \xB7 paused":""}`,"keys: \u2191/\u2193 phase \xB7 Enter drill in \xB7 Esc unpin \xB7 f filter \xB7 p pause \xB7 x stop \xB7 s save","clear it with /workflow clear"].join(`
104
+ `));return}if(s==="plan"){if(Gr()||gt().state==="pending"){gn(Hr(gt())),p("plan","plan mode off; edits are allowed again");return}gn(Kr(gt())),p("plan",`plan mode armed \u2014 send your next prompt to start planning
105
+ plan file: ${Br()??"(unknown)"}`);return}if(s==="goal"){let c=l.trim();if(!c){p("goal",hn(ht()));return}let{goal:m,error:b}=Ur(ht(),"set",c,void 0,void 0);if(b){H(b);return}Wr(m),await k.sendCustomMessage({customType:jr,content:c,display:!1,details:m}),p("goal",`goal set
106
+ ${hn(m)}`);return}if(s==="session"){let c=k.model;p("session",c?`${c.provider}/${c.id}`:"no model");return}if(s==="skills"){p("skills",yi(k.resourceLoader.getSkills().skills));return}if(s==="preset"){Wo(l);return}if(s==="roblox"){let c=ee(e.cwd).entries.find(S=>S.manifest.name==="rotoolbox");if(!c||c.source!=="installed"){p("roblox","RoToolbox is not installed. Run /preset and install RoToolbox first.");return}let m=nn(c.dir),b=k.getActiveToolNames().filter(S=>/roblox[-_]studio/i.test(S)),g=b.length>0;p("roblox",m?`RoToolbox: disabled
107
107
  Enable with /preset enable rotoolbox
108
- The MCP server and manager stay stopped while disabled.`:["RoToolbox: active",`MCP server: ${b?`connected \u2014 ${g.length} tool${g.length===1?"":"s"} registered`:"not connected yet"}`,"Open Roblox Studio with a place, then use a prompt to inspect it.","Disable with /preset disable rotoolbox"].join(`
109
- `));return}let d=bi(o,k.resourceLoader.getSkills().skills.map(c=>c.name));if(d){Ao(d);return}let y=k.extensionRunner.getCommand(s??"");if(y){try{await y.handler(l,k.extensionRunner.createCommandContext())}catch(c){H(c instanceof Error?c.message:String(c))}return}m("command",`/${s??""} is not available in this screen yet`)};Nr((o,s)=>{let{promise:a,resolve:l}=Promise.withResolvers();return _(o,s.map(d=>({value:d,label:d})),l,()=>l("cancelled")),a}),process.on("SIGTERM",_e),vi(()=>{_e()}),t.setTitle(`${en} ${it}`),Zl(),r.start(),r.requestRender(!0),Co(!0);{let{maybeShowWelcome:o}=await import("./chunk-FRGMJPNO.js");await o({cwd:e.cwd,note:e.note,signedIn:ge!==void 0,runSlash:s=>{Ne(s)},openExternal:s=>{Ve(s)}},_,m)}e.initialPrompt&&zt(e.initialPrompt),await new Promise(()=>{})}var ne,Ql=1e3/30,ec=45e3;export{Xn as Dock,zn as Hud,Yn as PinnedBlock,Yl as approvalDetail,bt as orderModelsForDefault,zl as pickerPanel,mu as runWorkbench,qn as slashCommands,Xl as workflowPanel,Et as workflowPanelFromRun,Jn as workflowRunOf};
108
+ The MCP server and manager stay stopped while disabled.`:["RoToolbox: active",`MCP server: ${g?`connected \u2014 ${b.length} tool${b.length===1?"":"s"} registered`:"not connected yet"}`,"Open Roblox Studio with a place, then use a prompt to inspect it.","Disable with /preset disable rotoolbox"].join(`
109
+ `));return}let d=wi(o,k.resourceLoader.getSkills().skills.map(c=>c.name));if(d){Ao(d);return}let y=k.extensionRunner.getCommand(s??"");if(y){try{await y.handler(l,k.extensionRunner.createCommandContext())}catch(c){H(c instanceof Error?c.message:String(c))}return}p("command",`/${s??""} is not available in this screen yet`)};Fr((o,s)=>{let{promise:a,resolve:l}=Promise.withResolvers();return _(o,s.map(d=>({value:d,label:d})),l,()=>l("cancelled")),a}),process.on("SIGTERM",_e),xi(()=>{_e()}),t.setTitle(`${en} ${it}`),Ql(),r.start(),r.requestRender(!0),Co(!0);{let{maybeShowWelcome:o}=await import("./chunk-GVTLSEBC.js");await o({cwd:e.cwd,note:e.note,signedIn:ge!==void 0,runSlash:s=>{Ne(s)},openExternal:s=>{Ve(s)}},_,p)}e.initialPrompt&&zt(e.initialPrompt),await new Promise(()=>{})}var ne,ec=1e3/30,tc=45e3;export{Xn as Dock,zn as Hud,Yn as PinnedBlock,Xl as approvalDetail,bt as orderModelsForDefault,Yl as pickerPanel,mu as runWorkbench,qn as slashCommands,Jl as workflowPanel,Et as workflowPanelFromRun,Jn as workflowRunOf};
@@ -0,0 +1,6 @@
1
+ import{a as g}from"./chunk-UTYFLLSM.js";import{h,i as E}from"./chunk-DMNE4TU6.js";import{existsSync as L,mkdirSync as R,readFileSync as p}from"node:fs";import{join as b}from"node:path";var P="https://models.dev/api.json";var _=["anthropic","openai","google","deepseek","zai","xai","moonshotai","minimax","alibaba","xiaomi","meta","tencent","nvidia","venice","openrouter"];function y(t){return t.toLowerCase().replace(/[^a-z0-9]+/g,"")}function A(t){let o=t.split("/");return y(o[o.length-1]??t)}function F(t){let o=new Map,n=new Map;if(!t||typeof t!="object")return o;let r=t,e=a=>{let s=_.indexOf(a);return s===-1?_.length:s};for(let a of Object.keys(r).sort()){let s=r[a]?.models;if(!(!s||typeof s!="object"))for(let i of Object.keys(s)){let c=s[i],l=Number(c?.limit?.context);if(!Number.isFinite(l)||l<=0)continue;let u=y(i),d=e(a),f=n.get(u);if(f!==void 0&&f<=d)continue;let m=Number(c?.limit?.output);o.set(u,{contextWindow:Math.floor(l),maxTokens:Number.isFinite(m)&&m>0?Math.floor(m):void 0,reasoning:c?.reasoning===!0,vision:Array.isArray(c?.modalities?.input)&&c.modalities.input.includes("image")}),n.set(u,d)}}return o}function T(t,o){let n=y(o);if(!n)return;let r=t.get(n);if(r)return r;let e=A(o);for(let[a,s]of t)if(A(a)===e)return s;for(let[a,s]of t)if(a.endsWith(n)||n.endsWith(a))return s}function O(t){return`${t}/models-dev-cache.json`}function S(t){let o={};for(let[n,r]of t)o[n]=[r.contextWindow,r.maxTokens??0,r.reasoning?1:0,r.vision?1:0];return JSON.stringify(o)}function v(t){let o=new Map,n;try{n=JSON.parse(t)}catch{return o}if(!n||typeof n!="object")return o;for(let[r,e]of Object.entries(n)){if(!Array.isArray(e)||e.length<3)continue;let a=Number(e[0]),s=Number(e[1]);!Number.isFinite(a)||a<=0||o.set(r,{contextWindow:Math.floor(a),maxTokens:Number.isFinite(s)&&s>0?Math.floor(s):void 0,reasoning:e[2]===1||e[2]===!0,vision:e[3]===1||e[3]===!0})}return o}async function I(t){let o=t?.url??P,n=t?.fetchImpl??fetch,r=t?.timeoutMs??2e4,e=new AbortController,a=setTimeout(()=>e.abort(),r);try{let s=await n(o,{signal:e.signal,headers:{Accept:"application/json"}});if(!s.ok)return{ok:!1,message:`the model catalogue answered ${s.status}`};let i=F(await s.json());return i.size===0?{ok:!1,message:"the model catalogue was empty or in an unexpected shape"}:{ok:!0,index:i}}catch(s){return{ok:!1,message:s instanceof Error&&s.name==="AbortError"?`the model catalogue did not answer within ${Math.round(r/1e3)}s`:"could not reach the model catalogue"}}finally{clearTimeout(a)}}var x="https://api.howtofix.id/v1",te="https://howtofix.id/keys",M=["howtofix","howtofix-free"];function ne(t){try{let n=JSON.parse(p(b(t,"models.json"),"utf8")).providers;return!n||typeof n!="object"?new Set:new Set(Object.keys(n))}catch{return new Set}}function re(){return{baseUrl:x,api:"openai-completions",headers:{[h]:E()}}}function oe(t){let o=b(t,"models.json"),n;try{n=JSON.parse(p(o,"utf8"))}catch{return 0}let r=n.providers;if(!r||typeof r!="object")return 0;let e=0;for(let a of M){let s=r[a];if(!s||!Array.isArray(s.models))continue;let i=B(s.models),c={...s.headers??{},[h]:E()},l=s.headers?.[h]!==c[h];i.changed===0&&!l||(s.models=i.models,s.headers=c,e+=i.changed===0?1:i.changed)}if(e===0)return 0;try{g(o,`${JSON.stringify(n,null,2)}
2
+ `)}catch{return 0}return e}var W=10080*60*1e3;async function N(t,o){let n=O(t),r=o?.now??Date.now(),e,a=0;try{let c=JSON.parse(p(n,"utf8"));typeof c?.entries=="string"&&(e=v(c.entries),a=Number(c.at)||0)}catch{e=void 0}if(e&&e.size>0&&r-a<W&&!o?.force)return{index:e};let i=await I({fetchImpl:o?.fetchImpl});if(!i.ok)return e&&e.size>0?{index:e,message:i.message}:{index:new Map,message:i.message};try{R(t,{recursive:!0}),g(n,`${JSON.stringify({at:r,entries:S(i.index)})}
3
+ `)}catch{}return{index:i.index}}async function se(t,o){let n=b(t,"models.json"),r;try{r=JSON.parse(p(n,"utf8"))}catch{return{changed:0}}let e=r.providers;if(!e||typeof e!="object")return{changed:0};let{index:a,message:s}=await N(t,o);if(a.size===0)return{changed:0,message:s};let i=0;for(let c of M){let l=e[c];if(!l||!Array.isArray(l.models))continue;let u=X(l.models,a);u.changed!==0&&(l.models=u.models,i+=u.changed)}if(i>0)try{g(n,`${JSON.stringify(r,null,2)}
4
+ `)}catch{return{changed:0,message:"the models file could not be written"}}return{changed:i,message:s}}var D=3e5;function ae(t){let o=b(t,"settings.json"),n={};try{let r=p(o,"utf8"),e=JSON.parse(r);e&&typeof e=="object"&&!Array.isArray(e)&&(n=e)}catch{if(L(o))return!1}if("httpIdleTimeoutMs"in n)return!1;n.httpIdleTimeoutMs=D;try{R(t,{recursive:!0}),g(o,`${JSON.stringify(n,null,2)}
5
+ `)}catch{return!1}return!0}var $={supportsDeveloperRole:!1},j=128e3;function ie(t){let o=t.trim();return o.length<=10?"***":`${o.slice(0,6)}\u2026${o.slice(-4)}`}function ce(t){return/^sk-[A-Za-z0-9_-]{8,}$/.test(t.trim())}function z(t){let o=(()=>{if(Array.isArray(t))return t;if(t&&typeof t=="object"){let r=t;if(Array.isArray(r.data))return r.data;if(Array.isArray(r.models))return r.models}return[]})(),n=[];for(let r of o){let e=typeof r=="string"?r:r&&typeof r=="object"&&typeof r.id=="string"?r.id:void 0;e&&!n.includes(e)&&n.push(e)}return n}function le(t){return M.includes(t)}var J=1e8;async function H(t,o){let n=await t(o,{headers:{Accept:"application/json"}});if(!n.ok)return"USD";let e=(await n.json())?.data?.quota_display_type;return typeof e=="string"&&e.trim()?e.trim().toUpperCase():"USD"}async function ue(t,o){let n=(o?.baseUrl??x).replace(/\/+$/,""),r=o?.fetchImpl??fetch,e=o?.timeoutMs??15e3,a=t.trim();if(!a)return{ok:!1,unlimited:!1,unit:"USD",message:"no token given"};let s=`${n.replace(/\/v1$/,"")}/api/status`,i=await H(r,s).catch(()=>"USD"),c=new AbortController,l=setTimeout(()=>c.abort(),e),u={Authorization:`Bearer ${a}`};try{let[d,f]=await Promise.all([r(`${n}/dashboard/billing/subscription`,{headers:u,signal:c.signal}),r(`${n}/dashboard/billing/usage`,{headers:u,signal:c.signal})]);if(d.status===401||d.status===403)return{ok:!1,unlimited:!1,unit:i,message:"the gateway rejected that token when asking for the balance"};if(!d.ok)return{ok:!1,unlimited:!1,unit:i,message:`the balance endpoint answered ${d.status}`};let m=await d.json();if(m.error?.message)return{ok:!1,unlimited:!1,unit:i,message:m.error.message};let w=Number(m.hard_limit_usd??m.soft_limit_usd??0);if(w>=J)return{ok:!0,unlimited:!0,unit:i,message:"this token has no quota limit"};let k=0;if(f.ok){let U=await f.json();k=Number(U.total_usage??0)/100}let C=Math.max(0,w-k);return{ok:!0,unlimited:!1,limit:w,used:k,remaining:C,unit:i,message:`${C.toFixed(2)} ${i} left of ${w.toFixed(2)} (${k.toFixed(2)} used)`}}catch(d){let f=d instanceof Error&&d.name==="AbortError";return{ok:!1,unlimited:!1,unit:i,message:f?`the gateway did not answer within ${Math.round(e/1e3)}s`:"could not reach the gateway"}}finally{clearTimeout(l)}}async function de(t,o){let n=b(t,"models.json"),r;try{r=JSON.parse(p(n,"utf8"))}catch{return{added:0,touched:0}}let e=r.providers;if(!e||typeof e!="object")return{added:0,touched:0};let{index:a}=await N(t).catch(()=>({index:new Map})),s=0,i=0;for(let c of M){let l=e[c];if(!l||!Array.isArray(l.models))continue;let u=l.models.length;l.models=G(l.models,o,a),s+=l.models.length-u,i++}if(s===0)return{added:0,touched:i};try{g(n,`${JSON.stringify(r,null,2)}
6
+ `)}catch{return{added:0,touched:i}}return{added:s,touched:i}}function G(t,o,n){let r=new Set(t.map(a=>a.id)),e=[...t];for(let a of o){if(r.has(a))continue;r.add(a);let s=n?.get(y(a))??(n?T(n,a):void 0);e.push({id:a,contextWindow:s?.contextWindow??j,...s?.maxTokens?{maxTokens:s.maxTokens}:{},...s?{reasoning:s.reasoning}:{},...s?.vision?{input:["text","image"]}:{},compat:{...$}})}return e}function X(t,o){let n=0;return{models:t.map(e=>{let a=T(o,e.id);if(!a)return e;let s={...e},i=!1;return a.contextWindow&&e.contextWindow===j&&(s.contextWindow=a.contextWindow,i=!0),a.maxTokens&&!e.maxTokens&&(s.maxTokens=a.maxTokens,i=!0),e.reasoning===void 0&&(s.reasoning=a.reasoning,i=!0),a.vision&&!(e.input??[]).includes("image")&&(s.input=[...(e.input??["text"]).filter(c=>c!=="image"),"image"],i=!0),i?(n++,s):e}),changed:n}}function B(t){let o=0;return{models:t.map(r=>r.compat?.supportsDeveloperRole===!1?r:(o++,{...r,compat:{...r.compat,...$}})),changed:o}}function me(t,o){let n=new Set(t.map(r=>r.id));return o.filter(r=>!n.has(r)).length}async function V(t,o,n){let r=(n?.baseUrl??x).replace(/\/+$/,""),e=n?.fetchImpl??fetch,a=n?.timeoutMs??1e4,s=new AbortController,i=setTimeout(()=>s.abort(),a);try{let c=await e(`${r}/chat/completions`,{method:"POST",headers:{Authorization:`Bearer ${o}`,"Content-Type":"application/json"},body:JSON.stringify({model:t,messages:[{role:"user",content:"hi"}],max_tokens:1}),signal:s.signal});if(c.ok)return{ok:!0,detail:"ok"};let l=await c.text().catch(()=>"");return{ok:!1,detail:/"message"\s*:\s*"([^"]{0,80})/.exec(l)?.[1]??`HTTP ${c.status}`}}catch(c){return{ok:!1,detail:c instanceof Error&&c.name==="AbortError"?"timed out":"unreachable"}}finally{clearTimeout(i)}}async function fe(t,o,n){let r=Math.max(0,n?.limit??4),e=[...new Set(t)].filter(s=>s!==n?.exclude).slice(0,r),a=await Promise.all(e.map(s=>V(s,o,n)));return{live:e.filter((s,i)=>a[i]?.ok),probed:e}}async function ge(t,o){let n=(o?.baseUrl??x).replace(/\/+$/,""),r=o?.fetchImpl??fetch,e=o?.timeoutMs??15e3,a=t.trim();if(!a)return{ok:!1,models:[],message:"no token given"};let s=new AbortController,i=setTimeout(()=>s.abort(),e);try{let c=await r(`${n}/models`,{headers:{Authorization:`Bearer ${a}`},signal:s.signal});if(c.status===401)return{ok:!1,models:[],message:"the gateway rejected that token (401). Check it in the Console, or make a new one."};if(c.status===403)return{ok:!1,models:[],message:"that token is not allowed to list models (403). The Console shows what a token may call."};if(!c.ok)return{ok:!1,models:[],message:`the gateway answered ${c.status}`};let l=z(await c.json());return l.length===0?{ok:!1,models:[],message:"the token works but the gateway listed no models"}:{ok:!0,models:l,message:`${l.length} models available to this token`}}catch(c){let l=c instanceof Error&&c.name==="AbortError";return{ok:!1,models:[],message:l?`the gateway did not answer within ${Math.round(e/1e3)}s`:"could not reach the gateway"}}finally{clearTimeout(i)}}export{x as a,te as b,M as c,ne as d,re as e,oe as f,W as g,N as h,se as i,D as j,ae as k,$ as l,j as m,ie as n,ce as o,z as p,le as q,J as r,ue as s,de as t,G as u,X as v,B as w,me as x,V as y,fe as z,ge as A};
@@ -1,2 +1,2 @@
1
- import{a as x}from"./chunk-UTYFLLSM.js";import{g as P,j as M}from"./chunk-WZKWT757.js";import{existsSync as z,readFileSync as ye}from"node:fs";import{join as xe}from"node:path";import{createHash as J,randomBytes as G}from"node:crypto";import{createServer as ne}from"node:http";import{execFileSync as X}from"node:child_process";import{createHmac as Q}from"node:crypto";import{readFileSync as ee}from"node:fs";import{arch as N,cpus as $,hostname as O,platform as _,userInfo as H}from"node:os";var te="howtofix-cli-hwid-v1";function v(e){try{let t=ee(e,"utf8").trim();return t.length>0?t:void 0}catch{return}}function F(e,t){try{let r=X(e,t,{encoding:"utf8",timeout:3e3,stdio:["ignore","pipe","ignore"]});return r.trim().length>0?r.trim():void 0}catch{return}}function re(){let e=_();if(e==="linux"){let t=v("/etc/machine-id");if(t)return{value:t,source:"machine-id",strong:!0};let r=v("/var/lib/dbus/machine-id");if(r)return{value:r,source:"dbus-machine-id",strong:!0};let s=v("/sys/class/dmi/id/product_uuid");return s?{value:s,source:"dmi-product-uuid",strong:!0}:void 0}if(e==="win32"){let r=F("reg",["query","HKLM\\SOFTWARE\\Microsoft\\Cryptography","/v","MachineGuid"])?.match(/MachineGuid\s+REG_SZ\s+(\S+)/i);return r?.[1]?{value:r[1],source:"windows-machine-guid",strong:!0}:void 0}if(e==="darwin"){let r=F("ioreg",["-rd1","-c","IOPlatformExpertDevice"])?.match(/"IOPlatformUUID"\s*=\s*"([^"]+)"/);return r?.[1]?{value:r[1],source:"platform-uuid",strong:!0}:void 0}}function U(){let e=re(),t=e?.value??[O(),_(),N(),H().username].join("\0"),r=e?.source??"hostname";return{id:Q("sha256",te).update(t).digest("hex").slice(0,32),source:r,strong:e?.strong??!1}}function j(e){return[e.id,e.source,O(),_(),N(),H().username,String($().length),$()[0]?.model??""]}var I="https://howtofix.id",se=300*1e3,L=3e3,K="/callback";function A(e){return e.toString("base64").replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function oe(){return A(G(32))}function ie(e){return A(J("sha256").update(e).digest())}function ae(){return A(G(16))}var ce="howtofix-cli-",ue="x-howtofix-client",le="cli";function C(e){let t=e??j(U());return ce+J("sha256").update(t.join("\0")).digest("hex").slice(0,32)}function de(){return{"content-type":"application/json",[ue]:le}}var fe=()=>new Promise((e,t)=>{let r=ne();r.once("error",t),r.listen(0,"127.0.0.1",()=>{let{port:s}=r.address();e({port:s,close:()=>r.close(),waitForCode:(o,n)=>new Promise((i,a)=>{let c=(l,m)=>{let h=new URL(l.url??"/","http://127.0.0.1");if(h.pathname!==K){m.writeHead(404).end("not found");return}let y=(V,Z)=>m.writeHead(200,{"content-type":"text/html; charset=utf-8"}).end(`<!doctype html><meta charset="utf-8"><h2>${V}</h2><p>${Z}</p>`),T=h.searchParams.get("error")??"",R=h.searchParams.get("code")??"",Y=h.searchParams.get("state")??"";if(T){y("Sign-in was refused","You can close this tab."),u(new Error(`the browser reported: ${T}`));return}if(!R||Y!==o){y("This callback did not belong to the login","You can close this tab."),u(new Error("the callback carried the wrong state"));return}y("Signed in","You can close this tab and go back to HowToFix."),u(void 0,R)},u=(l,m)=>{r.off("request",c),n?.removeEventListener("abort",f),l?a(l):i(m)},f=()=>u(new Error("cancelled"));n?.addEventListener("abort",f,{once:!0}),r.on("request",c)})})})});function k(e,t){e.onProgress?.(t)}async function g(e,t,r,s){let o=await e(t,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(r),signal:s}),n={};try{n=await o.json()}catch{}let i=Number(o.headers?.get?.("retry-after"));return{status:o.status,body:n,retryAfterSeconds:Number.isFinite(i)&&i>0?i:void 0}}function d(...e){for(let t of e)if(typeof t=="string"&&t.trim()!=="")return t.trim()}function D(...e){for(let t of e)if(typeof t=="number"&&Number.isFinite(t))return t;return 0}function me(e){try{let t=new URL(e).searchParams.get("code");return t&&t.trim()!==""?t.trim():void 0}catch{return}}async function pe(e,t,r){let s=await e(t,{headers:de(),signal:r}),o={};try{o=await s.json()}catch{}let n=Number(s.headers?.get?.("retry-after"));return{status:s.status,body:o,retryAfterSeconds:Number.isFinite(n)&&n>0?n:void 0}}function S(e){let t=e.data,r=[e.token,e.api_key,e.apiKey,e.key,t?.token,t?.api_key,t?.apiKey,t?.key];for(let s of r)if(typeof s=="string"&&s.trim().startsWith("sk-"))return s.trim()}function ge(e){let t=e.data,r=d(e.token,t?.token),s=d(e.refresh_token,t?.refresh_token),o=d(e.device_id,t?.device_id);if(!r||!s||!o)return;let n=D(e.access_expires_at,t?.access_expires_at),i=D(e.refresh_expires_at,t?.refresh_expires_at);return{accessToken:r,accessExpiresAt:n,refreshToken:s,deviceId:o,refreshExpiresAt:i}}function p(e,t){let r=e.message??e.error;return typeof r=="string"&&r.trim()?r.trim():t}async function Oe(e){let t=e.fetchImpl??fetch,r=(e.panelUrl??I).replace(/\/+$/,""),s=e.timeoutMs??se,o={...e,panel:r,fetchImpl:t,timeoutMs:s},n=await ke(o);if(n.ok||n.terminal)return n.result;let i=await he(o);if(i.ok||i.terminal)return i.result;let a=await we(o);return a.ok?a:{ok:!1,message:`${n.result.ok?"":n.result.message}; ${i.result.ok?"":i.result.message}; ${a.message}. howtofix.id does not offer a browser login a local client can complete yet \u2014 run /connect and paste a token from ${r}/keys instead.`}}async function he(e){let t=oe(),r=ae(),s;try{s=await(e.loopback??fe)();let o=`http://127.0.0.1:${s.port}${K}`,n=await g(e.fetchImpl,`${e.panel}/api/oauth/device/start`,{redirect_uri:o,code_challenge:ie(t),code_challenge_method:"S256",state:r},e.signal);if(n.status===404)return{ok:!1,terminal:!1,result:{ok:!1,message:"the panel has no loopback login endpoint"}};if(n.status>=400)return{ok:!1,terminal:!1,result:{ok:!1,message:p(n.body,`the panel refused the login (${n.status})`)}};let i=typeof n.body.authorize_url=="string"?n.body.authorize_url:"";if(!i)return{ok:!1,terminal:!1,result:{ok:!1,message:"the panel did not say where to send the browser"}};k(e,{kind:"browser",url:i});let a=await be(s.waitForCode(r,e.signal),e.timeoutMs),c=await g(e.fetchImpl,`${e.panel}/api/oauth/device/token`,{flow_token:n.body.flow_token,code:a,code_verifier:t},e.signal);if(c.status>=400)return{ok:!1,terminal:!0,result:{ok:!1,message:p(c.body,`the panel refused the exchange (${c.status})`)}};let u=S(c.body);return u?{ok:!0,result:{ok:!0,token:u}}:{ok:!1,terminal:!0,result:{ok:!1,message:"the panel did not return an API key"}}}catch(o){let n=o instanceof Error?o.message:String(o);return{ok:!1,terminal:n==="cancelled",result:{ok:!1,message:n}}}finally{s?.close()}}async function ke(e){let t=e.pollIntervalMs??L,r=e.fingerprintId??C(),s=e.clientInfo??P(),o=M(r,s);try{let n=await g(e.fetchImpl,`${e.panel}/api/auth/cli/code`,{fingerprintId:r,clientInfo:s,...o},e.signal);if(n.status===404)return{ok:!1,terminal:!1,result:{ok:!1,message:"the panel has no CLI login endpoint"}};if(n.status===401)return{ok:!1,terminal:!1,result:{ok:!1,message:"the panel did not recognise this build as the HowToFix CLI \u2014 update it with `npm install -g howtofixcli@latest`"}};if(n.status===429)return{ok:!1,terminal:!0,result:{ok:!1,message:`too many sign-in attempts from this machine right now.${n.retryAfterSeconds?` Try again in ${Math.ceil(n.retryAfterSeconds/60)} minute(s).`:""}`}};if(n.status>=400)return{ok:!1,terminal:!1,result:{ok:!1,message:p(n.body,`the panel refused the login (${n.status})`)}};let i=n.body.data??{},a=d(n.body.login_url,i.login_url),c=d(n.body.code,i.code)??(a?me(a):void 0),u=d(n.body.secret,i.secret);return!a||!c?{ok:!1,terminal:!1,result:{ok:!1,message:"the panel did not return a login URL"}}:u?(k(e,{kind:"browser",url:a}),await q(e,c,u)):(k(e,{kind:"browser",url:a}),await q(e,c,void 0))}catch(n){let i=n instanceof Error?n.message:String(n);return{ok:!1,terminal:i==="cancelled",result:{ok:!1,message:i}}}}async function q(e,t,r){let s=e.pollIntervalMs??L,o=Date.now()+e.timeoutMs;for(;Date.now()<o;){await w(s,e.signal);let n=new URLSearchParams(r?{code:t,secret:r}:{code:t});n.set("capability","device-refresh");let i=await pe(e.fetchImpl,`${e.panel}/api/auth/cli/status?${n}`,e.signal);if(i.status===404)return{ok:!1,terminal:!1,result:{ok:!1,message:"the panel has no CLI login status endpoint"}};if(i.status===403)return{ok:!1,terminal:!0,result:{ok:!1,message:"the panel rejected this poll \u2014 run /connect again"}};if(i.status===429){let u=Math.min(Math.max(i.retryAfterSeconds??5,1)*1e3,3e4);await w(u,e.signal);continue}let a=S(i.body);if(a)return{ok:!0,result:{ok:!0,token:a,credential:ge(i.body)}};if(d(i.body.data?.status,i.body.status)==="expired")return{ok:!1,terminal:!0,result:{ok:!1,message:"the sign-in link expired before it was approved"}};if(i.status>=400)return{ok:!1,terminal:!0,result:{ok:!1,message:p(i.body,`the panel refused the poll (${i.status})`)}}}return{ok:!1,terminal:!0,result:{ok:!1,message:"the sign-in was not approved in time"}}}async function we(e){let t=e.pollIntervalMs??L;try{let r=await g(e.fetchImpl,`${e.panel}/api/oauth/device`,{},e.signal);if(r.status===404)return{ok:!1,message:"the panel has no device-code endpoint"};if(r.status>=400)return{ok:!1,message:p(r.body,`the panel refused the request (${r.status})`)};let s=typeof r.body.device_code=="string"?r.body.device_code:"",o=typeof r.body.user_code=="string"?r.body.user_code:"",n=typeof r.body.verification_uri=="string"?r.body.verification_uri:`${e.panel}/oauth/device`;if(!s||!o)return{ok:!1,message:"the panel did not return a code to show"};k(e,{kind:"code",code:o,url:n});let i=Date.now()+e.timeoutMs;for(;Date.now()<i;){await w(t,e.signal);let a=await g(e.fetchImpl,`${e.panel}/api/oauth/device/poll`,{device_code:s},e.signal);if(a.status===404)return{ok:!1,message:"the panel has no device-code poll endpoint"};let c=typeof a.body.status=="string"?a.body.status:"";if(c==="pending")continue;if(c==="slow_down"){await w(t,e.signal);continue}if(c==="denied")return{ok:!1,message:"the sign-in was refused in the browser"};if(c==="expired")return{ok:!1,message:"the code expired; run /connect again"};let u=S(a.body);if(u)return{ok:!0,token:u};if(a.status>=400)return{ok:!1,message:p(a.body,`the panel refused the poll (${a.status})`)}}return{ok:!1,message:"the code was not approved in time"}}catch(r){return{ok:!1,message:r instanceof Error?r.message:String(r)}}}function be(e,t){return new Promise((r,s)=>{let o=setTimeout(()=>s(new Error("the sign-in was not finished in time")),t);e.then(n=>{clearTimeout(o),r(n)},n=>{clearTimeout(o),s(n)})})}function w(e,t){return new Promise((r,s)=>{let o=setTimeout(r,e);t?.addEventListener("abort",()=>{clearTimeout(o),s(new Error("cancelled"))},{once:!0})})}function b(e){return xe(e,"cli-credentials.json")}var ve=300*1e3;function _e(e,t=Date.now()){return e.accessToken?!Number.isFinite(e.accessExpiresAt)||e.accessExpiresAt<=0?!0:e.accessExpiresAt*1e3-ve>t:!1}function Ie(e,t=Date.now()){return!e.refreshToken||!e.deviceId?!1:!Number.isFinite(e.refreshExpiresAt)||e.refreshExpiresAt<=0?!0:e.refreshExpiresAt*1e3>t}function Je(e){let t=b(e);if(!z(t))return;let r;try{r=JSON.parse(ye(t,"utf8"))}catch{return}if(!r||typeof r!="object"||Array.isArray(r))return;let s=r,o=typeof s.accessToken=="string"?s.accessToken.trim():"",n=typeof s.refreshToken=="string"?s.refreshToken.trim():"",i=typeof s.deviceId=="string"?s.deviceId.trim():"";if(!(!o||!n||!i))return{accessToken:o,accessExpiresAt:W(s.accessExpiresAt),refreshToken:n,deviceId:i,refreshExpiresAt:W(s.refreshExpiresAt)}}function Le(e,t){try{return x(b(e),`${JSON.stringify(t,null,2)}
1
+ import{a as x}from"./chunk-UTYFLLSM.js";import{g as P,j as M}from"./chunk-DMNE4TU6.js";import{existsSync as z,readFileSync as ye}from"node:fs";import{join as xe}from"node:path";import{createHash as J,randomBytes as G}from"node:crypto";import{createServer as ne}from"node:http";import{execFileSync as X}from"node:child_process";import{createHmac as Q}from"node:crypto";import{readFileSync as ee}from"node:fs";import{arch as N,cpus as $,hostname as O,platform as _,userInfo as H}from"node:os";var te="howtofix-cli-hwid-v1";function v(e){try{let t=ee(e,"utf8").trim();return t.length>0?t:void 0}catch{return}}function F(e,t){try{let r=X(e,t,{encoding:"utf8",timeout:3e3,stdio:["ignore","pipe","ignore"]});return r.trim().length>0?r.trim():void 0}catch{return}}function re(){let e=_();if(e==="linux"){let t=v("/etc/machine-id");if(t)return{value:t,source:"machine-id",strong:!0};let r=v("/var/lib/dbus/machine-id");if(r)return{value:r,source:"dbus-machine-id",strong:!0};let s=v("/sys/class/dmi/id/product_uuid");return s?{value:s,source:"dmi-product-uuid",strong:!0}:void 0}if(e==="win32"){let r=F("reg",["query","HKLM\\SOFTWARE\\Microsoft\\Cryptography","/v","MachineGuid"])?.match(/MachineGuid\s+REG_SZ\s+(\S+)/i);return r?.[1]?{value:r[1],source:"windows-machine-guid",strong:!0}:void 0}if(e==="darwin"){let r=F("ioreg",["-rd1","-c","IOPlatformExpertDevice"])?.match(/"IOPlatformUUID"\s*=\s*"([^"]+)"/);return r?.[1]?{value:r[1],source:"platform-uuid",strong:!0}:void 0}}function U(){let e=re(),t=e?.value??[O(),_(),N(),H().username].join("\0"),r=e?.source??"hostname";return{id:Q("sha256",te).update(t).digest("hex").slice(0,32),source:r,strong:e?.strong??!1}}function j(e){return[e.id,e.source,O(),_(),N(),H().username,String($().length),$()[0]?.model??""]}var I="https://howtofix.id",se=300*1e3,L=3e3,K="/callback";function A(e){return e.toString("base64").replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function oe(){return A(G(32))}function ie(e){return A(J("sha256").update(e).digest())}function ae(){return A(G(16))}var ce="howtofix-cli-",ue="x-howtofix-client",le="cli";function C(e){let t=e??j(U());return ce+J("sha256").update(t.join("\0")).digest("hex").slice(0,32)}function de(){return{"content-type":"application/json",[ue]:le}}var fe=()=>new Promise((e,t)=>{let r=ne();r.once("error",t),r.listen(0,"127.0.0.1",()=>{let{port:s}=r.address();e({port:s,close:()=>r.close(),waitForCode:(o,n)=>new Promise((i,a)=>{let c=(l,m)=>{let h=new URL(l.url??"/","http://127.0.0.1");if(h.pathname!==K){m.writeHead(404).end("not found");return}let y=(V,Z)=>m.writeHead(200,{"content-type":"text/html; charset=utf-8"}).end(`<!doctype html><meta charset="utf-8"><h2>${V}</h2><p>${Z}</p>`),T=h.searchParams.get("error")??"",R=h.searchParams.get("code")??"",Y=h.searchParams.get("state")??"";if(T){y("Sign-in was refused","You can close this tab."),u(new Error(`the browser reported: ${T}`));return}if(!R||Y!==o){y("This callback did not belong to the login","You can close this tab."),u(new Error("the callback carried the wrong state"));return}y("Signed in","You can close this tab and go back to HowToFix."),u(void 0,R)},u=(l,m)=>{r.off("request",c),n?.removeEventListener("abort",f),l?a(l):i(m)},f=()=>u(new Error("cancelled"));n?.addEventListener("abort",f,{once:!0}),r.on("request",c)})})})});function k(e,t){e.onProgress?.(t)}async function g(e,t,r,s){let o=await e(t,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(r),signal:s}),n={};try{n=await o.json()}catch{}let i=Number(o.headers?.get?.("retry-after"));return{status:o.status,body:n,retryAfterSeconds:Number.isFinite(i)&&i>0?i:void 0}}function d(...e){for(let t of e)if(typeof t=="string"&&t.trim()!=="")return t.trim()}function D(...e){for(let t of e)if(typeof t=="number"&&Number.isFinite(t))return t;return 0}function me(e){try{let t=new URL(e).searchParams.get("code");return t&&t.trim()!==""?t.trim():void 0}catch{return}}async function pe(e,t,r){let s=await e(t,{headers:de(),signal:r}),o={};try{o=await s.json()}catch{}let n=Number(s.headers?.get?.("retry-after"));return{status:s.status,body:o,retryAfterSeconds:Number.isFinite(n)&&n>0?n:void 0}}function S(e){let t=e.data,r=[e.token,e.api_key,e.apiKey,e.key,t?.token,t?.api_key,t?.apiKey,t?.key];for(let s of r)if(typeof s=="string"&&s.trim().startsWith("sk-"))return s.trim()}function ge(e){let t=e.data,r=d(e.token,t?.token),s=d(e.refresh_token,t?.refresh_token),o=d(e.device_id,t?.device_id);if(!r||!s||!o)return;let n=D(e.access_expires_at,t?.access_expires_at),i=D(e.refresh_expires_at,t?.refresh_expires_at);return{accessToken:r,accessExpiresAt:n,refreshToken:s,deviceId:o,refreshExpiresAt:i}}function p(e,t){let r=e.message??e.error;return typeof r=="string"&&r.trim()?r.trim():t}async function Oe(e){let t=e.fetchImpl??fetch,r=(e.panelUrl??I).replace(/\/+$/,""),s=e.timeoutMs??se,o={...e,panel:r,fetchImpl:t,timeoutMs:s},n=await ke(o);if(n.ok||n.terminal)return n.result;let i=await he(o);if(i.ok||i.terminal)return i.result;let a=await we(o);return a.ok?a:{ok:!1,message:`${n.result.ok?"":n.result.message}; ${i.result.ok?"":i.result.message}; ${a.message}. howtofix.id does not offer a browser login a local client can complete yet \u2014 run /connect and paste a token from ${r}/keys instead.`}}async function he(e){let t=oe(),r=ae(),s;try{s=await(e.loopback??fe)();let o=`http://127.0.0.1:${s.port}${K}`,n=await g(e.fetchImpl,`${e.panel}/api/oauth/device/start`,{redirect_uri:o,code_challenge:ie(t),code_challenge_method:"S256",state:r},e.signal);if(n.status===404)return{ok:!1,terminal:!1,result:{ok:!1,message:"the panel has no loopback login endpoint"}};if(n.status>=400)return{ok:!1,terminal:!1,result:{ok:!1,message:p(n.body,`the panel refused the login (${n.status})`)}};let i=typeof n.body.authorize_url=="string"?n.body.authorize_url:"";if(!i)return{ok:!1,terminal:!1,result:{ok:!1,message:"the panel did not say where to send the browser"}};k(e,{kind:"browser",url:i});let a=await be(s.waitForCode(r,e.signal),e.timeoutMs),c=await g(e.fetchImpl,`${e.panel}/api/oauth/device/token`,{flow_token:n.body.flow_token,code:a,code_verifier:t},e.signal);if(c.status>=400)return{ok:!1,terminal:!0,result:{ok:!1,message:p(c.body,`the panel refused the exchange (${c.status})`)}};let u=S(c.body);return u?{ok:!0,result:{ok:!0,token:u}}:{ok:!1,terminal:!0,result:{ok:!1,message:"the panel did not return an API key"}}}catch(o){let n=o instanceof Error?o.message:String(o);return{ok:!1,terminal:n==="cancelled",result:{ok:!1,message:n}}}finally{s?.close()}}async function ke(e){let t=e.pollIntervalMs??L,r=e.fingerprintId??C(),s=e.clientInfo??P(),o=M(r,s);try{let n=await g(e.fetchImpl,`${e.panel}/api/auth/cli/code`,{fingerprintId:r,clientInfo:s,...o},e.signal);if(n.status===404)return{ok:!1,terminal:!1,result:{ok:!1,message:"the panel has no CLI login endpoint"}};if(n.status===401)return{ok:!1,terminal:!1,result:{ok:!1,message:"the panel did not recognise this build as the HowToFix CLI \u2014 update it with `npm install -g howtofixcli@latest`"}};if(n.status===429)return{ok:!1,terminal:!0,result:{ok:!1,message:`too many sign-in attempts from this machine right now.${n.retryAfterSeconds?` Try again in ${Math.ceil(n.retryAfterSeconds/60)} minute(s).`:""}`}};if(n.status>=400)return{ok:!1,terminal:!1,result:{ok:!1,message:p(n.body,`the panel refused the login (${n.status})`)}};let i=n.body.data??{},a=d(n.body.login_url,i.login_url),c=d(n.body.code,i.code)??(a?me(a):void 0),u=d(n.body.secret,i.secret);return!a||!c?{ok:!1,terminal:!1,result:{ok:!1,message:"the panel did not return a login URL"}}:u?(k(e,{kind:"browser",url:a}),await q(e,c,u)):(k(e,{kind:"browser",url:a}),await q(e,c,void 0))}catch(n){let i=n instanceof Error?n.message:String(n);return{ok:!1,terminal:i==="cancelled",result:{ok:!1,message:i}}}}async function q(e,t,r){let s=e.pollIntervalMs??L,o=Date.now()+e.timeoutMs;for(;Date.now()<o;){await w(s,e.signal);let n=new URLSearchParams(r?{code:t,secret:r}:{code:t});n.set("capability","device-refresh");let i=await pe(e.fetchImpl,`${e.panel}/api/auth/cli/status?${n}`,e.signal);if(i.status===404)return{ok:!1,terminal:!1,result:{ok:!1,message:"the panel has no CLI login status endpoint"}};if(i.status===403)return{ok:!1,terminal:!0,result:{ok:!1,message:"the panel rejected this poll \u2014 run /connect again"}};if(i.status===429){let u=Math.min(Math.max(i.retryAfterSeconds??5,1)*1e3,3e4);await w(u,e.signal);continue}let a=S(i.body);if(a)return{ok:!0,result:{ok:!0,token:a,credential:ge(i.body)}};if(d(i.body.data?.status,i.body.status)==="expired")return{ok:!1,terminal:!0,result:{ok:!1,message:"the sign-in link expired before it was approved"}};if(i.status>=400)return{ok:!1,terminal:!0,result:{ok:!1,message:p(i.body,`the panel refused the poll (${i.status})`)}}}return{ok:!1,terminal:!0,result:{ok:!1,message:"the sign-in was not approved in time"}}}async function we(e){let t=e.pollIntervalMs??L;try{let r=await g(e.fetchImpl,`${e.panel}/api/oauth/device`,{},e.signal);if(r.status===404)return{ok:!1,message:"the panel has no device-code endpoint"};if(r.status>=400)return{ok:!1,message:p(r.body,`the panel refused the request (${r.status})`)};let s=typeof r.body.device_code=="string"?r.body.device_code:"",o=typeof r.body.user_code=="string"?r.body.user_code:"",n=typeof r.body.verification_uri=="string"?r.body.verification_uri:`${e.panel}/oauth/device`;if(!s||!o)return{ok:!1,message:"the panel did not return a code to show"};k(e,{kind:"code",code:o,url:n});let i=Date.now()+e.timeoutMs;for(;Date.now()<i;){await w(t,e.signal);let a=await g(e.fetchImpl,`${e.panel}/api/oauth/device/poll`,{device_code:s},e.signal);if(a.status===404)return{ok:!1,message:"the panel has no device-code poll endpoint"};let c=typeof a.body.status=="string"?a.body.status:"";if(c==="pending")continue;if(c==="slow_down"){await w(t,e.signal);continue}if(c==="denied")return{ok:!1,message:"the sign-in was refused in the browser"};if(c==="expired")return{ok:!1,message:"the code expired; run /connect again"};let u=S(a.body);if(u)return{ok:!0,token:u};if(a.status>=400)return{ok:!1,message:p(a.body,`the panel refused the poll (${a.status})`)}}return{ok:!1,message:"the code was not approved in time"}}catch(r){return{ok:!1,message:r instanceof Error?r.message:String(r)}}}function be(e,t){return new Promise((r,s)=>{let o=setTimeout(()=>s(new Error("the sign-in was not finished in time")),t);e.then(n=>{clearTimeout(o),r(n)},n=>{clearTimeout(o),s(n)})})}function w(e,t){return new Promise((r,s)=>{let o=setTimeout(r,e);t?.addEventListener("abort",()=>{clearTimeout(o),s(new Error("cancelled"))},{once:!0})})}function b(e){return xe(e,"cli-credentials.json")}var ve=300*1e3;function _e(e,t=Date.now()){return e.accessToken?!Number.isFinite(e.accessExpiresAt)||e.accessExpiresAt<=0?!0:e.accessExpiresAt*1e3-ve>t:!1}function Ie(e,t=Date.now()){return!e.refreshToken||!e.deviceId?!1:!Number.isFinite(e.refreshExpiresAt)||e.refreshExpiresAt<=0?!0:e.refreshExpiresAt*1e3>t}function Je(e){let t=b(e);if(!z(t))return;let r;try{r=JSON.parse(ye(t,"utf8"))}catch{return}if(!r||typeof r!="object"||Array.isArray(r))return;let s=r,o=typeof s.accessToken=="string"?s.accessToken.trim():"",n=typeof s.refreshToken=="string"?s.refreshToken.trim():"",i=typeof s.deviceId=="string"?s.deviceId.trim():"";if(!(!o||!n||!i))return{accessToken:o,accessExpiresAt:W(s.accessExpiresAt),refreshToken:n,deviceId:i,refreshExpiresAt:W(s.refreshExpiresAt)}}function Le(e,t){try{return x(b(e),`${JSON.stringify(t,null,2)}
2
2
  `,{mode:384}),!0}catch{return!1}}function Ae(e){try{let t=b(e);z(t)&&x(t,"",{mode:384})}catch{}}function W(e){return typeof e=="number"&&Number.isFinite(e)?e:0}async function Ce(e,t){let r=(t?.panelUrl??I).replace(/\/+$/,""),s=t?.fetchImpl??fetch,o=t?.timeoutMs??15e3,n=new AbortController,i=setTimeout(()=>n.abort(),o);try{let a=await s(`${r}/api/auth/cli/refresh`,{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify({device_id:e.deviceId,refresh_token:e.refreshToken,fingerprint_id:C()}),signal:n.signal}),c=await a.json().catch(()=>({}));if(a.status===401||a.status===403)return{ok:!1,terminal:!0,message:"this sign-in is no longer valid \u2014 run /connect to sign in again"};if(!a.ok)return{ok:!1,terminal:!1,message:`the panel refused the renewal (${a.status})`};let u=c.data??{},f=E(c.token,u.token),l=E(c.refresh_token,u.refresh_token),m=E(c.device_id,u.device_id)??e.deviceId;return!f||!l?{ok:!1,terminal:!1,message:"the panel did not return a renewed credential"}:{ok:!0,terminal:!1,credential:{accessToken:f,accessExpiresAt:B(c.access_expires_at,u.access_expires_at),refreshToken:l,deviceId:m,refreshExpiresAt:B(c.refresh_expires_at,u.refresh_expires_at)}}}catch(a){return{ok:!1,terminal:!1,message:a instanceof Error&&a.name==="AbortError"?`the panel did not answer within ${Math.round(o/1e3)}s`:"could not reach the panel"}}finally{clearTimeout(i)}}function E(...e){for(let t of e)if(typeof t=="string"&&t.trim())return t.trim()}function B(...e){for(let t of e)if(typeof t=="number"&&Number.isFinite(t))return t;return 0}async function Ge(e,t,r){let s=r?.now??Date.now();if(_e(t,s)||!Ie(t,s))return{credential:t,renewed:!1,terminal:!1};let o=await Ce(t,r);if(!o.ok||!o.credential)return o.terminal&&Ae(e),{credential:t,renewed:!1,terminal:o.terminal,message:o.message};let n=Le(e,o.credential);return{credential:o.credential,renewed:!0,terminal:!1,message:n?void 0:`the renewed sign-in could not be saved to ${b(e)}`}}export{I as a,Oe as b,b as c,ve as d,_e as e,Ie as f,Je as g,Le as h,Ae as i,Ce as j,Ge as k};
@@ -1 +1 @@
1
- import{a,b,c,d,e,f,g,h,i,j}from"./chunk-WZKWT757.js";import"./chunk-4BWDGEXH.js";import"./chunk-WOT6VMZA.js";export{h as CLI_CLIENT_HEADER,a as CLI_SIGNING_KEY_ID,i as cliClientHeader,c as cliSignaturePayload,f as cliSigningKeyFingerprint,e as cliSigningKeyMatchesPanel,b as cliSigningPublicKey,d as createNonce,g as describeClient,j as signLoginRequest};
1
+ import{a,b,c,d,e,f,g,h,i,j}from"./chunk-DMNE4TU6.js";import"./chunk-C6HY4Q4J.js";import"./chunk-WOT6VMZA.js";export{h as CLI_CLIENT_HEADER,a as CLI_SIGNING_KEY_ID,i as cliClientHeader,c as cliSignaturePayload,f as cliSigningKeyFingerprint,e as cliSigningKeyMatchesPanel,b as cliSigningPublicKey,d as createNonce,g as describeClient,j as signLoginRequest};
package/dist/main.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import{b as N,c as U}from"./chunk-6FUWMLWO.js";import{a as M,b as P}from"./chunk-AGGIYXN7.js";import{D as A,K as T}from"./chunk-V656XVXV.js";import"./chunk-UTYFLLSM.js";import{a as i,b as x}from"./chunk-4BWDGEXH.js";import"./chunk-WOT6VMZA.js";var F={off:!0,minimal:!0,low:!0,medium:!0,high:!0,xhigh:!0,max:!0},I={suggest:!0,"auto-edit":!0,"full-auto":!0},R={text:!0,json:!0,"stream-json":!0};function ce(t){let e=Number(t);if(!Number.isFinite(e)||e<=0)throw new Error(`--max-budget-usd needs a positive number of dollars, got '${t}'`);return e}function _(t,e,l){let d=t[e];if(d?.includes("="))return d.slice(d.indexOf("=")+1);let p=t[e+1];if(!p||p.startsWith("-"))throw new Error(`${l} needs a value`);return t.splice(e+1,1),p}function W(t){let e={print:!1,continueSession:!1,noSession:!1,help:!1,version:!1,update:!1,checkUpdate:!1,outputFormat:"text",dangerouslySkipPermissions:!1,sandbox:!1,prompt:""},l=[],d=[...t];for(let p=0;p<d.length;p++){let s=d[p]??"";if(s==="--"){l.push(...d.slice(p+1));break}if(s==="-h"||s==="--help")e.help=!0;else if(s==="-v"||s==="--version")e.version=!0;else if(s==="-p"||s==="--print")e.print=!0;else if(s==="-c"||s==="--continue")e.continueSession=!0;else if(s==="--no-session")e.noSession=!0;else if(s==="--sandbox")e.sandbox=!0;else if(s==="--update")e.update=!0;else if(s==="--check-update")e.checkUpdate=!0;else if(s==="-r"||s==="--resume")e.continueSession=!0;else if(s==="--session"||s.startsWith("--session="))e.sessionPath=_(d,p,"--session");else if(s==="-m"||s==="--model"||s.startsWith("--model="))e.model=_(d,p,"--model");else if(s==="--thinking"||s.startsWith("--thinking="))e.thinking=_(d,p,"--thinking");else if(s==="--approval"||s.startsWith("--approval="))e.approval=_(d,p,"--approval");else if(s==="--output-format"||s.startsWith("--output-format="))e.outputFormat=_(d,p,"--output-format");else if(s==="--max-budget-usd"||s.startsWith("--max-budget-usd="))e.maxBudgetUsd=ce(_(d,p,"--max-budget-usd"));else if(s==="--dangerously-skip-permissions")e.dangerouslySkipPermissions=!0;else{if(s.startsWith("-"))throw new Error(`unknown option ${s}`);l.push(s)}}if(e.thinking&&!F[e.thinking])throw new Error(`thinking must be one of: ${Object.keys(F).join(", ")}`);if(e.approval&&!I[e.approval])throw new Error(`approval must be one of: ${Object.keys(I).join(", ")}`);if(!R[e.outputFormat])throw new Error(`output-format must be one of: ${Object.keys(R).join(", ")}`);if(e.outputFormat!=="text"&&!e.print)throw new Error(`--output-format ${e.outputFormat} is a machine contract; it needs --print`);if(e.dangerouslySkipPermissions&&!e.print)throw new Error("--dangerously-skip-permissions is for unattended runs; it needs --print. interactively, pick an approval mode instead (/approval, or --approval)");if(e.prompt=l.join(" ").trim(),e.update&&e.checkUpdate)throw new Error("--update installs; --check-update only looks. pick one");if((e.update||e.checkUpdate)&&(e.print||e.continueSession||e.sessionPath||e.prompt))throw new Error("--update and --check-update act on the installation, not a session; they take no prompt");if(e.continueSession&&e.noSession)throw new Error("--continue and --no-session cannot be combined");if(e.sessionPath&&e.noSession)throw new Error("--session and --no-session cannot be combined");if(e.sessionPath&&e.continueSession)throw new Error("--session and --continue cannot be combined");if(e.print&&(e.continueSession||e.sessionPath))throw new Error("--print runs one prompt in a throwaway session; it cannot be combined with --continue or --session");if(e.sessionPath&&!e.sessionPath.endsWith(".jsonl"))throw new Error(`--session expects a session file, got '${e.sessionPath}'`);return e}function $(){return`${i} ${x}
2
+ import{b as N,c as U}from"./chunk-6FUWMLWO.js";import{a as M,b as P}from"./chunk-AGGIYXN7.js";import{D as A,K as T}from"./chunk-V656XVXV.js";import"./chunk-UTYFLLSM.js";import{a as i,b as x}from"./chunk-C6HY4Q4J.js";import"./chunk-WOT6VMZA.js";var F={off:!0,minimal:!0,low:!0,medium:!0,high:!0,xhigh:!0,max:!0},I={suggest:!0,"auto-edit":!0,"full-auto":!0},R={text:!0,json:!0,"stream-json":!0};function ce(t){let e=Number(t);if(!Number.isFinite(e)||e<=0)throw new Error(`--max-budget-usd needs a positive number of dollars, got '${t}'`);return e}function _(t,e,l){let d=t[e];if(d?.includes("="))return d.slice(d.indexOf("=")+1);let p=t[e+1];if(!p||p.startsWith("-"))throw new Error(`${l} needs a value`);return t.splice(e+1,1),p}function W(t){let e={print:!1,continueSession:!1,noSession:!1,help:!1,version:!1,update:!1,checkUpdate:!1,outputFormat:"text",dangerouslySkipPermissions:!1,sandbox:!1,prompt:""},l=[],d=[...t];for(let p=0;p<d.length;p++){let s=d[p]??"";if(s==="--"){l.push(...d.slice(p+1));break}if(s==="-h"||s==="--help")e.help=!0;else if(s==="-v"||s==="--version")e.version=!0;else if(s==="-p"||s==="--print")e.print=!0;else if(s==="-c"||s==="--continue")e.continueSession=!0;else if(s==="--no-session")e.noSession=!0;else if(s==="--sandbox")e.sandbox=!0;else if(s==="--update")e.update=!0;else if(s==="--check-update")e.checkUpdate=!0;else if(s==="-r"||s==="--resume")e.continueSession=!0;else if(s==="--session"||s.startsWith("--session="))e.sessionPath=_(d,p,"--session");else if(s==="-m"||s==="--model"||s.startsWith("--model="))e.model=_(d,p,"--model");else if(s==="--thinking"||s.startsWith("--thinking="))e.thinking=_(d,p,"--thinking");else if(s==="--approval"||s.startsWith("--approval="))e.approval=_(d,p,"--approval");else if(s==="--output-format"||s.startsWith("--output-format="))e.outputFormat=_(d,p,"--output-format");else if(s==="--max-budget-usd"||s.startsWith("--max-budget-usd="))e.maxBudgetUsd=ce(_(d,p,"--max-budget-usd"));else if(s==="--dangerously-skip-permissions")e.dangerouslySkipPermissions=!0;else{if(s.startsWith("-"))throw new Error(`unknown option ${s}`);l.push(s)}}if(e.thinking&&!F[e.thinking])throw new Error(`thinking must be one of: ${Object.keys(F).join(", ")}`);if(e.approval&&!I[e.approval])throw new Error(`approval must be one of: ${Object.keys(I).join(", ")}`);if(!R[e.outputFormat])throw new Error(`output-format must be one of: ${Object.keys(R).join(", ")}`);if(e.outputFormat!=="text"&&!e.print)throw new Error(`--output-format ${e.outputFormat} is a machine contract; it needs --print`);if(e.dangerouslySkipPermissions&&!e.print)throw new Error("--dangerously-skip-permissions is for unattended runs; it needs --print. interactively, pick an approval mode instead (/approval, or --approval)");if(e.prompt=l.join(" ").trim(),e.update&&e.checkUpdate)throw new Error("--update installs; --check-update only looks. pick one");if((e.update||e.checkUpdate)&&(e.print||e.continueSession||e.sessionPath||e.prompt))throw new Error("--update and --check-update act on the installation, not a session; they take no prompt");if(e.continueSession&&e.noSession)throw new Error("--continue and --no-session cannot be combined");if(e.sessionPath&&e.noSession)throw new Error("--session and --no-session cannot be combined");if(e.sessionPath&&e.continueSession)throw new Error("--session and --continue cannot be combined");if(e.print&&(e.continueSession||e.sessionPath))throw new Error("--print runs one prompt in a throwaway session; it cannot be combined with --continue or --session");if(e.sessionPath&&!e.sessionPath.endsWith(".jsonl"))throw new Error(`--session expects a session file, got '${e.sessionPath}'`);return e}function $(){return`${i} ${x}
3
3
  coding agent. layout is a workbench, not a chat log.
4
4
 
5
5
  usage:
@@ -85,11 +85,11 @@ token; /login takes another provider's key.
85
85
  `}function pe(t,e=!1){let{message:l}=M(t);if(!e)return l;let d=t instanceof Error?t.stack:void 0;return d&&d.includes(`
86
86
  `)?`${l}
87
87
  ${d}`:l}function L(t,e){let l=e?.debug??process.env.HOWTOFIX_DEBUG==="1",d=e?.exit??(s=>process.exit(s)),p=s=>{console.error(`${t}: ${pe(s,l)}`),d(1)};process.on("uncaughtException",p),process.on("unhandledRejection",p)}function le(t){return t.type==="message_update"}function ue(t){if(t.type==="toolcall_start"){let d=t.contentIndex,s=d===void 0?void 0:t.partial?.content[d];if(s?.type!=="toolCall")return;let{partial:y,...v}=t;return{...v,id:s.id,toolName:s.name}}if(!("partial"in t))return t;let{partial:e,...l}=t;return l}function me(t){if(!le(t))return t;if(t.message.role!=="assistant")return;let e=ue(t.assistantMessageEvent);if(e!==void 0)return{type:"message_update",usage:t.message.usage,assistantMessageEvent:e}}function B(t){let e=me(t);if(e!==void 0)return`${JSON.stringify(e)}
88
- `}function fe(){try{return{cwd:process.cwd()}}catch{return{error:"the current directory no longer exists (it was deleted while the shell stayed in it). cd to a directory that exists, or pass one on the command line."}}}function he(){process.stdout.on("error",t=>{throw t.code==="EPIPE"&&process.exit(0),t})}async function ge(){he(),T();let t=performance.now(),e=fe();if("error"in e){console.error(`${i}: ${e.error}`),process.exitCode=1;return}let l=e.cwd,d=process.env.HXF_FAKE_NODE??process.versions.node,[p,s]=d.split(".").map(n=>Number.parseInt(n,10));if(!Number.isFinite(p)||p<22||p===22&&Number.isFinite(s)&&s<19){console.error(`${i}: Node ${d} is too old. Node 22.19 or newer is required (run "node --version" to check yours), because undici needs zstd, which Node added in 22.19. Upgrade Node and run this again.`),process.exitCode=1;let n=process.argv.slice(2);if(n.some(c=>c==="-h"||c==="--help")){console.log($());return}if(n.some(c=>c==="-v"||c==="--version")){console.log(`${i} ${x}`);return}return}let y=process.argv.slice(2);if(y[0]==="doctor"||y[0]==="models"||y[0]==="sessions"){let n=y[0];try{let c=await import("./chunk-PIEAJJRE.js");n==="doctor"?process.exitCode=await c.runDoctor():n==="models"?process.exitCode=c.runModels():process.exitCode=c.runSessions(y.slice(1))}catch(c){P(i,n,c),process.exitCode=1}return}let v;try{v=W(process.argv.slice(2))}catch(n){let c=n instanceof Error?n.message:String(n);console.error(`${i}: ${c}
89
- ${$()}`),process.exitCode=2;return}if(v.print&&!v.prompt){console.error(`${i}: --print needs a prompt`),process.exitCode=2;return}let{repairGatewayModels:D,ensureGatewaySettings:J,repairModelFacts:G,syncGatewayModelsOnStart:H,checkAccount:X}=await import("./chunk-CGHISVXB.js"),{readCliCredential:q,renewCliCredentialIfNeeded:K}=await import("./chunk-TEW62VDF.js"),{AGENT_DIR:h}=await import("./chunk-GXB7RZHH.js"),C=D(h);C>0&&console.error(`${i}: repaired ${C} howtofix model(s) that the gateway would have rejected`);let S=await G(h);S.changed>0?console.error(`${i}: filled in the context window and reasoning flag for ${S.changed} model(s) from the model catalogue`):S.message&&console.error(`${i}: model catalogue unavailable (${S.message}); context windows stay at their conservative defaults`),J(h)&&console.error(`${i}: set httpIdleTimeoutMs in settings.json so a stalled provider recovers instead of hanging`);try{let n=q(h);if(n){let c=await K(h,n),w=await X(c.credential.accessToken);if(w.ok){let m=await H(h,w.models);m.added>0&&console.error(`${i}: added ${m.added} model(s) this account can now reach`)}}}catch{}let o=v;if(o.help){console.log($());return}if(o.version){console.log(`${i} ${x}`);let{cliSigningKeyMatchesPanel:n,cliSigningKeyFingerprint:c}=await import("./chunk-2YYQ3OBQ.js");n()||(console.error(`${i}: this build's CLI signing key (${c()}) does not match the key the panel verifies against, so sign-in will be refused.`),process.exitCode=1);return}if(o.sandbox&&!process.env.HOWTOFIX_SANDBOXED){let{detectSandbox:n,enterSandbox:c,describeSandbox:w}=await import("./chunk-N345KWWK.js"),m=n();if(!m){console.error(`${i}: --sandbox needs a working bubblewrap (Linux) or sandbox-exec (macOS). Neither could be used here \u2014 on Linux this usually means unprivileged user namespaces are disabled.`),process.exitCode=1;return}console.error(w(m)),process.exitCode=c(m,{cwd:l,agentDir:A,argv:[process.execPath,...process.argv.slice(1)]});return}let{installProxy:V}=await import("./chunk-WKUJ7CFO.js");if(V(A),o.update||o.checkUpdate){let{PACKAGE_NAME:n,checkForUpdate:c,installUpdate:w,isInstalledCopy:m}=await import("./chunk-7CHDNTH6.js"),k=await c(x);if(!k.latest){console.error(`${i}: ${k.message}`),process.exitCode=o.update?1:0;return}if(console.log(k.message),o.checkUpdate||!k.available)return;if(!m()){console.error(`${i}: this copy was not installed by npm, so npm cannot replace it. install it with: npm install -g ${n}`),process.exitCode=1;return}let b=await w({version:k.latest});console.log(b.message),b.ok||(process.exitCode=1);return}let O=process.argv.slice(2);if(O[0]==="preset"){let{runPresetCommand:n}=await import("./chunk-FPXVDP32.js");process.exitCode=n(O.slice(1));return}let{expandFileReferences:Y}=await import("./chunk-TSEKPGK4.js"),{isApprovalMode:z,setApprovalMode:Q,setDangerousBypass:Z,isDangerousBypass:ee}=await import("./chunk-56SEAGAQ.js"),{openSession:se}=await import("./chunk-3KT55SQP.js");Q(o.approval&&z(o.approval)?o.approval:"full-auto");let{readWorkbenchSettings:te}=await import("./chunk-V3R4FYTJ.js");(o.dangerouslySkipPermissions||te(h).skipPermissions)&&Z(!0),ee()&&console.error(`${i}: permission checks are OFF \u2014 critical commands (filesystem wipes, fork bombs, host shutdown) and the repeated-call guard are NOT enforced for this run. Turn it off with /settings, or by removing skipPermissions from settings.json.`);let j=n=>se({cwd:l,model:o.model,thinking:o.thinking,continueSession:n.continueSession??!1,noSession:n.noSession??!1,sessionPath:n.sessionPath,interactive:!o.print}),r=await j({continueSession:o.continueSession,sessionPath:o.sessionPath,noSession:o.noSession||o.print});if(o.print&&r.note&&console.error(r.note),o.maxBudgetUsd!==void 0&&!r.priced){console.error(`${i}: ${U(r.modelLabel,h)}`),await r.dispose(),process.exitCode=2;return}if(o.print){let n=o.prompt.trimStart();if(n.startsWith("/")){let u=n.slice(1).split(/\s+/)[0]??"",{skillInvocation:f}=await import("./chunk-ILDDDLRC.js"),a=r.session.resourceLoader.getSkills().skills.map(E=>E.name);if(!(f(n,a)!==void 0)){let{slashCommands:E}=await import("./chunk-RDRF7DIS.js");if(E(r.session).some(de=>de.name===u)){console.error(`${i}: /${u} runs in the TUI only \u2014 --print sends prompts straight to the model. Run \`howtofix\` without --print for interactive commands.`),await r.dispose(),process.exitCode=2;return}}}let c=o.outputFormat==="stream-json",w=o.outputFormat==="json",m=c||w;if(c){let u={type:"system",subtype:"init",cwd:l,session_id:r.session.sessionId,model:r.modelLabel,output_format:o.outputFormat,max_budget_usd:o.maxBudgetUsd??null,dangerously_skip_permissions:o.dangerouslySkipPermissions,cli_version:x};process.stdout.write(`${JSON.stringify(u)}
88
+ `}function fe(){try{return{cwd:process.cwd()}}catch{return{error:"the current directory no longer exists (it was deleted while the shell stayed in it). cd to a directory that exists, or pass one on the command line."}}}function he(){process.stdout.on("error",t=>{throw t.code==="EPIPE"&&process.exit(0),t})}async function ge(){he(),T();let t=performance.now(),e=fe();if("error"in e){console.error(`${i}: ${e.error}`),process.exitCode=1;return}let l=e.cwd,d=process.env.HXF_FAKE_NODE??process.versions.node,[p,s]=d.split(".").map(n=>Number.parseInt(n,10));if(!Number.isFinite(p)||p<22||p===22&&Number.isFinite(s)&&s<19){console.error(`${i}: Node ${d} is too old. Node 22.19 or newer is required (run "node --version" to check yours), because undici needs zstd, which Node added in 22.19. Upgrade Node and run this again.`),process.exitCode=1;let n=process.argv.slice(2);if(n.some(c=>c==="-h"||c==="--help")){console.log($());return}if(n.some(c=>c==="-v"||c==="--version")){console.log(`${i} ${x}`);return}return}let y=process.argv.slice(2);if(y[0]==="doctor"||y[0]==="models"||y[0]==="sessions"){let n=y[0];try{let c=await import("./chunk-CMRKXR6X.js");n==="doctor"?process.exitCode=await c.runDoctor():n==="models"?process.exitCode=c.runModels():process.exitCode=c.runSessions(y.slice(1))}catch(c){P(i,n,c),process.exitCode=1}return}let v;try{v=W(process.argv.slice(2))}catch(n){let c=n instanceof Error?n.message:String(n);console.error(`${i}: ${c}
89
+ ${$()}`),process.exitCode=2;return}if(v.print&&!v.prompt){console.error(`${i}: --print needs a prompt`),process.exitCode=2;return}let{repairGatewayModels:D,ensureGatewaySettings:J,repairModelFacts:G,syncGatewayModelsOnStart:H,checkAccount:X}=await import("./chunk-EHLH4G5R.js"),{readCliCredential:q,renewCliCredentialIfNeeded:K}=await import("./chunk-QERX2QO6.js"),{AGENT_DIR:h}=await import("./chunk-GXB7RZHH.js"),C=D(h);C>0&&console.error(`${i}: repaired ${C} howtofix model(s) that the gateway would have rejected`);let S=await G(h);S.changed>0?console.error(`${i}: filled in the context window and reasoning flag for ${S.changed} model(s) from the model catalogue`):S.message&&console.error(`${i}: model catalogue unavailable (${S.message}); context windows stay at their conservative defaults`),J(h)&&console.error(`${i}: set httpIdleTimeoutMs in settings.json so a stalled provider recovers instead of hanging`);try{let n=q(h);if(n){let c=await K(h,n),w=await X(c.credential.accessToken);if(w.ok){let m=await H(h,w.models);m.added>0&&console.error(`${i}: added ${m.added} model(s) this account can now reach`)}}}catch{}let o=v;if(o.help){console.log($());return}if(o.version){console.log(`${i} ${x}`);let{cliSigningKeyMatchesPanel:n,cliSigningKeyFingerprint:c}=await import("./chunk-WXPWYEZK.js");n()||(console.error(`${i}: this build's CLI signing key (${c()}) does not match the key the panel verifies against, so sign-in will be refused.`),process.exitCode=1);return}if(o.sandbox&&!process.env.HOWTOFIX_SANDBOXED){let{detectSandbox:n,enterSandbox:c,describeSandbox:w}=await import("./chunk-N345KWWK.js"),m=n();if(!m){console.error(`${i}: --sandbox needs a working bubblewrap (Linux) or sandbox-exec (macOS). Neither could be used here \u2014 on Linux this usually means unprivileged user namespaces are disabled.`),process.exitCode=1;return}console.error(w(m)),process.exitCode=c(m,{cwd:l,agentDir:A,argv:[process.execPath,...process.argv.slice(1)]});return}let{installProxy:V}=await import("./chunk-WKUJ7CFO.js");if(V(A),o.update||o.checkUpdate){let{PACKAGE_NAME:n,checkForUpdate:c,installUpdate:w,isInstalledCopy:m}=await import("./chunk-7CHDNTH6.js"),k=await c(x);if(!k.latest){console.error(`${i}: ${k.message}`),process.exitCode=o.update?1:0;return}if(console.log(k.message),o.checkUpdate||!k.available)return;if(!m()){console.error(`${i}: this copy was not installed by npm, so npm cannot replace it. install it with: npm install -g ${n}`),process.exitCode=1;return}let b=await w({version:k.latest});console.log(b.message),b.ok||(process.exitCode=1);return}let O=process.argv.slice(2);if(O[0]==="preset"){let{runPresetCommand:n}=await import("./chunk-FPXVDP32.js");process.exitCode=n(O.slice(1));return}let{expandFileReferences:Y}=await import("./chunk-TSEKPGK4.js"),{isApprovalMode:z,setApprovalMode:Q,setDangerousBypass:Z,isDangerousBypass:ee}=await import("./chunk-56SEAGAQ.js"),{openSession:se}=await import("./chunk-K6ZKVFKO.js");Q(o.approval&&z(o.approval)?o.approval:"full-auto");let{readWorkbenchSettings:te}=await import("./chunk-V3R4FYTJ.js");(o.dangerouslySkipPermissions||te(h).skipPermissions)&&Z(!0),ee()&&console.error(`${i}: permission checks are OFF \u2014 critical commands (filesystem wipes, fork bombs, host shutdown) and the repeated-call guard are NOT enforced for this run. Turn it off with /settings, or by removing skipPermissions from settings.json.`);let j=n=>se({cwd:l,model:o.model,thinking:o.thinking,continueSession:n.continueSession??!1,noSession:n.noSession??!1,sessionPath:n.sessionPath,interactive:!o.print}),r=await j({continueSession:o.continueSession,sessionPath:o.sessionPath,noSession:o.noSession||o.print});if(o.print&&r.note&&console.error(r.note),o.maxBudgetUsd!==void 0&&!r.priced){console.error(`${i}: ${U(r.modelLabel,h)}`),await r.dispose(),process.exitCode=2;return}if(o.print){let n=o.prompt.trimStart();if(n.startsWith("/")){let u=n.slice(1).split(/\s+/)[0]??"",{skillInvocation:f}=await import("./chunk-ILDDDLRC.js"),a=r.session.resourceLoader.getSkills().skills.map(E=>E.name);if(!(f(n,a)!==void 0)){let{slashCommands:E}=await import("./chunk-S4TNEP7G.js");if(E(r.session).some(de=>de.name===u)){console.error(`${i}: /${u} runs in the TUI only \u2014 --print sends prompts straight to the model. Run \`howtofix\` without --print for interactive commands.`),await r.dispose(),process.exitCode=2;return}}}let c=o.outputFormat==="stream-json",w=o.outputFormat==="json",m=c||w;if(c){let u={type:"system",subtype:"init",cwd:l,session_id:r.session.sessionId,model:r.modelLabel,output_format:o.outputFormat,max_budget_usd:o.maxBudgetUsd??null,dangerously_skip_permissions:o.dangerouslySkipPermissions,cli_version:x};process.stdout.write(`${JSON.stringify(u)}
90
90
  `)}let k,b,ae=()=>{if(o.maxBudgetUsd===void 0||b!==void 0)return;let u=r.session.getSessionStats().cost;u>o.maxBudgetUsd&&(b={spent:u},r.session.abort())};try{k=r.session.subscribe(a=>{if(c){let g=B(a);g!==void 0&&process.stdout.write(g)}ae()}),await r.session.prompt(Y(o.prompt,l));let u=r.session.getLastAssistantText()??"";if(b){if(console.error(`${i}: ${N(b.spent,o.maxBudgetUsd)}`),m){let a=r.session.getSessionStats();process.stdout.write(`${JSON.stringify({type:"result",subtype:"error_max_budget_usd",is_error:!0,result:u,session_id:r.session.sessionId,duration_ms:Math.round(performance.now()-t),num_turns:a.assistantMessages,total_cost_usd:a.cost,usage:{input_tokens:a.tokens.input,output_tokens:a.tokens.output,cache_read_input_tokens:a.tokens.cacheRead,cache_creation_input_tokens:a.tokens.cacheWrite}})}
91
91
  `)}process.exitCode=1;return}if(m){let a=r.session.getSessionStats(),g=r.session.state.messages.at(-1);process.stdout.write(`${JSON.stringify({type:"result",subtype:"success",is_error:!1,result:u,session_id:r.session.sessionId,duration_ms:Math.round(performance.now()-t),num_turns:a.assistantMessages,total_cost_usd:a.cost,usage:{input_tokens:a.tokens.input,output_tokens:a.tokens.output,cache_read_input_tokens:a.tokens.cacheRead,cache_creation_input_tokens:a.tokens.cacheWrite},stop_reason:g?.role==="assistant"?g.stopReason:void 0})}
92
92
  `)}else process.stdout.write(u.endsWith(`
93
93
  `)?u:`${u}
94
94
  `);let f=r.session.state.messages.at(-1);if(f?.role==="assistant"){if((f.stopReason==="error"||f.stopReason==="aborted"||f.errorMessage)&&(process.exitCode=1),process.exitCode===1&&f.errorMessage){console.error(`${i}: ${f.errorMessage}`);let{diagnoseGatewayFailure:a}=await import("./chunk-MVLCGU3G.js"),g=a(f.errorMessage);g!==void 0&&console.error(`${i}: ${g}`)}if(m&&process.exitCode===1){let a=r.session.getSessionStats();process.stdout.write(`${JSON.stringify({type:"result",subtype:f.stopReason==="aborted"?"error_aborted":"error_during_execution",is_error:!0,result:u,session_id:r.session.sessionId,duration_ms:Math.round(performance.now()-t),num_turns:a.assistantMessages,total_cost_usd:a.cost,usage:{input_tokens:a.tokens.input,output_tokens:a.tokens.output,cache_read_input_tokens:a.tokens.cacheRead,cache_creation_input_tokens:a.tokens.cacheWrite},stop_reason:f.stopReason})}
95
- `)}}}finally{k?.(),await r.dispose()}return}if(!process.stdin.isTTY||!process.stdout.isTTY){console.error(`${i}: interactive mode needs a terminal. use --print for pipes.`),await r.dispose(),process.exitCode=2;return}let{runWorkbench:oe}=await import("./chunk-RDRF7DIS.js"),{autoUpdateEnabled:ne,isInstalledCopy:re}=await import("./chunk-7CHDNTH6.js"),ie=re()&&ne(`${h}/settings.json`);await oe({cwd:l,modelLabel:r.modelLabel,session:r.session,setCompressToolOutput:r.setCompressToolOutput,initialPrompt:o.prompt||void 0,note:r.note,maxBudgetUsd:o.maxBudgetUsd,update:ie?{current:x,install:!0}:void 0,reopen:j})}L(i);ge().catch(t=>{P(i,void 0,t),process.exitCode=1});
95
+ `)}}}finally{k?.(),await r.dispose()}return}if(!process.stdin.isTTY||!process.stdout.isTTY){console.error(`${i}: interactive mode needs a terminal. use --print for pipes.`),await r.dispose(),process.exitCode=2;return}let{runWorkbench:oe}=await import("./chunk-S4TNEP7G.js"),{autoUpdateEnabled:ne,isInstalledCopy:re}=await import("./chunk-7CHDNTH6.js"),ie=re()&&ne(`${h}/settings.json`);await oe({cwd:l,modelLabel:r.modelLabel,session:r.session,setCompressToolOutput:r.setCompressToolOutput,initialPrompt:o.prompt||void 0,note:r.note,maxBudgetUsd:o.maxBudgetUsd,update:ie?{current:x,install:!0}:void 0,reopen:j})}L(i);ge().catch(t=>{P(i,void 0,t),process.exitCode=1});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "howtofixcli",
3
- "version": "0.7.10",
3
+ "version": "0.7.11",
4
4
  "type": "module",
5
5
  "description": "HowToFix coding agent. Workbench TUI, sessions, background agents.",
6
6
  "license": "UNLICENSED",
@@ -1 +0,0 @@
1
- import{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z}from"./chunk-MTNY7MFG.js";import"./chunk-UTYFLLSM.js";import"./chunk-WZKWT757.js";import"./chunk-4BWDGEXH.js";import"./chunk-WOT6VMZA.js";export{f as CATALOG_CACHE_TTL_MS,l as DEFAULT_CONTEXT_WINDOW,a as HOWTOFIX_BASE_URL,b as HOWTOFIX_CONSOLE_URL,k as HOWTOFIX_MODEL_COMPAT,c as HOWTOFIX_PROVIDERS,i as HTTP_IDLE_TIMEOUT_MS,q as UNLIMITED_SENTINEL,u as applyCatalog,v as applyCompat,z as checkAccount,r as checkUsage,w as countNewModels,j as ensureGatewaySettings,y as findLiveModels,p as isHowtofixProvider,g as loadCatalog,n as looksLikeToken,m as maskToken,t as mergeModels,d as newProviderEntry,o as parseModelIds,x as probeModel,e as repairGatewayModels,h as repairModelFacts,s as syncGatewayModelsOnStart};
@@ -1,6 +0,0 @@
1
- import{a as g}from"./chunk-UTYFLLSM.js";import{h as p,i as E}from"./chunk-WZKWT757.js";import{existsSync as L,mkdirSync as R,readFileSync as y}from"node:fs";import{join as w}from"node:path";var P="https://models.dev/api.json";var _=["anthropic","openai","google","deepseek","zai","xai","moonshotai","minimax","alibaba","xiaomi","meta","tencent","nvidia","venice","openrouter"];function h(n){return n.toLowerCase().replace(/[^a-z0-9]+/g,"")}function A(n){let s=n.split("/");return h(s[s.length-1]??n)}function F(n){let s=new Map,o=new Map;if(!n||typeof n!="object")return s;let t=n,e=a=>{let r=_.indexOf(a);return r===-1?_.length:r};for(let a of Object.keys(t).sort()){let r=t[a]?.models;if(!(!r||typeof r!="object"))for(let i of Object.keys(r)){let c=r[i],l=Number(c?.limit?.context);if(!Number.isFinite(l)||l<=0)continue;let u=h(i),d=e(a),f=o.get(u);if(f!==void 0&&f<=d)continue;let m=Number(c?.limit?.output);s.set(u,{contextWindow:Math.floor(l),maxTokens:Number.isFinite(m)&&m>0?Math.floor(m):void 0,reasoning:c?.reasoning===!0,vision:Array.isArray(c?.modalities?.input)&&c.modalities.input.includes("image")}),o.set(u,d)}}return s}function T(n,s){let o=h(s);if(!o)return;let t=n.get(o);if(t)return t;let e=A(s);for(let[a,r]of n)if(A(a)===e)return r;for(let[a,r]of n)if(a.endsWith(o)||o.endsWith(a))return r}function O(n){return`${n}/models-dev-cache.json`}function S(n){let s={};for(let[o,t]of n)s[o]=[t.contextWindow,t.maxTokens??0,t.reasoning?1:0,t.vision?1:0];return JSON.stringify(s)}function v(n){let s=new Map,o;try{o=JSON.parse(n)}catch{return s}if(!o||typeof o!="object")return s;for(let[t,e]of Object.entries(o)){if(!Array.isArray(e)||e.length<3)continue;let a=Number(e[0]),r=Number(e[1]);!Number.isFinite(a)||a<=0||s.set(t,{contextWindow:Math.floor(a),maxTokens:Number.isFinite(r)&&r>0?Math.floor(r):void 0,reasoning:e[2]===1||e[2]===!0,vision:e[3]===1||e[3]===!0})}return s}async function I(n){let s=n?.url??P,o=n?.fetchImpl??fetch,t=n?.timeoutMs??2e4,e=new AbortController,a=setTimeout(()=>e.abort(),t);try{let r=await o(s,{signal:e.signal,headers:{Accept:"application/json"}});if(!r.ok)return{ok:!1,message:`the model catalogue answered ${r.status}`};let i=F(await r.json());return i.size===0?{ok:!1,message:"the model catalogue was empty or in an unexpected shape"}:{ok:!0,index:i}}catch(r){return{ok:!1,message:r instanceof Error&&r.name==="AbortError"?`the model catalogue did not answer within ${Math.round(t/1e3)}s`:"could not reach the model catalogue"}}finally{clearTimeout(a)}}var x="https://api.howtofix.id/v1",te="https://howtofix.id/keys",M=["howtofix","howtofix-free"];function ne(){return{baseUrl:x,api:"openai-completions",headers:{[p]:E()}}}function oe(n){let s=w(n,"models.json"),o;try{o=JSON.parse(y(s,"utf8"))}catch{return 0}let t=o.providers;if(!t||typeof t!="object")return 0;let e=0;for(let a of M){let r=t[a];if(!r||!Array.isArray(r.models))continue;let i=B(r.models),c={...r.headers??{},[p]:E()},l=r.headers?.[p]!==c[p];i.changed===0&&!l||(r.models=i.models,r.headers=c,e+=i.changed===0?1:i.changed)}if(e===0)return 0;try{g(s,`${JSON.stringify(o,null,2)}
2
- `)}catch{return 0}return e}var W=10080*60*1e3;async function $(n,s){let o=O(n),t=s?.now??Date.now(),e,a=0;try{let c=JSON.parse(y(o,"utf8"));typeof c?.entries=="string"&&(e=v(c.entries),a=Number(c.at)||0)}catch{e=void 0}if(e&&e.size>0&&t-a<W&&!s?.force)return{index:e};let i=await I({fetchImpl:s?.fetchImpl});if(!i.ok)return e&&e.size>0?{index:e,message:i.message}:{index:new Map,message:i.message};try{R(n,{recursive:!0}),g(o,`${JSON.stringify({at:t,entries:S(i.index)})}
3
- `)}catch{}return{index:i.index}}async function re(n,s){let o=w(n,"models.json"),t;try{t=JSON.parse(y(o,"utf8"))}catch{return{changed:0}}let e=t.providers;if(!e||typeof e!="object")return{changed:0};let{index:a,message:r}=await $(n,s);if(a.size===0)return{changed:0,message:r};let i=0;for(let c of M){let l=e[c];if(!l||!Array.isArray(l.models))continue;let u=X(l.models,a);u.changed!==0&&(l.models=u.models,i+=u.changed)}if(i>0)try{g(o,`${JSON.stringify(t,null,2)}
4
- `)}catch{return{changed:0,message:"the models file could not be written"}}return{changed:i,message:r}}var D=3e5;function se(n){let s=w(n,"settings.json"),o={};try{let t=y(s,"utf8"),e=JSON.parse(t);e&&typeof e=="object"&&!Array.isArray(e)&&(o=e)}catch{if(L(s))return!1}if("httpIdleTimeoutMs"in o)return!1;o.httpIdleTimeoutMs=D;try{R(n,{recursive:!0}),g(s,`${JSON.stringify(o,null,2)}
5
- `)}catch{return!1}return!0}var N={supportsDeveloperRole:!1},j=128e3;function ae(n){let s=n.trim();return s.length<=10?"***":`${s.slice(0,6)}\u2026${s.slice(-4)}`}function ie(n){return/^sk-[A-Za-z0-9_-]{8,}$/.test(n.trim())}function z(n){let s=(()=>{if(Array.isArray(n))return n;if(n&&typeof n=="object"){let t=n;if(Array.isArray(t.data))return t.data;if(Array.isArray(t.models))return t.models}return[]})(),o=[];for(let t of s){let e=typeof t=="string"?t:t&&typeof t=="object"&&typeof t.id=="string"?t.id:void 0;e&&!o.includes(e)&&o.push(e)}return o}function ce(n){return M.includes(n)}var J=1e8;async function H(n,s){let o=await n(s,{headers:{Accept:"application/json"}});if(!o.ok)return"USD";let e=(await o.json())?.data?.quota_display_type;return typeof e=="string"&&e.trim()?e.trim().toUpperCase():"USD"}async function le(n,s){let o=(s?.baseUrl??x).replace(/\/+$/,""),t=s?.fetchImpl??fetch,e=s?.timeoutMs??15e3,a=n.trim();if(!a)return{ok:!1,unlimited:!1,unit:"USD",message:"no token given"};let r=`${o.replace(/\/v1$/,"")}/api/status`,i=await H(t,r).catch(()=>"USD"),c=new AbortController,l=setTimeout(()=>c.abort(),e),u={Authorization:`Bearer ${a}`};try{let[d,f]=await Promise.all([t(`${o}/dashboard/billing/subscription`,{headers:u,signal:c.signal}),t(`${o}/dashboard/billing/usage`,{headers:u,signal:c.signal})]);if(d.status===401||d.status===403)return{ok:!1,unlimited:!1,unit:i,message:"the gateway rejected that token when asking for the balance"};if(!d.ok)return{ok:!1,unlimited:!1,unit:i,message:`the balance endpoint answered ${d.status}`};let m=await d.json();if(m.error?.message)return{ok:!1,unlimited:!1,unit:i,message:m.error.message};let b=Number(m.hard_limit_usd??m.soft_limit_usd??0);if(b>=J)return{ok:!0,unlimited:!0,unit:i,message:"this token has no quota limit"};let k=0;if(f.ok){let U=await f.json();k=Number(U.total_usage??0)/100}let C=Math.max(0,b-k);return{ok:!0,unlimited:!1,limit:b,used:k,remaining:C,unit:i,message:`${C.toFixed(2)} ${i} left of ${b.toFixed(2)} (${k.toFixed(2)} used)`}}catch(d){let f=d instanceof Error&&d.name==="AbortError";return{ok:!1,unlimited:!1,unit:i,message:f?`the gateway did not answer within ${Math.round(e/1e3)}s`:"could not reach the gateway"}}finally{clearTimeout(l)}}async function ue(n,s){let o=w(n,"models.json"),t;try{t=JSON.parse(y(o,"utf8"))}catch{return{added:0,touched:0}}let e=t.providers;if(!e||typeof e!="object")return{added:0,touched:0};let{index:a}=await $(n).catch(()=>({index:new Map})),r=0,i=0;for(let c of M){let l=e[c];if(!l||!Array.isArray(l.models))continue;let u=l.models.length;l.models=G(l.models,s,a),r+=l.models.length-u,i++}if(r===0)return{added:0,touched:i};try{g(o,`${JSON.stringify(t,null,2)}
6
- `)}catch{return{added:0,touched:i}}return{added:r,touched:i}}function G(n,s,o){let t=new Set(n.map(a=>a.id)),e=[...n];for(let a of s){if(t.has(a))continue;t.add(a);let r=o?.get(h(a))??(o?T(o,a):void 0);e.push({id:a,contextWindow:r?.contextWindow??j,...r?.maxTokens?{maxTokens:r.maxTokens}:{},...r?{reasoning:r.reasoning}:{},...r?.vision?{input:["text","image"]}:{},compat:{...N}})}return e}function X(n,s){let o=0;return{models:n.map(e=>{let a=T(s,e.id);if(!a)return e;let r={...e},i=!1;return a.contextWindow&&e.contextWindow===j&&(r.contextWindow=a.contextWindow,i=!0),a.maxTokens&&!e.maxTokens&&(r.maxTokens=a.maxTokens,i=!0),e.reasoning===void 0&&(r.reasoning=a.reasoning,i=!0),a.vision&&!(e.input??[]).includes("image")&&(r.input=[...(e.input??["text"]).filter(c=>c!=="image"),"image"],i=!0),i?(o++,r):e}),changed:o}}function B(n){let s=0;return{models:n.map(t=>t.compat?.supportsDeveloperRole===!1?t:(s++,{...t,compat:{...t.compat,...N}})),changed:s}}function de(n,s){let o=new Set(n.map(t=>t.id));return s.filter(t=>!o.has(t)).length}async function V(n,s,o){let t=(o?.baseUrl??x).replace(/\/+$/,""),e=o?.fetchImpl??fetch,a=o?.timeoutMs??1e4,r=new AbortController,i=setTimeout(()=>r.abort(),a);try{let c=await e(`${t}/chat/completions`,{method:"POST",headers:{Authorization:`Bearer ${s}`,"Content-Type":"application/json"},body:JSON.stringify({model:n,messages:[{role:"user",content:"hi"}],max_tokens:1}),signal:r.signal});if(c.ok)return{ok:!0,detail:"ok"};let l=await c.text().catch(()=>"");return{ok:!1,detail:/"message"\s*:\s*"([^"]{0,80})/.exec(l)?.[1]??`HTTP ${c.status}`}}catch(c){return{ok:!1,detail:c instanceof Error&&c.name==="AbortError"?"timed out":"unreachable"}}finally{clearTimeout(i)}}async function me(n,s,o){let t=Math.max(0,o?.limit??4),e=[...new Set(n)].filter(r=>r!==o?.exclude).slice(0,t),a=await Promise.all(e.map(r=>V(r,s,o)));return{live:e.filter((r,i)=>a[i]?.ok),probed:e}}async function fe(n,s){let o=(s?.baseUrl??x).replace(/\/+$/,""),t=s?.fetchImpl??fetch,e=s?.timeoutMs??15e3,a=n.trim();if(!a)return{ok:!1,models:[],message:"no token given"};let r=new AbortController,i=setTimeout(()=>r.abort(),e);try{let c=await t(`${o}/models`,{headers:{Authorization:`Bearer ${a}`},signal:r.signal});if(c.status===401)return{ok:!1,models:[],message:"the gateway rejected that token (401). Check it in the Console, or make a new one."};if(c.status===403)return{ok:!1,models:[],message:"that token is not allowed to list models (403). The Console shows what a token may call."};if(!c.ok)return{ok:!1,models:[],message:`the gateway answered ${c.status}`};let l=z(await c.json());return l.length===0?{ok:!1,models:[],message:"the token works but the gateway listed no models"}:{ok:!0,models:l,message:`${l.length} models available to this token`}}catch(c){let l=c instanceof Error&&c.name==="AbortError";return{ok:!1,models:[],message:l?`the gateway did not answer within ${Math.round(e/1e3)}s`:"could not reach the gateway"}}finally{clearTimeout(i)}}export{x as a,te as b,M as c,ne as d,oe as e,W as f,$ as g,re as h,D as i,se as j,N as k,j as l,ae as m,ie as n,z as o,ce as p,J as q,le as r,ue as s,G as t,X as u,B as v,de as w,V as x,me as y,fe as z};