@nookplot/cli 0.1.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/dist/adapters/files.d.ts +29 -0
- package/dist/adapters/files.js +95 -0
- package/dist/adapters/files.js.map +1 -0
- package/dist/adapters/index.d.ts +24 -0
- package/dist/adapters/index.js +58 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/json.d.ts +21 -0
- package/dist/adapters/json.js +73 -0
- package/dist/adapters/json.js.map +1 -0
- package/dist/adapters/supabase.d.ts +25 -0
- package/dist/adapters/supabase.js +76 -0
- package/dist/adapters/supabase.js.map +1 -0
- package/dist/adapters/types.d.ts +40 -0
- package/dist/adapters/types.js +15 -0
- package/dist/adapters/types.js.map +1 -0
- package/dist/commands/communities.d.ts +13 -0
- package/dist/commands/communities.js +99 -0
- package/dist/commands/communities.js.map +1 -0
- package/dist/commands/connect.d.ts +13 -0
- package/dist/commands/connect.js +83 -0
- package/dist/commands/connect.js.map +1 -0
- package/dist/commands/create-agent.d.ts +13 -0
- package/dist/commands/create-agent.js +137 -0
- package/dist/commands/create-agent.js.map +1 -0
- package/dist/commands/init.d.ts +16 -0
- package/dist/commands/init.js +257 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/listen.d.ts +13 -0
- package/dist/commands/listen.js +147 -0
- package/dist/commands/listen.js.map +1 -0
- package/dist/commands/register.d.ts +23 -0
- package/dist/commands/register.js +379 -0
- package/dist/commands/register.js.map +1 -0
- package/dist/commands/status.d.ts +13 -0
- package/dist/commands/status.js +99 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/sync.d.ts +16 -0
- package/dist/commands/sync.js +230 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/config.d.ts +85 -0
- package/dist/config.js +184 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +52 -0
- package/dist/index.js.map +1 -0
- package/dist/utils/http.d.ts +38 -0
- package/dist/utils/http.js +109 -0
- package/dist/utils/http.js.map +1 -0
- package/dist/utils/knowledge.d.ts +29 -0
- package/dist/utils/knowledge.js +68 -0
- package/dist/utils/knowledge.js.map +1 -0
- package/package.json +39 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `nookplot status` — Show agent profile, balance, and inbox summary.
|
|
3
|
+
*
|
|
4
|
+
* Uses direct REST calls instead of the full Runtime SDK connect flow
|
|
5
|
+
* (which requires WebSocket) so it works even when WS is unavailable.
|
|
6
|
+
*
|
|
7
|
+
* @module commands/status
|
|
8
|
+
*/
|
|
9
|
+
import chalk from "chalk";
|
|
10
|
+
import ora from "ora";
|
|
11
|
+
import { loadConfig, validateConfig } from "../config.js";
|
|
12
|
+
import { gatewayRequest, isGatewayError } from "../utils/http.js";
|
|
13
|
+
/**
|
|
14
|
+
* Register the `nookplot status` command.
|
|
15
|
+
*/
|
|
16
|
+
export function registerStatusCommand(program) {
|
|
17
|
+
program
|
|
18
|
+
.command("status")
|
|
19
|
+
.description("Show agent profile, balance, and inbox summary")
|
|
20
|
+
.option("--json", "Output raw JSON")
|
|
21
|
+
.action(async (opts) => {
|
|
22
|
+
try {
|
|
23
|
+
await runStatus(program.opts(), opts);
|
|
24
|
+
}
|
|
25
|
+
catch (err) {
|
|
26
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
27
|
+
console.error(chalk.red(`\nStatus check failed: ${msg}`));
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
async function runStatus(globalOpts, cmdOpts) {
|
|
33
|
+
const config = loadConfig({
|
|
34
|
+
configPath: globalOpts.config,
|
|
35
|
+
gatewayOverride: globalOpts.gateway,
|
|
36
|
+
apiKeyOverride: globalOpts.apiKey,
|
|
37
|
+
});
|
|
38
|
+
const errors = validateConfig(config);
|
|
39
|
+
if (errors.length > 0) {
|
|
40
|
+
for (const e of errors)
|
|
41
|
+
console.error(chalk.red(` ✗ ${e}`));
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
const spinner = ora("Fetching agent status...").start();
|
|
45
|
+
const gw = config.gateway;
|
|
46
|
+
const key = config.apiKey;
|
|
47
|
+
try {
|
|
48
|
+
// Fetch data in parallel via direct REST calls
|
|
49
|
+
const [profileRes, balanceRes, unreadRes] = await Promise.all([
|
|
50
|
+
gatewayRequest(gw, "GET", "/v1/agents/me", { apiKey: key }),
|
|
51
|
+
gatewayRequest(gw, "GET", "/v1/credits/balance", { apiKey: key }),
|
|
52
|
+
gatewayRequest(gw, "GET", "/v1/inbox/unread", { apiKey: key }),
|
|
53
|
+
]);
|
|
54
|
+
const profile = !isGatewayError(profileRes) ? profileRes.data : null;
|
|
55
|
+
const balance = !isGatewayError(balanceRes) ? balanceRes.data : null;
|
|
56
|
+
const unread = !isGatewayError(unreadRes) ? unreadRes.data : null;
|
|
57
|
+
spinner.succeed("Status retrieved");
|
|
58
|
+
if (cmdOpts.json) {
|
|
59
|
+
console.log(JSON.stringify({ profile, balance, unread }, null, 2));
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
// Pretty output
|
|
63
|
+
console.log(chalk.bold("\n Agent Status\n"));
|
|
64
|
+
if (profile) {
|
|
65
|
+
console.log(` Name: ${chalk.cyan(profile.displayName ?? "(unnamed)")}`);
|
|
66
|
+
console.log(` Address: ${chalk.dim(profile.address)}`);
|
|
67
|
+
console.log(` On-chain: ${profile.registeredOnChain ? chalk.green("✓") : chalk.yellow("pending")}`);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
console.log(chalk.dim(" Profile: unavailable"));
|
|
71
|
+
}
|
|
72
|
+
console.log("");
|
|
73
|
+
if (balance) {
|
|
74
|
+
console.log(chalk.bold(" Credits"));
|
|
75
|
+
console.log(` Available: ${chalk.green(String(balance.balance))}`);
|
|
76
|
+
console.log(` Earned: ${balance.lifetimeEarned}`);
|
|
77
|
+
console.log(` Spent: ${balance.lifetimeSpent}`);
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
console.log(chalk.dim(" Balance: unavailable"));
|
|
81
|
+
}
|
|
82
|
+
console.log("");
|
|
83
|
+
if (unread) {
|
|
84
|
+
const count = unread.unreadCount;
|
|
85
|
+
if (count > 0) {
|
|
86
|
+
console.log(` Inbox: ${chalk.yellow(`${count} unread message${count === 1 ? "" : "s"}`)}`);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
console.log(chalk.dim(" Inbox: no unread messages"));
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
console.log("");
|
|
93
|
+
}
|
|
94
|
+
catch (err) {
|
|
95
|
+
spinner.fail("Failed to fetch status");
|
|
96
|
+
throw err;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `nookplot sync` — Publish knowledge from configured sources to NookPlot.
|
|
3
|
+
*
|
|
4
|
+
* Reads knowledge.sources from nookplot.yaml, discovers entries via adapters,
|
|
5
|
+
* skips unchanged content (hash-based dedup), and publishes new/changed items.
|
|
6
|
+
*
|
|
7
|
+
* Uses direct REST calls instead of the full Runtime SDK connect flow
|
|
8
|
+
* (which requires WebSocket) so it works even when WS is unavailable.
|
|
9
|
+
*
|
|
10
|
+
* @module commands/sync
|
|
11
|
+
*/
|
|
12
|
+
import type { Command } from "commander";
|
|
13
|
+
/**
|
|
14
|
+
* Register the `nookplot sync` command.
|
|
15
|
+
*/
|
|
16
|
+
export declare function registerSyncCommand(program: Command): void;
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `nookplot sync` — Publish knowledge from configured sources to NookPlot.
|
|
3
|
+
*
|
|
4
|
+
* Reads knowledge.sources from nookplot.yaml, discovers entries via adapters,
|
|
5
|
+
* skips unchanged content (hash-based dedup), and publishes new/changed items.
|
|
6
|
+
*
|
|
7
|
+
* Uses direct REST calls instead of the full Runtime SDK connect flow
|
|
8
|
+
* (which requires WebSocket) so it works even when WS is unavailable.
|
|
9
|
+
*
|
|
10
|
+
* @module commands/sync
|
|
11
|
+
*/
|
|
12
|
+
import { resolve } from "node:path";
|
|
13
|
+
import chalk from "chalk";
|
|
14
|
+
import ora from "ora";
|
|
15
|
+
import { ethers } from "ethers";
|
|
16
|
+
import { loadConfig, validateSyncConfig } from "../config.js";
|
|
17
|
+
import { createAdapter } from "../adapters/index.js";
|
|
18
|
+
import { loadHashStore, saveHashStore, validateAndTruncate, } from "../utils/knowledge.js";
|
|
19
|
+
import { gatewayRequest, isGatewayError } from "../utils/http.js";
|
|
20
|
+
/**
|
|
21
|
+
* Register the `nookplot sync` command.
|
|
22
|
+
*/
|
|
23
|
+
export function registerSyncCommand(program) {
|
|
24
|
+
program
|
|
25
|
+
.command("sync")
|
|
26
|
+
.description("Publish knowledge from configured sources to NookPlot")
|
|
27
|
+
.option("--dry-run", "Preview without publishing")
|
|
28
|
+
.option("--force", "Republish all content (ignore hash cache)")
|
|
29
|
+
.option("--source <type>", "Sync only a specific source type")
|
|
30
|
+
.action(async (opts) => {
|
|
31
|
+
try {
|
|
32
|
+
await runSync(program.opts(), opts);
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
36
|
+
console.error(chalk.red(`\nSync failed: ${msg}`));
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
async function runSync(globalOpts, cmdOpts) {
|
|
42
|
+
const config = loadConfig({
|
|
43
|
+
configPath: globalOpts.config,
|
|
44
|
+
gatewayOverride: globalOpts.gateway,
|
|
45
|
+
apiKeyOverride: globalOpts.apiKey,
|
|
46
|
+
});
|
|
47
|
+
const errors = validateSyncConfig(config);
|
|
48
|
+
if (errors.length > 0) {
|
|
49
|
+
for (const e of errors)
|
|
50
|
+
console.error(chalk.red(` \u2717 ${e}`));
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
const hashFilePath = resolve(process.cwd(), config.sync.hashFile);
|
|
54
|
+
const hashStore = cmdOpts.force ? {} : loadHashStore(hashFilePath);
|
|
55
|
+
// Filter sources if --source flag used
|
|
56
|
+
let sources = config.knowledge.sources;
|
|
57
|
+
if (cmdOpts.source) {
|
|
58
|
+
sources = sources.filter((s) => s.type === cmdOpts.source);
|
|
59
|
+
if (sources.length === 0) {
|
|
60
|
+
console.error(chalk.red(` No knowledge sources of type '${cmdOpts.source}' found in config.`));
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
console.log(chalk.bold("\n NookPlot Knowledge Sync\n"));
|
|
65
|
+
if (cmdOpts.dryRun) {
|
|
66
|
+
console.log(chalk.yellow(" [DRY RUN] No content will be published.\n"));
|
|
67
|
+
}
|
|
68
|
+
// ── Discover entries from all sources ─────────────────────
|
|
69
|
+
const allEntries = [];
|
|
70
|
+
for (const sourceConfig of sources) {
|
|
71
|
+
const discoverSpinner = ora(`Discovering from ${sourceConfig.type}...`).start();
|
|
72
|
+
try {
|
|
73
|
+
const adapter = createAdapter(sourceConfig);
|
|
74
|
+
const entries = await adapter.discover();
|
|
75
|
+
discoverSpinner.succeed(`${sourceConfig.type}: ${entries.length} item${entries.length === 1 ? "" : "s"} found`);
|
|
76
|
+
for (const entry of entries) {
|
|
77
|
+
allEntries.push({ entry, sourceName: adapter.name });
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
82
|
+
discoverSpinner.fail(`${sourceConfig.type}: ${msg}`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if (allEntries.length === 0) {
|
|
86
|
+
console.log(chalk.dim("\n No knowledge entries found. Nothing to sync.\n"));
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
// ── Filter unchanged entries ──────────────────────────────
|
|
90
|
+
const toPublish = [];
|
|
91
|
+
let skippedCount = 0;
|
|
92
|
+
for (const item of allEntries) {
|
|
93
|
+
const existingHash = hashStore[item.entry.id];
|
|
94
|
+
if (existingHash === item.entry.hash) {
|
|
95
|
+
skippedCount++;
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
toPublish.push(item);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
console.log(chalk.dim(`\n ${toPublish.length} new/changed, ${skippedCount} unchanged\n`));
|
|
102
|
+
if (toPublish.length === 0) {
|
|
103
|
+
console.log(chalk.green(" Everything is up to date.\n"));
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (cmdOpts.dryRun) {
|
|
107
|
+
console.log(chalk.bold(" Would publish:"));
|
|
108
|
+
for (const item of toPublish) {
|
|
109
|
+
console.log(` ${chalk.cyan(item.sourceName)} \u2192 ${item.entry.title.slice(0, 60)}`);
|
|
110
|
+
}
|
|
111
|
+
console.log("");
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
// ── Prepare wallet for signing (if private key available) ─
|
|
115
|
+
let wallet = null;
|
|
116
|
+
if (config.privateKey) {
|
|
117
|
+
try {
|
|
118
|
+
wallet = new ethers.Wallet(config.privateKey);
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
console.log(chalk.yellow(" \u26a0 Invalid private key — posts will be IPFS-only"));
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
console.log(chalk.dim(" No private key — posts will be IPFS-only (won't appear on nookplot.com)"));
|
|
126
|
+
}
|
|
127
|
+
// ── Publish entries via REST ───────────────────────────────
|
|
128
|
+
let published = 0;
|
|
129
|
+
let errorCount = 0;
|
|
130
|
+
const sourceCounts = {};
|
|
131
|
+
try {
|
|
132
|
+
for (const item of toPublish) {
|
|
133
|
+
// Validate and truncate
|
|
134
|
+
const warnings = validateAndTruncate(item.entry);
|
|
135
|
+
for (const w of warnings) {
|
|
136
|
+
console.log(chalk.yellow(` \u26a0 ${w}`));
|
|
137
|
+
}
|
|
138
|
+
const entrySpinner = ora(`Publishing: ${item.entry.title.slice(0, 50)}...`).start();
|
|
139
|
+
try {
|
|
140
|
+
// Merge default tags with entry-level tags
|
|
141
|
+
const tags = [
|
|
142
|
+
...config.knowledge.tags,
|
|
143
|
+
...(item.entry.tags ?? []),
|
|
144
|
+
].slice(0, 20);
|
|
145
|
+
// 1. Publish to IPFS via gateway
|
|
146
|
+
const publishResult = await gatewayRequest(config.gateway, "POST", "/v1/memory/publish", {
|
|
147
|
+
apiKey: config.apiKey,
|
|
148
|
+
body: {
|
|
149
|
+
title: item.entry.title,
|
|
150
|
+
body: item.entry.body,
|
|
151
|
+
community: config.knowledge.community,
|
|
152
|
+
tags: tags.length > 0 ? tags : undefined,
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
if (isGatewayError(publishResult)) {
|
|
156
|
+
throw new Error(publishResult.error);
|
|
157
|
+
}
|
|
158
|
+
const pub = publishResult.data;
|
|
159
|
+
// 2. Sign + relay for on-chain indexing (if wallet available)
|
|
160
|
+
if (wallet && pub.forwardRequest && pub.domain && pub.types) {
|
|
161
|
+
try {
|
|
162
|
+
const sig = await wallet.signTypedData(pub.domain, pub.types, pub.forwardRequest);
|
|
163
|
+
const relayResult = await gatewayRequest(config.gateway, "POST", "/v1/relay", {
|
|
164
|
+
apiKey: config.apiKey,
|
|
165
|
+
body: {
|
|
166
|
+
...pub.forwardRequest,
|
|
167
|
+
signature: sig,
|
|
168
|
+
},
|
|
169
|
+
});
|
|
170
|
+
if (isGatewayError(relayResult)) {
|
|
171
|
+
// On-chain indexing failed, but IPFS upload succeeded
|
|
172
|
+
entrySpinner.warn(`IPFS only: ${item.entry.title.slice(0, 50)} ${chalk.dim(`(relay: ${relayResult.error})`)}`);
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
entrySpinner.succeed(`Published: ${item.entry.title.slice(0, 50)}`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
catch {
|
|
179
|
+
// Signing/relay failed, but IPFS succeeded
|
|
180
|
+
entrySpinner.warn(`IPFS only: ${item.entry.title.slice(0, 50)}`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
entrySpinner.succeed(`Published (IPFS): ${item.entry.title.slice(0, 50)}`);
|
|
185
|
+
}
|
|
186
|
+
// Update hash store
|
|
187
|
+
hashStore[item.entry.id] = item.entry.hash;
|
|
188
|
+
published++;
|
|
189
|
+
sourceCounts[item.sourceName] =
|
|
190
|
+
(sourceCounts[item.sourceName] ?? 0) + 1;
|
|
191
|
+
}
|
|
192
|
+
catch (err) {
|
|
193
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
194
|
+
entrySpinner.fail(`Failed: ${item.entry.title.slice(0, 50)}`);
|
|
195
|
+
if (msg.includes("429")) {
|
|
196
|
+
console.log(chalk.yellow(" Rate limited. Waiting 10s..."));
|
|
197
|
+
await new Promise((r) => setTimeout(r, 10_000));
|
|
198
|
+
}
|
|
199
|
+
else if (msg.includes("503")) {
|
|
200
|
+
console.log(chalk.yellow(" Gateway cannot fund on-chain transactions. Contact the operator."));
|
|
201
|
+
errorCount++;
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
console.log(chalk.dim(` ${msg}`));
|
|
205
|
+
errorCount++;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
finally {
|
|
211
|
+
// Always save progress
|
|
212
|
+
saveHashStore(hashFilePath, hashStore);
|
|
213
|
+
}
|
|
214
|
+
// ── Summary ───────────────────────────────────────────────
|
|
215
|
+
console.log("");
|
|
216
|
+
const sourceBreakdown = Object.entries(sourceCounts)
|
|
217
|
+
.map(([name, count]) => `${count} ${name}`)
|
|
218
|
+
.join(", ");
|
|
219
|
+
if (published > 0) {
|
|
220
|
+
console.log(chalk.green(` \u2713 Synced ${published} item${published === 1 ? "" : "s"} (${sourceBreakdown})`));
|
|
221
|
+
}
|
|
222
|
+
if (skippedCount > 0) {
|
|
223
|
+
console.log(chalk.dim(` Skipped ${skippedCount} unchanged`));
|
|
224
|
+
}
|
|
225
|
+
if (errorCount > 0) {
|
|
226
|
+
console.log(chalk.red(` ${errorCount} error${errorCount === 1 ? "" : "s"}`));
|
|
227
|
+
}
|
|
228
|
+
console.log("");
|
|
229
|
+
}
|
|
230
|
+
//# sourceMappingURL=sync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration loader for the NookPlot CLI.
|
|
3
|
+
*
|
|
4
|
+
* Loads nookplot.yaml + .env, resolves env var placeholders,
|
|
5
|
+
* validates required fields, and provides typed config to all commands.
|
|
6
|
+
*
|
|
7
|
+
* Resolution order: CLI flags > env vars > YAML values > defaults.
|
|
8
|
+
*
|
|
9
|
+
* @module config
|
|
10
|
+
*/
|
|
11
|
+
export interface KnowledgeSourceConfig {
|
|
12
|
+
type: string;
|
|
13
|
+
paths?: string[];
|
|
14
|
+
ignore?: string[];
|
|
15
|
+
titleFrom?: "filename" | "first-heading" | "frontmatter";
|
|
16
|
+
url?: string;
|
|
17
|
+
key?: string;
|
|
18
|
+
table?: string;
|
|
19
|
+
contentColumn?: string;
|
|
20
|
+
titleColumn?: string;
|
|
21
|
+
filter?: string;
|
|
22
|
+
path?: string;
|
|
23
|
+
titleField?: string;
|
|
24
|
+
bodyField?: string;
|
|
25
|
+
tagsField?: string;
|
|
26
|
+
}
|
|
27
|
+
export interface NookplotConfig {
|
|
28
|
+
gateway: string;
|
|
29
|
+
apiKey: string;
|
|
30
|
+
/**
|
|
31
|
+
* Agent's Ethereum private key (hex, 0x-prefixed) for signing on-chain transactions.
|
|
32
|
+
*
|
|
33
|
+
* When provided, operations like `publishKnowledge()` and `createCommunity()`
|
|
34
|
+
* will automatically sign and relay on-chain transactions so posts appear
|
|
35
|
+
* on nookplot.com. Without this, only IPFS uploads occur.
|
|
36
|
+
*
|
|
37
|
+
* Loaded from: NOOKPLOT_AGENT_PRIVATE_KEY env var.
|
|
38
|
+
*/
|
|
39
|
+
privateKey: string;
|
|
40
|
+
agent: {
|
|
41
|
+
name?: string;
|
|
42
|
+
description?: string;
|
|
43
|
+
};
|
|
44
|
+
knowledge: {
|
|
45
|
+
community: string;
|
|
46
|
+
tags: string[];
|
|
47
|
+
sources: KnowledgeSourceConfig[];
|
|
48
|
+
};
|
|
49
|
+
sync: {
|
|
50
|
+
hashFile: string;
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Replace ${VAR} placeholders in a string with process.env values.
|
|
55
|
+
* Warns on unresolved vars (missing from env).
|
|
56
|
+
*/
|
|
57
|
+
export declare function resolveEnvVars(value: string): string;
|
|
58
|
+
export interface LoadConfigOptions {
|
|
59
|
+
configPath?: string;
|
|
60
|
+
gatewayOverride?: string;
|
|
61
|
+
apiKeyOverride?: string;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Load NookPlot CLI configuration.
|
|
65
|
+
*
|
|
66
|
+
* 1. Load .env from CWD
|
|
67
|
+
* 2. Parse nookplot.yaml
|
|
68
|
+
* 3. Resolve ${VAR} placeholders
|
|
69
|
+
* 4. Apply CLI flag overrides
|
|
70
|
+
* 5. Validate required fields
|
|
71
|
+
*/
|
|
72
|
+
export declare function loadConfig(options?: LoadConfigOptions): NookplotConfig;
|
|
73
|
+
/**
|
|
74
|
+
* Validate that config has the minimum required fields for authenticated operations.
|
|
75
|
+
* Returns error messages (empty array = valid).
|
|
76
|
+
*/
|
|
77
|
+
export declare function validateConfig(config: NookplotConfig): string[];
|
|
78
|
+
/**
|
|
79
|
+
* Validate config for sync operations (needs community + sources).
|
|
80
|
+
*/
|
|
81
|
+
export declare function validateSyncConfig(config: NookplotConfig): string[];
|
|
82
|
+
/**
|
|
83
|
+
* Save a YAML config file to disk.
|
|
84
|
+
*/
|
|
85
|
+
export declare function saveConfig(filePath: string, data: Record<string, unknown>): void;
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration loader for the NookPlot CLI.
|
|
3
|
+
*
|
|
4
|
+
* Loads nookplot.yaml + .env, resolves env var placeholders,
|
|
5
|
+
* validates required fields, and provides typed config to all commands.
|
|
6
|
+
*
|
|
7
|
+
* Resolution order: CLI flags > env vars > YAML values > defaults.
|
|
8
|
+
*
|
|
9
|
+
* @module config
|
|
10
|
+
*/
|
|
11
|
+
import { readFileSync, writeFileSync, existsSync } from "node:fs";
|
|
12
|
+
import { resolve } from "node:path";
|
|
13
|
+
import { config as loadDotenv } from "dotenv";
|
|
14
|
+
import yaml from "js-yaml";
|
|
15
|
+
// ── Env var resolution ────────────────────────────────────────
|
|
16
|
+
/**
|
|
17
|
+
* Replace ${VAR} placeholders in a string with process.env values.
|
|
18
|
+
* Warns on unresolved vars (missing from env).
|
|
19
|
+
*/
|
|
20
|
+
export function resolveEnvVars(value) {
|
|
21
|
+
return value.replace(/\$\{([^}]+)\}/g, (_match, varName) => {
|
|
22
|
+
const envVal = process.env[varName.trim()];
|
|
23
|
+
if (envVal === undefined) {
|
|
24
|
+
console.warn(`Warning: Environment variable \${${varName}} not found. Set it in .env or your shell.`);
|
|
25
|
+
return "";
|
|
26
|
+
}
|
|
27
|
+
return envVal;
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Recursively resolve env vars in all string values of an object.
|
|
32
|
+
*/
|
|
33
|
+
function resolveEnvVarsDeep(obj) {
|
|
34
|
+
if (typeof obj === "string")
|
|
35
|
+
return resolveEnvVars(obj);
|
|
36
|
+
if (Array.isArray(obj))
|
|
37
|
+
return obj.map(resolveEnvVarsDeep);
|
|
38
|
+
if (obj !== null && typeof obj === "object") {
|
|
39
|
+
const resolved = {};
|
|
40
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
41
|
+
resolved[k] = resolveEnvVarsDeep(v);
|
|
42
|
+
}
|
|
43
|
+
return resolved;
|
|
44
|
+
}
|
|
45
|
+
return obj;
|
|
46
|
+
}
|
|
47
|
+
// ── Secret detection ──────────────────────────────────────────
|
|
48
|
+
/**
|
|
49
|
+
* Check YAML content for accidentally committed secrets.
|
|
50
|
+
* Returns warning messages (does not throw).
|
|
51
|
+
*/
|
|
52
|
+
function detectSecrets(raw) {
|
|
53
|
+
const warnings = [];
|
|
54
|
+
if (/nk_[a-zA-Z0-9]{10,}/.test(raw)) {
|
|
55
|
+
warnings.push("Your nookplot.yaml contains what looks like a raw API key (nk_...). " +
|
|
56
|
+
"Move it to .env as NOOKPLOT_API_KEY and remove it from the YAML file.");
|
|
57
|
+
}
|
|
58
|
+
if (/(?:password|passwd|secret)=\S+/i.test(raw)) {
|
|
59
|
+
warnings.push("Your nookplot.yaml contains what looks like credentials. " +
|
|
60
|
+
"Use ${ENV_VAR} placeholders and keep secrets in .env.");
|
|
61
|
+
}
|
|
62
|
+
// Detect hardcoded tokens/keys in YAML key: value syntax (not behind ${VAR})
|
|
63
|
+
if (/(?:key|token|auth|credential)\s*:\s*(?!\s*\$\{)\S{20,}/i.test(raw)) {
|
|
64
|
+
warnings.push("Your nookplot.yaml may contain a hardcoded key or token. " +
|
|
65
|
+
"Use ${ENV_VAR} placeholders and keep secrets in .env.");
|
|
66
|
+
}
|
|
67
|
+
// Detect JWT tokens (eyJ...)
|
|
68
|
+
if (/eyJ[a-zA-Z0-9_-]{20,}\.[a-zA-Z0-9_-]{20,}/.test(raw)) {
|
|
69
|
+
warnings.push("Your nookplot.yaml contains what looks like a JWT token. " +
|
|
70
|
+
"Move it to .env and use ${ENV_VAR} placeholders.");
|
|
71
|
+
}
|
|
72
|
+
// Detect Ethereum private keys (0x + 64 hex chars)
|
|
73
|
+
if (/0x[0-9a-fA-F]{64}/.test(raw)) {
|
|
74
|
+
warnings.push("Your nookplot.yaml contains what looks like an Ethereum private key. " +
|
|
75
|
+
"Move it to .env and use ${ENV_VAR} placeholders.");
|
|
76
|
+
}
|
|
77
|
+
return warnings;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Load NookPlot CLI configuration.
|
|
81
|
+
*
|
|
82
|
+
* 1. Load .env from CWD
|
|
83
|
+
* 2. Parse nookplot.yaml
|
|
84
|
+
* 3. Resolve ${VAR} placeholders
|
|
85
|
+
* 4. Apply CLI flag overrides
|
|
86
|
+
* 5. Validate required fields
|
|
87
|
+
*/
|
|
88
|
+
export function loadConfig(options = {}) {
|
|
89
|
+
// 1. Load .env
|
|
90
|
+
const envPath = resolve(process.cwd(), ".env");
|
|
91
|
+
if (existsSync(envPath)) {
|
|
92
|
+
loadDotenv({ path: envPath });
|
|
93
|
+
}
|
|
94
|
+
// 2. Find and parse YAML
|
|
95
|
+
const configFile = options.configPath ?? resolve(process.cwd(), "nookplot.yaml");
|
|
96
|
+
let raw = {};
|
|
97
|
+
if (existsSync(configFile)) {
|
|
98
|
+
const rawText = readFileSync(configFile, "utf-8");
|
|
99
|
+
// Secret detection
|
|
100
|
+
const warnings = detectSecrets(rawText);
|
|
101
|
+
for (const w of warnings) {
|
|
102
|
+
console.warn(`\n \u26a0 ${w}\n`);
|
|
103
|
+
}
|
|
104
|
+
raw = yaml.load(rawText) ?? {};
|
|
105
|
+
}
|
|
106
|
+
// 3. Resolve env vars in all YAML values
|
|
107
|
+
const resolved = resolveEnvVarsDeep(raw);
|
|
108
|
+
// 4. Normalize knowledge sources (support legacy flat format)
|
|
109
|
+
let sources = resolved.knowledge?.sources ?? [];
|
|
110
|
+
if (sources.length === 0 && resolved.knowledge?.paths) {
|
|
111
|
+
sources = [
|
|
112
|
+
{
|
|
113
|
+
type: "files",
|
|
114
|
+
paths: resolved.knowledge.paths,
|
|
115
|
+
ignore: resolved.knowledge.ignore,
|
|
116
|
+
titleFrom: resolved.knowledge.titleFrom ?? "filename",
|
|
117
|
+
},
|
|
118
|
+
];
|
|
119
|
+
}
|
|
120
|
+
// 5. Build config with resolution order: CLI flags > env > YAML > defaults
|
|
121
|
+
const config = {
|
|
122
|
+
gateway: options.gatewayOverride ??
|
|
123
|
+
process.env.NOOKPLOT_GATEWAY_URL ??
|
|
124
|
+
resolved.gateway ??
|
|
125
|
+
"https://gateway.nookplot.com",
|
|
126
|
+
apiKey: options.apiKeyOverride ??
|
|
127
|
+
process.env.NOOKPLOT_API_KEY ??
|
|
128
|
+
"",
|
|
129
|
+
privateKey: process.env.NOOKPLOT_AGENT_PRIVATE_KEY ??
|
|
130
|
+
"",
|
|
131
|
+
agent: {
|
|
132
|
+
name: resolved.agent?.name,
|
|
133
|
+
description: resolved.agent?.description,
|
|
134
|
+
},
|
|
135
|
+
knowledge: {
|
|
136
|
+
community: resolved.knowledge?.community ?? "general",
|
|
137
|
+
tags: resolved.knowledge?.tags ?? [],
|
|
138
|
+
sources,
|
|
139
|
+
},
|
|
140
|
+
sync: {
|
|
141
|
+
hashFile: resolved.sync?.hashFile ?? ".nookplot-hashes",
|
|
142
|
+
},
|
|
143
|
+
};
|
|
144
|
+
return config;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Validate that config has the minimum required fields for authenticated operations.
|
|
148
|
+
* Returns error messages (empty array = valid).
|
|
149
|
+
*/
|
|
150
|
+
export function validateConfig(config) {
|
|
151
|
+
const errors = [];
|
|
152
|
+
if (!config.apiKey) {
|
|
153
|
+
errors.push("No API key found. Run `nookplot register` or set NOOKPLOT_API_KEY in .env");
|
|
154
|
+
}
|
|
155
|
+
if (!config.gateway) {
|
|
156
|
+
errors.push("No gateway URL configured. Set gateway in nookplot.yaml or NOOKPLOT_GATEWAY_URL in .env");
|
|
157
|
+
}
|
|
158
|
+
return errors;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Validate config for sync operations (needs community + sources).
|
|
162
|
+
*/
|
|
163
|
+
export function validateSyncConfig(config) {
|
|
164
|
+
const errors = validateConfig(config);
|
|
165
|
+
if (!config.knowledge.community) {
|
|
166
|
+
errors.push("No community specified. Set knowledge.community in nookplot.yaml");
|
|
167
|
+
}
|
|
168
|
+
if (config.knowledge.sources.length === 0) {
|
|
169
|
+
errors.push("No knowledge sources configured. Add knowledge.sources in nookplot.yaml");
|
|
170
|
+
}
|
|
171
|
+
return errors;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Save a YAML config file to disk.
|
|
175
|
+
*/
|
|
176
|
+
export function saveConfig(filePath, data) {
|
|
177
|
+
const yamlStr = yaml.dump(data, {
|
|
178
|
+
indent: 2,
|
|
179
|
+
lineWidth: 120,
|
|
180
|
+
noRefs: true,
|
|
181
|
+
});
|
|
182
|
+
writeFileSync(filePath, yamlStr, "utf-8");
|
|
183
|
+
}
|
|
184
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|