chainlesschain 0.37.10 → 0.37.12
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/README.md +166 -10
- package/package.json +1 -1
- package/src/commands/a2a.js +374 -0
- package/src/commands/bi.js +240 -0
- package/src/commands/cowork.js +317 -0
- package/src/commands/economy.js +375 -0
- package/src/commands/evolution.js +398 -0
- package/src/commands/hmemory.js +273 -0
- package/src/commands/hook.js +260 -0
- package/src/commands/init.js +184 -0
- package/src/commands/lowcode.js +320 -0
- package/src/commands/plugin.js +55 -2
- package/src/commands/sandbox.js +366 -0
- package/src/commands/skill.js +254 -201
- package/src/commands/workflow.js +359 -0
- package/src/commands/zkp.js +277 -0
- package/src/index.js +44 -0
- package/src/lib/a2a-protocol.js +371 -0
- package/src/lib/agent-coordinator.js +273 -0
- package/src/lib/agent-economy.js +369 -0
- package/src/lib/app-builder.js +377 -0
- package/src/lib/bi-engine.js +299 -0
- package/src/lib/cowork/ab-comparator-cli.js +180 -0
- package/src/lib/cowork/code-knowledge-graph-cli.js +232 -0
- package/src/lib/cowork/debate-review-cli.js +144 -0
- package/src/lib/cowork/decision-kb-cli.js +153 -0
- package/src/lib/cowork/project-style-analyzer-cli.js +168 -0
- package/src/lib/cowork-adapter.js +106 -0
- package/src/lib/evolution-system.js +508 -0
- package/src/lib/hierarchical-memory.js +471 -0
- package/src/lib/hook-manager.js +387 -0
- package/src/lib/plugin-manager.js +118 -0
- package/src/lib/project-detector.js +53 -0
- package/src/lib/sandbox-v2.js +503 -0
- package/src/lib/service-container.js +183 -0
- package/src/lib/skill-loader.js +274 -0
- package/src/lib/workflow-engine.js +503 -0
- package/src/lib/zkp-engine.js +241 -0
- package/src/repl/agent-repl.js +117 -112
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BI commands
|
|
3
|
+
* chainlesschain bi query|dashboard|report|schedule|anomaly|predict|templates
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import chalk from "chalk";
|
|
7
|
+
import { logger } from "../lib/logger.js";
|
|
8
|
+
import { bootstrap, shutdown } from "../runtime/bootstrap.js";
|
|
9
|
+
import {
|
|
10
|
+
ensureBITables,
|
|
11
|
+
nlQuery,
|
|
12
|
+
createDashboard,
|
|
13
|
+
generateReport,
|
|
14
|
+
scheduleReport,
|
|
15
|
+
detectAnomaly,
|
|
16
|
+
predictTrend,
|
|
17
|
+
listTemplates,
|
|
18
|
+
} from "../lib/bi-engine.js";
|
|
19
|
+
|
|
20
|
+
export function registerBiCommand(program) {
|
|
21
|
+
const bi = program
|
|
22
|
+
.command("bi")
|
|
23
|
+
.description(
|
|
24
|
+
"Business intelligence — queries, dashboards, reports, analytics",
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
// bi query
|
|
28
|
+
bi.command("query <question>")
|
|
29
|
+
.description("Natural-language query (NL→SQL)")
|
|
30
|
+
.option("--json", "Output as JSON")
|
|
31
|
+
.action(async (question, options) => {
|
|
32
|
+
try {
|
|
33
|
+
const result = nlQuery(question);
|
|
34
|
+
if (options.json) {
|
|
35
|
+
console.log(JSON.stringify(result, null, 2));
|
|
36
|
+
} else {
|
|
37
|
+
logger.success("Query translated");
|
|
38
|
+
logger.log(
|
|
39
|
+
` ${chalk.bold("SQL:")} ${chalk.cyan(result.generatedSQL)}`,
|
|
40
|
+
);
|
|
41
|
+
logger.log(` ${chalk.bold("Rows:")} ${result.rowCount}`);
|
|
42
|
+
logger.log(` ${chalk.bold("Visual:")} ${result.visualization.type}`);
|
|
43
|
+
}
|
|
44
|
+
} catch (err) {
|
|
45
|
+
logger.error(`Failed: ${err.message}`);
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// bi dashboard
|
|
51
|
+
bi.command("dashboard <name>")
|
|
52
|
+
.description("Create a dashboard")
|
|
53
|
+
.option("--widgets <json>", "Widgets as JSON array")
|
|
54
|
+
.option("--layout <json>", "Layout as JSON")
|
|
55
|
+
.option("--json", "Output as JSON")
|
|
56
|
+
.action(async (name, options) => {
|
|
57
|
+
try {
|
|
58
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
59
|
+
if (!ctx.db) {
|
|
60
|
+
logger.error("Database not available");
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
const db = ctx.db.getDatabase();
|
|
64
|
+
ensureBITables(db);
|
|
65
|
+
|
|
66
|
+
const widgets = options.widgets ? JSON.parse(options.widgets) : [];
|
|
67
|
+
const layout = options.layout ? JSON.parse(options.layout) : undefined;
|
|
68
|
+
const dashboard = createDashboard(db, name, widgets, layout);
|
|
69
|
+
|
|
70
|
+
if (options.json) {
|
|
71
|
+
console.log(JSON.stringify(dashboard, null, 2));
|
|
72
|
+
} else {
|
|
73
|
+
logger.success(`Dashboard created: ${chalk.cyan(name)}`);
|
|
74
|
+
logger.log(` ${chalk.bold("ID:")} ${chalk.cyan(dashboard.id)}`);
|
|
75
|
+
logger.log(` ${chalk.bold("Widgets:")} ${dashboard.widgets.length}`);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
await shutdown();
|
|
79
|
+
} catch (err) {
|
|
80
|
+
logger.error(`Failed: ${err.message}`);
|
|
81
|
+
process.exit(1);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// bi report
|
|
86
|
+
bi.command("report <name>")
|
|
87
|
+
.description("Generate a report")
|
|
88
|
+
.option("--format <pdf|excel>", "Report format", "pdf")
|
|
89
|
+
.option("--sections <csv>", "Comma-separated section names")
|
|
90
|
+
.option("--json", "Output as JSON")
|
|
91
|
+
.action(async (name, options) => {
|
|
92
|
+
try {
|
|
93
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
94
|
+
if (!ctx.db) {
|
|
95
|
+
logger.error("Database not available");
|
|
96
|
+
process.exit(1);
|
|
97
|
+
}
|
|
98
|
+
const db = ctx.db.getDatabase();
|
|
99
|
+
ensureBITables(db);
|
|
100
|
+
|
|
101
|
+
const sections = options.sections
|
|
102
|
+
? options.sections.split(",").map((s) => s.trim())
|
|
103
|
+
: undefined;
|
|
104
|
+
const report = generateReport(db, name, {
|
|
105
|
+
format: options.format,
|
|
106
|
+
sections,
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
if (options.json) {
|
|
110
|
+
console.log(JSON.stringify(report, null, 2));
|
|
111
|
+
} else {
|
|
112
|
+
logger.success(`Report generated: ${chalk.cyan(name)}`);
|
|
113
|
+
logger.log(` ${chalk.bold("ID:")} ${chalk.cyan(report.id)}`);
|
|
114
|
+
logger.log(` ${chalk.bold("Format:")} ${report.format}`);
|
|
115
|
+
logger.log(` ${chalk.bold("Sections:")} ${report.sections.length}`);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
await shutdown();
|
|
119
|
+
} catch (err) {
|
|
120
|
+
logger.error(`Failed: ${err.message}`);
|
|
121
|
+
process.exit(1);
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// bi schedule
|
|
126
|
+
bi.command("schedule <report-id> <cron>")
|
|
127
|
+
.description("Schedule a report for recurring generation")
|
|
128
|
+
.option("--recipients <csv>", "Comma-separated recipient emails")
|
|
129
|
+
.action(async (reportId, cron, options) => {
|
|
130
|
+
try {
|
|
131
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
132
|
+
if (!ctx.db) {
|
|
133
|
+
logger.error("Database not available");
|
|
134
|
+
process.exit(1);
|
|
135
|
+
}
|
|
136
|
+
const db = ctx.db.getDatabase();
|
|
137
|
+
ensureBITables(db);
|
|
138
|
+
|
|
139
|
+
const recipients = options.recipients
|
|
140
|
+
? options.recipients.split(",").map((s) => s.trim())
|
|
141
|
+
: [];
|
|
142
|
+
const schedule = scheduleReport(db, reportId, cron, recipients);
|
|
143
|
+
logger.success("Report scheduled");
|
|
144
|
+
logger.log(` ${chalk.bold("ID:")} ${chalk.cyan(schedule.id)}`);
|
|
145
|
+
logger.log(` ${chalk.bold("Cron:")} ${schedule.cron}`);
|
|
146
|
+
logger.log(
|
|
147
|
+
` ${chalk.bold("Recipients:")} ${schedule.recipients.length}`,
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
await shutdown();
|
|
151
|
+
} catch (err) {
|
|
152
|
+
logger.error(`Failed: ${err.message}`);
|
|
153
|
+
process.exit(1);
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
// bi anomaly
|
|
158
|
+
bi.command("anomaly")
|
|
159
|
+
.description("Detect anomalies in data using Z-score")
|
|
160
|
+
.option("--data <json>", "Data as JSON array of numbers")
|
|
161
|
+
.option("--threshold <n>", "Z-score threshold", "2")
|
|
162
|
+
.option("--json", "Output as JSON")
|
|
163
|
+
.action(async (options) => {
|
|
164
|
+
try {
|
|
165
|
+
const data = options.data ? JSON.parse(options.data) : [];
|
|
166
|
+
const result = detectAnomaly(data, {
|
|
167
|
+
threshold: parseFloat(options.threshold),
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
if (options.json) {
|
|
171
|
+
console.log(JSON.stringify(result, null, 2));
|
|
172
|
+
} else {
|
|
173
|
+
logger.log(` ${chalk.bold("Mean:")} ${result.mean.toFixed(2)}`);
|
|
174
|
+
logger.log(` ${chalk.bold("Std Dev:")} ${result.std.toFixed(2)}`);
|
|
175
|
+
logger.log(` ${chalk.bold("Threshold:")} ${result.threshold}`);
|
|
176
|
+
logger.log(
|
|
177
|
+
` ${chalk.bold("Anomalies:")} ${result.anomalies.length}`,
|
|
178
|
+
);
|
|
179
|
+
for (const a of result.anomalies) {
|
|
180
|
+
logger.log(
|
|
181
|
+
` [${a.index}] value=${a.value} z=${a.zScore.toFixed(2)}`,
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
} catch (err) {
|
|
186
|
+
logger.error(`Failed: ${err.message}`);
|
|
187
|
+
process.exit(1);
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
// bi predict
|
|
192
|
+
bi.command("predict")
|
|
193
|
+
.description("Predict trend using linear regression")
|
|
194
|
+
.option("--data <json>", "Data as JSON array of numbers")
|
|
195
|
+
.option("--periods <n>", "Number of periods to predict", "3")
|
|
196
|
+
.option("--json", "Output as JSON")
|
|
197
|
+
.action(async (options) => {
|
|
198
|
+
try {
|
|
199
|
+
const data = options.data ? JSON.parse(options.data) : [];
|
|
200
|
+
const result = predictTrend(data, parseInt(options.periods));
|
|
201
|
+
|
|
202
|
+
if (options.json) {
|
|
203
|
+
console.log(JSON.stringify(result, null, 2));
|
|
204
|
+
} else {
|
|
205
|
+
logger.log(
|
|
206
|
+
` ${chalk.bold("Trend:")} ${chalk.cyan(result.trend)}`,
|
|
207
|
+
);
|
|
208
|
+
logger.log(` ${chalk.bold("Slope:")} ${result.slope}`);
|
|
209
|
+
logger.log(
|
|
210
|
+
` ${chalk.bold("Predictions:")} ${result.predictions.join(", ")}`,
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
} catch (err) {
|
|
214
|
+
logger.error(`Failed: ${err.message}`);
|
|
215
|
+
process.exit(1);
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
// bi templates
|
|
220
|
+
bi.command("templates")
|
|
221
|
+
.description("List available BI templates")
|
|
222
|
+
.option("--json", "Output as JSON")
|
|
223
|
+
.action(async (options) => {
|
|
224
|
+
try {
|
|
225
|
+
const templates = listTemplates();
|
|
226
|
+
if (options.json) {
|
|
227
|
+
console.log(JSON.stringify(templates, null, 2));
|
|
228
|
+
} else {
|
|
229
|
+
for (const t of templates) {
|
|
230
|
+
logger.log(
|
|
231
|
+
` ${chalk.cyan(t.id)} ${chalk.bold(t.name)} — ${t.description}`,
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
} catch (err) {
|
|
236
|
+
logger.error(`Failed: ${err.message}`);
|
|
237
|
+
process.exit(1);
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
}
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-agent collaboration commands
|
|
3
|
+
* chainlesschain cowork debate|compare|analyze|status
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import chalk from "chalk";
|
|
7
|
+
import ora from "ora";
|
|
8
|
+
import fs from "fs";
|
|
9
|
+
import path from "path";
|
|
10
|
+
import { logger } from "../lib/logger.js";
|
|
11
|
+
|
|
12
|
+
export function registerCoworkCommand(program) {
|
|
13
|
+
const cowork = program
|
|
14
|
+
.command("cowork")
|
|
15
|
+
.description(
|
|
16
|
+
"Multi-agent collaboration (debate review, A/B comparison, analysis)",
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
// cowork debate — multi-perspective code review
|
|
20
|
+
cowork
|
|
21
|
+
.command("debate")
|
|
22
|
+
.description("Multi-agent debate review of a file or topic")
|
|
23
|
+
.argument("<file-or-topic>", "File path to review, or a topic/question")
|
|
24
|
+
.option(
|
|
25
|
+
"--perspectives <list>",
|
|
26
|
+
"Comma-separated perspectives (performance,security,maintainability,correctness,architecture)",
|
|
27
|
+
"performance,security,maintainability",
|
|
28
|
+
)
|
|
29
|
+
.option("--provider <name>", "LLM provider to use")
|
|
30
|
+
.option("--model <name>", "LLM model to use")
|
|
31
|
+
.option("--json", "Output as JSON")
|
|
32
|
+
.action(async (target, options) => {
|
|
33
|
+
const { startDebate, DEFAULT_PERSPECTIVES } =
|
|
34
|
+
await import("../lib/cowork/debate-review-cli.js");
|
|
35
|
+
|
|
36
|
+
const perspectives = options.perspectives
|
|
37
|
+
.split(",")
|
|
38
|
+
.map((p) => p.trim())
|
|
39
|
+
.filter(Boolean);
|
|
40
|
+
|
|
41
|
+
// Read file content if target is a file path
|
|
42
|
+
let code = target;
|
|
43
|
+
let targetLabel = target;
|
|
44
|
+
const resolved = path.resolve(target);
|
|
45
|
+
if (fs.existsSync(resolved)) {
|
|
46
|
+
try {
|
|
47
|
+
code = fs.readFileSync(resolved, "utf-8");
|
|
48
|
+
targetLabel = resolved;
|
|
49
|
+
if (code.length > 15000) {
|
|
50
|
+
code = code.substring(0, 15000) + "\n... (truncated)";
|
|
51
|
+
}
|
|
52
|
+
} catch (err) {
|
|
53
|
+
logger.error(`Cannot read file: ${err.message}`);
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const spinner = ora(
|
|
59
|
+
`Running debate review with ${perspectives.length} perspectives...`,
|
|
60
|
+
).start();
|
|
61
|
+
|
|
62
|
+
try {
|
|
63
|
+
const llmOptions = {};
|
|
64
|
+
if (options.provider) llmOptions.provider = options.provider;
|
|
65
|
+
if (options.model) llmOptions.model = options.model;
|
|
66
|
+
|
|
67
|
+
const result = await startDebate({
|
|
68
|
+
target: targetLabel,
|
|
69
|
+
code,
|
|
70
|
+
perspectives,
|
|
71
|
+
llmOptions,
|
|
72
|
+
});
|
|
73
|
+
spinner.stop();
|
|
74
|
+
|
|
75
|
+
if (options.json) {
|
|
76
|
+
console.log(JSON.stringify(result, null, 2));
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Display results
|
|
81
|
+
logger.log(chalk.bold(`\nDebate Review: ${targetLabel}\n`));
|
|
82
|
+
|
|
83
|
+
for (const review of result.reviews) {
|
|
84
|
+
const verdictColor =
|
|
85
|
+
review.verdict === "APPROVE"
|
|
86
|
+
? chalk.green
|
|
87
|
+
: review.verdict === "REJECT"
|
|
88
|
+
? chalk.red
|
|
89
|
+
: chalk.yellow;
|
|
90
|
+
logger.log(
|
|
91
|
+
chalk.bold(` ${review.role}: `) + verdictColor(review.verdict),
|
|
92
|
+
);
|
|
93
|
+
// Show first few lines of the review
|
|
94
|
+
const lines = review.review.split("\n").slice(0, 8);
|
|
95
|
+
for (const line of lines) {
|
|
96
|
+
logger.log(chalk.gray(` ${line}`));
|
|
97
|
+
}
|
|
98
|
+
if (review.review.split("\n").length > 8) {
|
|
99
|
+
logger.log(chalk.gray(" ..."));
|
|
100
|
+
}
|
|
101
|
+
logger.log("");
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
logger.log(chalk.bold("Final Verdict"));
|
|
105
|
+
const verdictColor =
|
|
106
|
+
result.verdict === "APPROVE"
|
|
107
|
+
? chalk.green
|
|
108
|
+
: result.verdict === "REJECT"
|
|
109
|
+
? chalk.red
|
|
110
|
+
: chalk.yellow;
|
|
111
|
+
logger.log(` Verdict: ${verdictColor(result.verdict)}`);
|
|
112
|
+
logger.log(` Consensus: ${result.consensusScore}%`);
|
|
113
|
+
logger.log("");
|
|
114
|
+
|
|
115
|
+
// Show moderator summary
|
|
116
|
+
const summaryLines = result.summary.split("\n").slice(0, 15);
|
|
117
|
+
for (const line of summaryLines) {
|
|
118
|
+
logger.log(chalk.gray(` ${line}`));
|
|
119
|
+
}
|
|
120
|
+
logger.log("");
|
|
121
|
+
} catch (err) {
|
|
122
|
+
spinner.fail(`Debate review failed: ${err.message}`);
|
|
123
|
+
if (program.opts().verbose) console.error(err.stack);
|
|
124
|
+
process.exit(1);
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
// cowork compare — A/B solution comparison
|
|
129
|
+
cowork
|
|
130
|
+
.command("compare")
|
|
131
|
+
.description("Generate and compare multiple solution variants")
|
|
132
|
+
.argument("<prompt>", "Task or problem description")
|
|
133
|
+
.option("--variants <n>", "Number of variants to generate (max 4)", "3")
|
|
134
|
+
.option(
|
|
135
|
+
"--criteria <list>",
|
|
136
|
+
"Comma-separated evaluation criteria",
|
|
137
|
+
"quality,performance,readability",
|
|
138
|
+
)
|
|
139
|
+
.option("--provider <name>", "LLM provider to use")
|
|
140
|
+
.option("--model <name>", "LLM model to use")
|
|
141
|
+
.option("--json", "Output as JSON")
|
|
142
|
+
.action(async (prompt, options) => {
|
|
143
|
+
const { compare } = await import("../lib/cowork/ab-comparator-cli.js");
|
|
144
|
+
|
|
145
|
+
const variants = parseInt(options.variants, 10) || 3;
|
|
146
|
+
const criteria = options.criteria
|
|
147
|
+
.split(",")
|
|
148
|
+
.map((c) => c.trim())
|
|
149
|
+
.filter(Boolean);
|
|
150
|
+
|
|
151
|
+
const spinner = ora(
|
|
152
|
+
`Generating ${variants} solution variants...`,
|
|
153
|
+
).start();
|
|
154
|
+
|
|
155
|
+
try {
|
|
156
|
+
const llmOptions = {};
|
|
157
|
+
if (options.provider) llmOptions.provider = options.provider;
|
|
158
|
+
if (options.model) llmOptions.model = options.model;
|
|
159
|
+
|
|
160
|
+
const result = await compare({
|
|
161
|
+
prompt,
|
|
162
|
+
variants,
|
|
163
|
+
criteria,
|
|
164
|
+
llmOptions,
|
|
165
|
+
});
|
|
166
|
+
spinner.stop();
|
|
167
|
+
|
|
168
|
+
if (options.json) {
|
|
169
|
+
console.log(JSON.stringify(result, null, 2));
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
logger.log(chalk.bold(`\nA/B Comparison: ${prompt}\n`));
|
|
174
|
+
logger.log(chalk.gray(`Criteria: ${criteria.join(", ")}\n`));
|
|
175
|
+
|
|
176
|
+
for (const v of result.variants) {
|
|
177
|
+
logger.log(
|
|
178
|
+
chalk.bold(` Variant: ${chalk.cyan(v.name)}`) +
|
|
179
|
+
chalk.gray(` (total: ${v.totalScore})`),
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
// Show scores
|
|
183
|
+
if (v.scores && Object.keys(v.scores).length > 0) {
|
|
184
|
+
const scoreStr = Object.entries(v.scores)
|
|
185
|
+
.map(([k, val]) => `${k}=${val}`)
|
|
186
|
+
.join(", ");
|
|
187
|
+
logger.log(chalk.gray(` Scores: ${scoreStr}`));
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Show first lines of solution
|
|
191
|
+
const lines = v.solution.split("\n").slice(0, 6);
|
|
192
|
+
for (const line of lines) {
|
|
193
|
+
logger.log(chalk.gray(` ${line}`));
|
|
194
|
+
}
|
|
195
|
+
if (v.solution.split("\n").length > 6) {
|
|
196
|
+
logger.log(chalk.gray(" ..."));
|
|
197
|
+
}
|
|
198
|
+
logger.log("");
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
logger.log(chalk.bold("Result"));
|
|
202
|
+
logger.log(` Winner: ${chalk.green(result.winner)}`);
|
|
203
|
+
logger.log(` Reason: ${chalk.gray(result.reason)}`);
|
|
204
|
+
if (result.ranking.length > 0) {
|
|
205
|
+
logger.log(
|
|
206
|
+
` Ranking: ${result.ranking.map((r, i) => (i === 0 ? chalk.green(r) : chalk.gray(r))).join(" > ")}`,
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
logger.log("");
|
|
210
|
+
} catch (err) {
|
|
211
|
+
spinner.fail(`Comparison failed: ${err.message}`);
|
|
212
|
+
if (program.opts().verbose) console.error(err.stack);
|
|
213
|
+
process.exit(1);
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
// cowork analyze — code analysis (Phase 4B placeholder, delegates to knowledge modules)
|
|
218
|
+
cowork
|
|
219
|
+
.command("analyze")
|
|
220
|
+
.description("Analyze code structure, style, or knowledge graph")
|
|
221
|
+
.argument("<path>", "File or directory to analyze")
|
|
222
|
+
.option(
|
|
223
|
+
"--type <type>",
|
|
224
|
+
"Analysis type (style, knowledge-graph, decisions)",
|
|
225
|
+
"style",
|
|
226
|
+
)
|
|
227
|
+
.option("--provider <name>", "LLM provider to use")
|
|
228
|
+
.option("--model <name>", "LLM model to use")
|
|
229
|
+
.option("--json", "Output as JSON")
|
|
230
|
+
.action(async (targetPath, options) => {
|
|
231
|
+
const resolved = path.resolve(targetPath);
|
|
232
|
+
if (!fs.existsSync(resolved)) {
|
|
233
|
+
logger.error(`Path not found: ${resolved}`);
|
|
234
|
+
process.exit(1);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
const spinner = ora(`Analyzing (${options.type})...`).start();
|
|
238
|
+
|
|
239
|
+
try {
|
|
240
|
+
let result;
|
|
241
|
+
|
|
242
|
+
if (options.type === "style") {
|
|
243
|
+
const { analyzeProjectStyle } =
|
|
244
|
+
await import("../lib/cowork/project-style-analyzer-cli.js");
|
|
245
|
+
const llmOptions = {};
|
|
246
|
+
if (options.provider) llmOptions.provider = options.provider;
|
|
247
|
+
if (options.model) llmOptions.model = options.model;
|
|
248
|
+
result = await analyzeProjectStyle({
|
|
249
|
+
targetPath: resolved,
|
|
250
|
+
llmOptions,
|
|
251
|
+
});
|
|
252
|
+
} else if (options.type === "knowledge-graph") {
|
|
253
|
+
const { buildKnowledgeGraph } =
|
|
254
|
+
await import("../lib/cowork/code-knowledge-graph-cli.js");
|
|
255
|
+
result = await buildKnowledgeGraph({ targetPath: resolved });
|
|
256
|
+
} else if (options.type === "decisions") {
|
|
257
|
+
const { extractDecisions } =
|
|
258
|
+
await import("../lib/cowork/decision-kb-cli.js");
|
|
259
|
+
const llmOptions = {};
|
|
260
|
+
if (options.provider) llmOptions.provider = options.provider;
|
|
261
|
+
if (options.model) llmOptions.model = options.model;
|
|
262
|
+
result = await extractDecisions({
|
|
263
|
+
targetPath: resolved,
|
|
264
|
+
llmOptions,
|
|
265
|
+
});
|
|
266
|
+
} else {
|
|
267
|
+
spinner.fail(`Unknown analysis type: ${options.type}`);
|
|
268
|
+
process.exit(1);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
spinner.stop();
|
|
272
|
+
|
|
273
|
+
if (options.json) {
|
|
274
|
+
console.log(JSON.stringify(result, null, 2));
|
|
275
|
+
} else {
|
|
276
|
+
logger.log(
|
|
277
|
+
chalk.bold(`\nAnalysis (${options.type}): ${targetPath}\n`),
|
|
278
|
+
);
|
|
279
|
+
if (result.summary) {
|
|
280
|
+
logger.log(result.summary);
|
|
281
|
+
} else {
|
|
282
|
+
console.log(JSON.stringify(result, null, 2));
|
|
283
|
+
}
|
|
284
|
+
logger.log("");
|
|
285
|
+
}
|
|
286
|
+
} catch (err) {
|
|
287
|
+
spinner.fail(`Analysis failed: ${err.message}`);
|
|
288
|
+
if (program.opts().verbose) console.error(err.stack);
|
|
289
|
+
process.exit(1);
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
// cowork status — show collaboration state
|
|
294
|
+
cowork
|
|
295
|
+
.command("status")
|
|
296
|
+
.description("Show cowork collaboration status")
|
|
297
|
+
.action(async () => {
|
|
298
|
+
logger.log(chalk.bold("\nCowork Status\n"));
|
|
299
|
+
logger.log(` Available commands:`);
|
|
300
|
+
logger.log(
|
|
301
|
+
` ${chalk.cyan("cowork debate <file>")} Multi-perspective code review`,
|
|
302
|
+
);
|
|
303
|
+
logger.log(
|
|
304
|
+
` ${chalk.cyan("cowork compare <prompt>")} A/B solution comparison`,
|
|
305
|
+
);
|
|
306
|
+
logger.log(
|
|
307
|
+
` ${chalk.cyan("cowork analyze <path>")} Code analysis (style/knowledge-graph/decisions)`,
|
|
308
|
+
);
|
|
309
|
+
logger.log("");
|
|
310
|
+
logger.log(
|
|
311
|
+
chalk.gray(
|
|
312
|
+
" All commands use the configured LLM provider. Override with --provider/--model.",
|
|
313
|
+
),
|
|
314
|
+
);
|
|
315
|
+
logger.log("");
|
|
316
|
+
});
|
|
317
|
+
}
|