@weavelogic/knowledge-graph-agent 0.3.0 → 0.4.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/README.md +290 -3
- package/dist/_virtual/index10.js +2 -2
- package/dist/_virtual/index6.js +2 -2
- package/dist/_virtual/index7.js +2 -2
- package/dist/_virtual/index8.js +2 -2
- package/dist/_virtual/index9.js +2 -2
- package/dist/audit/config.d.ts +150 -0
- package/dist/audit/config.d.ts.map +1 -0
- package/dist/audit/config.js +111 -0
- package/dist/audit/config.js.map +1 -0
- package/dist/audit/index.d.ts +38 -0
- package/dist/audit/index.d.ts.map +1 -0
- package/dist/audit/services/audit-chain.d.ts +276 -0
- package/dist/audit/services/audit-chain.d.ts.map +1 -0
- package/dist/audit/services/audit-chain.js +502 -0
- package/dist/audit/services/audit-chain.js.map +1 -0
- package/dist/audit/services/index.d.ts +11 -0
- package/dist/audit/services/index.d.ts.map +1 -0
- package/dist/audit/services/syndication.d.ts +334 -0
- package/dist/audit/services/syndication.d.ts.map +1 -0
- package/dist/audit/services/syndication.js +589 -0
- package/dist/audit/services/syndication.js.map +1 -0
- package/dist/audit/types.d.ts +453 -0
- package/dist/audit/types.d.ts.map +1 -0
- package/dist/cli/commands/audit.d.ts +21 -0
- package/dist/cli/commands/audit.d.ts.map +1 -0
- package/dist/cli/commands/audit.js +621 -0
- package/dist/cli/commands/audit.js.map +1 -0
- package/dist/cli/commands/vector.d.ts +14 -0
- package/dist/cli/commands/vector.d.ts.map +1 -0
- package/dist/cli/commands/vector.js +429 -0
- package/dist/cli/commands/vector.js.map +1 -0
- package/dist/cli/commands/workflow.d.ts +12 -0
- package/dist/cli/commands/workflow.d.ts.map +1 -0
- package/dist/cli/commands/workflow.js +471 -0
- package/dist/cli/commands/workflow.js.map +1 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +26 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/database/schemas/index.d.ts +85 -0
- package/dist/database/schemas/index.d.ts.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp-server/tools/audit/checkpoint.d.ts +58 -0
- package/dist/mcp-server/tools/audit/checkpoint.d.ts.map +1 -0
- package/dist/mcp-server/tools/audit/checkpoint.js +73 -0
- package/dist/mcp-server/tools/audit/checkpoint.js.map +1 -0
- package/dist/mcp-server/tools/audit/index.d.ts +53 -0
- package/dist/mcp-server/tools/audit/index.d.ts.map +1 -0
- package/dist/mcp-server/tools/audit/index.js +12 -0
- package/dist/mcp-server/tools/audit/index.js.map +1 -0
- package/dist/mcp-server/tools/audit/query.d.ts +58 -0
- package/dist/mcp-server/tools/audit/query.d.ts.map +1 -0
- package/dist/mcp-server/tools/audit/query.js +125 -0
- package/dist/mcp-server/tools/audit/query.js.map +1 -0
- package/dist/mcp-server/tools/audit/sync.d.ts +58 -0
- package/dist/mcp-server/tools/audit/sync.d.ts.map +1 -0
- package/dist/mcp-server/tools/audit/sync.js +126 -0
- package/dist/mcp-server/tools/audit/sync.js.map +1 -0
- package/dist/mcp-server/tools/index.d.ts +3 -0
- package/dist/mcp-server/tools/index.d.ts.map +1 -1
- package/dist/mcp-server/tools/registry.js +90 -0
- package/dist/mcp-server/tools/registry.js.map +1 -1
- package/dist/mcp-server/tools/vector/index.d.ts +12 -0
- package/dist/mcp-server/tools/vector/index.d.ts.map +1 -0
- package/dist/mcp-server/tools/vector/index.js +12 -0
- package/dist/mcp-server/tools/vector/index.js.map +1 -0
- package/dist/mcp-server/tools/vector/search.d.ts +41 -0
- package/dist/mcp-server/tools/vector/search.d.ts.map +1 -0
- package/dist/mcp-server/tools/vector/search.js +224 -0
- package/dist/mcp-server/tools/vector/search.js.map +1 -0
- package/dist/mcp-server/tools/vector/trajectory.d.ts +39 -0
- package/dist/mcp-server/tools/vector/trajectory.d.ts.map +1 -0
- package/dist/mcp-server/tools/vector/trajectory.js +170 -0
- package/dist/mcp-server/tools/vector/trajectory.js.map +1 -0
- package/dist/mcp-server/tools/vector/upsert.d.ts +44 -0
- package/dist/mcp-server/tools/vector/upsert.d.ts.map +1 -0
- package/dist/mcp-server/tools/vector/upsert.js +175 -0
- package/dist/mcp-server/tools/vector/upsert.js.map +1 -0
- package/dist/mcp-server/tools/workflow/index.d.ts +29 -0
- package/dist/mcp-server/tools/workflow/index.d.ts.map +1 -0
- package/dist/mcp-server/tools/workflow/index.js +12 -0
- package/dist/mcp-server/tools/workflow/index.js.map +1 -0
- package/dist/mcp-server/tools/workflow/list.d.ts +41 -0
- package/dist/mcp-server/tools/workflow/list.d.ts.map +1 -0
- package/dist/mcp-server/tools/workflow/list.js +195 -0
- package/dist/mcp-server/tools/workflow/list.js.map +1 -0
- package/dist/mcp-server/tools/workflow/start.d.ts +40 -0
- package/dist/mcp-server/tools/workflow/start.d.ts.map +1 -0
- package/dist/mcp-server/tools/workflow/start.js +165 -0
- package/dist/mcp-server/tools/workflow/start.js.map +1 -0
- package/dist/mcp-server/tools/workflow/status.d.ts +38 -0
- package/dist/mcp-server/tools/workflow/status.d.ts.map +1 -0
- package/dist/mcp-server/tools/workflow/status.js +97 -0
- package/dist/mcp-server/tools/workflow/status.js.map +1 -0
- package/dist/node_modules/ajv/dist/compile/index.js +1 -1
- package/dist/node_modules/ajv/dist/vocabularies/applicator/index.js +1 -1
- package/dist/node_modules/ajv/dist/vocabularies/core/index.js +1 -1
- package/dist/node_modules/ajv/dist/vocabularies/format/index.js +1 -1
- package/dist/node_modules/ajv/dist/vocabularies/validation/index.js +1 -1
- package/dist/vector/config.d.ts +300 -0
- package/dist/vector/config.d.ts.map +1 -0
- package/dist/vector/config.js +124 -0
- package/dist/vector/config.js.map +1 -0
- package/dist/vector/index.d.ts +50 -0
- package/dist/vector/index.d.ts.map +1 -0
- package/dist/vector/services/index.d.ts +13 -0
- package/dist/vector/services/index.d.ts.map +1 -0
- package/dist/vector/services/trajectory-tracker.d.ts +405 -0
- package/dist/vector/services/trajectory-tracker.d.ts.map +1 -0
- package/dist/vector/services/trajectory-tracker.js +445 -0
- package/dist/vector/services/trajectory-tracker.js.map +1 -0
- package/dist/vector/services/vector-store.d.ts +339 -0
- package/dist/vector/services/vector-store.d.ts.map +1 -0
- package/dist/vector/services/vector-store.js +748 -0
- package/dist/vector/services/vector-store.js.map +1 -0
- package/dist/vector/types.d.ts +677 -0
- package/dist/vector/types.d.ts.map +1 -0
- package/dist/workflow/adapters/goap-adapter.d.ts +196 -0
- package/dist/workflow/adapters/goap-adapter.d.ts.map +1 -0
- package/dist/workflow/adapters/goap-adapter.js +706 -0
- package/dist/workflow/adapters/goap-adapter.js.map +1 -0
- package/dist/workflow/adapters/index.d.ts +10 -0
- package/dist/workflow/adapters/index.d.ts.map +1 -0
- package/dist/workflow/config.d.ts +135 -0
- package/dist/workflow/config.d.ts.map +1 -0
- package/dist/workflow/config.js +92 -0
- package/dist/workflow/config.js.map +1 -0
- package/dist/workflow/handlers/index.d.ts +9 -0
- package/dist/workflow/handlers/index.d.ts.map +1 -0
- package/dist/workflow/handlers/webhook-handlers.d.ts +397 -0
- package/dist/workflow/handlers/webhook-handlers.d.ts.map +1 -0
- package/dist/workflow/handlers/webhook-handlers.js +454 -0
- package/dist/workflow/handlers/webhook-handlers.js.map +1 -0
- package/dist/workflow/index.d.ts +42 -0
- package/dist/workflow/index.d.ts.map +1 -0
- package/dist/workflow/services/index.d.ts +9 -0
- package/dist/workflow/services/index.d.ts.map +1 -0
- package/dist/workflow/services/workflow-service.d.ts +318 -0
- package/dist/workflow/services/workflow-service.d.ts.map +1 -0
- package/dist/workflow/services/workflow-service.js +577 -0
- package/dist/workflow/services/workflow-service.js.map +1 -0
- package/dist/workflow/types.d.ts +470 -0
- package/dist/workflow/types.d.ts.map +1 -0
- package/dist/workflow/workflows/realtime-collab.d.ts +245 -0
- package/dist/workflow/workflows/realtime-collab.d.ts.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,621 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import ora from "ora";
|
|
4
|
+
import { join } from "path";
|
|
5
|
+
import { writeFile } from "fs/promises";
|
|
6
|
+
import { createAuditChainConfig } from "../../audit/config.js";
|
|
7
|
+
import { createAuditChain } from "../../audit/services/audit-chain.js";
|
|
8
|
+
import { createSyndicationService } from "../../audit/services/syndication.js";
|
|
9
|
+
import { validateProjectRoot } from "../../core/security.js";
|
|
10
|
+
function formatDate(date) {
|
|
11
|
+
if (!date) return "N/A";
|
|
12
|
+
return date.toISOString().replace("T", " ").replace(/\.\d{3}Z$/, "");
|
|
13
|
+
}
|
|
14
|
+
function formatHLC(hlc) {
|
|
15
|
+
const date = new Date(hlc.physicalMs);
|
|
16
|
+
return `${formatDate(date)} (L:${hlc.logical})`;
|
|
17
|
+
}
|
|
18
|
+
function formatDuration(ms) {
|
|
19
|
+
if (ms < 1e3) return `${ms}ms`;
|
|
20
|
+
if (ms < 6e4) return `${(ms / 1e3).toFixed(1)}s`;
|
|
21
|
+
return `${(ms / 6e4).toFixed(1)}m`;
|
|
22
|
+
}
|
|
23
|
+
function printEventsTable(events) {
|
|
24
|
+
if (events.length === 0) {
|
|
25
|
+
console.log(chalk.gray(" No events found"));
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
console.log(
|
|
29
|
+
chalk.gray(
|
|
30
|
+
" " + "ID".padEnd(16) + "Type".padEnd(24) + "Author".padEnd(20) + "Timestamp"
|
|
31
|
+
)
|
|
32
|
+
);
|
|
33
|
+
console.log(chalk.gray(" " + "-".repeat(80)));
|
|
34
|
+
for (const event of events) {
|
|
35
|
+
const id = event.id.substring(0, 14) + "..";
|
|
36
|
+
const type = event.envelope.payload.type;
|
|
37
|
+
const author = event.envelope.author.substring(0, 18);
|
|
38
|
+
const timestamp = formatHLC(event.envelope.hlc);
|
|
39
|
+
const typeColor = type.includes("Created") ? chalk.green : type.includes("Deleted") ? chalk.red : type.includes("Updated") ? chalk.yellow : type.includes("Completed") ? chalk.cyan : type.includes("Started") ? chalk.blue : chalk.white;
|
|
40
|
+
console.log(
|
|
41
|
+
" " + chalk.gray(id.padEnd(16)) + typeColor(type.padEnd(24)) + chalk.gray(author.padEnd(20)) + chalk.gray(timestamp)
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function printChainStats(stats) {
|
|
46
|
+
const statusColor = stats.status === "healthy" ? chalk.green : stats.status === "syncing" ? chalk.yellow : chalk.red;
|
|
47
|
+
console.log(chalk.white(" Overview"));
|
|
48
|
+
console.log(chalk.gray(` Status: `) + statusColor(stats.status));
|
|
49
|
+
console.log(chalk.gray(` Total events: ${stats.totalEvents}`));
|
|
50
|
+
console.log(chalk.gray(` Checkpoint height: ${stats.checkpointHeight}`));
|
|
51
|
+
console.log(chalk.gray(` Unique authors: ${stats.uniqueAuthors}`));
|
|
52
|
+
if (stats.lastEventTime) {
|
|
53
|
+
console.log(chalk.gray(` Last event: ${formatDate(stats.lastEventTime)}`));
|
|
54
|
+
}
|
|
55
|
+
if (Object.keys(stats.eventsByType).length > 0) {
|
|
56
|
+
console.log();
|
|
57
|
+
console.log(chalk.white(" Events by Type"));
|
|
58
|
+
const sortedTypes = Object.entries(stats.eventsByType).sort((a, b) => b[1] - a[1]);
|
|
59
|
+
for (const [type, count] of sortedTypes) {
|
|
60
|
+
const bar = "|".repeat(Math.min(Math.ceil(count / 5), 30));
|
|
61
|
+
console.log(
|
|
62
|
+
chalk.gray(` ${type.padEnd(24)} ${String(count).padStart(5)} `) + chalk.blue(bar)
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function printCheckpoint(checkpoint) {
|
|
68
|
+
if (!checkpoint) {
|
|
69
|
+
console.log(chalk.gray(" No checkpoints created yet"));
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
console.log(chalk.white(" Latest Checkpoint"));
|
|
73
|
+
console.log(chalk.gray(` Height: ${checkpoint.height}`));
|
|
74
|
+
console.log(chalk.gray(` Event root: ${checkpoint.eventRoot.substring(0, 32)}...`));
|
|
75
|
+
console.log(chalk.gray(` State root: ${checkpoint.stateRoot.substring(0, 32)}...`));
|
|
76
|
+
console.log(chalk.gray(` Timestamp: ${formatDate(checkpoint.timestamp)}`));
|
|
77
|
+
console.log(chalk.gray(` Signatures: ${checkpoint.validatorSignatures.length}`));
|
|
78
|
+
}
|
|
79
|
+
function printPeersTable(peers) {
|
|
80
|
+
if (peers.length === 0) {
|
|
81
|
+
console.log(chalk.gray(" No peers configured"));
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
console.log(
|
|
85
|
+
chalk.gray(
|
|
86
|
+
" " + "ID".padEnd(16) + "Status".padEnd(14) + "Last Sync".padEnd(22) + "Events (Rx/Tx)"
|
|
87
|
+
)
|
|
88
|
+
);
|
|
89
|
+
console.log(chalk.gray(" " + "-".repeat(70)));
|
|
90
|
+
for (const peer of peers) {
|
|
91
|
+
const statusColor = peer.status === "connected" ? chalk.green : peer.status === "syncing" ? chalk.yellow : peer.status === "error" ? chalk.red : chalk.gray;
|
|
92
|
+
const lastSync = peer.lastSyncTime ? formatDate(peer.lastSyncTime) : "Never";
|
|
93
|
+
const events = `${peer.eventsReceived}/${peer.eventsSent}`;
|
|
94
|
+
console.log(
|
|
95
|
+
" " + chalk.gray(peer.id.padEnd(16)) + statusColor(peer.status.padEnd(14)) + chalk.gray(lastSync.padEnd(22)) + chalk.gray(events)
|
|
96
|
+
);
|
|
97
|
+
if (peer.lastError) {
|
|
98
|
+
console.log(chalk.red(` Error: ${peer.lastError}`));
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
function printSyncResults(results) {
|
|
103
|
+
if (results.length === 0) {
|
|
104
|
+
console.log(chalk.gray(" No sync operations performed"));
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
console.log(
|
|
108
|
+
chalk.gray(
|
|
109
|
+
" " + "Peer".padEnd(16) + "Status".padEnd(10) + "Received".padEnd(10) + "Sent".padEnd(10) + "Duration"
|
|
110
|
+
)
|
|
111
|
+
);
|
|
112
|
+
console.log(chalk.gray(" " + "-".repeat(60)));
|
|
113
|
+
for (const result of results) {
|
|
114
|
+
const statusColor = result.success ? chalk.green : chalk.red;
|
|
115
|
+
const status = result.success ? "OK" : "FAIL";
|
|
116
|
+
console.log(
|
|
117
|
+
" " + chalk.gray(result.peerId.substring(0, 14).padEnd(16)) + statusColor(status.padEnd(10)) + chalk.gray(String(result.eventsReceived).padEnd(10)) + chalk.gray(String(result.eventsSent).padEnd(10)) + chalk.gray(formatDuration(result.duration))
|
|
118
|
+
);
|
|
119
|
+
if (result.error) {
|
|
120
|
+
console.log(chalk.red(` Error: ${result.error}`));
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
function parseDateToHLC(dateStr) {
|
|
125
|
+
if (!dateStr) return void 0;
|
|
126
|
+
const date = new Date(dateStr);
|
|
127
|
+
if (isNaN(date.getTime())) {
|
|
128
|
+
throw new Error(`Invalid date format: ${dateStr}`);
|
|
129
|
+
}
|
|
130
|
+
return {
|
|
131
|
+
physicalMs: date.getTime(),
|
|
132
|
+
logical: 0
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
function createAuditCommand() {
|
|
136
|
+
const audit = new Command("audit").description("Query and manage the exochain audit log");
|
|
137
|
+
audit.command("query").description("Query the audit log").option("-t, --type <type>", "Filter by event type (e.g., NodeCreated, WorkflowCompleted)").option("-s, --start <date>", "Start date (ISO format, e.g., 2024-01-01)").option("-e, --end <date>", "End date (ISO format)").option("-l, --limit <n>", "Maximum results to return", "50").option("-a, --author <did>", "Filter by author DID").option("--json", "Output as JSON").option("-p, --path <path>", "Project root path", ".").action(async (options) => {
|
|
138
|
+
const spinner = ora("Querying audit log...").start();
|
|
139
|
+
try {
|
|
140
|
+
const projectRoot = validateProjectRoot(options.path);
|
|
141
|
+
const auditChain = createAuditChain(createAuditChainConfig());
|
|
142
|
+
const queryOptions = {
|
|
143
|
+
limit: parseInt(options.limit, 10) || 50,
|
|
144
|
+
includeProof: false
|
|
145
|
+
};
|
|
146
|
+
if (options.type) {
|
|
147
|
+
queryOptions.type = options.type;
|
|
148
|
+
}
|
|
149
|
+
if (options.author) {
|
|
150
|
+
queryOptions.author = options.author;
|
|
151
|
+
}
|
|
152
|
+
if (options.start) {
|
|
153
|
+
queryOptions.since = parseDateToHLC(options.start);
|
|
154
|
+
}
|
|
155
|
+
if (options.end) {
|
|
156
|
+
queryOptions.until = parseDateToHLC(options.end);
|
|
157
|
+
}
|
|
158
|
+
const result = await auditChain.queryEvents(queryOptions);
|
|
159
|
+
spinner.stop();
|
|
160
|
+
if (options.json) {
|
|
161
|
+
console.log(JSON.stringify({
|
|
162
|
+
events: result.events.map((e) => ({
|
|
163
|
+
id: e.id,
|
|
164
|
+
type: e.envelope.payload.type,
|
|
165
|
+
author: e.envelope.author,
|
|
166
|
+
timestamp: e.envelope.hlc.physicalMs,
|
|
167
|
+
parents: e.envelope.parents,
|
|
168
|
+
payload: e.envelope.payload
|
|
169
|
+
})),
|
|
170
|
+
totalCount: result.totalCount,
|
|
171
|
+
hasMore: result.hasMore
|
|
172
|
+
}, null, 2));
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
console.log(chalk.cyan("\n Audit Log Query Results\n"));
|
|
176
|
+
console.log(chalk.gray(` Found ${result.totalCount} events (showing ${result.events.length})`));
|
|
177
|
+
if (result.hasMore) {
|
|
178
|
+
console.log(chalk.gray(" (more results available, increase --limit to see more)"));
|
|
179
|
+
}
|
|
180
|
+
console.log();
|
|
181
|
+
printEventsTable(result.events);
|
|
182
|
+
console.log();
|
|
183
|
+
const stats = auditChain.getStats();
|
|
184
|
+
console.log(chalk.gray(` Chain status: `) + chalk.green(stats.status));
|
|
185
|
+
console.log();
|
|
186
|
+
} catch (error) {
|
|
187
|
+
spinner.fail("Query failed");
|
|
188
|
+
console.error(chalk.red(String(error)));
|
|
189
|
+
process.exit(1);
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
audit.command("checkpoint").description("Create a checkpoint in the audit chain").option("-n, --name <name>", "Checkpoint name/label").option("-t, --tags <tags>", "Comma-separated tags").option("--json", "Output as JSON").option("-p, --path <path>", "Project root path", ".").action(async (options) => {
|
|
193
|
+
const spinner = ora("Creating checkpoint...").start();
|
|
194
|
+
try {
|
|
195
|
+
const projectRoot = validateProjectRoot(options.path);
|
|
196
|
+
const auditChain = createAuditChain(createAuditChainConfig());
|
|
197
|
+
const checkpoint = await auditChain.createCheckpoint();
|
|
198
|
+
spinner.succeed("Checkpoint created!");
|
|
199
|
+
if (options.json) {
|
|
200
|
+
console.log(JSON.stringify({
|
|
201
|
+
height: checkpoint.height,
|
|
202
|
+
eventRoot: checkpoint.eventRoot,
|
|
203
|
+
stateRoot: checkpoint.stateRoot,
|
|
204
|
+
timestamp: checkpoint.timestamp.toISOString(),
|
|
205
|
+
signatures: checkpoint.validatorSignatures.length,
|
|
206
|
+
name: options.name,
|
|
207
|
+
tags: options.tags?.split(",").map((t) => t.trim())
|
|
208
|
+
}, null, 2));
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
console.log(chalk.cyan("\n Checkpoint Details\n"));
|
|
212
|
+
if (options.name) {
|
|
213
|
+
console.log(chalk.white(` Name: ${options.name}`));
|
|
214
|
+
}
|
|
215
|
+
if (options.tags) {
|
|
216
|
+
const tags = options.tags.split(",").map((t) => t.trim());
|
|
217
|
+
console.log(chalk.white(` Tags: ${tags.join(", ")}`));
|
|
218
|
+
}
|
|
219
|
+
console.log();
|
|
220
|
+
printCheckpoint(checkpoint);
|
|
221
|
+
console.log();
|
|
222
|
+
} catch (error) {
|
|
223
|
+
spinner.fail("Checkpoint creation failed");
|
|
224
|
+
console.error(chalk.red(String(error)));
|
|
225
|
+
process.exit(1);
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
audit.command("verify").description("Verify audit chain integrity").option("--full", "Perform full chain verification (slower)").option("--json", "Output as JSON").option("-p, --path <path>", "Project root path", ".").action(async (options) => {
|
|
229
|
+
const spinner = ora("Verifying audit chain integrity...").start();
|
|
230
|
+
try {
|
|
231
|
+
const projectRoot = validateProjectRoot(options.path);
|
|
232
|
+
const auditChain = createAuditChain(createAuditChainConfig());
|
|
233
|
+
const startTime = Date.now();
|
|
234
|
+
const stats = auditChain.getStats();
|
|
235
|
+
const checkpoint = auditChain.getLatestCheckpoint();
|
|
236
|
+
const issues = [];
|
|
237
|
+
const warnings = [];
|
|
238
|
+
if (stats.status === "degraded") {
|
|
239
|
+
issues.push("Chain status is degraded");
|
|
240
|
+
}
|
|
241
|
+
if (stats.checkpointHeight > 0 && !checkpoint) {
|
|
242
|
+
issues.push("Checkpoint height > 0 but no checkpoint found");
|
|
243
|
+
}
|
|
244
|
+
const chainData = auditChain.export();
|
|
245
|
+
let genesisCount = 0;
|
|
246
|
+
for (const event of chainData.events) {
|
|
247
|
+
if (event.envelope.parents.length === 0) {
|
|
248
|
+
genesisCount++;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
if (genesisCount > 1) {
|
|
252
|
+
warnings.push(`Multiple genesis events found: ${genesisCount}`);
|
|
253
|
+
}
|
|
254
|
+
const tips = auditChain.getTips();
|
|
255
|
+
if (tips.length === 0 && chainData.events.length > 0) {
|
|
256
|
+
issues.push("No chain tips but events exist");
|
|
257
|
+
}
|
|
258
|
+
if (options.full) {
|
|
259
|
+
spinner.text = "Performing full chain verification...";
|
|
260
|
+
for (const event of chainData.events) {
|
|
261
|
+
for (const parentId of event.envelope.parents) {
|
|
262
|
+
const parent = chainData.events.find((e) => e.id === parentId);
|
|
263
|
+
if (!parent) {
|
|
264
|
+
issues.push(`Event ${event.id.substring(0, 12)}.. references missing parent ${parentId.substring(0, 12)}..`);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
const duration = Date.now() - startTime;
|
|
270
|
+
const valid = issues.length === 0;
|
|
271
|
+
spinner.stop();
|
|
272
|
+
if (options.json) {
|
|
273
|
+
console.log(JSON.stringify({
|
|
274
|
+
valid,
|
|
275
|
+
issues,
|
|
276
|
+
warnings,
|
|
277
|
+
stats: {
|
|
278
|
+
totalEvents: stats.totalEvents,
|
|
279
|
+
checkpointHeight: stats.checkpointHeight,
|
|
280
|
+
status: stats.status,
|
|
281
|
+
tips: tips.length
|
|
282
|
+
},
|
|
283
|
+
duration
|
|
284
|
+
}, null, 2));
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
console.log(chalk.cyan("\n Audit Chain Verification\n"));
|
|
288
|
+
if (valid) {
|
|
289
|
+
console.log(chalk.green(" Status: VALID"));
|
|
290
|
+
} else {
|
|
291
|
+
console.log(chalk.red(" Status: INVALID"));
|
|
292
|
+
}
|
|
293
|
+
console.log();
|
|
294
|
+
console.log(chalk.white(" Statistics"));
|
|
295
|
+
console.log(chalk.gray(` Events verified: ${stats.totalEvents}`));
|
|
296
|
+
console.log(chalk.gray(` Checkpoint height: ${stats.checkpointHeight}`));
|
|
297
|
+
console.log(chalk.gray(` Chain tips: ${tips.length}`));
|
|
298
|
+
console.log(chalk.gray(` Verification time: ${formatDuration(duration)}`));
|
|
299
|
+
if (issues.length > 0) {
|
|
300
|
+
console.log();
|
|
301
|
+
console.log(chalk.red(" Issues Found"));
|
|
302
|
+
for (const issue of issues) {
|
|
303
|
+
console.log(chalk.red(` - ${issue}`));
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
if (warnings.length > 0) {
|
|
307
|
+
console.log();
|
|
308
|
+
console.log(chalk.yellow(" Warnings"));
|
|
309
|
+
for (const warning of warnings) {
|
|
310
|
+
console.log(chalk.yellow(` - ${warning}`));
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
console.log();
|
|
314
|
+
if (!valid) {
|
|
315
|
+
process.exit(1);
|
|
316
|
+
}
|
|
317
|
+
} catch (error) {
|
|
318
|
+
spinner.fail("Verification failed");
|
|
319
|
+
console.error(chalk.red(String(error)));
|
|
320
|
+
process.exit(1);
|
|
321
|
+
}
|
|
322
|
+
});
|
|
323
|
+
const sync = audit.command("sync").description("Manage audit chain synchronization");
|
|
324
|
+
sync.command("status").description("Check synchronization status").option("--json", "Output as JSON").option("-p, --path <path>", "Project root path", ".").action(async (options) => {
|
|
325
|
+
const spinner = ora("Checking sync status...").start();
|
|
326
|
+
try {
|
|
327
|
+
const projectRoot = validateProjectRoot(options.path);
|
|
328
|
+
const auditChain = createAuditChain(createAuditChainConfig());
|
|
329
|
+
const syndication = createSyndicationService({ auditChain });
|
|
330
|
+
const stats = syndication.getStats();
|
|
331
|
+
const chainStats = auditChain.getStats();
|
|
332
|
+
spinner.stop();
|
|
333
|
+
if (options.json) {
|
|
334
|
+
console.log(JSON.stringify({
|
|
335
|
+
service: {
|
|
336
|
+
running: stats.isRunning,
|
|
337
|
+
autoSyncEnabled: stats.autoSyncEnabled,
|
|
338
|
+
syncInterval: stats.syncInterval
|
|
339
|
+
},
|
|
340
|
+
peers: {
|
|
341
|
+
total: stats.totalPeers,
|
|
342
|
+
connected: stats.connectedPeers,
|
|
343
|
+
syncing: stats.syncingPeers,
|
|
344
|
+
error: stats.errorPeers
|
|
345
|
+
},
|
|
346
|
+
transfer: {
|
|
347
|
+
received: stats.totalEventsReceived,
|
|
348
|
+
sent: stats.totalEventsSent,
|
|
349
|
+
errors: stats.totalErrors
|
|
350
|
+
},
|
|
351
|
+
chain: {
|
|
352
|
+
status: chainStats.status,
|
|
353
|
+
events: chainStats.totalEvents,
|
|
354
|
+
checkpointHeight: chainStats.checkpointHeight
|
|
355
|
+
}
|
|
356
|
+
}, null, 2));
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
console.log(chalk.cyan("\n Sync Status\n"));
|
|
360
|
+
console.log(chalk.white(" Service"));
|
|
361
|
+
console.log(chalk.gray(` Running: `) + (stats.isRunning ? chalk.green("Yes") : chalk.gray("No")));
|
|
362
|
+
console.log(chalk.gray(` Auto-sync: `) + (stats.autoSyncEnabled ? chalk.green("Enabled") : chalk.gray("Disabled")));
|
|
363
|
+
if (stats.autoSyncEnabled) {
|
|
364
|
+
console.log(chalk.gray(` Interval: ${formatDuration(stats.syncInterval)}`));
|
|
365
|
+
}
|
|
366
|
+
console.log();
|
|
367
|
+
console.log(chalk.white(" Peers"));
|
|
368
|
+
console.log(chalk.gray(` Total: ${stats.totalPeers}`));
|
|
369
|
+
console.log(chalk.gray(` Connected: `) + chalk.green(String(stats.connectedPeers)));
|
|
370
|
+
if (stats.syncingPeers > 0) {
|
|
371
|
+
console.log(chalk.gray(` Syncing: `) + chalk.yellow(String(stats.syncingPeers)));
|
|
372
|
+
}
|
|
373
|
+
if (stats.errorPeers > 0) {
|
|
374
|
+
console.log(chalk.gray(` Errors: `) + chalk.red(String(stats.errorPeers)));
|
|
375
|
+
}
|
|
376
|
+
console.log();
|
|
377
|
+
console.log(chalk.white(" Transfer Statistics"));
|
|
378
|
+
console.log(chalk.gray(` Events received: ${stats.totalEventsReceived}`));
|
|
379
|
+
console.log(chalk.gray(` Events sent: ${stats.totalEventsSent}`));
|
|
380
|
+
if (stats.totalErrors > 0) {
|
|
381
|
+
console.log(chalk.gray(` Errors: `) + chalk.red(String(stats.totalErrors)));
|
|
382
|
+
}
|
|
383
|
+
console.log();
|
|
384
|
+
console.log(chalk.white(" Chain"));
|
|
385
|
+
const chainStatusColor = chainStats.status === "healthy" ? chalk.green : chainStats.status === "syncing" ? chalk.yellow : chalk.red;
|
|
386
|
+
console.log(chalk.gray(` Status: `) + chainStatusColor(chainStats.status));
|
|
387
|
+
console.log(chalk.gray(` Events: ${chainStats.totalEvents}`));
|
|
388
|
+
console.log(chalk.gray(` Checkpoint: ${chainStats.checkpointHeight}`));
|
|
389
|
+
console.log();
|
|
390
|
+
} catch (error) {
|
|
391
|
+
spinner.fail("Status check failed");
|
|
392
|
+
console.error(chalk.red(String(error)));
|
|
393
|
+
process.exit(1);
|
|
394
|
+
}
|
|
395
|
+
});
|
|
396
|
+
sync.command("peers").description("List sync peers").option("--json", "Output as JSON").option("-p, --path <path>", "Project root path", ".").action(async (options) => {
|
|
397
|
+
const spinner = ora("Fetching peer list...").start();
|
|
398
|
+
try {
|
|
399
|
+
const projectRoot = validateProjectRoot(options.path);
|
|
400
|
+
const auditChain = createAuditChain(createAuditChainConfig());
|
|
401
|
+
const syndication = createSyndicationService({ auditChain });
|
|
402
|
+
const peers = syndication.getAllPeers();
|
|
403
|
+
spinner.stop();
|
|
404
|
+
if (options.json) {
|
|
405
|
+
console.log(JSON.stringify({
|
|
406
|
+
peers: peers.map((p) => ({
|
|
407
|
+
id: p.id,
|
|
408
|
+
endpoint: p.endpoint,
|
|
409
|
+
did: p.did,
|
|
410
|
+
status: p.status,
|
|
411
|
+
lastSync: p.lastSyncTime?.toISOString(),
|
|
412
|
+
lastCheckpointHeight: p.lastCheckpointHeight,
|
|
413
|
+
eventsReceived: p.eventsReceived,
|
|
414
|
+
eventsSent: p.eventsSent,
|
|
415
|
+
errors: p.errors,
|
|
416
|
+
lastError: p.lastError,
|
|
417
|
+
latency: p.latency
|
|
418
|
+
})),
|
|
419
|
+
summary: {
|
|
420
|
+
total: peers.length,
|
|
421
|
+
connected: peers.filter((p) => p.status === "connected").length,
|
|
422
|
+
error: peers.filter((p) => p.status === "error").length
|
|
423
|
+
}
|
|
424
|
+
}, null, 2));
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
console.log(chalk.cyan("\n Sync Peers\n"));
|
|
428
|
+
printPeersTable(peers);
|
|
429
|
+
const connected = peers.filter((p) => p.status === "connected").length;
|
|
430
|
+
const errors = peers.filter((p) => p.status === "error").length;
|
|
431
|
+
console.log();
|
|
432
|
+
console.log(chalk.gray(` Total: ${peers.length}, Connected: ${connected}, Errors: ${errors}`));
|
|
433
|
+
console.log();
|
|
434
|
+
} catch (error) {
|
|
435
|
+
spinner.fail("Failed to fetch peers");
|
|
436
|
+
console.error(chalk.red(String(error)));
|
|
437
|
+
process.exit(1);
|
|
438
|
+
}
|
|
439
|
+
});
|
|
440
|
+
sync.command("now").description("Force immediate synchronization with all peers").option("--json", "Output as JSON").option("-p, --path <path>", "Project root path", ".").action(async (options) => {
|
|
441
|
+
const spinner = ora("Syncing with peers...").start();
|
|
442
|
+
try {
|
|
443
|
+
const projectRoot = validateProjectRoot(options.path);
|
|
444
|
+
const auditChain = createAuditChain(createAuditChainConfig());
|
|
445
|
+
const syndication = createSyndicationService({ auditChain });
|
|
446
|
+
await syndication.start();
|
|
447
|
+
const results = await syndication.forceSyncNow();
|
|
448
|
+
await syndication.stop();
|
|
449
|
+
spinner.stop();
|
|
450
|
+
if (options.json) {
|
|
451
|
+
console.log(JSON.stringify({
|
|
452
|
+
results: results.map((r) => ({
|
|
453
|
+
peerId: r.peerId,
|
|
454
|
+
success: r.success,
|
|
455
|
+
eventsReceived: r.eventsReceived,
|
|
456
|
+
eventsSent: r.eventsSent,
|
|
457
|
+
newCheckpointHeight: r.newCheckpointHeight,
|
|
458
|
+
duration: r.duration,
|
|
459
|
+
error: r.error
|
|
460
|
+
})),
|
|
461
|
+
summary: {
|
|
462
|
+
total: results.length,
|
|
463
|
+
successful: results.filter((r) => r.success).length,
|
|
464
|
+
failed: results.filter((r) => !r.success).length
|
|
465
|
+
}
|
|
466
|
+
}, null, 2));
|
|
467
|
+
return;
|
|
468
|
+
}
|
|
469
|
+
console.log(chalk.cyan("\n Sync Results\n"));
|
|
470
|
+
printSyncResults(results);
|
|
471
|
+
const successful = results.filter((r) => r.success).length;
|
|
472
|
+
const failed = results.filter((r) => !r.success).length;
|
|
473
|
+
const totalReceived = results.reduce((sum, r) => sum + r.eventsReceived, 0);
|
|
474
|
+
const totalSent = results.reduce((sum, r) => sum + r.eventsSent, 0);
|
|
475
|
+
console.log();
|
|
476
|
+
console.log(chalk.gray(` Peers: ${results.length} (${successful} successful, ${failed} failed)`));
|
|
477
|
+
console.log(chalk.gray(` Events: ${totalReceived} received, ${totalSent} sent`));
|
|
478
|
+
console.log();
|
|
479
|
+
if (failed > 0) {
|
|
480
|
+
process.exit(1);
|
|
481
|
+
}
|
|
482
|
+
} catch (error) {
|
|
483
|
+
spinner.fail("Sync failed");
|
|
484
|
+
console.error(chalk.red(String(error)));
|
|
485
|
+
process.exit(1);
|
|
486
|
+
}
|
|
487
|
+
});
|
|
488
|
+
audit.command("export").description("Export audit log data").option("-o, --output <file>", "Output file path").option("-f, --format <format>", "Export format (json|jsonl)", "json").option("-t, --type <type>", "Filter by event type").option("-s, --start <date>", "Start date filter").option("-e, --end <date>", "End date filter").option("-l, --limit <n>", "Maximum events to export").option("-p, --path <path>", "Project root path", ".").action(async (options) => {
|
|
489
|
+
const spinner = ora("Exporting audit log...").start();
|
|
490
|
+
try {
|
|
491
|
+
const projectRoot = validateProjectRoot(options.path);
|
|
492
|
+
const auditChain = createAuditChain(createAuditChainConfig());
|
|
493
|
+
const queryOptions = {
|
|
494
|
+
includeProof: true
|
|
495
|
+
};
|
|
496
|
+
if (options.type) {
|
|
497
|
+
queryOptions.type = options.type;
|
|
498
|
+
}
|
|
499
|
+
if (options.start) {
|
|
500
|
+
queryOptions.since = parseDateToHLC(options.start);
|
|
501
|
+
}
|
|
502
|
+
if (options.end) {
|
|
503
|
+
queryOptions.until = parseDateToHLC(options.end);
|
|
504
|
+
}
|
|
505
|
+
if (options.limit) {
|
|
506
|
+
queryOptions.limit = parseInt(options.limit, 10);
|
|
507
|
+
}
|
|
508
|
+
const result = await auditChain.queryEvents(queryOptions);
|
|
509
|
+
const chainData = auditChain.export();
|
|
510
|
+
const checkpoint = auditChain.getLatestCheckpoint();
|
|
511
|
+
const exportData = {
|
|
512
|
+
metadata: {
|
|
513
|
+
exportedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
514
|
+
chainStatus: auditChain.getStats().status,
|
|
515
|
+
totalEvents: result.totalCount,
|
|
516
|
+
exportedEvents: result.events.length,
|
|
517
|
+
checkpointHeight: checkpoint?.height ?? 0,
|
|
518
|
+
filters: {
|
|
519
|
+
type: options.type,
|
|
520
|
+
startDate: options.start,
|
|
521
|
+
endDate: options.end,
|
|
522
|
+
limit: options.limit
|
|
523
|
+
}
|
|
524
|
+
},
|
|
525
|
+
checkpoint: checkpoint ? {
|
|
526
|
+
height: checkpoint.height,
|
|
527
|
+
eventRoot: checkpoint.eventRoot,
|
|
528
|
+
stateRoot: checkpoint.stateRoot,
|
|
529
|
+
timestamp: checkpoint.timestamp.toISOString(),
|
|
530
|
+
signatures: checkpoint.validatorSignatures.length
|
|
531
|
+
} : null,
|
|
532
|
+
events: result.events.map((e) => ({
|
|
533
|
+
id: e.id,
|
|
534
|
+
type: e.envelope.payload.type,
|
|
535
|
+
author: e.envelope.author,
|
|
536
|
+
timestamp: new Date(e.envelope.hlc.physicalMs).toISOString(),
|
|
537
|
+
hlc: e.envelope.hlc,
|
|
538
|
+
parents: e.envelope.parents,
|
|
539
|
+
payload: e.envelope.payload,
|
|
540
|
+
signature: e.signature
|
|
541
|
+
})),
|
|
542
|
+
tips: chainData.tips
|
|
543
|
+
};
|
|
544
|
+
let output;
|
|
545
|
+
if (options.format === "jsonl") {
|
|
546
|
+
const lines = [
|
|
547
|
+
JSON.stringify({ type: "metadata", data: exportData.metadata }),
|
|
548
|
+
...exportData.checkpoint ? [JSON.stringify({ type: "checkpoint", data: exportData.checkpoint })] : [],
|
|
549
|
+
...exportData.events.map((e) => JSON.stringify({ type: "event", data: e }))
|
|
550
|
+
];
|
|
551
|
+
output = lines.join("\n");
|
|
552
|
+
} else {
|
|
553
|
+
output = JSON.stringify(exportData, null, 2);
|
|
554
|
+
}
|
|
555
|
+
spinner.stop();
|
|
556
|
+
if (options.output) {
|
|
557
|
+
const outputPath = join(projectRoot, options.output);
|
|
558
|
+
await writeFile(outputPath, output, "utf-8");
|
|
559
|
+
console.log(chalk.green(`
|
|
560
|
+
Exported ${result.events.length} events to ${outputPath}
|
|
561
|
+
`));
|
|
562
|
+
} else {
|
|
563
|
+
console.log(output);
|
|
564
|
+
}
|
|
565
|
+
} catch (error) {
|
|
566
|
+
spinner.fail("Export failed");
|
|
567
|
+
console.error(chalk.red(String(error)));
|
|
568
|
+
process.exit(1);
|
|
569
|
+
}
|
|
570
|
+
});
|
|
571
|
+
audit.command("stats").description("Show audit chain statistics").option("--json", "Output as JSON").option("-p, --path <path>", "Project root path", ".").action(async (options) => {
|
|
572
|
+
try {
|
|
573
|
+
const projectRoot = validateProjectRoot(options.path);
|
|
574
|
+
const auditChain = createAuditChain(createAuditChainConfig());
|
|
575
|
+
const stats = auditChain.getStats();
|
|
576
|
+
const checkpoint = auditChain.getLatestCheckpoint();
|
|
577
|
+
const tips = auditChain.getTips();
|
|
578
|
+
if (options.json) {
|
|
579
|
+
console.log(JSON.stringify({
|
|
580
|
+
stats,
|
|
581
|
+
checkpoint: checkpoint ? {
|
|
582
|
+
height: checkpoint.height,
|
|
583
|
+
eventRoot: checkpoint.eventRoot,
|
|
584
|
+
stateRoot: checkpoint.stateRoot,
|
|
585
|
+
timestamp: checkpoint.timestamp.toISOString(),
|
|
586
|
+
signatures: checkpoint.validatorSignatures.length
|
|
587
|
+
} : null,
|
|
588
|
+
tips: {
|
|
589
|
+
count: tips.length,
|
|
590
|
+
ids: tips
|
|
591
|
+
}
|
|
592
|
+
}, null, 2));
|
|
593
|
+
return;
|
|
594
|
+
}
|
|
595
|
+
console.log(chalk.cyan("\n Audit Chain Statistics\n"));
|
|
596
|
+
printChainStats(stats);
|
|
597
|
+
console.log();
|
|
598
|
+
printCheckpoint(checkpoint);
|
|
599
|
+
if (tips.length > 0) {
|
|
600
|
+
console.log();
|
|
601
|
+
console.log(chalk.white(" Chain Tips"));
|
|
602
|
+
console.log(chalk.gray(` Count: ${tips.length}`));
|
|
603
|
+
for (const tip of tips.slice(0, 5)) {
|
|
604
|
+
console.log(chalk.gray(` - ${tip.substring(0, 32)}...`));
|
|
605
|
+
}
|
|
606
|
+
if (tips.length > 5) {
|
|
607
|
+
console.log(chalk.gray(` ... and ${tips.length - 5} more`));
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
console.log();
|
|
611
|
+
} catch (error) {
|
|
612
|
+
console.error(chalk.red("Failed to get statistics:"), String(error));
|
|
613
|
+
process.exit(1);
|
|
614
|
+
}
|
|
615
|
+
});
|
|
616
|
+
return audit;
|
|
617
|
+
}
|
|
618
|
+
export {
|
|
619
|
+
createAuditCommand
|
|
620
|
+
};
|
|
621
|
+
//# sourceMappingURL=audit.js.map
|