@nepopsx/cli 0.0.3 → 0.0.4
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/commands/install.d.ts.map +1 -1
- package/dist/commands/install.js +113 -24
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/login.d.ts +7 -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/scan.d.ts +2 -0
- package/dist/commands/scan.d.ts.map +1 -0
- package/dist/commands/scan.js +405 -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 +68 -120
- package/dist/commands/sync.js.map +1 -1
- 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 +37 -0
- package/dist/generator/package-renderer.d.ts.map +1 -0
- package/dist/generator/package-renderer.js +143 -0
- package/dist/generator/package-renderer.js.map +1 -0
- package/dist/generator/render.d.ts +11 -54
- package/dist/generator/render.d.ts.map +1 -1
- package/dist/generator/render.js +18 -174
- package/dist/generator/render.js.map +1 -1
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -1
- package/dist/licensing/installer.d.ts +43 -0
- package/dist/licensing/installer.d.ts.map +1 -0
- package/dist/licensing/installer.js +98 -0
- package/dist/licensing/installer.js.map +1 -0
- 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/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 +98 -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 +73 -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 +87 -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/package.json +15 -12
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Package renderer — renders agent template bundles into WriteOperations.
|
|
3
|
+
*
|
|
4
|
+
* Two rendering modes:
|
|
5
|
+
* renderBundleForInstall — all files land under .github/ (preserves bundle layout)
|
|
6
|
+
* renderAgentBundle — remaps schemas to openspec/ (used by sync)
|
|
7
|
+
*
|
|
8
|
+
* Both render .hbs templates with Handlebars and strip the .hbs extension.
|
|
9
|
+
* Decrypted templates are never written to disk — only the final rendered output is.
|
|
10
|
+
*/
|
|
11
|
+
import { join } from 'node:path';
|
|
12
|
+
import { renderTemplate, registerAgentPartialsFromMap, clearPartialNames } from './render.js';
|
|
13
|
+
// ─── Install mode ───────────────────────────────────────────
|
|
14
|
+
/**
|
|
15
|
+
* Render a downloaded agent bundle for `nepopsx install`.
|
|
16
|
+
*
|
|
17
|
+
* All files are written under `.github/<relativePath>` with .hbs stripped.
|
|
18
|
+
* This preserves the bundle's directory layout (agents/, prompts/, schemas/,
|
|
19
|
+
* partials/) exactly as the agent author designed.
|
|
20
|
+
*
|
|
21
|
+
* Decrypted .hbs source is kept in memory only — never touches disk.
|
|
22
|
+
*/
|
|
23
|
+
export function renderBundleForInstall(bundle, config, agentMeta) {
|
|
24
|
+
const operations = [];
|
|
25
|
+
// Register partials first so they're available when rendering other templates
|
|
26
|
+
const partialNames = registerAgentPartialsFromMap(bundle.templates, config, agentMeta);
|
|
27
|
+
for (const [relativePath, rawContent] of Object.entries(bundle.templates)) {
|
|
28
|
+
// Partials are registered above but also written to disk
|
|
29
|
+
const isHbs = relativePath.endsWith('.hbs');
|
|
30
|
+
const outputPath = isHbs ? relativePath.replace(/\.hbs$/, '') : relativePath;
|
|
31
|
+
const content = isHbs
|
|
32
|
+
? renderTemplate(rawContent, config, agentMeta)
|
|
33
|
+
: rawContent;
|
|
34
|
+
if (content.trim().length === 0)
|
|
35
|
+
continue;
|
|
36
|
+
operations.push({
|
|
37
|
+
path: join('.github', outputPath),
|
|
38
|
+
content,
|
|
39
|
+
source: `remote:${bundle.agent}/${relativePath}`,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
clearPartialNames(partialNames);
|
|
43
|
+
return operations;
|
|
44
|
+
}
|
|
45
|
+
// ─── Sync mode ──────────────────────────────────────────────
|
|
46
|
+
/**
|
|
47
|
+
* Render all templates from an agent bundle for `nepopsx sync`.
|
|
48
|
+
*
|
|
49
|
+
* Uses prefix-based remapping so schemas land in openspec/ and
|
|
50
|
+
* generated agent/prompt files land under .github/.
|
|
51
|
+
*/
|
|
52
|
+
export function renderAgentBundle(bundle, config, agentMeta) {
|
|
53
|
+
const operations = [];
|
|
54
|
+
// Register partials first so they're available when rendering agent/prompt templates
|
|
55
|
+
const partialNames = registerAgentPartialsFromMap(bundle.templates, config, agentMeta);
|
|
56
|
+
// Rendered template directories
|
|
57
|
+
const templateDirs = [
|
|
58
|
+
{ prefix: 'agents/', output: '.github/agents' },
|
|
59
|
+
{ prefix: 'prompts/', output: '.github/prompts' },
|
|
60
|
+
{ prefix: 'instructions/', output: '.github/instructions' },
|
|
61
|
+
];
|
|
62
|
+
for (const { prefix, output } of templateDirs) {
|
|
63
|
+
for (const [relativePath, templateSource] of Object.entries(bundle.templates)) {
|
|
64
|
+
if (!relativePath.startsWith(prefix) || !relativePath.endsWith('.hbs'))
|
|
65
|
+
continue;
|
|
66
|
+
const outputFileName = relativePath.slice(prefix.length).replace(/\.hbs$/, '');
|
|
67
|
+
const content = renderTemplate(templateSource, config, agentMeta);
|
|
68
|
+
if (content.trim().length === 0)
|
|
69
|
+
continue;
|
|
70
|
+
operations.push({
|
|
71
|
+
path: join(output, outputFileName),
|
|
72
|
+
content,
|
|
73
|
+
source: `remote:${bundle.agent}/${relativePath}`,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// Write partials to .github/partials/
|
|
78
|
+
for (const [relativePath, rawContent] of Object.entries(bundle.templates)) {
|
|
79
|
+
if (!relativePath.startsWith('partials/'))
|
|
80
|
+
continue;
|
|
81
|
+
const baseName = relativePath.slice('partials/'.length);
|
|
82
|
+
let outputFileName;
|
|
83
|
+
let content;
|
|
84
|
+
if (relativePath.endsWith('.hbs')) {
|
|
85
|
+
outputFileName = baseName.replace(/\.hbs$/, '');
|
|
86
|
+
content = renderTemplate(rawContent, config, agentMeta);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
outputFileName = baseName;
|
|
90
|
+
content = rawContent;
|
|
91
|
+
}
|
|
92
|
+
if (content.trim().length === 0)
|
|
93
|
+
continue;
|
|
94
|
+
operations.push({
|
|
95
|
+
path: join('.github/partials', outputFileName),
|
|
96
|
+
content,
|
|
97
|
+
source: `remote:${bundle.agent}/${relativePath}`,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
// Schema files → openspec/
|
|
101
|
+
copySyncSchemaFiles(bundle.templates, config, agentMeta, operations);
|
|
102
|
+
clearPartialNames(partialNames);
|
|
103
|
+
return operations;
|
|
104
|
+
}
|
|
105
|
+
// ─── Internals ──────────────────────────────────────────────
|
|
106
|
+
function copySyncSchemaFiles(templateMap, config, agentMeta, operations) {
|
|
107
|
+
const schemaContent = templateMap['schemas/schema.yaml'];
|
|
108
|
+
if (schemaContent) {
|
|
109
|
+
operations.push({
|
|
110
|
+
path: `openspec/schemas/${agentMeta.name}/schema.yaml`,
|
|
111
|
+
content: renderTemplate(schemaContent, config, agentMeta),
|
|
112
|
+
source: `remote:${agentMeta.name}/schemas/schema.yaml`,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
for (const [relativePath, rawContent] of Object.entries(templateMap)) {
|
|
116
|
+
if (!relativePath.startsWith('schemas/templates/'))
|
|
117
|
+
continue;
|
|
118
|
+
const outputName = relativePath.slice('schemas/templates/'.length).replace(/\.hbs$/, '');
|
|
119
|
+
const content = relativePath.endsWith('.hbs')
|
|
120
|
+
? renderTemplate(rawContent, config, agentMeta)
|
|
121
|
+
: rawContent;
|
|
122
|
+
operations.push({
|
|
123
|
+
path: `openspec/schemas/${agentMeta.name}/templates/${outputName}`,
|
|
124
|
+
content,
|
|
125
|
+
source: `remote:${agentMeta.name}/${relativePath}`,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
const configTemplate = `schema: {{agent.name}}\n` +
|
|
129
|
+
`context: |\n` +
|
|
130
|
+
` {{config.workspace.name}} platform services:\n` +
|
|
131
|
+
` {{#each config.services}}\n` +
|
|
132
|
+
` - {{name}} ({{language}}{{#if framework}}/{{framework}}{{/if}}) — {{path}}/ {{maturityBadge maturity}}\n` +
|
|
133
|
+
` {{/each}}\n` +
|
|
134
|
+
` {{#if config.execution_order}}\n` +
|
|
135
|
+
` Change order: {{join config.execution_order " → "}}\n` +
|
|
136
|
+
` {{/if}}\n`;
|
|
137
|
+
operations.push({
|
|
138
|
+
path: 'openspec/config.yaml',
|
|
139
|
+
content: renderTemplate(configTemplate, config, agentMeta),
|
|
140
|
+
source: `remote:${agentMeta.name}/openspec-config`,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=package-renderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-renderer.js","sourceRoot":"","sources":["../../src/generator/package-renderer.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,74 +1,31 @@
|
|
|
1
|
-
import type { WorkspaceConfig, WatermarkData } from '@nepopsx/core';
|
|
2
|
-
/**
|
|
3
|
-
* Parsed custom instruction file.
|
|
4
|
-
*/
|
|
5
|
-
export interface CustomInstruction {
|
|
6
|
-
content: string;
|
|
7
|
-
applies_to?: string[];
|
|
8
|
-
scope?: string;
|
|
9
|
-
source: string;
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Set the philosophy markdown block for the current sync run.
|
|
13
|
-
*/
|
|
14
|
-
export declare function setPhilosophyBlock(block: string): void;
|
|
15
1
|
/**
|
|
16
|
-
*
|
|
2
|
+
* CLI renderer — wraps @nepopsx/core/renderer with disk access and license watermarking.
|
|
3
|
+
* Pure template rendering is delegated to core; this module adds:
|
|
4
|
+
* - disk-based partial registration (registerAgentPartials, clearPartials)
|
|
5
|
+
* - renderTemplateFile (reads template from disk)
|
|
6
|
+
* - applyLicenseWatermark (steganographic fingerprint)
|
|
17
7
|
*/
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
agent?: {
|
|
22
|
-
name: string;
|
|
23
|
-
version: string;
|
|
24
|
-
};
|
|
25
|
-
timestamp: string;
|
|
26
|
-
}
|
|
8
|
+
import type { WorkspaceConfig, WatermarkData } from '@nepopsx/core';
|
|
9
|
+
import { renderTemplate, registerAgentPartialsFromMap, clearPartialNames, renderTemplateMap, setPhilosophyBlock, setCustomInstructions, type CustomInstruction, type RenderContext } from '@nepopsx/core';
|
|
10
|
+
export { renderTemplate, registerAgentPartialsFromMap, clearPartialNames, renderTemplateMap, setPhilosophyBlock, setCustomInstructions, type CustomInstruction, type RenderContext, };
|
|
27
11
|
/**
|
|
28
|
-
* Register all partials from
|
|
29
|
-
* .hbs partials are pre-rendered with config context; .md partials are included as-is.
|
|
12
|
+
* Register all partials from a package's partials/ directory on disk.
|
|
30
13
|
*/
|
|
31
14
|
export declare function registerAgentPartials(partialsDir: string, config: WorkspaceConfig, agentMeta?: {
|
|
32
15
|
name: string;
|
|
33
16
|
version: string;
|
|
34
17
|
}): void;
|
|
35
18
|
/**
|
|
36
|
-
* Unregister all partials
|
|
19
|
+
* Unregister all partials loaded from a partials/ directory.
|
|
37
20
|
*/
|
|
38
21
|
export declare function clearPartials(partialsDir: string): void;
|
|
39
22
|
/**
|
|
40
|
-
*
|
|
41
|
-
* Returns the partial names so they can be unregistered after rendering.
|
|
42
|
-
*/
|
|
43
|
-
export declare function registerAgentPartialsFromMap(templateMap: Record<string, string>, config: WorkspaceConfig, agentMeta?: {
|
|
44
|
-
name: string;
|
|
45
|
-
version: string;
|
|
46
|
-
}): string[];
|
|
47
|
-
export declare function clearPartialNames(partialNames: string[]): void;
|
|
48
|
-
/**
|
|
49
|
-
* Render a Handlebars template string with workspace config context.
|
|
50
|
-
* Context is sanitized to prevent prototype pollution attacks.
|
|
51
|
-
*/
|
|
52
|
-
export declare function renderTemplate(templateSource: string, config: WorkspaceConfig, agentMeta?: {
|
|
53
|
-
name: string;
|
|
54
|
-
version: string;
|
|
55
|
-
}): string;
|
|
56
|
-
/**
|
|
57
|
-
* Render a template file.
|
|
23
|
+
* Render a template file from disk.
|
|
58
24
|
*/
|
|
59
25
|
export declare function renderTemplateFile(templatePath: string, config: WorkspaceConfig, agentMeta?: {
|
|
60
26
|
name: string;
|
|
61
27
|
version: string;
|
|
62
28
|
}): string;
|
|
63
|
-
/**
|
|
64
|
-
* Set watermark data for the current sync run.
|
|
65
|
-
* When set, every rendered file gets a watermark header + steganographic fingerprint.
|
|
66
|
-
* Pass null to disable (e.g., dev mode / free tier).
|
|
67
|
-
*/
|
|
68
29
|
export declare function setWatermarkData(data: WatermarkData | null): void;
|
|
69
|
-
/**
|
|
70
|
-
* Apply watermark header + steganographic fingerprint to rendered content.
|
|
71
|
-
* Should be called AFTER Handlebars rendering, on the final output.
|
|
72
|
-
*/
|
|
73
30
|
export declare function applyLicenseWatermark(content: string): string;
|
|
74
31
|
//# sourceMappingURL=render.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/generator/render.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/generator/render.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,EAEL,cAAc,EACd,4BAA4B,EAC5B,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,qBAAqB,EACrB,KAAK,iBAAiB,EACtB,KAAK,aAAa,EACnB,MAAM,eAAe,CAAC;AAIvB,OAAO,EACL,cAAc,EACd,4BAA4B,EAC5B,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,qBAAqB,EACrB,KAAK,iBAAiB,EACtB,KAAK,aAAa,GACnB,CAAC;AAIF;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,eAAe,EACvB,SAAS,CAAC,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAC5C,IAAI,CAiBN;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAQvD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,eAAe,EACvB,SAAS,CAAC,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAC5C,MAAM,CAGR;AAMD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI,GAAG,IAAI,CAEjE;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAM7D"}
|
package/dist/generator/render.js
CHANGED
|
@@ -1,118 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI renderer — wraps @nepopsx/core/renderer with disk access and license watermarking.
|
|
3
|
+
* Pure template rendering is delegated to core; this module adds:
|
|
4
|
+
* - disk-based partial registration (registerAgentPartials, clearPartials)
|
|
5
|
+
* - renderTemplateFile (reads template from disk)
|
|
6
|
+
* - applyLicenseWatermark (steganographic fingerprint)
|
|
7
|
+
*/
|
|
1
8
|
import Handlebars from 'handlebars';
|
|
2
9
|
import { existsSync, readFileSync, readdirSync } from 'node:fs';
|
|
3
|
-
import { join
|
|
4
|
-
import { generateWatermark } from '@nepopsx/core';
|
|
10
|
+
import { join } from 'node:path';
|
|
11
|
+
import { generateWatermark, renderTemplate, registerAgentPartialsFromMap, clearPartialNames, renderTemplateMap, setPhilosophyBlock, setCustomInstructions, } from '@nepopsx/core';
|
|
5
12
|
import { applySteganography } from '../licensing/fingerprint.js';
|
|
6
|
-
//
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
* Deep-clone an object while stripping keys that could trigger
|
|
10
|
-
* Handlebars prototype pollution (e.g., {{constructor.constructor}}).
|
|
11
|
-
*/
|
|
12
|
-
function sanitizeContext(obj) {
|
|
13
|
-
if (obj === null || obj === undefined)
|
|
14
|
-
return obj;
|
|
15
|
-
if (typeof obj !== 'object')
|
|
16
|
-
return obj;
|
|
17
|
-
if (Array.isArray(obj)) {
|
|
18
|
-
return obj.map(sanitizeContext);
|
|
19
|
-
}
|
|
20
|
-
const clean = {};
|
|
21
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
22
|
-
if (BANNED_KEYS.has(key))
|
|
23
|
-
continue;
|
|
24
|
-
clean[key] = sanitizeContext(value);
|
|
25
|
-
}
|
|
26
|
-
return clean;
|
|
27
|
-
}
|
|
28
|
-
// ─── Register helpers ───────────────────────────────────────
|
|
29
|
-
Handlebars.registerHelper('eq', (a, b) => a === b);
|
|
30
|
-
Handlebars.registerHelper('neq', (a, b) => a !== b);
|
|
31
|
-
Handlebars.registerHelper('includes', (arr, val) => Array.isArray(arr) && arr.includes(val));
|
|
32
|
-
Handlebars.registerHelper('join', (arr, sep) => Array.isArray(arr) ? arr.join(sep) : '');
|
|
33
|
-
Handlebars.registerHelper('uppercase', (str) => str?.toUpperCase());
|
|
34
|
-
Handlebars.registerHelper('lowercase', (str) => str?.toLowerCase());
|
|
35
|
-
Handlebars.registerHelper('capitalize', (str) => str ? str.charAt(0).toUpperCase() + str.slice(1) : '');
|
|
36
|
-
// Index helper for numbered lists: {{idx @index}} → 1
|
|
37
|
-
Handlebars.registerHelper('idx', (i) => i + 1);
|
|
38
|
-
// Service filtering: {{#servicesByLang services "typescript"}}
|
|
39
|
-
Handlebars.registerHelper('servicesByLang', function (services, lang, options) {
|
|
40
|
-
const filtered = services.filter((s) => s.language === lang);
|
|
41
|
-
if (filtered.length === 0)
|
|
42
|
-
return '';
|
|
43
|
-
return filtered.map((s) => options.fn(s)).join('');
|
|
44
|
-
});
|
|
45
|
-
// Conditional block if workspace has a specific language
|
|
46
|
-
Handlebars.registerHelper('hasLanguage', function (services, lang, options) {
|
|
47
|
-
return services.some((s) => s.language === lang) ? options.fn(this) : '';
|
|
48
|
-
});
|
|
49
|
-
// Maturity badge
|
|
50
|
-
Handlebars.registerHelper('maturityBadge', (maturity) => {
|
|
51
|
-
switch (maturity) {
|
|
52
|
-
case 'production': return '[Mature]';
|
|
53
|
-
case 'evolving': return '[Evolving]';
|
|
54
|
-
case 'prototype': return '[Prototype]';
|
|
55
|
-
case 'legacy': return '[Legacy]';
|
|
56
|
-
default: return '';
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
// Safety rules block
|
|
60
|
-
Handlebars.registerHelper('safetyRules', function (config, options) {
|
|
61
|
-
const safety = config.safety;
|
|
62
|
-
if (!safety)
|
|
63
|
-
return '';
|
|
64
|
-
return options.fn(safety);
|
|
65
|
-
});
|
|
66
|
-
let _customInstructions = [];
|
|
67
|
-
let _philosophyBlock = '';
|
|
68
|
-
/**
|
|
69
|
-
* Set the philosophy markdown block for the current sync run.
|
|
70
|
-
*/
|
|
71
|
-
export function setPhilosophyBlock(block) {
|
|
72
|
-
_philosophyBlock = block;
|
|
73
|
-
}
|
|
13
|
+
// Re-export core renderer API so callers only need to import from this module
|
|
14
|
+
export { renderTemplate, registerAgentPartialsFromMap, clearPartialNames, renderTemplateMap, setPhilosophyBlock, setCustomInstructions, };
|
|
15
|
+
// ─── Disk-based partial helpers ─────────────────────────────
|
|
74
16
|
/**
|
|
75
|
-
*
|
|
76
|
-
*/
|
|
77
|
-
export function setCustomInstructions(customs) {
|
|
78
|
-
_customInstructions = customs;
|
|
79
|
-
}
|
|
80
|
-
// Helper: {{philosophyBlock}} — renders the philosophy as markdown
|
|
81
|
-
Handlebars.registerHelper('philosophyBlock', () => _philosophyBlock);
|
|
82
|
-
// Helper: {{customInstructions agentName}} — renders applicable custom instructions
|
|
83
|
-
// Pass "all" or omit to include all instructions. Pass an agent name to filter by applies_to.
|
|
84
|
-
Handlebars.registerHelper('customInstructions', (agentFileNameOrOptions) => {
|
|
85
|
-
if (_customInstructions.length === 0)
|
|
86
|
-
return '';
|
|
87
|
-
// When called as {{customInstructions}} with no args, Handlebars passes options as first arg
|
|
88
|
-
const agentFileName = typeof agentFileNameOrOptions === 'string' ? agentFileNameOrOptions : 'all';
|
|
89
|
-
const applicable = _customInstructions.filter((ci) => {
|
|
90
|
-
if (agentFileName === 'all' || agentFileName === 'worker') {
|
|
91
|
-
// Include all customs — no filtering by applies_to
|
|
92
|
-
return true;
|
|
93
|
-
}
|
|
94
|
-
// Filter by applies_to (if specified, agent name must match)
|
|
95
|
-
if (ci.applies_to && ci.applies_to.length > 0) {
|
|
96
|
-
return ci.applies_to.some((a) => agentFileName.includes(a));
|
|
97
|
-
}
|
|
98
|
-
return true;
|
|
99
|
-
});
|
|
100
|
-
if (applicable.length === 0)
|
|
101
|
-
return '';
|
|
102
|
-
const parts = [
|
|
103
|
-
'<!-- BEGIN CUSTOM INSTRUCTIONS -->',
|
|
104
|
-
'',
|
|
105
|
-
];
|
|
106
|
-
for (const ci of applicable) {
|
|
107
|
-
parts.push(ci.content);
|
|
108
|
-
parts.push('');
|
|
109
|
-
}
|
|
110
|
-
parts.push('<!-- END CUSTOM INSTRUCTIONS -->');
|
|
111
|
-
return parts.join('\n');
|
|
112
|
-
});
|
|
113
|
-
/**
|
|
114
|
-
* Register all partials from an agent package's partials/ directory.
|
|
115
|
-
* .hbs partials are pre-rendered with config context; .md partials are included as-is.
|
|
17
|
+
* Register all partials from a package's partials/ directory on disk.
|
|
116
18
|
*/
|
|
117
19
|
export function registerAgentPartials(partialsDir, config, agentMeta) {
|
|
118
20
|
if (!existsSync(partialsDir))
|
|
@@ -120,25 +22,21 @@ export function registerAgentPartials(partialsDir, config, agentMeta) {
|
|
|
120
22
|
for (const file of readdirSync(partialsDir)) {
|
|
121
23
|
const fullPath = join(partialsDir, file);
|
|
122
24
|
const raw = readFileSync(fullPath, 'utf-8');
|
|
123
|
-
// Derive partial name: "constitutional.md" → "constitutional", "worker-context.md.hbs" → "worker-context"
|
|
124
25
|
let partialName = file;
|
|
125
26
|
if (partialName.endsWith('.hbs'))
|
|
126
|
-
partialName = partialName.slice(0, -4);
|
|
27
|
+
partialName = partialName.slice(0, -4);
|
|
127
28
|
if (partialName.endsWith('.md'))
|
|
128
|
-
partialName = partialName.slice(0, -3);
|
|
29
|
+
partialName = partialName.slice(0, -3);
|
|
129
30
|
if (file.endsWith('.hbs')) {
|
|
130
|
-
|
|
131
|
-
const rendered = renderTemplate(raw, config, agentMeta);
|
|
132
|
-
Handlebars.registerPartial(partialName, rendered);
|
|
31
|
+
Handlebars.registerPartial(partialName, renderTemplate(raw, config, agentMeta));
|
|
133
32
|
}
|
|
134
33
|
else {
|
|
135
|
-
// Plain markdown — register as-is
|
|
136
34
|
Handlebars.registerPartial(partialName, raw);
|
|
137
35
|
}
|
|
138
36
|
}
|
|
139
37
|
}
|
|
140
38
|
/**
|
|
141
|
-
* Unregister all partials
|
|
39
|
+
* Unregister all partials loaded from a partials/ directory.
|
|
142
40
|
*/
|
|
143
41
|
export function clearPartials(partialsDir) {
|
|
144
42
|
if (!existsSync(partialsDir))
|
|
@@ -153,50 +51,7 @@ export function clearPartials(partialsDir) {
|
|
|
153
51
|
}
|
|
154
52
|
}
|
|
155
53
|
/**
|
|
156
|
-
*
|
|
157
|
-
* Returns the partial names so they can be unregistered after rendering.
|
|
158
|
-
*/
|
|
159
|
-
export function registerAgentPartialsFromMap(templateMap, config, agentMeta) {
|
|
160
|
-
const partialNames = [];
|
|
161
|
-
for (const [relativePath, raw] of Object.entries(templateMap)) {
|
|
162
|
-
if (!relativePath.startsWith('partials/'))
|
|
163
|
-
continue;
|
|
164
|
-
let partialName = basename(relativePath);
|
|
165
|
-
if (partialName.endsWith('.hbs'))
|
|
166
|
-
partialName = partialName.slice(0, -4);
|
|
167
|
-
if (partialName.endsWith('.md'))
|
|
168
|
-
partialName = partialName.slice(0, -3);
|
|
169
|
-
if (relativePath.endsWith('.hbs')) {
|
|
170
|
-
Handlebars.registerPartial(partialName, renderTemplate(raw, config, agentMeta));
|
|
171
|
-
}
|
|
172
|
-
else {
|
|
173
|
-
Handlebars.registerPartial(partialName, raw);
|
|
174
|
-
}
|
|
175
|
-
partialNames.push(partialName);
|
|
176
|
-
}
|
|
177
|
-
return partialNames;
|
|
178
|
-
}
|
|
179
|
-
export function clearPartialNames(partialNames) {
|
|
180
|
-
for (const partialName of partialNames) {
|
|
181
|
-
Handlebars.unregisterPartial(partialName);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
/**
|
|
185
|
-
* Render a Handlebars template string with workspace config context.
|
|
186
|
-
* Context is sanitized to prevent prototype pollution attacks.
|
|
187
|
-
*/
|
|
188
|
-
export function renderTemplate(templateSource, config, agentMeta) {
|
|
189
|
-
const context = {
|
|
190
|
-
config,
|
|
191
|
-
agent: agentMeta,
|
|
192
|
-
timestamp: new Date().toISOString().split('T')[0],
|
|
193
|
-
};
|
|
194
|
-
const safeContext = sanitizeContext(context);
|
|
195
|
-
const template = Handlebars.compile(templateSource, { noEscape: true });
|
|
196
|
-
return template(safeContext);
|
|
197
|
-
}
|
|
198
|
-
/**
|
|
199
|
-
* Render a template file.
|
|
54
|
+
* Render a template file from disk.
|
|
200
55
|
*/
|
|
201
56
|
export function renderTemplateFile(templatePath, config, agentMeta) {
|
|
202
57
|
const source = readFileSync(templatePath, 'utf-8');
|
|
@@ -204,25 +59,14 @@ export function renderTemplateFile(templatePath, config, agentMeta) {
|
|
|
204
59
|
}
|
|
205
60
|
// ─── Watermark + fingerprint post-processing ────────────────
|
|
206
61
|
let _watermarkData = null;
|
|
207
|
-
/**
|
|
208
|
-
* Set watermark data for the current sync run.
|
|
209
|
-
* When set, every rendered file gets a watermark header + steganographic fingerprint.
|
|
210
|
-
* Pass null to disable (e.g., dev mode / free tier).
|
|
211
|
-
*/
|
|
212
62
|
export function setWatermarkData(data) {
|
|
213
63
|
_watermarkData = data;
|
|
214
64
|
}
|
|
215
|
-
/**
|
|
216
|
-
* Apply watermark header + steganographic fingerprint to rendered content.
|
|
217
|
-
* Should be called AFTER Handlebars rendering, on the final output.
|
|
218
|
-
*/
|
|
219
65
|
export function applyLicenseWatermark(content) {
|
|
220
66
|
if (!_watermarkData)
|
|
221
67
|
return content;
|
|
222
|
-
// 1. Prepend visible watermark as first line
|
|
223
68
|
const watermarkLine = generateWatermark(_watermarkData);
|
|
224
69
|
let result = watermarkLine + '\n' + content;
|
|
225
|
-
// 2. Apply steganographic fingerprint
|
|
226
70
|
result = applySteganography(result, _watermarkData.fingerprint);
|
|
227
71
|
return result;
|
|
228
72
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/generator/render.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,YAAY,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAChE,OAAO,EAAE,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/generator/render.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,8 @@ import { doctorCommand } from './commands/doctor.js';
|
|
|
5
5
|
import { installCommand } from './commands/install.js';
|
|
6
6
|
import { activateCommand } from './commands/activate.js';
|
|
7
7
|
import { decodeCommand } from './commands/decode.js';
|
|
8
|
+
import { loginCommand } from './commands/login.js';
|
|
9
|
+
import { scanCommand } from './commands/scan.js';
|
|
8
10
|
import { serverClearCommand, serverSetCommand, serverShowCommand, } from './commands/server.js';
|
|
9
11
|
const program = new Command();
|
|
10
12
|
program
|
|
@@ -20,6 +22,8 @@ program
|
|
|
20
22
|
.command('sync')
|
|
21
23
|
.description('Generate .github/ files from workspace config + installed agents')
|
|
22
24
|
.option('-c, --config <path>', 'Path to workspace.yaml', '.nepopsx/workspace.yaml')
|
|
25
|
+
.option('--remote', 'Fetch workspace config from backend API instead of local file')
|
|
26
|
+
.option('--workspace <slug>', 'Workspace slug to fetch (used with --remote)')
|
|
23
27
|
.option('--dry-run', 'Preview changes without writing files')
|
|
24
28
|
.option('--dev', 'Dev mode — bypass license checks (for NEPOPSX agent developers)')
|
|
25
29
|
.action(syncCommand);
|
|
@@ -42,6 +46,12 @@ program
|
|
|
42
46
|
.command('decode <file>')
|
|
43
47
|
.description('Forensic decode — extract fingerprint from a generated file')
|
|
44
48
|
.action(decodeCommand);
|
|
49
|
+
program
|
|
50
|
+
.command('login')
|
|
51
|
+
.description('Log in to NEPOPSX and save credentials to .nepopsx/config.json')
|
|
52
|
+
.option('--email <email>', 'Your NEPOPSX account email')
|
|
53
|
+
.option('--password <password>', 'Your NEPOPSX account password')
|
|
54
|
+
.action(loginCommand);
|
|
45
55
|
const serverProgram = program
|
|
46
56
|
.command('server')
|
|
47
57
|
.description('Manage the NEPOPSX backend server URL for this workspace');
|
|
@@ -57,5 +67,26 @@ serverProgram
|
|
|
57
67
|
.command('clear')
|
|
58
68
|
.description('Remove the persisted NEPOPSX backend server URL override')
|
|
59
69
|
.action(serverClearCommand);
|
|
70
|
+
function collectRepeatable(value, previous) {
|
|
71
|
+
return [...previous, value];
|
|
72
|
+
}
|
|
73
|
+
program
|
|
74
|
+
.command('scan')
|
|
75
|
+
.description('LLM-powered workspace analysis — enrich workspace.yaml with discovered metadata')
|
|
76
|
+
.option('-y, --yes', 'Skip all confirmations')
|
|
77
|
+
.option('--provider <name>', 'LLM provider (openai, anthropic, ollama, compatible)')
|
|
78
|
+
.option('--model <name>', 'Model override')
|
|
79
|
+
.option('--endpoint <url>', 'Custom API endpoint (OpenAI-compatible or Ollama base URL)')
|
|
80
|
+
.option('--budget <tokens>', 'Per-service token budget', '30000')
|
|
81
|
+
.option('--agent-budget <tokens>', 'Total context budget for agent mode', '60000')
|
|
82
|
+
.option('--parallel <n>', 'Concurrent service analysis', '1')
|
|
83
|
+
.option('--customs', 'Generate/update customs directory files')
|
|
84
|
+
.option('--dry-run', 'Show what would change without writing')
|
|
85
|
+
.option('-v, --verbose', 'Show LLM prompts and raw responses')
|
|
86
|
+
.option('--service <name>', 'Scan only specific service(s)', collectRepeatable, [])
|
|
87
|
+
.option('--agent', 'Agent-assisted mode (generate prompt file for VS Code AI)')
|
|
88
|
+
.option('--apply <path>', 'Apply a JSON response file from agent-assisted mode')
|
|
89
|
+
.option('--resume', 'Resume a previously interrupted scan using cached service results')
|
|
90
|
+
.action(scanCommand);
|
|
60
91
|
program.parse();
|
|
61
92
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,sBAAsB,CAAC;AAE9B,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,SAAS,CAAC;KACf,WAAW,CAAC,mDAAmD,CAAC;KAChE,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,wDAAwD,CAAC;KACrE,MAAM,CAAC,mBAAmB,EAAE,0CAA0C,CAAC;KACvE,MAAM,CAAC,WAAW,CAAC,CAAC;AAEvB,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,kEAAkE,CAAC;KAC/E,MAAM,CAAC,qBAAqB,EAAE,wBAAwB,EAAE,yBAAyB,CAAC;KAClF,MAAM,CAAC,WAAW,EAAE,uCAAuC,CAAC;KAC5D,MAAM,CAAC,OAAO,EAAE,iEAAiE,CAAC;KAClF,MAAM,CAAC,WAAW,CAAC,CAAC;AAEvB,OAAO;KACJ,OAAO,CAAC,iBAAiB,CAAC;KAC1B,WAAW,CAAC,gEAAgE,CAAC;KAC7E,MAAM,CAAC,iBAAiB,EAAE,6BAA6B,CAAC;KACxD,MAAM,CAAC,cAAc,CAAC,CAAC;AAE1B,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,oDAAoD,CAAC;KACjE,MAAM,CAAC,qBAAqB,EAAE,wBAAwB,EAAE,yBAAyB,CAAC;KAClF,MAAM,CAAC,aAAa,CAAC,CAAC;AAEzB,OAAO;KACJ,OAAO,CAAC,gBAAgB,CAAC;KACzB,WAAW,CAAC,kDAAkD,CAAC;KAC/D,MAAM,CAAC,qBAAqB,EAAE,wBAAwB,EAAE,yBAAyB,CAAC;KAClF,MAAM,CAAC,eAAe,CAAC,CAAC;AAE3B,OAAO;KACJ,OAAO,CAAC,eAAe,CAAC;KACxB,WAAW,CAAC,6DAA6D,CAAC;KAC1E,MAAM,CAAC,aAAa,CAAC,CAAC;AAEzB,MAAM,aAAa,GAAG,OAAO;KAC1B,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,0DAA0D,CAAC,CAAC;AAE3E,aAAa;KACV,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,+CAA+C,CAAC;KAC5D,MAAM,CAAC,iBAAiB,CAAC,CAAC;AAE7B,aAAa;KACV,OAAO,CAAC,WAAW,CAAC;KACpB,WAAW,CAAC,+DAA+D,CAAC;KAC5E,MAAM,CAAC,gBAAgB,CAAC,CAAC;AAE5B,aAAa;KACV,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,0DAA0D,CAAC;KACvE,MAAM,CAAC,kBAAkB,CAAC,CAAC;AAE9B,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent bundle installer — downloads, decrypts, verifies, and writes
|
|
3
|
+
* agent template files from the NEPOPSX API.
|
|
4
|
+
*
|
|
5
|
+
* Flow:
|
|
6
|
+
* 1. downloadBundle — POST /v1/templates/:agent/:version (auth: Bearer <key>)
|
|
7
|
+
* 2. decryptBundle — AES-256-GCM, key = SHA-256(licenseKey + ":nepopsx-template-key")
|
|
8
|
+
* 3. verifyBundleSha — SHA-256 of raw JSON must match server-provided sha256
|
|
9
|
+
* 4. writeAgentFiles — atomic write via temp + rename into .github/<relative-path>
|
|
10
|
+
*/
|
|
11
|
+
import type { License } from "@nepopsx/core";
|
|
12
|
+
export interface EncryptedBundle {
|
|
13
|
+
payload: string;
|
|
14
|
+
iv: string;
|
|
15
|
+
tag: string;
|
|
16
|
+
agent: string;
|
|
17
|
+
version: string;
|
|
18
|
+
sha256: string;
|
|
19
|
+
}
|
|
20
|
+
export interface InstalledFile {
|
|
21
|
+
path: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Download an encrypted template bundle from the NEPOPSX API.
|
|
25
|
+
*/
|
|
26
|
+
export declare function downloadBundle(cwd: string, license: License, agent: string, version: string): Promise<EncryptedBundle>;
|
|
27
|
+
/**
|
|
28
|
+
* Decrypt an AES-256-GCM bundle using the license key.
|
|
29
|
+
* Returns the raw JSON string (not yet parsed).
|
|
30
|
+
*/
|
|
31
|
+
export declare function decryptBundle(bundle: EncryptedBundle, licenseKey: string): string;
|
|
32
|
+
/**
|
|
33
|
+
* Verify that the decrypted JSON matches the server's sha256.
|
|
34
|
+
* Throws if the digest does not match.
|
|
35
|
+
*/
|
|
36
|
+
export declare function verifyBundleSha(decryptedJson: string, expectedSha: string): void;
|
|
37
|
+
/**
|
|
38
|
+
* Atomically write agent template files into .github/<relative-path>.
|
|
39
|
+
* Uses a tmp-file + rename pattern to avoid partial writes.
|
|
40
|
+
* Returns the list of written file paths.
|
|
41
|
+
*/
|
|
42
|
+
export declare function writeAgentFiles(cwd: string, templates: Record<string, string>): InstalledFile[];
|
|
43
|
+
//# sourceMappingURL=installer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../../src/licensing/installer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAM7C,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;AAID;;GAEG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,eAAe,CAAC,CAiC1B;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"}
|