nightpay 0.3.0 → 0.3.2

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.

Potentially problematic release.


This version of nightpay might be problematic. Click here for more details.

package/bin/cli.js CHANGED
@@ -1,12 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { cpSync, existsSync, mkdirSync, readFileSync, chmodSync, readdirSync } from "node:fs";
4
- import { resolve, dirname, join } from "node:path";
3
+ import { cpSync, copyFileSync, existsSync, mkdirSync, readFileSync, chmodSync, readdirSync, statSync, writeFileSync } from "node:fs";
4
+ import { resolve, dirname, join, basename } from "node:path";
5
5
  import { fileURLToPath } from "node:url";
6
6
  import { execSync, spawnSync } from "node:child_process";
7
7
 
8
8
  const __dirname = dirname(fileURLToPath(import.meta.url));
9
- const SKILL_SRC = resolve(__dirname, "..", "skills", "nightpay");
9
+ const PKG_ROOT = resolve(__dirname, "..");
10
+ const SKILL_SRC = resolve(PKG_ROOT, "skills", "nightpay");
11
+ const SDK_SRC = resolve(PKG_ROOT, "nightpay_sdk.py");
12
+ const SETUP_SRC = resolve(PKG_ROOT, "scripts", "setup.sh");
10
13
  const COMMANDS = ["init", "add", "setup", "validate", "doctor", "list", "help"];
11
14
 
12
15
  const command = process.argv[2] || "help";
@@ -16,6 +19,13 @@ if (!COMMANDS.includes(command)) {
16
19
  process.exit(1);
17
20
  }
18
21
 
22
+ // ─── Version ─────────────────────────────────────────────────────────────────
23
+ let VERSION = "0.3.2";
24
+ try {
25
+ const pkg = JSON.parse(readFileSync(resolve(PKG_ROOT, "package.json"), "utf8"));
26
+ VERSION = pkg.version || VERSION;
27
+ } catch {}
28
+
19
29
  // ─── Colors ──────────────────────────────────────────────────────────────────
20
30
  const isTTY = process.stderr.isTTY;
