coherence-cli 0.7.0 → 0.8.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 +106 -1
- 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/nodes.mjs +10 -1
- 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/README.md
CHANGED
|
@@ -159,6 +159,35 @@ Every part of the network links to every other. Jump in wherever makes sense for
|
|
|
159
159
|
|
|
160
160
|
---
|
|
161
161
|
|
|
162
|
+
## API key — what it's for and how to get one
|
|
163
|
+
|
|
164
|
+
**No key needed for:** Browsing ideas, searching specs, viewing lineage, checking ledgers, reading node status, exploring the network.
|
|
165
|
+
|
|
166
|
+
**Key needed for:** Updating idea status, recording contributions, linking identities, voting on governance, creating specs, managing federation.
|
|
167
|
+
|
|
168
|
+
Most people start without a key. You only need one when you're ready to contribute.
|
|
169
|
+
|
|
170
|
+
### Get a key (interactive)
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
cc setup
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
This walks you through choosing a name, linking an identity (GitHub, Discord, Ethereum, etc.), and generates a key tied to your identity. Stored in `~/.coherence-network/config.json`.
|
|
177
|
+
|
|
178
|
+
### Manual setup
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
export COHERENCE_API_KEY=your-key
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Or set it permanently:
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
cc identity set myname
|
|
188
|
+
# Key is auto-generated and stored in ~/.coherence-network/config.json
|
|
189
|
+
```
|
|
190
|
+
|
|
162
191
|
## Configuration
|
|
163
192
|
|
|
164
193
|
By default, `cc` talks to the public API at `https://api.coherencycoin.com`. Override with environment variables:
|
|
@@ -167,7 +196,7 @@ By default, `cc` talks to the public API at `https://api.coherencycoin.com`. Ove
|
|
|
167
196
|
# Point to a local node
|
|
168
197
|
export COHERENCE_API_URL=http://localhost:8000
|
|
169
198
|
|
|
170
|
-
#
|
|
199
|
+
# Set API key for write operations
|
|
171
200
|
export COHERENCE_API_KEY=your-key
|
|
172
201
|
```
|
|
173
202
|
|
|
@@ -175,6 +204,82 @@ Config is stored in `~/.coherence-network/config.json`.
|
|
|
175
204
|
|
|
176
205
|
---
|
|
177
206
|
|
|
207
|
+
## Search, filter, and CRUD
|
|
208
|
+
|
|
209
|
+
Every resource in the network is accessible from the CLI. Here's how to find what you need:
|
|
210
|
+
|
|
211
|
+
### Ideas — the core unit
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
cc ideas # Top 20 by free-energy score (ROI × confidence)
|
|
215
|
+
cc ideas 50 # Top 50
|
|
216
|
+
cc idea <id> # Full detail: scores, open questions, children, tasks
|
|
217
|
+
cc idea create <id> <name> # Create a new idea
|
|
218
|
+
--desc "..." # Description
|
|
219
|
+
--value 50 --cost 5 # Potential value and estimated cost
|
|
220
|
+
--parent <parent-id> # Parent idea (fractal hierarchy)
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Specs — blueprints linked to ideas
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
cc specs # List specs with ROI and value gap
|
|
227
|
+
cc specs 50 # More results
|
|
228
|
+
cc spec <id> # Full spec: summary, pseudocode, implementation status
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### Tasks — the work queue
|
|
232
|
+
|
|
233
|
+
```bash
|
|
234
|
+
cc tasks # All pending tasks
|
|
235
|
+
cc tasks running # In-progress tasks
|
|
236
|
+
cc tasks completed 20 # Last 20 completed
|
|
237
|
+
cc task <id> # Full task: direction, idea link, output, provider
|
|
238
|
+
cc task next # Claim the highest-priority task
|
|
239
|
+
cc task seed <idea-id> spec # Create a task for an idea
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### Contributors and identity
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
cc identity # Your linked accounts and CC balance
|
|
246
|
+
cc identity lookup github <handle> # Find any contributor by provider identity
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### Nodes and federation
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
cc nodes # All nodes: status, SHA, providers, last seen
|
|
253
|
+
cc inbox # Messages from other nodes
|
|
254
|
+
cc msg <node> <text> # Send a message
|
|
255
|
+
cc cmd <node> status # Remote diagnostics
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### Searching and filtering
|
|
259
|
+
|
|
260
|
+
Most list commands accept a limit. For deeper filtering, use the API directly:
|
|
261
|
+
|
|
262
|
+
```bash
|
|
263
|
+
# Search ideas by keyword
|
|
264
|
+
curl -s "$CN_API/api/ideas/cards?search=treasury&limit=10" | jq '.items[] | {id, name}'
|
|
265
|
+
|
|
266
|
+
# Search specs by keyword
|
|
267
|
+
curl -s "$CN_API/api/spec-registry/cards?search=auth&limit=10" | jq '.items[] | {spec_id, title}'
|
|
268
|
+
|
|
269
|
+
# Filter tasks by type and status
|
|
270
|
+
curl -s "$CN_API/api/agent/tasks?status=completed&task_type=review&limit=10" | jq '.tasks[] | {id, task_type}'
|
|
271
|
+
|
|
272
|
+
# Contributor ledger
|
|
273
|
+
curl -s "$CN_API/api/contributions/ledger/seeker71" | jq '.balance'
|
|
274
|
+
|
|
275
|
+
# Ideas by parent (fractal drill-down)
|
|
276
|
+
curl -s "$CN_API/api/ideas/<parent-id>" | jq '.child_idea_ids'
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
The full API has 215 endpoints across 20 resource groups — see [api.coherencycoin.com/docs](https://api.coherencycoin.com/docs) for the complete reference. The CLI covers the most common operations; the API covers everything.
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
178
283
|
## All commands
|
|
179
284
|
|
|
180
285
|
```
|
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
|
+
}
|