chainlesschain 0.47.9 → 0.49.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/kg.js +371 -0
- package/src/commands/marketplace.js +326 -0
- package/src/commands/mcp.js +97 -18
- 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 +112 -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/knowledge-graph.js +530 -0
- package/src/lib/mcp-client.js +3 -0
- package/src/lib/multimodal.js +698 -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
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `cc perception` — CLI surface for Phase 84 Multimodal Perception Engine.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { Command } from "commander";
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
MODALITY,
|
|
9
|
+
VOICE_STATUS,
|
|
10
|
+
ANALYSIS_TYPE,
|
|
11
|
+
ensurePerceptionTables,
|
|
12
|
+
recordPerception,
|
|
13
|
+
getPerception,
|
|
14
|
+
listPerceptions,
|
|
15
|
+
startVoice,
|
|
16
|
+
updateVoiceStatus,
|
|
17
|
+
setTranscript,
|
|
18
|
+
getVoiceSession,
|
|
19
|
+
listVoiceSessions,
|
|
20
|
+
addIndexEntry,
|
|
21
|
+
getIndexEntry,
|
|
22
|
+
listIndexEntries,
|
|
23
|
+
removeIndexEntry,
|
|
24
|
+
crossModalQuery,
|
|
25
|
+
getPerceptionContext,
|
|
26
|
+
getPerceptionStats,
|
|
27
|
+
} from "../lib/perception.js";
|
|
28
|
+
|
|
29
|
+
function _dbFromCtx(cmd) {
|
|
30
|
+
const root = cmd?.parent?.parent ?? cmd?.parent;
|
|
31
|
+
return root?._db;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function registerPerceptionCommand(program) {
|
|
35
|
+
const perc = new Command("perception")
|
|
36
|
+
.description("Multimodal perception engine (Phase 84)")
|
|
37
|
+
.hook("preAction", (thisCmd) => {
|
|
38
|
+
const db = _dbFromCtx(thisCmd);
|
|
39
|
+
if (db) ensurePerceptionTables(db);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
/* ── Catalogs ────────────────────────────────────── */
|
|
43
|
+
|
|
44
|
+
perc
|
|
45
|
+
.command("modalities")
|
|
46
|
+
.description("List supported modalities")
|
|
47
|
+
.option("--json", "JSON output")
|
|
48
|
+
.action((opts) => {
|
|
49
|
+
const mods = Object.values(MODALITY);
|
|
50
|
+
if (opts.json) return console.log(JSON.stringify(mods, null, 2));
|
|
51
|
+
for (const m of mods) console.log(` ${m}`);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
perc
|
|
55
|
+
.command("voice-statuses")
|
|
56
|
+
.description("List voice session statuses")
|
|
57
|
+
.option("--json", "JSON output")
|
|
58
|
+
.action((opts) => {
|
|
59
|
+
const sts = Object.values(VOICE_STATUS);
|
|
60
|
+
if (opts.json) return console.log(JSON.stringify(sts, null, 2));
|
|
61
|
+
for (const s of sts) console.log(` ${s}`);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
perc
|
|
65
|
+
.command("analysis-types")
|
|
66
|
+
.description("List analysis types")
|
|
67
|
+
.option("--json", "JSON output")
|
|
68
|
+
.action((opts) => {
|
|
69
|
+
const types = Object.values(ANALYSIS_TYPE);
|
|
70
|
+
if (opts.json) return console.log(JSON.stringify(types, null, 2));
|
|
71
|
+
for (const t of types) console.log(` ${t}`);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
/* ── Perception Results ──────────────────────────── */
|
|
75
|
+
|
|
76
|
+
perc
|
|
77
|
+
.command("record")
|
|
78
|
+
.description("Record a perception result")
|
|
79
|
+
.requiredOption(
|
|
80
|
+
"-m, --modality <type>",
|
|
81
|
+
"Modality (screen/voice/document/video)",
|
|
82
|
+
)
|
|
83
|
+
.option(
|
|
84
|
+
"-a, --analysis <type>",
|
|
85
|
+
"Analysis type (ocr/object_detection/scene_recognition/action_detection)",
|
|
86
|
+
)
|
|
87
|
+
.option("-i, --input <source>", "Input source (file path or session id)")
|
|
88
|
+
.option("-r, --result <json>", "Result data JSON")
|
|
89
|
+
.option("-c, --confidence <n>", "Confidence score (0-1)", parseFloat)
|
|
90
|
+
.option("--metadata <json>", "Metadata JSON")
|
|
91
|
+
.option("--json", "JSON output")
|
|
92
|
+
.action((opts) => {
|
|
93
|
+
const db = _dbFromCtx(perc);
|
|
94
|
+
const result = recordPerception(db, {
|
|
95
|
+
modality: opts.modality,
|
|
96
|
+
analysisType: opts.analysis,
|
|
97
|
+
inputSource: opts.input,
|
|
98
|
+
resultData: opts.result,
|
|
99
|
+
confidence: opts.confidence,
|
|
100
|
+
metadata: opts.metadata,
|
|
101
|
+
});
|
|
102
|
+
if (opts.json) return console.log(JSON.stringify(result, null, 2));
|
|
103
|
+
if (result.recorded)
|
|
104
|
+
console.log(`Perception recorded: ${result.resultId}`);
|
|
105
|
+
else console.log(`Failed: ${result.reason}`);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
perc
|
|
109
|
+
.command("show <id>")
|
|
110
|
+
.description("Show perception result details")
|
|
111
|
+
.option("--json", "JSON output")
|
|
112
|
+
.action((id, opts) => {
|
|
113
|
+
const db = _dbFromCtx(perc);
|
|
114
|
+
const r = getPerception(db, id);
|
|
115
|
+
if (!r) return console.log("Result not found.");
|
|
116
|
+
if (opts.json) return console.log(JSON.stringify(r, null, 2));
|
|
117
|
+
console.log(`ID: ${r.id}`);
|
|
118
|
+
console.log(`Modality: ${r.modality}`);
|
|
119
|
+
if (r.analysis_type) console.log(`Analysis: ${r.analysis_type}`);
|
|
120
|
+
if (r.input_source) console.log(`Source: ${r.input_source}`);
|
|
121
|
+
console.log(`Confidence: ${r.confidence}`);
|
|
122
|
+
if (r.result_data)
|
|
123
|
+
console.log(`Data: ${r.result_data.slice(0, 80)}`);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
perc
|
|
127
|
+
.command("results")
|
|
128
|
+
.description("List perception results")
|
|
129
|
+
.option("-m, --modality <type>", "Filter by modality")
|
|
130
|
+
.option("-a, --analysis <type>", "Filter by analysis type")
|
|
131
|
+
.option("--limit <n>", "Max results", parseInt)
|
|
132
|
+
.option("--json", "JSON output")
|
|
133
|
+
.action((opts) => {
|
|
134
|
+
const db = _dbFromCtx(perc);
|
|
135
|
+
const results = listPerceptions(db, {
|
|
136
|
+
modality: opts.modality,
|
|
137
|
+
analysisType: opts.analysis,
|
|
138
|
+
limit: opts.limit,
|
|
139
|
+
});
|
|
140
|
+
if (opts.json) return console.log(JSON.stringify(results, null, 2));
|
|
141
|
+
if (results.length === 0) return console.log("No results.");
|
|
142
|
+
for (const r of results) {
|
|
143
|
+
console.log(
|
|
144
|
+
` ${r.modality.padEnd(10)} ${(r.analysis_type || "").padEnd(20)} conf:${String(r.confidence).padEnd(5)} ${(r.input_source || "").padEnd(20)} ${r.id.slice(0, 8)}`,
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
/* ── Voice Sessions ──────────────────────────────── */
|
|
150
|
+
|
|
151
|
+
perc
|
|
152
|
+
.command("voice-start")
|
|
153
|
+
.description("Start a voice session")
|
|
154
|
+
.option("-l, --language <lang>", "Language code", "zh-CN")
|
|
155
|
+
.option("-m, --model <model>", "ASR model name")
|
|
156
|
+
.option("--json", "JSON output")
|
|
157
|
+
.action((opts) => {
|
|
158
|
+
const db = _dbFromCtx(perc);
|
|
159
|
+
const result = startVoice(db, {
|
|
160
|
+
language: opts.language,
|
|
161
|
+
model: opts.model,
|
|
162
|
+
});
|
|
163
|
+
if (opts.json) return console.log(JSON.stringify(result, null, 2));
|
|
164
|
+
console.log(
|
|
165
|
+
`Voice session started: ${result.sessionId} [${result.status}]`,
|
|
166
|
+
);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
perc
|
|
170
|
+
.command("voice-status <id> <status>")
|
|
171
|
+
.description("Update voice session status")
|
|
172
|
+
.option("--json", "JSON output")
|
|
173
|
+
.action((id, status, opts) => {
|
|
174
|
+
const db = _dbFromCtx(perc);
|
|
175
|
+
const result = updateVoiceStatus(db, id, status);
|
|
176
|
+
if (opts.json) return console.log(JSON.stringify(result, null, 2));
|
|
177
|
+
if (result.updated)
|
|
178
|
+
console.log(`Voice session ${id.slice(0, 8)}: ${result.status}`);
|
|
179
|
+
else
|
|
180
|
+
console.log(
|
|
181
|
+
`Failed: ${result.reason}${result.from ? ` (${result.from} → ${result.to})` : ""}`,
|
|
182
|
+
);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
perc
|
|
186
|
+
.command("voice-transcript <id> <text>")
|
|
187
|
+
.description("Set voice session transcript")
|
|
188
|
+
.option("--json", "JSON output")
|
|
189
|
+
.action((id, text, opts) => {
|
|
190
|
+
const db = _dbFromCtx(perc);
|
|
191
|
+
const result = setTranscript(db, id, text);
|
|
192
|
+
if (opts.json) return console.log(JSON.stringify(result, null, 2));
|
|
193
|
+
console.log(
|
|
194
|
+
result.updated ? "Transcript set." : `Failed: ${result.reason}`,
|
|
195
|
+
);
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
perc
|
|
199
|
+
.command("voice-show <id>")
|
|
200
|
+
.description("Show voice session details")
|
|
201
|
+
.option("--json", "JSON output")
|
|
202
|
+
.action((id, opts) => {
|
|
203
|
+
const db = _dbFromCtx(perc);
|
|
204
|
+
const s = getVoiceSession(db, id);
|
|
205
|
+
if (!s) return console.log("Session not found.");
|
|
206
|
+
if (opts.json) return console.log(JSON.stringify(s, null, 2));
|
|
207
|
+
console.log(`ID: ${s.id}`);
|
|
208
|
+
console.log(`Status: ${s.status}`);
|
|
209
|
+
console.log(`Language: ${s.language}`);
|
|
210
|
+
if (s.model) console.log(`Model: ${s.model}`);
|
|
211
|
+
if (s.transcript) console.log(`Transcript: ${s.transcript.slice(0, 80)}`);
|
|
212
|
+
console.log(`Duration: ${s.duration_ms}ms`);
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
perc
|
|
216
|
+
.command("voice-sessions")
|
|
217
|
+
.description("List voice sessions")
|
|
218
|
+
.option("-s, --status <status>", "Filter by status")
|
|
219
|
+
.option("-l, --language <lang>", "Filter by language")
|
|
220
|
+
.option("--limit <n>", "Max results", parseInt)
|
|
221
|
+
.option("--json", "JSON output")
|
|
222
|
+
.action((opts) => {
|
|
223
|
+
const db = _dbFromCtx(perc);
|
|
224
|
+
const sessions = listVoiceSessions(db, {
|
|
225
|
+
status: opts.status,
|
|
226
|
+
language: opts.language,
|
|
227
|
+
limit: opts.limit,
|
|
228
|
+
});
|
|
229
|
+
if (opts.json) return console.log(JSON.stringify(sessions, null, 2));
|
|
230
|
+
if (sessions.length === 0) return console.log("No sessions.");
|
|
231
|
+
for (const s of sessions) {
|
|
232
|
+
console.log(
|
|
233
|
+
` ${s.status.padEnd(12)} ${s.language.padEnd(8)} ${String(s.duration_ms).padEnd(8)}ms ${s.id.slice(0, 8)}`,
|
|
234
|
+
);
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
/* ── Multimodal Index ────────────────────────────── */
|
|
239
|
+
|
|
240
|
+
perc
|
|
241
|
+
.command("index-add")
|
|
242
|
+
.description("Add a multimodal index entry")
|
|
243
|
+
.requiredOption("-m, --modality <type>", "Modality")
|
|
244
|
+
.requiredOption("-s, --source <id>", "Source perception result ID")
|
|
245
|
+
.option("-c, --summary <text>", "Content summary")
|
|
246
|
+
.option("-t, --tags <csv>", "Comma-separated tags")
|
|
247
|
+
.option("-e, --embedding <json>", "Embedding vector JSON")
|
|
248
|
+
.option("--json", "JSON output")
|
|
249
|
+
.action((opts) => {
|
|
250
|
+
const db = _dbFromCtx(perc);
|
|
251
|
+
const tags = opts.tags
|
|
252
|
+
? opts.tags.split(",").map((t) => t.trim())
|
|
253
|
+
: undefined;
|
|
254
|
+
const result = addIndexEntry(db, {
|
|
255
|
+
modality: opts.modality,
|
|
256
|
+
sourceId: opts.source,
|
|
257
|
+
contentSummary: opts.summary,
|
|
258
|
+
tags,
|
|
259
|
+
embedding: opts.embedding,
|
|
260
|
+
});
|
|
261
|
+
if (opts.json) return console.log(JSON.stringify(result, null, 2));
|
|
262
|
+
if (result.added) console.log(`Index entry added: ${result.indexId}`);
|
|
263
|
+
else console.log(`Failed: ${result.reason}`);
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
perc
|
|
267
|
+
.command("index-show <id>")
|
|
268
|
+
.description("Show index entry details")
|
|
269
|
+
.option("--json", "JSON output")
|
|
270
|
+
.action((id, opts) => {
|
|
271
|
+
const db = _dbFromCtx(perc);
|
|
272
|
+
const e = getIndexEntry(db, id);
|
|
273
|
+
if (!e) return console.log("Entry not found.");
|
|
274
|
+
if (opts.json) return console.log(JSON.stringify(e, null, 2));
|
|
275
|
+
console.log(`ID: ${e.id}`);
|
|
276
|
+
console.log(`Modality: ${e.modality}`);
|
|
277
|
+
console.log(`Source: ${e.source_id}`);
|
|
278
|
+
if (e.content_summary)
|
|
279
|
+
console.log(`Summary: ${e.content_summary.slice(0, 80)}`);
|
|
280
|
+
if (e.tags) console.log(`Tags: ${e.tags}`);
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
perc
|
|
284
|
+
.command("index-list")
|
|
285
|
+
.description("List index entries")
|
|
286
|
+
.option("-m, --modality <type>", "Filter by modality")
|
|
287
|
+
.option("--limit <n>", "Max results", parseInt)
|
|
288
|
+
.option("--json", "JSON output")
|
|
289
|
+
.action((opts) => {
|
|
290
|
+
const db = _dbFromCtx(perc);
|
|
291
|
+
const entries = listIndexEntries(db, {
|
|
292
|
+
modality: opts.modality,
|
|
293
|
+
limit: opts.limit,
|
|
294
|
+
});
|
|
295
|
+
if (opts.json) return console.log(JSON.stringify(entries, null, 2));
|
|
296
|
+
if (entries.length === 0) return console.log("No index entries.");
|
|
297
|
+
for (const e of entries) {
|
|
298
|
+
console.log(
|
|
299
|
+
` ${e.modality.padEnd(10)} ${(e.content_summary || "").slice(0, 40).padEnd(42)} ${e.id.slice(0, 8)}`,
|
|
300
|
+
);
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
perc
|
|
305
|
+
.command("index-remove <id>")
|
|
306
|
+
.description("Remove an index entry")
|
|
307
|
+
.option("--json", "JSON output")
|
|
308
|
+
.action((id, opts) => {
|
|
309
|
+
const db = _dbFromCtx(perc);
|
|
310
|
+
const result = removeIndexEntry(db, id);
|
|
311
|
+
if (opts.json) return console.log(JSON.stringify(result, null, 2));
|
|
312
|
+
console.log(
|
|
313
|
+
result.removed ? "Entry removed." : `Failed: ${result.reason}`,
|
|
314
|
+
);
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
/* ── Cross-Modal Query ───────────────────────────── */
|
|
318
|
+
|
|
319
|
+
perc
|
|
320
|
+
.command("query <text>")
|
|
321
|
+
.description("Cross-modal search across index entries")
|
|
322
|
+
.option("-m, --modalities <csv>", "Filter modalities (comma-separated)")
|
|
323
|
+
.option("--limit <n>", "Max results", parseInt)
|
|
324
|
+
.option("--json", "JSON output")
|
|
325
|
+
.action((text, opts) => {
|
|
326
|
+
const db = _dbFromCtx(perc);
|
|
327
|
+
const modalities = opts.modalities
|
|
328
|
+
? opts.modalities.split(",").map((m) => m.trim())
|
|
329
|
+
: undefined;
|
|
330
|
+
const result = crossModalQuery(db, {
|
|
331
|
+
query: text,
|
|
332
|
+
modalities,
|
|
333
|
+
limit: opts.limit,
|
|
334
|
+
});
|
|
335
|
+
if (opts.json) return console.log(JSON.stringify(result, null, 2));
|
|
336
|
+
if (result.results.length === 0) return console.log("No matches.");
|
|
337
|
+
console.log(`Found ${result.total} result(s):`);
|
|
338
|
+
for (const r of result.results) {
|
|
339
|
+
console.log(
|
|
340
|
+
` score:${String(r.score).padEnd(6)} ${r.modality.padEnd(10)} ${(r.content_summary || "").slice(0, 50)} ${r.id.slice(0, 8)}`,
|
|
341
|
+
);
|
|
342
|
+
}
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
/* ── Context & Stats ─────────────────────────────── */
|
|
346
|
+
|
|
347
|
+
perc
|
|
348
|
+
.command("context")
|
|
349
|
+
.description("Show current perception context")
|
|
350
|
+
.option("--json", "JSON output")
|
|
351
|
+
.action((opts) => {
|
|
352
|
+
const db = _dbFromCtx(perc);
|
|
353
|
+
const ctx = getPerceptionContext(db);
|
|
354
|
+
if (opts.json) return console.log(JSON.stringify(ctx, null, 2));
|
|
355
|
+
console.log(`Active sessions: ${ctx.activeSessions}`);
|
|
356
|
+
console.log(`Total results: ${ctx.totalResults}`);
|
|
357
|
+
console.log(`Index entries: ${ctx.totalIndexEntries}`);
|
|
358
|
+
console.log("Modality coverage:");
|
|
359
|
+
for (const [mod, count] of Object.entries(ctx.modalityCoverage)) {
|
|
360
|
+
if (count > 0) console.log(` ${mod.padEnd(10)} ${count}`);
|
|
361
|
+
}
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
perc
|
|
365
|
+
.command("stats")
|
|
366
|
+
.description("Perception engine statistics")
|
|
367
|
+
.option("--json", "JSON output")
|
|
368
|
+
.action((opts) => {
|
|
369
|
+
const db = _dbFromCtx(perc);
|
|
370
|
+
const s = getPerceptionStats(db);
|
|
371
|
+
if (opts.json) return console.log(JSON.stringify(s, null, 2));
|
|
372
|
+
console.log(
|
|
373
|
+
`Results: ${s.results.total} (avg confidence: ${s.results.avgConfidence})`,
|
|
374
|
+
);
|
|
375
|
+
for (const [mod, count] of Object.entries(s.results.byModality)) {
|
|
376
|
+
if (count > 0) console.log(` ${mod.padEnd(10)} ${count}`);
|
|
377
|
+
}
|
|
378
|
+
console.log(
|
|
379
|
+
`Voice: ${s.voiceSessions.total} total, ${s.voiceSessions.active} active, avg ${s.voiceSessions.avgDurationMs}ms`,
|
|
380
|
+
);
|
|
381
|
+
console.log(`Index: ${s.index.total} entries`);
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
program.addCommand(perc);
|
|
385
|
+
}
|
package/src/commands/pqc.js
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
generateKey,
|
|
13
13
|
getMigrationStatus,
|
|
14
14
|
migrate,
|
|
15
|
+
listAlgorithms,
|
|
15
16
|
} from "../lib/pqc-manager.js";
|
|
16
17
|
|
|
17
18
|
export function registerPqcCommand(program) {
|
|
@@ -127,6 +128,39 @@ export function registerPqcCommand(program) {
|
|
|
127
128
|
}
|
|
128
129
|
});
|
|
129
130
|
|
|
131
|
+
// pqc algorithms
|
|
132
|
+
pqc
|
|
133
|
+
.command("algorithms")
|
|
134
|
+
.description("List supported PQC algorithms (FIPS 203/204/205 + hybrid)")
|
|
135
|
+
.option(
|
|
136
|
+
"-f, --family <family>",
|
|
137
|
+
"Filter by family: ml-kem|ml-dsa|slh-dsa|hybrid",
|
|
138
|
+
)
|
|
139
|
+
.option("--json", "Output as JSON")
|
|
140
|
+
.action((options) => {
|
|
141
|
+
try {
|
|
142
|
+
const algos = listAlgorithms({ family: options.family });
|
|
143
|
+
if (options.json) {
|
|
144
|
+
console.log(JSON.stringify(algos, null, 2));
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
if (algos.length === 0) {
|
|
148
|
+
logger.info("No algorithms match filter.");
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
for (const a of algos) {
|
|
152
|
+
const sig =
|
|
153
|
+
a.signatureBytes != null ? `sig=${a.signatureBytes}B` : "sig=—";
|
|
154
|
+
logger.log(
|
|
155
|
+
` ${chalk.cyan(a.algorithm.padEnd(26))} ${chalk.dim(a.family.padEnd(8))} lvl=${a.keySize} pk=${a.publicKeyBytes}B ${sig}`,
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
} catch (err) {
|
|
159
|
+
logger.error(`Failed: ${err.message}`);
|
|
160
|
+
process.exit(1);
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
|
|
130
164
|
// pqc migrate
|
|
131
165
|
pqc
|
|
132
166
|
.command("migrate <plan-name> <target-algorithm>")
|