chainlesschain 0.47.9 → 0.51.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.
- package/bin/chainlesschain.js +0 -0
- package/package.json +1 -1
- package/src/assets/web-panel/.build-hash +1 -1
- package/src/assets/web-panel/assets/{AppLayout-6SPt_8Y_.js → AppLayout-Rvi759IS.js} +1 -1
- package/src/assets/web-panel/assets/Dashboard-BS-tzGNj.css +1 -0
- package/src/assets/web-panel/assets/{Dashboard-Br7kCwKJ.js → Dashboard-DBhFxXYQ.js} +2 -2
- package/src/assets/web-panel/assets/{index-tN-8TosE.js → index-uL0cZ8N_.js} +2 -2
- package/src/assets/web-panel/index.html +2 -2
- package/src/commands/codegen.js +303 -0
- package/src/commands/collab.js +482 -0
- package/src/commands/crosschain.js +382 -0
- package/src/commands/dbevo.js +388 -0
- package/src/commands/dev.js +411 -0
- package/src/commands/federation.js +427 -0
- package/src/commands/fusion.js +332 -0
- package/src/commands/governance.js +505 -0
- package/src/commands/hardening.js +110 -0
- package/src/commands/incentive.js +373 -0
- package/src/commands/inference.js +304 -0
- package/src/commands/infra.js +361 -0
- package/src/commands/ipfs.js +392 -0
- package/src/commands/kg.js +371 -0
- package/src/commands/marketplace.js +326 -0
- package/src/commands/mcp.js +97 -18
- package/src/commands/multimodal.js +404 -0
- package/src/commands/nlprog.js +329 -0
- package/src/commands/ops.js +408 -0
- package/src/commands/perception.js +385 -0
- package/src/commands/pqc.js +34 -0
- package/src/commands/privacy.js +345 -0
- package/src/commands/quantization.js +280 -0
- package/src/commands/recommend.js +336 -0
- package/src/commands/reputation.js +349 -0
- package/src/commands/runtime.js +500 -0
- package/src/commands/sla.js +352 -0
- package/src/commands/stress.js +252 -0
- package/src/commands/tech.js +268 -0
- package/src/commands/tenant.js +576 -0
- package/src/commands/trust.js +366 -0
- package/src/harness/mcp-client.js +330 -54
- package/src/index.js +118 -0
- package/src/lib/aiops.js +523 -0
- package/src/lib/autonomous-developer.js +524 -0
- package/src/lib/code-agent.js +442 -0
- package/src/lib/collaboration-governance.js +556 -0
- package/src/lib/community-governance.js +649 -0
- package/src/lib/content-recommendation.js +600 -0
- package/src/lib/cross-chain.js +669 -0
- package/src/lib/dbevo.js +669 -0
- package/src/lib/decentral-infra.js +445 -0
- package/src/lib/federation-hardening.js +587 -0
- package/src/lib/hardening-manager.js +409 -0
- package/src/lib/inference-network.js +407 -0
- package/src/lib/ipfs-storage.js +575 -0
- package/src/lib/knowledge-graph.js +530 -0
- package/src/lib/mcp-client.js +3 -0
- package/src/lib/multimodal.js +725 -0
- package/src/lib/nl-programming.js +595 -0
- package/src/lib/perception.js +500 -0
- package/src/lib/pqc-manager.js +141 -9
- package/src/lib/privacy-computing.js +575 -0
- package/src/lib/protocol-fusion.js +535 -0
- package/src/lib/quantization.js +362 -0
- package/src/lib/reputation-optimizer.js +509 -0
- package/src/lib/skill-marketplace.js +397 -0
- package/src/lib/sla-manager.js +484 -0
- package/src/lib/stress-tester.js +383 -0
- package/src/lib/tech-learning-engine.js +651 -0
- package/src/lib/tenant-saas.js +831 -0
- package/src/lib/token-incentive.js +513 -0
- package/src/lib/trust-security.js +473 -0
- package/src/lib/universal-runtime.js +771 -0
- package/src/assets/web-panel/assets/Dashboard-CKeMmCoT.css +0 -1
package/src/commands/mcp.js
CHANGED
|
@@ -9,7 +9,11 @@ import chalk from "chalk";
|
|
|
9
9
|
import ora from "ora";
|
|
10
10
|
import { logger } from "../lib/logger.js";
|
|
11
11
|
import { bootstrap, shutdown } from "../runtime/bootstrap.js";
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
MCPClient,
|
|
14
|
+
MCPServerConfig,
|
|
15
|
+
inferTransport,
|
|
16
|
+
} from "../harness/mcp-client.js";
|
|
13
17
|
import {
|
|
14
18
|
validateMcpServer,
|
|
15
19
|
annotateMcpCompatibility,
|
|
@@ -111,9 +115,15 @@ export function registerMcpCommand(program) {
|
|
|
111
115
|
? chalk.green(" [ok]")
|
|
112
116
|
: chalk.yellow(` [blocked: ${s._reason}]`);
|
|
113
117
|
logger.log(` ${chalk.cyan(s.name)}${auto}${flag}`);
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
118
|
+
if (s.url) {
|
|
119
|
+
logger.log(
|
|
120
|
+
` ${chalk.gray("URL:")} ${s.url} ${chalk.gray(`[${s.transport || s._transport || "http"}]`)}`,
|
|
121
|
+
);
|
|
122
|
+
} else {
|
|
123
|
+
logger.log(
|
|
124
|
+
` ${chalk.gray("Command:")} ${s.command} ${s.args.join(" ")}`,
|
|
125
|
+
);
|
|
126
|
+
}
|
|
117
127
|
logger.log(
|
|
118
128
|
` ${chalk.gray("Compatible:")} ${s._modeCompatibility.join(", ") || "(none)"}`,
|
|
119
129
|
);
|
|
@@ -132,8 +142,20 @@ export function registerMcpCommand(program) {
|
|
|
132
142
|
.command("add")
|
|
133
143
|
.description("Add or update an MCP server configuration")
|
|
134
144
|
.argument("<name>", "Server name")
|
|
135
|
-
.
|
|
145
|
+
.option("-c, --command <cmd>", "Server command to run (stdio transport)")
|
|
136
146
|
.option("-a, --args <args>", "Command arguments (comma-separated)")
|
|
147
|
+
.option(
|
|
148
|
+
"-u, --url <url>",
|
|
149
|
+
"Server URL (http / https / ws / wss transports)",
|
|
150
|
+
)
|
|
151
|
+
.option(
|
|
152
|
+
"-t, --transport <kind>",
|
|
153
|
+
"Transport kind: stdio | http | https | sse | ws | wss",
|
|
154
|
+
)
|
|
155
|
+
.option(
|
|
156
|
+
"-H, --header <header...>",
|
|
157
|
+
"HTTP header to include on requests (KEY=VALUE, repeatable)",
|
|
158
|
+
)
|
|
137
159
|
.option("--auto-connect", "Auto-connect on startup")
|
|
138
160
|
.option(
|
|
139
161
|
"--mode <mode>",
|
|
@@ -142,6 +164,17 @@ export function registerMcpCommand(program) {
|
|
|
142
164
|
.option("--json", "Output as JSON")
|
|
143
165
|
.action(async (name, options) => {
|
|
144
166
|
try {
|
|
167
|
+
if (!options.command && !options.url) {
|
|
168
|
+
logger.error(
|
|
169
|
+
"Provide either -c <command> (stdio) or -u <url> (http/ws).",
|
|
170
|
+
);
|
|
171
|
+
process.exit(1);
|
|
172
|
+
}
|
|
173
|
+
if (options.command && options.url) {
|
|
174
|
+
logger.error("Use either -c <command> or -u <url>, not both.");
|
|
175
|
+
process.exit(1);
|
|
176
|
+
}
|
|
177
|
+
|
|
145
178
|
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
146
179
|
if (!ctx.db) {
|
|
147
180
|
logger.error("Database not available");
|
|
@@ -154,9 +187,43 @@ export function registerMcpCommand(program) {
|
|
|
154
187
|
? options.args.split(",").map((a) => a.trim())
|
|
155
188
|
: [];
|
|
156
189
|
|
|
190
|
+
// Parse -H KEY=VALUE into { headers }
|
|
191
|
+
const headers = {};
|
|
192
|
+
if (Array.isArray(options.header)) {
|
|
193
|
+
for (const raw of options.header) {
|
|
194
|
+
const eq = raw.indexOf("=");
|
|
195
|
+
if (eq <= 0) {
|
|
196
|
+
logger.warn(
|
|
197
|
+
`Ignored malformed --header "${raw}" (expected KEY=VALUE)`,
|
|
198
|
+
);
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
headers[raw.slice(0, eq).trim()] = raw.slice(eq + 1);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const transport =
|
|
206
|
+
options.transport ||
|
|
207
|
+
(options.url ? inferTransport({ url: options.url }) : "stdio");
|
|
208
|
+
|
|
209
|
+
if (options.url) {
|
|
210
|
+
try {
|
|
211
|
+
new URL(options.url);
|
|
212
|
+
} catch (_e) {
|
|
213
|
+
logger.error(`Invalid URL: ${options.url}`);
|
|
214
|
+
process.exit(1);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
157
218
|
const mode = resolveMode(options);
|
|
158
219
|
const check = validateMcpServer(
|
|
159
|
-
{
|
|
220
|
+
{
|
|
221
|
+
name,
|
|
222
|
+
command: options.command,
|
|
223
|
+
args,
|
|
224
|
+
url: options.url,
|
|
225
|
+
transport,
|
|
226
|
+
},
|
|
160
227
|
mode,
|
|
161
228
|
);
|
|
162
229
|
if (!check.allowed) {
|
|
@@ -166,25 +233,37 @@ export function registerMcpCommand(program) {
|
|
|
166
233
|
}
|
|
167
234
|
|
|
168
235
|
config.add(name, {
|
|
169
|
-
command: options.command,
|
|
236
|
+
command: options.command || null,
|
|
170
237
|
args,
|
|
238
|
+
url: options.url || null,
|
|
239
|
+
transport,
|
|
240
|
+
env: {},
|
|
171
241
|
autoConnect: !!options.autoConnect,
|
|
242
|
+
headers: Object.keys(headers).length > 0 ? headers : undefined,
|
|
172
243
|
});
|
|
173
244
|
|
|
245
|
+
const payload = {
|
|
246
|
+
name,
|
|
247
|
+
command: options.command || null,
|
|
248
|
+
args,
|
|
249
|
+
url: options.url || null,
|
|
250
|
+
transport,
|
|
251
|
+
autoConnect: !!options.autoConnect,
|
|
252
|
+
};
|
|
253
|
+
|
|
174
254
|
if (options.json) {
|
|
175
|
-
console.log(
|
|
176
|
-
JSON.stringify({
|
|
177
|
-
name,
|
|
178
|
-
command: options.command,
|
|
179
|
-
args,
|
|
180
|
-
autoConnect: !!options.autoConnect,
|
|
181
|
-
}),
|
|
182
|
-
);
|
|
255
|
+
console.log(JSON.stringify(payload));
|
|
183
256
|
} else {
|
|
184
257
|
logger.success(`MCP server "${chalk.cyan(name)}" configured`);
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
258
|
+
if (options.url) {
|
|
259
|
+
logger.log(
|
|
260
|
+
` ${chalk.gray("URL:")} ${options.url} ${chalk.gray(`[${transport}]`)}`,
|
|
261
|
+
);
|
|
262
|
+
} else {
|
|
263
|
+
logger.log(
|
|
264
|
+
` ${chalk.gray("Command:")} ${options.command} ${args.join(" ")}`,
|
|
265
|
+
);
|
|
266
|
+
}
|
|
188
267
|
}
|
|
189
268
|
|
|
190
269
|
await shutdown();
|
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `cc multimodal` — CLI surface for Phase 27 多模态协作.
|
|
3
|
+
*
|
|
4
|
+
* Exposes 5-modality weighted fusion, doc parsing (txt/md/csv/json),
|
|
5
|
+
* context building with 4000-token cap, and 6 output formats.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import fs from "fs";
|
|
9
|
+
import { Command } from "commander";
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
MODALITIES,
|
|
13
|
+
MODALITY_WEIGHTS,
|
|
14
|
+
INPUT_FORMATS,
|
|
15
|
+
NATIVE_FORMATS,
|
|
16
|
+
OUTPUT_FORMATS,
|
|
17
|
+
SESSION_STATUS,
|
|
18
|
+
DEFAULT_MAX_TOKENS,
|
|
19
|
+
ensureMultimodalTables,
|
|
20
|
+
createSession,
|
|
21
|
+
getSession,
|
|
22
|
+
listSessions,
|
|
23
|
+
completeSession,
|
|
24
|
+
deleteSession,
|
|
25
|
+
addModality,
|
|
26
|
+
getSessionModalities,
|
|
27
|
+
fuse,
|
|
28
|
+
parseDocument,
|
|
29
|
+
getSupportedFormats,
|
|
30
|
+
buildContext,
|
|
31
|
+
getContext,
|
|
32
|
+
clearContext,
|
|
33
|
+
trimContext,
|
|
34
|
+
generateOutput,
|
|
35
|
+
getOutputFormats,
|
|
36
|
+
listArtifacts,
|
|
37
|
+
getMultimodalStats,
|
|
38
|
+
} from "../lib/multimodal.js";
|
|
39
|
+
|
|
40
|
+
function _dbFromCtx(cmd) {
|
|
41
|
+
const root = cmd?.parent?.parent ?? cmd?.parent;
|
|
42
|
+
return root?._db;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function _parseJson(raw) {
|
|
46
|
+
if (raw == null) return null;
|
|
47
|
+
try {
|
|
48
|
+
return JSON.parse(raw);
|
|
49
|
+
} catch (_e) {
|
|
50
|
+
return raw;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function _readData(opts) {
|
|
55
|
+
if (opts.file) return fs.readFileSync(opts.file, "utf-8");
|
|
56
|
+
if (opts.text != null) return opts.text;
|
|
57
|
+
if (opts.data != null) return _parseJson(opts.data);
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function registerMultimodalCommand(program) {
|
|
62
|
+
const mm = new Command("multimodal")
|
|
63
|
+
.alias("mm")
|
|
64
|
+
.description("Multimodal collaboration (Phase 27)")
|
|
65
|
+
.hook("preAction", (thisCmd) => {
|
|
66
|
+
const db = _dbFromCtx(thisCmd);
|
|
67
|
+
if (db) ensureMultimodalTables(db);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
/* ── Catalogs ─────────────────────────────────────── */
|
|
71
|
+
|
|
72
|
+
mm.command("modalities")
|
|
73
|
+
.description("List 5 input modalities with weights")
|
|
74
|
+
.option("--json", "JSON output")
|
|
75
|
+
.action((opts) => {
|
|
76
|
+
const rows = MODALITIES.map((m) => ({
|
|
77
|
+
modality: m,
|
|
78
|
+
weight: MODALITY_WEIGHTS[m],
|
|
79
|
+
}));
|
|
80
|
+
if (opts.json) return console.log(JSON.stringify(rows, null, 2));
|
|
81
|
+
for (const r of rows)
|
|
82
|
+
console.log(` ${r.modality.padEnd(10)} weight=${r.weight}`);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
mm.command("input-formats")
|
|
86
|
+
.description("List 7 supported document formats (4 native)")
|
|
87
|
+
.option("--json", "JSON output")
|
|
88
|
+
.action((opts) => {
|
|
89
|
+
const r = getSupportedFormats();
|
|
90
|
+
if (opts.json) return console.log(JSON.stringify(r, null, 2));
|
|
91
|
+
console.log("Formats:", r.formats.join(", "));
|
|
92
|
+
console.log("Native: ", r.native.join(", "));
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
mm.command("output-formats")
|
|
96
|
+
.description("List 6 output formats")
|
|
97
|
+
.option("--json", "JSON output")
|
|
98
|
+
.action((opts) => {
|
|
99
|
+
const r = getOutputFormats();
|
|
100
|
+
if (opts.json) return console.log(JSON.stringify(r, null, 2));
|
|
101
|
+
for (const f of r) console.log(` ${f}`);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
mm.command("statuses")
|
|
105
|
+
.description("List session statuses")
|
|
106
|
+
.option("--json", "JSON output")
|
|
107
|
+
.action((opts) => {
|
|
108
|
+
const s = Object.values(SESSION_STATUS);
|
|
109
|
+
if (opts.json) return console.log(JSON.stringify(s, null, 2));
|
|
110
|
+
for (const x of s) console.log(` ${x}`);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
/* ── Sessions ─────────────────────────────────────── */
|
|
114
|
+
|
|
115
|
+
mm.command("session-create")
|
|
116
|
+
.description("Create a multimodal session")
|
|
117
|
+
.option("-t, --title <title>", "Session title")
|
|
118
|
+
.option("-m, --meta <json>", "Metadata JSON")
|
|
119
|
+
.option("--json", "JSON output")
|
|
120
|
+
.action((opts) => {
|
|
121
|
+
const db = _dbFromCtx(mm);
|
|
122
|
+
const r = createSession(db, {
|
|
123
|
+
title: opts.title,
|
|
124
|
+
metadata: _parseJson(opts.meta),
|
|
125
|
+
});
|
|
126
|
+
if (opts.json) return console.log(JSON.stringify(r, null, 2));
|
|
127
|
+
console.log(`Session created: ${r.sessionId}`);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
mm.command("session-show <sessionId>")
|
|
131
|
+
.description("Show session details")
|
|
132
|
+
.option("--json", "JSON output")
|
|
133
|
+
.action((sessionId, opts) => {
|
|
134
|
+
const db = _dbFromCtx(mm);
|
|
135
|
+
const s = getSession(db, sessionId);
|
|
136
|
+
if (!s) return console.log("Not found");
|
|
137
|
+
if (opts.json) return console.log(JSON.stringify(s, null, 2));
|
|
138
|
+
console.log(`ID: ${s.id}`);
|
|
139
|
+
console.log(`Status: ${s.status}`);
|
|
140
|
+
console.log(`Modalities: ${s.modalities.join(", ") || "-"}`);
|
|
141
|
+
console.log(`Tokens: ${s.tokenCount}`);
|
|
142
|
+
console.log(`Created: ${new Date(s.createdAt).toISOString()}`);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
mm.command("sessions")
|
|
146
|
+
.description("List sessions")
|
|
147
|
+
.option("-s, --status <status>", "Filter by status")
|
|
148
|
+
.option("-n, --limit <n>", "Limit", (v) => parseInt(v, 10), 50)
|
|
149
|
+
.option("--json", "JSON output")
|
|
150
|
+
.action((opts) => {
|
|
151
|
+
const db = _dbFromCtx(mm);
|
|
152
|
+
const rows = listSessions(db, { status: opts.status, limit: opts.limit });
|
|
153
|
+
if (opts.json) return console.log(JSON.stringify(rows, null, 2));
|
|
154
|
+
if (rows.length === 0) return console.log("No sessions");
|
|
155
|
+
for (const r of rows)
|
|
156
|
+
console.log(
|
|
157
|
+
` ${r.id.slice(0, 8)}… ${r.status.padEnd(10)} tok=${String(r.tokenCount).padStart(5)} [${r.modalities.join(",")}]`,
|
|
158
|
+
);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
mm.command("session-complete <sessionId>")
|
|
162
|
+
.description("Mark session as completed")
|
|
163
|
+
.option("--json", "JSON output")
|
|
164
|
+
.action((sessionId, opts) => {
|
|
165
|
+
const db = _dbFromCtx(mm);
|
|
166
|
+
const r = completeSession(db, sessionId);
|
|
167
|
+
if (opts.json) return console.log(JSON.stringify(r, null, 2));
|
|
168
|
+
if (!r.completed) return console.log(`Failed: ${r.reason}`);
|
|
169
|
+
console.log("Session completed");
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
mm.command("session-delete <sessionId>")
|
|
173
|
+
.description("Delete session and all artifacts")
|
|
174
|
+
.option("--json", "JSON output")
|
|
175
|
+
.action((sessionId, opts) => {
|
|
176
|
+
const db = _dbFromCtx(mm);
|
|
177
|
+
const r = deleteSession(db, sessionId);
|
|
178
|
+
if (opts.json) return console.log(JSON.stringify(r, null, 2));
|
|
179
|
+
if (!r.deleted) return console.log(`Failed: ${r.reason}`);
|
|
180
|
+
console.log("Session deleted");
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
/* ── Modalities ───────────────────────────────────── */
|
|
184
|
+
|
|
185
|
+
mm.command("add <sessionId>")
|
|
186
|
+
.description("Add a modality input to a session")
|
|
187
|
+
.requiredOption(
|
|
188
|
+
"-m, --modality <type>",
|
|
189
|
+
"Modality (text|document|image|audio|screen)",
|
|
190
|
+
)
|
|
191
|
+
.option("-f, --file <path>", "Read content from file")
|
|
192
|
+
.option("-t, --text <text>", "Inline text content")
|
|
193
|
+
.option("-d, --data <json>", "Inline JSON content")
|
|
194
|
+
.option("--meta <json>", "Metadata JSON")
|
|
195
|
+
.option("--json", "JSON output")
|
|
196
|
+
.action((sessionId, opts) => {
|
|
197
|
+
const db = _dbFromCtx(mm);
|
|
198
|
+
const data = _readData(opts);
|
|
199
|
+
if (data == null)
|
|
200
|
+
return console.log("Must provide --file, --text, or --data");
|
|
201
|
+
const r = addModality(db, sessionId, opts.modality, data, {
|
|
202
|
+
metadata: _parseJson(opts.meta),
|
|
203
|
+
});
|
|
204
|
+
if (opts.json) return console.log(JSON.stringify(r, null, 2));
|
|
205
|
+
if (!r.added) return console.log(`Failed: ${r.reason}`);
|
|
206
|
+
console.log(`Added ${r.modality} modality (artifact=${r.artifactId})`);
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
mm.command("modalities-of <sessionId>")
|
|
210
|
+
.description("List modalities added to a session")
|
|
211
|
+
.option("--json", "JSON output")
|
|
212
|
+
.action((sessionId, opts) => {
|
|
213
|
+
const db = _dbFromCtx(mm);
|
|
214
|
+
const r = getSessionModalities(db, sessionId);
|
|
215
|
+
if (opts.json) return console.log(JSON.stringify(r, null, 2));
|
|
216
|
+
for (const [m, items] of Object.entries(r))
|
|
217
|
+
console.log(` ${m.padEnd(10)} ${items.length} item(s)`);
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
mm.command("fuse <sessionId>")
|
|
221
|
+
.description("Weighted fusion of all input artifacts")
|
|
222
|
+
.option("--json", "JSON output")
|
|
223
|
+
.action((sessionId, opts) => {
|
|
224
|
+
const db = _dbFromCtx(mm);
|
|
225
|
+
const r = fuse(db, sessionId);
|
|
226
|
+
if (opts.json) return console.log(JSON.stringify(r, null, 2));
|
|
227
|
+
if (!r.fused) return console.log(`Failed: ${r.reason}`);
|
|
228
|
+
console.log(
|
|
229
|
+
`Fused ${r.summary.length} modalities (weight=${r.totalWeight}, tokens~${r.tokenEstimate})`,
|
|
230
|
+
);
|
|
231
|
+
for (const s of r.summary)
|
|
232
|
+
console.log(` ${s.modality.padEnd(10)} n=${s.count} w=${s.weight}`);
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
/* ── Parsing ──────────────────────────────────────── */
|
|
236
|
+
|
|
237
|
+
mm.command("parse <filePath>")
|
|
238
|
+
.description("Parse a document (txt/md/csv/json native)")
|
|
239
|
+
.option("--json", "JSON output")
|
|
240
|
+
.action((filePath, opts) => {
|
|
241
|
+
const r = parseDocument(filePath);
|
|
242
|
+
if (opts.json) return console.log(JSON.stringify(r, null, 2));
|
|
243
|
+
if (!r.parsed)
|
|
244
|
+
return console.log(
|
|
245
|
+
`Failed: ${r.reason}${r.hint ? `\n ${r.hint}` : ""}`,
|
|
246
|
+
);
|
|
247
|
+
console.log(
|
|
248
|
+
`Parsed ${r.format}: length=${r.length}, tokens~${r.tokenEstimate}`,
|
|
249
|
+
);
|
|
250
|
+
if (r.rowCount != null) console.log(`Rows: ${r.rowCount}`);
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
/* ── Context ──────────────────────────────────────── */
|
|
254
|
+
|
|
255
|
+
mm.command("build-context <sessionId>")
|
|
256
|
+
.description("Build context from session artifacts")
|
|
257
|
+
.option(
|
|
258
|
+
"-t, --max-tokens <n>",
|
|
259
|
+
"Max tokens",
|
|
260
|
+
(v) => parseInt(v, 10),
|
|
261
|
+
DEFAULT_MAX_TOKENS,
|
|
262
|
+
)
|
|
263
|
+
.option("--json", "JSON output")
|
|
264
|
+
.action((sessionId, opts) => {
|
|
265
|
+
const db = _dbFromCtx(mm);
|
|
266
|
+
const r = buildContext(db, sessionId, { maxTokens: opts.maxTokens });
|
|
267
|
+
if (opts.json) return console.log(JSON.stringify(r, null, 2));
|
|
268
|
+
if (!r.built) return console.log(`Failed: ${r.reason}`);
|
|
269
|
+
console.log(
|
|
270
|
+
`Built context: ${r.tokens}/${r.maxTokens} tokens across ${r.itemCount} items`,
|
|
271
|
+
);
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
mm.command("get-context <sessionId>")
|
|
275
|
+
.description("Get cached/stored context")
|
|
276
|
+
.option("--json", "JSON output")
|
|
277
|
+
.action((sessionId, opts) => {
|
|
278
|
+
const db = _dbFromCtx(mm);
|
|
279
|
+
const r = getContext(db, sessionId);
|
|
280
|
+
if (!r) return console.log("No context built yet");
|
|
281
|
+
if (opts.json) return console.log(JSON.stringify(r, null, 2));
|
|
282
|
+
console.log(`Tokens: ${r.tokens}/${r.maxTokens}`);
|
|
283
|
+
console.log(`Items: ${r.items?.length || 0}`);
|
|
284
|
+
if (r.content) console.log(`\n--- content ---\n${r.content}`);
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
mm.command("clear-context <sessionId>")
|
|
288
|
+
.description("Clear the session's context")
|
|
289
|
+
.option("--json", "JSON output")
|
|
290
|
+
.action((sessionId, opts) => {
|
|
291
|
+
const db = _dbFromCtx(mm);
|
|
292
|
+
const r = clearContext(db, sessionId);
|
|
293
|
+
if (opts.json) return console.log(JSON.stringify(r, null, 2));
|
|
294
|
+
if (!r.cleared) return console.log(`Failed: ${r.reason}`);
|
|
295
|
+
console.log("Context cleared");
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
mm.command("trim-context <sessionId>")
|
|
299
|
+
.description("Trim current context to max tokens")
|
|
300
|
+
.requiredOption("-t, --max-tokens <n>", "Max tokens", (v) =>
|
|
301
|
+
parseInt(v, 10),
|
|
302
|
+
)
|
|
303
|
+
.option("--json", "JSON output")
|
|
304
|
+
.action((sessionId, opts) => {
|
|
305
|
+
const db = _dbFromCtx(mm);
|
|
306
|
+
const ctx = getContext(db, sessionId);
|
|
307
|
+
if (!ctx) return console.log("No context built yet");
|
|
308
|
+
const r = trimContext(ctx, opts.maxTokens);
|
|
309
|
+
if (opts.json) return console.log(JSON.stringify(r, null, 2));
|
|
310
|
+
if (!r.trimmed) return console.log(`Failed: ${r.reason}`);
|
|
311
|
+
console.log(
|
|
312
|
+
`Trimmed to ${r.tokens}/${r.maxTokens} tokens (${r.items.length} items)`,
|
|
313
|
+
);
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
/* ── Output generation ────────────────────────────── */
|
|
317
|
+
|
|
318
|
+
mm.command("generate")
|
|
319
|
+
.description("Generate output in one of 6 formats")
|
|
320
|
+
.requiredOption("-f, --format <format>", "Output format")
|
|
321
|
+
.option("-s, --session <id>", "Session to attach artifact")
|
|
322
|
+
.option("-c, --content <text>", "Inline content")
|
|
323
|
+
.option("--file <path>", "Read content from file")
|
|
324
|
+
.option("--data <json>", "Inline JSON content")
|
|
325
|
+
.option("-o, --out <path>", "Write output to file")
|
|
326
|
+
.option("--title <title>", "Optional title")
|
|
327
|
+
.option("--chart-type <type>", "Chart type for chart format", "line")
|
|
328
|
+
.option("--json", "JSON output")
|
|
329
|
+
.action((opts) => {
|
|
330
|
+
const db = _dbFromCtx(mm);
|
|
331
|
+
let content;
|
|
332
|
+
if (opts.file) content = fs.readFileSync(opts.file, "utf-8");
|
|
333
|
+
else if (opts.data) content = _parseJson(opts.data);
|
|
334
|
+
else content = opts.content ?? "";
|
|
335
|
+
const r = generateOutput(db, opts.session, content, opts.format, {
|
|
336
|
+
title: opts.title,
|
|
337
|
+
chartType: opts.chartType,
|
|
338
|
+
});
|
|
339
|
+
if (!r.generated)
|
|
340
|
+
return console.log(
|
|
341
|
+
`Failed: ${r.reason}${r.format ? ` (format=${r.format})` : ""}`,
|
|
342
|
+
);
|
|
343
|
+
if (opts.out) {
|
|
344
|
+
fs.writeFileSync(opts.out, r.content);
|
|
345
|
+
console.log(`Wrote ${r.size} bytes to ${opts.out}`);
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
if (opts.json) return console.log(JSON.stringify(r, null, 2));
|
|
349
|
+
console.log(`--- ${r.format} (${r.size} bytes) ---`);
|
|
350
|
+
console.log(r.content);
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
/* ── Artifacts ────────────────────────────────────── */
|
|
354
|
+
|
|
355
|
+
mm.command("artifacts <sessionId>")
|
|
356
|
+
.description("List artifacts for a session")
|
|
357
|
+
.option("-t, --type <type>", "input|output")
|
|
358
|
+
.option("-m, --modality <m>", "Filter by modality")
|
|
359
|
+
.option("-n, --limit <n>", "Limit", (v) => parseInt(v, 10), 100)
|
|
360
|
+
.option("--json", "JSON output")
|
|
361
|
+
.action((sessionId, opts) => {
|
|
362
|
+
const db = _dbFromCtx(mm);
|
|
363
|
+
const rows = listArtifacts(db, sessionId, {
|
|
364
|
+
type: opts.type,
|
|
365
|
+
modality: opts.modality,
|
|
366
|
+
limit: opts.limit,
|
|
367
|
+
});
|
|
368
|
+
if (opts.json) return console.log(JSON.stringify(rows, null, 2));
|
|
369
|
+
if (rows.length === 0) return console.log("No artifacts");
|
|
370
|
+
for (const a of rows) {
|
|
371
|
+
const head =
|
|
372
|
+
typeof a.content === "string"
|
|
373
|
+
? a.content.slice(0, 40).replace(/\n/g, " ")
|
|
374
|
+
: "(json)";
|
|
375
|
+
console.log(
|
|
376
|
+
` ${a.id.slice(0, 8)}… ${a.type.padEnd(6)} ${(a.modality || a.format || "-").padEnd(10)} ${head}`,
|
|
377
|
+
);
|
|
378
|
+
}
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
/* ── Stats ────────────────────────────────────────── */
|
|
382
|
+
|
|
383
|
+
mm.command("stats")
|
|
384
|
+
.description("Multimodal system statistics")
|
|
385
|
+
.option("--json", "JSON output")
|
|
386
|
+
.action((opts) => {
|
|
387
|
+
const db = _dbFromCtx(mm);
|
|
388
|
+
const s = getMultimodalStats(db);
|
|
389
|
+
if (opts.json) return console.log(JSON.stringify(s, null, 2));
|
|
390
|
+
console.log(`Sessions: ${s.sessions}`);
|
|
391
|
+
console.log(
|
|
392
|
+
`Artifacts: ${s.artifacts} (in=${s.inputs}, out=${s.outputs})`,
|
|
393
|
+
);
|
|
394
|
+
console.log(`Tokens: ${s.totalTokens}`);
|
|
395
|
+
console.log("By status:");
|
|
396
|
+
for (const [k, v] of Object.entries(s.byStatus))
|
|
397
|
+
console.log(` ${k}: ${v}`);
|
|
398
|
+
console.log("By modality:");
|
|
399
|
+
for (const [k, v] of Object.entries(s.byModality))
|
|
400
|
+
console.log(` ${k}: ${v}`);
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
program.addCommand(mm);
|
|
404
|
+
}
|