cnagent 2.0.2 → 2.0.4

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.
Files changed (2) hide show
  1. package/bin/cn +78 -7
  2. package/package.json +1 -1
package/bin/cn CHANGED
@@ -11,7 +11,7 @@ const { execSync, spawn } = require('child_process');
11
11
  const path = require('path');
12
12
  const fs = require('fs');
13
13
 
14
- const VERSION = '2.0.2';
14
+ const VERSION = '2.0.4';
15
15
 
16
16
  // Colors (respects NO_COLOR)
17
17
  const noColor = process.env.NO_COLOR !== undefined;
@@ -44,6 +44,7 @@ Commands:
44
44
  flush Execute decisions
45
45
  peer Manage peers
46
46
  doctor Check system health
47
+ update Update cn to latest version
47
48
 
48
49
  Aliases:
49
50
  i = inbox, s = status, d = doctor
@@ -103,6 +104,7 @@ function doctor(hubPath) {
103
104
  console.log('');
104
105
 
105
106
  let checks = [];
107
+ let warnings = [];
106
108
 
107
109
  // Git
108
110
  try {
@@ -127,28 +129,84 @@ function doctor(hubPath) {
127
129
  checks.push({ name: 'git user.email', ok: false, val: 'not set' });
128
130
  }
129
131
 
130
- // Hub
131
- checks.push({ name: 'hub directory', ok: fs.existsSync(hubPath), val: hubPath ? 'exists' : 'not found' });
132
+ // Hub directory
133
+ checks.push({ name: 'hub directory', ok: fs.existsSync(hubPath), val: fs.existsSync(hubPath) ? 'exists' : 'not found' });
132
134
 
133
- // Print
135
+ // .cn/config.json
136
+ const configPath = path.join(hubPath, '.cn', 'config.json');
137
+ checks.push({ name: '.cn/config.json', ok: fs.existsSync(configPath), val: fs.existsSync(configPath) ? 'exists' : 'missing' });
138
+
139
+ // spec/SOUL.md
140
+ const soulPath = path.join(hubPath, 'spec', 'SOUL.md');
141
+ if (fs.existsSync(soulPath)) {
142
+ checks.push({ name: 'spec/SOUL.md', ok: true, val: 'exists' });
143
+ } else {
144
+ warnings.push({ name: 'spec/SOUL.md', val: 'missing (optional)' });
145
+ }
146
+
147
+ // state/peers.md
148
+ const peersPath = path.join(hubPath, 'state', 'peers.md');
149
+ if (fs.existsSync(peersPath)) {
150
+ const content = fs.readFileSync(peersPath, 'utf8');
151
+ const peerCount = (content.match(/- name:/g) || []).length;
152
+ checks.push({ name: 'state/peers.md', ok: true, val: `${peerCount} peer(s)` });
153
+ } else {
154
+ checks.push({ name: 'state/peers.md', ok: false, val: 'missing' });
155
+ }
156
+
157
+ // origin remote
158
+ try {
159
+ execSync('git remote get-url origin', { cwd: hubPath, encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] });
160
+ checks.push({ name: 'origin remote', ok: true, val: 'configured' });
161
+ } catch {
162
+ checks.push({ name: 'origin remote', ok: false, val: 'not configured' });
163
+ }
164
+
165
+ // inbox status
166
+ try {
167
+ const result = execSync(`node ${path.join(__dirname, '..', 'dist', 'inbox.js')} check ${hubPath} ${deriveName(hubPath)} 2>&1`, { encoding: 'utf8' });
168
+ const inboundMatch = result.match(/(\d+) inbound/);
169
+ if (inboundMatch) {
170
+ const count = parseInt(inboundMatch[1]);
171
+ if (count > 0) {
172
+ warnings.push({ name: 'inbox', val: `${count} pending` });
173
+ } else {
174
+ checks.push({ name: 'inbox', ok: true, val: 'clear' });
175
+ }
176
+ } else if (result.includes('All clear')) {
177
+ checks.push({ name: 'inbox', ok: true, val: 'clear' });
178
+ }
179
+ } catch {
180
+ warnings.push({ name: 'inbox', val: 'check failed' });
181
+ }
182
+
183
+ // Print checks
134
184
  const width = 22;
135
185
  checks.forEach(({ name, ok: isOk, val }) => {
136
- const dots = '.'.repeat(width - name.length);
186
+ const dots = '.'.repeat(Math.max(1, width - name.length));
137
187
  const status = isOk
138
188
  ? `${c.green}✓ ${val}${c.reset}`
139
189
  : `${c.red}✗ ${val}${c.reset}`;
140
190
  console.log(`${name}${dots} ${status}`);
141
191
  });
142
192
 
193
+ // Print warnings
194
+ warnings.forEach(({ name, val }) => {
195
+ const dots = '.'.repeat(Math.max(1, width - name.length));
196
+ console.log(`${name}${dots} ${c.yellow}⚠ ${val}${c.reset}`);
197
+ });
198
+
143
199
  console.log('');
144
200
  const fails = checks.filter(c => !c.ok).length;
201
+ const warns = warnings.length;
202
+
145
203
  if (fails === 0) {
146
- ok('All checks passed.');
204
+ ok('All critical checks passed.');
147
205
  } else {
148
206
  fail(`${fails} issue(s) found.`);
149
207
  }
150
208
 
151
- console.log(`${c.dim}[status] ok=${checks.filter(c=>c.ok).length} fail=${fails} version=${VERSION}${c.reset}`);
209
+ console.log(`${c.dim}[status] ok=${checks.filter(c=>c.ok).length} warn=${warns} fail=${fails} version=${VERSION}${c.reset}`);
152
210
  process.exit(fails > 0 ? 1 : 0);
153
211
  }
154
212
 
@@ -184,6 +242,19 @@ if (command === 'init') {
184
242
  process.exit(1);
185
243
  }
186
244
 
245
+ if (command === 'update') {
246
+ info('Updating cnagent...');
247
+ try {
248
+ execSync('npm install -g cnagent@latest', { stdio: 'inherit' });
249
+ ok('Updated to latest version.');
250
+ execSync('cn --version', { stdio: 'inherit' });
251
+ } catch (e) {
252
+ fail('Update failed. Try: npm install -g cnagent@latest');
253
+ process.exit(1);
254
+ }
255
+ process.exit(0);
256
+ }
257
+
187
258
  // Find hub
188
259
  const hubPath = findHubPath();
189
260
  if (!hubPath) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cnagent",
3
- "version": "2.0.2",
3
+ "version": "2.0.4",
4
4
  "description": "Coherent Network agent CLI — everything runs through cn",
5
5
  "keywords": [
6
6
  "cn-agent",