chainlesschain 0.37.9 → 0.37.11

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 (84) hide show
  1. package/README.md +309 -19
  2. package/bin/chainlesschain.js +4 -0
  3. package/package.json +1 -1
  4. package/src/commands/a2a.js +374 -0
  5. package/src/commands/audit.js +286 -0
  6. package/src/commands/auth.js +387 -0
  7. package/src/commands/bi.js +240 -0
  8. package/src/commands/browse.js +184 -0
  9. package/src/commands/cowork.js +317 -0
  10. package/src/commands/did.js +376 -0
  11. package/src/commands/economy.js +375 -0
  12. package/src/commands/encrypt.js +233 -0
  13. package/src/commands/evolution.js +398 -0
  14. package/src/commands/export.js +125 -0
  15. package/src/commands/git.js +215 -0
  16. package/src/commands/hmemory.js +273 -0
  17. package/src/commands/hook.js +260 -0
  18. package/src/commands/import.js +259 -0
  19. package/src/commands/init.js +184 -0
  20. package/src/commands/instinct.js +202 -0
  21. package/src/commands/llm.js +155 -4
  22. package/src/commands/lowcode.js +320 -0
  23. package/src/commands/mcp.js +302 -0
  24. package/src/commands/memory.js +282 -0
  25. package/src/commands/note.js +187 -0
  26. package/src/commands/org.js +505 -0
  27. package/src/commands/p2p.js +274 -0
  28. package/src/commands/plugin.js +451 -0
  29. package/src/commands/sandbox.js +366 -0
  30. package/src/commands/search.js +237 -0
  31. package/src/commands/session.js +238 -0
  32. package/src/commands/skill.js +254 -201
  33. package/src/commands/sync.js +249 -0
  34. package/src/commands/tokens.js +214 -0
  35. package/src/commands/wallet.js +416 -0
  36. package/src/commands/workflow.js +359 -0
  37. package/src/commands/zkp.js +277 -0
  38. package/src/index.js +93 -1
  39. package/src/lib/a2a-protocol.js +371 -0
  40. package/src/lib/agent-coordinator.js +273 -0
  41. package/src/lib/agent-economy.js +369 -0
  42. package/src/lib/app-builder.js +377 -0
  43. package/src/lib/audit-logger.js +364 -0
  44. package/src/lib/bi-engine.js +299 -0
  45. package/src/lib/bm25-search.js +322 -0
  46. package/src/lib/browser-automation.js +216 -0
  47. package/src/lib/cowork/ab-comparator-cli.js +180 -0
  48. package/src/lib/cowork/code-knowledge-graph-cli.js +232 -0
  49. package/src/lib/cowork/debate-review-cli.js +144 -0
  50. package/src/lib/cowork/decision-kb-cli.js +153 -0
  51. package/src/lib/cowork/project-style-analyzer-cli.js +168 -0
  52. package/src/lib/cowork-adapter.js +106 -0
  53. package/src/lib/crypto-manager.js +246 -0
  54. package/src/lib/did-manager.js +270 -0
  55. package/src/lib/ensure-utf8.js +59 -0
  56. package/src/lib/evolution-system.js +508 -0
  57. package/src/lib/git-integration.js +220 -0
  58. package/src/lib/hierarchical-memory.js +471 -0
  59. package/src/lib/hook-manager.js +387 -0
  60. package/src/lib/instinct-manager.js +190 -0
  61. package/src/lib/knowledge-exporter.js +302 -0
  62. package/src/lib/knowledge-importer.js +293 -0
  63. package/src/lib/llm-providers.js +325 -0
  64. package/src/lib/mcp-client.js +413 -0
  65. package/src/lib/memory-manager.js +211 -0
  66. package/src/lib/note-versioning.js +244 -0
  67. package/src/lib/org-manager.js +424 -0
  68. package/src/lib/p2p-manager.js +317 -0
  69. package/src/lib/pdf-parser.js +96 -0
  70. package/src/lib/permission-engine.js +374 -0
  71. package/src/lib/plan-mode.js +333 -0
  72. package/src/lib/plugin-manager.js +430 -0
  73. package/src/lib/project-detector.js +53 -0
  74. package/src/lib/response-cache.js +156 -0
  75. package/src/lib/sandbox-v2.js +503 -0
  76. package/src/lib/service-container.js +183 -0
  77. package/src/lib/session-manager.js +189 -0
  78. package/src/lib/skill-loader.js +274 -0
  79. package/src/lib/sync-manager.js +347 -0
  80. package/src/lib/token-tracker.js +200 -0
  81. package/src/lib/wallet-manager.js +348 -0
  82. package/src/lib/workflow-engine.js +503 -0
  83. package/src/lib/zkp-engine.js +241 -0
  84. package/src/repl/agent-repl.js +259 -124
