coherence-cli 0.7.1 → 0.8.1
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/cc.mjs +196 -107
- package/lib/commands/assets.mjs +73 -0
- package/lib/commands/contributors.mjs +79 -0
- package/lib/commands/diagnostics.mjs +131 -0
- package/lib/commands/friction.mjs +86 -0
- package/lib/commands/governance.mjs +90 -0
- package/lib/commands/lineage.mjs +101 -0
- package/lib/commands/news.mjs +121 -0
- package/lib/commands/providers.mjs +57 -0
- package/lib/commands/services.mjs +106 -0
- package/lib/commands/traceability.mjs +107 -0
- package/lib/commands/treasury.mjs +69 -0
- package/package.json +1 -1
package/bin/cc.mjs
CHANGED
|
@@ -7,73 +7,57 @@
|
|
|
7
7
|
* Zero dependencies. Node 18+ required.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import { createRequire } from "node:module";
|
|
11
10
|
import { listIdeas, showIdea, shareIdea, stakeOnIdea, forkIdea, createIdea } from "../lib/commands/ideas.mjs";
|
|
12
11
|
import { listSpecs, showSpec } from "../lib/commands/specs.mjs";
|
|
13
12
|
import { contribute } from "../lib/commands/contribute.mjs";
|
|
14
13
|
import { showStatus, showResonance } from "../lib/commands/status.mjs";
|
|
15
14
|
import { showIdentity, linkIdentity, unlinkIdentity, lookupIdentity, setupIdentity, setIdentity } from "../lib/commands/identity.mjs";
|
|
16
|
-
import { listNodes, sendMessage, readMessages
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
signal: AbortSignal.timeout(3000),
|
|
29
|
-
});
|
|
30
|
-
if (!resp.ok) return;
|
|
31
|
-
const data = await resp.json();
|
|
32
|
-
const latest = data.version;
|
|
33
|
-
if (latest && latest !== LOCAL_VERSION && latest > LOCAL_VERSION) {
|
|
34
|
-
console.log(
|
|
35
|
-
`\n\x1b[33m Update available: ${LOCAL_VERSION} → ${latest} — auto-updating...\x1b[0m`,
|
|
36
|
-
);
|
|
37
|
-
const { execSync } = await import("node:child_process");
|
|
38
|
-
try {
|
|
39
|
-
execSync(`npm i -g coherence-cli@${latest}`, { stdio: "pipe" });
|
|
40
|
-
console.log(`\x1b[32m ✓ Updated to v${latest}\x1b[0m\n`);
|
|
41
|
-
} catch {
|
|
42
|
-
console.log(`\x1b[31m ✗ Auto-update failed. Run: npm i -g coherence-cli@${latest}\x1b[0m\n`);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
} catch {
|
|
46
|
-
// Silent — don't block the CLI for a version check
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const updateCheck = checkForUpdate();
|
|
15
|
+
import { listNodes, sendMessage, readMessages } from "../lib/commands/nodes.mjs";
|
|
16
|
+
import { listContributors, showContributor, showContributions } from "../lib/commands/contributors.mjs";
|
|
17
|
+
import { listAssets, showAsset, createAsset } from "../lib/commands/assets.mjs";
|
|
18
|
+
import { showNewsFeed, showTrending, showSources, addSource, showNewsResonance } from "../lib/commands/news.mjs";
|
|
19
|
+
import { showTreasury, showDeposits, makeDeposit } from "../lib/commands/treasury.mjs";
|
|
20
|
+
import { listLinks, showLink, showValuation, payoutPreview } from "../lib/commands/lineage.mjs";
|
|
21
|
+
import { listChangeRequests, showChangeRequest, vote, propose } from "../lib/commands/governance.mjs";
|
|
22
|
+
import { listServices, showService, showServicesHealth, showServicesDeps } from "../lib/commands/services.mjs";
|
|
23
|
+
import { showFrictionReport, listFrictionEvents, showFrictionCategories } from "../lib/commands/friction.mjs";
|
|
24
|
+
import { listProviders, showProviderStats } from "../lib/commands/providers.mjs";
|
|
25
|
+
import { showTraceability, showCoverage, traceIdea, traceSpec } from "../lib/commands/traceability.mjs";
|
|
26
|
+
import { showDiag, showDiagHealth, showDiagIssues, showDiagRunners, showDiagVisibility } from "../lib/commands/diagnostics.mjs";
|
|
51
27
|
|
|
52
28
|
const [command, ...args] = process.argv.slice(2);
|
|
53
29
|
|
|
54
30
|
const COMMANDS = {
|
|
55
|
-
ideas:
|
|
56
|
-
idea:
|
|
57
|
-
share:
|
|
58
|
-
stake:
|
|
59
|
-
fork:
|
|
60
|
-
specs:
|
|
61
|
-
spec:
|
|
62
|
-
contribute:
|
|
63
|
-
status:
|
|
64
|
-
resonance:
|
|
65
|
-
identity:
|
|
66
|
-
nodes:
|
|
67
|
-
msg:
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
31
|
+
ideas: () => listIdeas(args),
|
|
32
|
+
idea: () => handleIdea(args),
|
|
33
|
+
share: () => shareIdea(),
|
|
34
|
+
stake: () => stakeOnIdea(args),
|
|
35
|
+
fork: () => forkIdea(args),
|
|
36
|
+
specs: () => listSpecs(args),
|
|
37
|
+
spec: () => showSpec(args),
|
|
38
|
+
contribute: () => contribute(args),
|
|
39
|
+
status: () => showStatus(),
|
|
40
|
+
resonance: () => showResonance(),
|
|
41
|
+
identity: () => handleIdentity(args),
|
|
42
|
+
nodes: () => listNodes(),
|
|
43
|
+
msg: () => sendMessage(args),
|
|
44
|
+
messages: () => readMessages(args),
|
|
45
|
+
inbox: () => readMessages(args),
|
|
46
|
+
contributors: () => listContributors(args),
|
|
47
|
+
contributor: () => handleContributor(args),
|
|
48
|
+
assets: () => listAssets(args),
|
|
49
|
+
asset: () => handleAsset(args),
|
|
50
|
+
news: () => handleNews(args),
|
|
51
|
+
treasury: () => handleTreasury(args),
|
|
52
|
+
lineage: () => handleLineage(args),
|
|
53
|
+
governance: () => handleGovernance(args),
|
|
54
|
+
services: () => handleServices(args),
|
|
55
|
+
service: () => showService(args),
|
|
56
|
+
friction: () => handleFriction(args),
|
|
57
|
+
providers: () => handleProviders(args),
|
|
58
|
+
trace: () => handleTrace(args),
|
|
59
|
+
diag: () => handleDiag(args),
|
|
60
|
+
help: () => showHelp(),
|
|
77
61
|
};
|
|
78
62
|
|
|
79
63
|
async function handleIdea(args) {
|
|
@@ -81,17 +65,6 @@ async function handleIdea(args) {
|
|
|
81
65
|
return showIdea(args);
|
|
82
66
|
}
|
|
83
67
|
|
|
84
|
-
async function handleTask(args) {
|
|
85
|
-
const sub = args[0];
|
|
86
|
-
switch (sub) {
|
|
87
|
-
case "next": return claimNext();
|
|
88
|
-
case "claim": return claimTask(args.slice(1));
|
|
89
|
-
case "report": return reportTask(args.slice(1));
|
|
90
|
-
case "seed": return seedTask(args.slice(1));
|
|
91
|
-
default: return showTask(args);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
68
|
async function handleIdentity(args) {
|
|
96
69
|
const sub = args[0];
|
|
97
70
|
const subArgs = args.slice(1);
|
|
@@ -105,26 +78,101 @@ async function handleIdentity(args) {
|
|
|
105
78
|
}
|
|
106
79
|
}
|
|
107
80
|
|
|
108
|
-
async function
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
81
|
+
async function handleContributor(args) {
|
|
82
|
+
if (args[1] === "contributions") return showContributions(args);
|
|
83
|
+
return showContributor(args);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async function handleAsset(args) {
|
|
87
|
+
if (args[0] === "create") return createAsset(args.slice(1));
|
|
88
|
+
return showAsset(args);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async function handleNews(args) {
|
|
92
|
+
const sub = args[0];
|
|
93
|
+
switch (sub) {
|
|
94
|
+
case "trending": return showTrending();
|
|
95
|
+
case "sources": return showSources();
|
|
96
|
+
case "source":
|
|
97
|
+
if (args[1] === "add") return addSource(args.slice(2));
|
|
98
|
+
return showSources();
|
|
99
|
+
case "resonance": return showNewsResonance(args.slice(1));
|
|
100
|
+
default: return showNewsFeed();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async function handleTreasury(args) {
|
|
105
|
+
const sub = args[0];
|
|
106
|
+
switch (sub) {
|
|
107
|
+
case "deposits": return showDeposits(args.slice(1));
|
|
108
|
+
case "deposit": return makeDeposit(args.slice(1));
|
|
109
|
+
default: return showTreasury();
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
async function handleLineage(args) {
|
|
114
|
+
if (!args[0]) return listLinks([]);
|
|
115
|
+
if (args[1] === "valuation") return showValuation(args);
|
|
116
|
+
if (args[1] === "payout") return payoutPreview([args[0], args[2]]);
|
|
117
|
+
// If first arg is a number, treat as limit
|
|
118
|
+
if (/^\d+$/.test(args[0])) return listLinks(args);
|
|
119
|
+
return showLink(args);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async function handleGovernance(args) {
|
|
123
|
+
const sub = args[0];
|
|
124
|
+
switch (sub) {
|
|
125
|
+
case "vote": return vote(args.slice(1));
|
|
126
|
+
case "propose": return propose(args.slice(1));
|
|
127
|
+
case undefined: return listChangeRequests();
|
|
128
|
+
default: return showChangeRequest(args);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
async function handleServices(args) {
|
|
133
|
+
const sub = args[0];
|
|
134
|
+
switch (sub) {
|
|
135
|
+
case "health": return showServicesHealth();
|
|
136
|
+
case "deps": return showServicesDeps();
|
|
137
|
+
default: return listServices();
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
async function handleFriction(args) {
|
|
142
|
+
const sub = args[0];
|
|
143
|
+
switch (sub) {
|
|
144
|
+
case "events": return listFrictionEvents(args.slice(1));
|
|
145
|
+
case "categories": return showFrictionCategories();
|
|
146
|
+
default: return showFrictionReport();
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
async function handleProviders(args) {
|
|
151
|
+
const sub = args[0];
|
|
152
|
+
switch (sub) {
|
|
153
|
+
case "stats": return showProviderStats();
|
|
154
|
+
default: return listProviders();
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
async function handleTrace(args) {
|
|
159
|
+
const sub = args[0];
|
|
160
|
+
switch (sub) {
|
|
161
|
+
case "coverage": return showCoverage();
|
|
162
|
+
case "idea": return traceIdea(args.slice(1));
|
|
163
|
+
case "spec": return traceSpec(args.slice(1));
|
|
164
|
+
default: return showTraceability();
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
async function handleDiag(args) {
|
|
169
|
+
const sub = args[0];
|
|
170
|
+
switch (sub) {
|
|
171
|
+
case "health": return showDiagHealth();
|
|
172
|
+
case "issues": return showDiagIssues();
|
|
173
|
+
case "runners": return showDiagRunners();
|
|
174
|
+
case "visibility": return showDiagVisibility();
|
|
175
|
+
default: return showDiag();
|
|
128
176
|
}
|
|
129
177
|
}
|
|
130
178
|
|
|
@@ -158,31 +206,72 @@ function showHelp() {
|
|
|
158
206
|
identity unlink <p> Unlink a provider
|
|
159
207
|
identity lookup <p> <id> Find contributor by identity
|
|
160
208
|
|
|
161
|
-
\x1b[1mTasks (agent-to-agent):\x1b[0m
|
|
162
|
-
tasks [status] [limit] List tasks (pending|running|completed)
|
|
163
|
-
task <id> View task detail
|
|
164
|
-
task next Claim next pending task (for AI agents)
|
|
165
|
-
task claim <id> Claim a specific task
|
|
166
|
-
task report <id> <status> [output] Report result (completed|failed)
|
|
167
|
-
task seed <idea> [type] Create task from idea (spec|test|impl|review)
|
|
168
|
-
|
|
169
209
|
\x1b[1mFederation:\x1b[0m
|
|
170
210
|
nodes List federation nodes
|
|
171
211
|
msg <node|broadcast> <text> Send message to a node
|
|
172
|
-
cmd <node> <command> Remote command (update|status|diagnose|restart|ping)
|
|
173
212
|
inbox Read your messages
|
|
174
213
|
|
|
175
|
-
\x1b[
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
214
|
+
\x1b[1mContributors:\x1b[0m
|
|
215
|
+
contributors [limit] List contributors
|
|
216
|
+
contributor <id> View contributor detail
|
|
217
|
+
contributor <id> contributions View contributions
|
|
218
|
+
|
|
219
|
+
\x1b[1mAssets:\x1b[0m
|
|
220
|
+
assets [limit] List assets
|
|
221
|
+
asset <id> View asset detail
|
|
222
|
+
asset create <type> <desc> Create an asset
|
|
223
|
+
|
|
224
|
+
\x1b[1mNews:\x1b[0m
|
|
225
|
+
news News feed
|
|
226
|
+
news trending Trending news
|
|
227
|
+
news sources List news sources
|
|
228
|
+
news source add <url> <name> Add a news source
|
|
229
|
+
news resonance [contributor] News resonance
|
|
230
|
+
|
|
231
|
+
\x1b[1mTreasury:\x1b[0m
|
|
232
|
+
treasury Treasury overview
|
|
233
|
+
treasury deposits <id> Deposits for contributor
|
|
234
|
+
treasury deposit <amt> <asset> Make a deposit
|
|
235
|
+
|
|
236
|
+
\x1b[1mLineage:\x1b[0m
|
|
237
|
+
lineage [limit] Value lineage links
|
|
238
|
+
lineage <id> View lineage link
|
|
239
|
+
lineage <id> valuation Link valuation
|
|
240
|
+
lineage <id> payout <amt> Payout preview
|
|
241
|
+
|
|
242
|
+
\x1b[1mGovernance:\x1b[0m
|
|
243
|
+
governance List change requests
|
|
244
|
+
governance <id> View change request
|
|
245
|
+
governance vote <id> <yes|no> Vote on change request
|
|
246
|
+
governance propose <title> <desc> Create proposal
|
|
247
|
+
|
|
248
|
+
\x1b[1mServices:\x1b[0m
|
|
249
|
+
services List services
|
|
250
|
+
service <id> View service detail
|
|
251
|
+
services health Services health check
|
|
252
|
+
services deps Service dependencies
|
|
253
|
+
|
|
254
|
+
\x1b[1mFriction:\x1b[0m
|
|
255
|
+
friction Friction report
|
|
256
|
+
friction events [limit] Friction events
|
|
257
|
+
friction categories Friction categories
|
|
179
258
|
|
|
180
259
|
\x1b[1mProviders:\x1b[0m
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
260
|
+
providers List providers
|
|
261
|
+
providers stats Provider statistics
|
|
262
|
+
|
|
263
|
+
\x1b[1mTraceability:\x1b[0m
|
|
264
|
+
trace Traceability overview
|
|
265
|
+
trace coverage Traceability coverage
|
|
266
|
+
trace idea <id> Trace an idea
|
|
267
|
+
trace spec <id> Trace a spec
|
|
268
|
+
|
|
269
|
+
\x1b[1mDiagnostics:\x1b[0m
|
|
270
|
+
diag Agent effectiveness + pipeline
|
|
271
|
+
diag health Collective health
|
|
272
|
+
diag issues Fatal + monitor issues
|
|
273
|
+
diag runners Agent runners
|
|
274
|
+
diag visibility Agent visibility
|
|
186
275
|
|
|
187
276
|
\x1b[2mHub: https://api.coherencycoin.com\x1b[0m
|
|
188
277
|
`);
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Assets commands: assets, asset
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { get, post } from "../api.mjs";
|
|
6
|
+
|
|
7
|
+
function truncate(str, len) {
|
|
8
|
+
if (!str) return "";
|
|
9
|
+
return str.length > len ? str.slice(0, len - 1) + "\u2026" : str;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export async function listAssets(args) {
|
|
13
|
+
const limit = parseInt(args[0]) || 20;
|
|
14
|
+
const raw = await get("/api/assets", { limit });
|
|
15
|
+
const data = Array.isArray(raw) ? raw : raw?.assets;
|
|
16
|
+
if (!data || !Array.isArray(data)) {
|
|
17
|
+
console.log("Could not fetch assets.");
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
if (data.length === 0) {
|
|
21
|
+
console.log("No assets found.");
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
console.log();
|
|
26
|
+
console.log(`\x1b[1m ASSETS\x1b[0m (${data.length})`);
|
|
27
|
+
console.log(` ${"─".repeat(60)}`);
|
|
28
|
+
for (const a of data) {
|
|
29
|
+
const name = truncate(a.name || a.description || a.id, 35);
|
|
30
|
+
const type = (a.type || a.asset_type || "").padEnd(12);
|
|
31
|
+
console.log(` ${type} ${name}`);
|
|
32
|
+
}
|
|
33
|
+
console.log();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export async function showAsset(args) {
|
|
37
|
+
const id = args[0];
|
|
38
|
+
if (!id) {
|
|
39
|
+
console.log("Usage: cc asset <id>");
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const data = await get(`/api/assets/${encodeURIComponent(id)}`);
|
|
43
|
+
if (!data) {
|
|
44
|
+
console.log(`Asset '${id}' not found.`);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
console.log();
|
|
48
|
+
console.log(`\x1b[1m ${data.name || data.id}\x1b[0m`);
|
|
49
|
+
console.log(` ${"─".repeat(50)}`);
|
|
50
|
+
if (data.type || data.asset_type) console.log(` Type: ${data.type || data.asset_type}`);
|
|
51
|
+
if (data.description) console.log(` Description: ${truncate(data.description, 60)}`);
|
|
52
|
+
if (data.value != null) console.log(` Value: ${data.value}`);
|
|
53
|
+
if (data.created_at) console.log(` Created: ${data.created_at}`);
|
|
54
|
+
console.log();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export async function createAsset(args) {
|
|
58
|
+
const type = args[0];
|
|
59
|
+
const desc = args.slice(1).join(" ");
|
|
60
|
+
if (!type || !desc) {
|
|
61
|
+
console.log("Usage: cc asset create <type> <description>");
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const result = await post("/api/assets", {
|
|
65
|
+
type,
|
|
66
|
+
description: desc,
|
|
67
|
+
});
|
|
68
|
+
if (result) {
|
|
69
|
+
console.log(`\x1b[32m✓\x1b[0m Asset created: ${result.id || "(new)"}`);
|
|
70
|
+
} else {
|
|
71
|
+
console.log("Failed to create asset.");
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Contributors commands: contributors, contributor
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { get } from "../api.mjs";
|
|
6
|
+
|
|
7
|
+
function truncate(str, len) {
|
|
8
|
+
if (!str) return "";
|
|
9
|
+
return str.length > len ? str.slice(0, len - 1) + "\u2026" : str;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export async function listContributors(args) {
|
|
13
|
+
const limit = parseInt(args[0]) || 20;
|
|
14
|
+
const raw = await get("/api/contributors", { limit });
|
|
15
|
+
const data = Array.isArray(raw) ? raw : raw?.contributors;
|
|
16
|
+
if (!data || !Array.isArray(data)) {
|
|
17
|
+
console.log("Could not fetch contributors.");
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
if (data.length === 0) {
|
|
21
|
+
console.log("No contributors found.");
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
console.log();
|
|
26
|
+
console.log(`\x1b[1m CONTRIBUTORS\x1b[0m (${data.length})`);
|
|
27
|
+
console.log(` ${"─".repeat(60)}`);
|
|
28
|
+
for (const c of data) {
|
|
29
|
+
const name = truncate(c.name || c.display_name || c.id, 30);
|
|
30
|
+
const cc = c.total_cc != null ? `${c.total_cc} CC` : "";
|
|
31
|
+
console.log(` ${name.padEnd(32)} ${cc}`);
|
|
32
|
+
}
|
|
33
|
+
console.log();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export async function showContributor(args) {
|
|
37
|
+
const id = args[0];
|
|
38
|
+
if (!id) {
|
|
39
|
+
console.log("Usage: cc contributor <id>");
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const data = await get(`/api/contributors/${encodeURIComponent(id)}`);
|
|
43
|
+
if (!data) {
|
|
44
|
+
console.log(`Contributor '${id}' not found.`);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
console.log();
|
|
48
|
+
console.log(`\x1b[1m ${data.name || data.display_name || data.id}\x1b[0m`);
|
|
49
|
+
console.log(` ${"─".repeat(50)}`);
|
|
50
|
+
if (data.id) console.log(` ID: ${data.id}`);
|
|
51
|
+
if (data.total_cc != null) console.log(` Total CC: ${data.total_cc}`);
|
|
52
|
+
if (data.role) console.log(` Role: ${data.role}`);
|
|
53
|
+
if (data.joined_at) console.log(` Joined: ${data.joined_at}`);
|
|
54
|
+
console.log();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export async function showContributions(args) {
|
|
58
|
+
const id = args[0];
|
|
59
|
+
if (!id) {
|
|
60
|
+
console.log("Usage: cc contributor <id> contributions");
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const data = await get(`/api/contributors/${encodeURIComponent(id)}/contributions`);
|
|
64
|
+
const list = Array.isArray(data) ? data : data?.contributions;
|
|
65
|
+
if (!list || !Array.isArray(list)) {
|
|
66
|
+
console.log(`No contributions found for '${id}'.`);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
console.log();
|
|
71
|
+
console.log(`\x1b[1m CONTRIBUTIONS\x1b[0m for ${id} (${list.length})`);
|
|
72
|
+
console.log(` ${"─".repeat(60)}`);
|
|
73
|
+
for (const c of list) {
|
|
74
|
+
const desc = truncate(c.description || c.type || "?", 45);
|
|
75
|
+
const cc = c.cc_amount != null ? `${c.cc_amount} CC` : "";
|
|
76
|
+
console.log(` ${desc.padEnd(47)} ${cc}`);
|
|
77
|
+
}
|
|
78
|
+
console.log();
|
|
79
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Diagnostics commands: diag, diag health, diag issues, diag runners, diag visibility
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { get } from "../api.mjs";
|
|
6
|
+
|
|
7
|
+
function truncate(str, len) {
|
|
8
|
+
if (!str) return "";
|
|
9
|
+
return str.length > len ? str.slice(0, len - 1) + "\u2026" : str;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export async function showDiag() {
|
|
13
|
+
const [effectiveness, pipeline] = await Promise.all([
|
|
14
|
+
get("/api/agent/effectiveness"),
|
|
15
|
+
get("/api/agent/pipeline-status"),
|
|
16
|
+
]);
|
|
17
|
+
|
|
18
|
+
console.log();
|
|
19
|
+
console.log(`\x1b[1m DIAGNOSTICS\x1b[0m`);
|
|
20
|
+
console.log(` ${"─".repeat(50)}`);
|
|
21
|
+
|
|
22
|
+
if (effectiveness) {
|
|
23
|
+
console.log(` \x1b[1mEffectiveness:\x1b[0m`);
|
|
24
|
+
for (const [key, val] of Object.entries(effectiveness)) {
|
|
25
|
+
console.log(` ${key}: ${JSON.stringify(val)}`);
|
|
26
|
+
}
|
|
27
|
+
} else {
|
|
28
|
+
console.log(` Effectiveness: \x1b[2munavailable\x1b[0m`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (pipeline) {
|
|
32
|
+
console.log(` \x1b[1mPipeline Status:\x1b[0m`);
|
|
33
|
+
for (const [key, val] of Object.entries(pipeline)) {
|
|
34
|
+
console.log(` ${key}: ${JSON.stringify(val)}`);
|
|
35
|
+
}
|
|
36
|
+
} else {
|
|
37
|
+
console.log(` Pipeline Status: \x1b[2munavailable\x1b[0m`);
|
|
38
|
+
}
|
|
39
|
+
console.log();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export async function showDiagHealth() {
|
|
43
|
+
const data = await get("/api/agent/collective-health");
|
|
44
|
+
if (!data) {
|
|
45
|
+
console.log("Could not fetch collective health.");
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
console.log();
|
|
50
|
+
console.log(`\x1b[1m COLLECTIVE HEALTH\x1b[0m`);
|
|
51
|
+
console.log(` ${"─".repeat(50)}`);
|
|
52
|
+
for (const [key, val] of Object.entries(data)) {
|
|
53
|
+
console.log(` ${key}: ${JSON.stringify(val)}`);
|
|
54
|
+
}
|
|
55
|
+
console.log();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export async function showDiagIssues() {
|
|
59
|
+
const [fatal, monitor] = await Promise.all([
|
|
60
|
+
get("/api/agent/fatal-issues"),
|
|
61
|
+
get("/api/agent/monitor-issues"),
|
|
62
|
+
]);
|
|
63
|
+
|
|
64
|
+
console.log();
|
|
65
|
+
console.log(`\x1b[1m ISSUES\x1b[0m`);
|
|
66
|
+
console.log(` ${"─".repeat(50)}`);
|
|
67
|
+
|
|
68
|
+
const fatalList = Array.isArray(fatal) ? fatal : fatal?.issues || [];
|
|
69
|
+
const monitorList = Array.isArray(monitor) ? monitor : monitor?.issues || [];
|
|
70
|
+
|
|
71
|
+
if (fatalList.length > 0) {
|
|
72
|
+
console.log(` \x1b[31mFatal (${fatalList.length}):\x1b[0m`);
|
|
73
|
+
for (const i of fatalList) {
|
|
74
|
+
const desc = truncate(i.description || i.message || i.id || JSON.stringify(i), 60);
|
|
75
|
+
console.log(` \x1b[31m✗\x1b[0m ${desc}`);
|
|
76
|
+
}
|
|
77
|
+
} else {
|
|
78
|
+
console.log(` \x1b[32mNo fatal issues\x1b[0m`);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (monitorList.length > 0) {
|
|
82
|
+
console.log(` \x1b[33mMonitor (${monitorList.length}):\x1b[0m`);
|
|
83
|
+
for (const i of monitorList) {
|
|
84
|
+
const desc = truncate(i.description || i.message || i.id || JSON.stringify(i), 60);
|
|
85
|
+
console.log(` \x1b[33m!\x1b[0m ${desc}`);
|
|
86
|
+
}
|
|
87
|
+
} else {
|
|
88
|
+
console.log(` \x1b[32mNo monitor issues\x1b[0m`);
|
|
89
|
+
}
|
|
90
|
+
console.log();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export async function showDiagRunners() {
|
|
94
|
+
const raw = await get("/api/agent/runners");
|
|
95
|
+
const data = Array.isArray(raw) ? raw : raw?.runners;
|
|
96
|
+
if (!data || !Array.isArray(data)) {
|
|
97
|
+
console.log("Could not fetch runners.");
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
if (data.length === 0) {
|
|
101
|
+
console.log("No runners found.");
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
console.log();
|
|
106
|
+
console.log(`\x1b[1m RUNNERS\x1b[0m (${data.length})`);
|
|
107
|
+
console.log(` ${"─".repeat(50)}`);
|
|
108
|
+
for (const r of data) {
|
|
109
|
+
const name = truncate(r.name || r.id || "?", 25);
|
|
110
|
+
const status = r.status || "?";
|
|
111
|
+
const dot = status === "active" || status === "running" ? "\x1b[32m●\x1b[0m" : "\x1b[2m○\x1b[0m";
|
|
112
|
+
console.log(` ${dot} ${name.padEnd(27)} ${status}`);
|
|
113
|
+
}
|
|
114
|
+
console.log();
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export async function showDiagVisibility() {
|
|
118
|
+
const data = await get("/api/agent/visibility");
|
|
119
|
+
if (!data) {
|
|
120
|
+
console.log("Could not fetch visibility.");
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
console.log();
|
|
125
|
+
console.log(`\x1b[1m VISIBILITY\x1b[0m`);
|
|
126
|
+
console.log(` ${"─".repeat(50)}`);
|
|
127
|
+
for (const [key, val] of Object.entries(data)) {
|
|
128
|
+
console.log(` ${key}: ${JSON.stringify(val)}`);
|
|
129
|
+
}
|
|
130
|
+
console.log();
|
|
131
|
+
}
|