@nepopsx/cli 0.0.3 → 0.0.5

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 (168) hide show
  1. package/dist/agents/configuration.d.ts +9 -0
  2. package/dist/agents/configuration.d.ts.map +1 -0
  3. package/dist/agents/configuration.js +57 -0
  4. package/dist/agents/configuration.js.map +1 -0
  5. package/dist/agents/remote-config.d.ts +30 -0
  6. package/dist/agents/remote-config.d.ts.map +1 -0
  7. package/dist/agents/remote-config.js +102 -0
  8. package/dist/agents/remote-config.js.map +1 -0
  9. package/dist/commands/activate.d.ts.map +1 -1
  10. package/dist/commands/activate.js +4 -3
  11. package/dist/commands/activate.js.map +1 -1
  12. package/dist/commands/decode.js +2 -2
  13. package/dist/commands/decode.js.map +1 -1
  14. package/dist/commands/doctor.js +16 -16
  15. package/dist/commands/doctor.js.map +1 -1
  16. package/dist/commands/init.d.ts.map +1 -1
  17. package/dist/commands/init.js +353 -18
  18. package/dist/commands/init.js.map +1 -1
  19. package/dist/commands/install.d.ts +1 -0
  20. package/dist/commands/install.d.ts.map +1 -1
  21. package/dist/commands/install.js +253 -25
  22. package/dist/commands/install.js.map +1 -1
  23. package/dist/commands/login.d.ts +6 -0
  24. package/dist/commands/login.d.ts.map +1 -0
  25. package/dist/commands/login.js +108 -0
  26. package/dist/commands/login.js.map +1 -0
  27. package/dist/commands/push-learnings.d.ts +14 -0
  28. package/dist/commands/push-learnings.d.ts.map +1 -0
  29. package/dist/commands/push-learnings.js +186 -0
  30. package/dist/commands/push-learnings.js.map +1 -0
  31. package/dist/commands/scan.d.ts +2 -0
  32. package/dist/commands/scan.d.ts.map +1 -0
  33. package/dist/commands/scan.js +520 -0
  34. package/dist/commands/scan.js.map +1 -0
  35. package/dist/commands/sync.d.ts +2 -0
  36. package/dist/commands/sync.d.ts.map +1 -1
  37. package/dist/commands/sync.js +203 -234
  38. package/dist/commands/sync.js.map +1 -1
  39. package/dist/config/api-config.d.ts.map +1 -1
  40. package/dist/config/api-config.js +4 -0
  41. package/dist/config/api-config.js.map +1 -1
  42. package/dist/constants.d.ts +7 -0
  43. package/dist/constants.d.ts.map +1 -0
  44. package/dist/constants.js +7 -0
  45. package/dist/constants.js.map +1 -0
  46. package/dist/customs/instructions.d.ts +3 -0
  47. package/dist/customs/instructions.d.ts.map +1 -0
  48. package/dist/customs/instructions.js +51 -0
  49. package/dist/customs/instructions.js.map +1 -0
  50. package/dist/enrichment/confirm.d.ts +17 -0
  51. package/dist/enrichment/confirm.d.ts.map +1 -0
  52. package/dist/enrichment/confirm.js +44 -0
  53. package/dist/enrichment/confirm.js.map +1 -0
  54. package/dist/enrichment/state.d.ts +8 -0
  55. package/dist/enrichment/state.d.ts.map +1 -0
  56. package/dist/enrichment/state.js +107 -0
  57. package/dist/enrichment/state.js.map +1 -0
  58. package/dist/enrichment/types.d.ts +13 -0
  59. package/dist/enrichment/types.d.ts.map +1 -0
  60. package/dist/enrichment/types.js +2 -0
  61. package/dist/enrichment/types.js.map +1 -0
  62. package/dist/enrichment/workflow.d.ts +35 -0
  63. package/dist/enrichment/workflow.d.ts.map +1 -0
  64. package/dist/enrichment/workflow.js +305 -0
  65. package/dist/enrichment/workflow.js.map +1 -0
  66. package/dist/generator/builtin-templates.d.ts +2 -1
  67. package/dist/generator/builtin-templates.d.ts.map +1 -1
  68. package/dist/generator/builtin-templates.js +161 -2
  69. package/dist/generator/builtin-templates.js.map +1 -1
  70. package/dist/generator/package-renderer.d.ts +29 -0
  71. package/dist/generator/package-renderer.d.ts.map +1 -0
  72. package/dist/generator/package-renderer.js +123 -0
  73. package/dist/generator/package-renderer.js.map +1 -0
  74. package/dist/generator/render.d.ts +14 -63
  75. package/dist/generator/render.d.ts.map +1 -1
  76. package/dist/generator/render.js +30 -176
  77. package/dist/generator/render.js.map +1 -1
  78. package/dist/index.js +42 -2
  79. package/dist/index.js.map +1 -1
  80. package/dist/licensing/installer.d.ts +51 -0
  81. package/dist/licensing/installer.d.ts.map +1 -0
  82. package/dist/licensing/installer.js +112 -0
  83. package/dist/licensing/installer.js.map +1 -0
  84. package/dist/licensing/license-manager.d.ts +6 -0
  85. package/dist/licensing/license-manager.d.ts.map +1 -1
  86. package/dist/licensing/license-manager.js +12 -35
  87. package/dist/licensing/license-manager.js.map +1 -1
  88. package/dist/licensing/template-fetch.d.ts +3 -2
  89. package/dist/licensing/template-fetch.d.ts.map +1 -1
  90. package/dist/licensing/template-fetch.js +10 -41
  91. package/dist/licensing/template-fetch.js.map +1 -1
  92. package/dist/scan/__tests__/context-gatherer.test.d.ts +2 -0
  93. package/dist/scan/__tests__/context-gatherer.test.d.ts.map +1 -0
  94. package/dist/scan/__tests__/context-gatherer.test.js +111 -0
  95. package/dist/scan/__tests__/context-gatherer.test.js.map +1 -0
  96. package/dist/scan/__tests__/merge.test.d.ts +2 -0
  97. package/dist/scan/__tests__/merge.test.d.ts.map +1 -0
  98. package/dist/scan/__tests__/merge.test.js +163 -0
  99. package/dist/scan/__tests__/merge.test.js.map +1 -0
  100. package/dist/scan/auto-bootstrap.d.ts +3 -0
  101. package/dist/scan/auto-bootstrap.d.ts.map +1 -0
  102. package/dist/scan/auto-bootstrap.js +30 -0
  103. package/dist/scan/auto-bootstrap.js.map +1 -0
  104. package/dist/scan/config.d.ts +24 -0
  105. package/dist/scan/config.d.ts.map +1 -0
  106. package/dist/scan/config.js +77 -0
  107. package/dist/scan/config.js.map +1 -0
  108. package/dist/scan/context/gatherer.d.ts +13 -0
  109. package/dist/scan/context/gatherer.d.ts.map +1 -0
  110. package/dist/scan/context/gatherer.js +97 -0
  111. package/dist/scan/context/gatherer.js.map +1 -0
  112. package/dist/scan/context/gitignore.d.ts +9 -0
  113. package/dist/scan/context/gitignore.d.ts.map +1 -0
  114. package/dist/scan/context/gitignore.js +50 -0
  115. package/dist/scan/context/gitignore.js.map +1 -0
  116. package/dist/scan/context/patterns.d.ts +14 -0
  117. package/dist/scan/context/patterns.d.ts.map +1 -0
  118. package/dist/scan/context/patterns.js +159 -0
  119. package/dist/scan/context/patterns.js.map +1 -0
  120. package/dist/scan/customs/writer.d.ts +6 -0
  121. package/dist/scan/customs/writer.d.ts.map +1 -0
  122. package/dist/scan/customs/writer.js +149 -0
  123. package/dist/scan/customs/writer.js.map +1 -0
  124. package/dist/scan/llm/anthropic.d.ts +11 -0
  125. package/dist/scan/llm/anthropic.d.ts.map +1 -0
  126. package/dist/scan/llm/anthropic.js +89 -0
  127. package/dist/scan/llm/anthropic.js.map +1 -0
  128. package/dist/scan/llm/factory.d.ts +4 -0
  129. package/dist/scan/llm/factory.d.ts.map +1 -0
  130. package/dist/scan/llm/factory.js +20 -0
  131. package/dist/scan/llm/factory.js.map +1 -0
  132. package/dist/scan/llm/ollama.d.ts +11 -0
  133. package/dist/scan/llm/ollama.d.ts.map +1 -0
  134. package/dist/scan/llm/ollama.js +64 -0
  135. package/dist/scan/llm/ollama.js.map +1 -0
  136. package/dist/scan/llm/openai.d.ts +12 -0
  137. package/dist/scan/llm/openai.d.ts.map +1 -0
  138. package/dist/scan/llm/openai.js +78 -0
  139. package/dist/scan/llm/openai.js.map +1 -0
  140. package/dist/scan/llm/types.d.ts +23 -0
  141. package/dist/scan/llm/types.d.ts.map +1 -0
  142. package/dist/scan/llm/types.js +3 -0
  143. package/dist/scan/llm/types.js.map +1 -0
  144. package/dist/scan/merge/diff-display.d.ts +11 -0
  145. package/dist/scan/merge/diff-display.d.ts.map +1 -0
  146. package/dist/scan/merge/diff-display.js +72 -0
  147. package/dist/scan/merge/diff-display.js.map +1 -0
  148. package/dist/scan/prompt/agent.d.ts +23 -0
  149. package/dist/scan/prompt/agent.d.ts.map +1 -0
  150. package/dist/scan/prompt/agent.js +95 -0
  151. package/dist/scan/prompt/agent.js.map +1 -0
  152. package/dist/scan/prompt/builder.d.ts +16 -0
  153. package/dist/scan/prompt/builder.d.ts.map +1 -0
  154. package/dist/scan/prompt/builder.js +64 -0
  155. package/dist/scan/prompt/builder.js.map +1 -0
  156. package/dist/scan/prompt/schema.d.ts +7 -0
  157. package/dist/scan/prompt/schema.d.ts.map +1 -0
  158. package/dist/scan/prompt/schema.js +52 -0
  159. package/dist/scan/prompt/schema.js.map +1 -0
  160. package/dist/security/scanner.d.ts +3 -40
  161. package/dist/security/scanner.d.ts.map +1 -1
  162. package/dist/security/scanner.js +3 -169
  163. package/dist/security/scanner.js.map +1 -1
  164. package/dist/utils/fetch.d.ts +9 -0
  165. package/dist/utils/fetch.d.ts.map +1 -0
  166. package/dist/utils/fetch.js +18 -0
  167. package/dist/utils/fetch.js.map +1 -0
  168. package/package.json +15 -12
