infernoflow 0.42.5 → 0.42.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# Changelog — infernoflow
|
|
2
2
|
|
|
3
|
+
## 0.42.7 — 2026-05-06
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
Same content as 0.42.6 — that version got registered on npm during a flaky publish attempt but the dist contents were stale. 0.42.7 is the actual usable build with these fixes:
|
|
7
|
+
|
|
8
|
+
## 0.42.6 — 2026-05-06
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- **`infernoflow contract graph` no longer crashes with cryptic "Cannot read properties of undefined (reading 'add')"**. Two issues addressed:
|
|
12
|
+
1. Friendly error when `inferno/scan.json` is missing — tells the user to run `infernoflow scan` first instead of crashing.
|
|
13
|
+
2. Defensive guard around the dependency-edge build — stale or duplicate scan entries can no longer trigger the undefined-Set crash.
|
|
14
|
+
- **MCP server: `infernoflow setup` no longer registers a phantom `infernoflow_suggest` tool**. The MCP_TOOLS pre-approval list in `lib/commands/setup.mjs` was out of sync with the actual MCP server (`templates/cursor/inferno-mcp-server.mjs`) — it included one tool that was never implemented and was missing several real ones. Now lists all 14 actual tools: 9 `infernoflow_*` (added `infernoflow_apply`) + 5 `amp_*` aliases (`amp_read`, `amp_write`, `amp_search`, `amp_handoff`, `amp_health`).
|
|
15
|
+
- **MCP server: CLI failures are surfaced as proper JSON-RPC errors**. Previously `runCmd()` swallowed all command failures and returned the raw error text as if it were successful output, so AI agents got garbled stderr mixed into their tool replies. `runCmd()` now returns a structured `{__error, message, stderr, stdout, status}` object on failure; a central check at the dispatcher converts these into `sendError()` calls. `amp_health` and `amp_handoff` defensively handle CLI failures instead of throwing on `.trim()`.
|
|
16
|
+
|
|
17
|
+
### Notes
|
|
18
|
+
- VS Code extension `infernoflow.infernoflow@0.7.2` shipped on the same day. To get the matching auto-capture popup, CodeLens, bulk-delete, and orphan-handling features, install the extension from the VS Code Marketplace.
|
|
19
|
+
- Existing users running `infernoflow setup` after upgrading to 0.42.6 will see all 14 MCP tools pre-approved correctly. Old `.claude/settings.json` files with the phantom `infernoflow_suggest` entry won't cause harm — that tool just isn't available — but re-running `setup` will clean it up.
|
|
20
|
+
|
|
3
21
|
## 0.42.5 — 2026-05-05
|
|
4
22
|
|
|
5
23
|
### Added
|
|
@@ -68,6 +86,15 @@
|
|
|
68
86
|
|
|
69
87
|
|
|
70
88
|
|
|
89
|
+
- VS Code Marketplace badge + extension install section
|
|
90
|
+
|
|
91
|
+
- extension v0.7.2 + CLI hotfixes: auto-capture, CodeLens, bulk + orphan delete, MCP setup tools fix, graph crash guard
|
|
92
|
+
- VS Code Marketplace badge + extension install section
|
|
93
|
+
|
|
94
|
+
- infernoflow CLI v0.42.6: graph crash fix + MCP setup/error-handling hotfixes
|
|
95
|
+
- extension v0.7.2 + CLI hotfixes: auto-capture, CodeLens, bulk + orphan delete, MCP setup tools fix, graph crash guard
|
|
96
|
+
- VS Code Marketplace badge + extension install section
|
|
97
|
+
|
|
71
98
|
## 0.42.1 — 2026-05-03
|
|
72
99
|
|
|
73
100
|
### Added
|
package/README.md
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
[](https://www.npmjs.com/package/infernoflow)
|
|
9
9
|
[](./package.json)
|
|
10
10
|
[](https://docs.npmjs.com/cli/v10/commands/npm-audit)
|
|
11
|
+
[](https://marketplace.visualstudio.com/items?itemName=infernoflow.infernoflow)
|
|
11
12
|
|
|
12
13
|
## The 60-second pitch
|
|
13
14
|
|
|
@@ -92,6 +93,27 @@ When you run `infernoflow log`, infernoflow silently keeps these files up to dat
|
|
|
92
93
|
|
|
93
94
|
You don't have to paste anything. Set up once, every future session is better.
|
|
94
95
|
|
|
96
|
+
## VS Code extension
|
|
97
|
+
|
|
98
|
+
The companion extension turns the CLI into a live visual surface inside VS Code. Install it from the Marketplace:
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
ext install infernoflow.infernoflow
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Or browse it [on the Marketplace](https://marketplace.visualstudio.com/items?itemName=infernoflow.infernoflow). Activates automatically on any project containing `.ai-memory/sessions.jsonl` or `inferno/`.
|
|
105
|
+
|
|
106
|
+
**What you get (v0.7.2):**
|
|
107
|
+
|
|
108
|
+
- **Auto-capture popup** — when you edit the same file 5+ times in 10 minutes, a popup asks "Stuck on something?" with [Log Gotcha] [Log Attempt] [Dismiss] buttons. Click once → entry is auto-written with timestamp, file:line, the enclosing function name, a 5-line code-context window, and any nearby TypeScript/ESLint diagnostics. Zero typing.
|
|
109
|
+
- **Sidebar memory panel** — Session Health (A–F grade), Gotchas, Decisions, Failed Attempts, Quick Actions, and a CLI Tools section with one-click access to 11 CLI commands (status, check, doctor, scan, init --adopt, setup, ai setup, install-cursor-hooks, watch, cloud status, show context).
|
|
110
|
+
- **Inline CodeLens** — `🔥 ⚠ 2 gotchas · 1 failed · 1 decision` above any file with logged entries. Per-line annotations at gotcha locations. Click for full entry detail.
|
|
111
|
+
- **Editor diagnostics** — gotchas as yellow Warnings, failed attempts as blue Information squiggles. Visible in the Problems panel and as inline squiggles. Copilot reads them too.
|
|
112
|
+
- **Status bar** — `🔥 B 65 · ⚠3 · ✓2 · ❌1 · 📋 Switch` with grade-based color coding. Click to open the panel; click "Switch" to copy a handoff.
|
|
113
|
+
- **Bulk delete + orphan cleanup** — "Manage entries…" picker grouped by date for cleaning up old entries. "Cleanup orphaned entries…" finds entries whose source files were deleted (e.g., after a refactor) and lets you bulk-remove them.
|
|
114
|
+
- **Help tooltips on everything** — hover any sidebar item or section header for a description of what it does, when to use it, and what happens when clicked.
|
|
115
|
+
- **Keyboard shortcuts** — `Ctrl+Alt+G/D/A/S/R` for log gotcha / log decision / ask memory / generate handoff / show recap.
|
|
116
|
+
|
|
95
117
|
## Cursor / VS Code MCP integration
|
|
96
118
|
|
|
97
119
|
```bash
|
|
@@ -1 +1,3 @@
|
|
|
1
|
-
import*as
|
|
1
|
+
import*as k from"node:fs";import*as m from"node:path";import{bold as h,cyan as L,gray as f,green as w,yellow as v,red as u}from"../ui/output.mjs";function x(t){try{return JSON.parse(k.readFileSync(t,"utf8"))}catch{return null}}function J(t){return t?.stability||"experimental"}const j={frozen:"\u{1F9CA}",stable:"\u3030\uFE0F ",experimental:"\u{1F30A}"},O={frozen:u,stable:v,experimental:w};function z(t,i){const c={},a={},g={},s={};for(const e of t){const l=i.find(n=>n.id===e.id)||{};c[e.id]={id:e.id,name:e.name||l.name||l.title||e.id,stability:l.stability||"experimental",functions:e.codeAnalysis?.functions||[],calls:e.codeAnalysis?.calls||[],services:e.codeAnalysis?.services||[],dbCalls:e.codeAnalysis?.dbCalls||[],httpCalls:e.codeAnalysis?.httpCalls||[]},a[e.id]=new Set,g[e.id]=new Set;for(const n of e.codeAnalysis?.functions||[]){const o=n.replace(/\(\)$/,"");s[o]=e.id,s[o.toLowerCase()]=e.id}}for(const[e,l]of Object.entries(c))for(const n of l.calls){const o=n.replace(/\(\)$/,""),d=s[o]||s[o.toLowerCase()];d&&d!==e&&a[e]&&g[d]&&(a[e].add(d),g[d].add(e))}const y={},r={};for(const e of Object.keys(c))y[e]=[...a[e]],r[e]=[...g[e]];return{nodes:c,edges:y,reverse:r}}function I(t){const{nodes:i,edges:c,reverse:a}=t,g=Object.keys(i).sort();console.log(),console.log(h(" Capability Dependency Graph")),console.log(f(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")),console.log();let s=!1;for(const r of g){const e=i[r],l=c[r]||[],n=a[r]||[],o=j[e.stability]||"\u{1F30A}",d=O[e.stability]||w;if(!(l.length===0&&n.length===0)){if(s=!0,console.log(` ${o} ${h(d(r))}`),l.length>0){console.log(f(" calls \u2192"));for(const p of l){const $=i[p],b=j[$?.stability]||"\u{1F30A}";console.log(f(` ${b} ${p}`))}}if(n.length>0){console.log(f(" called by \u2190"));for(const p of n){const $=j[i[p]?.stability]||"\u{1F30A}";console.log(f(` ${$} ${p}`))}}console.log()}}s||(console.log(f(" No inter-capability dependencies detected.")),console.log(f(" Run `infernoflow scan` first to populate call data.")),console.log());const y=Object.values(t.edges).reduce((r,e)=>r+e.length,0);console.log(f(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")),console.log(f(` ${g.length} capabilities \xB7 ${y} dependency edge(s)`)),console.log()}function E(t,i){const{nodes:c,edges:a,reverse:g}=i,s=c[t];s||(console.error(u(`\u2717 Capability "${t}" not found in graph.`)),process.exit(1));const y=j[s.stability]||"\u{1F30A}",r=O[s.stability]||w;console.log(),console.log(h(` ${y} ${r(t)}`)+f(` (${s.stability})`)),s.services?.length&&console.log(f(" external: ")+L(s.services.join(", "))),console.log();const e=a[t]||[],l=g[t]||[];if(e.length>0){console.log(h(" Calls (downstream dependencies):"));for(const n of e){const o=c[n],d=O[o?.stability]||w,p=j[o?.stability]||"\u{1F30A}";console.log(` ${p} ${d(n)}`+f(o?.services?.length?` [${o.services.join(", ")}]`:""))}console.log()}else console.log(f(" No downstream dependencies.")),console.log();if(l.length>0){console.log(h(" Called by (upstream dependents):"));for(const n of l){const o=c[n],d=O[o?.stability]||w,p=j[o?.stability]||"\u{1F30A}";console.log(` ${p} ${d(n)}`)}console.log()}else console.log(f(" No capabilities call this one.")),console.log();if((s.stability==="frozen"||s.stability==="stable")&&l.length>0){const n=s.stability==="frozen"?u:v;console.log(n(` \u26A0 This capability is ${s.stability}. Changing it may break:`));for(const o of l)console.log(n(` \u2022 ${o}`));console.log()}}function F(t,i){const c=[];if(!t||!i)return c;for(const[a,g]of Object.entries(i.nodes)){if(g.stability==="experimental")continue;const s=new Set(t.reverse?.[a]||[]),r=[...new Set(i.reverse[a]||[])].filter(e=>!s.has(e));if(r.length>0&&c.push({type:"new-dependents",capId:a,stability:g.stability,detail:`${r.join(", ")} now depend on this`}),g.stability==="frozen"){const e=new Set(t.edges?.[a]||[]),l=new Set(i.edges[a]||[]),n=[...l].filter(d=>!e.has(d)),o=[...e].filter(d=>!l.has(d));(n.length>0||o.length>0)&&c.push({type:"frozen-internals-changed",capId:a,stability:g.stability,detail:[n.length?`added calls: ${n.join(", ")}`:"",o.length?`removed calls: ${o.join(", ")}`:""].filter(Boolean).join("; ")})}}return c}async function P(t){const i=(t||[]).slice(1),c=i.includes("--json"),a=i.includes("--check"),g=i.indexOf("--cap"),s=g!==-1?i[g+1]:null,y=process.cwd(),r=m.join(y,"inferno"),e=m.join(r,"scan.json"),l=m.join(r,"graph.json"),n=m.join(r,"capabilities.json"),o=x(e);o||(console.error(u("\u2717 inferno/scan.json not found.")),console.error(f(" The graph is built from a deep AST scan of your codebase.")),console.error(f(" Run this first to generate it:")),console.error(L(`
|
|
2
|
+
infernoflow scan
|
|
3
|
+
`)),process.exit(1)),(!Array.isArray(o.capabilities)||o.capabilities.length===0)&&(console.error(u("\u2717 inferno/scan.json has no capabilities.")),console.error(f(" Re-run `infernoflow scan` to refresh the data.")),process.exit(1));let d=[];const p=x(n);p&&(d=Array.isArray(p)?p:p.capabilities||[]);const $=o.capabilities||[],b=z($,d),N=x(l),A=F(N,b),D={builtAt:new Date().toISOString(),capabilities:Object.keys(b.nodes).length,edges:Object.values(b.edges).reduce((C,S)=>C+S.length,0),nodes:b.nodes,deps:b.edges,dependents:b.reverse};if(c||k.writeFileSync(l,JSON.stringify(D,null,2)),c){console.log(JSON.stringify(D,null,2));return}if(s?E(s,b):I(b),A.length>0){console.log(v(" \u26A0 Dependency changes detected:"));for(const C of A){const S=C.stability==="frozen"?u("\u{1F9CA}"):v("\u3030\uFE0F ");console.log(` ${S} ${h(C.capId)} \u2014 ${C.detail}`)}console.log(),a&&process.exit(1)}c||console.log(f(" Graph saved \u2192 inferno/graph.json"))}function T(t){return x(m.join(t,"graph.json"))}export{P as graphCommand,T as loadGraph};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import*as t from"node:fs";import*as c from"node:path";import*as x from"node:os";import{fileURLToPath as $}from"node:url";import{execSync as k}from"node:child_process";import{detectIdeContext as P}from"../ai/ideDetection.mjs";import{header as O,ok as a,warn as d,info as j,done as J,cyan as _,yellow as F,bold as m,green as g}from"../ui/output.mjs";import{installCursorHooksArtifacts as M}from"../cursorHooksInstall.mjs";import{installVsCodeCopilotHooksArtifacts as N}from"../vsCodeCopilotHooksInstall.mjs";const b=c.dirname($(import.meta.url));function A(){return c.resolve(b,"../../templates")}function T(
|
|
1
|
+
import*as t from"node:fs";import*as c from"node:path";import*as x from"node:os";import{fileURLToPath as $}from"node:url";import{execSync as k}from"node:child_process";import{detectIdeContext as P}from"../ai/ideDetection.mjs";import{header as O,ok as a,warn as d,info as j,done as J,cyan as _,yellow as F,bold as m,green as g}from"../ui/output.mjs";import{installCursorHooksArtifacts as M}from"../cursorHooksInstall.mjs";import{installVsCodeCopilotHooksArtifacts as N}from"../vsCodeCopilotHooksInstall.mjs";const b=c.dirname($(import.meta.url));function A(){return c.resolve(b,"../../templates")}function T(r){try{return k(`npx infernoflow ${r}`,{encoding:"utf8",cwd:process.cwd(),timeout:6e4,stdio:["inherit","pipe","pipe"]})}catch(e){return e.stdout||e.stderr||e.message}}const D=["infernoflow_status","infernoflow_run","infernoflow_apply","infernoflow_check","infernoflow_context","infernoflow_implement","infernoflow_git_drift","infernoflow_scan_ui","infernoflow_review","amp_read","amp_write","amp_search","amp_handoff","amp_health"];function L(r){const e=c.join(x.homedir(),".claude.json");let o={};if(t.existsSync(e))try{o=JSON.parse(t.readFileSync(e,"utf8"))}catch{o={}}o.mcpServers||(o.mcpServers={});const s=o.mcpServers.infernoflow;if(s&&s.args&&s.args[0]===r)return{updated:!1};o.mcpServers.infernoflow={command:"node",args:[r]};const i=JSON.stringify(o,null,2).replace(/\u0000+/g,"");return t.writeFileSync(e,i,"utf8"),{updated:!0,path:e}}function R(r,e){const o=c.join(r,".claude"),s=c.join(o,"settings.json");let i={};if(t.existsSync(s))try{i=JSON.parse(t.readFileSync(s,"utf8"))}catch{i={}}const l=new Set(i.allowedTools||[]);for(const u of D)l.add(`mcp__infernoflow__${u}`);const w={...i,allowedTools:[...l]};return t.mkdirSync(o,{recursive:!0}),t.writeFileSync(s,JSON.stringify(w,null,2),"utf8"),s}async function E(r){const e=process.cwd(),o=r.includes("--force")||r.includes("-f"),s=r.includes("--yes")||r.includes("-y"),i=A();O("infernoflow setup");const{ideDetected:l}=P("auto");j(`IDE detected: ${m(l==="cursor"?"Cursor":l==="vscode"?"VS Code":l==="windsurf"?"Windsurf":"unknown")}`);const u=c.join(e,"inferno"),y=c.join(u,"contract.json");if(t.existsSync(y))a("inferno/contract.json already exists \u2014 skipping init");else{console.log(`
|
|
2
2
|
${F("inferno/")} not found \u2014 running init --adopt ...
|
|
3
|
-
`);const n=["--adopt",
|
|
3
|
+
`);const n=["--adopt",s?"--yes":""].filter(Boolean).join(" ");T(`init ${n}`)}const h=n=>a(n),S=n=>d(n);M({cwd:e,templatesRoot:i,force:o,silent:!1,logOk:h,logWarn:S});const v=c.join(i,"cursor","inferno-mcp-server.mjs"),f=c.join(e,".cursor","inferno-mcp-server.mjs");(!t.existsSync(f)||o)&&(t.mkdirSync(c.dirname(f),{recursive:!0}),t.copyFileSync(v,f),a("Copied MCP server \u2192 .cursor/inferno-mcp-server.mjs")),l==="vscode"&&N({cwd:e,templatesRoot:i,force:o,silent:!1,logOk:h,logWarn:S}),console.log(),j("Configuring Claude Code (VS Code extension)...");const C=f;try{L(C).updated?a("Updated ~/.claude.json \u2192 infernoflow MCP server registered"):a("~/.claude.json already has infernoflow \u2014 no changes needed")}catch(n){d(`Could not update ~/.claude.json: ${n.message}`),d(`Add manually: ${_('"mcpServers": { "infernoflow": { "command": "node", "args": ["'+C+'"] } }')}`)}try{const n=R(e,o);a("Written .claude/settings.json \u2014 infernoflow tools pre-approved (no more prompts)")}catch(n){d(`Could not write .claude/settings.json: ${n.message}`)}let p=0;try{p=(JSON.parse(t.readFileSync(y,"utf8")).capabilities||[]).length}catch{}console.log(),J(p>0?`infernoflow ready \u2014 ${p} capabilities tracked`:"infernoflow ready"),console.log(`
|
|
4
4
|
${m("What was set up:")}`),console.log(` ${g("\u2714")} MCP server installed \u2192 .cursor/inferno-mcp-server.mjs`),console.log(` ${g("\u2714")} ~/.claude.json updated \u2192 Claude Code will find infernoflow`),console.log(` ${g("\u2714")} .claude/settings.json \u2192 no permission prompts`),console.log(),console.log(` ${m("Next step:")} Restart VS Code, then ask Claude:`),console.log(` ${_('"show me the infernoflow status of this project"')}`),console.log()}export{E as setupCommand};
|
|
@@ -7,9 +7,33 @@ function send(obj) { process.stdout.write(JSON.stringify(obj) + "\n"); }
|
|
|
7
7
|
function sendResult(id, result) { send({ jsonrpc: "2.0", id, result }); }
|
|
8
8
|
function sendError(id, code, message) { send({ jsonrpc: "2.0", id, error: { code, message } }); }
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Run the infernoflow CLI. Returns either the stdout string OR a structured
|
|
12
|
+
* error object so call sites can decide whether to surface it via JSON-RPC
|
|
13
|
+
* sendError() instead of returning gibberish text to the agent.
|
|
14
|
+
*/
|
|
10
15
|
function runCmd(args, env = {}) {
|
|
11
|
-
try {
|
|
12
|
-
|
|
16
|
+
try {
|
|
17
|
+
return execSync(`npx infernoflow ${args}`, {
|
|
18
|
+
encoding: "utf8",
|
|
19
|
+
cwd: process.cwd(),
|
|
20
|
+
timeout: 30000,
|
|
21
|
+
env: { ...process.env, ...env },
|
|
22
|
+
});
|
|
23
|
+
} catch (err) {
|
|
24
|
+
return {
|
|
25
|
+
__error: true,
|
|
26
|
+
message: err.message || "command failed",
|
|
27
|
+
stderr: err.stderr || "",
|
|
28
|
+
stdout: err.stdout || "",
|
|
29
|
+
status: err.status ?? 1,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** True if a runCmd() result is actually a structured error. */
|
|
35
|
+
function isCmdError(result) {
|
|
36
|
+
return typeof result === "object" && result !== null && result.__error === true;
|
|
13
37
|
}
|
|
14
38
|
|
|
15
39
|
const TOOLS = [
|
|
@@ -480,7 +504,10 @@ function handleTool(id, name, input) {
|
|
|
480
504
|
text = runCmd(`log ${m} --type ${t} ${extras.join(" ")}`);
|
|
481
505
|
} else if (name === "amp_handoff") {
|
|
482
506
|
// switch writes a file; we read it back to return the content
|
|
483
|
-
runCmd("switch");
|
|
507
|
+
const switchResult = runCmd("switch");
|
|
508
|
+
if (isCmdError(switchResult)) {
|
|
509
|
+
return sendError(id, -32000, `infernoflow switch failed: ${switchResult.message}\n${switchResult.stderr || switchResult.stdout || ""}`.trim());
|
|
510
|
+
}
|
|
484
511
|
try {
|
|
485
512
|
const ampPath = path.join(process.cwd(), ".ai-memory", "handoff.md");
|
|
486
513
|
const legacyPath = path.join(process.cwd(), "inferno", "HANDOFF.md");
|
|
@@ -498,9 +525,25 @@ function handleTool(id, name, input) {
|
|
|
498
525
|
if (input.type) args.push("--type", input.type);
|
|
499
526
|
text = runCmd("ask " + args.join(" "));
|
|
500
527
|
} else if (name === "amp_health") {
|
|
501
|
-
|
|
528
|
+
const recap = runCmd("recap --json");
|
|
529
|
+
if (isCmdError(recap)) {
|
|
530
|
+
text = runCmd("status");
|
|
531
|
+
} else {
|
|
532
|
+
text = recap.trim() || runCmd("status");
|
|
533
|
+
}
|
|
502
534
|
|
|
503
535
|
} else { return sendError(id, -32601, `Unknown tool: ${name}`); }
|
|
536
|
+
|
|
537
|
+
// Central error check — if any runCmd() call produced a structured error,
|
|
538
|
+
// surface it as a real JSON-RPC error so the calling AI sees a proper
|
|
539
|
+
// failure instead of garbled stderr text mixed into a "successful" reply.
|
|
540
|
+
if (isCmdError(text)) {
|
|
541
|
+
const detail = (text.stderr || text.stdout || "").trim();
|
|
542
|
+
const fullMsg = detail
|
|
543
|
+
? `infernoflow CLI failed: ${text.message}\n${detail}`
|
|
544
|
+
: `infernoflow CLI failed: ${text.message}`;
|
|
545
|
+
return sendError(id, -32000, fullMsg);
|
|
546
|
+
}
|
|
504
547
|
sendResult(id, { content: [{ type: "text", text: text || "(no output)" }] });
|
|
505
548
|
} catch (err) { sendError(id, -32000, err.message); }
|
|
506
549
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "infernoflow",
|
|
3
|
-
"version": "0.42.
|
|
3
|
+
"version": "0.42.7",
|
|
4
4
|
"description": "Persistent memory for AI coding sessions \u2014 captures what agents can't infer from code alone. Works with Copilot, Cursor, Claude, and Windsurf.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|