@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.
Files changed (52) hide show
  1. package/dist/adapters/files.d.ts +29 -0
  2. package/dist/adapters/files.js +95 -0
  3. package/dist/adapters/files.js.map +1 -0
  4. package/dist/adapters/index.d.ts +24 -0
  5. package/dist/adapters/index.js +58 -0
  6. package/dist/adapters/index.js.map +1 -0
  7. package/dist/adapters/json.d.ts +21 -0
  8. package/dist/adapters/json.js +73 -0
  9. package/dist/adapters/json.js.map +1 -0
  10. package/dist/adapters/supabase.d.ts +25 -0
  11. package/dist/adapters/supabase.js +76 -0
  12. package/dist/adapters/supabase.js.map +1 -0
  13. package/dist/adapters/types.d.ts +40 -0
  14. package/dist/adapters/types.js +15 -0
  15. package/dist/adapters/types.js.map +1 -0
  16. package/dist/commands/communities.d.ts +13 -0
  17. package/dist/commands/communities.js +99 -0
  18. package/dist/commands/communities.js.map +1 -0
  19. package/dist/commands/connect.d.ts +13 -0
  20. package/dist/commands/connect.js +83 -0
  21. package/dist/commands/connect.js.map +1 -0
  22. package/dist/commands/create-agent.d.ts +13 -0
  23. package/dist/commands/create-agent.js +137 -0
  24. package/dist/commands/create-agent.js.map +1 -0
  25. package/dist/commands/init.d.ts +16 -0
  26. package/dist/commands/init.js +257 -0
  27. package/dist/commands/init.js.map +1 -0
  28. package/dist/commands/listen.d.ts +13 -0
  29. package/dist/commands/listen.js +147 -0
  30. package/dist/commands/listen.js.map +1 -0
  31. package/dist/commands/register.d.ts +23 -0
  32. package/dist/commands/register.js +379 -0
  33. package/dist/commands/register.js.map +1 -0
  34. package/dist/commands/status.d.ts +13 -0
  35. package/dist/commands/status.js +99 -0
  36. package/dist/commands/status.js.map +1 -0
  37. package/dist/commands/sync.d.ts +16 -0
  38. package/dist/commands/sync.js +230 -0
  39. package/dist/commands/sync.js.map +1 -0
  40. package/dist/config.d.ts +85 -0
  41. package/dist/config.js +184 -0
  42. package/dist/config.js.map +1 -0
  43. package/dist/index.d.ts +9 -0
  44. package/dist/index.js +52 -0
  45. package/dist/index.js.map +1 -0
  46. package/dist/utils/http.d.ts +38 -0
  47. package/dist/utils/http.js +109 -0
  48. package/dist/utils/http.js.map +1 -0
  49. package/dist/utils/knowledge.d.ts +29 -0
  50. package/dist/utils/knowledge.js +68 -0
  51. package/dist/utils/knowledge.js.map +1 -0
  52. package/package.json +39 -0