@@ -1,29 +1,257 @@
1
- import chalk from 'chalk';
1
+ import chalk from "chalk";
2
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
3
+ import { resolve } from "node:path";
4
+ import { cwd } from "node:process";
5
+ import { parse, stringify } from "yaml";
6
+ import { validateWorkspaceConfig, generateFingerprint, TIER_LIMITS, } from "@nepopsx/core";
7
+ import { readLicense } from "../licensing/license-manager.js";
8
+ import { downloadBundle, decryptBundle, verifyBundleSha, } from "../licensing/installer.js";
9
+ import { getAgentConfigPath, getAgentSupportOperations, } from "../agents/configuration.js";
10
+ import { loadLocalAgentConfig, pushRemoteAgentConfig, pushRemoteWorkspaceConfig, } from '../agents/remote-config.js';
11
+ import { loadCustomInstructions } from '../customs/instructions.js';
12
+ import { readLocalEnrichmentState, retargetEnrichmentMetadata, writeLocalEnrichmentState, } from '../enrichment/state.js';
13
+ import { checkEnrichmentGate, checkAgentEnrichmentGate, enrichSingleAgent, } from '../enrichment/workflow.js';
14
+ import { renderBundleForInstall } from "../generator/package-renderer.js";
15
+ import { setWatermarkData, applyLicenseWatermark, } from "../generator/render.js";
16
+ import { writeGeneratedFiles, printWriteResult } from "../generator/writer.js";
17
+ import { generateManifest } from "../security/index.js";
18
+ const AGENT_NAME_RE = /^[a-z][a-z0-9-]*$/;
19
+ const WORKSPACE_CONFIG = ".nepopsx/workspace.yaml";
2
20
  export async function installCommand(agent, options) {
3
- const knownAgents = {
4
- 'feature-factory': '@nepopsx/agent-feature-factory',
5
- 'sdlc-orchestrator': '@nepopsx/agent-sdlc-orchestrator',
6
- 'qa-commander': '@nepopsx/agent-qa-commander',
7
- 'code-review-guardian': '@nepopsx/agent-code-review-guardian',
21
+ if (!AGENT_NAME_RE.test(agent)) {
22
+ console.error(chalk.red(`Invalid agent name: "${agent}"`), chalk.dim("(must be lowercase kebab-case, e.g. feature-factory)"));
23
+ process.exit(1);
24
+ }
25
+ const rootDir = cwd();
26
+ // License check
27
+ const license = readLicense(rootDir);
28
+ if (!license) {
29
+ console.error(chalk.red("No active license found."), chalk.dim("\nRun `nepopsx activate <key>` to activate a license first."));
30
+ process.exit(1);
31
+ return;
32
+ }
33
+ const activeLicense = license;
34
+ // Workspace config is required for template rendering context
35
+ const configPath = resolve(rootDir, WORKSPACE_CONFIG);
36
+ if (!existsSync(configPath)) {
37
+ console.error(chalk.red("Workspace config not found."), chalk.dim(`\nRun ${chalk.cyan("nepopsx init")} first.`));
38
+ process.exit(1);
39
+ }
40
+ const requestedVersion = normalizeRequestedVersion(options.version);
41
+ // ── Enrichment gate check ──────────────────────────────────
42
+ const gateResult = checkEnrichmentGate(rootDir);
43
+ if (!gateResult.ready) {
44
+ console.error(chalk.red(`\n🔍 ${gateResult.reason}`));
45
+ console.log(chalk.dim('\n Before installing an agent, your workspace needs to be scanned'));
46
+ console.log(chalk.dim(' so the agent templates are customized to your codebase.\n'));
47
+ console.log(` Run: ${chalk.cyan('nepopsx scan')}\n`);
48
+ process.exit(1);
49
+ return;
50
+ }
51
+ const workspaceEnrichment = gateResult.workspaceEnrichment;
52
+ let { localState } = gateResult;
53
+ // Check if this specific agent needs enrichment
54
+ const localAgentConfig = loadLocalAgentConfig(rootDir, agent, gateResult.config.agents?.[agent]);
55
+ let agentEnrichment = localState.agents[agent];
56
+ if (localAgentConfig) {
57
+ const agentGate = checkAgentEnrichmentGate(localState, agent, localAgentConfig);
58
+ if (!agentGate.ready) {
59
+ // Workspace is enriched but agent isn't — auto-enrich this single agent
60
+ console.log(chalk.yellow(`\n⚠ Agent "${agent}" needs enrichment before install.`));
61
+ console.log(chalk.dim(' Your workspace is already enriched. Running agent-only enrichment...\n'));
62
+ try {
63
+ const result = await enrichSingleAgent(rootDir, activeLicense, agent, requestedVersion ?? 'latest', gateResult.config, localState, workspaceEnrichment, { yes: options.yes });
64
+ agentEnrichment = result.enrichment;
65
+ // Re-read local state since enrichSingleAgent writes it
66
+ localState = readLocalEnrichmentState(rootDir);
67
+ }
68
+ catch (error) {
69
+ console.error(chalk.red('Agent enrichment failed:'), error instanceof Error ? error.message : String(error));
70
+ process.exit(1);
71
+ return;
72
+ }
73
+ }
74
+ else {
75
+ agentEnrichment = agentGate.enrichment;
76
+ }
77
+ }
78
+ else {
79
+ // No local config yet — this is a fresh install, agent will need enrichment
80
+ try {
81
+ const result = await enrichSingleAgent(rootDir, activeLicense, agent, requestedVersion ?? 'latest', gateResult.config, localState, workspaceEnrichment, { yes: options.yes });
82
+ agentEnrichment = result.enrichment;
83
+ localState = readLocalEnrichmentState(rootDir);
84
+ }
85
+ catch (error) {
86
+ console.error(chalk.red('Agent enrichment failed:'), error instanceof Error ? error.message : String(error));
87
+ process.exit(1);
88
+ return;
89
+ }
90
+ }
91
+ const rawConfig = parse(readFileSync(configPath, "utf-8"));
92
+ const validation = validateWorkspaceConfig(rawConfig);
93
+ if (!validation.valid) {
94
+ console.error(chalk.red("Invalid workspace config:"));
95
+ for (const err of validation.errors) {
96
+ console.error(chalk.red(` ✗ ${err}`));
97
+ }
98
+ process.exit(1);
99
+ }
100
+ const config = validation.config;
101
+ // ── Plan limit checks ──────────────────────────────────────────
102
+ const limits = TIER_LIMITS[activeLicense.tier];
103
+ // Agent count: count currently installed agents from the config
104
+ const installedAgentCount = config.agents
105
+ ? Object.values(config.agents).filter((a) => a.enabled).length
106
+ : 0;
107
+ const isAlreadyInstalled = config.agents && agent in config.agents;
108
+ if (!isAlreadyInstalled && installedAgentCount >= limits.max_agents) {
109
+ console.error(chalk.red(`Plan limit reached: your ${activeLicense.tier} plan allows ${limits.max_agents} agent package(s).`));
110
+ console.error(chalk.dim(`You have ${installedAgentCount} installed. Upgrade to install more: https://nepopsx.io/pricing`));
111
+ process.exit(1);
112
+ return;
113
+ }
114
+ console.log(chalk.bold.cyan(`\nInstalling ${agent}@${requestedVersion ?? "latest"}...\n`));
115
+ const bootstrapRawConfig = patchWorkspaceAgents(rawConfig, agent, requestedVersion, getAgentConfigPath(agent, config.agents?.[agent]));
116
+ const bootstrapValidation = validateWorkspaceConfig(bootstrapRawConfig);
117
+ if (!bootstrapValidation.valid) {
118
+ console.error(chalk.red("Updated workspace config would be invalid:"));
119
+ for (const err of bootstrapValidation.errors) {
120
+ console.error(chalk.red(` ✗ ${err}`));
121
+ }
122
+ process.exit(1);
123
+ }
124
+ const bootstrapWorkspaceEnrichment = retargetEnrichmentMetadata(workspaceEnrichment, bootstrapValidation.config);
125
+ await pushRemoteWorkspaceConfig(rootDir, activeLicense.key, bootstrapValidation.config, bootstrapWorkspaceEnrichment);
126
+ const customInstructions = loadCustomInstructions(resolve(rootDir, config.customs_dir ?? 'customs'));
127
+ const existingAgentConfig = loadLocalAgentConfig(rootDir, agent, config.agents?.[agent]);
128
+ if (existingAgentConfig && agentEnrichment) {
129
+ await pushRemoteAgentConfig(rootDir, activeLicense.key, agent, existingAgentConfig, activeLicense.workspace, agentEnrichment);
130
+ }
131
+ // Download → decrypt → verify
132
+ let encBundle = null;
133
+ try {
134
+ encBundle = await downloadBundle(rootDir, activeLicense, agent, requestedVersion ?? "latest", customInstructions);
135
+ }
136
+ catch (err) {
137
+ console.error(chalk.red("Download failed:"), err instanceof Error ? err.message : String(err));
138
+ process.exit(1);
139
+ return;
140
+ }
141
+ if (!encBundle) {
142
+ return;
143
+ }
144
+ let decryptedJson = null;
145
+ try {
146
+ decryptedJson = decryptBundle(encBundle, activeLicense.key);
147
+ }
148
+ catch (err) {
149
+ console.error(chalk.red("Decryption failed:"), err instanceof Error ? err.message : String(err));
150
+ process.exit(1);
151
+ return;
152
+ }
153
+ if (!decryptedJson) {
154
+ return;
155
+ }
156
+ try {
157
+ verifyBundleSha(decryptedJson, encBundle.sha256);
158
+ }
159
+ catch (err) {
160
+ console.error(chalk.red("Integrity check failed:"), err instanceof Error ? err.message : String(err));
161
+ process.exit(1);
162
+ }
163
+ const templates = JSON.parse(decryptedJson);
164
+ const resolvedVersion = encBundle.version;
165
+ const updatedRawConfig = patchWorkspaceAgents(rawConfig, agent, resolvedVersion, getAgentConfigPath(agent, config.agents?.[agent]));
166
+ const updatedValidation = validateWorkspaceConfig(updatedRawConfig);
167
+ if (!updatedValidation.valid) {
168
+ console.error(chalk.red("Resolved workspace config would be invalid:"));
169
+ for (const err of updatedValidation.errors) {
170
+ console.error(chalk.red(` ✗ ${err}`));
171
+ }
172
+ process.exit(1);
173
+ }
174
+ if (resolvedVersion !== (requestedVersion ?? resolvedVersion)) {
175
+ const resolvedWorkspaceEnrichment = retargetEnrichmentMetadata(workspaceEnrichment, updatedValidation.config);
176
+ await pushRemoteWorkspaceConfig(rootDir, activeLicense.key, updatedValidation.config, resolvedWorkspaceEnrichment);
177
+ if (existingAgentConfig && agentEnrichment) {
178
+ await pushRemoteAgentConfig(rootDir, activeLicense.key, agent, existingAgentConfig, activeLicense.workspace, agentEnrichment);
179
+ }
180
+ }
181
+ // Set up watermark so generated files are fingerprinted
182
+ const fingerprint = generateFingerprint(activeLicense.org, activeLicense.key, activeLicense.workspace ?? "");
183
+ const watermarkData = {
184
+ version: "0.1.0",
185
+ org: activeLicense.org,
186
+ plan: activeLicense.tier,
187
+ valid_until: activeLicense.valid_until,
188
+ fingerprint,
189
+ };
190
+ setWatermarkData(watermarkData);
191
+ // Render templates into write operations
192
+ const bundle = {
193
+ agent,
194
+ version: resolvedVersion,
195
+ templates,
196
+ source: "remote",
8
197
  };
9
- const pkg = knownAgents[agent];
10
- if (!pkg) {
11
- console.log(chalk.red(`Unknown agent: "${agent}"`));
12
- console.log(chalk.dim(`Available agents: ${Object.keys(knownAgents).join(', ')}`));
13
- process.exit(1);
14
- }
15
- const version = options.version ?? 'latest';
16
- console.log(chalk.cyan(`\nInstalling ${pkg}@${version}...`));
17
- // TODO: In full implementation, this will:
18
- // 1. npm install / download the agent package
19
- // 2. Add the agent to .nepopsx/workspace.yaml
20
- // 3. Run nepopsx sync to generate files
21
- console.log(chalk.yellow('\n⚠ Agent registry not yet connected. For now, add the agent manually to .nepopsx/workspace.yaml:'));
22
- console.log(chalk.dim(`
23
- agents:
24
- ${agent}:
25
- enabled: true
26
- `));
27
- console.log(chalk.dim(`Then run: ${chalk.cyan('nepopsx sync')}\n`));
198
+ const operations = [
199
+ ...getAgentSupportOperations(rootDir, bundle, agent, config.agents?.[agent]),
200
+ ...renderBundleForInstall(bundle),
201
+ ];
202
+ // Apply watermark to all rendered files
203
+ for (const op of operations) {
204
+ op.content = applyLicenseWatermark(op.content, op.path);
205
+ }
206
+ // Reset global watermark state
207
+ setWatermarkData(null);
208
+ // Write files (diff-aware skips unchanged)
209
+ const result = writeGeneratedFiles(rootDir, operations, false);
210
+ printWriteResult(result, false);
211
+ writeFileSync(configPath, stringify(updatedRawConfig, { lineWidth: 120 }), "utf-8");
212
+ const localEnrichmentState = readLocalEnrichmentState(rootDir);
213
+ localEnrichmentState.workspace = retargetEnrichmentMetadata(workspaceEnrichment, updatedValidation.config);
214
+ if (agentEnrichment) {
215
+ localEnrichmentState.agents[agent] = agentEnrichment;
216
+ }
217
+ writeLocalEnrichmentState(rootDir, localEnrichmentState);
218
+ console.log(chalk.dim(`\nWorkspace config updated: agents.${agent} enabled`));
219
+ // Update integrity manifest for installed files
220
+ const allFiles = operations.map((op) => ({ path: op.path, content: op.content }));
221
+ const manifest = generateManifest(rootDir, allFiles);
222
+ console.log(chalk.dim(`Integrity manifest: ${manifest.length} file(s) hashed → .nepopsx/manifest.sha256`));
223
+ console.log(chalk.bold.green(`\n✅ Installed ${agent}@${resolvedVersion}\n`));
224
+ }
225
+ /**
226
+ * Add or update the agent entry in workspace.yaml agents section.
227
+ * Preserves all other config keys and existing agent entries.
228
+ */
229
+ function patchWorkspaceAgents(rawConfig, agentName, version, agentConfigPath) {
230
+ const updatedConfig = { ...rawConfig };
231
+ const agents = (typeof rawConfig.agents === "object" && rawConfig.agents !== null
232
+ ? rawConfig.agents
233
+ : {});
234
+ const existing = (typeof agents[agentName] === 'object' && agents[agentName] !== null
235
+ ? agents[agentName]
236
+ : {});
237
+ const { config: _inlineConfig, ...existingWithoutInlineConfig } = existing;
238
+ agents[agentName] = {
239
+ ...existingWithoutInlineConfig,
240
+ enabled: true,
241
+ ...(typeof version === 'string' ? { version } : {}),
242
+ config_path: typeof existing.config_path === 'string' ? existing.config_path : agentConfigPath,
243
+ };
244
+ updatedConfig.agents = agents;
245
+ return updatedConfig;
246
+ }
247
+ function normalizeRequestedVersion(version) {
248
+ if (typeof version !== 'string') {
249
+ return undefined;
250
+ }
251
+ const trimmedVersion = version.trim();
252
+ if (trimmedVersion.length === 0 || trimmedVersion === 'latest') {
253
+ return undefined;
254
+ }
255
+ return trimmedVersion;
28
256
  }
29
257
  //# sourceMappingURL=install.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/commands/install.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAM1B,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,KAAa,EAAE,OAAuB;IACzE,MAAM,WAAW,GAA2B;QAC1C,iBAAiB,EAAE,gCAAgC;QACnD,mBAAmB,EAAE,kCAAkC;QACvD,cAAc,EAAE,6BAA6B;QAC7C,sBAAsB,EAAE,qCAAqC;KAC9D,CAAC;IAEF,MAAM,GAAG,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;IAC/B,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,mBAAmB,KAAK,GAAG,CAAC,CAAC,CAAC;QACpD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,qBAAqB,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QACnF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,QAAQ,CAAC;IAC5C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,gBAAgB,GAAG,IAAI,OAAO,KAAK,CAAC,CAAC,CAAC;IAE7D,2CAA2C;IAC3C,8CAA8C;IAC9C,8CAA8C;IAC9C,wCAAwC;IAExC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,mGAAmG,CAAC,CAAC,CAAC;IAC/H,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC;;MAElB,KAAK;;CAEV,CAAC,CAAC,CAAC;IACF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,aAAa,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC;AACtE,CAAC"}
1
+ {"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/commands/install.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ interface LoginOptions {
2
+ email?: string;
3
+ }
4
+ export declare function loginCommand(options: LoginOptions): Promise<void>;
5
+ export {};
6
+ //# sourceMappingURL=login.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAWA,UAAU,YAAY;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA4ED,wBAAsB,YAAY,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAqDvE"}
@@ -0,0 +1,108 @@
1
+ import chalk from "chalk";
2
+ import { createInterface } from "node:readline";
3
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
4
+ import { join } from "node:path";
5
+ import { cwd } from "node:process";
6
+ import { resolveApiBase } from "../config/api-config.js";
7
+ import { API_TIMEOUT_MS } from "../constants.js";
8
+ const NEPOPSX_DIR = ".nepopsx";
9
+ const CONFIG_FILE = "config.json";
10
+ async function prompt(question, hidden = false) {
11
+ const rl = createInterface({
12
+ input: process.stdin,
13
+ output: process.stdout,
14
+ });
15
+ return new Promise((resolve) => {
16
+ if (hidden && process.stdin.isTTY) {
17
+ process.stdout.write(question);
18
+ process.stdin.setRawMode(true);
19
+ process.stdin.resume();
20
+ let value = "";
21
+ process.stdin.on("data", function onData(char) {
22
+ const ch = char.toString("utf-8");
23
+ if (ch === "\n" || ch === "\r" || ch === "\u0004") {
24
+ process.stdin.setRawMode(false);
25
+ process.stdin.pause();
26
+ process.stdin.removeListener("data", onData);
27
+ process.stdout.write("\n");
28
+ rl.close();
29
+ resolve(value);
30
+ }
31
+ else if (ch === "\u0003") {
32
+ process.stdout.write("\n");
33
+ process.exit(0);
34
+ }
35
+ else if (ch === "\u007f") {
36
+ value = value.slice(0, -1);
37
+ }
38
+ else {
39
+ value += ch;
40
+ }
41
+ });
42
+ }
43
+ else {
44
+ rl.question(question, (answer) => {
45
+ rl.close();
46
+ resolve(answer);
47
+ });
48
+ }
49
+ });
50
+ }
51
+ function writeConfig(rootDir, patch) {
52
+ const configPath = join(rootDir, NEPOPSX_DIR, CONFIG_FILE);
53
+ let existing = {};
54
+ if (existsSync(configPath)) {
55
+ try {
56
+ existing = JSON.parse(readFileSync(configPath, "utf-8"));
57
+ }
58
+ catch {
59
+ /* start fresh */
60
+ }
61
+ }
62
+ const merged = { ...existing, ...patch };
63
+ mkdirSync(join(rootDir, NEPOPSX_DIR), { recursive: true });
64
+ writeFileSync(configPath, JSON.stringify(merged, null, 2) + "\n", "utf-8");
65
+ }
66
+ export async function loginCommand(options) {
67
+ const rootDir = cwd();
68
+ const email = options.email ?? (await prompt("Email: "));
69
+ const password = await prompt("Password: ", true);
70
+ if (!email || !password) {
71
+ console.error(chalk.red("Email and password are required."));
72
+ process.exit(1);
73
+ }
74
+ const apiBase = resolveApiBase(rootDir);
75
+ const controller = new AbortController();
76
+ const timer = setTimeout(() => controller.abort(), API_TIMEOUT_MS);
77
+ let response;
78
+ try {
79
+ response = await fetch(`${apiBase}/auth/login`, {
80
+ method: "POST",
81
+ headers: { "Content-Type": "application/json" },
82
+ body: JSON.stringify({ email, password }),
83
+ signal: controller.signal,
84
+ });
85
+ }
86
+ catch (err) {
87
+ console.error(chalk.red("Login failed:"), err instanceof Error ? err.message : String(err));
88
+ process.exit(1);
89
+ }
90
+ finally {
91
+ clearTimeout(timer);
92
+ }
93
+ if (!response.ok) {
94
+ const body = await response.text().catch(() => "");
95
+ console.error(chalk.red(`Login failed (${response.status}):`), body || response.statusText);
96
+ process.exit(1);
97
+ }
98
+ const data = (await response.json());
99
+ writeConfig(rootDir, {
100
+ auth: {
101
+ token: data.access_token,
102
+ email: data.user?.email ?? email,
103
+ org: data.user?.org ?? "",
104
+ },
105
+ });
106
+ console.log(chalk.green(`\n✔ Logged in as ${data.user?.email ?? email}\n`));
107
+ }
108
+ //# sourceMappingURL=login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ interface PushLearningsOptions {
2
+ config: string;
3
+ workspace?: string;
4
+ yes?: boolean;
5
+ agent?: string;
6
+ }
7
+ /**
8
+ * Collect learnings from local `customs/auto/*.md` files and
9
+ * `customs/auto/config-suggestion-*.md` files, then push them
10
+ * to the NEPOPSX backend.
11
+ */
12
+ export declare function pushLearningsCommand(options: PushLearningsOptions): Promise<void>;
13
+ export {};
14
+ //# sourceMappingURL=push-learnings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"push-learnings.d.ts","sourceRoot":"","sources":["../../src/commands/push-learnings.ts"],"names":[],"mappings":"AASA,UAAU,oBAAoB;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAeD;;;;GAIG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAwHvF"}
@@ -0,0 +1,186 @@
1
+ import { existsSync, readFileSync, readdirSync } from 'node:fs';
2
+ import { resolve, basename } from 'node:path';
3
+ import { parse as parseYaml } from 'yaml';
4
+ import chalk from 'chalk';
5
+ import { resolveApiBase } from '../config/api-config.js';
6
+ import { readLicense, isDevMode } from '../licensing/index.js';
7
+ import { fetchWithTimeout } from '../utils/fetch.js';
8
+ import { DOWNLOAD_TIMEOUT_MS } from '../constants.js';
9
+ /**
10
+ * Collect learnings from local `customs/auto/*.md` files and
11
+ * `customs/auto/config-suggestion-*.md` files, then push them
12
+ * to the NEPOPSX backend.
13
+ */
14
+ export async function pushLearningsCommand(options) {
15
+ const cwd = process.cwd();
16
+ const configPath = resolve(cwd, options.config);
17
+ const devMode = isDevMode();
18
+ console.log(chalk.bold.cyan('\n📤 NEPOPSX Push Learnings\n'));
19
+ if (devMode) {
20
+ console.warn(chalk.yellow(' [dev mode — license checks bypassed]\n'));
21
+ }
22
+ // Read workspace config to determine customs_dir and agents
23
+ let config = {};
24
+ if (existsSync(configPath)) {
25
+ const raw = parseYaml(readFileSync(configPath, 'utf-8'));
26
+ if (typeof raw === 'object' && raw !== null) {
27
+ config = raw;
28
+ }
29
+ }
30
+ const customsDir = resolve(cwd, config.customs_dir ?? 'customs');
31
+ const autoDir = resolve(customsDir, 'auto');
32
+ // Collect local learnings
33
+ const learnings = collectLocalLearnings(autoDir, options.agent);
34
+ if (learnings.length === 0) {
35
+ console.log(chalk.dim(' No learnings found in customs/auto/.'));
36
+ console.log(chalk.dim(' Run an agent with reflection enabled to generate learnings.\n'));
37
+ return;
38
+ }
39
+ console.log(chalk.dim(` Found ${learnings.length} learning(s) in customs/auto/`));
40
+ for (const l of learnings) {
41
+ const badge = l.type === 'config_patch' ? '🔧' : l.type === 'skill' ? '📚' : '📝';
42
+ console.log(chalk.dim(` ${badge} [${l.confidence}] ${l.slug} (${l.agent || 'unknown'})`));
43
+ }
44
+ // Confirmation unless --yes
45
+ if (!options.yes) {
46
+ const readline = await import('node:readline');
47
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
48
+ const answer = await new Promise((resolve) => {
49
+ rl.question(chalk.yellow(`\n Push ${learnings.length} learning(s) to the platform? [y/N] `), resolve);
50
+ });
51
+ rl.close();
52
+ if (answer.toLowerCase() !== 'y') {
53
+ console.log(chalk.dim('\n Cancelled.\n'));
54
+ return;
55
+ }
56
+ }
57
+ // Read license
58
+ const license = readLicense(cwd);
59
+ if (!license && !devMode) {
60
+ console.error(chalk.red('\n No license found. Run nepopsx activate first.\n'));
61
+ process.exit(1);
62
+ }
63
+ if (!license) {
64
+ console.error(chalk.red('\n No license found even in dev mode.\n'));
65
+ process.exit(1);
66
+ }
67
+ // Push to backend
68
+ const apiBase = resolveApiBase(cwd);
69
+ const workspace = options.workspace ?? license.workspace;
70
+ console.log(chalk.dim(`\n Pushing to ${apiBase}/learnings...`));
71
+ const response = await fetchWithTimeout(`${apiBase}/learnings`, {
72
+ method: 'POST',
73
+ headers: {
74
+ Authorization: `Bearer ${license.key}`,
75
+ 'Content-Type': 'application/json',
76
+ },
77
+ body: JSON.stringify({
78
+ workspace,
79
+ learnings: learnings.map((l) => ({
80
+ type: l.type,
81
+ confidence: l.confidence,
82
+ slug: l.slug,
83
+ title: l.title,
84
+ content: l.content,
85
+ agent: l.agent,
86
+ applies_to: l.applies_to,
87
+ evidence: l.evidence,
88
+ config_path: l.config_path,
89
+ config_value: l.config_value,
90
+ })),
91
+ }),
92
+ }, DOWNLOAD_TIMEOUT_MS);
93
+ if (!response.ok) {
94
+ const body = await response.text().catch(() => '');
95
+ console.error(chalk.red(`\n Backend returned ${response.status}: ${body}`));
96
+ process.exit(1);
97
+ }
98
+ const result = await response.json();
99
+ console.log(chalk.bold.green(`\n ✅ Pushed ${result.received} learning(s)`));
100
+ console.log(chalk.dim(` Auto-applied: ${result.auto_applied}`));
101
+ console.log(chalk.dim(` Suggested: ${result.suggested}`));
102
+ for (const r of result.results) {
103
+ const icon = r.status === 'approved' ? '✅' : r.status === 'suggested' ? '💡' : '⏳';
104
+ console.log(chalk.dim(` ${icon} ${r.slug} → ${r.status} (seen ${r.occurrences}×)`));
105
+ }
106
+ console.log(chalk.dim(`\n Teammates can pull these via: ${chalk.cyan('nepopsx sync --remote')}\n`));
107
+ }
108
+ /**
109
+ * Parse customs/auto/*.md files into structured learnings.
110
+ *
111
+ * Expected frontmatter format:
112
+ * ```yaml
113
+ * ---
114
+ * name: slug-name
115
+ * applies_to: [agent-name]
116
+ * confidence: high
117
+ * type: custom_instruction # optional, defaults to custom_instruction
118
+ * agent: docs-agent # optional, inferred from applies_to
119
+ * config_path: workflow.settings.x # only for config_patch type
120
+ * config_value: 42 # only for config_patch type
121
+ * ---
122
+ * ```
123
+ */
124
+ function collectLocalLearnings(autoDir, agentFilter) {
125
+ if (!existsSync(autoDir))
126
+ return [];
127
+ const learnings = [];
128
+ const files = readdirSync(autoDir).filter((f) => f.endsWith('.md'));
129
+ for (const file of files) {
130
+ const filePath = resolve(autoDir, file);
131
+ const raw = readFileSync(filePath, 'utf-8');
132
+ const parsed = parseFrontmatter(raw);
133
+ if (!parsed.frontmatter)
134
+ continue;
135
+ const fm = parsed.frontmatter;
136
+ const isConfigSuggestion = file.startsWith('config-suggestion-');
137
+ const slug = fm.name ?? basename(file, '.md');
138
+ const type = isConfigSuggestion
139
+ ? 'config_patch'
140
+ : (fm.type ?? 'custom_instruction');
141
+ const confidence = fm.confidence ?? 'medium';
142
+ const appliesTo = Array.isArray(fm.applies_to)
143
+ ? fm.applies_to
144
+ : typeof fm.applies_to === 'string'
145
+ ? [fm.applies_to]
146
+ : [];
147
+ // Infer agent from applies_to or frontmatter
148
+ let agent = fm.agent ?? '';
149
+ if (!agent && appliesTo.length > 0) {
150
+ // e.g. "qa-executor" → "qa-agent", "docs-writer" → "docs-agent"
151
+ const prefix = appliesTo[0].split('-')[0];
152
+ agent = `${prefix}-agent`;
153
+ }
154
+ if (agentFilter && agent !== agentFilter)
155
+ continue;
156
+ learnings.push({
157
+ type: type,
158
+ confidence: confidence,
159
+ slug,
160
+ title: fm.title ?? slug.replace(/-/g, ' '),
161
+ content: parsed.body.trim(),
162
+ agent,
163
+ applies_to: appliesTo,
164
+ evidence: fm.evidence ?? undefined,
165
+ config_path: fm.config_path ?? undefined,
166
+ config_value: fm.config_value ?? undefined,
167
+ });
168
+ }
169
+ return learnings;
170
+ }
171
+ function parseFrontmatter(content) {
172
+ const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/);
173
+ if (!match)
174
+ return { frontmatter: null, body: content };
175
+ try {
176
+ const fm = parseYaml(match[1]);
177
+ return {
178
+ frontmatter: typeof fm === 'object' && fm !== null ? fm : null,
179
+ body: match[2],
180
+ };
181
+ }
182
+ catch {
183
+ return { frontmatter: null, body: content };
184
+ }
185
+ }
186
+ //# sourceMappingURL=push-learnings.js.map