infernoflow 0.43.11 → 0.43.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/commands/log.mjs +12 -12
- package/dist/lib/ruleFiles.mjs +8 -5
- package/dist/lib/upgradeCheck.mjs +1 -1
- package/package.json +1 -1
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import*as f from"node:fs";import*as m from"node:path";import"node:os";import{bold as j,cyan as
|
|
1
|
+
import*as f from"node:fs";import*as m from"node:path";import"node:os";import{bold as j,cyan as T,gray as n,green as F,red as b}from"../ui/output.mjs";import{ampPaths as A,appendEntry as k,readEntries as D,AMP_MARKERS as E}from"../amp/io.mjs";import{refreshRuleFilesFromMemory as _}from"../ruleFiles.mjs";function C(){return A(process.cwd())}function P(){try{const e=D(process.cwd()),l=e.filter(o=>o.type==="gotcha"),i=e.filter(o=>o.type==="decision"),t=e.filter(o=>o.type==="attempt"&&(o.result==="failed"||o.result==="partial")),s=["# Project Context (auto-generated by infernoflow)","",`> Last updated: ${new Date().toISOString()}`,""];if(l.length){s.push("## \u26A0\uFE0F Known Gotchas (Read These First)","");for(const o of l)s.push(`- ${o.summary}`);s.push("")}if(i.length){s.push("## \u2713 Decisions In Effect","");for(const o of i)s.push(`- ${o.summary}`);s.push("")}if(t.length){s.push("## \u274C Things That Don't Work (Don't Try These)","");for(const o of t)s.push(`- ${o.summary}`);s.push("")}const p=s.join(`
|
|
2
2
|
`),g=`${E.start}
|
|
3
3
|
${p}
|
|
4
4
|
${E.end}
|
|
5
|
-
`,a=process.cwd(),d=
|
|
5
|
+
`,a=process.cwd(),d=o=>{let c="";try{c=f.readFileSync(o,"utf8")}catch{}const w=c.indexOf(E.start),S=c.indexOf(E.end);let $;w!==-1&&S!==-1&&S>w?$=c.slice(0,w)+g+c.slice(S+E.end.length).replace(/^\n+/,""):c?$=c.replace(/\s+$/,"")+`
|
|
6
6
|
|
|
7
|
-
`+g:$=g,f.writeFileSync(
|
|
8
|
-
`)),process.exit(1)),k(
|
|
9
|
-
`+j("\u{1F525} infernoflow \u2014 session memory")),console.log(" "+"\u2500".repeat(50)),!x.length){console.log(
|
|
7
|
+
`+g:$=g,f.writeFileSync(o,$,"utf8")},O=m.join(a,"CLAUDE.md");f.existsSync(O)&&d(O);const I=m.join(a,".cursorrules");(f.existsSync(I)||f.existsSync(m.join(a,".cursor")))&&d(I);const y=m.join(a,".github","copilot-instructions.md");f.existsSync(m.join(a,".github"))&&d(y)}catch{}}const N=["note","attempt","decision","gotcha","preference","theme","handoff","error"],L=["worked","failed","partial","unknown"];function U(){return D(process.cwd())}function W(e,{auto:l=!1,quiet:i=!1}={}){const t=process.cwd(),s=m.join(t,".ai-memory"),p=m.join(t,"inferno");if(l&&!f.existsSync(s)&&!f.existsSync(p))return!1;!f.existsSync(s)&&!f.existsSync(p)&&(i||console.error(b(` \u2718 no .ai-memory/ or inferno/ \u2014 run: infernoflow init
|
|
8
|
+
`)),process.exit(1)),k(t,e);try{_(t)}catch{}return!0}function M(){return process.env.CURSOR_SESSION?"cursor":process.env.COPILOT_SESSION?"copilot":process.env.CLAUDE_CODE_SESSION?"claude":process.env.WINDSURF_SESSION?"windsurf":process.env.INFERNOFLOW_AGENT?process.env.INFERNOFLOW_AGENT:"human"}function V(e,l){const i=new Date(e.ts).toLocaleString("en-GB",{day:"2-digit",month:"short",hour:"2-digit",minute:"2-digit"}),t=e.type||"note",s=t==="gotcha"?"\x1B[33m":t==="decision"?"\x1B[36m":t==="theme"?"\x1B[35m":t==="preference"?"\x1B[34m":t==="attempt"?"\x1B[90m":t==="error"?"\x1B[31m":"\x1B[0m",p="\x1B[0m",g=e.result?` [${e.result}]`:"",a=e.agent&&e.agent!=="human"?n(` (${e.agent})`):"";return` ${n(String(l+1).padStart(3))} ${n(i)} ${s}${t}${p}${g} ${e.summary}${a}`}async function Y(e){const l=r=>e.includes(r),i=(r,u)=>{const h=e.indexOf(r);return h!==-1&&e[h+1]?e[h+1]:u},t=l("--show"),s=l("--clear"),p=l("--json"),g=l("--auto"),a=l("--quiet"),d=i("--source",null);if(t||p){const r=U(),u=e[e.indexOf("--show")+1],h=u&&/^\d+$/.test(u)?parseInt(u):20,x=r.slice(-h);if(p){console.log(JSON.stringify(x,null,2));return}if(console.log(`
|
|
9
|
+
`+j("\u{1F525} infernoflow \u2014 session memory")),console.log(" "+"\u2500".repeat(50)),!x.length){console.log(n(`
|
|
10
10
|
No entries yet. Start logging with: infernoflow log "<what happened>"
|
|
11
|
-
`));return}console.log(
|
|
12
|
-
`)),x.forEach((v,
|
|
13
|
-
`));return}const u=r.replace(".jsonl",`-archive-${Date.now()}.jsonl`);f.renameSync(r,u),console.log(
|
|
11
|
+
`));return}console.log(n(` Showing last ${x.length} of ${r.length} entries
|
|
12
|
+
`)),x.forEach((v,R)=>console.log(V(v,r.length-x.length+R))),console.log();return}if(s){const{sessions:r}=C();if(!f.existsSync(r)){console.log(n(` Nothing to clear.
|
|
13
|
+
`));return}const u=r.replace(".jsonl",`-archive-${Date.now()}.jsonl`);f.renameSync(r,u),console.log(F(` \u2714 Session log archived \u2192 ${m.basename(u)}
|
|
14
14
|
`));return}const O=new Set([i("--type",""),i("--result",""),i("--agent",""),i("--source","")].filter(Boolean)),y=e.slice(1).filter(r=>!r.startsWith("--")&&!O.has(r)).join(" ").trim();if(!y){console.log(`
|
|
15
15
|
`+j("\u{1F525} infernoflow log")+` \u2014 append to session memory
|
|
16
|
-
`),console.log(
|
|
17
|
-
`));return}const
|
|
16
|
+
`),console.log(n(" Usage:")),console.log(n(' infernoflow log "what happened"')),console.log(n(' infernoflow log "tried X, failed because Y" --type attempt --result failed')),console.log(n(' infernoflow log "always use multipart/form-data" --type gotcha')),console.log(n(' infernoflow log "switched to dark mode" --type theme')),console.log(n(" infernoflow log --show Print last 20 entries")),console.log(n(" infernoflow log --json Print as JSON")),console.log(),console.log(n(" Types: note \xB7 attempt \xB7 decision \xB7 gotcha \xB7 preference \xB7 theme \xB7 handoff \xB7 error")),console.log(n(" Results: worked \xB7 failed \xB7 partial \xB7 unknown")),console.log(n(` Auto-capture: --auto (silent skip if no inferno/) \xB7 --quiet \xB7 --source <name>
|
|
17
|
+
`));return}const o=i("--type","note"),c=i("--result",null),w=i("--agent",M());N.includes(o)||(a||console.error(b(` \u2718 Invalid type: ${o}. Valid: ${N.join(", ")}
|
|
18
18
|
`)),process.exit(1)),c&&!L.includes(c)&&(a||console.error(b(` \u2718 Invalid result: ${c}. Valid: ${L.join(", ")}
|
|
19
|
-
`)),process.exit(1));const S={ts:new Date().toISOString(),agent:w,type:
|
|
20
|
-
`)}}export{
|
|
19
|
+
`)),process.exit(1));const S={ts:new Date().toISOString(),agent:w,type:o,summary:y,...c?{result:c}:{},...d?{source:d}:{},...g?{auto:!0}:{}};if(W(S,{auto:g,quiet:a})&&(P(),!a)){const r=o!=="note"?T(` [${o}]`):"",u=c?n(` \u2192 ${c}`):"",h=d?n(` (via ${d})`):"";console.log(F(` \u2714 Logged${r}${u}${h}: `)+y+`
|
|
20
|
+
`)}}export{Y as logCommand};
|
package/dist/lib/ruleFiles.mjs
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import*as
|
|
2
|
-
`)}function
|
|
3
|
-
`)}function g(e,
|
|
4
|
-
`,"utf8"),{created:!0,updated:!1};const t=
|
|
1
|
+
import*as c from"node:fs";import*as l from"node:path";import{execSync as w}from"node:child_process";const m="<!-- infernoflow:start -->",h="<!-- infernoflow:end -->",d=[".cursorrules","CLAUDE.md",l.join(".github","copilot-instructions.md")];function y(){const e=[];return e.push("### Memory protocol \u2014 capture as you go"),e.push(""),e.push("You have the `amp_write` MCP tool. **Use it proactively** (without the user asking) whenever you detect any of these moments. Capture the lesson in one sentence so the next AI session inherits it."),e.push(""),e.push("| When you see\u2026 | Call `amp_write` with\u2026 |"),e.push("|---|---|"),e.push("| User types `!!!`, `not working`, `still broken`, `no change`, `same error`, repeated frustration | `{type: 'attempt', msg: '<one-line: what was tried and how it failed>', file: '<active file>'}` |"),e.push("| You generate a plan, numbered steps, or `Plan:` / `Approach:` block | `{type: 'note', msg: 'Plan: <one-line summary>', file: '<focus file>'}` |"),e.push("| User picks X over Y, decides an architectural approach, or you both agree on a direction | `{type: 'decision', msg: '<X> chosen over <Y> because <reason>', file: '<file>'}` |"),e.push("| Discovered non-obvious behavior, API quirk, or `aha \u2014 turns out\u2026` moment | `{type: 'gotcha', msg: '<one-line>', file: '<file>', line: <line if known>}` |"),e.push("| User says `switching` / `back to X`, or ~30 min passed without logging | `{type: 'note', msg: 'Session snapshot \u2014 worked on: <X>. Open threads: <Y>.'}` |"),e.push(""),e.push("**Do NOT log:** typos, syntax errors, obvious bugs visible in the code, anything the next AI can infer by re-reading the file."),e.push("**Do log:** anything that taught you something non-derivable from code."),e.push("**Be concise:** entries should be one sentence. Future-you will skim them."),e.join(`
|
|
2
|
+
`)}function b(){return[m,"<!-- Auto-managed by infernoflow. Don't edit between these markers. -->","## Project memory (infernoflow)","",y(),"",'_No entries yet. They\'ll appear here as you and your AI tools log them \u2014 run `infernoflow log "..."` or call `amp_write` from any MCP-aware AI._',h].join(`
|
|
3
|
+
`)}function g(e,u){const s=l.dirname(e);if(c.existsSync(s)||c.mkdirSync(s,{recursive:!0}),!c.existsSync(e))return c.writeFileSync(e,u+`
|
|
4
|
+
`,"utf8"),{created:!0,updated:!1};const t=c.readFileSync(e,"utf8"),i=t.indexOf(m),r=t.indexOf(h);if(i===-1||r===-1){const a=u+`
|
|
5
5
|
|
|
6
|
-
`+t;return
|
|
6
|
+
`+t;return c.writeFileSync(e,a,"utf8"),{created:!1,updated:!0}}const p=t.slice(0,i),o=t.slice(r+h.length),n=p+u+o;return n===t?{created:!1,updated:!1}:(c.writeFileSync(e,n,"utf8"),{created:!1,updated:!0})}function v(e){const u=b(),s=[];for(const t of d){const i=l.join(e,t);try{const r=g(i,u);s.push({rel:t,...r})}catch(r){s.push({rel:t,error:r.message})}}return s}function S(e){const u=[l.join(e,".ai-memory","sessions.jsonl"),l.join(e,"inferno","sessions.jsonl")];for(const s of u)if(c.existsSync(s))try{return c.readFileSync(s,"utf8").split(`
|
|
7
|
+
`).filter(Boolean).map(i=>{try{return JSON.parse(i)}catch{return null}}).filter(Boolean)}catch{}return[]}function x(e,u=10){try{return w(`git log --pretty=format:"%h%x09%ad%x09%s" --date=short -n ${u}`,{cwd:e,encoding:"utf8",stdio:["ignore","pipe","ignore"]}).split(`
|
|
8
|
+
`).filter(Boolean).map(t=>{const[i,r,p]=t.split(" ");return{hash:(i||"").slice(0,7),date:r||"",subject:p||""}})}catch{return[]}}function j(e,u=10,s=10){const t=S(e),i=x(e,s);t.sort((n,a)=>{const f=typeof n.ts=="number"?n.ts:Date.parse(n.ts||0);return(typeof a.ts=="number"?a.ts:Date.parse(a.ts||0))-f});const r=t.slice(0,u),p={gotcha:"\u26A0",decision:"\u2713",attempt:"\u2717",note:"\xB7",detection:"\u25CB",pattern:"\u25C7"},o=[];if(o.push(m),o.push("<!-- Auto-managed by infernoflow. Don't edit between these markers. -->"),o.push("## Project memory (infernoflow)"),o.push(""),o.push(y()),o.push(""),i.length>0){o.push("### Recent commits");for(const n of i)o.push(`- \`${n.hash}\` _${n.date}_ ${n.subject}`);o.push("")}if(r.length>0){o.push("### Recent memory");for(const n of r){const a=n.file?` (\`${n.file}${n.line?":"+n.line:""}\`)`:"",f=(n.msg||n.summary||"").replace(/\n/g," ");o.push(`- ${p[n.type]||"\xB7"} **${n.type||"note"}**${a}: ${f}`)}o.push("")}return t.length===0&&i.length===0&&o.push('_No entries yet. They\'ll appear here as you and your AI tools log them \u2014 run `infernoflow log "..."` or call `amp_write` from any MCP-aware AI._'),o.push(h),o.join(`
|
|
9
|
+
`)}function A(e){const u=j(e),s=[];for(const t of d){const i=l.join(e,t);try{const r=g(i,u);s.push({rel:t,...r})}catch(r){s.push({rel:t,error:r.message})}}return s}export{A as refreshRuleFilesFromMemory,v as writeInitRuleFiles};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import*as o from"node:fs";import*as a from"node:path";const u=new Set(["--help","-h","--version","-v","commands","doctor","setup","init","uninstall"]);function p(t){const n=a.join(t,".ai-memory"),e=a.join(t,"inferno");return o.existsSync(n)?a.join(n,".last-cli-version"):o.existsSync(e)?a.join(e,".last-cli-version"):null}function d(t){try{return o.readFileSync(t,"utf8").trim()}catch{return""}}async function m(t,n){if(!t||n&&u.has(n))return;const e=process.cwd(),c=p(e);if(!c)return;const s=d(c);if(s===t)return;let f=!1,l=s==="";try{const{
|
|
1
|
+
import*as o from"node:fs";import*as a from"node:path";const u=new Set(["--help","-h","--version","-v","commands","doctor","setup","init","uninstall"]);function p(t){const n=a.join(t,".ai-memory"),e=a.join(t,"inferno");return o.existsSync(n)?a.join(n,".last-cli-version"):o.existsSync(e)?a.join(e,".last-cli-version"):null}function d(t){try{return o.readFileSync(t,"utf8").trim()}catch{return""}}async function m(t,n){if(!t||n&&u.has(n))return;const e=process.cwd(),c=p(e);if(!c)return;const s=d(c);if(s===t)return;let f=!1,l=s==="";try{const{refreshRuleFilesFromMemory:i}=await import("./ruleFiles.mjs");i(e)}catch{}try{const{ensureGitignoreEntries:i}=await import("./commands/init.mjs");i(e,{silent:!0})}catch{}try{const{autoSetupMcp:i}=await import("./commands/setup.mjs"),r=i(e,{silent:!0});f=!!(r&&(r.mcpServer||r.claudeJson||r.cursorMcp||r.vscodeMcp||r.claudeSettings))}catch{}try{o.writeFileSync(c,t,"utf8")}catch{}if(f||l)try{const{gray:i}=await import("./ui/output.mjs"),r=s?`upgraded ${s} \u2192 ${t}`:`initialized for ${t}`;process.stderr.write(i(` infernoflow: ${r}, wired MCP servers + rule files
|
|
2
2
|
`))}catch{process.stderr.write(` infernoflow: refreshed for v${t}
|
|
3
3
|
`)}}export{m as runUpgradeBackfillIfNeeded};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "infernoflow",
|
|
3
|
-
"version": "0.43.
|
|
3
|
+
"version": "0.43.12",
|
|
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": {
|