infernoflow 0.10.13 → 0.10.14
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/bin/infernoflow.mjs +68 -0
- package/dist/lib/ai/ideDetection.mjs +1 -0
- package/dist/lib/ai/localProvider.mjs +1 -0
- package/dist/lib/ai/providerRouter.mjs +1 -0
- package/dist/lib/commands/adopt.mjs +20 -0
- package/dist/lib/commands/check.mjs +3 -0
- package/dist/lib/commands/context.mjs +20 -0
- package/dist/lib/commands/docGate.mjs +2 -0
- package/dist/lib/commands/implement.mjs +7 -0
- package/dist/lib/commands/init.mjs +17 -0
- package/dist/lib/commands/installCursorHooks.mjs +1 -0
- package/dist/lib/commands/installVsCodeCopilotHooks.mjs +1 -0
- package/dist/lib/commands/prImpact.mjs +2 -0
- package/dist/lib/commands/run.mjs +10 -0
- package/dist/lib/commands/status.mjs +4 -0
- package/dist/lib/commands/suggest.mjs +62 -0
- package/dist/lib/commands/syncAuto.mjs +1 -0
- package/dist/lib/cursorHooksInstall.mjs +1 -0
- package/dist/lib/draftToolingInstall.mjs +8 -0
- package/dist/lib/ui/output.mjs +6 -0
- package/dist/lib/ui/prompts.mjs +6 -0
- package/dist/lib/vsCodeCopilotHooksInstall.mjs +1 -0
- package/package.json +48 -44
- package/bin/infernoflow.mjs +0 -138
- package/lib/ai/ideDetection.mjs +0 -31
- package/lib/ai/localProvider.mjs +0 -88
- package/lib/ai/providerRouter.mjs +0 -73
- package/lib/commands/adopt.mjs +0 -768
- package/lib/commands/check.mjs +0 -179
- package/lib/commands/context.mjs +0 -164
- package/lib/commands/docGate.mjs +0 -81
- package/lib/commands/implement.mjs +0 -103
- package/lib/commands/init.mjs +0 -401
- package/lib/commands/installCursorHooks.mjs +0 -36
- package/lib/commands/installVsCodeCopilotHooks.mjs +0 -37
- package/lib/commands/prImpact.mjs +0 -157
- package/lib/commands/run.mjs +0 -338
- package/lib/commands/status.mjs +0 -172
- package/lib/commands/suggest.mjs +0 -501
- package/lib/commands/syncAuto.mjs +0 -96
- package/lib/cursorHooksInstall.mjs +0 -39
- package/lib/draftToolingInstall.mjs +0 -69
- package/lib/ui/output.mjs +0 -72
- package/lib/ui/prompts.mjs +0 -147
- package/lib/vsCodeCopilotHooksInstall.mjs +0 -42
- /package/{templates → dist/templates}/ci/github-inferno-check.yml +0 -0
- /package/{templates → dist/templates}/cursor/hooks/inferno-session-draft.mjs +0 -0
- /package/{templates → dist/templates}/cursor/hooks.json +0 -0
- /package/{templates → dist/templates}/github-hooks/infernoflow-drafts.json +0 -0
- /package/{templates → dist/templates}/inferno/CHANGELOG.md +0 -0
- /package/{templates → dist/templates}/inferno/capabilities.json +0 -0
- /package/{templates → dist/templates}/inferno/contract.json +0 -0
- /package/{templates → dist/templates}/inferno/scenarios/happy_path.json +0 -0
- /package/{templates → dist/templates}/scripts/inferno-doc-gate.mjs +0 -0
- /package/{templates → dist/templates}/scripts/inferno-install-hooks.mjs +0 -0
- /package/{templates → dist/templates}/scripts/inferno-promote-draft.mjs +0 -0
- /package/{templates → dist/templates}/scripts/inferno-vscode-copilot-hook.mjs +0 -0
package/bin/infernoflow.mjs
DELETED
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { readFileSync } from "node:fs";
|
|
3
|
-
import { dirname, join } from "node:path";
|
|
4
|
-
import { fileURLToPath } from "node:url";
|
|
5
|
-
import { bold, gray, cyan, red } from "../lib/ui/output.mjs";
|
|
6
|
-
|
|
7
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
|
-
const pkg = JSON.parse(readFileSync(join(__dirname, "..", "package.json"), "utf8"));
|
|
9
|
-
const VERSION = pkg.version || "0.0.0";
|
|
10
|
-
const COMMAND_DESCRIPTIONS = {
|
|
11
|
-
init: "Scaffold inferno/ in your project (or adopt existing project)",
|
|
12
|
-
"install-cursor-hooks": "Install Cursor hooks: draft agent replies to inferno/CONTEXT.draft.md",
|
|
13
|
-
"install-vscode-copilot-hooks":
|
|
14
|
-
"Install VS Code + Copilot agent hooks (Preview): draft to inferno/CONTEXT.draft.md",
|
|
15
|
-
check: "Validate contract, capabilities, scenarios, changelog",
|
|
16
|
-
status: "Show contract health at a glance",
|
|
17
|
-
"pr-impact": "Summarize PR impact on capabilities and docs",
|
|
18
|
-
sync: "Run deterministic inferno sync flow",
|
|
19
|
-
run: "One-command detect/propose/apply/validate flow",
|
|
20
|
-
"doc-gate": "Fail if code changed but docs were not updated",
|
|
21
|
-
suggest: "Generate AI prompt + apply capability updates",
|
|
22
|
-
implement: "Generate code-agent implementation prompt(s)",
|
|
23
|
-
context: "Generate AI-ready context for new sessions",
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
const COMMAND_HANDLERS = {
|
|
27
|
-
init: async (args) => (await import("../lib/commands/init.mjs")).initCommand(args),
|
|
28
|
-
"install-cursor-hooks": async (args) =>
|
|
29
|
-
(await import("../lib/commands/installCursorHooks.mjs")).installCursorHooksCommand(args),
|
|
30
|
-
"install-vscode-copilot-hooks": async (args) =>
|
|
31
|
-
(await import("../lib/commands/installVsCodeCopilotHooks.mjs")).installVsCodeCopilotHooksCommand(args),
|
|
32
|
-
check: async (args) => (await import("../lib/commands/check.mjs")).checkCommand(args),
|
|
33
|
-
status: async (args) => (await import("../lib/commands/status.mjs")).statusCommand(args),
|
|
34
|
-
"pr-impact": async (args) => (await import("../lib/commands/prImpact.mjs")).prImpactCommand(args),
|
|
35
|
-
sync: async (args) => (await import("../lib/commands/syncAuto.mjs")).syncCommand(args),
|
|
36
|
-
run: async (args) => (await import("../lib/commands/run.mjs")).runCommand(args),
|
|
37
|
-
suggest: async (args) => (await import("../lib/commands/suggest.mjs")).suggestCommand(args),
|
|
38
|
-
implement: async (args) => (await import("../lib/commands/implement.mjs")).implementCommand(args),
|
|
39
|
-
context: async (args) => (await import("../lib/commands/context.mjs")).contextCommand(args),
|
|
40
|
-
"doc-gate": async (args) => (await import("../lib/commands/docGate.mjs")).docGateCommand(args),
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
function formatCommandsHelp() {
|
|
44
|
-
const names = Object.keys(COMMAND_DESCRIPTIONS);
|
|
45
|
-
const w = Math.max(...names.map((n) => n.length), 8) + 1;
|
|
46
|
-
return Object.entries(COMMAND_DESCRIPTIONS)
|
|
47
|
-
.map(([name, desc]) => ` ${name.padEnd(w, " ")}${desc}`)
|
|
48
|
-
.join("\n");
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const HELP = `
|
|
52
|
-
${bold("🔥 infernoflow")} ${gray("v" + VERSION)}
|
|
53
|
-
${gray("The forge for liquid code — keep every AI session in sync")}
|
|
54
|
-
|
|
55
|
-
${bold("Usage:")}
|
|
56
|
-
infernoflow <command> [options]
|
|
57
|
-
|
|
58
|
-
${bold("Commands:")}
|
|
59
|
-
${formatCommandsHelp()}
|
|
60
|
-
|
|
61
|
-
${bold("init options:")}
|
|
62
|
-
--cursor-hooks Also install Cursor hooks (draft → inferno/CONTEXT.draft.md)
|
|
63
|
-
--vscode-copilot-hooks Also install VS Code + Copilot hooks (.github/hooks — Preview)
|
|
64
|
-
--adopt Infer capabilities from an existing codebase
|
|
65
|
-
--lang <name> Override detected language (e.g. ts, js, py)
|
|
66
|
-
--framework <name> Override detected framework (e.g. react, angular, express)
|
|
67
|
-
--project-type <t> Override project type (frontend|backend|fullstack|cli|library)
|
|
68
|
-
--report-json Print inferred adoption report as JSON
|
|
69
|
-
--report-json-only Print JSON report only (no human-readable logs)
|
|
70
|
-
--report-human-only Print only human-readable adoption report (no JSON block)
|
|
71
|
-
--yes, -y Skip prompts and accept inferred/default values
|
|
72
|
-
--force, -f Overwrite existing inferno/ files
|
|
73
|
-
|
|
74
|
-
${bold("install-cursor-hooks options:")}
|
|
75
|
-
--force, -f Overwrite .cursor/hooks.json and hook scripts if they exist
|
|
76
|
-
|
|
77
|
-
${bold("install-vscode-copilot-hooks options:")}
|
|
78
|
-
--force, -f Overwrite .github/hooks/infernoflow-drafts.json and scripts if they exist
|
|
79
|
-
|
|
80
|
-
${bold("context options:")}
|
|
81
|
-
--intent "..." What you plan to build next
|
|
82
|
-
--working "..." What you are building right now
|
|
83
|
-
--decision "..." Record a decision or note
|
|
84
|
-
--show Print context without writing file
|
|
85
|
-
--copy, -c Copy context to clipboard instantly
|
|
86
|
-
--reset Clear all stored state
|
|
87
|
-
|
|
88
|
-
${bold("implement options:")}
|
|
89
|
-
--mode <type> cursor | generic | both (default: both)
|
|
90
|
-
--copy, -c Copy generated prompt(s) to clipboard
|
|
91
|
-
|
|
92
|
-
${bold("run options:")}
|
|
93
|
-
--dry-run Execute full flow without writing files
|
|
94
|
-
--json Emit machine-readable events and result payload
|
|
95
|
-
--no-rollback Keep changes even if validation fails
|
|
96
|
-
--provider <type> auto | agent | local | prompt (default: auto)
|
|
97
|
-
--ide <name> auto | cursor | vscode | windsurf (default: auto)
|
|
98
|
-
|
|
99
|
-
${bold("Typical workflow:")}
|
|
100
|
-
${gray('1. infernoflow context --intent "what I want to build"')}
|
|
101
|
-
${gray("2. [paste inferno/CONTEXT.md into Claude / Cursor / Copilot]")}
|
|
102
|
-
${gray("3. [build the feature]")}
|
|
103
|
-
${gray('4. infernoflow suggest "what I built"')}
|
|
104
|
-
${gray("5. infernoflow check")}
|
|
105
|
-
|
|
106
|
-
${bold("Machine output:")}
|
|
107
|
-
${gray("status --json")}
|
|
108
|
-
${gray("check --json")}
|
|
109
|
-
${gray("doc-gate --json")}
|
|
110
|
-
${gray("pr-impact --json")}
|
|
111
|
-
${gray("sync --auto --json")}
|
|
112
|
-
${gray('run "task" --json')}
|
|
113
|
-
`;
|
|
114
|
-
|
|
115
|
-
const [, , cmd, ...rest] = process.argv;
|
|
116
|
-
|
|
117
|
-
if (!cmd || cmd === "--help" || cmd === "-h") {
|
|
118
|
-
console.log(HELP);
|
|
119
|
-
process.exit(0);
|
|
120
|
-
}
|
|
121
|
-
if (cmd === "--version" || cmd === "-v") {
|
|
122
|
-
console.log(VERSION);
|
|
123
|
-
process.exit(0);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
const commands = Object.keys(COMMAND_HANDLERS);
|
|
127
|
-
|
|
128
|
-
if (!commands.includes(cmd)) {
|
|
129
|
-
console.error(red(`\nUnknown command: ${cmd}`));
|
|
130
|
-
console.error(gray("Run: infernoflow --help\n"));
|
|
131
|
-
process.exit(1);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
const args = [cmd, ...rest];
|
|
135
|
-
COMMAND_HANDLERS[cmd](args).catch((err) => {
|
|
136
|
-
console.error(red("\nError: ") + err.message);
|
|
137
|
-
process.exit(1);
|
|
138
|
-
});
|
package/lib/ai/ideDetection.mjs
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
export function detectIdeContext(preferredIde = "auto") {
|
|
2
|
-
const env = process.env;
|
|
3
|
-
const lowerPreferred = String(preferredIde || "auto").toLowerCase();
|
|
4
|
-
|
|
5
|
-
const hasCursor = !!(env.CURSOR_TRACE_ID || env.CURSOR_AGENT || env.CURSOR_SESSION_ID || (env.VSCODE_GIT_ASKPASS_NODE || "").toLowerCase().includes("cursor") || (env.VSCODE_GIT_ASKPASS_MAIN || "").toLowerCase().includes("cursor"));
|
|
6
|
-
const hasVscode = !!(env.VSCODE_PID || env.VSCODE_CWD || env.GITHUB_COPILOT_AGENT);
|
|
7
|
-
const hasWindsurf = !!(env.WINDSURF || env.CODEIUM || env.WINDSURF_SESSION_ID);
|
|
8
|
-
|
|
9
|
-
let ideDetected = "unknown";
|
|
10
|
-
if (hasCursor) ideDetected = "cursor";
|
|
11
|
-
else if (hasVscode) ideDetected = "vscode";
|
|
12
|
-
else if (hasWindsurf) ideDetected = "windsurf";
|
|
13
|
-
|
|
14
|
-
if (lowerPreferred !== "auto" && ["cursor", "vscode", "windsurf"].includes(lowerPreferred)) {
|
|
15
|
-
ideDetected = lowerPreferred;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const explicitAgentAvailability = env.INFERNO_AGENT_AVAILABLE;
|
|
19
|
-
const agentAvailable = explicitAgentAvailability != null
|
|
20
|
-
? explicitAgentAvailability === "1" || explicitAgentAvailability === "true"
|
|
21
|
-
: ideDetected !== "unknown";
|
|
22
|
-
|
|
23
|
-
const reasonCodes = [];
|
|
24
|
-
if (ideDetected !== "unknown") reasonCodes.push(`IDE_${ideDetected.toUpperCase()}_DETECTED`);
|
|
25
|
-
else reasonCodes.push("IDE_UNKNOWN");
|
|
26
|
-
if (agentAvailable) reasonCodes.push("IDE_AGENT_AVAILABLE");
|
|
27
|
-
else reasonCodes.push("IDE_AGENT_UNAVAILABLE");
|
|
28
|
-
|
|
29
|
-
return { ideDetected, agentAvailable, reasonCodes };
|
|
30
|
-
}
|
|
31
|
-
|
package/lib/ai/localProvider.mjs
DELETED
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
const DEFAULT_TIMEOUT_MS = 45000;
|
|
2
|
-
|
|
3
|
-
function withTimeout(ms) {
|
|
4
|
-
const controller = new AbortController();
|
|
5
|
-
const timer = setTimeout(() => controller.abort(), ms);
|
|
6
|
-
return { controller, timer };
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
async function callOllama(prompt, timeoutMs) {
|
|
10
|
-
const endpoint = process.env.INFERNO_LOCAL_ENDPOINT || "http://127.0.0.1:11434/api/generate";
|
|
11
|
-
const model = process.env.INFERNO_LOCAL_MODEL || "llama3.1:8b";
|
|
12
|
-
const { controller, timer } = withTimeout(timeoutMs);
|
|
13
|
-
try {
|
|
14
|
-
const res = await fetch(endpoint, {
|
|
15
|
-
method: "POST",
|
|
16
|
-
headers: { "Content-Type": "application/json" },
|
|
17
|
-
signal: controller.signal,
|
|
18
|
-
body: JSON.stringify({
|
|
19
|
-
model,
|
|
20
|
-
prompt,
|
|
21
|
-
stream: false,
|
|
22
|
-
}),
|
|
23
|
-
});
|
|
24
|
-
if (!res.ok) {
|
|
25
|
-
const body = await res.text();
|
|
26
|
-
throw new Error(`local_model_http_${res.status}: ${body.slice(0, 240)}`);
|
|
27
|
-
}
|
|
28
|
-
const data = await res.json();
|
|
29
|
-
if (!data?.response || typeof data.response !== "string") {
|
|
30
|
-
throw new Error("local_model_invalid_response");
|
|
31
|
-
}
|
|
32
|
-
return data.response.trim();
|
|
33
|
-
} finally {
|
|
34
|
-
clearTimeout(timer);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
async function callOpenAICompat(prompt, timeoutMs) {
|
|
39
|
-
const endpoint = process.env.INFERNO_LOCAL_ENDPOINT || "http://127.0.0.1:1234/v1/chat/completions";
|
|
40
|
-
const model = process.env.INFERNO_LOCAL_MODEL || "local-model";
|
|
41
|
-
const apiKey = process.env.INFERNO_LOCAL_API_KEY || "local";
|
|
42
|
-
const { controller, timer } = withTimeout(timeoutMs);
|
|
43
|
-
try {
|
|
44
|
-
const res = await fetch(endpoint, {
|
|
45
|
-
method: "POST",
|
|
46
|
-
headers: {
|
|
47
|
-
"Content-Type": "application/json",
|
|
48
|
-
Authorization: `Bearer ${apiKey}`,
|
|
49
|
-
},
|
|
50
|
-
signal: controller.signal,
|
|
51
|
-
body: JSON.stringify({
|
|
52
|
-
model,
|
|
53
|
-
temperature: 0.1,
|
|
54
|
-
messages: [
|
|
55
|
-
{ role: "system", content: "Return JSON only." },
|
|
56
|
-
{ role: "user", content: prompt },
|
|
57
|
-
],
|
|
58
|
-
}),
|
|
59
|
-
});
|
|
60
|
-
if (!res.ok) {
|
|
61
|
-
const body = await res.text();
|
|
62
|
-
throw new Error(`local_model_http_${res.status}: ${body.slice(0, 240)}`);
|
|
63
|
-
}
|
|
64
|
-
const data = await res.json();
|
|
65
|
-
const text = data?.choices?.[0]?.message?.content;
|
|
66
|
-
if (!text || typeof text !== "string") {
|
|
67
|
-
throw new Error("local_model_invalid_response");
|
|
68
|
-
}
|
|
69
|
-
return text.trim();
|
|
70
|
-
} finally {
|
|
71
|
-
clearTimeout(timer);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export async function generateWithLocalModel(prompt, options = {}) {
|
|
76
|
-
if (process.env.INFERNO_LOCAL_MOCK_RESPONSE) {
|
|
77
|
-
return process.env.INFERNO_LOCAL_MOCK_RESPONSE;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const provider = (process.env.INFERNO_LOCAL_PROVIDER || "ollama").toLowerCase();
|
|
81
|
-
const timeoutMs = Number(options.timeoutMs || process.env.INFERNO_LOCAL_TIMEOUT_MS || DEFAULT_TIMEOUT_MS);
|
|
82
|
-
|
|
83
|
-
if (provider === "openai") {
|
|
84
|
-
return callOpenAICompat(prompt, timeoutMs);
|
|
85
|
-
}
|
|
86
|
-
return callOllama(prompt, timeoutMs);
|
|
87
|
-
}
|
|
88
|
-
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import { detectIdeContext } from "./ideDetection.mjs";
|
|
2
|
-
|
|
3
|
-
export async function resolveProvider(requestedProvider = "auto", preferredIde = "auto") {
|
|
4
|
-
const providerRequested = String(requestedProvider || "auto").toLowerCase();
|
|
5
|
-
const ide = detectIdeContext(preferredIde);
|
|
6
|
-
const reasonCodes = [...ide.reasonCodes];
|
|
7
|
-
|
|
8
|
-
if (providerRequested === "local") {
|
|
9
|
-
reasonCodes.push("LOCAL_PROVIDER_SELECTED");
|
|
10
|
-
return {
|
|
11
|
-
providerRequested,
|
|
12
|
-
providerResolved: "local",
|
|
13
|
-
ideDetected: ide.ideDetected,
|
|
14
|
-
agentAvailable: ide.agentAvailable,
|
|
15
|
-
reasonCodes,
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
if (providerRequested === "prompt") {
|
|
20
|
-
reasonCodes.push("PROMPT_PROVIDER_SELECTED");
|
|
21
|
-
return {
|
|
22
|
-
providerRequested,
|
|
23
|
-
providerResolved: "prompt",
|
|
24
|
-
ideDetected: ide.ideDetected,
|
|
25
|
-
agentAvailable: ide.agentAvailable,
|
|
26
|
-
reasonCodes,
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
if (providerRequested === "agent") {
|
|
31
|
-
if (!ide.agentAvailable) {
|
|
32
|
-
reasonCodes.push("EXPLICIT_AGENT_REQUIRED");
|
|
33
|
-
return {
|
|
34
|
-
providerRequested,
|
|
35
|
-
providerResolved: "none",
|
|
36
|
-
ideDetected: ide.ideDetected,
|
|
37
|
-
agentAvailable: ide.agentAvailable,
|
|
38
|
-
reasonCodes,
|
|
39
|
-
error: "agent_unavailable",
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
reasonCodes.push("IDE_AGENT_SELECTED");
|
|
43
|
-
return {
|
|
44
|
-
providerRequested,
|
|
45
|
-
providerResolved: "agent",
|
|
46
|
-
ideDetected: ide.ideDetected,
|
|
47
|
-
agentAvailable: ide.agentAvailable,
|
|
48
|
-
reasonCodes,
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// auto
|
|
53
|
-
if (ide.agentAvailable) {
|
|
54
|
-
reasonCodes.push("IDE_AGENT_SELECTED");
|
|
55
|
-
return {
|
|
56
|
-
providerRequested: "auto",
|
|
57
|
-
providerResolved: "agent",
|
|
58
|
-
ideDetected: ide.ideDetected,
|
|
59
|
-
agentAvailable: ide.agentAvailable,
|
|
60
|
-
reasonCodes,
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
reasonCodes.push("FALLBACK_PROMPT_MODE");
|
|
65
|
-
return {
|
|
66
|
-
providerRequested: "auto",
|
|
67
|
-
providerResolved: "prompt",
|
|
68
|
-
ideDetected: ide.ideDetected,
|
|
69
|
-
agentAvailable: ide.agentAvailable,
|
|
70
|
-
reasonCodes,
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
|