infernoflow 0.10.15 → 0.10.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1 +1 @@
|
|
|
1
|
-
import*as
|
|
1
|
+
import*as r from"node:fs";import*as o from"node:path";import{installInfernoDraftTooling as v}from"./draftToolingInstall.mjs";function h(f){const{cwd:s,templatesRoot:t,force:m,silent:e}=f,a=f.logOk||(()=>{}),l=f.logWarn||(()=>{});function p(n,c){return r.existsSync(c)&&!m?(e||l("Skipped (exists): "+o.relative(s,c)),!1):(r.mkdirSync(o.dirname(c),{recursive:!0}),r.copyFileSync(n,c),e||a("Created: "+o.relative(s,c)),!0)}v({cwd:s,templatesRoot:t,force:m,silent:e,logOk:a,logWarn:l});const u=o.join(t,"cursor","hooks.json"),j=o.join(s,".cursor","hooks.json"),k=o.join(t,"cursor","hooks","inferno-session-draft.mjs"),S=o.join(s,".cursor","hooks","inferno-session-draft.mjs");p(u,j),p(k,S);const d=o.join(t,"cursor","inferno-mcp-server.mjs"),y=o.join(s,"inferno-mcp-server.mjs");p(d,y);const i=o.join(s,".cursor","mcp.json");if(!r.existsSync(i)||m){let n={};if(r.existsSync(i))try{n=JSON.parse(r.readFileSync(i,"utf8"))}catch{}n.mcpServers||(n.mcpServers={}),n.mcpServers.infernoflow={command:"node",args:["./inferno-mcp-server.mjs"],env:{}},r.mkdirSync(o.dirname(i),{recursive:!0}),r.writeFileSync(i,JSON.stringify(n,null,2),"utf8"),e||a("Created: .cursor/mcp.json")}else e||l("Skipped (exists): .cursor/mcp.json")}export{h as installCursorHooksArtifacts};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { execSync } from "node:child_process";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import readline from "node:readline";
|
|
5
|
+
|
|
6
|
+
function send(obj) { process.stdout.write(JSON.stringify(obj) + "\n"); }
|
|
7
|
+
function sendResult(id, result) { send({ jsonrpc: "2.0", id, result }); }
|
|
8
|
+
function sendError(id, code, message) { send({ jsonrpc: "2.0", id, error: { code, message } }); }
|
|
9
|
+
|
|
10
|
+
function runCmd(args, env = {}) {
|
|
11
|
+
try { return execSync(`npx infernoflow ${args}`, { encoding: "utf8", cwd: process.cwd(), timeout: 30000, env: { ...process.env, ...env } }); }
|
|
12
|
+
catch (err) { return err.stdout || err.message; }
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const TOOLS = [
|
|
16
|
+
{ name: "infernoflow_run", description: "Generate an infernoflow task prompt. Returns the prompt — respond to it with JSON, then call infernoflow_apply.", inputSchema: { type: "object", properties: { task: { type: "string", description: "What to build" } }, required: ["task"] } },
|
|
17
|
+
{ name: "infernoflow_apply", description: "Apply an infernoflow suggestion JSON returned by the agent. Call this after responding to infernoflow_run.", inputSchema: { type: "object", properties: { json: { type: "string", description: "The JSON suggestion from the agent" } }, required: ["json"] } },
|
|
18
|
+
{ name: "infernoflow_check", description: "Validate infernoflow contract and capabilities", inputSchema: { type: "object", properties: {} } },
|
|
19
|
+
{ name: "infernoflow_status", description: "Show contract health at a glance", inputSchema: { type: "object", properties: {} } },
|
|
20
|
+
{ name: "infernoflow_context", description: "Generate AI-ready context", inputSchema: { type: "object", properties: { intent: { type: "string" }, working: { type: "string" } } } },
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
function buildPrompt(task) {
|
|
24
|
+
const infernoDir = path.join(process.cwd(), "inferno");
|
|
25
|
+
const contractPath = path.join(infernoDir, "contract.json");
|
|
26
|
+
const capsPath = path.join(infernoDir, "capabilities.json");
|
|
27
|
+
if (!fs.existsSync(contractPath)) return null;
|
|
28
|
+
const contract = JSON.parse(fs.readFileSync(contractPath, "utf8"));
|
|
29
|
+
const caps = fs.existsSync(capsPath) ? JSON.parse(fs.readFileSync(capsPath, "utf8")) : {};
|
|
30
|
+
const capList = (caps.capabilities || []).map(c => ` - ${c.id}: ${c.title || c.id}`).join("\n");
|
|
31
|
+
return `You are a developer assistant for the infernoflow CLI tool.
|
|
32
|
+
Analyze this task and suggest updates to the infernoflow contract files.
|
|
33
|
+
|
|
34
|
+
## Current contract
|
|
35
|
+
policyId: ${contract.policyId}
|
|
36
|
+
policyVersion: ${contract.policyVersion}
|
|
37
|
+
capabilities: [${(contract.capabilities || []).join(", ")}]
|
|
38
|
+
|
|
39
|
+
## Capabilities registry
|
|
40
|
+
${capList || " (none)"}
|
|
41
|
+
|
|
42
|
+
## Task
|
|
43
|
+
"${task}"
|
|
44
|
+
|
|
45
|
+
## Instructions
|
|
46
|
+
Respond with ONLY a valid JSON object:
|
|
47
|
+
{
|
|
48
|
+
"summary": "one-line summary of what changed",
|
|
49
|
+
"newCapabilities": [{ "id": "PascalCase", "title": "Human readable title", "reason": "why this is new" }],
|
|
50
|
+
"removedCapabilities": [],
|
|
51
|
+
"updatedScenarios": [],
|
|
52
|
+
"changelogEntry": "- Short description for CHANGELOG.md"
|
|
53
|
+
}`;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function handleTool(id, name, input) {
|
|
57
|
+
try {
|
|
58
|
+
let text = "";
|
|
59
|
+
if (name === "infernoflow_run") {
|
|
60
|
+
const prompt = buildPrompt(input.task);
|
|
61
|
+
if (!prompt) { sendError(id, -32000, "inferno/ not found — run infernoflow init first"); return; }
|
|
62
|
+
const promptFile = path.join(process.cwd(), "inferno", "agent-prompt.md");
|
|
63
|
+
fs.writeFileSync(promptFile, prompt, "utf8");
|
|
64
|
+
text = `## infernoflow task: "${input.task}"\n\n${prompt}\n\n---\nRespond with the JSON, then call **infernoflow_apply** with your JSON string.`;
|
|
65
|
+
} else if (name === "infernoflow_apply") {
|
|
66
|
+
const responseFile = path.join(process.cwd(), "inferno", "agent-response.json");
|
|
67
|
+
let json = input.json.trim().replace(/^```json?\n?/, "").replace(/\n?```$/, "");
|
|
68
|
+
fs.writeFileSync(responseFile, json, "utf8");
|
|
69
|
+
text = runCmd(`run "apply"`, { INFERNO_AGENT_RESPONSE_FILE: responseFile, INFERNO_AGENT_AVAILABLE: "1" });
|
|
70
|
+
} else if (name === "infernoflow_check") {
|
|
71
|
+
text = runCmd("check");
|
|
72
|
+
} else if (name === "infernoflow_status") {
|
|
73
|
+
text = runCmd("status");
|
|
74
|
+
} else if (name === "infernoflow_context") {
|
|
75
|
+
const parts = [];
|
|
76
|
+
if (input.intent) parts.push(`--intent "${input.intent}"`);
|
|
77
|
+
if (input.working) parts.push(`--working "${input.working}"`);
|
|
78
|
+
text = runCmd("context " + parts.join(" "));
|
|
79
|
+
} else { return sendError(id, -32601, `Unknown tool: ${name}`); }
|
|
80
|
+
sendResult(id, { content: [{ type: "text", text: text || "(no output)" }] });
|
|
81
|
+
} catch (err) { sendError(id, -32000, err.message); }
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const rl = readline.createInterface({ input: process.stdin });
|
|
85
|
+
rl.on("line", (line) => {
|
|
86
|
+
let msg; try { msg = JSON.parse(line); } catch { return; }
|
|
87
|
+
const { id, method, params } = msg;
|
|
88
|
+
if (method === "initialize") { sendResult(id, { protocolVersion: "2024-11-05", capabilities: { tools: {} }, serverInfo: { name: "infernoflow", version: "1.0.0" } }); return; }
|
|
89
|
+
if (method === "tools/list") { sendResult(id, { tools: TOOLS }); return; }
|
|
90
|
+
if (method === "tools/call") { handleTool(id, params.name, params.arguments || {}); return; }
|
|
91
|
+
if (id !== undefined) sendError(id, -32601, `Method not found: ${method}`);
|
|
92
|
+
});
|
|
93
|
+
process.stderr.write("[infernoflow MCP] started\n");
|