@devflow-tools/cli 0.2.2 → 0.3.0

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.
Files changed (55) hide show
  1. package/dist/commands/benchmark-cmd.d.ts +5 -0
  2. package/dist/commands/benchmark-cmd.d.ts.map +1 -0
  3. package/dist/commands/benchmark-cmd.js +39 -0
  4. package/dist/commands/benchmark-cmd.js.map +1 -0
  5. package/dist/commands/context.d.ts +1 -2
  6. package/dist/commands/context.d.ts.map +1 -1
  7. package/dist/commands/context.js +9 -7
  8. package/dist/commands/context.js.map +1 -1
  9. package/dist/commands/doctor.d.ts +3 -0
  10. package/dist/commands/doctor.d.ts.map +1 -1
  11. package/dist/commands/doctor.js +7 -0
  12. package/dist/commands/doctor.js.map +1 -1
  13. package/dist/commands/graph.d.ts +1 -0
  14. package/dist/commands/graph.d.ts.map +1 -1
  15. package/dist/commands/graph.js +8 -6
  16. package/dist/commands/graph.js.map +1 -1
  17. package/dist/commands/index-cmd.d.ts +3 -7
  18. package/dist/commands/index-cmd.d.ts.map +1 -1
  19. package/dist/commands/index-cmd.js +12 -9
  20. package/dist/commands/index-cmd.js.map +1 -1
  21. package/dist/commands/knowledge.d.ts +4 -4
  22. package/dist/commands/knowledge.d.ts.map +1 -1
  23. package/dist/commands/knowledge.js +19 -12
  24. package/dist/commands/knowledge.js.map +1 -1
  25. package/dist/commands/memory.d.ts +3 -4
  26. package/dist/commands/memory.d.ts.map +1 -1
  27. package/dist/commands/memory.js +16 -13
  28. package/dist/commands/memory.js.map +1 -1
  29. package/dist/commands/plugin-loader.d.ts +1 -5
  30. package/dist/commands/plugin-loader.d.ts.map +1 -1
  31. package/dist/commands/plugin-loader.js +1 -70
  32. package/dist/commands/plugin-loader.js.map +1 -1
  33. package/dist/commands/review.d.ts +6 -0
  34. package/dist/commands/review.d.ts.map +1 -0
  35. package/dist/commands/review.js +75 -0
  36. package/dist/commands/review.js.map +1 -0
  37. package/dist/commands/server.d.ts +11 -0
  38. package/dist/commands/server.d.ts.map +1 -0
  39. package/dist/commands/server.js +58 -0
  40. package/dist/commands/server.js.map +1 -0
  41. package/dist/commands/skill.d.ts +8 -2
  42. package/dist/commands/skill.d.ts.map +1 -1
  43. package/dist/commands/skill.js +94 -12
  44. package/dist/commands/skill.js.map +1 -1
  45. package/dist/commands/workflow.d.ts +4 -5
  46. package/dist/commands/workflow.d.ts.map +1 -1
  47. package/dist/commands/workflow.js +18 -16
  48. package/dist/commands/workflow.js.map +1 -1
  49. package/dist/index.js +145 -20
  50. package/dist/index.js.map +1 -1
  51. package/dist/lib/with-server.d.ts +7 -0
  52. package/dist/lib/with-server.d.ts.map +1 -0
  53. package/dist/lib/with-server.js +28 -0
  54. package/dist/lib/with-server.js.map +1 -0
  55. package/package.json +22 -22
