@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,73 @@
|
|
|
1
|
+
const DEFAULT_MODEL = 'llama3.2';
|
|
2
|
+
const DEFAULT_BASE_URL = 'http://localhost:11434';
|
|
3
|
+
const TIMEOUT_MS = 180_000; // Local models can be slower
|
|
4
|
+
const MAX_RETRIES = 5; // Higher retry budget for local models
|
|
5
|
+
async function fetchWithTimeout(url, init, ms) {
|
|
6
|
+
const controller = new AbortController();
|
|
7
|
+
const timer = setTimeout(() => controller.abort(), ms);
|
|
8
|
+
try {
|
|
9
|
+
return await fetch(url, { ...init, signal: controller.signal });
|
|
10
|
+
}
|
|
11
|
+
finally {
|
|
12
|
+
clearTimeout(timer);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export class OllamaProvider {
|
|
16
|
+
baseUrl;
|
|
17
|
+
model;
|
|
18
|
+
name;
|
|
19
|
+
supportsJsonMode = false; // Unconstrained JSON — needs strict validation
|
|
20
|
+
constructor(baseUrl = DEFAULT_BASE_URL, model = DEFAULT_MODEL) {
|
|
21
|
+
this.baseUrl = baseUrl;
|
|
22
|
+
this.model = model;
|
|
23
|
+
this.name = `ollama:${model}`;
|
|
24
|
+
}
|
|
25
|
+
estimateTokens(text) {
|
|
26
|
+
return Math.ceil(text.length / 3.5);
|
|
27
|
+
}
|
|
28
|
+
async chat(request) {
|
|
29
|
+
const url = `${this.baseUrl.replace(/\/$/, '')}/api/chat`;
|
|
30
|
+
const body = {
|
|
31
|
+
model: this.model,
|
|
32
|
+
stream: false,
|
|
33
|
+
format: 'json',
|
|
34
|
+
options: { temperature: request.temperature },
|
|
35
|
+
messages: [
|
|
36
|
+
{ role: 'system', content: request.systemPrompt },
|
|
37
|
+
{ role: 'user', content: request.userPrompt },
|
|
38
|
+
],
|
|
39
|
+
};
|
|
40
|
+
let lastError = null;
|
|
41
|
+
for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
|
|
42
|
+
if (attempt > 0) {
|
|
43
|
+
await new Promise((r) => setTimeout(r, 1000 * Math.pow(2, Math.min(attempt - 1, 4))));
|
|
44
|
+
}
|
|
45
|
+
try {
|
|
46
|
+
const res = await fetchWithTimeout(url, {
|
|
47
|
+
method: 'POST',
|
|
48
|
+
headers: { 'Content-Type': 'application/json' },
|
|
49
|
+
body: JSON.stringify(body),
|
|
50
|
+
}, TIMEOUT_MS);
|
|
51
|
+
if (!res.ok) {
|
|
52
|
+
const text = await res.text();
|
|
53
|
+
throw new Error(`Ollama error ${res.status}: ${text.slice(0, 200)}`);
|
|
54
|
+
}
|
|
55
|
+
const data = (await res.json());
|
|
56
|
+
return {
|
|
57
|
+
content: data.message?.content ?? '',
|
|
58
|
+
inputTokens: data.prompt_eval_count ?? 0,
|
|
59
|
+
outputTokens: data.eval_count ?? 0,
|
|
60
|
+
model: data.model,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
lastError = err instanceof Error ? err : new Error(String(err));
|
|
65
|
+
if (lastError.name === 'AbortError') {
|
|
66
|
+
throw new Error(`Ollama request timed out after ${TIMEOUT_MS}ms`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
throw lastError ?? new Error('Ollama request failed after retries');
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=ollama.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ollama.js","sourceRoot":"","sources":["../../../src/scan/llm/ollama.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { LlmProvider, LlmRequest, LlmResponse } from './types.js';
|
|
2
|
+
export declare class OpenAiProvider implements LlmProvider {
|
|
3
|
+
private readonly apiKey;
|
|
4
|
+
private readonly model;
|
|
5
|
+
private readonly endpoint;
|
|
6
|
+
readonly name: string;
|
|
7
|
+
readonly supportsJsonMode = true;
|
|
8
|
+
constructor(apiKey: string, model?: string, endpoint?: string);
|
|
9
|
+
estimateTokens(text: string): number;
|
|
10
|
+
chat(request: LlmRequest): Promise<LlmResponse>;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=openai.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../../src/scan/llm/openai.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAiBvE,qBAAa,cAAe,YAAW,WAAW;IAK9C,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAN3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,gBAAgB,QAAQ;gBAGd,MAAM,EAAE,MAAM,EACd,KAAK,GAAE,MAAsB,EAC7B,QAAQ,GAAE,MAAyB;IAKtD,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAI9B,IAAI,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC;CAqEtD"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
const DEFAULT_MODEL = 'gpt-4o';
|
|
2
|
+
const DEFAULT_ENDPOINT = 'https://api.openai.com/v1';
|
|
3
|
+
const TIMEOUT_MS = 120_000;
|
|
4
|
+
const MAX_RETRIES = 3;
|
|
5
|
+
async function fetchWithTimeout(url, init, ms) {
|
|
6
|
+
const controller = new AbortController();
|
|
7
|
+
const timer = setTimeout(() => controller.abort(), ms);
|
|
8
|
+
try {
|
|
9
|
+
return await fetch(url, { ...init, signal: controller.signal });
|
|
10
|
+
}
|
|
11
|
+
finally {
|
|
12
|
+
clearTimeout(timer);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export class OpenAiProvider {
|
|
16
|
+
apiKey;
|
|
17
|
+
model;
|
|
18
|
+
endpoint;
|
|
19
|
+
name;
|
|
20
|
+
supportsJsonMode = true;
|
|
21
|
+
constructor(apiKey, model = DEFAULT_MODEL, endpoint = DEFAULT_ENDPOINT) {
|
|
22
|
+
this.apiKey = apiKey;
|
|
23
|
+
this.model = model;
|
|
24
|
+
this.endpoint = endpoint;
|
|
25
|
+
this.name = `openai:${model}`;
|
|
26
|
+
}
|
|
27
|
+
estimateTokens(text) {
|
|
28
|
+
return Math.ceil(text.length / 3.5);
|
|
29
|
+
}
|
|
30
|
+
async chat(request) {
|
|
31
|
+
const url = `${this.endpoint.replace(/\/$/, '')}/chat/completions`;
|
|
32
|
+
const body = {
|
|
33
|
+
model: this.model,
|
|
34
|
+
messages: [
|
|
35
|
+
{ role: 'system', content: request.systemPrompt },
|
|
36
|
+
{ role: 'user', content: request.userPrompt },
|
|
37
|
+
],
|
|
38
|
+
max_tokens: request.maxTokens,
|
|
39
|
+
temperature: request.temperature,
|
|
40
|
+
};
|
|
41
|
+
if (request.jsonSchema) {
|
|
42
|
+
body.response_format = {
|
|
43
|
+
type: 'json_schema',
|
|
44
|
+
json_schema: {
|
|
45
|
+
name: 'scan_response',
|
|
46
|
+
strict: true,
|
|
47
|
+
schema: request.jsonSchema,
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
let lastError = null;
|
|
52
|
+
for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
|
|
53
|
+
if (attempt > 0) {
|
|
54
|
+
await new Promise((r) => setTimeout(r, 1000 * Math.pow(2, attempt - 1)));
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
const res = await fetchWithTimeout(url, {
|
|
58
|
+
method: 'POST',
|
|
59
|
+
headers: {
|
|
60
|
+
'Content-Type': 'application/json',
|
|
61
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
62
|
+
},
|
|
63
|
+
body: JSON.stringify(body),
|
|
64
|
+
}, TIMEOUT_MS);
|
|
65
|
+
if (!res.ok) {
|
|
66
|
+
const text = await res.text();
|
|
67
|
+
throw new Error(`OpenAI API error ${res.status}: ${text.slice(0, 200)}`);
|
|
68
|
+
}
|
|
69
|
+
const data = (await res.json());
|
|
70
|
+
return {
|
|
71
|
+
content: data.choices[0]?.message?.content ?? '',
|
|
72
|
+
inputTokens: data.usage?.prompt_tokens ?? 0,
|
|
73
|
+
outputTokens: data.usage?.completion_tokens ?? 0,
|
|
74
|
+
model: data.model,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
lastError = err instanceof Error ? err : new Error(String(err));
|
|
79
|
+
if (lastError.name === 'AbortError') {
|
|
80
|
+
throw new Error(`OpenAI request timed out after ${TIMEOUT_MS}ms`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
throw lastError ?? new Error('OpenAI request failed after retries');
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=openai.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai.js","sourceRoot":"","sources":["../../../src/scan/llm/openai.ts"],"names":[],"mappings":"AAGA,MAAM,aAAa,GAAG,QAAQ,CAAC;AAC/B,MAAM,gBAAgB,GAAG,2BAA2B,CAAC;AACrD,MAAM,UAAU,GAAG,OAAO,CAAC;AAC3B,MAAM,WAAW,GAAG,CAAC,CAAC;AAEtB,KAAK,UAAU,gBAAgB,CAAC,GAAW,EAAE,IAAiB,EAAE,EAAU;IACxE,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;IACvD,IAAI,CAAC;QACH,OAAO,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;IAClE,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;AACH,CAAC;AAED,MAAM,OAAO,cAAc;IAKN;IACA;IACA;IANV,IAAI,CAAS;IACb,gBAAgB,GAAG,IAAI,CAAC;IAEjC,YACmB,MAAc,EACd,QAAgB,aAAa,EAC7B,WAAmB,gBAAgB;QAFnC,WAAM,GAAN,MAAM,CAAQ;QACd,UAAK,GAAL,KAAK,CAAwB;QAC7B,aAAQ,GAAR,QAAQ,CAA2B;QAEpD,IAAI,CAAC,IAAI,GAAG,UAAU,KAAK,EAAE,CAAC;IAChC,CAAC;IAED,cAAc,CAAC,IAAY;QACzB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC;IACtC,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,OAAmB;QAC5B,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,mBAAmB,CAAC;QAEnE,MAAM,IAAI,GAA4B;YACpC,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,QAAQ,EAAE;gBACR,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,YAAY,EAAE;gBACjD,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,UAAU,EAAE;aAC9C;YACD,UAAU,EAAE,OAAO,CAAC,SAAS;YAC7B,WAAW,EAAE,OAAO,CAAC,WAAW;SACjC,CAAC;QAEF,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;YACvB,IAAI,CAAC,eAAe,GAAG;gBACrB,IAAI,EAAE,aAAa;gBACnB,WAAW,EAAE;oBACX,IAAI,EAAE,eAAe;oBACrB,MAAM,EAAE,IAAI;oBACZ,MAAM,EAAE,OAAO,CAAC,UAAU;iBAC3B;aACF,CAAC;QACJ,CAAC;QAED,IAAI,SAAS,GAAiB,IAAI,CAAC;QACnC,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC;YACvD,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;gBAChB,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YAC3E,CAAC;YACD,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,MAAM,gBAAgB,CAChC,GAAG,EACH;oBACE,MAAM,EAAE,MAAM;oBACd,OAAO,EAAE;wBACP,cAAc,EAAE,kBAAkB;wBAClC,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;qBACvC;oBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;iBAC3B,EACD,UAAU,CACX,CAAC;gBAEF,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;oBACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;oBAC9B,MAAM,IAAI,KAAK,CAAC,oBAAoB,GAAG,CAAC,MAAM,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;gBAC3E,CAAC;gBAED,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAI7B,CAAC;gBAEF,OAAO;oBACL,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,IAAI,EAAE;oBAChD,WAAW,EAAE,IAAI,CAAC,KAAK,EAAE,aAAa,IAAI,CAAC;oBAC3C,YAAY,EAAE,IAAI,CAAC,KAAK,EAAE,iBAAiB,IAAI,CAAC;oBAChD,KAAK,EAAE,IAAI,CAAC,KAAK;iBAClB,CAAC;YACJ,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,SAAS,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;gBAChE,IAAI,SAAS,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;oBACpC,MAAM,IAAI,KAAK,CAAC,kCAAkC,UAAU,IAAI,CAAC,CAAC;gBACpE,CAAC;YACH,CAAC;QACH,CAAC;QACD,MAAM,SAAS,IAAI,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACtE,CAAC;CACF"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface LlmRequest {
|
|
2
|
+
systemPrompt: string;
|
|
3
|
+
userPrompt: string;
|
|
4
|
+
/** JSON schema for providers with native structured output */
|
|
5
|
+
jsonSchema?: object;
|
|
6
|
+
maxTokens: number;
|
|
7
|
+
temperature: number;
|
|
8
|
+
}
|
|
9
|
+
export interface LlmResponse {
|
|
10
|
+
/** Raw text content (JSON string) */
|
|
11
|
+
content: string;
|
|
12
|
+
inputTokens: number;
|
|
13
|
+
outputTokens: number;
|
|
14
|
+
model: string;
|
|
15
|
+
}
|
|
16
|
+
export interface LlmProvider {
|
|
17
|
+
name: string;
|
|
18
|
+
chat(request: LlmRequest): Promise<LlmResponse>;
|
|
19
|
+
supportsJsonMode: boolean;
|
|
20
|
+
estimateTokens(text: string): number;
|
|
21
|
+
}
|
|
22
|
+
export type ProviderName = 'openai' | 'anthropic' | 'ollama' | 'compatible';
|
|
23
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/scan/llm/types.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,UAAU;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,8DAA8D;IAC9D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,qCAAqC;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAChD,gBAAgB,EAAE,OAAO,CAAC;IAC1B,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;CACtC;AAED,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,WAAW,GAAG,QAAQ,GAAG,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/scan/llm/types.ts"],"names":[],"mappings":"AAAA,oCAAoC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { WorkspaceConfig } from '@nepopsx/core';
|
|
2
|
+
import type { MergeResult } from '@nepopsx/core';
|
|
3
|
+
/**
|
|
4
|
+
* Display a colorized diff of what `nepopsx scan` would change in workspace.yaml.
|
|
5
|
+
*
|
|
6
|
+
* - Green: new fields (were empty, now filled)
|
|
7
|
+
* - Yellow: updated scan fields (provenance was 'scan', new value discovered)
|
|
8
|
+
* - Cyan: suggestions (user-locked fields — scan found a different value but preserved yours)
|
|
9
|
+
*/
|
|
10
|
+
export declare function displayDiff(original: WorkspaceConfig, merged: MergeResult): void;
|
|
11
|
+
//# sourceMappingURL=diff-display.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff-display.d.ts","sourceRoot":"","sources":["../../../src/scan/merge/diff-display.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,eAAe,EAAE,MAAM,EAAE,WAAW,GAAG,IAAI,CA6ChF"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// @nepopsx/cli — Terminal diff display for scan merge results
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
/**
|
|
4
|
+
* Display a colorized diff of what `nepopsx scan` would change in workspace.yaml.
|
|
5
|
+
*
|
|
6
|
+
* - Green: new fields (were empty, now filled)
|
|
7
|
+
* - Yellow: updated scan fields (provenance was 'scan', new value discovered)
|
|
8
|
+
* - Cyan: suggestions (user-locked fields — scan found a different value but preserved yours)
|
|
9
|
+
*/
|
|
10
|
+
export function displayDiff(original, merged) {
|
|
11
|
+
const { changedFields, suggestions } = merged;
|
|
12
|
+
if (changedFields.length === 0 && suggestions.length === 0) {
|
|
13
|
+
console.log(chalk.dim(' No changes detected.'));
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
if (changedFields.length > 0) {
|
|
17
|
+
console.log(chalk.bold('\nChanges to write:'));
|
|
18
|
+
for (const field of changedFields) {
|
|
19
|
+
const oldValue = getNestedValue(original, field);
|
|
20
|
+
const newValue = getNestedValue(merged.updated, field);
|
|
21
|
+
const oldStr = formatValue(oldValue);
|
|
22
|
+
const newStr = formatValue(newValue);
|
|
23
|
+
if (oldStr === '—') {
|
|
24
|
+
// New field
|
|
25
|
+
console.log(` ${chalk.green('+')} ${chalk.bold(field)}: ${chalk.green(newStr)}`);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
// Updated field
|
|
29
|
+
console.log(` ${chalk.yellow('~')} ${chalk.bold(field)}: ${chalk.dim(oldStr)} → ${chalk.yellow(newStr)}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (suggestions.length > 0) {
|
|
34
|
+
console.log(chalk.bold('\nSuggestions (your values preserved):'));
|
|
35
|
+
for (const s of suggestions) {
|
|
36
|
+
console.log(` ${chalk.cyan('!')} ${chalk.bold(s.path)}: keeping ${chalk.cyan(formatValue(s.currentValue))} (scan found: ${chalk.dim(formatValue(s.suggestedValue))})`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
console.log('');
|
|
40
|
+
console.log(chalk.dim(` ${changedFields.length} field(s) changed · ${suggestions.length} suggestion(s) preserved`));
|
|
41
|
+
}
|
|
42
|
+
function formatValue(value) {
|
|
43
|
+
if (value === undefined || value === null)
|
|
44
|
+
return '—';
|
|
45
|
+
if (Array.isArray(value))
|
|
46
|
+
return `[${value.join(', ')}]`;
|
|
47
|
+
if (typeof value === 'object')
|
|
48
|
+
return JSON.stringify(value);
|
|
49
|
+
return String(value);
|
|
50
|
+
}
|
|
51
|
+
/** Resolve a flat dot-notation path like "services.api.description" in a nested object */
|
|
52
|
+
function getNestedValue(obj, path) {
|
|
53
|
+
const parts = path.split('.');
|
|
54
|
+
let current = obj;
|
|
55
|
+
for (const part of parts) {
|
|
56
|
+
if (current === null || current === undefined)
|
|
57
|
+
return undefined;
|
|
58
|
+
// Handle array access by name: "services.api" → look for services[*] where name===api
|
|
59
|
+
if (Array.isArray(current)) {
|
|
60
|
+
const found = current.find((item) => typeof item === 'object' && item !== null && item.name === part);
|
|
61
|
+
current = found;
|
|
62
|
+
}
|
|
63
|
+
else if (typeof current === 'object') {
|
|
64
|
+
current = current[part];
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return current;
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=diff-display.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff-display.js","sourceRoot":"","sources":["../../../src/scan/merge/diff-display.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Service } from '@nepopsx/core';
|
|
2
|
+
import type { FileContext } from '../context/gatherer.js';
|
|
3
|
+
export interface ServiceWithContext {
|
|
4
|
+
service: Service;
|
|
5
|
+
context: FileContext;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Generate the scan-context.md file content for agent-assisted mode.
|
|
9
|
+
* Enforces agentBudget by trimming lower-tier files from largest services first.
|
|
10
|
+
*/
|
|
11
|
+
export declare function generateScanContextFile(services: ServiceWithContext[], existingConfig: string, schema: object, agentBudget: number, workspaceRoot: string): string;
|
|
12
|
+
/**
|
|
13
|
+
* Generate the .github/prompts/nepopsx-scan.prompt.md Copilot prompt file content.
|
|
14
|
+
*/
|
|
15
|
+
export declare function generateCopilotPromptFile(contextFilePath: string): string;
|
|
16
|
+
/**
|
|
17
|
+
* Write the agent prompt files to disk and return their paths.
|
|
18
|
+
*/
|
|
19
|
+
export declare function writeAgentPromptFiles(services: ServiceWithContext[], existingConfig: string, schema: object, agentBudget: number, workspaceRoot: string): Promise<{
|
|
20
|
+
contextPath: string;
|
|
21
|
+
promptPath: string;
|
|
22
|
+
}>;
|
|
23
|
+
//# sourceMappingURL=agent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../../src/scan/prompt/agent.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAE1D,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,WAAW,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,kBAAkB,EAAE,EAC9B,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,aAAa,EAAE,MAAM,GACpB,MAAM,CA6DR;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,CAczE;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,kBAAkB,EAAE,EAC9B,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAoBtD"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// @nepopsx/cli — Agent-assisted mode prompt file generation
|
|
2
|
+
import { writeFile, mkdir } from 'node:fs/promises';
|
|
3
|
+
import { dirname, relative, resolve } from 'node:path';
|
|
4
|
+
/**
|
|
5
|
+
* Generate the scan-context.md file content for agent-assisted mode.
|
|
6
|
+
* Enforces agentBudget by trimming lower-tier files from largest services first.
|
|
7
|
+
*/
|
|
8
|
+
export function generateScanContextFile(services, existingConfig, schema, agentBudget, workspaceRoot) {
|
|
9
|
+
const schemaJson = JSON.stringify(schema, null, 2);
|
|
10
|
+
// Build per-service file lists and enforce the global agent budget
|
|
11
|
+
let totalTokens = 0;
|
|
12
|
+
const serviceSections = [];
|
|
13
|
+
// Sort by service token count descending so we trim the largest first when over budget
|
|
14
|
+
const sorted = [...services].sort((a, b) => b.context.totalTokens - a.context.totalTokens);
|
|
15
|
+
for (const { service, context } of sorted) {
|
|
16
|
+
const fileEntries = [];
|
|
17
|
+
for (const [relPath, content] of context.files) {
|
|
18
|
+
const tokens = Math.ceil(content.length / 3.5);
|
|
19
|
+
const absPath = resolve(workspaceRoot, service.path, relPath);
|
|
20
|
+
const relToRoot = relative(workspaceRoot, absPath);
|
|
21
|
+
fileEntries.push({ relToRoot, tokens });
|
|
22
|
+
}
|
|
23
|
+
// Trim from end (lowest-priority files) until fits within remaining budget
|
|
24
|
+
let serviceTokens = fileEntries.reduce((s, f) => s + f.tokens, 0);
|
|
25
|
+
while (totalTokens + serviceTokens > agentBudget && fileEntries.length > 0) {
|
|
26
|
+
const last = fileEntries.pop();
|
|
27
|
+
serviceTokens -= last.tokens;
|
|
28
|
+
}
|
|
29
|
+
if (fileEntries.length === 0)
|
|
30
|
+
continue;
|
|
31
|
+
totalTokens += serviceTokens;
|
|
32
|
+
const fileRefs = fileEntries.map((f) => `#file:${f.relToRoot}`).join('\n');
|
|
33
|
+
serviceSections.push(`### Service: ${service.name}\n${fileRefs}`);
|
|
34
|
+
}
|
|
35
|
+
return [
|
|
36
|
+
'# NEPOPSX Scan Context',
|
|
37
|
+
'',
|
|
38
|
+
'> Generated by `nepopsx scan --agent`. Paste this into your VS Code AI agent (GitHub Copilot, Claude, Cursor).',
|
|
39
|
+
'> After the agent responds, run: `nepopsx scan --apply <response-file.json>`',
|
|
40
|
+
'',
|
|
41
|
+
'## Task',
|
|
42
|
+
'',
|
|
43
|
+
'Analyze the source files below and return a JSON object matching the ScanResponse schema.',
|
|
44
|
+
'Return ONLY valid JSON — no markdown, no explanation, no code fences.',
|
|
45
|
+
'',
|
|
46
|
+
'## ScanResponse Schema',
|
|
47
|
+
'',
|
|
48
|
+
'```json',
|
|
49
|
+
schemaJson,
|
|
50
|
+
'```',
|
|
51
|
+
'',
|
|
52
|
+
'## Existing Workspace Config',
|
|
53
|
+
'',
|
|
54
|
+
'```yaml',
|
|
55
|
+
existingConfig,
|
|
56
|
+
'```',
|
|
57
|
+
'',
|
|
58
|
+
'## Source Files',
|
|
59
|
+
'',
|
|
60
|
+
serviceSections.join('\n\n'),
|
|
61
|
+
].join('\n');
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Generate the .github/prompts/nepopsx-scan.prompt.md Copilot prompt file content.
|
|
65
|
+
*/
|
|
66
|
+
export function generateCopilotPromptFile(contextFilePath) {
|
|
67
|
+
return [
|
|
68
|
+
'---',
|
|
69
|
+
'mode: ask',
|
|
70
|
+
'description: NEPOPSX workspace scan — analyze services and return structured JSON',
|
|
71
|
+
'---',
|
|
72
|
+
'',
|
|
73
|
+
'Analyze the workspace services described in the scan context file and return a ScanResponse JSON object.',
|
|
74
|
+
'',
|
|
75
|
+
`#file:${contextFilePath}`,
|
|
76
|
+
'',
|
|
77
|
+
'Return ONLY valid JSON matching the ScanResponse schema defined in the context file.',
|
|
78
|
+
'Do not include any explanation, markdown, or code fences — just raw JSON.',
|
|
79
|
+
].join('\n');
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Write the agent prompt files to disk and return their paths.
|
|
83
|
+
*/
|
|
84
|
+
export async function writeAgentPromptFiles(services, existingConfig, schema, agentBudget, workspaceRoot) {
|
|
85
|
+
const contextPath = resolve(workspaceRoot, '.nepopsx', 'scan-context.md');
|
|
86
|
+
const promptPath = resolve(workspaceRoot, '.github', 'prompts', 'nepopsx-scan.prompt.md');
|
|
87
|
+
const contextContent = generateScanContextFile(services, existingConfig, schema, agentBudget, workspaceRoot);
|
|
88
|
+
const promptContent = generateCopilotPromptFile('.nepopsx/scan-context.md');
|
|
89
|
+
await mkdir(dirname(contextPath), { recursive: true });
|
|
90
|
+
await writeFile(contextPath, contextContent, 'utf-8');
|
|
91
|
+
await mkdir(dirname(promptPath), { recursive: true });
|
|
92
|
+
await writeFile(promptPath, promptContent, 'utf-8');
|
|
93
|
+
return { contextPath, promptPath };
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../../../src/scan/prompt/agent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Service } from '@nepopsx/core';
|
|
2
|
+
import type { ServiceScanResult } from '@nepopsx/core';
|
|
3
|
+
import type { FileContext } from '../context/gatherer.js';
|
|
4
|
+
export interface BuiltPrompt {
|
|
5
|
+
systemPrompt: string;
|
|
6
|
+
userPrompt: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Build the per-service analysis prompt.
|
|
10
|
+
*/
|
|
11
|
+
export declare function buildServicePrompt(service: Service, context: FileContext, existingConfig: string, schema: object): BuiltPrompt;
|
|
12
|
+
/**
|
|
13
|
+
* Build the cross-service synthesis prompt using per-service results as summaries.
|
|
14
|
+
*/
|
|
15
|
+
export declare function buildCrossServicePrompt(serviceResults: ServiceScanResult[], existingConfig: string, schema: object): BuiltPrompt;
|
|
16
|
+
//# sourceMappingURL=builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../../src/scan/prompt/builder.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAE1D,MAAM,WAAW,WAAW;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,WAAW,EACpB,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,MAAM,GACb,WAAW,CAiCb;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,cAAc,EAAE,iBAAiB,EAAE,EACnC,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,MAAM,GACb,WAAW,CAiCb"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build the per-service analysis prompt.
|
|
3
|
+
*/
|
|
4
|
+
export function buildServicePrompt(service, context, existingConfig, schema) {
|
|
5
|
+
const systemPrompt = 'You are a senior software architect analyzing a codebase to extract structured metadata.\n' +
|
|
6
|
+
'Your job is to analyze the provided source files and return a JSON object matching the provided schema exactly.\n' +
|
|
7
|
+
'Return ONLY valid JSON — no markdown, no explanation, no code fences. Just raw JSON.';
|
|
8
|
+
const fileContents = Array.from(context.files.entries())
|
|
9
|
+
.map(([path, content]) => `### File: ${path}\n\`\`\`\n${content}\n\`\`\``)
|
|
10
|
+
.join('\n\n');
|
|
11
|
+
const userPrompt = [
|
|
12
|
+
`Analyze the following source files for the service named "${service.name}" and return a JSON object matching this schema:`,
|
|
13
|
+
'',
|
|
14
|
+
'## Schema (ServiceScanResult)',
|
|
15
|
+
'```json',
|
|
16
|
+
JSON.stringify(schema, null, 2),
|
|
17
|
+
'```',
|
|
18
|
+
'',
|
|
19
|
+
'## Existing workspace config for context',
|
|
20
|
+
'```yaml',
|
|
21
|
+
existingConfig,
|
|
22
|
+
'```',
|
|
23
|
+
'',
|
|
24
|
+
'## Source Files',
|
|
25
|
+
'',
|
|
26
|
+
fileContents,
|
|
27
|
+
'',
|
|
28
|
+
`Return a JSON object for this service. The "service_name" field must be "${service.name}".`,
|
|
29
|
+
'All string fields should be concise (1-2 sentences max).',
|
|
30
|
+
'For "confidence", rate each field you filled: "low", "medium", or "high".',
|
|
31
|
+
].join('\n');
|
|
32
|
+
return { systemPrompt, userPrompt };
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Build the cross-service synthesis prompt using per-service results as summaries.
|
|
36
|
+
*/
|
|
37
|
+
export function buildCrossServicePrompt(serviceResults, existingConfig, schema) {
|
|
38
|
+
const systemPrompt = 'You are a senior software architect analyzing a multi-service workspace to extract cross-cutting metadata.\n' +
|
|
39
|
+
'Return ONLY valid JSON — no markdown, no explanation, no code fences.';
|
|
40
|
+
const summaries = serviceResults
|
|
41
|
+
.map((r) => `- **${r.service_name}**: ${r.description ?? 'No description'} | databases: ${(r.databases ?? []).map((d) => d.name).join(', ') || 'none'}`)
|
|
42
|
+
.join('\n');
|
|
43
|
+
const userPrompt = [
|
|
44
|
+
'Based on the per-service analysis results below, produce a cross-service summary matching this schema:',
|
|
45
|
+
'',
|
|
46
|
+
'## Schema (CrossServiceScanResult)',
|
|
47
|
+
'```json',
|
|
48
|
+
JSON.stringify(schema, null, 2),
|
|
49
|
+
'```',
|
|
50
|
+
'',
|
|
51
|
+
'## Existing workspace config',
|
|
52
|
+
'```yaml',
|
|
53
|
+
existingConfig,
|
|
54
|
+
'```',
|
|
55
|
+
'',
|
|
56
|
+
'## Per-service results summary',
|
|
57
|
+
summaries,
|
|
58
|
+
'',
|
|
59
|
+
'Return a JSON object matching the CrossServiceScanResult schema.',
|
|
60
|
+
'Focus on: execution order, shared databases, workspace-wide conventions.',
|
|
61
|
+
].join('\n');
|
|
62
|
+
return { systemPrompt, userPrompt };
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builder.js","sourceRoot":"","sources":["../../../src/scan/prompt/builder.ts"],"names":[],"mappings":"AAUA;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAChC,OAAgB,EAChB,OAAoB,EACpB,cAAsB,EACtB,MAAc;IAEd,MAAM,YAAY,GAChB,4FAA4F;QAC5F,mHAAmH;QACnH,sFAAsF,CAAC;IAEzF,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;SACrD,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,aAAa,IAAI,aAAa,OAAO,UAAU,CAAC;SACzE,IAAI,CAAC,MAAM,CAAC,CAAC;IAEhB,MAAM,UAAU,GAAG;QACjB,6DAA6D,OAAO,CAAC,IAAI,kDAAkD;QAC3H,EAAE;QACF,+BAA+B;QAC/B,SAAS;QACT,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/B,KAAK;QACL,EAAE;QACF,0CAA0C;QAC1C,SAAS;QACT,cAAc;QACd,KAAK;QACL,EAAE;QACF,iBAAiB;QACjB,EAAE;QACF,YAAY;QACZ,EAAE;QACF,4EAA4E,OAAO,CAAC,IAAI,IAAI;QAC5F,0DAA0D;QAC1D,2EAA2E;KAC5E,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEb,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC;AACtC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB,CACrC,cAAmC,EACnC,cAAsB,EACtB,MAAc;IAEd,MAAM,YAAY,GAChB,8GAA8G;QAC9G,uEAAuE,CAAC;IAE1E,MAAM,SAAS,GAAG,cAAc;SAC7B,GAAG,CACF,CAAC,CAAC,EAAE,EAAE,CACJ,OAAO,CAAC,CAAC,YAAY,OAAO,CAAC,CAAC,WAAW,IAAI,gBAAgB,iBAAiB,CAAC,CAAC,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM,EAAE,CAC9I;SACA,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,MAAM,UAAU,GAAG;QACjB,wGAAwG;QACxG,EAAE;QACF,oCAAoC;QACpC,SAAS;QACT,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/B,KAAK;QACL,EAAE;QACF,8BAA8B;QAC9B,SAAS;QACT,cAAc;QACd,KAAK;QACL,EAAE;QACF,gCAAgC;QAChC,SAAS;QACT,EAAE;QACF,kEAAkE;QAClE,0EAA0E;KAC3E,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEb,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC;AACtC,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Full ScanResponse JSON schema */
|
|
2
|
+
export declare function getScanResponseSchema(): Record<string, unknown>;
|
|
3
|
+
/** Per-service subset (ServiceScanResult) */
|
|
4
|
+
export declare function getServiceScanSchema(): Record<string, unknown>;
|
|
5
|
+
/** Cross-service subset (CrossServiceScanResult) */
|
|
6
|
+
export declare function getCrossServiceScanSchema(): Record<string, unknown>;
|
|
7
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/scan/prompt/schema.ts"],"names":[],"mappings":"AAgCA,oCAAoC;AACpC,wBAAgB,qBAAqB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAE/D;AAED,6CAA6C;AAC7C,wBAAgB,oBAAoB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAQ9D;AAED,oDAAoD;AACpD,wBAAgB,yBAAyB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAQnE"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// @nepopsx/cli — Embed scan response JSON schema into prompts
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
import { dirname, join } from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
// Cache the schema after first load
|
|
7
|
+
let _schema = null;
|
|
8
|
+
function loadSchema() {
|
|
9
|
+
if (_schema)
|
|
10
|
+
return _schema;
|
|
11
|
+
// Resolve candidates from workspace-local paths (monorepo) and installed package paths
|
|
12
|
+
const candidates = [
|
|
13
|
+
join(__dirname, '..', '..', '..', '..', '..', 'core', 'dist', 'schema', 'scan-response.schema.json'),
|
|
14
|
+
join(__dirname, '..', '..', '..', '..', '..', 'core', 'src', 'schema', 'scan-response.schema.json'),
|
|
15
|
+
join(__dirname, '..', '..', '..', 'node_modules', '@nepopsx', 'core', 'dist', 'schema', 'scan-response.schema.json'),
|
|
16
|
+
];
|
|
17
|
+
for (const p of candidates) {
|
|
18
|
+
try {
|
|
19
|
+
_schema = JSON.parse(readFileSync(p, 'utf-8'));
|
|
20
|
+
return _schema;
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
// Try next candidate
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
throw new Error('Could not locate scan-response.schema.json. Run `pnpm build` in @nepopsx/core first.');
|
|
27
|
+
}
|
|
28
|
+
/** Full ScanResponse JSON schema */
|
|
29
|
+
export function getScanResponseSchema() {
|
|
30
|
+
return loadSchema();
|
|
31
|
+
}
|
|
32
|
+
/** Per-service subset (ServiceScanResult) */
|
|
33
|
+
export function getServiceScanSchema() {
|
|
34
|
+
const full = loadSchema();
|
|
35
|
+
const defs = full.$defs;
|
|
36
|
+
return {
|
|
37
|
+
$schema: 'http://json-schema.org/draft-07/schema#',
|
|
38
|
+
...(defs?.['ServiceScanResult'] ?? {}),
|
|
39
|
+
$defs: defs,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/** Cross-service subset (CrossServiceScanResult) */
|
|
43
|
+
export function getCrossServiceScanSchema() {
|
|
44
|
+
const full = loadSchema();
|
|
45
|
+
const defs = full.$defs;
|
|
46
|
+
return {
|
|
47
|
+
$schema: 'http://json-schema.org/draft-07/schema#',
|
|
48
|
+
...(defs?.['CrossServiceScanResult'] ?? {}),
|
|
49
|
+
$defs: defs,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/scan/prompt/schema.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAE1D,oCAAoC;AACpC,IAAI,OAAO,GAAmC,IAAI,CAAC;AAEnD,SAAS,UAAU;IACjB,IAAI,OAAO;QAAE,OAAO,OAAO,CAAC;IAE5B,uFAAuF;IACvF,MAAM,UAAU,GAAG;QACjB,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,2BAA2B,CAAC;QACpG,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,2BAA2B,CAAC;QACnG,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,2BAA2B,CAAC;KACrH,CAAC;IAEF,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,IAAI,CAAC;YACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,EAAE,OAAO,CAAC,CAA4B,CAAC;YAC1E,OAAO,OAAO,CAAC;QACjB,CAAC;QAAC,MAAM,CAAC;YACP,qBAAqB;QACvB,CAAC;IACH,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,sFAAsF,CAAC,CAAC;AAC1G,CAAC;AAED,oCAAoC;AACpC,MAAM,UAAU,qBAAqB;IACnC,OAAO,UAAU,EAAE,CAAC;AACtB,CAAC;AAED,6CAA6C;AAC7C,MAAM,UAAU,oBAAoB;IAClC,MAAM,IAAI,GAAG,UAAU,EAAE,CAAC;IAC1B,MAAM,IAAI,GAAG,IAAI,CAAC,KAA4C,CAAC;IAC/D,OAAO;QACL,OAAO,EAAE,yCAAyC;QAClD,GAAG,CAAE,IAAI,EAAE,CAAC,mBAAmB,CAA6B,IAAI,EAAE,CAAC;QACnE,KAAK,EAAE,IAAI;KACZ,CAAC;AACJ,CAAC;AAED,oDAAoD;AACpD,MAAM,UAAU,yBAAyB;IACvC,MAAM,IAAI,GAAG,UAAU,EAAE,CAAC;IAC1B,MAAM,IAAI,GAAG,IAAI,CAAC,KAA4C,CAAC;IAC/D,OAAO;QACL,OAAO,EAAE,yCAAyC;QAClD,GAAG,CAAE,IAAI,EAAE,CAAC,wBAAwB,CAA6B,IAAI,EAAE,CAAC;QACxE,KAAK,EAAE,IAAI;KACZ,CAAC;AACJ,CAAC"}
|