21
31
  const C = {
@@ -30,14 +40,15 @@ const C = {
30
40
  const OK = `${C.green}✅${C.reset}`;
31
41
  const FAIL = `${C.red}❌${C.reset}`;
32
42
  const WARN = `${C.yellow}⚠️${C.reset}`;
43
+ const INFO = `${C.cyan}ℹ${C.reset}`;
33
44
 
34
45
  // ─── Help ────────────────────────────────────────────────────────────────────
35
46
  if (command === "help") {
36
47
  console.log(`
37
- ${C.bold}nightpay${C.reset} — anonymous community bounties for AI agents
48
+ ${C.bold}nightpay${C.reset} v${VERSION} — anonymous community bounties for AI agents
38
49
 
39
50
  ${C.bold}COMMANDS${C.reset}
40
- npx nightpay ${C.cyan}init${C.reset} Copy skill files into ./skills/nightpay
51
+ npx nightpay ${C.cyan}init${C.reset} Install skill files, SDK, and setup script
41
52
  npx nightpay ${C.cyan}setup${C.reset} Full onboarding: install + validate + platform config
42
53
  npx nightpay ${C.cyan}validate${C.reset} Check env vars, prerequisites, and connectivity
43
54
  npx nightpay ${C.cyan}doctor${C.reset} Diagnose and auto-fix common issues
@@ -55,6 +66,11 @@ ${C.bold}QUICK START${C.reset}
55
66
  export NIGHTPAY_API_URL="https://api.nightpay.dev"
56
67
  export BRIDGE_URL="https://bridge.nightpay.dev"
57
68
  npx nightpay validate
69
+
70
+ ${C.bold}WHAT INIT INSTALLS${C.reset}
71
+ ./skills/nightpay/ Skill files (SKILL.md, scripts, config)
72
+ ./skills/nightpay/sdk/ Python SDK (nightpay_sdk.py)
73
+ ./skills/nightpay/scripts/ Gateway + setup scripts
58
74
  `);
59
75
  process.exit(0);
60
76
  }
@@ -67,7 +83,7 @@ ${C.bold}Available skill:${C.reset}
67
83
  Many funders pool shielded NIGHT → AI agent completes work → ZK receipt
68
84
 
69
85
  ${C.bold}Platforms:${C.reset} OpenClaw, Claude Code, Cursor, GitHub Copilot, ACP, Raw API
70
- ${C.bold}Version:${C.reset} 0.2.4
86
+ ${C.bold}Version:${C.reset} ${VERSION}
71
87
  ${C.bold}License:${C.reset} Apache-2.0
72
88
  `);
73
89
  process.exit(0);
@@ -82,38 +98,106 @@ function detectPlatform() {
82
98
  return "raw";
83
99
  }
84
100
 
85
- // ─── Init (copy files) ──────────────────────────────────────────────────────
101
+ // ─── Copy one file safely ───────────────────────────────────────────────────
102
+ function safeCopy(src, dest, label) {
103
+ if (!existsSync(src)) {
104
+ return { status: "skip", reason: "source not found in package" };
105
+ }
106
+ mkdirSync(dirname(dest), { recursive: true });
107
+ if (existsSync(dest)) {
108
+ // Compare sizes — if same, skip
109
+ try {
110
+ const srcStat = statSync(src);
111
+ const destStat = statSync(dest);
112
+ if (srcStat.size === destStat.size) {
113
+ return { status: "exists", reason: "already up to date" };
114
+ }
115
+ } catch {}
116
+ }
117
+ copyFileSync(src, dest);
118
+ return { status: "copied" };
119
+ }
120
+
121
+ // ─── Init (copy ALL files) ──────────────────────────────────────────────────
86
122
  function init() {
87
123
  const dest = resolve(process.cwd(), "skills", "nightpay");
124
+ const installed = [];
125
+
126
+ console.log(`\n${C.bold}Installing NightPay${C.reset} v${VERSION}\n`);
88
127
 
128
+ // 1. Core skill files (SKILL.md, scripts/gateway.sh, etc.)
129
+ mkdirSync(resolve(process.cwd(), "skills"), { recursive: true });
89
130
  if (existsSync(join(dest, "SKILL.md"))) {
90
- console.log(`${OK} Skill already installed at ${dest}`);
91
- return dest;
131
+ // Update existing re-copy to catch any upstream changes
132
+ cpSync(SKILL_SRC, dest, { recursive: true });
133
+ console.log(` ${OK} Skill files updated at ${C.dim}./skills/nightpay/${C.reset}`);
134
+ installed.push("skills/nightpay/ (updated)");
135
+ } else {
136
+ cpSync(SKILL_SRC, dest, { recursive: true });
137
+ console.log(` ${OK} Skill files installed to ${C.dim}./skills/nightpay/${C.reset}`);
138
+ installed.push("skills/nightpay/");
92
139
  }
93
140
 
94
- mkdirSync(resolve(process.cwd(), "skills"), { recursive: true });
95
- cpSync(SKILL_SRC, dest, { recursive: true });
96
- console.log(`${OK} Installed skill files to ${dest}`);
141
+ // 2. Python SDK ./skills/nightpay/sdk/nightpay_sdk.py
142
+ const sdkDest = join(dest, "sdk", "nightpay_sdk.py");
143
+ const sdkResult = safeCopy(SDK_SRC, sdkDest, "Python SDK");
144
+ if (sdkResult.status === "copied") {
145
+ console.log(` ${OK} Python SDK installed to ${C.dim}./skills/nightpay/sdk/nightpay_sdk.py${C.reset}`);
146
+ installed.push("sdk/nightpay_sdk.py");
147
+ } else if (sdkResult.status === "exists") {
148
+ console.log(` ${OK} Python SDK ${C.dim}(already up to date)${C.reset}`);
149
+ } else {
150
+ console.log(` ${INFO} Python SDK not bundled in this version ${C.dim}(download from GitHub)${C.reset}`);
151
+ }
97
152
 
98
- // Fix permissions on scripts
153
+ // Also copy SDK to project root for direct import convenience
154
+ const sdkRootDest = resolve(process.cwd(), "nightpay_sdk.py");
155
+ const sdkRootResult = safeCopy(SDK_SRC, sdkRootDest, "Python SDK (root)");
156
+ if (sdkRootResult.status === "copied") {
157
+ console.log(` ${OK} Python SDK also at ${C.dim}./nightpay_sdk.py${C.reset} ${C.dim}(for direct import)${C.reset}`);
158
+ }
159
+
160
+ // 3. Setup script → ./skills/nightpay/scripts/setup.sh
161
+ const setupDest = join(dest, "scripts", "setup.sh");
162
+ const setupResult = safeCopy(SETUP_SRC, setupDest, "setup.sh");
163
+ if (setupResult.status === "copied") {
164
+ console.log(` ${OK} Setup script installed to ${C.dim}./skills/nightpay/scripts/setup.sh${C.reset}`);
165
+ installed.push("scripts/setup.sh");
166
+ } else if (setupResult.status === "exists") {
167
+ console.log(` ${OK} Setup script ${C.dim}(already up to date)${C.reset}`);
168
+ } else {
169
+ console.log(` ${INFO} Setup script not bundled in this version`);
170
+ }
171
+
172
+ // 4. Fix permissions on ALL scripts
99
173
  const scriptsDir = join(dest, "scripts");
100
174
  if (existsSync(scriptsDir)) {
175
+ let chmodCount = 0;
101
176
  try {
102
177
  for (const f of readdirSync(scriptsDir)) {
103
178
  if (f.endsWith(".sh")) {
104
179
  chmodSync(join(scriptsDir, f), 0o755);
180
+ chmodCount++;
105
181
  }
106
182
  }
107
- console.log(`${OK} Script permissions fixed`);
183
+ if (chmodCount > 0) {
184
+ console.log(` ${OK} Made ${chmodCount} script(s) executable`);
185
+ }
108
186
  } catch {}
109
187
  }
110
188
 
111
- // Auto-flatten if needed
189
+ // 5. Auto-flatten nested skill directory (common misinstall)
112
190
  const nestedSkill = join(dest, "skills", "nightpay", "SKILL.md");
113
- if (!existsSync(join(dest, "SKILL.md")) && existsSync(nestedSkill)) {
114
- console.log(`${WARN} SKILL.md nested — flattening...`);
191
+ if (existsSync(nestedSkill)) {
192
+ console.log(` ${WARN} Nested skill directory detected — flattening...`);
115
193
  cpSync(join(dest, "skills", "nightpay"), dest, { recursive: true });
116
- console.log(`${OK} Flattened skill directory`);
194
+ console.log(` ${OK} Flattened: ${C.dim}skills/nightpay/skills/nightpay/ → skills/nightpay/${C.reset}`);
195
+ }
196
+
197
+ // 6. Summary
198
+ console.log(`\n${C.bold}Installed ${installed.length} component(s):${C.reset}`);
199
+ for (const item of installed) {
200
+ console.log(` ${C.dim}•${C.reset} ${item}`);
117
201
  }
118
202
 
119
203
  return dest;
@@ -135,13 +219,18 @@ function validate() {
135
219
  }
136
220
  }
137
221
 
138
- // sha256sum or shasum
139
222
  let hasHash = false;
140
223
  try { execSync("which sha256sum", { stdio: "ignore" }); hasHash = true; } catch {}
141
224
  try { execSync("which shasum", { stdio: "ignore" }); hasHash = true; } catch {}
142
225
  if (hasHash) console.log(` ${OK} sha256sum/shasum found`);
143
226
  else { console.log(` ${FAIL} sha256sum/shasum not found`); errors++; }
144
227
 
228
+ // Python check (for SDK)
229
+ let hasPython = false;
230
+ try { execSync("which python3", { stdio: "ignore" }); hasPython = true; } catch {}
231
+ if (hasPython) console.log(` ${OK} python3 found (SDK available)`);
232
+ else console.log(` ${INFO} python3 not found ${C.dim}(optional — needed for Python SDK)${C.reset}`);
233
+
145
234
  console.log(`\n${C.bold}Environment variables${C.reset}`);
146
235
  const required = {
147
236
  MASUMI_API_KEY: "Masumi payment API key",
@@ -170,18 +259,30 @@ function validate() {
170
259
 
171
260
  console.log(`\n${C.bold}Skill files${C.reset}`);
172
261
  const dest = resolve(process.cwd(), "skills", "nightpay");
173
- if (existsSync(join(dest, "SKILL.md"))) {
174
- console.log(` ${OK} SKILL.md found`);
175
- } else {
176
- console.log(` ${FAIL} SKILL.md not found run: npx nightpay init`);
177
- errors++;
262
+
263
+ const fileChecks = [
264
+ { path: join(dest, "SKILL.md"), label: "SKILL.md", required: true },
265
+ { path: join(dest, "scripts", "gateway.sh"), label: "gateway.sh", required: true },
266
+ { path: join(dest, "scripts", "setup.sh"), label: "setup.sh", required: false },
267
+ { path: join(dest, "sdk", "nightpay_sdk.py"), label: "Python SDK (sdk/)", required: false },
268
+ ];
269
+
270
+ for (const check of fileChecks) {
271
+ if (existsSync(check.path)) {
272
+ console.log(` ${OK} ${check.label} found`);
273
+ } else if (check.required) {
274
+ console.log(` ${FAIL} ${check.label} not found — run: ${C.cyan}npx nightpay init${C.reset}`);
275
+ errors++;
276
+ } else {
277
+ console.log(` ${WARN} ${check.label} not found — run: ${C.cyan}npx nightpay init${C.reset} to install`);
278
+ warnings++;
279
+ }
178
280
  }
179
281
 
180
- if (existsSync(join(dest, "scripts", "gateway.sh"))) {
181
- console.log(` ${OK} gateway.sh found`);
182
- } else {
183
- console.log(` ${FAIL} gateway.sh not found`);
184
- errors++;
282
+ // Check for root-level SDK copy too
283
+ const rootSdk = resolve(process.cwd(), "nightpay_sdk.py");
284
+ if (existsSync(rootSdk)) {
285
+ console.log(` ${OK} Python SDK also at ./nightpay_sdk.py`);
185
286
  }
186
287
 
187
288
  console.log(`\n${C.bold}Connectivity${C.reset}`);
@@ -223,21 +324,21 @@ function validate() {
223
324
 
224
325
  // ─── Doctor (diagnose + auto-fix) ────────────────────────────────────────────
225
326
  function doctor() {
226
- console.log(`\n${C.bold}NightPay Doctor${C.reset} — diagnosing and fixing issues...\n`);
327
+ console.log(`\n${C.bold}NightPay Doctor${C.reset} v${VERSION} — diagnosing and fixing issues...\n`);
227
328
  let fixed = 0;
228
329
 
229
330
  const dest = resolve(process.cwd(), "skills", "nightpay");
230
331
 
231
- // Fix 1: Missing skill files
332
+ // Fix 1: Missing skill files → full init
232
333
  if (!existsSync(join(dest, "SKILL.md"))) {
233
- console.log(` ${WARN} Skill not installed — installing now...`);
334
+ console.log(` ${WARN} Skill not installed — running full init...`);
234
335
  init();
235
336
  fixed++;
236
337
  }
237
338
 
238
339
  // Fix 2: Nested SKILL.md
239
340
  const nestedSkill = join(dest, "skills", "nightpay", "SKILL.md");
240
- if (existsSync(nestedSkill) && !existsSync(join(dest, "SKILL.md"))) {
341
+ if (existsSync(nestedSkill)) {
241
342
  console.log(` ${WARN} SKILL.md nested — flattening...`);
242
343
  cpSync(join(dest, "skills", "nightpay"), dest, { recursive: true });
243
344
  console.log(` ${OK} Fixed: flattened skill directory`);
@@ -245,16 +346,47 @@ function doctor() {
245
346
  }
246
347
 
247
348
  // Fix 3: Script permissions
248
- const gateway = join(dest, "scripts", "gateway.sh");
249
- if (existsSync(gateway)) {
250
- try {
251
- chmodSync(gateway, 0o755);
252
- console.log(` ${OK} Fixed: gateway.sh permissions`);
253
- fixed++;
254
- } catch {}
349
+ const scriptsDir = join(dest, "scripts");
350
+ if (existsSync(scriptsDir)) {
351
+ for (const f of readdirSync(scriptsDir)) {
352
+ if (f.endsWith(".sh")) {
353
+ try {
354
+ chmodSync(join(scriptsDir, f), 0o755);
355
+ fixed++;
356
+ } catch {}
357
+ }
358
+ }
359
+ console.log(` ${OK} Fixed: script permissions`);
360
+ }
361
+
362
+ // Fix 4: Missing SDK
363
+ const sdkDest = join(dest, "sdk", "nightpay_sdk.py");
364
+ if (!existsSync(sdkDest) && existsSync(SDK_SRC)) {
365
+ mkdirSync(join(dest, "sdk"), { recursive: true });
366
+ copyFileSync(SDK_SRC, sdkDest);
367
+ console.log(` ${OK} Fixed: installed Python SDK to ${C.dim}sdk/nightpay_sdk.py${C.reset}`);
368
+ fixed++;
369
+ }
370
+
371
+ // Fix 5: Missing setup.sh
372
+ const setupDest = join(dest, "scripts", "setup.sh");
373
+ if (!existsSync(setupDest) && existsSync(SETUP_SRC)) {
374
+ mkdirSync(join(dest, "scripts"), { recursive: true });
375
+ copyFileSync(SETUP_SRC, setupDest);
376
+ chmodSync(setupDest, 0o755);
377
+ console.log(` ${OK} Fixed: installed setup.sh to ${C.dim}scripts/setup.sh${C.reset}`);
378
+ fixed++;
255
379
  }
256
380
 
257
- // Fix 4: Warn about placeholder env vars
381
+ // Fix 6: Root SDK convenience copy
382
+ const rootSdk = resolve(process.cwd(), "nightpay_sdk.py");
383
+ if (!existsSync(rootSdk) && existsSync(SDK_SRC)) {
384
+ copyFileSync(SDK_SRC, rootSdk);
385
+ console.log(` ${OK} Fixed: copied SDK to ${C.dim}./nightpay_sdk.py${C.reset} for direct import`);
386
+ fixed++;
387
+ }
388
+
389
+ // Fix 7: Warn about placeholder env vars
258
390
  const fragment = join(dest, "openclaw-fragment.json");
259
391
  if (existsSync(fragment)) {
260
392
  try {
@@ -278,36 +410,100 @@ function doctor() {
278
410
  // ─── Setup (full onboarding) ─────────────────────────────────────────────────
279
411
  function setup() {
280
412
  const platform = detectPlatform();
281
- console.log(`\n${C.bold}NightPay Agent Onboarding${C.reset} v0.2.4`);
413
+ console.log(`\n${C.bold}NightPay Agent Onboarding${C.reset} v${VERSION}`);
282
414
  console.log(`${C.dim}Anonymous community bounties for AI agents${C.reset}`);
283
415
  console.log(`\n Platform: ${C.bold}${platform}${C.reset}\n`);
284
416
 
285
- // Step 1: Install
417
+ // Step 1: Smart install (all files)
286
418
  const dest = init();
287
419
 
288
420
  // Step 2: Platform-specific config
289
- console.log(`\n${C.bold}Platform setup (${platform})${C.reset}`);
290
-
291
- // Check if bash setup.sh exists and delegate for platform-specific stuff
292
- const setupSh = join(dest, "scripts", "setup.sh");
293
- if (existsSync(setupSh)) {
294
- const result = spawnSync("bash", [setupSh, "--platform", platform, "--validate-only"], {
295
- stdio: "inherit",
296
- env: { ...process.env, NIGHTPAY_WORKSPACE: dest }
297
- });
298
- if (result.status === 0) {
299
- console.log(`\n${C.green}${C.bold}Setup complete!${C.reset}`);
421
+ console.log(`\n${C.bold}Platform config (${platform})${C.reset}`);
422
+
423
+ if (platform === "claude-code") {
424
+ const cmdDir = resolve(process.cwd(), ".claude", "commands");
425
+ const cmdFile = join(cmdDir, "nightpay.md");
426
+ if (!existsSync(cmdFile)) {
427
+ mkdirSync(cmdDir, { recursive: true });
428
+ writeFileSync(cmdFile, [
429
+ "# NightPay",
430
+ "",
431
+ "Use the nightpay skill at ./skills/nightpay/ for bounty operations.",
432
+ "",
433
+ "## Quick commands",
434
+ "- `bash skills/nightpay/scripts/gateway.sh stats` — contract stats",
435
+ "- `bash skills/nightpay/scripts/gateway.sh post-bounty \"<desc>\" <amount>` — post bounty",
436
+ "- `python3 skills/nightpay/sdk/nightpay_sdk.py validate` — health check",
437
+ "- `python3 skills/nightpay/sdk/nightpay_sdk.py doctor --auto-fix` — self-heal",
438
+ "",
439
+ ].join("\n"));
440
+ console.log(` ${OK} Created ${C.dim}.claude/commands/nightpay.md${C.reset}`);
441
+ } else {
442
+ console.log(` ${OK} ${C.dim}.claude/commands/nightpay.md${C.reset} already exists`);
443
+ }
444
+ } else if (platform === "cursor") {
445
+ const rulesDir = resolve(process.cwd(), ".cursor", "rules");
446
+ const rulesFile = join(rulesDir, "nightpay.md");
447
+ if (!existsSync(rulesFile)) {
448
+ mkdirSync(rulesDir, { recursive: true });
449
+ writeFileSync(rulesFile, [
450
+ "# NightPay Skill",
451
+ "",
452
+ "The nightpay skill is at ./skills/nightpay/. Read SKILL.md for capabilities.",
453
+ "Python SDK at ./skills/nightpay/sdk/nightpay_sdk.py or ./nightpay_sdk.py.",
454
+ "",
455
+ "Quick: `bash skills/nightpay/scripts/gateway.sh stats`",
456
+ "",
457
+ ].join("\n"));
458
+ console.log(` ${OK} Created ${C.dim}.cursor/rules/nightpay.md${C.reset}`);
459
+ } else {
460
+ console.log(` ${OK} ${C.dim}.cursor/rules/nightpay.md${C.reset} already exists`);
461
+ }
462
+ } else if (platform === "copilot") {
463
+ const instrFile = resolve(process.cwd(), ".github", "copilot-instructions.md");
464
+ if (existsSync(instrFile)) {
465
+ const content = readFileSync(instrFile, "utf8");
466
+ if (!content.includes("nightpay")) {
467
+ const addition = [
468
+ "",
469
+ "## NightPay",
470
+ "",
471
+ "Bounty skill at ./skills/nightpay/. Read SKILL.md for full capabilities.",
472
+ "Python SDK at ./skills/nightpay/sdk/nightpay_sdk.py.",
473
+ "Gateway: `bash skills/nightpay/scripts/gateway.sh`",
474
+ "",
475
+ ].join("\n");
476
+ writeFileSync(instrFile, content + addition);
477
+ console.log(` ${OK} Appended NightPay section to ${C.dim}.github/copilot-instructions.md${C.reset}`);
478
+ } else {
479
+ console.log(` ${OK} Copilot instructions already mention nightpay`);
480
+ }
481
+ } else {
482
+ console.log(` ${INFO} No .github/copilot-instructions.md — skipping Copilot config`);
300
483
  }
484
+ } else if (platform === "openclaw") {
485
+ console.log(` ${OK} OpenClaw auto-discovers skills from ./skills/nightpay/`);
486
+ console.log(` ${C.dim} Tip: merge openclaw-fragment.json into your openclaw.json${C.reset}`);
301
487
  } else {
302
- // Fallback: just validate
303
- validate();
488
+ console.log(` ${INFO} Raw platform — no config file needed`);
489
+ console.log(` ${C.dim} Use: bash skills/nightpay/scripts/gateway.sh <command>${C.reset}`);
304
490
  }