@@ -0,0 +1,184 @@
1
+ /**
2
+ * Browser automation commands
3
+ * chainlesschain browse <url> | browse scrape <url> | browse screenshot <url>
4
+ */
5
+
6
+ import chalk from "chalk";
7
+ import ora from "ora";
8
+ import { logger } from "../lib/logger.js";
9
+ import {
10
+ fetchPage,
11
+ extractText,
12
+ extractTitle,
13
+ extractMeta,
14
+ querySelectorAll,
15
+ extractLinks,
16
+ takeScreenshot,
17
+ } from "../lib/browser-automation.js";
18
+
19
+ export function registerBrowseCommand(program) {
20
+ const browse = program
21
+ .command("browse")
22
+ .description("Headless browser automation and web scraping");
23
+
24
+ // browse fetch — fetch and display page content
25
+ browse
26
+ .command("fetch")
27
+ .description("Fetch a URL and display text content")
28
+ .argument("<url>", "URL to fetch")
29
+ .option("--html", "Show raw HTML instead of text")
30
+ .option("--links", "Extract links only")
31
+ .option("--json", "Output as JSON")
32
+ .action(async (url, options) => {
33
+ try {
34
+ const spinner = ora(`Fetching ${url}...`).start();
35
+ const result = await fetchPage(url);
36
+ spinner.stop();
37
+
38
+ const title = extractTitle(result.html);
39
+ const text = extractText(result.html);
40
+ const description = extractMeta(result.html);
41
+
42
+ if (options.json) {
43
+ const output = {
44
+ url: result.url,
45
+ status: result.status,
46
+ title,
47
+ description,
48
+ size: result.size,
49
+ };
50
+ if (options.html) output.html = result.html;
51
+ else if (options.links)
52
+ output.links = extractLinks(result.html, result.url);
53
+ else output.text = text;
54
+ console.log(JSON.stringify(output, null, 2));
55
+ return;
56
+ }
57
+
58
+ if (options.links) {
59
+ const links = extractLinks(result.html, result.url);
60
+ logger.log(
61
+ chalk.bold(`Links from ${title || url} (${links.length}):\n`),
62
+ );
63
+ for (const link of links.slice(0, 50)) {
64
+ logger.log(
65
+ ` ${chalk.cyan(link.text.substring(0, 60).padEnd(62))} ${chalk.gray(link.href)}`,
66
+ );
67
+ }
68
+ if (links.length > 50)
69
+ logger.log(chalk.gray(` ... and ${links.length - 50} more`));
70
+ return;
71
+ }
72
+
73
+ if (options.html) {
74
+ console.log(result.html);
75
+ return;
76
+ }
77
+
78
+ logger.log(chalk.bold(title || url));
79
+ if (description) logger.log(chalk.gray(description));
80
+ logger.log(
81
+ chalk.gray(`${result.size} bytes | ${result.contentType}\n`),
82
+ );
83
+ logger.log(text.substring(0, 5000));
84
+ if (text.length > 5000) {
85
+ logger.log(
86
+ chalk.gray(`\n... truncated (${text.length} chars total)`),
87
+ );
88
+ }
89
+ } catch (err) {
90
+ logger.error(`Fetch failed: ${err.message}`);
91
+ process.exit(1);
92
+ }
93
+ });
94
+
95
+ // browse scrape — scrape elements matching a CSS selector
96
+ browse
97
+ .command("scrape")
98
+ .description("Scrape elements from a URL using CSS selector")
99
+ .argument("<url>", "URL to scrape")
100
+ .requiredOption("-s, --selector <css>", "CSS selector (tag, .class, #id)")
101
+ .option("-n, --limit <n>", "Max results", "20")
102
+ .option("--json", "Output as JSON")
103
+ .action(async (url, options) => {
104
+ try {
105
+ const spinner = ora(`Scraping ${url}...`).start();
106
+ const result = await fetchPage(url);
107
+ const elements = querySelectorAll(result.html, options.selector);
108
+ spinner.stop();
109
+
110
+ const limit = parseInt(options.limit) || 20;
111
+ const limited = elements.slice(0, limit);
112
+
113
+ if (options.json) {
114
+ console.log(
115
+ JSON.stringify(
116
+ {
117
+ url: result.url,
118
+ selector: options.selector,
119
+ count: elements.length,
120
+ results: limited.map((e) => ({ text: e.text })),
121
+ },
122
+ null,
123
+ 2,
124
+ ),
125
+ );
126
+ return;
127
+ }
128
+
129
+ if (elements.length === 0) {
130
+ logger.info(`No elements matching "${options.selector}"`);
131
+ } else {
132
+ logger.log(
133
+ chalk.bold(
134
+ `Scraped ${elements.length} elements matching "${options.selector}":\n`,
135
+ ),
136
+ );
137
+ for (let i = 0; i < limited.length; i++) {
138
+ const text = limited[i].text.substring(0, 200).replace(/\n/g, " ");
139
+ logger.log(` ${chalk.gray(`[${i + 1}]`)} ${text}`);
140
+ }
141
+ if (elements.length > limit) {
142
+ logger.log(chalk.gray(` ... ${elements.length - limit} more`));
143
+ }
144
+ }
145
+ } catch (err) {
146
+ logger.error(`Scrape failed: ${err.message}`);
147
+ process.exit(1);
148
+ }
149
+ });
150
+
151
+ // browse screenshot — take a screenshot (requires playwright)
152
+ browse
153
+ .command("screenshot")
154
+ .description("Take a screenshot of a URL (requires playwright)")
155
+ .argument("<url>", "URL to screenshot")
156
+ .option("-o, --output <path>", "Output file path", "screenshot.png")
157
+ .option("--width <n>", "Viewport width", "1280")
158
+ .option("--height <n>", "Viewport height", "720")
159
+ .option("--full-page", "Capture full page")
160
+ .option("--json", "Output as JSON")
161
+ .action(async (url, options) => {
162
+ try {
163
+ const spinner = ora(`Taking screenshot of ${url}...`).start();
164
+ const result = await takeScreenshot(url, options.output, {
165
+ width: parseInt(options.width),
166
+ height: parseInt(options.height),
167
+ fullPage: !!options.fullPage,
168
+ });
169
+ spinner.stop();
170
+
171
+ if (options.json) {
172
+ console.log(JSON.stringify(result, null, 2));
173
+ } else if (result.success) {
174
+ logger.success(`Screenshot saved: ${chalk.cyan(result.path)}`);
175
+ } else {
176
+ logger.error(result.error);
177
+ logger.info("Install playwright: npm install -g playwright");
178
+ }
179
+ } catch (err) {
180
+ logger.error(`Screenshot failed: ${err.message}`);
181
+ process.exit(1);
182
+ }
183
+ });
184
+ }
@@ -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
+ }