@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.
- package/dist/agents/configuration.d.ts +9 -0
- package/dist/agents/configuration.d.ts.map +1 -0
- package/dist/agents/configuration.js +57 -0
- package/dist/agents/configuration.js.map +1 -0
- package/dist/agents/remote-config.d.ts +30 -0
- package/dist/agents/remote-config.d.ts.map +1 -0
- package/dist/agents/remote-config.js +102 -0
- package/dist/agents/remote-config.js.map +1 -0
- package/dist/commands/activate.d.ts.map +1 -1
- package/dist/commands/activate.js +4 -3
- package/dist/commands/activate.js.map +1 -1
- package/dist/commands/decode.js +2 -2
- package/dist/commands/decode.js.map +1 -1
- package/dist/commands/doctor.js +16 -16
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +353 -18
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/install.d.ts +1 -0
- package/dist/commands/install.d.ts.map +1 -1
- package/dist/commands/install.js +253 -25
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/login.d.ts +6 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +108 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/push-learnings.d.ts +14 -0
- package/dist/commands/push-learnings.d.ts.map +1 -0
- package/dist/commands/push-learnings.js +186 -0
- package/dist/commands/push-learnings.js.map +1 -0
- package/dist/commands/scan.d.ts +2 -0
- package/dist/commands/scan.d.ts.map +1 -0
- package/dist/commands/scan.js +520 -0
- package/dist/commands/scan.js.map +1 -0
- package/dist/commands/sync.d.ts +2 -0
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +203 -234
- package/dist/commands/sync.js.map +1 -1
- package/dist/config/api-config.d.ts.map +1 -1
- package/dist/config/api-config.js +4 -0
- package/dist/config/api-config.js.map +1 -1
- package/dist/constants.d.ts +7 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +7 -0
- package/dist/constants.js.map +1 -0
- package/dist/customs/instructions.d.ts +3 -0
- package/dist/customs/instructions.d.ts.map +1 -0
- package/dist/customs/instructions.js +51 -0
- package/dist/customs/instructions.js.map +1 -0
- package/dist/enrichment/confirm.d.ts +17 -0
- package/dist/enrichment/confirm.d.ts.map +1 -0
- package/dist/enrichment/confirm.js +44 -0
- package/dist/enrichment/confirm.js.map +1 -0
- package/dist/enrichment/state.d.ts +8 -0
- package/dist/enrichment/state.d.ts.map +1 -0
- package/dist/enrichment/state.js +107 -0
- package/dist/enrichment/state.js.map +1 -0
- package/dist/enrichment/types.d.ts +13 -0
- package/dist/enrichment/types.d.ts.map +1 -0
- package/dist/enrichment/types.js +2 -0
- package/dist/enrichment/types.js.map +1 -0
- package/dist/enrichment/workflow.d.ts +35 -0
- package/dist/enrichment/workflow.d.ts.map +1 -0
- package/dist/enrichment/workflow.js +305 -0
- package/dist/enrichment/workflow.js.map +1 -0
- package/dist/generator/builtin-templates.d.ts +2 -1
- package/dist/generator/builtin-templates.d.ts.map +1 -1
- package/dist/generator/builtin-templates.js +161 -2
- package/dist/generator/builtin-templates.js.map +1 -1
- package/dist/generator/package-renderer.d.ts +29 -0
- package/dist/generator/package-renderer.d.ts.map +1 -0
- package/dist/generator/package-renderer.js +123 -0
- package/dist/generator/package-renderer.js.map +1 -0
- package/dist/generator/render.d.ts +14 -63
- package/dist/generator/render.d.ts.map +1 -1
- package/dist/generator/render.js +30 -176
- package/dist/generator/render.js.map +1 -1
- package/dist/index.js +42 -2
- package/dist/index.js.map +1 -1
- package/dist/licensing/installer.d.ts +51 -0
- package/dist/licensing/installer.d.ts.map +1 -0
- package/dist/licensing/installer.js +112 -0
- package/dist/licensing/installer.js.map +1 -0
- package/dist/licensing/license-manager.d.ts +6 -0
- package/dist/licensing/license-manager.d.ts.map +1 -1
- package/dist/licensing/license-manager.js +12 -35
- package/dist/licensing/license-manager.js.map +1 -1
- package/dist/licensing/template-fetch.d.ts +3 -2
- package/dist/licensing/template-fetch.d.ts.map +1 -1
- package/dist/licensing/template-fetch.js +10 -41
- package/dist/licensing/template-fetch.js.map +1 -1
- package/dist/scan/__tests__/context-gatherer.test.d.ts +2 -0
- package/dist/scan/__tests__/context-gatherer.test.d.ts.map +1 -0
- package/dist/scan/__tests__/context-gatherer.test.js +111 -0
- package/dist/scan/__tests__/context-gatherer.test.js.map +1 -0
- package/dist/scan/__tests__/merge.test.d.ts +2 -0
- package/dist/scan/__tests__/merge.test.d.ts.map +1 -0
- package/dist/scan/__tests__/merge.test.js +163 -0
- package/dist/scan/__tests__/merge.test.js.map +1 -0
- package/dist/scan/auto-bootstrap.d.ts +3 -0
- package/dist/scan/auto-bootstrap.d.ts.map +1 -0
- package/dist/scan/auto-bootstrap.js +30 -0
- package/dist/scan/auto-bootstrap.js.map +1 -0
- package/dist/scan/config.d.ts +24 -0
- package/dist/scan/config.d.ts.map +1 -0
- package/dist/scan/config.js +77 -0
- package/dist/scan/config.js.map +1 -0
- package/dist/scan/context/gatherer.d.ts +13 -0
- package/dist/scan/context/gatherer.d.ts.map +1 -0
- package/dist/scan/context/gatherer.js +97 -0
- package/dist/scan/context/gatherer.js.map +1 -0
- package/dist/scan/context/gitignore.d.ts +9 -0
- package/dist/scan/context/gitignore.d.ts.map +1 -0
- package/dist/scan/context/gitignore.js +50 -0
- package/dist/scan/context/gitignore.js.map +1 -0
- package/dist/scan/context/patterns.d.ts +14 -0
- package/dist/scan/context/patterns.d.ts.map +1 -0
- package/dist/scan/context/patterns.js +159 -0
- package/dist/scan/context/patterns.js.map +1 -0
- package/dist/scan/customs/writer.d.ts +6 -0
- package/dist/scan/customs/writer.d.ts.map +1 -0
- package/dist/scan/customs/writer.js +149 -0
- package/dist/scan/customs/writer.js.map +1 -0
- package/dist/scan/llm/anthropic.d.ts +11 -0
- package/dist/scan/llm/anthropic.d.ts.map +1 -0
- package/dist/scan/llm/anthropic.js +89 -0
- package/dist/scan/llm/anthropic.js.map +1 -0
- package/dist/scan/llm/factory.d.ts +4 -0
- package/dist/scan/llm/factory.d.ts.map +1 -0
- package/dist/scan/llm/factory.js +20 -0
- package/dist/scan/llm/factory.js.map +1 -0
- package/dist/scan/llm/ollama.d.ts +11 -0
- package/dist/scan/llm/ollama.d.ts.map +1 -0
- package/dist/scan/llm/ollama.js +64 -0
- package/dist/scan/llm/ollama.js.map +1 -0
- package/dist/scan/llm/openai.d.ts +12 -0
- package/dist/scan/llm/openai.d.ts.map +1 -0
- package/dist/scan/llm/openai.js +78 -0
- package/dist/scan/llm/openai.js.map +1 -0
- package/dist/scan/llm/types.d.ts +23 -0
- package/dist/scan/llm/types.d.ts.map +1 -0
- package/dist/scan/llm/types.js +3 -0
- package/dist/scan/llm/types.js.map +1 -0
- package/dist/scan/merge/diff-display.d.ts +11 -0
- package/dist/scan/merge/diff-display.d.ts.map +1 -0
- package/dist/scan/merge/diff-display.js +72 -0
- package/dist/scan/merge/diff-display.js.map +1 -0
- package/dist/scan/prompt/agent.d.ts +23 -0
- package/dist/scan/prompt/agent.d.ts.map +1 -0
- package/dist/scan/prompt/agent.js +95 -0
- package/dist/scan/prompt/agent.js.map +1 -0
- package/dist/scan/prompt/builder.d.ts +16 -0
- package/dist/scan/prompt/builder.d.ts.map +1 -0
- package/dist/scan/prompt/builder.js +64 -0
- package/dist/scan/prompt/builder.js.map +1 -0
- package/dist/scan/prompt/schema.d.ts +7 -0
- package/dist/scan/prompt/schema.d.ts.map +1 -0
- package/dist/scan/prompt/schema.js +52 -0
- package/dist/scan/prompt/schema.js.map +1 -0
- package/dist/security/scanner.d.ts +3 -40
- package/dist/security/scanner.d.ts.map +1 -1
- package/dist/security/scanner.js +3 -169
- package/dist/security/scanner.js.map +1 -1
- package/dist/utils/fetch.d.ts +9 -0
- package/dist/utils/fetch.d.ts.map +1 -0
- package/dist/utils/fetch.js +18 -0
- package/dist/utils/fetch.js.map +1 -0
- package/package.json +15 -12
package/dist/commands/install.js
CHANGED
|
@@ -1,29 +1,257 @@
|
|
|
1
|
-
import chalk from
|
|
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
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
//
|
|
18
|
-
|
|
19
|
-
//
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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 @@
|
|
|
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
|