@@ -0,0 +1,58 @@
1
+ import { spawn } from "child_process";
2
+ import { readFileSync, writeFileSync, existsSync, unlinkSync, mkdirSync } from "fs";
3
+ import { join } from "path";
4
+ import { createRequire } from "module";
5
+ const require = createRequire(import.meta.url);
6
+ function getPidFile(projectRoot) {
7
+ const dotdev = join(projectRoot, ".devflow");
8
+ if (!existsSync(dotdev))
9
+ mkdirSync(dotdev, { recursive: true });
10
+ return join(dotdev, "server.pid");
11
+ }
12
+ function getServerScript() {
13
+ try {
14
+ return require.resolve("@devflow-tools/server/dist/main.js");
15
+ }
16
+ catch {
17
+ return join(process.cwd(), "apps", "server", "dist", "main.js");
18
+ }
19
+ }
20
+ export async function startServer(opts) {
21
+ const script = getServerScript();
22
+ const pidFile = getPidFile(process.cwd());
23
+ const child = spawn("node", [script], {
24
+ env: { ...process.env, PORT: String(opts.port) },
25
+ stdio: "ignore",
26
+ detached: true,
27
+ });
28
+ writeFileSync(pidFile, String(child.pid ?? 0));
29
+ child.unref();
30
+ return { pid: child.pid ?? 0 };
31
+ }
32
+ export async function stopServer() {
33
+ const pidFile = getPidFile(process.cwd());
34
+ if (!existsSync(pidFile))
35
+ return false;
36
+ const pid = parseInt(readFileSync(pidFile, "utf-8").trim(), 10);
37
+ try {
38
+ process.kill(pid);
39
+ unlinkSync(pidFile);
40
+ return true;
41
+ }
42
+ catch {
43
+ unlinkSync(pidFile);
44
+ return false;
45
+ }
46
+ }
47
+ export async function serverStatus() {
48
+ const { DevFlowApiClient } = await import("@devflow-tools/sdk");
49
+ const client = new DevFlowApiClient({ baseUrl: "http://localhost:3100", projectRoot: process.cwd() });
50
+ const reachable = await client.ping();
51
+ if (reachable) {
52
+ const pidFile = getPidFile(process.cwd());
53
+ const pid = existsSync(pidFile) ? parseInt(readFileSync(pidFile, "utf-8").trim(), 10) : undefined;
54
+ return { running: true, pid };
55
+ }
56
+ return { running: false };
57
+ }
58
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"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"}
@@ -6,7 +6,13 @@ export interface SkillMeta {
6
6
  tags: string[];
7
7
  installed: boolean;
8
8
  }
9
- export declare function listSkills(): Promise<SkillMeta[]>;
9
+ export declare function listSkills(skipServer?: boolean): Promise<SkillMeta[]>;
10
10
  export declare function listSkillsSync(): SkillMeta[];
11
- export declare function searchSkills(query: string): Promise<SkillMeta[]>;
11
+ export declare function searchSkills(query: string, skipServer?: boolean): Promise<SkillMeta[]>;
12
+ export declare function installSkill(name: string, projectRoot?: string, skipServer?: boolean): Promise<{
13
+ name: string;
14
+ version: string;
15
+ templates: string[];
16
+ }>;
17
+ export declare function uninstallSkill(name: string, projectRoot?: string, skipServer?: boolean): Promise<void>;
12
18
  //# sourceMappingURL=skill.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"skill.d.ts","sourceRoot":"","sources":["../../src/commands/skill.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,wBAAsB,UAAU,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC,CAUvD;AAED,wBAAgB,cAAc,IAAI,SAAS,EAAE,CAE5C;AAED,wBAAsB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAStE"}