305
491
 
306
- // Step 3: Next steps
492
+ // Step 3: Run validate
493
+ console.log("");
494
+ const { errors } = validate();
495
+
496
+ // Step 4: Next steps
307
497
  console.log(`\n${C.bold}Next steps${C.reset}`);
308
- console.log(` 1. Set your environment variables (if not already set)`);
309
- console.log(` 2. Run: ${C.cyan}bash skills/nightpay/scripts/gateway.sh stats${C.reset}`);
310
- console.log(` 3. Post your first bounty: ${C.cyan}bash skills/nightpay/scripts/gateway.sh post-bounty "Review this PR" 5000${C.reset}`);
498
+ if (errors > 0) {
499
+ console.log(` 1. Fix the ${errors} error(s) above`);
500
+ console.log(` 2. Run: ${C.cyan}npx nightpay validate${C.reset}`);
501
+ } else {
502
+ console.log(` 1. ${C.cyan}bash skills/nightpay/scripts/gateway.sh stats${C.reset} — check contract`);
503
+ console.log(` 2. ${C.cyan}bash skills/nightpay/scripts/gateway.sh post-bounty "Review this PR" 5000${C.reset}`);
504
+ }
505
+ console.log(`\n ${C.dim}Python SDK:${C.reset} from nightpay_sdk import NightPay; NightPay().stats()`);
506
+ console.log(` ${C.dim}Self-heal:${C.reset} npx nightpay doctor`);
311
507
  console.log("");
312
508
  }
313
509
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nightpay",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "Anonymous community bounties for AI agents. Midnight ZK proofs + Masumi settlement + Cardano finality.",
5
5
  "keywords": [
6
6
  "bounties",