@devflow-tools/devflow 0.15.0 → 0.16.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/acceptance-manifest.json +35 -0
- package/dist/cli.js +115 -28
- package/dist/dashboard/404.html +1 -0
- package/dist/dashboard/_next/static/PV20UFAxDva62WLq6zWVa/_buildManifest.js +1 -0
- package/dist/dashboard/_next/static/PV20UFAxDva62WLq6zWVa/_ssgManifest.js +1 -0
- package/dist/dashboard/_next/static/chunks/1dd3208c-f3e84932bdc53383.js +1 -0
- package/dist/dashboard/_next/static/chunks/221-893fab1a7d7d9317.js +1 -0
- package/dist/dashboard/_next/static/chunks/249-e04c1de6240fd78a.js +1 -0
- package/dist/dashboard/_next/static/chunks/343-09a7e255220705c5.js +1 -0
- package/dist/dashboard/_next/static/chunks/402-a2e4eb98bb6a524c.js +1 -0
- package/dist/dashboard/_next/static/chunks/429-eac85fdc49353ed8.js +1 -0
- package/dist/dashboard/_next/static/chunks/458-75822399a849befa.js +1 -0
- package/dist/dashboard/_next/static/chunks/528-7d4fc14903647f1e.js +2 -0
- package/dist/dashboard/_next/static/chunks/568-50487ea5e93fe11f.js +1 -0
- package/dist/dashboard/_next/static/chunks/697-05cf55b6c667773f.js +1 -0
- package/dist/dashboard/_next/static/chunks/6b3bb038-34d5cf36bd0210d6.js +1 -0
- package/dist/dashboard/_next/static/chunks/736-db1a009357c222d2.js +1 -0
- package/dist/dashboard/_next/static/chunks/806-195d4d5cc6c28f6c.js +1 -0
- package/dist/dashboard/_next/static/chunks/app/_not-found/page-5252c260804ee1ce.js +1 -0
- package/dist/dashboard/_next/static/chunks/app/accuracy/page-ca6a419d8b29eb4f.js +1 -0
- package/dist/dashboard/_next/static/chunks/app/benchmark/page-6c6d0acbcde4eb85.js +1 -0
- package/dist/dashboard/_next/static/chunks/app/context/page-1874ae1050524cb6.js +1 -0
- package/dist/dashboard/_next/static/chunks/app/doctor/page-d542f2ab8d6a1c59.js +1 -0
- package/dist/dashboard/_next/static/chunks/app/executions/page-b98ec834dcda8d93.js +1 -0
- package/dist/dashboard/_next/static/chunks/app/graph/page-f0e7e15288791e9c.js +1 -0
- package/dist/dashboard/_next/static/chunks/app/knowledge/page-86808abd0d47c026.js +1 -0
- package/dist/dashboard/_next/static/chunks/app/layout-4b78776412bd4fee.js +1 -0
- package/dist/dashboard/_next/static/chunks/app/memory/page-e169762426ac7a23.js +1 -0
- package/dist/dashboard/_next/static/chunks/app/page-c3e980fb2621470c.js +1 -0
- package/dist/dashboard/_next/static/chunks/app/replay/page-a8a465ed885df0cf.js +1 -0
- package/dist/dashboard/_next/static/chunks/app/runs/[id]/page-cc1d5182707fca5b.js +1 -0
- package/dist/dashboard/_next/static/chunks/app/runs/page-bbf0a58abd70430c.js +1 -0
- package/dist/dashboard/_next/static/chunks/app/settings/page-9602ff45892e7910.js +1 -0
- package/dist/dashboard/_next/static/chunks/app/timeline/page-a8eb3caf23be8a86.js +1 -0
- package/dist/dashboard/_next/static/chunks/app/tool-metrics/page-1f86f62b187f2b5e.js +1 -0
- package/dist/dashboard/_next/static/chunks/app/workflows/page-551939c9e86b26c6.js +1 -0
- package/dist/dashboard/_next/static/chunks/framework-58c3457e28c4602f.js +1 -0
- package/dist/dashboard/_next/static/chunks/main-3175faffdbfc3051.js +1 -0
- package/dist/dashboard/_next/static/chunks/main-app-202a5f91ead17fa7.js +1 -0
- package/dist/dashboard/_next/static/chunks/pages/_app-58c3f1a8a070bd35.js +1 -0
- package/dist/dashboard/_next/static/chunks/pages/_error-312a564ec7e2663f.js +1 -0
- package/dist/dashboard/_next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
- package/dist/dashboard/_next/static/chunks/webpack-d6388c5dcd85b0c5.js +1 -0
- package/dist/dashboard/_next/static/css/322e14d06135256b.css +31 -0
- package/dist/dashboard/_next/static/css/7d4d1db5aa137b5a.css +3 -0
- package/dist/dashboard/accuracy.html +1 -0
- package/dist/dashboard/accuracy.txt +7 -0
- package/dist/dashboard/benchmark.html +1 -0
- package/dist/dashboard/benchmark.txt +7 -0
- package/dist/dashboard/context.html +1 -0
- package/dist/dashboard/context.txt +7 -0
- package/dist/dashboard/doctor.html +1 -0
- package/dist/dashboard/doctor.txt +7 -0
- package/dist/dashboard/executions.html +1 -0
- package/dist/dashboard/executions.txt +7 -0
- package/dist/dashboard/graph.html +1 -0
- package/dist/dashboard/graph.txt +7 -0
- package/dist/dashboard/index.html +1 -0
- package/dist/dashboard/index.txt +7 -0
- package/dist/dashboard/knowledge.html +1 -0
- package/dist/dashboard/knowledge.txt +7 -0
- package/dist/dashboard/locales/en.json +335 -0
- package/dist/dashboard/locales/zh.json +335 -0
- package/dist/dashboard/memory.html +1 -0
- package/dist/dashboard/memory.txt +7 -0
- package/dist/dashboard/replay.html +1 -0
- package/dist/dashboard/replay.txt +7 -0
- package/dist/dashboard/runs/_.html +1 -0
- package/dist/dashboard/runs/_.txt +8 -0
- package/dist/dashboard/runs.html +1 -0
- package/dist/dashboard/runs.txt +7 -0
- package/dist/dashboard/settings.html +1 -0
- package/dist/dashboard/settings.txt +7 -0
- package/dist/dashboard/timeline.html +1 -0
- package/dist/dashboard/timeline.txt +7 -0
- package/dist/dashboard/tool-metrics.html +1 -0
- package/dist/dashboard/tool-metrics.txt +7 -0
- package/dist/dashboard/workflows.html +1 -0
- package/dist/dashboard/workflows.txt +7 -0
- package/dist/fallback.html +1 -3
- package/dist/hooks/enforcer-summary.js +6 -0
- package/dist/hooks/hook-client.js +6 -8
- package/dist/hooks/hook-daemon.js +13 -7
- package/dist/hooks/post-tool-use-failure.js +2 -2
- package/dist/hooks/post-tool-use.js +3 -2
- package/dist/hooks/pre-compact.js +3 -2
- package/dist/hooks/pre-tool-use.js +2 -2
- package/dist/hooks/server-bootstrap.js +109 -0
- package/dist/hooks/session-end.js +2 -2
- package/dist/hooks/stop.js +2 -2
- package/dist/hooks/user-prompt-submit.js +2 -2
- package/dist/plugin/.claude-plugin/plugin.json +1 -1
- package/dist/plugin/CLAUDE.md +34 -0
- package/dist/plugin/dist/command-registry.json +297 -0
- package/dist/plugin/dist/hooks/enforcer-summary.js +6 -0
- package/dist/plugin/dist/hooks/hook-client.js +6 -0
- package/dist/plugin/dist/hooks/hook-daemon.js +14 -0
- package/dist/plugin/dist/hooks/post-tool-use-failure.js +2 -0
- package/dist/plugin/dist/hooks/post-tool-use.js +3 -0
- package/dist/plugin/dist/hooks/pre-compact.js +3 -0
- package/dist/plugin/dist/hooks/pre-tool-use.js +2 -0
- package/dist/plugin/dist/hooks/server-bootstrap.js +109 -0
- package/dist/plugin/dist/hooks/session-end.js +2 -0
- package/dist/plugin/dist/hooks/stop.js +2 -0
- package/dist/plugin/dist/hooks/user-prompt-submit.js +2 -0
- package/dist/plugin/dist/skills/devflow:animation/SKILL.md +63 -0
- package/dist/plugin/dist/skills/devflow:context/SKILL.md +90 -0
- package/dist/plugin/dist/skills/devflow:css/SKILL.md +63 -0
- package/dist/plugin/dist/skills/devflow:docker/SKILL.md +67 -0
- package/dist/plugin/dist/skills/devflow:electron/SKILL.md +67 -0
- package/dist/plugin/dist/skills/devflow:git/SKILL.md +67 -0
- package/dist/plugin/dist/skills/devflow:graph/SKILL.md +80 -0
- package/dist/plugin/dist/skills/devflow:graphql/SKILL.md +66 -0
- package/dist/plugin/dist/skills/devflow:knowledge/SKILL.md +80 -0
- package/dist/plugin/dist/skills/devflow:memory/SKILL.md +79 -0
- package/dist/plugin/dist/skills/devflow:nest/SKILL.md +68 -0
- package/dist/plugin/dist/skills/devflow:nextjs/SKILL.md +65 -0
- package/dist/plugin/dist/skills/devflow:performance/SKILL.md +67 -0
- package/dist/plugin/dist/skills/devflow:react/SKILL.md +83 -0
- package/dist/plugin/dist/skills/devflow:tailwind/SKILL.md +65 -0
- package/dist/plugin/dist/skills/devflow:taro/SKILL.md +66 -0
- package/dist/plugin/dist/skills/devflow:ui-layout/SKILL.md +63 -0
- package/dist/plugin/dist/skills/devflow:vue/SKILL.md +72 -0
- package/dist/plugin/dist/skills/devflow:workflow/SKILL.md +80 -0
- package/dist/plugin/hooks/constitution.md +20 -0
- package/dist/plugin/hooks/post-tool-use +20 -0
- package/dist/plugin/hooks/post-tool-use-failure +19 -0
- package/dist/plugin/hooks/pre-compact +19 -0
- package/dist/plugin/hooks/pre-tool-use +23 -0
- package/dist/plugin/hooks/session-end +19 -0
- package/dist/plugin/hooks/session-start +259 -0
- package/dist/plugin/hooks/stop +26 -0
- package/dist/plugin/hooks/user-prompt-submit +19 -0
- package/dist/plugin/package.json +44 -0
- package/package.json +14 -13
- package/plugin-registry.json +30 -46
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import {spawn,execFileSync}from'node:child_process';import {randomUUID}from'node:crypto';import {mkdirSync,writeFileSync,existsSync}from'node:fs';import {request}from'node:http';import {createRequire}from'node:module';import {homedir}from'node:os';import {join}from'node:path';var{DatabaseSync:y}=createRequire(import.meta.url)("node:sqlite"),C=75,x=400,U=2e3,H=300*1e3,W=1e3,B=1e3,F=15e3,Q=["--yes","@devflow-tools/server","--devflow-instance-token"],z=process.env.DEVFLOW_SERVER_BOOTSTRAP_HEALTH_URL??"http://127.0.0.1:13337/api/health";function E(e){let t=e instanceof Error?e.message:String(e);console.error(`[devflow] Server bootstrap skipped: ${t}`);}function $(e){let t=new y(e);t.exec(`PRAGMA busy_timeout = ${C}`);let n=t.prepare(`
|
|
2
|
+
SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'server_bootstrap_state'
|
|
3
|
+
`).get();if(n?.sql&&!n.sql.includes("'terminating'")){t.exec("BEGIN IMMEDIATE");try{t.exec("ALTER TABLE server_bootstrap_state RENAME TO server_bootstrap_state_legacy"),g(t),t.exec(`
|
|
4
|
+
INSERT INTO server_bootstrap_state (
|
|
5
|
+
id, token, state, owner_pid, wrapper_pid, process_group_id, server_pid,
|
|
6
|
+
created_at, updated_at
|
|
7
|
+
)
|
|
8
|
+
SELECT
|
|
9
|
+
id, token, state, owner_pid, wrapper_pid, process_group_id, server_pid,
|
|
10
|
+
created_at, updated_at
|
|
11
|
+
FROM server_bootstrap_state_legacy
|
|
12
|
+
`),t.exec("DROP TABLE server_bootstrap_state_legacy"),t.exec("COMMIT");}catch(r){try{t.exec("ROLLBACK");}catch{}throw r}}else n||g(t);return t}function g(e){e.exec(`
|
|
13
|
+
CREATE TABLE IF NOT EXISTS server_bootstrap_state (
|
|
14
|
+
id INTEGER PRIMARY KEY CHECK (id = 1),
|
|
15
|
+
token TEXT NOT NULL,
|
|
16
|
+
state TEXT NOT NULL CHECK (state IN ('launching', 'running', 'terminating')),
|
|
17
|
+
owner_pid INTEGER NOT NULL,
|
|
18
|
+
wrapper_pid INTEGER,
|
|
19
|
+
process_group_id INTEGER,
|
|
20
|
+
server_pid INTEGER,
|
|
21
|
+
created_at INTEGER NOT NULL,
|
|
22
|
+
updated_at INTEGER NOT NULL
|
|
23
|
+
)
|
|
24
|
+
`);}function K(e){return e.prepare(`
|
|
25
|
+
SELECT
|
|
26
|
+
token,
|
|
27
|
+
state,
|
|
28
|
+
owner_pid AS ownerPid,
|
|
29
|
+
wrapper_pid AS wrapperPid,
|
|
30
|
+
process_group_id AS processGroupId,
|
|
31
|
+
server_pid AS serverPid,
|
|
32
|
+
created_at AS createdAt,
|
|
33
|
+
updated_at AS updatedAt
|
|
34
|
+
FROM server_bootstrap_state
|
|
35
|
+
WHERE id = 1
|
|
36
|
+
`).get()}function c(e){return Number(e.changes)}function q(e){if(!Number.isSafeInteger(e)||e<=1)return false;try{return process.kill(e,0),!0}catch{return false}}function A(){let e=execFileSync("ps",["-axo","pid=,pgid=,command="],{encoding:"utf8",stdio:["ignore","pipe","ignore"],timeout:500}),t=[];for(let n of e.split(`
|
|
37
|
+
`)){let r=n.match(/^\s*(\d+)\s+(\d+)\s+(.+)$/);if(!r)continue;let o=Number(r[1]),a=Number(r[2]);!Number.isSafeInteger(o)||!Number.isSafeInteger(a)||t.push({pid:o,processGroupId:a,command:r[3]});}return t}function V(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function v(e,t){let n=V(t);return new RegExp(`(?:^|\\s)--devflow-instance-token(?:=|\\s+)${n}(?:\\s|$)`).test(e)}function P(e){return /(?:@devflow-tools\/server|devflow-server)/.test(e)}function Y(e){let t=A().filter(r=>P(r.command)&&v(r.command,e)),n=new Map;for(let r of t){let o=n.get(r.processGroupId)??[];o.push(r),n.set(r.processGroupId,o);}return [...n.entries()].map(([r,o])=>({processGroupId:r,processes:o})).sort((r,o)=>o.processes.length-r.processes.length)}function w(e,t){return Y(e).find(n=>t===void 0||n.processGroupId===t)}function d(e,t){let n=m(e,t);if(!n)return;let r=n.processes.find(o=>o.pid!==n.wrapperPid&&o.command.includes("devflow-server"));if(r)return {wrapperPid:n.wrapperPid,processGroupId:n.processGroupId,serverPid:r.pid,processes:n.processes}}function m(e,t){let n=w(e,t);if(!n)return;let r=n.processes.find(o=>o.pid===n.processGroupId&&o.command.includes("@devflow-tools/server"));if(r)return {wrapperPid:r.pid,processGroupId:r.processGroupId,processes:n.processes}}function _(e){if(!q(e))return false;try{return execFileSync("ps",["-p",String(e),"-o","command="],{encoding:"utf8",stdio:["ignore","pipe","ignore"],timeout:250}).trim().includes("server-bootstrap")}catch{return false}}function X(){return new Promise(e=>{let t=false,n=r=>{t||(t=true,e(r));};try{let r=request(z,{method:"GET",timeout:x},o=>{o.resume(),n((o.statusCode??500)>=200&&(o.statusCode??500)<300);});r.on("timeout",()=>r.destroy(new Error("health timeout"))),r.on("error",()=>n(!1)),r.end();}catch{n(false);}})}async function j(e){let t=false;try{e.exec("BEGIN IMMEDIATE"),t=!0;let n=await X(),r=K(e);if(n){if(r?.state==="running"||r?.state==="launching"){let s=d(r.token,r.processGroupId??void 0);s?e.prepare(`
|
|
38
|
+
UPDATE server_bootstrap_state
|
|
39
|
+
SET state = 'running', owner_pid = ?, wrapper_pid = ?, process_group_id = ?, server_pid = ?,
|
|
40
|
+
updated_at = ?
|
|
41
|
+
WHERE id = 1 AND token = ? AND state = ?
|
|
42
|
+
`).run(process.pid,s.wrapperPid,s.processGroupId,s.serverPid,Date.now(),r.token,r.state):r.state==="running"&&e.prepare(`
|
|
43
|
+
DELETE FROM server_bootstrap_state
|
|
44
|
+
WHERE id = 1 AND token = ? AND state = 'running'
|
|
45
|
+
`).run(r.token);}return e.exec("COMMIT"),t=!1,{action:"skip"}}if(r?.state==="launching"){if(_(r.ownerPid))return e.exec("COMMIT"),t=!1,{action:"skip"};let s=r.processGroupId??void 0,i=d(r.token,s);if(i){let f=e.prepare(`
|
|
46
|
+
UPDATE server_bootstrap_state
|
|
47
|
+
SET state = 'running', owner_pid = ?, wrapper_pid = ?, process_group_id = ?,
|
|
48
|
+
server_pid = ?, updated_at = ?
|
|
49
|
+
WHERE id = 1 AND token = ? AND state = 'launching' AND owner_pid = ?
|
|
50
|
+
`).run(process.pid,i.wrapperPid,i.processGroupId,i.serverPid,Date.now(),r.token,r.ownerPid);if(c(f)!==1)throw new Error("launch intent changed before adoption");return e.exec("COMMIT"),t=!1,console.error(`[devflow] Adopted server process group ${i.processGroupId}`),{action:"skip"}}let p=m(r.token,s);if(p&&Date.now()-r.createdAt<H)return e.exec("COMMIT"),t=!1,{action:"skip"};if(p){let f=e.prepare(`
|
|
51
|
+
UPDATE server_bootstrap_state
|
|
52
|
+
SET state = 'terminating', owner_pid = ?, process_group_id = ?, updated_at = ?
|
|
53
|
+
WHERE id = 1 AND token = ? AND state = 'launching' AND owner_pid = ?
|
|
54
|
+
`).run(process.pid,p.processGroupId,Date.now(),r.token,r.ownerPid);if(c(f)!==1)throw new Error("launch intent changed before cleanup claim");return e.exec("COMMIT"),t=!1,{action:"cleanup",token:r.token,processGroupId:p.processGroupId}}e.prepare(`
|
|
55
|
+
DELETE FROM server_bootstrap_state
|
|
56
|
+
WHERE id = 1 AND token = ? AND state = 'launching' AND owner_pid = ?
|
|
57
|
+
`).run(r.token,r.ownerPid);}else if(r?.state==="terminating"){if(_(r.ownerPid))return e.exec("COMMIT"),t=!1,{action:"skip"};let s=w(r.token);if(s){let i=e.prepare(`
|
|
58
|
+
UPDATE server_bootstrap_state
|
|
59
|
+
SET owner_pid = ?, process_group_id = ?, updated_at = ?
|
|
60
|
+
WHERE id = 1 AND token = ? AND state = 'terminating' AND owner_pid = ?
|
|
61
|
+
`).run(process.pid,s.processGroupId,Date.now(),r.token,r.ownerPid);if(c(i)!==1)throw new Error("cleanup ownership changed during recovery");return e.exec("COMMIT"),t=!1,{action:"cleanup",token:r.token,processGroupId:s.processGroupId}}e.prepare(`
|
|
62
|
+
DELETE FROM server_bootstrap_state
|
|
63
|
+
WHERE id = 1 AND token = ? AND state = 'terminating' AND owner_pid = ?
|
|
64
|
+
`).run(r.token,r.ownerPid);}else if(r?.state==="running"){let s=d(r.token);if(s)return e.prepare(`
|
|
65
|
+
UPDATE server_bootstrap_state
|
|
66
|
+
SET owner_pid = ?, wrapper_pid = ?, process_group_id = ?, server_pid = ?, updated_at = ?
|
|
67
|
+
WHERE id = 1 AND token = ? AND state = 'running'
|
|
68
|
+
`).run(process.pid,s.wrapperPid,s.processGroupId,s.serverPid,Date.now(),r.token),e.exec("COMMIT"),t=!1,{action:"skip"};let i=w(r.token);if(i&&!_(r.ownerPid)){let p=e.prepare(`
|
|
69
|
+
UPDATE server_bootstrap_state
|
|
70
|
+
SET state = 'terminating', owner_pid = ?, process_group_id = ?, updated_at = ?
|
|
71
|
+
WHERE id = 1 AND token = ? AND state = 'running' AND owner_pid = ?
|
|
72
|
+
`).run(process.pid,i.processGroupId,Date.now(),r.token,r.ownerPid);if(c(p)!==1)throw new Error("running cleanup ownership changed");return e.exec("COMMIT"),t=!1,{action:"cleanup",token:r.token,processGroupId:i.processGroupId}}e.prepare(`
|
|
73
|
+
DELETE FROM server_bootstrap_state
|
|
74
|
+
WHERE id = 1 AND token = ? AND state = 'running' AND owner_pid = ?
|
|
75
|
+
`).run(r.token,r.ownerPid);}let o=randomUUID(),a=Date.now();return e.prepare(`
|
|
76
|
+
INSERT INTO server_bootstrap_state (
|
|
77
|
+
id, token, state, owner_pid, wrapper_pid, process_group_id, server_pid,
|
|
78
|
+
created_at, updated_at
|
|
79
|
+
) VALUES (1, ?, 'launching', ?, NULL, NULL, NULL, ?, ?)
|
|
80
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
81
|
+
token = excluded.token,
|
|
82
|
+
state = 'launching',
|
|
83
|
+
owner_pid = excluded.owner_pid,
|
|
84
|
+
wrapper_pid = NULL,
|
|
85
|
+
process_group_id = NULL,
|
|
86
|
+
server_pid = NULL,
|
|
87
|
+
created_at = excluded.created_at,
|
|
88
|
+
updated_at = excluded.updated_at
|
|
89
|
+
`).run(o,process.pid,a,a),e.exec("COMMIT"),t=!1,{action:"launch",token:o}}finally{if(t)try{e.exec("ROLLBACK");}catch{}}}function J(e){return new Promise((t,n)=>{let r;try{r=spawn("npx",[...Q,e],{detached:!0,env:process.env,stdio:["ignore","inherit","inherit"]});}catch(o){n(o);return}r.once("spawn",()=>t(r)),r.once("error",n);})}async function u(e,t){let n=Date.now()+t;for(;Date.now()<n;){if(e())return true;await new Promise(r=>setTimeout(r,10));}return e()}async function h(e){let t=process.env[e];if(!t)return;writeFileSync(t,`${process.pid}
|
|
90
|
+
`);let n=process.env.DEVFLOW_SERVER_BOOTSTRAP_TEST_CONTINUE_FILE;if(!n)return;if(!await u(()=>existsSync(n),F))throw new Error(`test checkpoint timed out: ${e}`)}async function Z(e,t){let n;return await u(()=>{let o=d(e,t);return o?(n=o,true):false},U)?n:void 0}function ee(e,t,n){let r=false;try{e.exec("BEGIN IMMEDIATE"),r=!0;let o=e.prepare(`
|
|
91
|
+
UPDATE server_bootstrap_state
|
|
92
|
+
SET wrapper_pid = ?, process_group_id = ?, server_pid = NULL, updated_at = ?
|
|
93
|
+
WHERE id = 1 AND token = ? AND state = 'launching' AND owner_pid = ?
|
|
94
|
+
`).run(n.wrapperPid,n.processGroupId,Date.now(),t,process.pid);if(c(o)!==1)throw new Error("launch intent ownership changed before wrapper persistence");e.exec("COMMIT"),r=!1;}finally{if(r)try{e.exec("ROLLBACK");}catch{}}}function re(e,t,n){let r=false;try{e.exec("BEGIN IMMEDIATE"),r=!0;let o=e.prepare(`
|
|
95
|
+
UPDATE server_bootstrap_state
|
|
96
|
+
SET state = 'running', wrapper_pid = ?, process_group_id = ?, server_pid = ?,
|
|
97
|
+
updated_at = ?
|
|
98
|
+
WHERE id = 1 AND token = ? AND state = 'launching' AND owner_pid = ?
|
|
99
|
+
`).run(n.wrapperPid,n.processGroupId,n.serverPid,Date.now(),t,process.pid);if(c(o)!==1)throw new Error("launch intent ownership changed before promotion");e.exec("COMMIT"),r=!1;}finally{if(r)try{e.exec("ROLLBACK");}catch{}}}function te(e,t){let n=false;try{e.exec("BEGIN IMMEDIATE"),n=!0,e.prepare(`
|
|
100
|
+
DELETE FROM server_bootstrap_state
|
|
101
|
+
WHERE id = 1 AND token = ? AND state = 'launching' AND owner_pid = ?
|
|
102
|
+
`).run(t,process.pid),e.exec("COMMIT"),n=!1;}finally{if(n)try{e.exec("ROLLBACK");}catch{}}}function ne(e,t,n){let r=false;try{e.exec("BEGIN IMMEDIATE"),r=!0;let o=e.prepare(`
|
|
103
|
+
UPDATE server_bootstrap_state
|
|
104
|
+
SET state = 'terminating', owner_pid = ?, updated_at = ?
|
|
105
|
+
WHERE id = 1 AND token = ? AND state = 'launching' AND owner_pid = ?
|
|
106
|
+
`).run(process.pid,Date.now(),t,n);return e.exec("COMMIT"),r=!1,c(o)===1}finally{if(r)try{e.exec("ROLLBACK");}catch{}}}function oe(e,t){let n=false;try{e.exec("BEGIN IMMEDIATE"),n=!0;let r=e.prepare(`
|
|
107
|
+
DELETE FROM server_bootstrap_state
|
|
108
|
+
WHERE id = 1 AND token = ? AND state = 'terminating' AND owner_pid = ?
|
|
109
|
+
`).run(t,process.pid);return e.exec("COMMIT"),n=!1,c(r)===1}finally{if(n)try{e.exec("ROLLBACK");}catch{}}}function l(e){return A().filter(t=>t.processGroupId===e)}function S(e,t){return l(e).some(n=>P(n.command)&&v(n.command,t))}async function se(e,t){if(!S(e,t))return false;console.error(`[devflow] Terminating untracked server process group ${e}`);try{process.kill(-e,"SIGTERM");}catch{}if(await u(()=>l(e).length===0,W))return true;if(!S(e,t))return false;try{process.kill(-e,"SIGKILL");}catch{}return u(()=>l(e).length===0,B)}async function D(e,t,n){return l(n).length===0||await se(n,t)?oe(e,t):false}async function ie(){let e=join(homedir(),".devflow");mkdirSync(e,{recursive:true});let t=$(join(e,"server-bootstrap.sqlite")),n,r,o=false;try{for(;;){let i=await j(t);if(i.action==="skip")return;if(i.action==="cleanup"){if(!await D(t,i.token,i.processGroupId))throw new Error("claimed server process group cleanup did not complete");continue}n=i.token;break}if(await h("DEVFLOW_SERVER_BOOTSTRAP_TEST_INTENT_READY_FILE"),r=await J(n),!r.pid)throw new Error("npx launched without a PID");let a=r.pid,s=await Z(n,a);if(!s){let i=m(n,a);if(!i)throw new Error("npx process group ownership could not be validated");ee(t,n,i),r.unref(),console.error(`[devflow] Server package launch still warming (PID ${i.wrapperPid})`);return}await h("DEVFLOW_SERVER_BOOTSTRAP_TEST_AFTER_SPAWN_READY_FILE"),re(t,n,s),o=!0,r.unref(),console.error(`[devflow] Server starting in background (PID ${s.wrapperPid})`);}catch(a){if(n&&r?.pid&&!o){let s=false;try{s=ne(t,n,process.pid);}catch(i){E(i);}s?await D(t,n,r.pid)||console.error(`[devflow] Server process group ${r.pid} cleanup did not complete`):(console.error(`[devflow] Server cleanup claim lost for token ${n}`),r.unref());}else if(n&&!r)try{te(t,n);}catch(s){E(s);}throw a}finally{try{t.close();}catch{}}}ie().catch(E).then(()=>{process.exitCode=0;},()=>{process.exitCode=0;});
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export{
|
|
1
|
+
import {request}from'http';import {existsSync,readFileSync,readdirSync,unlinkSync,mkdirSync,writeFileSync}from'fs';import {join}from'path';import {createHash}from'crypto';import {getLocalApiKey,getProjectStateDir}from'@devflow-tools/sdk';import {openGlobalDevFlowDatabase}from'@devflow-tools/database';import {homedir}from'os';import {MemoryGate}from'@devflow-tools/memory-engine';function b(i){return i??process.env.CLAUDE_PROJECT_DIR??process.cwd()}function I(i){return process.env.DEVFLOW_STATE_DIR??getProjectStateDir(b(i))}var O=1e4,B=3e4,g=500;function G(i,t,e){return new Promise(n=>{try{let r=new URL(i),o=request({hostname:r.hostname,port:r.port||80,path:r.pathname+r.search,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":e,"Content-Length":Buffer.byteLength(t)},timeout:5e3},s=>{let l=[];s.on("data",a=>l.push(a)),s.on("end",()=>{let a=Buffer.concat(l).toString();n(s.statusCode!=null&&s.statusCode>=200&&s.statusCode<300?a:null);});});o.on("error",()=>n(null)),o.on("timeout",()=>{o.destroy(),n(null);}),o.write(t),o.end();}catch{n(null);}})}var y=class{constructor(t){this.retryScheduled=false;this.apiUrl=t?.apiUrl??process.env.DEVFLOW_API_URL??"http://127.0.0.1:13337",this.apiKey=t?.apiKey??getLocalApiKey(),this.cacheDir=t?.cacheDir??join(process.env.DEVFLOW_STATE_DIR??join(homedir(),".devflow","global"),"telemetry-cache"),this.legacyCacheDir=t?.legacyCacheDir??(t?.cacheDir?null:join(homedir(),".devflow","telemetry-cache")),this.database=t?.database??null,this.ownsDatabase=!t?.database;}async sendEvent(t){let e={...t,input:this.truncateInput(t.input)};return this.commitOrCache("tool_call",e)?(this.postHttp("/api/telemetry/tool-call",e),t.eventId):null}async sendExecutionStart(t,e,n,r){let o={executionId:t,sessionId:e,skillName:n,startedAt:r};this.commitOrCache("execution_start",o)&&this.postHttp("/api/telemetry/skill-execution/start",o);}async sendSessionStart(t,e,n){let r={id:t,projectRoot:e,startedAt:n,label:e.split("/").pop()??"unknown"},o=this.commitOrCache("session_start",r);return o&&this.postHttp("/api/telemetry/sessions",r),o}async completeEvent(t){let e=this.commitOrCache("complete_event",t);return e&&(this.getDatabase().aggregatePendingToolMetrics(),this.postHttp("/api/telemetry/tool-call/output",t)),e}async endSession(t,e=Date.now()){let n={sessionId:t,finishedAt:e},r=this.commitOrCache("session_end",n);return r&&(this.getDatabase().aggregatePendingToolMetrics(),this.postHttp(`/api/telemetry/sessions/${encodeURIComponent(t)}/close`,{finishedAt:e})),r}async flushCache(){try{let n=this.getDatabase(),r=n.listTelemetryFailures({unresolvedOnly:!0,limit:g}).reverse();for(let o of r)try{this.applyOperation(o.operation,o.payload),n.resolveTelemetryFailure(o.id);}catch{}n.trimTelemetryFailures(g);}catch{}let e=[...new Set([this.cacheDir,this.legacyCacheDir].filter(n=>!!n))].filter(n=>existsSync(n)).flatMap(n=>readdirSync(n).filter(r=>r.endsWith(".json")).map(r=>{let o=join(n,r);try{return {cacheFile:o,envelope:J(JSON.parse(readFileSync(o,"utf8")),r)}}catch{return null}})).filter(n=>n!==null).sort((n,r)=>n.envelope.timestamp-r.envelope.timestamp||P(n.envelope.operation)-P(r.envelope.operation));for(let{cacheFile:n,envelope:r}of e)try{let o=this.getDatabase();o.insertTelemetryFailure({id:r.id,operation:r.operation,payload:r.payload,error:r.failure,createdAt:r.timestamp}),this.applyOperation(r.operation,r.payload),o.resolveTelemetryFailure(r.id),unlinkSync(n);}catch{}this.database?.aggregatePendingToolMetrics();}aggregateMetrics(){return this.getDatabase().aggregatePendingToolMetrics()}async flushAndAggregate(){await this.flushCache(),this.aggregateMetrics();}close(){this.ownsDatabase&&this.database?.close(),this.database=null;}getDatabase(){return this.database??=openGlobalDevFlowDatabase(),this.database}commitOrCache(t,e){try{return this.applyOperation(t,e),!0}catch(n){return this.cacheOperation(t,e,n),false}}applyOperation(t,e){let n=this.getDatabase();switch(t){case "tool_call":n.insertToolCallEvent(e);return;case "execution_start":n.insertSkillExecution({executionId:e.executionId,sessionId:e.sessionId,skillName:e.skillName,startedAt:e.startedAt,status:"running"});return;case "session_start":n.insertSession(e),n.insertRun({id:M(e.id),source:"hook",tool:"session",input:{projectRoot:e.projectRoot},status:"active",startedAt:e.startedAt,tokenUsed:0,metadata:{sessionId:e.id,projectRoot:e.projectRoot}});return;case "complete_event":if(!n.updateToolCallEvent(e.eventId,{output:e.output===void 0?void 0:JSON.stringify(e.output),error:e.error,duration:e.duration}))throw new Error(`Tool call event ${e.eventId} is not available for completion`);return;case "session_end":n.closeSession(e.sessionId,e.finishedAt),n.updateRun(M(e.sessionId),{status:"completed",finishedAt:e.finishedAt});return}}cacheOperation(t,e,n){let r=Date.now(),o={id:`failure:${r}:${Math.random().toString(36).slice(2,11)}`,operation:t,payload:e,failure:n instanceof Error?n.message:String(n),timestamp:r};try{let s=this.getDatabase();s.insertTelemetryFailure({id:o.id,operation:t,payload:e,error:o.failure,createdAt:r}),s.trimTelemetryFailures(g),this.scheduleRetry();return}catch{}try{existsSync(this.cacheDir)||mkdirSync(this.cacheDir,{recursive:!0});let s=join(this.cacheDir,`${r}_${Math.random().toString(36).slice(2,11)}.json`);writeFileSync(s,JSON.stringify(o,null,2),{mode:384}),this.trimCompatibilityCache(),this.scheduleRetry();}catch{}}trimCompatibilityCache(){try{let t=readdirSync(this.cacheDir).filter(e=>e.endsWith(".json")).sort();for(let e of t.slice(0,Math.max(0,t.length-g)))unlinkSync(join(this.cacheDir,e));}catch{}}scheduleRetry(){this.retryScheduled||(this.retryScheduled=true,setTimeout(()=>{this.retryScheduled=false,this.flushCache();},B).unref());}postHttp(t,e){G(`${this.apiUrl}${t}`,JSON.stringify(e),this.apiKey);}truncateInput(t){let e=JSON.stringify(t);return e===void 0||e.length<=O?t:{_truncated:true,_original_size:e.length,_preview:`${e.substring(0,O)}...`}}};function P(i){return ["session_start","execution_start","tool_call","complete_event","session_end"].indexOf(i)}function M(i){return `hook-run:${i}`}function J(i,t){if(!i||typeof i!="object")throw new Error("Invalid telemetry cache envelope");let e=i;if(typeof e.operation=="string"&&e.payload!==void 0)return e;let n=e.type==="tool_call"?"tool_call":e.type==="execution_start"?"execution_start":null;if(!n)throw new Error("Unknown legacy telemetry cache operation");let r=e.payload??{},o=Number(r.timestamp??r.startedAt??Date.now());return {id:`legacy-cache:${t}`,operation:n,payload:r,failure:"Replayed legacy HTTP-first telemetry cache entry",timestamp:o}}async function F(i){let t=!i.memory,e=i.memory??new MemoryGate(i.projectRoot),n=0,r=0;try{await e.forceWarmUp(),i.trigger==="session_end"&&(n=await e.releasePendingDistillLeases(i.sessionId)),r=e.getPendingEventCount();}finally{t&&e.close();}let o={pendingEvents:r,releasedLeases:n,trigger:i.trigger,sessionId:i.sessionId};try{let s=openGlobalDevFlowDatabase();try{let l=Date.now(),a=`distill:${l}:${Math.random().toString(36).slice(2,10)}`;s.recordMemoryDistillCheckpoint({id:a,projectRoot:i.projectRoot,sessionId:i.sessionId,trigger:i.trigger,pendingEvents:r,releasedLeases:n,createdAt:l}),s.insertEvent({kind:"memory_distill_requested",timestamp:l,success:!0,metadata:{...o,projectRoot:i.projectRoot}});}finally{s.close();}}catch{}return o}var ee=process.env.DEVFLOW_SERVER_URL||"http://127.0.0.1:13337",te=getLocalApiKey();function ne(i,t){return new Promise(e=>{let n=JSON.stringify(t),r=new URL(i,ee),o=request({hostname:r.hostname,port:r.port,path:r.pathname,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":te,"Content-Length":Buffer.byteLength(n)},timeout:5e3},()=>e());o.on("error",()=>e()),o.write(n),o.end();})}function _(i){let t=I(i),e=createHash("sha256").update(i).digest("hex").slice(0,12);return [join(t,`session-id-${e}`),join(t,"current-execution-id"),join(t,"current-skill.json"),join(t,"event-map.json")]}function re(i){try{let t=_(i)[0];if(existsSync(t))return readFileSync(t,"utf-8").trim()}catch{}return null}function ie(i){for(let t of _(i))try{existsSync(t)&&unlinkSync(t);}catch{}}async function oe(i,t=b(),e=true,n){let r;try{r=JSON.parse(i);}catch{return}let o=r.session_id||re(t);if(!o)return;let s=n?.telemetry??new y,l=!n?.telemetry;try{try{await s.flushAndAggregate();}catch{}let a;try{a=openGlobalDevFlowDatabase();let L=a.listToolCallEventsBySession(o),C=_(t)[1];if(e&&existsSync(C)){let p="";try{p=readFileSync(C,"utf-8").trim();}catch{}if(p){let h=L.filter(m=>m.executionId===p),c=h.length,d=h.filter(m=>m.isMcpTool).length,T=c-d,w=h.filter(m=>m.toolType==="subagent").length,v=h.map(m=>m.timestamp).filter(Boolean),E=v.length>=2?Math.max(...v)-Math.min(...v):0;try{a.updateSkillExecution(p,{status:"completed",finishedAt:Date.now(),totalToolCalls:c,mcpToolCalls:d,directToolCalls:T,subagentCount:w,totalDuration:E,mcpComplianceRate:c>0?Math.round(d/c*1e4)/100:0}),await ne("/api/telemetry/skill-execution/complete",{executionId:p,finishedAt:Date.now(),status:"completed",summary:{totalToolCalls:c,mcpToolCalls:d,directToolCalls:T,subagentCount:w,totalDuration:E,mcpComplianceRate:c>0?Math.round(d/c*1e4)/100:0}});}catch{}}}e&&a.deleteHookReceipt(t);}catch{}finally{a?.close();}try{await F({projectRoot:t,sessionId:o,trigger:"session_end",memory:n?.memory});}catch{}try{await s.endSession(o),await s.flushAndAggregate();}catch{}}finally{l&&s.close(),e&&ie(t);}}if(process.argv[1]?.endsWith("session-end")||process.argv[1]?.endsWith("session-end.js")){let i="";process.stdin.setEncoding("utf8"),process.stdin.on("data",t=>{i+=t;}),process.stdin.on("end",async()=>{await oe(i.trim()||process.argv[2]||""),process.exit(0);}),process.stdin.on("error",()=>process.exit(0)),setTimeout(()=>process.exit(0),1e4).unref();}
|
|
2
|
+
export{oe as handleSessionEnd};
|
package/dist/hooks/stop.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {request}from'http';import {existsSync,readFileSync}from'fs';import {join}from'path';import {homedir}from'os';var
|
|
2
|
-
export{
|
|
1
|
+
import {request}from'http';import {existsSync,readFileSync}from'fs';import {join}from'path';import {homedir}from'os';import {createHash}from'crypto';import {getLocalApiKey}from'@devflow-tools/sdk';var h=process.env.DEVFLOW_SERVER_URL||"http://127.0.0.1:13337",f=getLocalApiKey();function _(t,e){return new Promise(o=>{let r=JSON.stringify(e),n=new URL(t,h),s=request({hostname:n.hostname,port:n.port,path:n.pathname,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":f,"Content-Length":Buffer.byteLength(r)},timeout:5e3},()=>o());s.on("error",()=>o()),s.write(r),s.end();})}var S=join(homedir(),".devflow"),g=process.env.CLAUDE_PROJECT_DIR||process.cwd(),E=createHash("sha256").update(g).digest("hex").slice(0,12),i=join(S,`session-id-${E}`);function R(){try{if(existsSync(i))return readFileSync(i,"utf-8").trim()}catch{}return null}async function y(t){let e;try{e=JSON.parse(t);}catch{return null}if(e.stop_hook_active)return null;let o=R();return o&&_(`/api/telemetry/sessions/${encodeURIComponent(o)}/tick`,{timestamp:Date.now()}).catch(()=>{}),null}if(process.argv[1]?.endsWith("stop")||process.argv[1]?.endsWith("stop.js")){let t="";process.stdin.setEncoding("utf8"),process.stdin.on("data",e=>{t+=e;}),process.stdin.on("end",async()=>{await y(t.trim()||process.argv[2]||""),process.exit(0);}),process.stdin.on("error",()=>process.exit(0)),setTimeout(()=>process.exit(0),4e3).unref();}
|
|
2
|
+
export{y as handleStop};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export{
|
|
1
|
+
import {createHash}from'node:crypto';import {mkdirSync,appendFileSync}from'node:fs';import {homedir}from'node:os';import {dirname,join}from'node:path';import {MemoryGate}from'@devflow-tools/memory-engine';import'@devflow-tools/database';var g=/(?:^|[.!?。!?]\s*)(?:(?:please\s+)?(?:remember|memorize)\b|(?:请记|(?:请)?记住))/iu,D=/\b(?:(?:do\s+not|don't|dont|never|not)(?:\s+need\s+to)?|no\s+need\s+to)\s+(?:please\s+)?(?:remember|memorize)\b|(?:不要|别|不用|无需|不必|不需要)(?:再)?(?:记住|记|记忆)/iu;function c(e){let t=e.trim();return t&&g.test(t)&&!D.test(t)?t:null}function S(e){let t=createHash("sha256").update(e).digest("hex").slice(0,16),n=process.env.DEVFLOW_STATE_DIR||join(homedir(),".devflow","state",t);return join(n,"memory-intents.jsonl")}function a(e,t){let n=S(e);mkdirSync(dirname(n),{recursive:true}),appendFileSync(n,`${JSON.stringify(t)}
|
|
2
|
+
`,{mode:384});}var m="WARNING: DevFlow is in degraded mode (daemon unreachable): 4-Gate enforcement and memory prefetch cache are unavailable. Run `devflow doctor` for details.";function u(){return process.env.DEVFLOW_HOOK_DEGRADED==="1"}var p=process.env.CLAUDE_PROJECT_DIR||process.cwd();async function I(e){let t=u()?{additionalContext:m}:{},n;try{n=JSON.parse(e);}catch{return {hookSpecificOutput:{hookEventName:"UserPromptSubmit",permissionDecision:"allow",...t}}}let r=n.prompt||"";if(!r.trim())return {hookSpecificOutput:{hookEventName:"UserPromptSubmit",permissionDecision:"allow",...t}};let s=c(r);if(s)try{a(p,{content:s,sessionId:n.session_id,createdAt:Date.now()});}catch{}let o=new MemoryGate(p);try{await o.forceWarmUp(),await o.recordUserMessage(r.slice(0,2e3));}catch{}finally{o.close();}return {hookSpecificOutput:{hookEventName:"UserPromptSubmit",permissionDecision:"allow",...t}}}if(process.argv[1]?.endsWith("user-prompt-submit")||process.argv[1]?.endsWith("user-prompt-submit.js")){let e="";process.stdin.setEncoding("utf8"),process.stdin.on("data",t=>{e+=t;}),process.stdin.on("end",async()=>{let t=await I(e.trim()||process.argv[2]||"");console.log(JSON.stringify(t)),process.exit(0);}),process.stdin.on("error",()=>{console.log(JSON.stringify({hookSpecificOutput:{hookEventName:"UserPromptSubmit",permissionDecision:"allow"}})),process.exit(0);}),setTimeout(()=>{console.log(JSON.stringify({hookSpecificOutput:{hookEventName:"UserPromptSubmit",permissionDecision:"allow"}})),process.exit(0);},3e4).unref();}export{I as handleUserPromptSubmit};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "devflow",
|
|
3
3
|
"description": "DevFlow \u2014 Developer Intelligence Platform: project context, code graph, knowledge base, memory engine, and workflow automation with 14 domain plugins",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.16.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "DevFlow"
|
|
7
7
|
},
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# DevFlow Plugin for Claude Code
|
|
2
|
+
|
|
3
|
+
This plugin provides the DevFlow developer intelligence platform inside Claude Code.
|
|
4
|
+
|
|
5
|
+
## What You Get
|
|
6
|
+
|
|
7
|
+
- **Context Engine** — Search code by natural language query. Use `/devflow:context` before making any code change.
|
|
8
|
+
- **Graph Engine** — View architecture layers, file groups, and dependency graphs. Use `/devflow:graph` to understand module structure.
|
|
9
|
+
- **Memory Engine** — Access project conventions, tech stack, and past decisions. Use `/devflow:memory` at the start of every task.
|
|
10
|
+
- **Knowledge Engine** — Search official docs for React, Vue, NestJS, TypeScript, and more. Use `/devflow:knowledge` when unsure about API usage.
|
|
11
|
+
- **Workflow Engine** — Run standardized development workflows (bug fixes, features, reviews). Use `/devflow:workflow` for complex multi-step tasks.
|
|
12
|
+
- **Domain Plugins** — Specialized expertise for 14 frameworks/tools via `/devflow:react`, `/devflow:git`, `/devflow:nextjs`, etc.
|
|
13
|
+
|
|
14
|
+
## How to Use
|
|
15
|
+
|
|
16
|
+
1. **Before any code change:** `/devflow:context` to understand the current implementation
|
|
17
|
+
2. **Before writing new code:** `/devflow:memory` to check conventions
|
|
18
|
+
3. **When stuck on API:** `/devflow:knowledge` to search docs
|
|
19
|
+
4. **When debugging:** `/devflow:graph` to trace dependencies
|
|
20
|
+
5. **For complex workflows:** `/devflow:workflow` or domain-specific commands like `/devflow:react`
|
|
21
|
+
|
|
22
|
+
## Architecture
|
|
23
|
+
|
|
24
|
+
This plugin is a thin skill layer. The real work happens in:
|
|
25
|
+
- `devflow-mcp` — MCP stdio server (auto-started by this plugin)
|
|
26
|
+
- `devflow` CLI — Command-line interface for direct usage
|
|
27
|
+
|
|
28
|
+
## Project Setup
|
|
29
|
+
|
|
30
|
+
If DevFlow hasn't been initialized in the current project yet, run:
|
|
31
|
+
```
|
|
32
|
+
devflow init
|
|
33
|
+
devflow index
|
|
34
|
+
```
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"commands": {
|
|
4
|
+
"devflow:context": {
|
|
5
|
+
"mcpTools": [
|
|
6
|
+
"get_project_context",
|
|
7
|
+
"search_symbol"
|
|
8
|
+
],
|
|
9
|
+
"blockedNative": [
|
|
10
|
+
"grep",
|
|
11
|
+
"find",
|
|
12
|
+
"rg",
|
|
13
|
+
"ag",
|
|
14
|
+
"Grep",
|
|
15
|
+
"Glob",
|
|
16
|
+
"Explore",
|
|
17
|
+
"WebSearch",
|
|
18
|
+
"WebFetch"
|
|
19
|
+
]
|
|
20
|
+
},
|
|
21
|
+
"devflow:graph": {
|
|
22
|
+
"mcpTools": [
|
|
23
|
+
"get_dependency_graph"
|
|
24
|
+
],
|
|
25
|
+
"blockedNative": [
|
|
26
|
+
"grep",
|
|
27
|
+
"find",
|
|
28
|
+
"rg",
|
|
29
|
+
"ag",
|
|
30
|
+
"Grep",
|
|
31
|
+
"Glob",
|
|
32
|
+
"Explore"
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
"devflow:knowledge": {
|
|
36
|
+
"mcpTools": [
|
|
37
|
+
"get_knowledge"
|
|
38
|
+
],
|
|
39
|
+
"blockedNative": [
|
|
40
|
+
"WebSearch",
|
|
41
|
+
"WebFetch"
|
|
42
|
+
]
|
|
43
|
+
},
|
|
44
|
+
"devflow:memory": {
|
|
45
|
+
"mcpTools": [
|
|
46
|
+
"get_memory"
|
|
47
|
+
],
|
|
48
|
+
"blockedNative": [
|
|
49
|
+
"grep",
|
|
50
|
+
"find",
|
|
51
|
+
"rg",
|
|
52
|
+
"ag",
|
|
53
|
+
"Grep",
|
|
54
|
+
"Glob",
|
|
55
|
+
"Explore"
|
|
56
|
+
]
|
|
57
|
+
},
|
|
58
|
+
"devflow:workflow": {
|
|
59
|
+
"mcpTools": [
|
|
60
|
+
"run_workflow"
|
|
61
|
+
],
|
|
62
|
+
"blockedNative": []
|
|
63
|
+
},
|
|
64
|
+
"devflow:animation": {
|
|
65
|
+
"mcpTools": [
|
|
66
|
+
"animation_suggest"
|
|
67
|
+
],
|
|
68
|
+
"blockedNative": [
|
|
69
|
+
"grep",
|
|
70
|
+
"find",
|
|
71
|
+
"rg",
|
|
72
|
+
"ag",
|
|
73
|
+
"Grep",
|
|
74
|
+
"Glob",
|
|
75
|
+
"Explore",
|
|
76
|
+
"WebSearch",
|
|
77
|
+
"WebFetch"
|
|
78
|
+
]
|
|
79
|
+
},
|
|
80
|
+
"devflow:css": {
|
|
81
|
+
"mcpTools": [
|
|
82
|
+
"css_audit_selectors"
|
|
83
|
+
],
|
|
84
|
+
"blockedNative": [
|
|
85
|
+
"grep",
|
|
86
|
+
"find",
|
|
87
|
+
"rg",
|
|
88
|
+
"ag",
|
|
89
|
+
"Grep",
|
|
90
|
+
"Glob",
|
|
91
|
+
"Explore",
|
|
92
|
+
"WebSearch",
|
|
93
|
+
"WebFetch"
|
|
94
|
+
]
|
|
95
|
+
},
|
|
96
|
+
"devflow:docker": {
|
|
97
|
+
"mcpTools": [
|
|
98
|
+
"docker_dockerize_project"
|
|
99
|
+
],
|
|
100
|
+
"blockedNative": [
|
|
101
|
+
"grep",
|
|
102
|
+
"find",
|
|
103
|
+
"rg",
|
|
104
|
+
"ag",
|
|
105
|
+
"Grep",
|
|
106
|
+
"Glob",
|
|
107
|
+
"Explore",
|
|
108
|
+
"WebSearch",
|
|
109
|
+
"WebFetch"
|
|
110
|
+
]
|
|
111
|
+
},
|
|
112
|
+
"devflow:electron": {
|
|
113
|
+
"mcpTools": [
|
|
114
|
+
"electron_diagnose_bug"
|
|
115
|
+
],
|
|
116
|
+
"blockedNative": [
|
|
117
|
+
"grep",
|
|
118
|
+
"find",
|
|
119
|
+
"rg",
|
|
120
|
+
"ag",
|
|
121
|
+
"Grep",
|
|
122
|
+
"Glob",
|
|
123
|
+
"Explore",
|
|
124
|
+
"WebSearch",
|
|
125
|
+
"WebFetch"
|
|
126
|
+
]
|
|
127
|
+
},
|
|
128
|
+
"devflow:git": {
|
|
129
|
+
"mcpTools": [
|
|
130
|
+
"git_analyze_repo"
|
|
131
|
+
],
|
|
132
|
+
"blockedNative": [
|
|
133
|
+
"grep",
|
|
134
|
+
"find",
|
|
135
|
+
"rg",
|
|
136
|
+
"ag",
|
|
137
|
+
"Grep",
|
|
138
|
+
"Glob",
|
|
139
|
+
"Explore",
|
|
140
|
+
"WebSearch",
|
|
141
|
+
"WebFetch"
|
|
142
|
+
]
|
|
143
|
+
},
|
|
144
|
+
"devflow:graphql": {
|
|
145
|
+
"mcpTools": [
|
|
146
|
+
"graphql_diagnose_bug"
|
|
147
|
+
],
|
|
148
|
+
"blockedNative": [
|
|
149
|
+
"grep",
|
|
150
|
+
"find",
|
|
151
|
+
"rg",
|
|
152
|
+
"ag",
|
|
153
|
+
"Grep",
|
|
154
|
+
"Glob",
|
|
155
|
+
"Explore",
|
|
156
|
+
"WebSearch",
|
|
157
|
+
"WebFetch"
|
|
158
|
+
]
|
|
159
|
+
},
|
|
160
|
+
"devflow:nest": {
|
|
161
|
+
"mcpTools": [
|
|
162
|
+
"nest_diagnose_bug",
|
|
163
|
+
"nest_new_module"
|
|
164
|
+
],
|
|
165
|
+
"blockedNative": [
|
|
166
|
+
"grep",
|
|
167
|
+
"find",
|
|
168
|
+
"rg",
|
|
169
|
+
"ag",
|
|
170
|
+
"Grep",
|
|
171
|
+
"Glob",
|
|
172
|
+
"Explore",
|
|
173
|
+
"WebSearch",
|
|
174
|
+
"WebFetch"
|
|
175
|
+
]
|
|
176
|
+
},
|
|
177
|
+
"devflow:nextjs": {
|
|
178
|
+
"mcpTools": [
|
|
179
|
+
"nextjs_diagnose_bug",
|
|
180
|
+
"nextjs_new_page"
|
|
181
|
+
],
|
|
182
|
+
"blockedNative": [
|
|
183
|
+
"grep",
|
|
184
|
+
"find",
|
|
185
|
+
"rg",
|
|
186
|
+
"ag",
|
|
187
|
+
"Grep",
|
|
188
|
+
"Glob",
|
|
189
|
+
"Explore",
|
|
190
|
+
"WebSearch",
|
|
191
|
+
"WebFetch"
|
|
192
|
+
]
|
|
193
|
+
},
|
|
194
|
+
"devflow:performance": {
|
|
195
|
+
"mcpTools": [
|
|
196
|
+
"performance_audit_performance"
|
|
197
|
+
],
|
|
198
|
+
"blockedNative": [
|
|
199
|
+
"grep",
|
|
200
|
+
"find",
|
|
201
|
+
"rg",
|
|
202
|
+
"ag",
|
|
203
|
+
"Grep",
|
|
204
|
+
"Glob",
|
|
205
|
+
"Explore",
|
|
206
|
+
"WebSearch",
|
|
207
|
+
"WebFetch"
|
|
208
|
+
]
|
|
209
|
+
},
|
|
210
|
+
"devflow:react": {
|
|
211
|
+
"mcpTools": [
|
|
212
|
+
"react_review_hooks",
|
|
213
|
+
"react_audit_performance",
|
|
214
|
+
"react_refactor_component",
|
|
215
|
+
"react_diagnose_bug",
|
|
216
|
+
"react_new_component"
|
|
217
|
+
],
|
|
218
|
+
"blockedNative": [
|
|
219
|
+
"grep",
|
|
220
|
+
"find",
|
|
221
|
+
"rg",
|
|
222
|
+
"ag",
|
|
223
|
+
"Grep",
|
|
224
|
+
"Glob",
|
|
225
|
+
"Explore",
|
|
226
|
+
"WebSearch",
|
|
227
|
+
"WebFetch"
|
|
228
|
+
]
|
|
229
|
+
},
|
|
230
|
+
"devflow:tailwind": {
|
|
231
|
+
"mcpTools": [
|
|
232
|
+
"tailwind_new_component",
|
|
233
|
+
"tailwind_optimize_classes"
|
|
234
|
+
],
|
|
235
|
+
"blockedNative": [
|
|
236
|
+
"grep",
|
|
237
|
+
"find",
|
|
238
|
+
"rg",
|
|
239
|
+
"ag",
|
|
240
|
+
"Grep",
|
|
241
|
+
"Glob",
|
|
242
|
+
"Explore",
|
|
243
|
+
"WebSearch",
|
|
244
|
+
"WebFetch"
|
|
245
|
+
]
|
|
246
|
+
},
|
|
247
|
+
"devflow:taro": {
|
|
248
|
+
"mcpTools": [
|
|
249
|
+
"taro_new_page"
|
|
250
|
+
],
|
|
251
|
+
"blockedNative": [
|
|
252
|
+
"grep",
|
|
253
|
+
"find",
|
|
254
|
+
"rg",
|
|
255
|
+
"ag",
|
|
256
|
+
"Grep",
|
|
257
|
+
"Glob",
|
|
258
|
+
"Explore",
|
|
259
|
+
"WebSearch",
|
|
260
|
+
"WebFetch"
|
|
261
|
+
]
|
|
262
|
+
},
|
|
263
|
+
"devflow:ui-layout": {
|
|
264
|
+
"mcpTools": [
|
|
265
|
+
"ui_layout_generate"
|
|
266
|
+
],
|
|
267
|
+
"blockedNative": [
|
|
268
|
+
"grep",
|
|
269
|
+
"find",
|
|
270
|
+
"rg",
|
|
271
|
+
"ag",
|
|
272
|
+
"Grep",
|
|
273
|
+
"Glob",
|
|
274
|
+
"Explore",
|
|
275
|
+
"WebSearch",
|
|
276
|
+
"WebFetch"
|
|
277
|
+
]
|
|
278
|
+
},
|
|
279
|
+
"devflow:vue": {
|
|
280
|
+
"mcpTools": [
|
|
281
|
+
"vue_diagnose_bug",
|
|
282
|
+
"vue_debug_reactivity"
|
|
283
|
+
],
|
|
284
|
+
"blockedNative": [
|
|
285
|
+
"grep",
|
|
286
|
+
"find",
|
|
287
|
+
"rg",
|
|
288
|
+
"ag",
|
|
289
|
+
"Grep",
|
|
290
|
+
"Glob",
|
|
291
|
+
"Explore",
|
|
292
|
+
"WebSearch",
|
|
293
|
+
"WebFetch"
|
|
294
|
+
]
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import {existsSync}from'node:fs';import {homedir}from'node:os';import {resolve,join}from'node:path';import {fileURLToPath}from'node:url';async function m(n=homedir()){let a=process.env.DEVFLOW_STATE_DIR??join(n,".devflow","global"),r=join(a,"devflow.db");if(!existsSync(r))return {gateCount:4,ruleCount:null,source:"fallback"};let e;try{let{DatabaseSync:u}=await import('node:sqlite');e=new u(r,{readOnly:!0});let t=e.prepare(`
|
|
2
|
+
SELECT COUNT(*) AS rule_count, COUNT(DISTINCT gate) AS gate_count
|
|
3
|
+
FROM devflow_rules
|
|
4
|
+
WHERE enabled = 1
|
|
5
|
+
`).get();return {gateCount:Number(t?.gate_count??0),ruleCount:Number(t?.rule_count??0),source:"database"}}catch{return {gateCount:4,ruleCount:null,source:"fallback"}}finally{e?.close();}}process.argv[1]&&fileURLToPath(import.meta.url)===resolve(process.argv[1])&&process.stdout.write(`${JSON.stringify(await m())}
|
|
6
|
+
`);export{m as readEnforcerSummary};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import {createConnection}from'node:net';import {getDaemonSocketPath}from'@devflow-tools/sdk';import {mkdirSync,appendFileSync}from'node:fs';import {homedir}from'node:os';import {join,dirname}from'node:path';import {openGlobalDevFlowDatabase}from'@devflow-tools/database';function d(e,o,t){try{let r=openGlobalDevFlowDatabase();try{r.insertEvent({kind:e,timestamp:Date.now(),duration:t,success:o.success!==!1,metadata:o});}finally{r.close();}}catch{}}var E=["4-Gate enforcement","memory prefetch cache","daemon-shared hook state"];function a(e){let o=R(e.input)??e.requestType;if(d("hook_daemon_request",{success:e.success,projectRoot:e.projectRoot,requestType:e.requestType,tool:o,attempts:e.attempts},e.durationMs),!e.success)try{let t=Date.now(),r=join(homedir(),".devflow","logs","hook-fallback",`${new Date(t).toISOString().slice(0,10)}.log`);mkdirSync(dirname(r),{recursive:!0,mode:448}),appendFileSync(r,`${JSON.stringify({ts:t,tool:o,requestType:e.requestType,projectRoot:e.projectRoot,reason:"daemon-unreachable",durationMs:e.durationMs,attempts:e.attempts,bypassCountLost:!0,disabledFeatures:E})}
|
|
2
|
+
`,{mode:384});}catch{}}function R(e){try{let o=JSON.parse(e);return typeof o.tool_name=="string"&&o.tool_name?o.tool_name:null}catch{return null}}var i=process.env.CLAUDE_PROJECT_DIR||process.cwd(),v=getDaemonSocketPath(i),n=process.argv[2],S=process.argv[3],m=Number(process.env.DEVFLOW_HOOK_CLIENT_TIMEOUT_MS),N=Number.isFinite(m)&&m>0?m:4e3,l=Number(process.env.DEVFLOW_HOOK_CLIENT_RETRY_DELAY_MS),k=Number.isFinite(l)&&l>=0?l:1e3;async function q(){let e=n==="pre-tool-use"?await P():S??"",o=Date.now();for(let t=0;t<2;t+=1){let r=await L(e);if(r!==null)return a({projectRoot:i,requestType:n,input:e,durationMs:Date.now()-o,success:true,attempts:t+1}),process.stdout.write(`${r}
|
|
3
|
+
`),0;t===0&&await A(k);}return process.env.DEVFLOW_HOOK_CLIENT_SUPPRESS_FALLBACK_LOG!=="1"&&a({projectRoot:i,requestType:n,input:e,durationMs:Date.now()-o,success:false,attempts:2}),1}function L(e){return new Promise(o=>{let t=createConnection(v),r=false,u="",c=s=>{r||(r=true,clearTimeout(f),t.destroy(),o(s));},f=setTimeout(()=>c(null),N);t.setEncoding("utf8"),t.on("connect",()=>{t.write(`${JSON.stringify({type:"hello",rootPath:i})}
|
|
4
|
+
`);let s=M(e);if(!s){c(null);return}t.write(`${JSON.stringify(s)}
|
|
5
|
+
`);}),t.on("data",s=>{u+=s;let p=u.indexOf(`
|
|
6
|
+
`);if(p<0)return;let g=u.slice(0,p).trim();c(g||null);}),t.on("error",()=>c(null)),t.on("close",()=>c(null));})}function M(e){return n==="stop"?{type:"stop"}:n==="memory-snapshot"?{type:"memory-snapshot"}:["session-start","session-end","post-tool-use","post-tool-use-failure","pre-tool-use","user-prompt-submit","pre-compact"].includes(n)?{type:n,input:e}:null}function P(){return new Promise(e=>{let o="";process.stdin.setEncoding("utf8"),process.stdin.on("data",t=>{o+=t;}),process.stdin.on("end",()=>e(o)),process.stdin.on("error",()=>e(""));})}function A(e){return new Promise(o=>setTimeout(o,e))}q().then(e=>process.exit(e)).catch(()=>process.exit(1));
|