1
+ {"version":3,"file":"skill.d.ts","sourceRoot":"","sources":["../../src/commands/skill.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,wBAAsB,UAAU,CAAC,UAAU,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CA2B3E;AAED,wBAAgB,cAAc,IAAI,SAAS,EAAE,CAE5C;AAED,wBAAsB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAS5F;AAmBD,wBAAsB,YAAY,CAChC,IAAI,EAAE,MAAM,EACZ,WAAW,GAAE,MAAsB,EACnC,UAAU,CAAC,EAAE,OAAO,GACnB,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAyCjE;AAED,wBAAsB,cAAc,CAClC,IAAI,EAAE,MAAM,EACZ,WAAW,GAAE,MAAsB,EACnC,UAAU,CAAC,EAAE,OAAO,GACnB,OAAO,CAAC,IAAI,CAAC,CAyBf"}
@@ -1,23 +1,105 @@
1
+ import { withServer } from "../lib/with-server.js";
1
2
  import { loadPlugins } from "./plugin-loader.js";
2
- export async function listSkills() {
3
- const plugins = await loadPlugins();
4
- return Array.from(plugins.values()).map((p) => ({
5
- name: p.meta.name,
6
- version: p.meta.version,
7
- description: p.meta.description,
8
- icon: p.meta.icon,
9
- tags: p.meta.tags,
10
- installed: true,
11
- }));
3
+ import { existsSync, readFileSync, writeFileSync, mkdirSync, rmSync } from "fs";
4
+ import { join } from "path";
5
+ import { execSync } from "child_process";
6
+ export async function listSkills(skipServer) {
7
+ return withServer(process.cwd(), async (client) => {
8
+ const plugins = await client.listPlugins();
9
+ return plugins.map((p) => ({
10
+ name: p.name,
11
+ version: p.version,
12
+ description: p.description,
13
+ icon: p.icon,
14
+ tags: p.tags ?? [],
15
+ installed: true,
16
+ }));
17
+ }, async () => {
18
+ const plugins = await loadPlugins();
19
+ return Array.from(plugins.values()).map((p) => ({
20
+ name: p.meta.name,
21
+ version: p.meta.version,
22
+ description: p.meta.description,
23
+ icon: p.meta.icon,
24
+ tags: p.meta.tags,
25
+ installed: true,
26
+ }));
27
+ }, { skipServer });
12
28
  }
13
29
  export function listSkillsSync() {
14
30
  return [];
15
31
  }
16
- export async function searchSkills(query) {
17
- const all = await listSkills();
32
+ export async function searchSkills(query, skipServer) {
33
+ const all = await listSkills(skipServer);
18
34
  const q = query.toLowerCase();
19
35
  return all.filter((s) => s.name.toLowerCase().includes(q) ||
20
36
  s.description.toLowerCase().includes(q) ||
21
37
  s.tags.some((t) => t.toLowerCase().includes(q)));
22
38
  }
39
+ const HOME_SKILLS_DIR = join(process.env.HOME ?? "~", ".devflow", "skills");
40
+ function readConfig(projectRoot) {
41
+ const configPath = join(projectRoot, ".devflow", "config.json");
42
+ if (!existsSync(configPath))
43
+ return { plugins: [] };
44
+ return JSON.parse(readFileSync(configPath, "utf-8"));
45
+ }
46
+ function writeConfig(projectRoot, config) {
47
+ const configPath = join(projectRoot, ".devflow", "config.json");
48
+ writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
49
+ }
50
+ export async function installSkill(name, projectRoot = process.cwd(), skipServer) {
51
+ return withServer(projectRoot, async (client) => {
52
+ const result = await client.installPlugin(name);
53
+ return result;
54
+ }, async () => {
55
+ const npmName = name.startsWith("@devflow-tools/plugin-") ? name : `@devflow-tools/plugin-${name}`;
56
+ const shortName = name.replace(/^@devflow-tools\/plugin-/, "");
57
+ mkdirSync(HOME_SKILLS_DIR, { recursive: true });
58
+ try {
59
+ execSync(`npm install --prefix "${HOME_SKILLS_DIR}" ${npmName}`, {
60
+ stdio: "pipe",
61
+ timeout: 60_000,
62
+ });
63
+ }
64
+ catch {
65
+ // If npm install fails, still register
66
+ }
67
+ const config = readConfig(projectRoot);
68
+ if (!config.plugins)
69
+ config.plugins = [];
70
+ if (!config.plugins.includes(shortName)) {
71
+ config.plugins.push(shortName);
72
+ writeConfig(projectRoot, config);
73
+ }
74
+ let templates = [];
75
+ try {
76
+ const pkgJson = JSON.parse(readFileSync(join(HOME_SKILLS_DIR, "node_modules", npmName, "package.json"), "utf-8"));
77
+ templates = pkgJson?.devflow?.templates ?? [];
78
+ }
79
+ catch {
80
+ // Plugin metadata not available
81
+ }
82
+ return { name: shortName, version: "0.1.0", templates };
83
+ }, { skipServer });
84
+ }
85
+ export async function uninstallSkill(name, projectRoot = process.cwd(), skipServer) {
86
+ return withServer(projectRoot, async (client) => { await client.uninstallPlugin(name); }, async () => {
87
+ const shortName = name.replace(/^@devflow-tools\/plugin-/, "");
88
+ const config = readConfig(projectRoot);
89
+ if (config.plugins) {
90
+ config.plugins = config.plugins.filter(p => p !== shortName);
91
+ writeConfig(projectRoot, config);
92
+ }
93
+ const npmName = name.startsWith("@devflow-tools/plugin-") ? name : `@devflow-tools/plugin-${name}`;
94
+ try {
95
+ const pkgDir = join(HOME_SKILLS_DIR, "node_modules", npmName);
96
+ if (existsSync(pkgDir)) {
97
+ rmSync(pkgDir, { recursive: true, force: true });
98
+ }
99
+ }
100
+ catch {
101
+ // Cleanup failure is non-fatal
102
+ }
103
+ }, { skipServer });
104
+ }
23
105
  //# sourceMappingURL=skill.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"skill.js","sourceRoot":"","sources":["../../src/commands/skill.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAWjD,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,MAAM,OAAO,GAAG,MAAM,WAAW,EAAE,CAAC;IACpC,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC9C,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI;QACjB,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO;QACvB,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,WAAW;QAC/B,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI;QACjB,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI;QACjB,SAAS,EAAE,IAAI;KAChB,CAAC,CAAC,CAAC;AACN,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,KAAa;IAC9C,MAAM,GAAG,GAAG,MAAM,UAAU,EAAE,CAAC;IAC/B,MAAM,CAAC,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IAC9B,OAAO,GAAG,CAAC,MAAM,CACf,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;QAChC,CAAC,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;QACvC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAClD,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"skill.js","sourceRoot":"","sources":["../../src/commands/skill.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,6 @@
1
1
  import type { WorkflowMeta, WorkflowRun, WorkflowRunResult } from "@devflow-tools/sdk";
2
- export declare function getWorkflowEngine(): Promise<import("@devflow-tools/workflow-engine").WorkflowEngine>;
3
- export declare function listWorkflows(): Promise<WorkflowMeta[]>;
4
- export declare function runWorkflow(type: string, input: Record<string, unknown>): Promise<WorkflowRunResult>;
5
- export declare function getWorkflowStatus(): Promise<WorkflowRun[]>;
6
- export declare function getWorkflowRuns(): Promise<WorkflowRun[]>;
2
+ export declare function listWorkflows(skipServer?: boolean): Promise<WorkflowMeta[]>;
3
+ export declare function runWorkflow(type: string, input: Record<string, unknown>, skipServer?: boolean): Promise<WorkflowRunResult>;
4
+ export declare function getWorkflowStatus(skipServer?: boolean): Promise<WorkflowRun[]>;
5
+ export declare function getWorkflowRuns(skipServer?: boolean): Promise<WorkflowRun[]>;
7
6
  //# sourceMappingURL=workflow.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"workflow.d.ts","sourceRoot":"","sources":["../../src/commands/workflow.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAEvF,wBAAsB,iBAAiB,qEAGtC;AAED,wBAAsB,aAAa,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC,CAG7D;AAED,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,OAAO,CAAC,iBAAiB,CAAC,CAG5B;AAED,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAGhE;AAED,wBAAsB,eAAe,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAG9D"}
1
+ {"version":3,"file":"workflow.d.ts","sourceRoot":"","sources":["../../src/commands/workflow.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAEvF,wBAAsB,aAAa,CAAC,UAAU,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAUjF;AAED,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,UAAU,CAAC,EAAE,OAAO,GACnB,OAAO,CAAC,iBAAiB,CAAC,CAU5B;AAED,wBAAsB,iBAAiB,CAAC,UAAU,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAEpF;AAED,wBAAsB,eAAe,CAAC,UAAU,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAUlF"}
@@ -1,22 +1,24 @@
1
+ import { withServer } from "../lib/with-server.js";
1
2
  import { createEngines } from "@devflow-tools/context-engine";
2
- export async function getWorkflowEngine() {
3
- const { workflow } = await createEngines(process.cwd());
4
- return workflow;
3
+ export async function listWorkflows(skipServer) {
4
+ return withServer(process.cwd(), (client) => client.listWorkflows(), async () => {
5
+ const { workflow } = await createEngines(process.cwd());
6
+ return workflow.list();
7
+ }, { skipServer });
5
8
  }
6
- export async function listWorkflows() {
7
- const engine = await getWorkflowEngine();
8
- return engine.list();
9
+ export async function runWorkflow(type, input, skipServer) {
10
+ return withServer(process.cwd(), (client) => client.runWorkflow(type, input), async () => {
11
+ const { workflow } = await createEngines(process.cwd());
12
+ return workflow.run(type, input);
13
+ }, { skipServer });
9
14
  }
10
- export async function runWorkflow(type, input) {
11
- const engine = await getWorkflowEngine();
12
- return engine.run(type, input);
15
+ export async function getWorkflowStatus(skipServer) {
16
+ return getWorkflowRuns(skipServer);
13
17
  }
14
- export async function getWorkflowStatus() {
15
- const engine = await getWorkflowEngine();
16
- return engine.listRuns();
17
- }
18
- export async function getWorkflowRuns() {
19
- const engine = await getWorkflowEngine();
20
- return engine.listRuns();
18
+ export async function getWorkflowRuns(skipServer) {
19
+ return withServer(process.cwd(), (client) => client.getWorkflowRuns(), async () => {
20
+ const { workflow } = await createEngines(process.cwd());
21
+ return workflow.listRuns();
22
+ }, { skipServer });
21
23
  }
22
24
  //# sourceMappingURL=workflow.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"workflow.js","sourceRoot":"","sources":["../../src/commands/workflow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAG9D,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,aAAa,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACxD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,MAAM,GAAG,MAAM,iBAAiB,EAAE,CAAC;IACzC,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC;AACvB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,IAAY,EACZ,KAA8B;IAE9B,MAAM,MAAM,GAAG,MAAM,iBAAiB,EAAE,CAAC;IACzC,OAAO,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,MAAM,MAAM,GAAG,MAAM,iBAAiB,EAAE,CAAC;IACzC,OAAO,MAAM,CAAC,QAAQ,EAAE,CAAC;AAC3B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,MAAM,MAAM,GAAG,MAAM,iBAAiB,EAAE,CAAC;IACzC,OAAO,MAAM,CAAC,QAAQ,EAAE,CAAC;AAC3B,CAAC"}
1
+ {"version":3,"file":"workflow.js","sourceRoot":"","sources":["../../src/commands/workflow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAA0B,MAAM,uBAAuB,CAAC;AAC3E,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAG9D,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,UAAoB;IACtD,OAAO,UAAU,CACf,OAAO,CAAC,GAAG,EAAE,EACb,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,aAAa,EAA6B,EAC7D,KAAK,IAAI,EAAE;QACT,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,aAAa,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QACxD,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;IACzB,CAAC,EACD,EAAE,UAAU,EAAE,CACf,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,IAAY,EACZ,KAA8B,EAC9B,UAAoB;IAEpB,OAAO,UAAU,CACf,OAAO,CAAC,GAAG,EAAE,EACb,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,KAAK,CAA+B,EACzE,KAAK,IAAI,EAAE;QACT,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,aAAa,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QACxD,OAAO,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACnC,CAAC,EACD,EAAE,UAAU,EAAE,CACf,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,UAAoB;IAC1D,OAAO,eAAe,CAAC,UAAU,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,UAAoB;IACxD,OAAO,UAAU,CACf,OAAO,CAAC,GAAG,EAAE,EACb,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,eAAe,EAA4B,EAC9D,KAAK,IAAI,EAAE;QACT,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,aAAa,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QACxD,OAAO,QAAQ,CAAC,QAAQ,EAAE,CAAC;IAC7B,CAAC,EACD,EAAE,UAAU,EAAE,CACf,CAAC;AACJ,CAAC"}
package/dist/index.js CHANGED
@@ -10,13 +10,18 @@ import { getContext } from "./commands/context.js";
10
10
  import { listWorkflows, runWorkflow, getWorkflowStatus, getWorkflowRuns, } from "./commands/workflow.js";
11
11
  import { showMemory, setMemory, reviewCandidates } from "./commands/memory.js";
12
12
  import { searchKnowledge } from "./commands/knowledge.js";
13
- import { listSkills, searchSkills } from "./commands/skill.js";
13
+ import { listSkills, searchSkills, installSkill, uninstallSkill } from "./commands/skill.js";
14
14
  import { runDoctor } from "./commands/doctor.js";
15
+ import { runBenchmark } from "./commands/benchmark-cmd.js";
16
+ import { runReview } from "./commands/review.js";
17
+ import { startServer, stopServer, serverStatus } from "./commands/server.js";
18
+ import { KnowledgeEngine } from "@devflow-tools/knowledge-engine";
15
19
  const program = new Command();
16
20
  program
17
21
  .name("devflow")
18
22
  .description("Developer Intelligence Platform for AI Coding Agents")
19
- .version("0.1.0");
23
+ .version("0.1.0")
24
+ .option("--local", "Force local engine, skip server");
20
25
  // --- init ---
21
26
  program
22
27
  .command("init")
@@ -76,7 +81,7 @@ program
76
81
  .description("Show index status")
77
82
  .option("--watch", "Start file watcher for hot updates (stub)")
78
83
  .action(async (opts) => {
79
- const status = await getIndexStatus();
84
+ const status = await getIndexStatus(program.opts().local);
80
85
  console.log(chalk.blue("Index Status"));
81
86
  console.log(` Files: ${status.totalFiles}`);
82
87
  console.log(` Symbols: ${status.totalSymbols}`);
@@ -91,7 +96,7 @@ program
91
96
  .description("Show dependency graph")
92
97
  .option("--depth <n>", "Expansion depth", "2")
93
98
  .action(async (target, opts) => {
94
- const graph = await getGraph({ target, depth: parseInt(opts.depth, 10) });
99
+ const graph = await getGraph({ target, depth: parseInt(opts.depth, 10), skipServer: program.opts().local });
95
100
  console.log(chalk.blue("Dependency Graph"));
96
101
  console.log(` Nodes: ${graph.nodes.length}`);
97
102
  console.log(` Edges: ${graph.edges.length}`);
@@ -107,6 +112,7 @@ program
107
112
  query,
108
113
  mode: opts.mode,
109
114
  maxTokens: parseInt(opts.maxTokens, 10),
115
+ skipServer: program.opts().local,
110
116
  });
111
117
  console.log(chalk.blue(`Context: "${query}"`));
112
118
  console.log(` Files: ${result.files.length}`);
@@ -121,7 +127,7 @@ workflowCmd
121
127
  .command("list")
122
128
  .description("List available workflows")
123
129
  .action(async () => {
124
- const workflows = await listWorkflows();
130
+ const workflows = await listWorkflows(program.opts().local);
125
131
  if (workflows.length === 0) {
126
132
  console.log(chalk.dim("No workflows registered."));
127
133
  return;
@@ -134,7 +140,7 @@ workflowCmd
134
140
  .command("run <type> [input]")
135
141
  .description("Run a workflow")
136
142
  .action(async (type, input) => {
137
- const result = await runWorkflow(type, { input: input ?? "" });
143
+ const result = await runWorkflow(type, { input: input ?? "" }, program.opts().local);
138
144
  console.log(`Run: ${result.runId}`);
139
145
  console.log(`Status: ${result.status}`);
140
146
  console.log(`Duration: ${result.duration}ms`);
@@ -143,7 +149,7 @@ workflowCmd
143
149
  .command("status")
144
150
  .description("Show running workflows")
145
151
  .action(async () => {
146
- const runs = await getWorkflowStatus();
152
+ const runs = await getWorkflowStatus(program.opts().local);
147
153
  console.log(`${runs.length} run(s)`);
148
154
  for (const r of runs) {
149
155
  console.log(` ${r.runId} — ${r.status}`);
@@ -153,7 +159,7 @@ workflowCmd
153
159
  .command("runs")
154
160
  .description("Show workflow history")
155
161
  .action(async () => {
156
- const runs = await getWorkflowRuns();
162
+ const runs = await getWorkflowRuns(program.opts().local);
157
163
  if (runs.length === 0) {
158
164
  console.log(chalk.dim("No runs yet."));
159
165
  return;
@@ -171,21 +177,21 @@ memoryCmd
171
177
  .command("show")
172
178
  .description("Show current project memory")
173
179
  .action(async () => {
174
- const mem = await showMemory();
180
+ const mem = await showMemory(program.opts().local);
175
181
  console.log(JSON.stringify(mem, null, 2));
176
182
  });
177
183
  memoryCmd
178
184
  .command("set <key> <value>")
179
185
  .description("Set a memory key")
180
186
  .action(async (key, value) => {
181
- await setMemory(key, value);
187
+ await setMemory(key, value, program.opts().local);
182
188
  console.log(chalk.green(`Memory set: ${key} = ${value}`));
183
189
  });
184
190
  memoryCmd
185
191
  .command("review")
186
192
  .description("Review memory candidates")
187
193
  .action(async () => {
188
- const candidates = await reviewCandidates();
194
+ const candidates = await reviewCandidates(program.opts().local);
189
195
  console.log(JSON.stringify(candidates, null, 2));
190
196
  });
191
197
  // --- knowledge ---
@@ -193,20 +199,47 @@ const knowledgeCmd = program
193
199
  .command("knowledge <query>")
194
200
  .description("Search knowledge base")
195
201
  .action(async (query) => {
196
- const results = await searchKnowledge(query);
202
+ const results = await searchKnowledge(query, undefined, program.opts().local);
197
203
  console.log(chalk.blue(`Knowledge: "${query}"`));
198
204
  console.log(` Results: ${results.length}`);
199
205
  for (const r of results.slice(0, 5)) {
200
206
  console.log(` — ${r.title}`);
201
207
  }
202
208
  });
203
- // docs (alias under knowledge)
209
+ // docs sync
204
210
  program
205
- .command("docs")
206
- .description("Document sync status")
207
- .action(async () => {
208
- console.log(chalk.blue("Docs sync status (stub)"));
209
- console.log(chalk.dim(" Full docs sync will be available in server mode."));
211
+ .command("docs sync [plugin-name]")
212
+ .description("Sync documentation for plugins")
213
+ .action(async (pluginName) => {
214
+ console.log(chalk.blue(`◉ Syncing docs${pluginName ? ` for ${pluginName} plugin` : ""}`));
215
+ const engine = new KnowledgeEngine({ projectRoot: process.cwd() });
216
+ if (pluginName) {
217
+ const results = await engine.syncDocs(pluginName);
218
+ for (const r of results) {
219
+ if (r.added > 0) {
220
+ console.log(` ${chalk.green("✓")} ${r.source} → ${r.added} chunks`);
221
+ }
222
+ else {
223
+ console.log(` ${chalk.red("✗")} ${r.source} — ${r.errors.join(", ") || "no content"}`);
224
+ }
225
+ }
226
+ console.log(chalk.green(`\n ${pluginName} docs synced to .devflow/knowledge/${pluginName}/`));
227
+ }
228
+ else {
229
+ const sources = await engine.getSources();
230
+ for (const s of sources) {
231
+ const results = await engine.syncDocs(s.source.name);
232
+ for (const r of results) {
233
+ if (r.added > 0) {
234
+ console.log(` ${chalk.green("✓")} ${r.source} → ${r.added} chunks`);
235
+ }
236
+ else {
237
+ console.log(` ${chalk.red("✗")} ${r.source} — ${r.errors.join(", ") || "no content"}`);
238
+ }
239
+ }
240
+ }
241
+ console.log(chalk.green("\n All docs synced."));
242
+ }
210
243
  });
211
244
  // --- skill ---
212
245
  const skillCmd = program
@@ -216,7 +249,7 @@ skillCmd
216
249
  .command("list")
217
250
  .description("List installed skills")
218
251
  .action(async () => {
219
- const skills = await listSkills();
252
+ const skills = await listSkills(program.opts().local);
220
253
  if (skills.length === 0) {
221
254
  console.log(chalk.dim("No skills installed. Use 'devflow skill search' to find plugins."));
222
255
  return;
@@ -229,7 +262,7 @@ skillCmd
229
262
  .command("search <query>")
230
263
  .description("Search available plugins")
231
264
  .action(async (query) => {
232
- const results = await searchSkills(query);
265
+ const results = await searchSkills(query, program.opts().local);
233
266
  console.log(chalk.blue(`Search: "${query}"`));
234
267
  if (results.length === 0) {
235
268
  console.log(chalk.dim(" No matching plugins found."));
@@ -239,6 +272,35 @@ skillCmd
239
272
  console.log(` ${chalk.green(s.name)} @ ${s.version} — ${s.description}`);
240
273
  }
241
274
  });
275
+ skillCmd
276
+ .command("install <name>")
277
+ .description("Install a plugin/skill")
278
+ .action(async (name) => {
279
+ try {
280
+ const result = await installSkill(name, process.cwd(), program.opts().local);
281
+ console.log(chalk.green(`✓ Installed @devflow-tools/plugin-${result.name}@${result.version}`));
282
+ if (result.templates.length > 0) {
283
+ console.log(` Templates: ${result.templates.join(", ")}`);
284
+ }
285
+ }
286
+ catch (err) {
287
+ console.log(chalk.red(`Error: ${err.message}`));
288
+ process.exit(1);
289
+ }
290
+ });
291
+ skillCmd
292
+ .command("uninstall <name>")
293
+ .description("Uninstall a plugin/skill")
294
+ .action(async (name) => {
295
+ try {
296
+ await uninstallSkill(name, process.cwd(), program.opts().local);
297
+ console.log(chalk.green(`✓ Uninstalled ${name}`));
298
+ }
299
+ catch (err) {
300
+ console.log(chalk.red(`Error: ${err.message}`));
301
+ process.exit(1);
302
+ }
303
+ });
242
304
  // --- doctor ---
243
305
  program
244
306
  .command("doctor")
@@ -259,6 +321,14 @@ program
259
321
  console.log(chalk.bold("◉ Knowledge"));
260
322
  console.log(` Sources ${report.knowledge.sources}`);
261
323
  console.log();
324
+ console.log(chalk.bold("◉ Server"));
325
+ if (report.server.running) {
326
+ console.log(` ${chalk.green("✔")} Running on http://localhost:3100`);
327
+ }
328
+ else {
329
+ console.log(` ${chalk.yellow("○")} Not running — run \`devflow server start\` for telemetry`);
330
+ }
331
+ console.log();
262
332
  console.log(chalk.bold("◉ Plugins"));
263
333
  if (report.plugins.installed === 0) {
264
334
  console.log(` ${chalk.dim("No plugins installed")}`);
@@ -275,5 +345,60 @@ program
275
345
  const scoreColor = report.readyScore >= 70 ? chalk.green : report.readyScore >= 40 ? chalk.yellow : chalk.red;
276
346
  console.log(`AI Ready: ${scoreColor(report.readyScore + "%")}`);
277
347
  });
348
+ // --- benchmark ---
349
+ program
350
+ .command("benchmark [target]")
351
+ .description("Run benchmark on engines")
352
+ .option("--iterations <n>", "Number of iterations", "5")
353
+ .option("--output <format>", "json | text", "text")
354
+ .action(async (target, opts) => {
355
+ const output = await runBenchmark(target ?? "all", {
356
+ iterations: parseInt(opts.iterations, 10),
357
+ output: opts.output,
358
+ });
359
+ console.log(output);
360
+ });
361
+ // --- review ---
362
+ program
363
+ .command("review [pr-url]")
364
+ .description("Review a PR or current branch diff")
365
+ .option("--agent <agent>", "AI agent to use", "claude")
366
+ .action(async (prUrl, opts) => {
367
+ const output = await runReview({ prUrl, agent: opts.agent });
368
+ console.log(output);
369
+ });
370
+ // --- server ---
371
+ const serverCmd = program
372
+ .command("server")
373
+ .description("Manage DevFlow server");
374
+ serverCmd
375
+ .command("start")
376
+ .description("Start the DevFlow REST server")
377
+ .option("--port <n>", "Port number", "3100")
378
+ .action(async (opts) => {
379
+ console.log(chalk.blue("Starting DevFlow server..."));
380
+ const result = await startServer({ port: parseInt(opts.port, 10) });
381
+ console.log(chalk.green(`Server started (pid: ${result.pid}) on port ${opts.port}`));
382
+ });
383
+ serverCmd
384
+ .command("stop")
385
+ .description("Stop the DevFlow REST server")
386
+ .action(async () => {
387
+ const ok = await stopServer();
388
+ if (ok)
389
+ console.log(chalk.green("Server stopped"));
390
+ else
391
+ console.log(chalk.dim("No server running"));
392
+ });
393
+ serverCmd
394
+ .command("status")
395
+ .description("Show server status")
396
+ .action(async () => {
397
+ const status = await serverStatus();
398
+ if (status.running)
399
+ console.log(chalk.green(`Running (pid: ${status.pid})`));
400
+ else
401
+ console.log(chalk.yellow("Not running"));
402
+ });
278
403
  program.parse();
279
404
  //# sourceMappingURL=index.js.map