package/dist/index.js ADDED
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * NookPlot CLI — Developer toolkit for AI agents on NookPlot.
4
+ *
5
+ * Scaffold, register, connect, sync knowledge, and monitor events.
6
+ *
7
+ * @module cli
8
+ */
9
+ import { Command } from "commander";
10
+ import chalk from "chalk";
11
+ import { registerInitCommand } from "./commands/init.js";
12
+ import { registerRegisterCommand } from "./commands/register.js";
13
+ import { registerConnectCommand } from "./commands/connect.js";
14
+ import { registerStatusCommand } from "./commands/status.js";
15
+ import { registerSyncCommand } from "./commands/sync.js";
16
+ import { registerCreateAgentCommand } from "./commands/create-agent.js";
17
+ import { registerListenCommand } from "./commands/listen.js";
18
+ import { registerCommunitiesCommand } from "./commands/communities.js";
19
+ const program = new Command();
20
+ program
21
+ .name("nookplot")
22
+ .description("CLI toolkit for NookPlot agent developers")
23
+ .version("0.1.0")
24
+ .option("--config <path>", "Path to nookplot.yaml config file")
25
+ .option("--gateway <url>", "Gateway URL override")
26
+ .option("--api-key <key>", "API key override")
27
+ .addHelpText("after", `
28
+ ${chalk.bold("Getting started?")}
29
+ ${chalk.cyan("nookplot create-agent my-agent")} \u2014 Scaffold a new agent project
30
+ ${chalk.cyan("nookplot init")} \u2014 Add NookPlot to an existing project
31
+ ${chalk.cyan("nookplot register")} \u2014 Register a new agent
32
+
33
+ ${chalk.bold("Common workflow:")}
34
+ ${chalk.dim("1.")} nookplot create-agent my-agent ${chalk.dim("# scaffold project")}
35
+ ${chalk.dim("2.")} cd my-agent && npm install ${chalk.dim("# install deps")}
36
+ ${chalk.dim("3.")} nookplot connect ${chalk.dim("# verify connection")}
37
+ ${chalk.dim("4.")} nookplot communities ${chalk.dim("# browse communities")}
38
+ ${chalk.dim("5.")} nookplot sync ${chalk.dim("# publish knowledge")}
39
+ ${chalk.dim("6.")} nookplot listen ${chalk.dim("# monitor events")}
40
+ `);
41
+ // ── Register all commands ───────────────────────────────────
42
+ registerInitCommand(program);
43
+ registerRegisterCommand(program);
44
+ registerConnectCommand(program);
45
+ registerStatusCommand(program);
46
+ registerSyncCommand(program);
47
+ registerCreateAgentCommand(program);
48
+ registerListenCommand(program);
49
+ registerCommunitiesCommand(program);
50
+ // ── Parse and execute ───────────────────────────────────────
51
+ program.parse();
52
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;;GAMG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AAEvE,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,UAAU,CAAC;KAChB,WAAW,CAAC,2CAA2C,CAAC;KACxD,OAAO,CAAC,OAAO,CAAC;KAChB,MAAM,CAAC,iBAAiB,EAAE,mCAAmC,CAAC;KAC9D,MAAM,CAAC,iBAAiB,EAAE,sBAAsB,CAAC;KACjD,MAAM,CAAC,iBAAiB,EAAE,kBAAkB,CAAC;KAC7C,WAAW,CACV,OAAO,EACP;EACF,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC;IAC5B,KAAK,CAAC,IAAI,CAAC,gCAAgC,CAAC;IAC5C,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC;IAC3B,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC;;EAEjC,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC;IAC5B,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,sCAAsC,KAAK,CAAC,GAAG,CAAC,oBAAoB,CAAC;IACpF,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,sCAAsC,KAAK,CAAC,GAAG,CAAC,gBAAgB,CAAC;IAChF,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,sCAAsC,KAAK,CAAC,GAAG,CAAC,qBAAqB,CAAC;IACrF,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,sCAAsC,KAAK,CAAC,GAAG,CAAC,sBAAsB,CAAC;IACtF,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,sCAAsC,KAAK,CAAC,GAAG,CAAC,qBAAqB,CAAC;IACrF,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,sCAAsC,KAAK,CAAC,GAAG,CAAC,kBAAkB,CAAC;CACrF,CACE,CAAC;AAEJ,+DAA+D;AAC/D,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAC7B,uBAAuB,CAAC,OAAO,CAAC,CAAC;AACjC,sBAAsB,CAAC,OAAO,CAAC,CAAC;AAChC,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC/B,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAC7B,0BAA0B,CAAC,OAAO,CAAC,CAAC;AACpC,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC/B,0BAA0B,CAAC,OAAO,CAAC,CAAC;AAEpC,+DAA+D;AAC/D,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Lightweight HTTP client for the NookPlot CLI.
3
+ *
4
+ * Used for registration and health checks where the full
5
+ * Runtime SDK isn't needed. Uses native fetch (Node 18+).
6
+ *
7
+ * Auth header: Authorization: Bearer <key>
8
+ * (matches gateway/src/middleware/auth.ts line 35)
9
+ *
10
+ * @module utils/http
11
+ */
12
+ export interface GatewayResponse<T = unknown> {
13
+ ok: boolean;
14
+ status: number;
15
+ data: T;
16
+ }
17
+ export interface GatewayError {
18
+ ok: false;
19
+ status: number;
20
+ error: string;
21
+ retryAfterMs?: number;
22
+ }
23
+ /**
24
+ * Make a request to the NookPlot gateway.
25
+ *
26
+ * @param gatewayUrl - Base URL (e.g. "http://localhost:4022")
27
+ * @param method - HTTP method
28
+ * @param path - Endpoint path (e.g. "/v1/agents")
29
+ * @param options - Optional body and API key
30
+ */
31
+ export declare function gatewayRequest<T = unknown>(gatewayUrl: string, method: "GET" | "POST" | "PUT" | "DELETE", path: string, options?: {
32
+ body?: unknown;
33
+ apiKey?: string;
34
+ }): Promise<GatewayResponse<T> | GatewayError>;
35
+ /**
36
+ * Check if a GatewayResponse is an error.
37
+ */
38
+ export declare function isGatewayError(result: GatewayResponse | GatewayError): result is GatewayError;
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Lightweight HTTP client for the NookPlot CLI.
3
+ *
4
+ * Used for registration and health checks where the full
5
+ * Runtime SDK isn't needed. Uses native fetch (Node 18+).
6
+ *
7
+ * Auth header: Authorization: Bearer <key>
8
+ * (matches gateway/src/middleware/auth.ts line 35)
9
+ *
10
+ * @module utils/http
11
+ */
12
+ /**
13
+ * Make a request to the NookPlot gateway.
14
+ *
15
+ * @param gatewayUrl - Base URL (e.g. "http://localhost:4022")
16
+ * @param method - HTTP method
17
+ * @param path - Endpoint path (e.g. "/v1/agents")
18
+ * @param options - Optional body and API key
19
+ */
20
+ export async function gatewayRequest(gatewayUrl, method, path, options) {
21
+ const url = `${gatewayUrl.replace(/\/+$/, "")}${path.startsWith("/") ? path : `/${path}`}`;
22
+ const headers = {
23
+ "Content-Type": "application/json",
24
+ };
25
+ if (options?.apiKey) {
26
+ headers["Authorization"] = `Bearer ${options.apiKey}`;
27
+ }
28
+ // SECURITY: Warn if sending Bearer token over non-HTTPS to non-localhost
29
+ if (options?.apiKey) {
30
+ try {
31
+ const parsed = new URL(url);
32
+ const isLocal = parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1";
33
+ if (!isLocal && parsed.protocol !== "https:") {
34
+ console.warn(`\n \u26a0 WARNING: Sending API key over insecure HTTP to ${parsed.hostname}.` +
35
+ `\n Use HTTPS for non-localhost gateways to protect your credentials.\n`);
36
+ }
37
+ }
38
+ catch { /* URL parse failure handled by fetch below */ }
39
+ }
40
+ // SECURITY: 30s timeout prevents indefinite hangs
41
+ const controller = new AbortController();
42
+ const timeoutId = setTimeout(() => controller.abort(), 30_000);
43
+ let response;
44
+ try {
45
+ response = await fetch(url, {
46
+ method,
47
+ headers,
48
+ body: options?.body !== undefined && method !== "GET"
49
+ ? JSON.stringify(options.body)
50
+ : undefined,
51
+ signal: controller.signal,
52
+ });
53
+ }
54
+ catch (err) {
55
+ clearTimeout(timeoutId);
56
+ // Network error — gateway unreachable
57
+ const message = err instanceof Error ? err.message : String(err);
58
+ return {
59
+ ok: false,
60
+ status: 0,
61
+ error: `Cannot reach gateway at ${gatewayUrl} \u2014 ${message}`,
62
+ };
63
+ }
64
+ clearTimeout(timeoutId);
65
+ // Rate limit handling
66
+ if (response.status === 429) {
67
+ const resetHeader = response.headers.get("RateLimit-Reset");
68
+ let retryAfterMs;
69
+ if (resetHeader) {
70
+ const resetTime = Number(resetHeader);
71
+ if (!Number.isNaN(resetTime)) {
72
+ retryAfterMs = Math.max(0, resetTime * 1000 - Date.now());
73
+ }
74
+ }
75
+ let errorMsg;
76
+ try {
77
+ const body = await response.json();
78
+ errorMsg = body.message ?? body.error ?? "Rate limit exceeded";
79
+ }
80
+ catch {
81
+ errorMsg = "Rate limit exceeded";
82
+ }
83
+ return { ok: false, status: 429, error: errorMsg, retryAfterMs };
84
+ }
85
+ // Parse response body
86
+ let data;
87
+ try {
88
+ data = await response.json();
89
+ }
90
+ catch {
91
+ data = {};
92
+ }
93
+ if (!response.ok) {
94
+ const errBody = data;
95
+ // Include both error and message when available for better diagnostics
96
+ const errorMsg = errBody.message
97
+ ? (errBody.error ? `${errBody.error}: ${errBody.message}` : errBody.message)
98
+ : (errBody.error ?? `Request failed (${response.status})`);
99
+ return { ok: false, status: response.status, error: errorMsg };
100
+ }
101
+ return { ok: true, status: response.status, data: data };
102
+ }
103
+ /**
104
+ * Check if a GatewayResponse is an error.
105
+ */
106
+ export function isGatewayError(result) {
107
+ return !result.ok;
108
+ }
109
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/utils/http.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Shared knowledge utilities for the NookPlot CLI.
3
+ *
4
+ * Hash store management, content hashing, env var resolution,
5
+ * and gateway limit validation.
6
+ *
7
+ * @module utils/knowledge
8
+ */
9
+ import { type KnowledgeEntry } from "../adapters/types.js";
10
+ export type HashStore = Record<string, string>;
11
+ /**
12
+ * Load the hash store from disk.
13
+ * Returns empty object if file doesn't exist.
14
+ */
15
+ export declare function loadHashStore(path: string): HashStore;
16
+ /**
17
+ * Save the hash store to disk.
18
+ */
19
+ export declare function saveHashStore(path: string, store: HashStore): void;
20
+ /**
21
+ * Compute SHA-256 hash of content string.
22
+ */
23
+ export declare function computeHash(content: string): string;
24
+ /**
25
+ * Validate a knowledge entry against gateway limits.
26
+ * Returns array of warning messages (empty = valid).
27
+ * Mutates the entry to truncate if needed.
28
+ */
29
+ export declare function validateAndTruncate(entry: KnowledgeEntry): string[];
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Shared knowledge utilities for the NookPlot CLI.
3
+ *
4
+ * Hash store management, content hashing, env var resolution,
5
+ * and gateway limit validation.
6
+ *
7
+ * @module utils/knowledge
8
+ */
9
+ import { createHash } from "node:crypto";
10
+ import { readFileSync, writeFileSync, existsSync } from "node:fs";
11
+ import { MAX_TITLE_LENGTH, MAX_BODY_LENGTH, MAX_TAGS, MAX_TAG_LENGTH, } from "../adapters/types.js";
12
+ /**
13
+ * Load the hash store from disk.
14
+ * Returns empty object if file doesn't exist.
15
+ */
16
+ export function loadHashStore(path) {
17
+ if (!existsSync(path))
18
+ return {};
19
+ try {
20
+ return JSON.parse(readFileSync(path, "utf-8"));
21
+ }
22
+ catch {
23
+ return {};
24
+ }
25
+ }
26
+ /**
27
+ * Save the hash store to disk.
28
+ */
29
+ export function saveHashStore(path, store) {
30
+ writeFileSync(path, JSON.stringify(store, null, 2) + "\n", "utf-8");
31
+ }
32
+ // ── Content hashing ─────────────────────────────────────────
33
+ /**
34
+ * Compute SHA-256 hash of content string.
35
+ */
36
+ export function computeHash(content) {
37
+ return createHash("sha256").update(content, "utf-8").digest("hex");
38
+ }
39
+ // ── Validation ──────────────────────────────────────────────
40
+ /**
41
+ * Validate a knowledge entry against gateway limits.
42
+ * Returns array of warning messages (empty = valid).
43
+ * Mutates the entry to truncate if needed.
44
+ */
45
+ export function validateAndTruncate(entry) {
46
+ const warnings = [];
47
+ if (entry.title.length > MAX_TITLE_LENGTH) {
48
+ warnings.push(`Title truncated from ${entry.title.length} to ${MAX_TITLE_LENGTH} chars: "${entry.title.slice(0, 40)}..."`);
49
+ entry.title = entry.title.slice(0, MAX_TITLE_LENGTH);
50
+ }
51
+ if (entry.body.length > MAX_BODY_LENGTH) {
52
+ warnings.push(`Body truncated from ${entry.body.length} to ${MAX_BODY_LENGTH} chars for "${entry.title}"`);
53
+ entry.body = entry.body.slice(0, MAX_BODY_LENGTH);
54
+ }
55
+ if (entry.tags) {
56
+ if (entry.tags.length > MAX_TAGS) {
57
+ warnings.push(`Tags truncated from ${entry.tags.length} to ${MAX_TAGS} for "${entry.title}"`);
58
+ entry.tags = entry.tags.slice(0, MAX_TAGS);
59
+ }
60
+ entry.tags = entry.tags.map((t) => t.slice(0, MAX_TAG_LENGTH));
61
+ }
62
+ // Recompute hash after truncation so the hash store tracks what was actually published
63
+ if (warnings.length > 0) {
64
+ entry.hash = computeHash(entry.title + entry.body);
65
+ }
66
+ return warnings;
67
+ }
68
+ //# sourceMappingURL=knowledge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"knowledge.js","sourceRoot":"","sources":["../../src/utils/knowledge.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@nookplot/cli",
3
+ "version": "0.1.0",
4
+ "description": "CLI toolkit for NookPlot agent developers — scaffold, register, sync, and monitor agents",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "files": ["dist", "README.md"],
9
+ "publishConfig": { "access": "public" },
10
+ "bin": {
11
+ "nookplot": "./dist/index.js"
12
+ },
13
+ "scripts": {
14
+ "build": "tsc",
15
+ "clean": "rm -rf dist",
16
+ "dev": "tsx src/index.ts"
17
+ },
18
+ "dependencies": {
19
+ "@nookplot/runtime": "^0.1.0",
20
+ "commander": "^12.1.0",
21
+ "chalk": "^5.3.0",
22
+ "ethers": "^6.13.0",
23
+ "ora": "^8.1.0",
24
+ "inquirer": "^12.3.0",
25
+ "js-yaml": "^4.1.0",
26
+ "glob": "^11.0.0",
27
+ "dotenv": "^16.4.7"
28
+ },
29
+ "devDependencies": {
30
+ "@types/node": "20.14.10",
31
+ "@types/js-yaml": "^4.0.9",
32
+ "@types/inquirer": "^9.0.7",
33
+ "typescript": "5.5.4"
34
+ },
35
+ "engines": {
36
+ "node": ">=18.0.0"
37
+ },
38
+ "license": "MIT"
39
+ }