@otomus/nerva-cli 0.1.1

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 (45) hide show
  1. package/dist/commands/dev.d.ts +42 -0
  2. package/dist/commands/dev.d.ts.map +1 -0
  3. package/dist/commands/dev.js +257 -0
  4. package/dist/commands/dev.js.map +1 -0
  5. package/dist/commands/generate.d.ts +24 -0
  6. package/dist/commands/generate.d.ts.map +1 -0
  7. package/dist/commands/generate.js +162 -0
  8. package/dist/commands/generate.js.map +1 -0
  9. package/dist/commands/list.d.ts +19 -0
  10. package/dist/commands/list.d.ts.map +1 -0
  11. package/dist/commands/list.js +96 -0
  12. package/dist/commands/list.js.map +1 -0
  13. package/dist/commands/new.d.ts +23 -0
  14. package/dist/commands/new.d.ts.map +1 -0
  15. package/dist/commands/new.js +138 -0
  16. package/dist/commands/new.js.map +1 -0
  17. package/dist/commands/plugin.d.ts +79 -0
  18. package/dist/commands/plugin.d.ts.map +1 -0
  19. package/dist/commands/plugin.js +319 -0
  20. package/dist/commands/plugin.js.map +1 -0
  21. package/dist/commands/test.d.ts +52 -0
  22. package/dist/commands/test.d.ts.map +1 -0
  23. package/dist/commands/test.js +110 -0
  24. package/dist/commands/test.js.map +1 -0
  25. package/dist/commands/trace-ui.d.ts +16 -0
  26. package/dist/commands/trace-ui.d.ts.map +1 -0
  27. package/dist/commands/trace-ui.js +117 -0
  28. package/dist/commands/trace-ui.js.map +1 -0
  29. package/dist/config/nerva-yaml.d.ts +70 -0
  30. package/dist/config/nerva-yaml.d.ts.map +1 -0
  31. package/dist/config/nerva-yaml.js +185 -0
  32. package/dist/config/nerva-yaml.js.map +1 -0
  33. package/dist/index.d.ts +14 -0
  34. package/dist/index.d.ts.map +1 -0
  35. package/dist/index.js +36 -0
  36. package/dist/index.js.map +1 -0
  37. package/dist/registry/plugin-registry.d.ts +30 -0
  38. package/dist/registry/plugin-registry.d.ts.map +1 -0
  39. package/dist/registry/plugin-registry.js +134 -0
  40. package/dist/registry/plugin-registry.js.map +1 -0
  41. package/dist/templates/render.d.ts +36 -0
  42. package/dist/templates/render.d.ts.map +1 -0
  43. package/dist/templates/render.js +52 -0
  44. package/dist/templates/render.js.map +1 -0
  45. package/package.json +32 -0
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Community plugin registry client.
3
+ *
4
+ * Searches the npm registry for packages with the `nerva-plugin` keyword
5
+ * and fetches package metadata. Uses `https.get` with no external dependencies.
6
+ */
7
+ import { get } from 'node:https';
8
+ // ---------------------------------------------------------------------------
9
+ // Constants
10
+ // ---------------------------------------------------------------------------
11
+ /** Base URL for the npm registry API. */
12
+ const NPM_REGISTRY = 'https://registry.npmjs.org';
13
+ /** npm search API endpoint. */
14
+ const NPM_SEARCH_URL = 'https://registry.npmjs.org/-/v1/search';
15
+ /** Request timeout in milliseconds. */
16
+ const REQUEST_TIMEOUT_MS = 10_000;
17
+ // ---------------------------------------------------------------------------
18
+ // HTTP helpers
19
+ // ---------------------------------------------------------------------------
20
+ /**
21
+ * Performs an HTTPS GET request and returns the response body as a string.
22
+ *
23
+ * @param url - Full URL to fetch
24
+ * @returns Response body
25
+ * @throws {Error} If the request fails or returns a non-2xx status
26
+ */
27
+ function httpsGet(url) {
28
+ return new Promise((resolve, reject) => {
29
+ const req = get(url, { timeout: REQUEST_TIMEOUT_MS }, (res) => {
30
+ const statusCode = res.statusCode ?? 0;
31
+ if (statusCode < 200 || statusCode >= 300) {
32
+ res.resume();
33
+ reject(new Error(`HTTP ${statusCode} from ${url}`));
34
+ return;
35
+ }
36
+ const chunks = [];
37
+ res.on('data', (chunk) => chunks.push(chunk));
38
+ res.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));
39
+ });
40
+ req.on('error', (err) => reject(new Error(`Request failed: ${err.message}`)));
41
+ req.on('timeout', () => {
42
+ req.destroy();
43
+ reject(new Error(`Request timed out after ${REQUEST_TIMEOUT_MS}ms`));
44
+ });
45
+ });
46
+ }
47
+ // ---------------------------------------------------------------------------
48
+ // Public API
49
+ // ---------------------------------------------------------------------------
50
+ /**
51
+ * Searches the npm registry for packages matching a query and the `nerva-plugin` keyword.
52
+ *
53
+ * @param query - Free-text search query
54
+ * @returns Array of matching plugin summaries, sorted by relevance
55
+ * @throws {Error} If the npm registry is unreachable or returns invalid data
56
+ */
57
+ export async function searchPlugins(query) {
58
+ const encodedQuery = encodeURIComponent(`${query} keywords:nerva-plugin`);
59
+ const url = `${NPM_SEARCH_URL}?text=${encodedQuery}&size=20`;
60
+ const body = await httpsGet(url);
61
+ const data = parseJson(body, 'npm search response');
62
+ if (!Array.isArray(data.objects)) {
63
+ return [];
64
+ }
65
+ return data.objects.map((obj) => ({
66
+ name: obj.package.name,
67
+ description: obj.package.description ?? '',
68
+ version: obj.package.version,
69
+ downloads: obj.downloads?.monthly ?? 0,
70
+ }));
71
+ }
72
+ /**
73
+ * Fetches detailed package info from the npm registry for a specific package.
74
+ *
75
+ * @param name - Exact npm package name
76
+ * @returns Plugin info with name, description, latest version, and monthly downloads
77
+ * @throws {Error} If the package is not found or the registry is unreachable
78
+ */
79
+ export async function fetchPluginInfo(name) {
80
+ const encodedName = encodeURIComponent(name);
81
+ const url = `${NPM_REGISTRY}/${encodedName}`;
82
+ const body = await httpsGet(url);
83
+ const data = parseJson(body, `npm package "${name}"`);
84
+ const latestVersion = data['dist-tags']?.latest ?? 'unknown';
85
+ const description = data.description ??
86
+ data.versions?.[latestVersion]?.description ??
87
+ '';
88
+ // Fetch download counts separately (different API)
89
+ const downloads = await fetchMonthlyDownloads(name);
90
+ return {
91
+ name: data.name,
92
+ description,
93
+ version: latestVersion,
94
+ downloads,
95
+ };
96
+ }
97
+ /**
98
+ * Fetches monthly download count for a package from the npm downloads API.
99
+ *
100
+ * Returns 0 if the request fails — download counts are non-critical metadata.
101
+ *
102
+ * @param name - Exact npm package name
103
+ * @returns Monthly download count
104
+ */
105
+ async function fetchMonthlyDownloads(name) {
106
+ try {
107
+ const encodedName = encodeURIComponent(name);
108
+ const url = `https://api.npmjs.org/downloads/point/last-month/${encodedName}`;
109
+ const body = await httpsGet(url);
110
+ const data = parseJson(body, 'npm downloads');
111
+ return data.downloads ?? 0;
112
+ }
113
+ catch {
114
+ // Download counts are best-effort — don't fail the whole operation
115
+ return 0;
116
+ }
117
+ }
118
+ /**
119
+ * Parses a JSON string with a descriptive error on failure.
120
+ *
121
+ * @param raw - Raw JSON string
122
+ * @param context - Human-readable description of what was being parsed
123
+ * @returns Parsed value
124
+ * @throws {Error} If the JSON is invalid
125
+ */
126
+ function parseJson(raw, context) {
127
+ try {
128
+ return JSON.parse(raw);
129
+ }
130
+ catch {
131
+ throw new Error(`Invalid JSON in ${context}`);
132
+ }
133
+ }
134
+ //# sourceMappingURL=plugin-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-registry.js","sourceRoot":"","sources":["../../src/registry/plugin-registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Template rendering utilities.
3
+ *
4
+ * Simple string interpolation for scaffold templates.
5
+ * Uses {{key}} placeholders — no external template engine required.
6
+ */
7
+ /** Variable map for template interpolation. */
8
+ export type TemplateVars = Record<string, string>;
9
+ /**
10
+ * Replaces all {{key}} placeholders in a template string with values from vars.
11
+ *
12
+ * Unknown placeholders are left as-is to avoid silent data loss.
13
+ *
14
+ * @param template - Raw template string with {{key}} placeholders
15
+ * @param vars - Key-value pairs to substitute
16
+ * @returns Rendered string
17
+ */
18
+ export declare function renderTemplate(template: string, vars: TemplateVars): string;
19
+ /**
20
+ * Converts a kebab-case or snake_case name to PascalCase for class names.
21
+ *
22
+ * @param name - Input name (e.g. "my-agent" or "my_agent")
23
+ * @returns PascalCase string (e.g. "MyAgent")
24
+ */
25
+ export declare function toPascalCase(name: string): string;
26
+ /**
27
+ * Loads a template file from the templates directory and renders it.
28
+ *
29
+ * @param lang - Project language ("python" or "typescript")
30
+ * @param templateName - Template filename (e.g. "agent.py.tmpl")
31
+ * @param vars - Variables to substitute into the template
32
+ * @returns Rendered file content
33
+ * @throws {Error} If the template file cannot be read
34
+ */
35
+ export declare function loadAndRender(lang: string, templateName: string, vars: TemplateVars): Promise<string>;
36
+ //# sourceMappingURL=render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/templates/render.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,+CAA+C;AAC/C,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAMlD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,GAAG,MAAM,CAI3E;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKjD;AAED;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,YAAY,GACjB,OAAO,CAAC,MAAM,CAAC,CAIjB"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Template rendering utilities.
3
+ *
4
+ * Simple string interpolation for scaffold templates.
5
+ * Uses {{key}} placeholders — no external template engine required.
6
+ */
7
+ import { readFile } from 'node:fs/promises';
8
+ import { join, dirname } from 'node:path';
9
+ import { fileURLToPath } from 'node:url';
10
+ const TEMPLATE_PATTERN = /\{\{(\w+)\}\}/g;
11
+ const CURRENT_DIR = dirname(fileURLToPath(import.meta.url));
12
+ /**
13
+ * Replaces all {{key}} placeholders in a template string with values from vars.
14
+ *
15
+ * Unknown placeholders are left as-is to avoid silent data loss.
16
+ *
17
+ * @param template - Raw template string with {{key}} placeholders
18
+ * @param vars - Key-value pairs to substitute
19
+ * @returns Rendered string
20
+ */
21
+ export function renderTemplate(template, vars) {
22
+ return template.replace(TEMPLATE_PATTERN, (_match, key) => {
23
+ return key in vars ? vars[key] : `{{${key}}}`;
24
+ });
25
+ }
26
+ /**
27
+ * Converts a kebab-case or snake_case name to PascalCase for class names.
28
+ *
29
+ * @param name - Input name (e.g. "my-agent" or "my_agent")
30
+ * @returns PascalCase string (e.g. "MyAgent")
31
+ */
32
+ export function toPascalCase(name) {
33
+ return name
34
+ .split(/[-_]/)
35
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())
36
+ .join('');
37
+ }
38
+ /**
39
+ * Loads a template file from the templates directory and renders it.
40
+ *
41
+ * @param lang - Project language ("python" or "typescript")
42
+ * @param templateName - Template filename (e.g. "agent.py.tmpl")
43
+ * @param vars - Variables to substitute into the template
44
+ * @returns Rendered file content
45
+ * @throws {Error} If the template file cannot be read
46
+ */
47
+ export async function loadAndRender(lang, templateName, vars) {
48
+ const templatePath = join(CURRENT_DIR, lang, templateName);
49
+ const raw = await readFile(templatePath, 'utf-8');
50
+ return renderTemplate(raw, vars);
51
+ }
52
+ //# sourceMappingURL=render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/templates/render.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAKzC,MAAM,gBAAgB,GAAG,gBAAgB,CAAC;AAE1C,MAAM,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAE5D;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc,CAAC,QAAgB,EAAE,IAAkB;IACjE,OAAO,QAAQ,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC,MAAM,EAAE,GAAW,EAAE,EAAE;QAChE,OAAO,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC;IAChD,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAO,IAAI;SACR,KAAK,CAAC,MAAM,CAAC;SACb,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;SACzE,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,IAAY,EACZ,YAAoB,EACpB,IAAkB;IAElB,MAAM,YAAY,GAAG,IAAI,CAAC,WAAW,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC;IAC3D,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IAClD,OAAO,cAAc,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;AACnC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "@otomus/nerva-cli",
3
+ "version": "0.1.1",
4
+ "description": "CLI for the Nerva agent runtime",
5
+ "type": "module",
6
+ "bin": {
7
+ "nerva": "./dist/index.js"
8
+ },
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "test": "vitest run",
12
+ "typecheck": "tsc --noEmit"
13
+ },
14
+ "dependencies": {
15
+ "commander": "^12.1.0"
16
+ },
17
+ "devDependencies": {
18
+ "@types/node": "^20.14.0",
19
+ "typescript": "^5.4.0",
20
+ "vitest": "^1.6.0"
21
+ },
22
+ "license": "MIT",
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "https://github.com/otomus/nerva",
26
+ "directory": "packages/nerva-cli"
27
+ },
28
+ "files": [
29
+ "dist",
30
+ "README.md"
31
+ ]
32
+ }