infernoflow 0.37.4 → 0.38.1
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 +18 -0
- package/dist/bin/infernoflow.mjs +19 -19
- package/dist/lib/cloud/credentials.mjs +2 -0
- package/dist/lib/cloud/supabase.mjs +1 -0
- package/dist/lib/commands/log.mjs +16 -16
- package/dist/lib/commands/login.mjs +30 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -203,6 +203,24 @@
|
|
|
203
203
|
- v0.37.3 — remove Scarf, zero-dep install, no more Windows hang
|
|
204
204
|
- v0.37.3 — remove @scarf/scarf to fix Windows install hang
|
|
205
205
|
|
|
206
|
+
- v0.38.0 — cloud login, auto-push to Supabase on every log
|
|
207
|
+
- v0.37.4
|
|
208
|
+
- v0.37.3 — remove Scarf, zero-dep install, no more Windows hang
|
|
209
|
+
- v0.37.3 — remove @scarf/scarf to fix Windows install hang
|
|
210
|
+
|
|
211
|
+
- v0.38.0 — cloud login + auto-push to Supabase on every log
|
|
212
|
+
- v0.38.0 — cloud login, auto-push to Supabase on every log
|
|
213
|
+
- v0.37.4
|
|
214
|
+
- v0.37.3 — remove Scarf, zero-dep install, no more Windows hang
|
|
215
|
+
- v0.37.3 — remove @scarf/scarf to fix Windows install hang
|
|
216
|
+
|
|
217
|
+
- v0.38.1
|
|
218
|
+
- v0.38.0 — cloud login + auto-push to Supabase on every log
|
|
219
|
+
- v0.38.0 — cloud login, auto-push to Supabase on every log
|
|
220
|
+
- v0.37.4
|
|
221
|
+
- v0.37.3 — remove Scarf, zero-dep install, no more Windows hang
|
|
222
|
+
- v0.37.3 — remove @scarf/scarf to fix Windows install hang
|
|
223
|
+
|
|
206
224
|
## 0.10.25 — 2026-04-22
|
|
207
225
|
|
|
208
226
|
### Added
|
package/dist/bin/infernoflow.mjs
CHANGED
|
@@ -1,34 +1,34 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
(function(){if(process.platform!=="win32"||process.env.WT_SESSION||process.env.ConEmuPID||process.env.TERM_PROGRAM==="vscode")return;const s={"\u2500":"-","\u2501":"-","\u2550":"=","\u2502":"|","\u2503":"|","\u2551":"|","\u250C":"+","\u2510":"+","\u2514":"+","\u2518":"+","\u251C":"+","\u2524":"+","\u252C":"+","\u2534":"+","\u253C":"+","\xB7":"*","\u2192":"->","\u2190":"<-","\u2714":"[OK]","\u2713":"[OK]","\u2718":"[X]","\u2717":"[X]","\u26A0":"[!]",\u2139:"[i]"},e=new RegExp(Object.keys(s).join("|"),"g");function c(m){const h=m.write.bind(m);m.write=function(i,...u){if(typeof i=="string")i=i.replace(e,p=>s[p]);else if(Buffer.isBuffer(i)){const p=i.toString("utf8").replace(e,w=>s[w]);i=Buffer.from(p,"utf8")}return h(i,...u)}}c(process.stdout),c(process.stderr)})();import{readFileSync as g}from"node:fs";import{dirname as C,join as b}from"node:path";import{fileURLToPath as v}from"node:url";import{bold as r,gray as t,cyan as o,red as l}from"../lib/ui/output.mjs";const k=C(v(import.meta.url)),S=JSON.parse(g(b(k,"..","..","package.json"),"utf8")),d=S.version||"0.0.0",y={publish:"Bump version, update changelog, build, npm publish, git commit + push in one shot",diff:"Show what capabilities changed since the last git tag (or any ref)",changelog:"Draft a changelog entry from commits since the last tag",setup:"One command to get fully operational \u2014 detects IDE, inits, installs hooks + MCP",init:"Scaffold inferno/ in your project (or adopt existing project)","install-cursor-hooks":"Install Cursor hooks: draft agent replies to inferno/CONTEXT.draft.md","install-vscode-copilot-hooks":"Install VS Code + Copilot agent hooks (Preview): draft to inferno/CONTEXT.draft.md",check:"Validate contract, capabilities, scenarios, changelog",status:"Show contract health at a glance","pr-impact":"Summarize PR impact on capabilities and docs",sync:"Run deterministic inferno sync flow",run:"One-command detect/propose/apply/validate flow","doc-gate":"Fail if code changed but docs were not updated",suggest:"Generate AI prompt + apply capability updates",implement:"Generate code-agent implementation prompt(s)",context:"Generate AI-ready context for new sessions","generate-skills":"Generate personalised Cursor rules + skill files from your developer profile",synthesize:"Auto-detect workflow patterns and synthesize reusable skills + agents",agent:"Manage and run auto-synthesized agents (list | run | show | delete)",version:"Smart semver bump recommendation based on capability changes (--apply to write)","pr-comment":"Post capability drift analysis as a GitHub PR comment (works in CI automatically)",dashboard:"Launch local web dashboard on localhost:7337 \u2014 live contract health, capabilities, agents","team-sync":"Sync capability contract across a team via a shared git branch (push | pull | status | init)",onboard:"Interactive onboarding wizard for new developers \u2014 explains infernoflow in 5 minutes",cloud:"Sync capability contracts via infernoflow cloud (init | push | pull | status | dashboard)",share:"Generate a public read-only HTML snapshot of your capability contract",watch:"Watch source files and run suggest automatically on save",ci:"CI-native check: GitHub Actions annotations, GitLab code quality, exit codes",notify:"Post capability drift summary to Slack or Discord",report:"Generate a weekly/monthly HTML or Markdown report of capability activity",monorepo:"Manage infernoflow across monorepo packages (init | list | status | diff | sync)",link:"Link capabilities to Jira, Linear, or GitHub Issues tickets",audit:"Classify capabilities by sensitivity (auth, payment, PII, admin) and generate security surface map",scout:"Scan source files for undocumented capabilities not yet in the contract",export:"Export contract to OpenAPI, Backstage catalog-info.yaml, CSV, or Markdown",snapshot:"Save/diff/restore named snapshots of the capability contract",health:"Compute a 0\u2013100 health score across coverage, docs, freshness, completeness, drift",vibe:"Vibe coding mode \u2014 watches files, auto-syncs contract, regenerates context on every save",adopt:"Interactive wizard to adopt infernoflow in an existing project (detect \u2192 review \u2192 wire up)",doctor:"Diagnose your infernoflow setup \u2014 checks Node, git, contract, AI providers, MCP, hooks",coverage:"Map test files to capabilities \u2014 show which caps have test coverage and which don't",review:"AI-powered capability impact review for staged or recent git changes",scan:"Deep AST scan \u2014 route discovery, entry point detection, HTTP URL extraction, capability suggestions",graph:"Build capability dependency graph \u2014 shows which caps call which, detects breaking changes",stability:"Show solid/liquid stability level for every capability (frozen/stable/experimental)",freeze:"Mark a capability as frozen (solid) \u2014 AI will not modify it without explicit instruction",thaw:"Reset a capability to experimental (liquid) \u2014 free to evolve",why:"Given a file or function name \u2014 show which capability it serves, scenarios, stability, and git history",impact:"Blast radius analysis \u2014 see every cap, scenario, and risk level affected before you change anything",scaffold:"Generate a new capability \u2014 source skeleton, contract registration, and placeholder scenario in one command",explain:"AI narrative about a capability \u2014 what it does, why it exists, what's risky, and what to test",test:"Run registered scenarios for a capability \u2014 auto-generates a smoke harness if no test runner is configured",ai:"Manage AI providers \u2014 setup, status, test connection (subcommands: setup | status | test | clear)",demo:"Interactive walkthrough \u2014 scaffolds a sample project and runs the full capability chain end-to-end",log:"Append to session memory (decisions, gotchas, failed attempts, theme changes) \u2014 what AI can't infer from code",theme:"Scan fonts, colors, and CSS variables \u2014 write inferno/theme.json so AI always matches the design system",switch:"Generate a handoff summary when switching AI agents \u2014 paste into the next session so nothing is lost",upgrade:"Upgrade a lite infernoflow setup to the full structure (scenarios, changelog, scripts)",stats:"Value dashboard \u2014 session memory, tokens injected per session, coverage %, estimated savings",ask:"Query session memory \u2014 search gotchas, decisions, and failed attempts by keyword or type",recap:"End-of-session summary \u2014 what was captured, what git changes weren't logged, session health score",uninstall:"Remove infernoflow from a project \u2014 inferno/, CLAUDE.md, MCP server, git hooks (--dry-run to preview)",feedback:"60-second CLI survey about how you use infernoflow (--form to open web form)",telemetry:"Manage anonymous usage telemetry (on | off | status) \u2014 opt-in, command names only"},f={publish:async a=>(await import("../lib/commands/publish.mjs")).publishCommand(a),diff:async a=>(await import("../lib/commands/diff.mjs")).diffCommand(a),changelog:async a=>(await import("../lib/commands/changelog.mjs")).changelogCommand(a),setup:async a=>(await import("../lib/commands/setup.mjs")).setupCommand(a),init:async a=>(await import("../lib/commands/init.mjs")).initCommand(a),"install-cursor-hooks":async a=>(await import("../lib/commands/installCursorHooks.mjs")).installCursorHooksCommand(a),"install-vscode-copilot-hooks":async a=>(await import("../lib/commands/installVsCodeCopilotHooks.mjs")).installVsCodeCopilotHooksCommand(a),check:async a=>(await import("../lib/commands/check.mjs")).checkCommand(a),status:async a=>(await import("../lib/commands/status.mjs")).statusCommand(a),"pr-impact":async a=>(await import("../lib/commands/prImpact.mjs")).prImpactCommand(a),sync:async a=>(await import("../lib/commands/syncAuto.mjs")).syncCommand(a),run:async a=>(await import("../lib/commands/run.mjs")).runCommand(a),suggest:async a=>(await import("../lib/commands/suggest.mjs")).suggestCommand(a),implement:async a=>(await import("../lib/commands/implement.mjs")).implementCommand(a),context:async a=>(await import("../lib/commands/context.mjs")).contextCommand(a),"doc-gate":async a=>(await import("../lib/commands/docGate.mjs")).docGateCommand(a),"generate-skills":async a=>(await import("../lib/commands/generateSkills.mjs")).generateSkillsCommand(a),synthesize:async a=>(await import("../lib/commands/synthesize.mjs")).synthesizeCommand(a),agent:async a=>(await import("../lib/commands/agent.mjs")).agentCommand(a),version:async a=>(await import("../lib/commands/version.mjs")).versionCommand(a),"pr-comment":async a=>(await import("../lib/commands/prComment.mjs")).prCommentCommand(a),dashboard:async a=>(await import("../lib/commands/dashboard.mjs")).dashboardCommand(a),"team-sync":async a=>(await import("../lib/commands/teamSync.mjs")).teamSyncCommand(a),onboard:async a=>(await import("../lib/commands/onboard.mjs")).onboardCommand(a),cloud:async a=>(await import("../lib/commands/cloud.mjs")).cloudCommand(a),share:async a=>(await import("../lib/commands/share.mjs")).shareCommand(a),watch:async a=>(await import("../lib/commands/watch.mjs")).watchCommand(a),ci:async a=>(await import("../lib/commands/ci.mjs")).ciCommand(a),notify:async a=>(await import("../lib/commands/notify.mjs")).notifyCommand(a),report:async a=>(await import("../lib/commands/report.mjs")).reportCommand(a),monorepo:async a=>(await import("../lib/commands/monorepo.mjs")).monorepoCommand(a),link:async a=>(await import("../lib/commands/link.mjs")).linkCommand(a),audit:async a=>(await import("../lib/commands/audit.mjs")).auditCommand(a),scout:async a=>(await import("../lib/commands/scout.mjs")).scoutCommand(a),export:async a=>(await import("../lib/commands/export.mjs")).exportCommand(a),snapshot:async a=>(await import("../lib/commands/snapshot.mjs")).snapshotCommand(a),health:async a=>(await import("../lib/commands/health.mjs")).healthCommand(a),vibe:async a=>(await import("../lib/commands/vibe.mjs")).vibeCommand(a),adopt:async a=>(await import("../lib/commands/adoptWizard.mjs")).adoptWizardCommand(a),doctor:async a=>(await import("../lib/commands/doctor.mjs")).doctorCommand(a),coverage:async a=>(await import("../lib/commands/coverage.mjs")).coverageCommand(a),review:async a=>(await import("../lib/commands/review.mjs")).reviewCommand(a),scan:async a=>(await import("../lib/commands/scan.mjs")).scanCommand(a),graph:async a=>(await import("../lib/commands/graph.mjs")).graphCommand(a),stability:async a=>(await import("../lib/commands/stability.mjs")).stabilityCommand(a),freeze:async a=>(await import("../lib/commands/stability.mjs")).freezeCommand(a),thaw:async a=>(await import("../lib/commands/stability.mjs")).thawCommand(a),why:async a=>(await import("../lib/commands/why.mjs")).whyCommand(a),impact:async a=>(await import("../lib/commands/impact.mjs")).impactCommand(a),scaffold:async a=>(await import("../lib/commands/scaffold.mjs")).scaffoldCommand(a),explain:async a=>(await import("../lib/commands/explain.mjs")).explainCommand(a),test:async a=>(await import("../lib/commands/test.mjs")).testCommand(a),ai:async a=>(await import("../lib/commands/ai.mjs")).aiCommand(a),demo:async a=>(await import("../lib/commands/demo.mjs")).demoCommand(a),log:async a=>(await import("../lib/commands/log.mjs")).logCommand(a),theme:async a=>(await import("../lib/commands/theme.mjs")).themeCommand(a),switch:async a=>(await import("../lib/commands/switch.mjs")).switchCommand(a),upgrade:async a=>(await import("../lib/commands/upgrade.mjs")).upgradeCommand(a),stats:async a=>(await import("../lib/commands/stats.mjs")).statsCommand(a),ask:async a=>(await import("../lib/commands/ask.mjs")).askCommand(a),recap:async a=>(await import("../lib/commands/recap.mjs")).recapCommand(a),uninstall:async a=>(await import("../lib/commands/uninstall.mjs")).uninstallCommand(a),feedback:async a=>(await import("../lib/commands/feedback.mjs")).feedbackCommand(a),telemetry:async a=>(await import("../lib/telemetry.mjs")).telemetryCommand(a)};function D(){const a=Object.keys(y),s=Math.max(...a.map(e=>e.length),8)+1;return Object.entries(y).map(([e,c])=>` ${e.padEnd(s," ")}${c}`).join(`
|
|
3
|
-
`)}const $={"Session Memory":["log","ask","switch","recap","stats","theme"],Context:["context","scan","suggest","check","status"],"Code Analysis":["graph","impact","why","coverage","stability","freeze","thaw","scout"],Workflow:["run","sync","watch","vibe","implement","doc-gate","synthesize","agent"],Publishing:["publish","version","changelog","diff"],Team:["team-sync","cloud","share","notify","pr-comment","pr-impact"],Quality:["health","audit","review","snapshot","export","link"],Integration:["ai","ci","coverage"],Setup:["init","setup","adopt","demo","doctor","onboard","generate-skills","upgrade","uninstall"],Advanced:["scaffold","explain","test","report","monorepo","feedback","telemetry"]};function x(){return Object.entries($).map(([
|
|
4
|
-
${
|
|
2
|
+
(function(){if(process.platform!=="win32"||process.env.WT_SESSION||process.env.ConEmuPID||process.env.TERM_PROGRAM==="vscode")return;const i={"\u2500":"-","\u2501":"-","\u2550":"=","\u2502":"|","\u2503":"|","\u2551":"|","\u250C":"+","\u2510":"+","\u2514":"+","\u2518":"+","\u251C":"+","\u2524":"+","\u252C":"+","\u2534":"+","\u253C":"+","\xB7":"*","\u2192":"->","\u2190":"<-","\u2714":"[OK]","\u2713":"[OK]","\u2718":"[X]","\u2717":"[X]","\u26A0":"[!]",\u2139:"[i]"},o=new RegExp(Object.keys(i).join("|"),"g");function c(m){const f=m.write.bind(m);m.write=function(s,...u){if(typeof s=="string")s=s.replace(o,l=>i[l]);else if(Buffer.isBuffer(s)){const l=s.toString("utf8").replace(o,w=>i[w]);s=Buffer.from(l,"utf8")}return f(s,...u)}}c(process.stdout),c(process.stderr)})();import{readFileSync as g}from"node:fs";import{dirname as C,join as b}from"node:path";import{fileURLToPath as v}from"node:url";import{bold as r,gray as t,cyan as e,red as d}from"../lib/ui/output.mjs";const k=C(v(import.meta.url)),S=JSON.parse(g(b(k,"..","..","package.json"),"utf8")),p=S.version||"0.0.0",y={publish:"Bump version, update changelog, build, npm publish, git commit + push in one shot",diff:"Show what capabilities changed since the last git tag (or any ref)",changelog:"Draft a changelog entry from commits since the last tag",setup:"One command to get fully operational \u2014 detects IDE, inits, installs hooks + MCP",init:"Scaffold inferno/ in your project (or adopt existing project)","install-cursor-hooks":"Install Cursor hooks: draft agent replies to inferno/CONTEXT.draft.md","install-vscode-copilot-hooks":"Install VS Code + Copilot agent hooks (Preview): draft to inferno/CONTEXT.draft.md",check:"Validate contract, capabilities, scenarios, changelog",status:"Show contract health at a glance","pr-impact":"Summarize PR impact on capabilities and docs",sync:"Run deterministic inferno sync flow",run:"One-command detect/propose/apply/validate flow","doc-gate":"Fail if code changed but docs were not updated",suggest:"Generate AI prompt + apply capability updates",implement:"Generate code-agent implementation prompt(s)",context:"Generate AI-ready context for new sessions","generate-skills":"Generate personalised Cursor rules + skill files from your developer profile",synthesize:"Auto-detect workflow patterns and synthesize reusable skills + agents",agent:"Manage and run auto-synthesized agents (list | run | show | delete)",version:"Smart semver bump recommendation based on capability changes (--apply to write)","pr-comment":"Post capability drift analysis as a GitHub PR comment (works in CI automatically)",dashboard:"Launch local web dashboard on localhost:7337 \u2014 live contract health, capabilities, agents","team-sync":"Sync capability contract across a team via a shared git branch (push | pull | status | init)",onboard:"Interactive onboarding wizard for new developers \u2014 explains infernoflow in 5 minutes",login:"Sign in with GitHub \u2014 syncs session memory to the cloud on every log",logout:"Sign out and remove local credentials",whoami:"Show currently logged-in user",cloud:"Sync capability contracts via infernoflow cloud (init | push | pull | status | dashboard)",share:"Generate a public read-only HTML snapshot of your capability contract",watch:"Watch source files and run suggest automatically on save",ci:"CI-native check: GitHub Actions annotations, GitLab code quality, exit codes",notify:"Post capability drift summary to Slack or Discord",report:"Generate a weekly/monthly HTML or Markdown report of capability activity",monorepo:"Manage infernoflow across monorepo packages (init | list | status | diff | sync)",link:"Link capabilities to Jira, Linear, or GitHub Issues tickets",audit:"Classify capabilities by sensitivity (auth, payment, PII, admin) and generate security surface map",scout:"Scan source files for undocumented capabilities not yet in the contract",export:"Export contract to OpenAPI, Backstage catalog-info.yaml, CSV, or Markdown",snapshot:"Save/diff/restore named snapshots of the capability contract",health:"Compute a 0\u2013100 health score across coverage, docs, freshness, completeness, drift",vibe:"Vibe coding mode \u2014 watches files, auto-syncs contract, regenerates context on every save",adopt:"Interactive wizard to adopt infernoflow in an existing project (detect \u2192 review \u2192 wire up)",doctor:"Diagnose your infernoflow setup \u2014 checks Node, git, contract, AI providers, MCP, hooks",coverage:"Map test files to capabilities \u2014 show which caps have test coverage and which don't",review:"AI-powered capability impact review for staged or recent git changes",scan:"Deep AST scan \u2014 route discovery, entry point detection, HTTP URL extraction, capability suggestions",graph:"Build capability dependency graph \u2014 shows which caps call which, detects breaking changes",stability:"Show solid/liquid stability level for every capability (frozen/stable/experimental)",freeze:"Mark a capability as frozen (solid) \u2014 AI will not modify it without explicit instruction",thaw:"Reset a capability to experimental (liquid) \u2014 free to evolve",why:"Given a file or function name \u2014 show which capability it serves, scenarios, stability, and git history",impact:"Blast radius analysis \u2014 see every cap, scenario, and risk level affected before you change anything",scaffold:"Generate a new capability \u2014 source skeleton, contract registration, and placeholder scenario in one command",explain:"AI narrative about a capability \u2014 what it does, why it exists, what's risky, and what to test",test:"Run registered scenarios for a capability \u2014 auto-generates a smoke harness if no test runner is configured",ai:"Manage AI providers \u2014 setup, status, test connection (subcommands: setup | status | test | clear)",demo:"Interactive walkthrough \u2014 scaffolds a sample project and runs the full capability chain end-to-end",log:"Append to session memory (decisions, gotchas, failed attempts, theme changes) \u2014 what AI can't infer from code",theme:"Scan fonts, colors, and CSS variables \u2014 write inferno/theme.json so AI always matches the design system",switch:"Generate a handoff summary when switching AI agents \u2014 paste into the next session so nothing is lost",upgrade:"Upgrade a lite infernoflow setup to the full structure (scenarios, changelog, scripts)",stats:"Value dashboard \u2014 session memory, tokens injected per session, coverage %, estimated savings",ask:"Query session memory \u2014 search gotchas, decisions, and failed attempts by keyword or type",recap:"End-of-session summary \u2014 what was captured, what git changes weren't logged, session health score",uninstall:"Remove infernoflow from a project \u2014 inferno/, CLAUDE.md, MCP server, git hooks (--dry-run to preview)",feedback:"60-second CLI survey about how you use infernoflow (--form to open web form)",telemetry:"Manage anonymous usage telemetry (on | off | status) \u2014 opt-in, command names only"},h={publish:async a=>(await import("../lib/commands/publish.mjs")).publishCommand(a),diff:async a=>(await import("../lib/commands/diff.mjs")).diffCommand(a),changelog:async a=>(await import("../lib/commands/changelog.mjs")).changelogCommand(a),setup:async a=>(await import("../lib/commands/setup.mjs")).setupCommand(a),init:async a=>(await import("../lib/commands/init.mjs")).initCommand(a),"install-cursor-hooks":async a=>(await import("../lib/commands/installCursorHooks.mjs")).installCursorHooksCommand(a),"install-vscode-copilot-hooks":async a=>(await import("../lib/commands/installVsCodeCopilotHooks.mjs")).installVsCodeCopilotHooksCommand(a),check:async a=>(await import("../lib/commands/check.mjs")).checkCommand(a),status:async a=>(await import("../lib/commands/status.mjs")).statusCommand(a),"pr-impact":async a=>(await import("../lib/commands/prImpact.mjs")).prImpactCommand(a),sync:async a=>(await import("../lib/commands/syncAuto.mjs")).syncCommand(a),run:async a=>(await import("../lib/commands/run.mjs")).runCommand(a),suggest:async a=>(await import("../lib/commands/suggest.mjs")).suggestCommand(a),implement:async a=>(await import("../lib/commands/implement.mjs")).implementCommand(a),context:async a=>(await import("../lib/commands/context.mjs")).contextCommand(a),"doc-gate":async a=>(await import("../lib/commands/docGate.mjs")).docGateCommand(a),"generate-skills":async a=>(await import("../lib/commands/generateSkills.mjs")).generateSkillsCommand(a),synthesize:async a=>(await import("../lib/commands/synthesize.mjs")).synthesizeCommand(a),agent:async a=>(await import("../lib/commands/agent.mjs")).agentCommand(a),version:async a=>(await import("../lib/commands/version.mjs")).versionCommand(a),"pr-comment":async a=>(await import("../lib/commands/prComment.mjs")).prCommentCommand(a),dashboard:async a=>(await import("../lib/commands/dashboard.mjs")).dashboardCommand(a),"team-sync":async a=>(await import("../lib/commands/teamSync.mjs")).teamSyncCommand(a),onboard:async a=>(await import("../lib/commands/onboard.mjs")).onboardCommand(a),login:async a=>(await import("../lib/commands/login.mjs")).loginCommand(a),logout:async()=>(await import("../lib/commands/login.mjs")).logoutCommand(),whoami:async()=>(await import("../lib/commands/login.mjs")).whoamiCommand(),cloud:async a=>(await import("../lib/commands/cloud.mjs")).cloudCommand(a),share:async a=>(await import("../lib/commands/share.mjs")).shareCommand(a),watch:async a=>(await import("../lib/commands/watch.mjs")).watchCommand(a),ci:async a=>(await import("../lib/commands/ci.mjs")).ciCommand(a),notify:async a=>(await import("../lib/commands/notify.mjs")).notifyCommand(a),report:async a=>(await import("../lib/commands/report.mjs")).reportCommand(a),monorepo:async a=>(await import("../lib/commands/monorepo.mjs")).monorepoCommand(a),link:async a=>(await import("../lib/commands/link.mjs")).linkCommand(a),audit:async a=>(await import("../lib/commands/audit.mjs")).auditCommand(a),scout:async a=>(await import("../lib/commands/scout.mjs")).scoutCommand(a),export:async a=>(await import("../lib/commands/export.mjs")).exportCommand(a),snapshot:async a=>(await import("../lib/commands/snapshot.mjs")).snapshotCommand(a),health:async a=>(await import("../lib/commands/health.mjs")).healthCommand(a),vibe:async a=>(await import("../lib/commands/vibe.mjs")).vibeCommand(a),adopt:async a=>(await import("../lib/commands/adoptWizard.mjs")).adoptWizardCommand(a),doctor:async a=>(await import("../lib/commands/doctor.mjs")).doctorCommand(a),coverage:async a=>(await import("../lib/commands/coverage.mjs")).coverageCommand(a),review:async a=>(await import("../lib/commands/review.mjs")).reviewCommand(a),scan:async a=>(await import("../lib/commands/scan.mjs")).scanCommand(a),graph:async a=>(await import("../lib/commands/graph.mjs")).graphCommand(a),stability:async a=>(await import("../lib/commands/stability.mjs")).stabilityCommand(a),freeze:async a=>(await import("../lib/commands/stability.mjs")).freezeCommand(a),thaw:async a=>(await import("../lib/commands/stability.mjs")).thawCommand(a),why:async a=>(await import("../lib/commands/why.mjs")).whyCommand(a),impact:async a=>(await import("../lib/commands/impact.mjs")).impactCommand(a),scaffold:async a=>(await import("../lib/commands/scaffold.mjs")).scaffoldCommand(a),explain:async a=>(await import("../lib/commands/explain.mjs")).explainCommand(a),test:async a=>(await import("../lib/commands/test.mjs")).testCommand(a),ai:async a=>(await import("../lib/commands/ai.mjs")).aiCommand(a),demo:async a=>(await import("../lib/commands/demo.mjs")).demoCommand(a),log:async a=>(await import("../lib/commands/log.mjs")).logCommand(a),theme:async a=>(await import("../lib/commands/theme.mjs")).themeCommand(a),switch:async a=>(await import("../lib/commands/switch.mjs")).switchCommand(a),upgrade:async a=>(await import("../lib/commands/upgrade.mjs")).upgradeCommand(a),stats:async a=>(await import("../lib/commands/stats.mjs")).statsCommand(a),ask:async a=>(await import("../lib/commands/ask.mjs")).askCommand(a),recap:async a=>(await import("../lib/commands/recap.mjs")).recapCommand(a),uninstall:async a=>(await import("../lib/commands/uninstall.mjs")).uninstallCommand(a),feedback:async a=>(await import("../lib/commands/feedback.mjs")).feedbackCommand(a),telemetry:async a=>(await import("../lib/telemetry.mjs")).telemetryCommand(a)};function D(){const a=Object.keys(y),i=Math.max(...a.map(o=>o.length),8)+1;return Object.entries(y).map(([o,c])=>` ${o.padEnd(i," ")}${c}`).join(`
|
|
3
|
+
`)}const $={"Session Memory":["log","ask","switch","recap","stats","theme"],Context:["context","scan","suggest","check","status"],"Code Analysis":["graph","impact","why","coverage","stability","freeze","thaw","scout"],Workflow:["run","sync","watch","vibe","implement","doc-gate","synthesize","agent"],Publishing:["publish","version","changelog","diff"],Team:["login","logout","whoami","team-sync","cloud","share","notify","pr-comment","pr-impact"],Quality:["health","audit","review","snapshot","export","link"],Integration:["ai","ci","coverage"],Setup:["init","setup","adopt","demo","doctor","onboard","generate-skills","upgrade","uninstall"],Advanced:["scaffold","explain","test","report","monorepo","feedback","telemetry"]};function x(){return Object.entries($).map(([i,o])=>` ${r(i+":")}
|
|
4
|
+
${o.join(" ")}`).join(`
|
|
5
5
|
|
|
6
6
|
`)}const I=`
|
|
7
|
-
${r("\u{1F525} infernoflow")} ${t("v"+
|
|
7
|
+
${r("\u{1F525} infernoflow")} ${t("v"+p)}
|
|
8
8
|
${t("Persistent memory for AI coding sessions")}
|
|
9
9
|
|
|
10
10
|
${r("Usage:")}
|
|
11
11
|
infernoflow [command] [options]
|
|
12
12
|
|
|
13
13
|
${r("Core Commands:")}
|
|
14
|
-
${
|
|
15
|
-
${
|
|
16
|
-
${
|
|
17
|
-
${
|
|
18
|
-
${
|
|
14
|
+
${e("log")} ${t('"..."')} Add to session memory ${t("(--type gotcha|decision|attempt|preference)")}
|
|
15
|
+
${e("ask")} ${t('"..."')} Search your memory by keyword ${t("(gotchas surface first)")}
|
|
16
|
+
${e("switch")} Generate handoff for next AI agent
|
|
17
|
+
${e("recap")} End-of-session health score + unlogged changes
|
|
18
|
+
${e("status")} Contract health at a glance
|
|
19
19
|
|
|
20
20
|
${r("Getting Started:")}
|
|
21
|
-
${
|
|
22
|
-
${
|
|
23
|
-
${
|
|
21
|
+
${e("setup")} One command to get fully operational
|
|
22
|
+
${e("demo")} Interactive walkthrough ${t("(5 minutes)")}
|
|
23
|
+
${e("doctor")} Diagnose your setup
|
|
24
24
|
|
|
25
|
-
${t("Run")} ${
|
|
26
|
-
${t("Run")} ${
|
|
27
|
-
`;import*as A from"node:fs";import*as M from"node:path";try{const a=M.join(process.cwd(),"inferno");if(A.existsSync(a)){const{observeCommandStart:
|
|
28
|
-
${r("\u{1F525} infernoflow")} ${t("v"+
|
|
25
|
+
${t("Run")} ${e("infernoflow commands")} ${t("to see all 50+ commands.")}
|
|
26
|
+
${t("Run")} ${e("infernoflow <command> --help")} ${t("for command-specific options.")}
|
|
27
|
+
`;import*as A from"node:fs";import*as M from"node:path";try{const a=M.join(process.cwd(),"inferno");if(A.existsSync(a)){const{observeCommandStart:i}=await import("../lib/learning/observe.mjs"),o=process.argv[2];o&&!o.startsWith("-")&&i(a,o)}}catch{}const[,,n,...O]=process.argv;(!n||n==="--help"||n==="-h")&&(console.log(I),process.exit(0)),(n==="--version"||n==="-v")&&(console.log(p),process.exit(0)),n==="commands"&&(console.log(`
|
|
28
|
+
${r("\u{1F525} infernoflow")} ${t("v"+p)} ${t("\u2014 all commands")}
|
|
29
29
|
`),console.log(x()),console.log(`
|
|
30
|
-
${t("Run")} ${
|
|
31
|
-
`),process.exit(0));const R=Object.keys(
|
|
30
|
+
${t("Run")} ${e("infernoflow <command> --help")} ${t("for options.")}
|
|
31
|
+
`),process.exit(0));const R=Object.keys(h);R.includes(n)||(console.error(d(`
|
|
32
32
|
Unknown command: ${n}`)),console.error(t("Run: infernoflow commands (see all commands)")),console.error(t(`Run: infernoflow --help (quick start)
|
|
33
|
-
`)),process.exit(1));const
|
|
33
|
+
`)),process.exit(1));const G=[n,...O];h[n](G).catch(a=>{console.error(d(`
|
|
34
34
|
Error: `)+a.message),process.exit(1)});
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import*as e from"node:fs";import*as i from"node:path";import*as o from"node:os";const n=i.join(o.homedir(),".infernoflow"),t=i.join(n,"credentials.json");function c(){try{return e.existsSync(t)?JSON.parse(e.readFileSync(t,"utf8")):null}catch{return null}}function a(r){e.existsSync(n)||e.mkdirSync(n,{recursive:!0}),e.writeFileSync(t,JSON.stringify(r,null,2)+`
|
|
2
|
+
`,{mode:384})}function f(){try{return e.existsSync(t)&&e.unlinkSync(t),!0}catch{return!1}}function u(){const r=c();if(!r?.access_token)return!1;if(r.expires_at){const s=new Date(r.expires_at).getTime();if(Date.now()>s-6e4)return!1}return!0}export{f as deleteCredentials,u as isLoggedIn,c as readCredentials,a as writeCredentials};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import*as m from"node:https";const n=process.env.INFERNOFLOW_SUPABASE_URL||"https://vscesbbtmrsctfroigyx.supabase.co",f=process.env.INFERNOFLOW_SUPABASE_ANON_KEY||"sb_publishable_yThoZzOisgqLxrH8BOli-Q_yHVqEhUk";function i(t,e,r,s){return new Promise((h,l)=>{const c=new URL(e),a=r?JSON.stringify(r):null,y={hostname:c.hostname,port:443,path:c.pathname+c.search,method:t,headers:{"Content-Type":"application/json",Accept:"application/json","User-Agent":"infernoflow-cli",apikey:f,...s,...a?{"Content-Length":Buffer.byteLength(a)}:{}}},o=m.request(y,u=>{let p="";u.on("data",d=>p+=d),u.on("end",()=>{try{h({status:u.statusCode,body:JSON.parse(p)})}catch{h({status:u.statusCode,body:p})}})});o.on("error",l),o.setTimeout(8e3,()=>{o.destroy(new Error("timeout"))}),a&&o.write(a),o.end()})}async function A(t,e,r){try{const s={project_id:r,ts:t.ts,type:t.type||"note",summary:t.summary,result:t.result||null,source:t.source||null,auto:t.auto||!1,agent:t.agent||null};await i("POST",`${n}/rest/v1/entries`,s,{Authorization:`Bearer ${e}`,Prefer:"return=minimal"})}catch{}}async function S(t){return await i("POST",`${n}/auth/v1/token?grant_type=pkce`,{auth_code:t},{})}function _(t,e){const r=new URLSearchParams({provider:"github",redirect_to:e,state:t});return`${n}/auth/v1/authorize?${r.toString()}`}async function g(t){const e=await i("GET",`${n}/auth/v1/user`,null,{Authorization:`Bearer ${t}`});return e.status===200?e.body:null}async function E(t,e){const r=new URLSearchParams({project_id:`eq.${e}`,order:"ts.asc",limit:"10000"}),s=await i("GET",`${n}/rest/v1/entries?${r.toString()}`,null,{Authorization:`Bearer ${t}`});return s.status===200&&Array.isArray(s.body)?s.body:[]}export{f as SUPABASE_ANON_KEY,n as SUPABASE_URL,S as exchangeCodeForSession,_ as getOAuthUrl,g as getUser,E as pullEntries,A as pushEntry};
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import*as
|
|
2
|
-
`).filter(Boolean).map(
|
|
3
|
-
`),a=process.cwd(),u=
|
|
4
|
-
`).filter(Boolean).map(e=>{try{return JSON.parse(e)}catch{return null}}).filter(Boolean):[]}function
|
|
5
|
-
`)),process.exit(1)}return
|
|
6
|
-
`,"utf8"),!0}function
|
|
7
|
-
`+
|
|
1
|
+
import*as s from"node:fs";import*as f from"node:path";import"node:os";import{bold as N,cyan as v,gray as n,green as j,red as I}from"../ui/output.mjs";import{readCredentials as _,isLoggedIn as R}from"../cloud/credentials.mjs";import{pushEntry as k}from"../cloud/supabase.mjs";const O="inferno",h=f.join(O,"sessions.jsonl");function A(){try{const e=s.existsSync(h)?s.readFileSync(h,"utf8").split(`
|
|
2
|
+
`).filter(Boolean).map(t=>{try{return JSON.parse(t)}catch{return null}}).filter(Boolean):[],c=e.filter(t=>t.type==="gotcha"),r=e.filter(t=>t.type==="decision"),l=e.filter(t=>t.type==="attempt"&&(t.result==="failed"||t.result==="partial")),i=["# Project Context (auto-generated by infernoflow)","",`> Last updated: ${new Date().toISOString()}`,""];if(c.length){i.push("## \u26A0\uFE0F Known Gotchas (Read These First)","");for(const t of c)i.push(`- ${t.summary}`);i.push("")}if(r.length){i.push("## \u2713 Decisions In Effect","");for(const t of r)i.push(`- ${t.summary}`);i.push("")}if(l.length){i.push("## \u274C Things That Don't Work (Don't Try These)","");for(const t of l)i.push(`- ${t.summary}`);i.push("")}const p=i.join(`
|
|
3
|
+
`),a=process.cwd(),u=f.join(a,"CLAUDE.md");s.existsSync(u)&&s.writeFileSync(u,p,"utf8");const m=f.join(a,".cursorrules");(s.existsSync(m)||s.existsSync(f.join(a,".cursor")))&&s.writeFileSync(m,p,"utf8");const $=f.join(a,".github","copilot-instructions.md");s.existsSync(f.join(a,".github"))&&s.writeFileSync($,p,"utf8")}catch{}}const F=["note","attempt","decision","gotcha","preference","theme","handoff","error"],b=["worked","failed","partial","unknown"];function C(){return s.existsSync(h)?s.readFileSync(h,"utf8").split(`
|
|
4
|
+
`).filter(Boolean).map(e=>{try{return JSON.parse(e)}catch{return null}}).filter(Boolean):[]}function U(e,{auto:c=!1,quiet:r=!1}={}){if(!s.existsSync(O)){if(c)return!1;r||console.error(I(` \u2718 inferno/ not found \u2014 run: infernoflow init
|
|
5
|
+
`)),process.exit(1)}return s.appendFileSync(h,JSON.stringify(e)+`
|
|
6
|
+
`,"utf8"),!0}function B(){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 J(e,c){const r=new Date(e.ts).toLocaleString("en-GB",{day:"2-digit",month:"short",hour:"2-digit",minute:"2-digit"}),l=e.type||"note",i=l==="gotcha"?"\x1B[33m":l==="decision"?"\x1B[36m":l==="theme"?"\x1B[35m":l==="preference"?"\x1B[34m":l==="attempt"?"\x1B[90m":l==="error"?"\x1B[31m":"\x1B[0m",p="\x1B[0m",a=e.result?` [${e.result}]`:"",u=e.agent&&e.agent!=="human"?n(` (${e.agent})`):"";return` ${n(String(c+1).padStart(3))} ${n(r)} ${i}${l}${p}${a} ${e.summary}${u}`}async function K(e){const c=o=>e.includes(o),r=(o,g)=>{const d=e.indexOf(o);return d!==-1&&e[d+1]?e[d+1]:g},l=c("--show"),i=c("--clear"),p=c("--json"),a=c("--auto"),u=c("--quiet"),m=r("--source",null);if(l||p){const o=C(),g=e[e.indexOf("--show")+1],d=g&&/^\d+$/.test(g)?parseInt(g):20,w=o.slice(-d);if(p){console.log(JSON.stringify(w,null,2));return}if(console.log(`
|
|
7
|
+
`+N("\u{1F525} infernoflow \u2014 session memory")),console.log(" "+"\u2500".repeat(50)),!w.length){console.log(n(`
|
|
8
8
|
No entries yet. Start logging with: infernoflow log "<what happened>"
|
|
9
|
-
`));return}console.log(n(` Showing last ${w.length} of ${
|
|
10
|
-
`)),w.forEach((D,T)=>console.log(
|
|
11
|
-
`));return}const
|
|
12
|
-
`));return}const $=new Set([
|
|
13
|
-
`+
|
|
9
|
+
`));return}console.log(n(` Showing last ${w.length} of ${o.length} entries
|
|
10
|
+
`)),w.forEach((D,T)=>console.log(J(D,o.length-w.length+T))),console.log();return}if(i){if(!s.existsSync(h)){console.log(n(` Nothing to clear.
|
|
11
|
+
`));return}const o=h.replace(".jsonl",`-archive-${Date.now()}.jsonl`);s.renameSync(h,o),console.log(j(` \u2714 Session log archived \u2192 ${f.basename(o)}
|
|
12
|
+
`));return}const $=new Set([r("--type",""),r("--result",""),r("--agent",""),r("--source","")].filter(Boolean)),x=e.filter(o=>!o.startsWith("--")&&!$.has(o)).join(" ").trim();if(!x){console.log(`
|
|
13
|
+
`+N("\u{1F525} infernoflow log")+` \u2014 append to session memory
|
|
14
14
|
`),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>
|
|
15
|
-
`));return}const S=
|
|
16
|
-
`)),process.exit(1)),
|
|
17
|
-
`)),process.exit(1));const
|
|
18
|
-
`)}}export{
|
|
15
|
+
`));return}const S=r("--type","note"),y=r("--result",null),L=r("--agent",B());F.includes(S)||(u||console.error(I(` \u2718 Invalid type: ${S}. Valid: ${F.join(", ")}
|
|
16
|
+
`)),process.exit(1)),y&&!b.includes(y)&&(u||console.error(I(` \u2718 Invalid result: ${y}. Valid: ${b.join(", ")}
|
|
17
|
+
`)),process.exit(1));const E={ts:new Date().toISOString(),agent:L,type:S,summary:x,...y?{result:y}:{},...m?{source:m}:{},...a?{auto:!0}:{}};if(U(E,{auto:a,quiet:u})){A();try{if(R()){const o=_(),g=(()=>{try{return JSON.parse(s.readFileSync(f.join(O,"config.json"),"utf8")).projectId||f.basename(process.cwd())}catch{return f.basename(process.cwd())}})();k(E,o.access_token,g).catch(()=>{})}}catch{}if(!u){const o=S!=="note"?v(` [${S}]`):"",g=y?n(` \u2192 ${y}`):"",d=m?n(` (via ${m})`):"";console.log(j(` \u2714 Logged${o}${g}${d}: `)+x+`
|
|
18
|
+
`)}}}export{K as logCommand};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import*as k from"node:http";import*as L from"node:crypto";import"node:fs";import"node:path";import{bold as i,cyan as r,gray as t,green as g,red as y,yellow as x}from"../ui/output.mjs";import{readCredentials as _,writeCredentials as A,deleteCredentials as O,isLoggedIn as $}from"../cloud/credentials.mjs";import{getOAuthUrl as C,getUser as P,SUPABASE_URL as T}from"../cloud/supabase.mjs";const u=9242,w="/auth/callback",v=`http://localhost:${u}${w}`;function E(e){try{const{execSync:s}=require("child_process"),l=process.platform==="win32"?`start "" "${e}"`:process.platform==="darwin"?`open "${e}"`:`xdg-open "${e}"`;s(l,{stdio:"ignore"})}catch{}}async function U(){if(T.includes("YOUR_PROJECT")&&(console.log(),console.log(` ${y("\u2718")} Supabase not configured yet.`),console.log(),console.log(" Set up your Supabase project first:"),console.log(` ${t("1.")} Create a project at ${r("https://supabase.com")}`),console.log(` ${t("2.")} Run ${r("scripts/supabase-schema.sql")} in the SQL editor`),console.log(` ${t("3.")} Enable GitHub OAuth in Authentication \u2192 Providers`),console.log(` ${t("4.")} Set ${r("INFERNOFLOW_SUPABASE_URL")} and ${r("INFERNOFLOW_SUPABASE_ANON_KEY")}`),console.log(" (or hardcode them in lib/cloud/supabase.mjs)"),console.log(),process.exit(1)),$()){const n=_()?.user;console.log(),console.log(` ${g("\u2714")} Already logged in as ${i(n?.email||n?.user_metadata?.user_name||"unknown")}`),console.log(` Run ${r("infernoflow logout")} to sign out.`),console.log();return}const e=L.randomBytes(16).toString("hex");console.log(),console.log(` ${i("\u{1F525} infernoflow login")}`),console.log();let s,l;const d=new Promise((o,n)=>{s=o,l=n}),a=k.createServer((o,n)=>{if(new URL(o.url,`http://localhost:${u}`).pathname!==w){n.writeHead(404),n.end("Not found");return}if(o.method==="GET"){n.writeHead(200,{"Content-Type":"text/html"}),n.end(`<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head><meta charset="utf-8"><title>infernoflow login</title>
|
|
4
|
+
<style>body{font-family:system-ui;display:flex;align-items:center;justify-content:center;height:100vh;margin:0;background:#0f172a;color:#f1f5f9}</style>
|
|
5
|
+
</head>
|
|
6
|
+
<body>
|
|
7
|
+
<script>
|
|
8
|
+
const hash = window.location.hash.slice(1);
|
|
9
|
+
const params = new URLSearchParams(hash);
|
|
10
|
+
const access_token = params.get('access_token');
|
|
11
|
+
const refresh_token = params.get('refresh_token');
|
|
12
|
+
const expires_in = params.get('expires_in');
|
|
13
|
+
const error = params.get('error_description') || params.get('error');
|
|
14
|
+
if (access_token) {
|
|
15
|
+
fetch('/auth/callback', {
|
|
16
|
+
method: 'POST',
|
|
17
|
+
headers: {'Content-Type': 'application/json'},
|
|
18
|
+
body: JSON.stringify({ access_token, refresh_token, expires_in })
|
|
19
|
+
}).then(() => {
|
|
20
|
+
document.body.innerHTML = '<div style="text-align:center"><div style="font-size:48px">\u{1F525}</div><h2>Logged in!</h2><p style="color:#94a3b8">You can close this tab and return to the terminal.</p></div>';
|
|
21
|
+
});
|
|
22
|
+
} else if (error) {
|
|
23
|
+
document.body.innerHTML = '<div style="text-align:center"><h2>Login failed</h2><p style="color:#f87171">' + error + '</p></div>';
|
|
24
|
+
fetch('/auth/callback', { method: 'POST', headers: {'Content-Type':'application/json'}, body: JSON.stringify({ error }) });
|
|
25
|
+
} else {
|
|
26
|
+
document.body.innerHTML = '<div style="text-align:center"><p style="color:#94a3b8">Processing\u2026</p></div>';
|
|
27
|
+
}
|
|
28
|
+
</script>
|
|
29
|
+
</body>
|
|
30
|
+
</html>`);return}if(o.method==="POST"){let h="";o.on("data",c=>h+=c),o.on("end",()=>{n.writeHead(200),n.end("ok"),a.close();try{const c=JSON.parse(h);c.error?l(new Error(c.error)):s(c)}catch(c){l(c)}})}});a.listen(u,"127.0.0.1",()=>{const o=C(e,v);console.log(" Opening browser for GitHub login\u2026"),console.log(),console.log(` ${t("If the browser doesn't open, visit:")}`),console.log(` ${r(o)}`),console.log(),E(o),console.log(` ${t("Waiting for login\u2026")} ${t("(Ctrl+C to cancel)")}`)});const m=setTimeout(()=>{a.close(),l(new Error("Login timed out after 3 minutes"))},180*1e3);try{const o=await d;clearTimeout(m);const n=await P(o.access_token),f={access_token:o.access_token,refresh_token:o.refresh_token||null,expires_at:o.expires_in?new Date(Date.now()+parseInt(o.expires_in)*1e3).toISOString():null,user:n,logged_in_at:new Date().toISOString()};A(f);const p=n?.user_metadata?.user_name||n?.email||"unknown";console.log(),console.log(` ${g("\u2714")} Logged in as ${i(p)}`),console.log(),console.log(` ${t("Session memory will now sync to the cloud on every")} ${r("infernoflow log")}`),console.log()}catch(o){clearTimeout(m),a.close(),console.log(),console.log(` ${y("\u2718")} Login failed: ${o.message}`),console.log(),process.exit(1)}}function S(){const e=O();console.log(),console.log(e?` ${g("\u2714")} Logged out. Local credentials removed.`:` ${t("Already logged out.")}`),console.log()}async function b(){const e=_();if(console.log(),!e?.access_token){console.log(` ${t("Not logged in.")} Run ${r("infernoflow login")}`),console.log();return}const s=e.user?.user_metadata?.user_name||e.user?.email||"unknown",l=e.user?.email||t("(no email)"),d=e.logged_in_at?new Date(e.logged_in_at).toLocaleDateString():"unknown",a=!$();console.log(` ${i("\u{1F525} infernoflow")} \u2014 logged in as:`),console.log(),console.log(` User: ${i(s)}`),console.log(` Email: ${l}`),console.log(` Since: ${t(d)}`),console.log(a?` Status: ${x("\u26A0 Token expired \u2014 run infernoflow login to refresh")}`:` Status: ${g("\u2714 Active")}`),console.log()}async function D(e){const s=e[1];return s==="logout"?S():s==="whoami"?b():U()}async function Y(){return S()}async function F(){return b()}export{D as loginCommand,Y as logoutCommand,F as whoamiCommand};
|
package/package.json
CHANGED