@nepopsx/cli 0.0.19 → 0.0.20
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/agents/catalog.d.ts +19 -0
- package/dist/agents/catalog.d.ts.map +1 -0
- package/dist/agents/catalog.js +45 -0
- package/dist/agents/catalog.js.map +1 -0
- package/dist/agents/configuration.d.ts +1 -0
- package/dist/agents/configuration.d.ts.map +1 -1
- package/dist/agents/configuration.js +36 -0
- package/dist/agents/configuration.js.map +1 -1
- package/dist/agents/configuration.test.d.ts +2 -0
- package/dist/agents/configuration.test.d.ts.map +1 -0
- package/dist/agents/configuration.test.js +32 -0
- package/dist/agents/configuration.test.js.map +1 -0
- package/dist/commands/capture.d.ts +19 -0
- package/dist/commands/capture.d.ts.map +1 -0
- package/dist/commands/capture.js +105 -0
- package/dist/commands/capture.js.map +1 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +11 -30
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/install.d.ts +2 -0
- package/dist/commands/install.d.ts.map +1 -1
- package/dist/commands/install.js +86 -15
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/login.d.ts +8 -1
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +169 -80
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/push-learnings.d.ts.map +1 -1
- package/dist/commands/push-learnings.js +93 -62
- package/dist/commands/push-learnings.js.map +1 -1
- package/dist/commands/sync.d.ts +4 -0
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +120 -64
- package/dist/commands/sync.js.map +1 -1
- package/dist/commands/up.d.ts +23 -0
- package/dist/commands/up.d.ts.map +1 -0
- package/dist/commands/up.js +263 -0
- package/dist/commands/up.js.map +1 -0
- package/dist/enrichment/workflow.d.ts +1 -0
- package/dist/enrichment/workflow.d.ts.map +1 -1
- package/dist/enrichment/workflow.js +13 -0
- package/dist/enrichment/workflow.js.map +1 -1
- package/dist/generator/preview.d.ts +13 -0
- package/dist/generator/preview.d.ts.map +1 -0
- package/dist/generator/preview.js +242 -0
- package/dist/generator/preview.js.map +1 -0
- package/dist/generator/preview.test.d.ts +19 -0
- package/dist/generator/preview.test.d.ts.map +1 -0
- package/dist/generator/preview.test.js +289 -0
- package/dist/generator/preview.test.js.map +1 -0
- package/dist/generator/render.d.ts +2 -2
- package/dist/generator/render.d.ts.map +1 -1
- package/dist/generator/render.js +37 -18
- package/dist/generator/render.js.map +1 -1
- package/dist/generator/writer.d.ts +15 -1
- package/dist/generator/writer.d.ts.map +1 -1
- package/dist/generator/writer.js +41 -3
- package/dist/generator/writer.js.map +1 -1
- package/dist/hooks/capture-hooks.d.ts +9 -0
- package/dist/hooks/capture-hooks.d.ts.map +1 -0
- package/dist/hooks/capture-hooks.js +100 -0
- package/dist/hooks/capture-hooks.js.map +1 -0
- package/dist/hooks/capture-hooks.test.d.ts +2 -0
- package/dist/hooks/capture-hooks.test.d.ts.map +1 -0
- package/dist/hooks/capture-hooks.test.js +50 -0
- package/dist/hooks/capture-hooks.test.js.map +1 -0
- package/dist/index.js +26 -3
- package/dist/index.js.map +1 -1
- package/dist/learnings/yaml-learnings.d.ts +16 -2
- package/dist/learnings/yaml-learnings.d.ts.map +1 -1
- package/dist/learnings/yaml-learnings.js +43 -8
- package/dist/learnings/yaml-learnings.js.map +1 -1
- package/dist/learnings/yaml-learnings.test.d.ts +2 -0
- package/dist/learnings/yaml-learnings.test.d.ts.map +1 -0
- package/dist/learnings/yaml-learnings.test.js +39 -0
- package/dist/learnings/yaml-learnings.test.js.map +1 -0
- package/dist/licensing/installer.d.ts +2 -2
- package/dist/licensing/installer.d.ts.map +1 -1
- package/dist/licensing/installer.js +3 -1
- package/dist/licensing/installer.js.map +1 -1
- package/dist/licensing/template-fetch.d.ts +2 -2
- package/dist/licensing/template-fetch.d.ts.map +1 -1
- package/dist/licensing/template-fetch.js +4 -1
- package/dist/licensing/template-fetch.js.map +1 -1
- package/dist/mcp/config-generator.d.ts +42 -0
- package/dist/mcp/config-generator.d.ts.map +1 -0
- package/dist/mcp/config-generator.js +55 -0
- package/dist/mcp/config-generator.js.map +1 -0
- package/dist/mcp/config-generator.test.d.ts +7 -0
- package/dist/mcp/config-generator.test.d.ts.map +1 -0
- package/dist/mcp/config-generator.test.js +79 -0
- package/dist/mcp/config-generator.test.js.map +1 -0
- package/dist/ruflo/config-generator.d.ts +22 -0
- package/dist/ruflo/config-generator.d.ts.map +1 -0
- package/dist/ruflo/config-generator.js +89 -0
- package/dist/ruflo/config-generator.js.map +1 -0
- package/dist/ruflo/config-generator.test.d.ts +2 -0
- package/dist/ruflo/config-generator.test.d.ts.map +1 -0
- package/dist/ruflo/config-generator.test.js +18 -0
- package/dist/ruflo/config-generator.test.js.map +1 -0
- package/dist/ruflo/detect.d.ts +11 -0
- package/dist/ruflo/detect.d.ts.map +1 -0
- package/dist/ruflo/detect.js +30 -0
- package/dist/ruflo/detect.js.map +1 -0
- package/dist/ruflo/index.d.ts +3 -0
- package/dist/ruflo/index.d.ts.map +1 -0
- package/dist/ruflo/index.js +3 -0
- package/dist/ruflo/index.js.map +1 -0
- package/dist/security/index.d.ts +1 -1
- package/dist/security/index.d.ts.map +1 -1
- package/dist/security/index.js +1 -1
- package/dist/security/index.js.map +1 -1
- package/dist/security/integrity.d.ts +8 -0
- package/dist/security/integrity.d.ts.map +1 -1
- package/dist/security/integrity.js +28 -0
- package/dist/security/integrity.js.map +1 -1
- package/package.json +5 -3
- package/dist/generator/package-renderer.d.ts +0 -38
- package/dist/generator/package-renderer.d.ts.map +0 -1
- package/dist/generator/package-renderer.js +0 -181
- package/dist/generator/package-renderer.js.map +0 -1
- package/dist/generator/provider-transform.d.ts +0 -15
- package/dist/generator/provider-transform.d.ts.map +0 -1
- package/dist/generator/provider-transform.js +0 -163
- package/dist/generator/provider-transform.js.map +0 -1
- package/dist/licensing/fingerprint.test.d.ts +0 -2
- package/dist/licensing/fingerprint.test.d.ts.map +0 -1
- package/dist/licensing/fingerprint.test.js +0 -41
- package/dist/licensing/fingerprint.test.js.map +0 -1
|
@@ -4,22 +4,27 @@
|
|
|
4
4
|
* Reads/writes learning files from .nepopsx/learnings/*.yaml.
|
|
5
5
|
* These are the canonical local store for reflector-produced learnings.
|
|
6
6
|
*/
|
|
7
|
-
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from 'node:fs';
|
|
7
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, writeFileSync } from 'node:fs';
|
|
8
8
|
import { basename, resolve } from 'node:path';
|
|
9
9
|
import { parse, stringify } from 'yaml';
|
|
10
10
|
const VALID_TYPES = new Set(['custom_instruction', 'config_patch', 'skill', 'scope_change']);
|
|
11
11
|
const VALID_CONFIDENCES = new Set(['high', 'medium', 'low']);
|
|
12
12
|
const VALID_STATUSES = new Set(['local', 'pending', 'approved', 'suggested', 'reverted']);
|
|
13
13
|
/**
|
|
14
|
-
* Load all YAML learning files from a directory.
|
|
15
|
-
* Recursively scans local subdirectories, excluding server-owned
|
|
14
|
+
* Load all YAML learning files from a directory, keeping each file's path.
|
|
15
|
+
* Recursively scans local subdirectories, excluding the server-owned `team/`
|
|
16
|
+
* folder (pulled team learnings, never re-pushed).
|
|
16
17
|
*/
|
|
17
|
-
export function
|
|
18
|
+
export function loadLearningFiles(learningsDir, agentFilter) {
|
|
18
19
|
if (!existsSync(learningsDir))
|
|
19
20
|
return [];
|
|
20
|
-
const
|
|
21
|
-
scanDir(learningsDir,
|
|
22
|
-
return
|
|
21
|
+
const out = [];
|
|
22
|
+
scanDir(learningsDir, out, agentFilter);
|
|
23
|
+
return out;
|
|
24
|
+
}
|
|
25
|
+
/** Load learnings without their paths (back-compat wrapper). */
|
|
26
|
+
export function loadYamlLearnings(learningsDir, agentFilter) {
|
|
27
|
+
return loadLearningFiles(learningsDir, agentFilter).map((f) => f.learning);
|
|
23
28
|
}
|
|
24
29
|
function scanDir(dir, out, agentFilter) {
|
|
25
30
|
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
@@ -38,7 +43,33 @@ function scanDir(dir, out, agentFilter) {
|
|
|
38
43
|
continue;
|
|
39
44
|
if (agentFilter && learning.agent !== agentFilter)
|
|
40
45
|
continue;
|
|
41
|
-
out.push(learning);
|
|
46
|
+
out.push({ learning, filePath: fullPath });
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Update just the `status` field of a learning file in place, preserving its
|
|
51
|
+
* location and all other fields. Best-effort — used after a successful push so
|
|
52
|
+
* locally-authored learnings aren't re-pushed (which would inflate occurrences).
|
|
53
|
+
*/
|
|
54
|
+
export function setLearningStatus(filePath, status) {
|
|
55
|
+
try {
|
|
56
|
+
const raw = readFileSync(filePath, 'utf-8');
|
|
57
|
+
// Surgically replace (or append) the top-level `status:` line. A full YAML
|
|
58
|
+
// parse→stringify round-trip would strip comments and reinterpret ambiguous
|
|
59
|
+
// scalars (leading-zero strings → numbers, drop quotes), so we edit the line
|
|
60
|
+
// in place. `^status:` (column 0) can't match indented block-scalar content.
|
|
61
|
+
const next = /^status:.*$/m.test(raw)
|
|
62
|
+
? raw.replace(/^status:.*$/m, `status: ${status}`)
|
|
63
|
+
: `${raw.endsWith('\n') ? raw : raw + '\n'}status: ${status}\n`;
|
|
64
|
+
if (next === raw)
|
|
65
|
+
return;
|
|
66
|
+
// Atomic write (tmp → rename) so a crash or concurrent capture can't truncate it.
|
|
67
|
+
const tmp = `${filePath}.tmp`;
|
|
68
|
+
writeFileSync(tmp, next, 'utf-8');
|
|
69
|
+
renameSync(tmp, filePath);
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
// Non-fatal: a failed status write just means the learning may re-push once.
|
|
42
73
|
}
|
|
43
74
|
}
|
|
44
75
|
/**
|
|
@@ -69,6 +100,7 @@ export function parseYamlLearning(filePath) {
|
|
|
69
100
|
confidence,
|
|
70
101
|
agent,
|
|
71
102
|
applies_to: Array.isArray(parsed.applies_to) ? parsed.applies_to : [],
|
|
103
|
+
services: Array.isArray(parsed.services) ? parsed.services : [],
|
|
72
104
|
status,
|
|
73
105
|
content: parsed.content.trim(),
|
|
74
106
|
evidence: parsed.evidence ?? undefined,
|
|
@@ -97,6 +129,9 @@ export function writeYamlLearning(dir, learning) {
|
|
|
97
129
|
status: learning.status,
|
|
98
130
|
content: learning.content,
|
|
99
131
|
};
|
|
132
|
+
if (learning.services && learning.services.length > 0) {
|
|
133
|
+
data.services = learning.services;
|
|
134
|
+
}
|
|
100
135
|
if (learning.evidence)
|
|
101
136
|
data.evidence = learning.evidence;
|
|
102
137
|
if (learning.created_at)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"yaml-learnings.js","sourceRoot":"","sources":["../../src/learnings/yaml-learnings.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"yaml-learnings.js","sourceRoot":"","sources":["../../src/learnings/yaml-learnings.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"yaml-learnings.test.d.ts","sourceRoot":"","sources":["../../src/learnings/yaml-learnings.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { strict as assert } from 'node:assert';
|
|
2
|
+
import { describe, it } from 'node:test';
|
|
3
|
+
import { mkdtempSync, writeFileSync, readFileSync, rmSync } from 'node:fs';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
import { tmpdir } from 'node:os';
|
|
6
|
+
import { setLearningStatus } from './yaml-learnings.js';
|
|
7
|
+
describe('setLearningStatus', () => {
|
|
8
|
+
it('surgically updates status, preserving comments and ambiguous scalars', () => {
|
|
9
|
+
const dir = mkdtempSync(join(tmpdir(), 'learn-'));
|
|
10
|
+
const file = join(dir, 'x.yaml');
|
|
11
|
+
writeFileSync(file, ['slug: "007-pattern" # keep quotes + comment', 'type: custom_instruction', 'status: local', 'confidence: high'].join('\n') + '\n');
|
|
12
|
+
setLearningStatus(file, 'approved');
|
|
13
|
+
const out = readFileSync(file, 'utf-8');
|
|
14
|
+
assert.match(out, /^status: approved$/m);
|
|
15
|
+
assert.doesNotMatch(out, /status: local/);
|
|
16
|
+
// a full YAML round-trip would drop the comment and unquote "007-pattern" (→ 7); we don't
|
|
17
|
+
assert.match(out, /slug: "007-pattern" # keep quotes \+ comment/);
|
|
18
|
+
rmSync(dir, { recursive: true, force: true });
|
|
19
|
+
});
|
|
20
|
+
it('appends status when the file has none', () => {
|
|
21
|
+
const dir = mkdtempSync(join(tmpdir(), 'learn-'));
|
|
22
|
+
const file = join(dir, 'y.yaml');
|
|
23
|
+
writeFileSync(file, 'slug: foo\ncontent: bar\n');
|
|
24
|
+
setLearningStatus(file, 'pending');
|
|
25
|
+
assert.match(readFileSync(file, 'utf-8'), /^status: pending$/m);
|
|
26
|
+
rmSync(dir, { recursive: true, force: true });
|
|
27
|
+
});
|
|
28
|
+
it('does not match an indented status: inside block-scalar content', () => {
|
|
29
|
+
const dir = mkdtempSync(join(tmpdir(), 'learn-'));
|
|
30
|
+
const file = join(dir, 'z.yaml');
|
|
31
|
+
writeFileSync(file, 'status: local\ncontent: |\n status: not-a-field\n');
|
|
32
|
+
setLearningStatus(file, 'approved');
|
|
33
|
+
const out = readFileSync(file, 'utf-8');
|
|
34
|
+
assert.match(out, /^status: approved$/m);
|
|
35
|
+
assert.match(out, / status: not-a-field/); // the indented one is untouched
|
|
36
|
+
rmSync(dir, { recursive: true, force: true });
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
//# sourceMappingURL=yaml-learnings.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"yaml-learnings.test.js","sourceRoot":"","sources":["../../src/learnings/yaml-learnings.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,MAAM,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAC3E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,EAAE,CAAC,sEAAsE,EAAE,GAAG,EAAE;QAC9E,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC;QAClD,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QACjC,aAAa,CACX,IAAI,EACJ,CAAC,6CAA6C,EAAE,0BAA0B,EAAE,eAAe,EAAE,kBAAkB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CACnI,CAAC;QACF,iBAAiB,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QACpC,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACxC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,qBAAqB,CAAC,CAAC;QACzC,MAAM,CAAC,YAAY,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC;QAC1C,0FAA0F;QAC1F,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,8CAA8C,CAAC,CAAC;QAClE,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC;QAClD,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QACjC,aAAa,CAAC,IAAI,EAAE,2BAA2B,CAAC,CAAC;QACjD,iBAAiB,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QACnC,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,oBAAoB,CAAC,CAAC;QAChE,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gEAAgE,EAAE,GAAG,EAAE;QACxE,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC;QAClD,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QACjC,aAAa,CAAC,IAAI,EAAE,oDAAoD,CAAC,CAAC;QAC1E,iBAAiB,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QACpC,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACxC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,qBAAqB,CAAC,CAAC;QACzC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,uBAAuB,CAAC,CAAC,CAAC,gCAAgC;QAC5E,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* 3. verifyBundleSha — SHA-256 of raw JSON must match server-provided sha256
|
|
9
9
|
* 4. writeAgentFiles — atomic write via temp + rename into .github/<relative-path>
|
|
10
10
|
*/
|
|
11
|
-
import type { License } from "@nepopsx/core";
|
|
11
|
+
import type { License, OutputProvider } from "@nepopsx/core";
|
|
12
12
|
import type { CustomInstruction } from "../generator/render.js";
|
|
13
13
|
export interface EncryptedBundle {
|
|
14
14
|
payload: string;
|
|
@@ -30,7 +30,7 @@ export interface AgentBootstrapConfig {
|
|
|
30
30
|
/**
|
|
31
31
|
* Download an encrypted template bundle from the NEPOPSX API.
|
|
32
32
|
*/
|
|
33
|
-
export declare function downloadBundle(cwd: string, license: License, agent: string, version: string, customInstructions?: CustomInstruction[]): Promise<EncryptedBundle>;
|
|
33
|
+
export declare function downloadBundle(cwd: string, license: License, agent: string, version: string, customInstructions?: CustomInstruction[], providers?: OutputProvider[]): Promise<EncryptedBundle>;
|
|
34
34
|
export declare function downloadBootstrapConfig(cwd: string, license: License, agent: string, version: string, customInstructions?: CustomInstruction[]): Promise<AgentBootstrapConfig>;
|
|
35
35
|
/**
|
|
36
36
|
* Decrypt an AES-256-GCM bundle using the license key.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../../src/licensing/installer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAOH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../../src/licensing/installer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAOH,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE7D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAIhE,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAID;;GAEG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,kBAAkB,GAAE,iBAAiB,EAAO,EAC5C,SAAS,GAAE,cAAc,EAAO,GAC/B,OAAO,CAAC,eAAe,CAAC,CA2B1B;AAED,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,kBAAkB,GAAE,iBAAiB,EAAO,GAC3C,OAAO,CAAC,oBAAoB,CAAC,CA6B/B;AAID;;;GAGG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAcjF;AAID;;;GAGG;AACH,wBAAgB,eAAe,CAAC,aAAa,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,CAOhF;AAID;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAChC,aAAa,EAAE,CAmBjB"}
|
|
@@ -18,7 +18,7 @@ import { DOWNLOAD_TIMEOUT_MS } from "../constants.js";
|
|
|
18
18
|
/**
|
|
19
19
|
* Download an encrypted template bundle from the NEPOPSX API.
|
|
20
20
|
*/
|
|
21
|
-
export async function downloadBundle(cwd, license, agent, version, customInstructions = []) {
|
|
21
|
+
export async function downloadBundle(cwd, license, agent, version, customInstructions = [], providers = []) {
|
|
22
22
|
const apiBase = resolveApiBase(cwd);
|
|
23
23
|
const url = `${apiBase}/templates/${encodeURIComponent(agent)}/${encodeURIComponent(version)}`;
|
|
24
24
|
const response = await fetchWithTimeout(url, {
|
|
@@ -31,6 +31,8 @@ export async function downloadBundle(cwd, license, agent, version, customInstruc
|
|
|
31
31
|
machine_id: license.machine_id,
|
|
32
32
|
workspace: license.workspace ?? "",
|
|
33
33
|
custom_instructions: customInstructions,
|
|
34
|
+
// When set, the backend returns FINAL per-provider files.
|
|
35
|
+
providers,
|
|
34
36
|
}),
|
|
35
37
|
}, DOWNLOAD_TIMEOUT_MS);
|
|
36
38
|
if (!response.ok) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"installer.js","sourceRoot":"","sources":["../../src/licensing/installer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC3E,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAyBtD,+DAA+D;AAE/D;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,GAAW,EACX,OAAgB,EAChB,KAAa,EACb,OAAe,EACf,qBAA0C,EAAE;
|
|
1
|
+
{"version":3,"file":"installer.js","sourceRoot":"","sources":["../../src/licensing/installer.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*
|
|
11
11
|
* In dev mode (NEPOPSX_DEV=1) or for free tier, falls back to local templates.
|
|
12
12
|
*/
|
|
13
|
-
import type { License } from '@nepopsx/core';
|
|
13
|
+
import type { License, OutputProvider } from '@nepopsx/core';
|
|
14
14
|
import type { CustomInstruction } from '../generator/render.js';
|
|
15
15
|
export interface TemplateBundle {
|
|
16
16
|
/** Agent name (e.g., "feature-factory") */
|
|
@@ -28,5 +28,5 @@ export interface TemplateBundle {
|
|
|
28
28
|
*
|
|
29
29
|
* @returns TemplateBundle on success, null on failure (caller should use local fallback)
|
|
30
30
|
*/
|
|
31
|
-
export declare function fetchRemoteTemplates(rootDir: string, license: License, agentName: string, agentVersion: string, customInstructions?: CustomInstruction[]): Promise<TemplateBundle | null>;
|
|
31
|
+
export declare function fetchRemoteTemplates(rootDir: string, license: License, agentName: string, agentVersion: string, customInstructions?: CustomInstruction[], providers?: OutputProvider[]): Promise<TemplateBundle | null>;
|
|
32
32
|
//# sourceMappingURL=template-fetch.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"template-fetch.d.ts","sourceRoot":"","sources":["../../src/licensing/template-fetch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"template-fetch.d.ts","sourceRoot":"","sources":["../../src/licensing/template-fetch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAK7D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAIhE,MAAM,WAAW,cAAc;IAC7B,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,oBAAoB;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,mDAAmD;IACnD,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,sDAAsD;IACtD,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC;CAC5B;AAMD;;;;;GAKG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,kBAAkB,GAAE,iBAAiB,EAAO,EAC5C,SAAS,GAAE,cAAc,EAAO,GAC/B,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAyChC"}
|
|
@@ -22,7 +22,7 @@ import { DOWNLOAD_TIMEOUT_MS } from '../constants.js';
|
|
|
22
22
|
*
|
|
23
23
|
* @returns TemplateBundle on success, null on failure (caller should use local fallback)
|
|
24
24
|
*/
|
|
25
|
-
export async function fetchRemoteTemplates(rootDir, license, agentName, agentVersion, customInstructions = []) {
|
|
25
|
+
export async function fetchRemoteTemplates(rootDir, license, agentName, agentVersion, customInstructions = [], providers = []) {
|
|
26
26
|
const apiBase = resolveApiBase(rootDir);
|
|
27
27
|
try {
|
|
28
28
|
const response = await fetchWithTimeout(`${apiBase}/templates/${agentName}/${agentVersion}`, {
|
|
@@ -35,6 +35,9 @@ export async function fetchRemoteTemplates(rootDir, license, agentName, agentVer
|
|
|
35
35
|
machine_id: license.machine_id,
|
|
36
36
|
workspace: license.workspace,
|
|
37
37
|
custom_instructions: customInstructions,
|
|
38
|
+
// When set, the backend returns FINAL per-provider files (already path-
|
|
39
|
+
// mapped + frontmatter-transformed). The CLI just writes them.
|
|
40
|
+
providers,
|
|
38
41
|
}),
|
|
39
42
|
}, DOWNLOAD_TIMEOUT_MS);
|
|
40
43
|
if (!response.ok) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"template-fetch.js","sourceRoot":"","sources":["../../src/licensing/template-fetch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,aAAa,IAAI,gBAAgB,EAAwB,MAAM,gBAAgB,CAAC;AACzF,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAgBtD,gDAAgD;AAEhD,+DAA+D;AAE/D;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,OAAe,EACf,OAAgB,EAChB,SAAiB,EACjB,YAAoB,EACpB,qBAA0C,EAAE;
|
|
1
|
+
{"version":3,"file":"template-fetch.js","sourceRoot":"","sources":["../../src/licensing/template-fetch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,aAAa,IAAI,gBAAgB,EAAwB,MAAM,gBAAgB,CAAC;AACzF,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAgBtD,gDAAgD;AAEhD,+DAA+D;AAE/D;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,OAAe,EACf,OAAgB,EAChB,SAAiB,EACjB,YAAoB,EACpB,qBAA0C,EAAE,EAC5C,YAA8B,EAAE;IAEhC,MAAM,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;IAExC,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CACrC,GAAG,OAAO,cAAc,SAAS,IAAI,YAAY,EAAE,EACnD;YACE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,eAAe,EAAE,UAAU,OAAO,CAAC,GAAG,EAAE;aACzC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,UAAU,EAAE,OAAO,CAAC,UAAU;gBAC9B,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,mBAAmB,EAAE,kBAAkB;gBACvC,wEAAwE;gBACxE,+DAA+D;gBAC/D,SAAS;aACV,CAAC;SACH,EACD,mBAAmB,CACpB,CAAC;QAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAqB,CAAC;QAC3D,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,CAA2B,CAAC;QAEjG,OAAO;YACL,KAAK,EAAE,SAAS;YAChB,OAAO,EAAE,YAAY;YACrB,SAAS;YACT,MAAM,EAAE,QAAQ;SACjB,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,+DAA+D;QAC/D,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,+DAA+D;AAE/D,8CAA8C;AAE9C,+DAA+D;AAE/D,0DAA0D"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate the `.mcp.json` that registers our own provider-agnostic MCP server
|
|
3
|
+
* (`nepopsx-memory`) so Claude Code — and GitHub Copilot — can call
|
|
4
|
+
* `learning_search` / `learning_store` for governed team recall.
|
|
5
|
+
*
|
|
6
|
+
* Claude Code's remote HTTP MCP form is `{ type: "http", url, headers }`, and it
|
|
7
|
+
* expands `${VAR}` in the config — so we embed the license key as an env
|
|
8
|
+
* placeholder (`${NEPOPSX_LICENSE_KEY}`) rather than the raw secret, keeping the
|
|
9
|
+
* committed `.mcp.json` shareable across the team without leaking the key.
|
|
10
|
+
*/
|
|
11
|
+
export declare const MEMORY_SERVER_NAME = "nepopsx-memory";
|
|
12
|
+
export declare const LICENSE_ENV_VAR = "NEPOPSX_LICENSE_KEY";
|
|
13
|
+
export interface McpHttpServer {
|
|
14
|
+
type: 'http';
|
|
15
|
+
url: string;
|
|
16
|
+
headers: Record<string, string>;
|
|
17
|
+
}
|
|
18
|
+
export interface McpConfigFile {
|
|
19
|
+
mcpServers: Record<string, McpHttpServer>;
|
|
20
|
+
[key: string]: unknown;
|
|
21
|
+
}
|
|
22
|
+
export interface McpSetupOptions {
|
|
23
|
+
rootDir: string;
|
|
24
|
+
/** Backend API base, including `/v1` (e.g. http://localhost:3100/v1). */
|
|
25
|
+
apiUrl: string;
|
|
26
|
+
/** Raw license key — only embedded when `inlineKey` is true (dev convenience). */
|
|
27
|
+
licenseKey?: string;
|
|
28
|
+
/** Embed the raw key instead of the `${NEPOPSX_LICENSE_KEY}` placeholder. */
|
|
29
|
+
inlineKey?: boolean;
|
|
30
|
+
}
|
|
31
|
+
/** Build the `nepopsx-memory` HTTP server entry for `.mcp.json`. */
|
|
32
|
+
export declare function buildMemoryServerEntry(apiUrl: string, opts?: {
|
|
33
|
+
licenseKey?: string;
|
|
34
|
+
inlineKey?: boolean;
|
|
35
|
+
}): McpHttpServer;
|
|
36
|
+
/**
|
|
37
|
+
* Write/merge `.mcp.json` at the workspace root. Preserves any other configured
|
|
38
|
+
* servers and unknown top-level keys; only (re)writes the `nepopsx-memory`
|
|
39
|
+
* entry. Returns the written file paths (relative to rootDir).
|
|
40
|
+
*/
|
|
41
|
+
export declare function generateMcpConfig(options: McpSetupOptions): string[];
|
|
42
|
+
//# sourceMappingURL=config-generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-generator.d.ts","sourceRoot":"","sources":["../../src/mcp/config-generator.ts"],"names":[],"mappings":"AAGA;;;;;;;;;GASG;AAEH,eAAO,MAAM,kBAAkB,mBAAmB,CAAC;AACnD,eAAO,MAAM,eAAe,wBAAwB,CAAC;AAErD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAC1C,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,yEAAyE;IACzE,MAAM,EAAE,MAAM,CAAC;IACf,kFAAkF;IAClF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,oEAAoE;AACpE,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,MAAM,EACd,IAAI,GAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAAO,GACtD,aAAa,CAWf;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,EAAE,CA4BpE"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
/**
|
|
4
|
+
* Generate the `.mcp.json` that registers our own provider-agnostic MCP server
|
|
5
|
+
* (`nepopsx-memory`) so Claude Code — and GitHub Copilot — can call
|
|
6
|
+
* `learning_search` / `learning_store` for governed team recall.
|
|
7
|
+
*
|
|
8
|
+
* Claude Code's remote HTTP MCP form is `{ type: "http", url, headers }`, and it
|
|
9
|
+
* expands `${VAR}` in the config — so we embed the license key as an env
|
|
10
|
+
* placeholder (`${NEPOPSX_LICENSE_KEY}`) rather than the raw secret, keeping the
|
|
11
|
+
* committed `.mcp.json` shareable across the team without leaking the key.
|
|
12
|
+
*/
|
|
13
|
+
export const MEMORY_SERVER_NAME = 'nepopsx-memory';
|
|
14
|
+
export const LICENSE_ENV_VAR = 'NEPOPSX_LICENSE_KEY';
|
|
15
|
+
/** Build the `nepopsx-memory` HTTP server entry for `.mcp.json`. */
|
|
16
|
+
export function buildMemoryServerEntry(apiUrl, opts = {}) {
|
|
17
|
+
const base = apiUrl.replace(/\/+$/, '');
|
|
18
|
+
const token = opts.inlineKey && opts.licenseKey
|
|
19
|
+
? opts.licenseKey
|
|
20
|
+
: '${' + LICENSE_ENV_VAR + '}';
|
|
21
|
+
return {
|
|
22
|
+
type: 'http',
|
|
23
|
+
url: `${base}/mcp`,
|
|
24
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Write/merge `.mcp.json` at the workspace root. Preserves any other configured
|
|
29
|
+
* servers and unknown top-level keys; only (re)writes the `nepopsx-memory`
|
|
30
|
+
* entry. Returns the written file paths (relative to rootDir).
|
|
31
|
+
*/
|
|
32
|
+
export function generateMcpConfig(options) {
|
|
33
|
+
const configPath = join(options.rootDir, '.mcp.json');
|
|
34
|
+
let existing = { mcpServers: {} };
|
|
35
|
+
if (existsSync(configPath)) {
|
|
36
|
+
try {
|
|
37
|
+
const raw = JSON.parse(readFileSync(configPath, 'utf-8'));
|
|
38
|
+
if (raw && typeof raw === 'object') {
|
|
39
|
+
const obj = raw;
|
|
40
|
+
const servers = obj.mcpServers && typeof obj.mcpServers === 'object'
|
|
41
|
+
? obj.mcpServers
|
|
42
|
+
: {};
|
|
43
|
+
existing = { ...obj, mcpServers: { ...servers } };
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
// Malformed config — start fresh rather than throwing mid-install.
|
|
48
|
+
existing = { mcpServers: {} };
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
existing.mcpServers[MEMORY_SERVER_NAME] = buildMemoryServerEntry(options.apiUrl, { licenseKey: options.licenseKey, inlineKey: options.inlineKey });
|
|
52
|
+
writeFileSync(configPath, JSON.stringify(existing, null, 2) + '\n', 'utf-8');
|
|
53
|
+
return ['.mcp.json'];
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=config-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-generator.js","sourceRoot":"","sources":["../../src/mcp/config-generator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC;;;;;;;;;GASG;AAEH,MAAM,CAAC,MAAM,kBAAkB,GAAG,gBAAgB,CAAC;AACnD,MAAM,CAAC,MAAM,eAAe,GAAG,qBAAqB,CAAC;AAuBrD,oEAAoE;AACpE,MAAM,UAAU,sBAAsB,CACpC,MAAc,EACd,OAAqD,EAAE;IAEvD,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACxC,MAAM,KAAK,GACT,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,UAAU;QAC/B,CAAC,CAAC,IAAI,CAAC,UAAU;QACjB,CAAC,CAAC,IAAI,GAAG,eAAe,GAAG,GAAG,CAAC;IACnC,OAAO;QACL,IAAI,EAAE,MAAM;QACZ,GAAG,EAAE,GAAG,IAAI,MAAM;QAClB,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE;KAC9C,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAwB;IACxD,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IAEtD,IAAI,QAAQ,GAAkB,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC;IACjD,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3B,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAY,CAAC;YACrE,IAAI,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;gBACnC,MAAM,GAAG,GAAG,GAA8B,CAAC;gBAC3C,MAAM,OAAO,GACX,GAAG,CAAC,UAAU,IAAI,OAAO,GAAG,CAAC,UAAU,KAAK,QAAQ;oBAClD,CAAC,CAAE,GAAG,CAAC,UAA4C;oBACnD,CAAC,CAAC,EAAE,CAAC;gBACT,QAAQ,GAAG,EAAE,GAAG,GAAG,EAAE,UAAU,EAAE,EAAE,GAAG,OAAO,EAAE,EAAE,CAAC;YACpD,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,mEAAmE;YACnE,QAAQ,GAAG,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC;QAChC,CAAC;IACH,CAAC;IAED,QAAQ,CAAC,UAAU,CAAC,kBAAkB,CAAC,GAAG,sBAAsB,CAC9D,OAAO,CAAC,MAAM,EACd,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CACjE,CAAC;IAEF,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC;IAC7E,OAAO,CAAC,WAAW,CAAC,CAAC;AACvB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-generator.test.d.ts","sourceRoot":"","sources":["../../src/mcp/config-generator.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for optx-package/packages/cli/src/mcp/config-generator.ts
|
|
3
|
+
*
|
|
4
|
+
* Run: pnpm --filter @nepopsx/cli build && pnpm --filter @nepopsx/cli test
|
|
5
|
+
*/
|
|
6
|
+
import { strict as assert } from 'node:assert';
|
|
7
|
+
import { mkdtempSync, readFileSync, writeFileSync, rmSync } from 'node:fs';
|
|
8
|
+
import { join } from 'node:path';
|
|
9
|
+
import { tmpdir } from 'node:os';
|
|
10
|
+
import { describe, it, before, after } from 'node:test';
|
|
11
|
+
import { buildMemoryServerEntry, generateMcpConfig, LICENSE_ENV_VAR, MEMORY_SERVER_NAME, } from './config-generator.js';
|
|
12
|
+
describe('buildMemoryServerEntry', () => {
|
|
13
|
+
it('builds the http MCP entry with /mcp appended and trailing slash stripped', () => {
|
|
14
|
+
const e = buildMemoryServerEntry('http://localhost:3100/v1/');
|
|
15
|
+
assert.equal(e.type, 'http');
|
|
16
|
+
assert.equal(e.url, 'http://localhost:3100/v1/mcp');
|
|
17
|
+
});
|
|
18
|
+
it('uses the env placeholder for the token by default (no raw secret)', () => {
|
|
19
|
+
const e = buildMemoryServerEntry('https://api.nepopsx.dev/v1', {
|
|
20
|
+
licenseKey: 'nepopsx_lic_secret',
|
|
21
|
+
});
|
|
22
|
+
assert.equal(e.headers.Authorization, `Bearer \${${LICENSE_ENV_VAR}}`);
|
|
23
|
+
assert.ok(!e.headers.Authorization.includes('secret'));
|
|
24
|
+
});
|
|
25
|
+
it('inlines the raw key only when inlineKey is set', () => {
|
|
26
|
+
const e = buildMemoryServerEntry('https://api.nepopsx.dev/v1', {
|
|
27
|
+
licenseKey: 'nepopsx_lic_secret',
|
|
28
|
+
inlineKey: true,
|
|
29
|
+
});
|
|
30
|
+
assert.equal(e.headers.Authorization, 'Bearer nepopsx_lic_secret');
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
describe('generateMcpConfig', () => {
|
|
34
|
+
let dir;
|
|
35
|
+
before(() => {
|
|
36
|
+
dir = mkdtempSync(join(tmpdir(), 'nepopsx-mcp-'));
|
|
37
|
+
});
|
|
38
|
+
after(() => {
|
|
39
|
+
rmSync(dir, { recursive: true, force: true });
|
|
40
|
+
});
|
|
41
|
+
it('writes a .mcp.json with the nepopsx-memory server', () => {
|
|
42
|
+
const written = generateMcpConfig({
|
|
43
|
+
rootDir: dir,
|
|
44
|
+
apiUrl: 'http://localhost:3100/v1',
|
|
45
|
+
});
|
|
46
|
+
assert.deepEqual(written, ['.mcp.json']);
|
|
47
|
+
const cfg = JSON.parse(readFileSync(join(dir, '.mcp.json'), 'utf-8'));
|
|
48
|
+
assert.equal(cfg.mcpServers[MEMORY_SERVER_NAME].url, 'http://localhost:3100/v1/mcp');
|
|
49
|
+
});
|
|
50
|
+
it('preserves other configured servers when merging', () => {
|
|
51
|
+
writeFileSync(join(dir, '.mcp.json'), JSON.stringify({
|
|
52
|
+
mcpServers: {
|
|
53
|
+
other: { type: 'http', url: 'https://x/mcp', headers: {} },
|
|
54
|
+
},
|
|
55
|
+
}));
|
|
56
|
+
generateMcpConfig({ rootDir: dir, apiUrl: 'http://localhost:3100/v1' });
|
|
57
|
+
const cfg = JSON.parse(readFileSync(join(dir, '.mcp.json'), 'utf-8'));
|
|
58
|
+
assert.ok(cfg.mcpServers.other, 'other server preserved');
|
|
59
|
+
assert.ok(cfg.mcpServers[MEMORY_SERVER_NAME], 'memory server added');
|
|
60
|
+
});
|
|
61
|
+
it('is idempotent (re-run only rewrites the nepopsx-memory entry)', () => {
|
|
62
|
+
generateMcpConfig({ rootDir: dir, apiUrl: 'http://localhost:3100/v1' });
|
|
63
|
+
const first = readFileSync(join(dir, '.mcp.json'), 'utf-8');
|
|
64
|
+
generateMcpConfig({ rootDir: dir, apiUrl: 'http://localhost:3100/v1' });
|
|
65
|
+
const second = readFileSync(join(dir, '.mcp.json'), 'utf-8');
|
|
66
|
+
assert.equal(first, second);
|
|
67
|
+
});
|
|
68
|
+
it('recovers from a malformed existing file', () => {
|
|
69
|
+
writeFileSync(join(dir, '.mcp.json'), '{ not json');
|
|
70
|
+
const written = generateMcpConfig({
|
|
71
|
+
rootDir: dir,
|
|
72
|
+
apiUrl: 'http://localhost:3100/v1',
|
|
73
|
+
});
|
|
74
|
+
assert.deepEqual(written, ['.mcp.json']);
|
|
75
|
+
const cfg = JSON.parse(readFileSync(join(dir, '.mcp.json'), 'utf-8'));
|
|
76
|
+
assert.ok(cfg.mcpServers[MEMORY_SERVER_NAME]);
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
//# sourceMappingURL=config-generator.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-generator.test.js","sourceRoot":"","sources":["../../src/mcp/config-generator.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { OutputProvider, RufloConfig } from "@nepopsx/core";
|
|
2
|
+
export interface RufloSetupOptions {
|
|
3
|
+
rootDir: string;
|
|
4
|
+
orgSlug: string;
|
|
5
|
+
workspaceSlug: string;
|
|
6
|
+
agent: string;
|
|
7
|
+
providers: OutputProvider[];
|
|
8
|
+
apiUrl: string;
|
|
9
|
+
licenseKey: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Generate `.claude-flow/config.yaml` with memory namespace and MCP server config.
|
|
13
|
+
* Also registers the MCP server with the provider if applicable.
|
|
14
|
+
*/
|
|
15
|
+
export declare function generateRufloConfig(options: RufloSetupOptions): string[];
|
|
16
|
+
/**
|
|
17
|
+
* Build the `ruflo` binding persisted into workspace.yaml and pushed to the
|
|
18
|
+
* backend. Its presence in the workspace config is what activates the
|
|
19
|
+
* `{{#if config.ruflo}}` memory blocks when the backend renders agent templates.
|
|
20
|
+
*/
|
|
21
|
+
export declare function buildRufloBinding(orgSlug: string, workspaceSlug: string): RufloConfig;
|
|
22
|
+
//# sourceMappingURL=config-generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-generator.d.ts","sourceRoot":"","sources":["../../src/ruflo/config-generator.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAMjE,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,cAAc,EAAE,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AAiBD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM,EAAE,CA4ExE;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,MAAM,GACpB,WAAW,CAKb"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { stringify as yamlDump } from "yaml";
|
|
4
|
+
// Pinned ruflo version for the generated MCP launch command. Bump deliberately —
|
|
5
|
+
// ruflo ships multiple releases/day and v4.0 makes strict-mode the default.
|
|
6
|
+
const RUFLO_VERSION = "3.10.45";
|
|
7
|
+
/**
|
|
8
|
+
* Generate `.claude-flow/config.yaml` with memory namespace and MCP server config.
|
|
9
|
+
* Also registers the MCP server with the provider if applicable.
|
|
10
|
+
*/
|
|
11
|
+
export function generateRufloConfig(options) {
|
|
12
|
+
const configDir = join(options.rootDir, ".claude-flow");
|
|
13
|
+
if (!existsSync(configDir)) {
|
|
14
|
+
mkdirSync(configDir, { recursive: true });
|
|
15
|
+
}
|
|
16
|
+
const namespace = `${options.orgSlug}/${options.workspaceSlug}`;
|
|
17
|
+
const config = {
|
|
18
|
+
version: "1.0",
|
|
19
|
+
workspace: {
|
|
20
|
+
org: options.orgSlug,
|
|
21
|
+
workspace: options.workspaceSlug,
|
|
22
|
+
agent: options.agent,
|
|
23
|
+
},
|
|
24
|
+
memory: {
|
|
25
|
+
namespace,
|
|
26
|
+
backend: "hybrid",
|
|
27
|
+
// Ruflo's own direct push to /learnings/auto is DISABLED: this file is
|
|
28
|
+
// committed (only *.db/cache are gitignored), so it must never carry the
|
|
29
|
+
// license-key bearer the endpoint requires — an unauthenticated push just
|
|
30
|
+
// 401s silently. Learnings reach the backend via the authenticated
|
|
31
|
+
// `nepopsx capture` session-end hook instead (see generateCaptureHooks).
|
|
32
|
+
sync: {
|
|
33
|
+
enabled: false,
|
|
34
|
+
endpoint: `${options.apiUrl}/learnings/auto`,
|
|
35
|
+
interval_seconds: 300,
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
mcp: {
|
|
39
|
+
servers: [
|
|
40
|
+
{
|
|
41
|
+
name: "nepopsx-memory",
|
|
42
|
+
transport: "stdio",
|
|
43
|
+
command: "npx",
|
|
44
|
+
// Canonical ruflo MCP launch is `npx ruflo@<version> mcp start` (verified
|
|
45
|
+
// against ruvnet/ruflo). Pinned, not @latest, because ruflo ships multiple
|
|
46
|
+
// builds/day and v4.0 flips strict-mode on. Namespace + sync endpoint are
|
|
47
|
+
// carried in the `memory` block above; verify ruflo reads them from
|
|
48
|
+
// .claude-flow/config.yaml against the pinned version before depending on it.
|
|
49
|
+
args: [`ruflo@${RUFLO_VERSION}`, "mcp", "start"],
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
},
|
|
53
|
+
hooks: {
|
|
54
|
+
// Local, in-process ruflo memory capture (no network) — safe to keep.
|
|
55
|
+
on_task_complete: [
|
|
56
|
+
{
|
|
57
|
+
action: "capture_pattern",
|
|
58
|
+
confidence_threshold: "medium",
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
// No `sync_learnings` here: the authenticated `nepopsx capture` hook owns
|
|
62
|
+
// the session-end push to the backend. A ruflo-driven sync would hit the
|
|
63
|
+
// unauthenticated endpoint above and 401.
|
|
64
|
+
on_session_end: [],
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
const configPath = join(configDir, "config.yaml");
|
|
68
|
+
writeFileSync(configPath, yamlDump(config, { lineWidth: 120 }), "utf-8");
|
|
69
|
+
const writtenFiles = [".claude-flow/config.yaml"];
|
|
70
|
+
// Generate .claude-flow/.gitignore if it doesn't exist
|
|
71
|
+
const gitignorePath = join(configDir, ".gitignore");
|
|
72
|
+
if (!existsSync(gitignorePath)) {
|
|
73
|
+
writeFileSync(gitignorePath, "# Local ruflo state — not committed\n*.db\n*.sqlite\ncache/\n", "utf-8");
|
|
74
|
+
writtenFiles.push(".claude-flow/.gitignore");
|
|
75
|
+
}
|
|
76
|
+
return writtenFiles;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Build the `ruflo` binding persisted into workspace.yaml and pushed to the
|
|
80
|
+
* backend. Its presence in the workspace config is what activates the
|
|
81
|
+
* `{{#if config.ruflo}}` memory blocks when the backend renders agent templates.
|
|
82
|
+
*/
|
|
83
|
+
export function buildRufloBinding(orgSlug, workspaceSlug) {
|
|
84
|
+
return {
|
|
85
|
+
enabled: true,
|
|
86
|
+
namespace: `${orgSlug}/${workspaceSlug}`,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=config-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-generator.js","sourceRoot":"","sources":["../../src/ruflo/config-generator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,IAAI,QAAQ,EAAE,MAAM,MAAM,CAAC;AAG7C,iFAAiF;AACjF,4EAA4E;AAC5E,MAAM,aAAa,GAAG,SAAS,CAAC;AA2BhC;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAA0B;IAC5D,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;IACxD,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3B,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,CAAC;IAED,MAAM,SAAS,GAAG,GAAG,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;IAEhE,MAAM,MAAM,GAAqB;QAC/B,OAAO,EAAE,KAAK;QACd,SAAS,EAAE;YACT,GAAG,EAAE,OAAO,CAAC,OAAO;YACpB,SAAS,EAAE,OAAO,CAAC,aAAa;YAChC,KAAK,EAAE,OAAO,CAAC,KAAK;SACrB;QACD,MAAM,EAAE;YACN,SAAS;YACT,OAAO,EAAE,QAAQ;YACjB,uEAAuE;YACvE,yEAAyE;YACzE,0EAA0E;YAC1E,mEAAmE;YACnE,yEAAyE;YACzE,IAAI,EAAE;gBACJ,OAAO,EAAE,KAAK;gBACd,QAAQ,EAAE,GAAG,OAAO,CAAC,MAAM,iBAAiB;gBAC5C,gBAAgB,EAAE,GAAG;aACtB;SACF;QACD,GAAG,EAAE;YACH,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,gBAAgB;oBACtB,SAAS,EAAE,OAAO;oBAClB,OAAO,EAAE,KAAK;oBACd,0EAA0E;oBAC1E,2EAA2E;oBAC3E,0EAA0E;oBAC1E,oEAAoE;oBACpE,8EAA8E;oBAC9E,IAAI,EAAE,CAAC,SAAS,aAAa,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC;iBACjD;aACF;SACF;QACD,KAAK,EAAE;YACL,sEAAsE;YACtE,gBAAgB,EAAE;gBAChB;oBACE,MAAM,EAAE,iBAAiB;oBACzB,oBAAoB,EAAE,QAAQ;iBAC/B;aACF;YACD,0EAA0E;YAC1E,yEAAyE;YACzE,0CAA0C;YAC1C,cAAc,EAAE,EAAE;SACnB;KACF,CAAC;IAEF,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;IAClD,aAAa,CAAC,UAAU,EAAE,QAAQ,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC;IAEzE,MAAM,YAAY,GAAG,CAAC,0BAA0B,CAAC,CAAC;IAElD,uDAAuD;IACvD,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;IACpD,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QAC/B,aAAa,CACX,aAAa,EACb,+DAA+D,EAC/D,OAAO,CACR,CAAC;QACF,YAAY,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;IAC/C,CAAC;IAED,OAAO,YAAY,CAAC;AACtB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAC/B,OAAe,EACf,aAAqB;IAErB,OAAO;QACL,OAAO,EAAE,IAAI;QACb,SAAS,EAAE,GAAG,OAAO,IAAI,aAAa,EAAE;KACzC,CAAC;AACJ,CAAC"}
|