structx 1.0.0
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/benchmark/baseline.d.ts +10 -0
- package/dist/benchmark/baseline.d.ts.map +1 -0
- package/dist/benchmark/baseline.js +84 -0
- package/dist/benchmark/baseline.js.map +1 -0
- package/dist/benchmark/questions.d.ts +2 -0
- package/dist/benchmark/questions.d.ts.map +1 -0
- package/dist/benchmark/questions.js +14 -0
- package/dist/benchmark/questions.js.map +1 -0
- package/dist/benchmark/reporter.d.ts +8 -0
- package/dist/benchmark/reporter.d.ts.map +1 -0
- package/dist/benchmark/reporter.js +120 -0
- package/dist/benchmark/reporter.js.map +1 -0
- package/dist/benchmark/runner.d.ts +24 -0
- package/dist/benchmark/runner.d.ts.map +1 -0
- package/dist/benchmark/runner.js +110 -0
- package/dist/benchmark/runner.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +753 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +15 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +83 -0
- package/dist/config.js.map +1 -0
- package/dist/db/connection.d.ts +5 -0
- package/dist/db/connection.d.ts.map +1 -0
- package/dist/db/connection.js +89 -0
- package/dist/db/connection.js.map +1 -0
- package/dist/db/queries.d.ts +122 -0
- package/dist/db/queries.d.ts.map +1 -0
- package/dist/db/queries.js +191 -0
- package/dist/db/queries.js.map +1 -0
- package/dist/db/schema.sql +85 -0
- package/dist/ingest/differ.d.ts +13 -0
- package/dist/ingest/differ.d.ts.map +1 -0
- package/dist/ingest/differ.js +63 -0
- package/dist/ingest/differ.js.map +1 -0
- package/dist/ingest/parser.d.ts +15 -0
- package/dist/ingest/parser.d.ts.map +1 -0
- package/dist/ingest/parser.js +154 -0
- package/dist/ingest/parser.js.map +1 -0
- package/dist/ingest/relationships.d.ts +8 -0
- package/dist/ingest/relationships.d.ts.map +1 -0
- package/dist/ingest/relationships.js +93 -0
- package/dist/ingest/relationships.js.map +1 -0
- package/dist/ingest/scanner.d.ts +2 -0
- package/dist/ingest/scanner.d.ts.map +1 -0
- package/dist/ingest/scanner.js +67 -0
- package/dist/ingest/scanner.js.map +1 -0
- package/dist/instructions/claude.md +41 -0
- package/dist/instructions/copilot.md +39 -0
- package/dist/instructions/cursor.md +39 -0
- package/dist/instructions/generic.md +41 -0
- package/dist/query/answerer.d.ts +9 -0
- package/dist/query/answerer.d.ts.map +1 -0
- package/dist/query/answerer.js +46 -0
- package/dist/query/answerer.js.map +1 -0
- package/dist/query/classifier.d.ts +10 -0
- package/dist/query/classifier.d.ts.map +1 -0
- package/dist/query/classifier.js +60 -0
- package/dist/query/classifier.js.map +1 -0
- package/dist/query/context-builder.d.ts +3 -0
- package/dist/query/context-builder.d.ts.map +1 -0
- package/dist/query/context-builder.js +104 -0
- package/dist/query/context-builder.js.map +1 -0
- package/dist/query/retriever.d.ts +23 -0
- package/dist/query/retriever.d.ts.map +1 -0
- package/dist/query/retriever.js +142 -0
- package/dist/query/retriever.js.map +1 -0
- package/dist/semantic/analyzer.d.ts +15 -0
- package/dist/semantic/analyzer.d.ts.map +1 -0
- package/dist/semantic/analyzer.js +179 -0
- package/dist/semantic/analyzer.js.map +1 -0
- package/dist/semantic/cost.d.ts +11 -0
- package/dist/semantic/cost.d.ts.map +1 -0
- package/dist/semantic/cost.js +31 -0
- package/dist/semantic/cost.js.map +1 -0
- package/dist/semantic/prompt.d.ts +11 -0
- package/dist/semantic/prompt.d.ts.map +1 -0
- package/dist/semantic/prompt.js +71 -0
- package/dist/semantic/prompt.js.map +1 -0
- package/dist/semantic/validator.d.ts +15 -0
- package/dist/semantic/validator.d.ts.map +1 -0
- package/dist/semantic/validator.js +95 -0
- package/dist/semantic/validator.js.map +1 -0
- package/dist/utils/logger.d.ts +9 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +48 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/tokens.d.ts +3 -0
- package/dist/utils/tokens.d.ts.map +1 -0
- package/dist/utils/tokens.js +21 -0
- package/dist/utils/tokens.js.map +1 -0
- package/package.json +39 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.analyzeBatch = analyzeBatch;
|
|
7
|
+
exports.rebuildSearchIndex = rebuildSearchIndex;
|
|
8
|
+
const sdk_1 = __importDefault(require("@anthropic-ai/sdk"));
|
|
9
|
+
const queries_1 = require("../db/queries");
|
|
10
|
+
const prompt_1 = require("./prompt");
|
|
11
|
+
const validator_1 = require("./validator");
|
|
12
|
+
const tokens_1 = require("../utils/tokens");
|
|
13
|
+
const logger_1 = require("../utils/logger");
|
|
14
|
+
async function analyzeBatch(db, queueItems, model, apiKey) {
|
|
15
|
+
const client = new sdk_1.default({ apiKey });
|
|
16
|
+
const result = { analyzed: 0, cached: 0, failed: 0, totalInputTokens: 0, totalOutputTokens: 0, totalCost: 0 };
|
|
17
|
+
// Build prompt functions from queue items
|
|
18
|
+
const promptFunctions = [];
|
|
19
|
+
const functionMap = new Map();
|
|
20
|
+
for (const item of queueItems) {
|
|
21
|
+
const fn = (0, queries_1.getFunctionById)(db, item.function_id);
|
|
22
|
+
if (!fn) {
|
|
23
|
+
(0, queries_1.updateAnalysisStatus)(db, item.id, 'failed');
|
|
24
|
+
result.failed++;
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
// Get file path for location
|
|
28
|
+
const file = db.prepare('SELECT path FROM files WHERE id = ?').get(fn.file_id);
|
|
29
|
+
const location = file ? `${file.path}:${fn.start_line}` : `unknown:${fn.start_line}`;
|
|
30
|
+
// Get calls
|
|
31
|
+
const callees = (0, queries_1.getCallees)(db, fn.id);
|
|
32
|
+
const callers = (0, queries_1.getCallersByName)(db, fn.name);
|
|
33
|
+
promptFunctions.push({
|
|
34
|
+
function_name: fn.name,
|
|
35
|
+
location,
|
|
36
|
+
signature: fn.signature,
|
|
37
|
+
code: fn.body,
|
|
38
|
+
calls: callees.map(c => c.callee_name),
|
|
39
|
+
called_by: callers.map(c => {
|
|
40
|
+
const callerFn = (0, queries_1.getFunctionById)(db, c.caller_function_id);
|
|
41
|
+
return callerFn?.name || 'unknown';
|
|
42
|
+
}),
|
|
43
|
+
});
|
|
44
|
+
functionMap.set(fn.name, { queueId: item.id, functionId: fn.id });
|
|
45
|
+
}
|
|
46
|
+
if (promptFunctions.length === 0)
|
|
47
|
+
return result;
|
|
48
|
+
const prompt = (0, prompt_1.buildBatchPrompt)(promptFunctions);
|
|
49
|
+
const promptHash = (0, prompt_1.hashPrompt)(prompt);
|
|
50
|
+
// Check cache for each function
|
|
51
|
+
const uncachedFunctions = [];
|
|
52
|
+
const cachedResults = [];
|
|
53
|
+
for (const pf of promptFunctions) {
|
|
54
|
+
const mapping = functionMap.get(pf.function_name);
|
|
55
|
+
const cached = (0, queries_1.getCachedResponse)(db, mapping.functionId, promptHash);
|
|
56
|
+
if (cached) {
|
|
57
|
+
try {
|
|
58
|
+
const parsed = JSON.parse(cached.response_json);
|
|
59
|
+
cachedResults.push(parsed);
|
|
60
|
+
(0, queries_1.updateAnalysisStatus)(db, mapping.queueId, 'done');
|
|
61
|
+
applySemanticResult(db, mapping.functionId, parsed);
|
|
62
|
+
result.cached++;
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
uncachedFunctions.push(pf);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
uncachedFunctions.push(pf);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
// If everything was cached, done
|
|
73
|
+
if (uncachedFunctions.length === 0) {
|
|
74
|
+
return result;
|
|
75
|
+
}
|
|
76
|
+
// Build prompt for uncached functions only
|
|
77
|
+
const batchPrompt = (0, prompt_1.buildBatchPrompt)(uncachedFunctions);
|
|
78
|
+
const batchPromptHash = (0, prompt_1.hashPrompt)(batchPrompt);
|
|
79
|
+
// Call LLM
|
|
80
|
+
let responseText;
|
|
81
|
+
let inputTokens = 0;
|
|
82
|
+
let outputTokens = 0;
|
|
83
|
+
try {
|
|
84
|
+
const response = await client.messages.create({
|
|
85
|
+
model,
|
|
86
|
+
max_tokens: uncachedFunctions.length * 200,
|
|
87
|
+
messages: [{ role: 'user', content: batchPrompt }],
|
|
88
|
+
});
|
|
89
|
+
responseText = response.content
|
|
90
|
+
.filter(block => block.type === 'text')
|
|
91
|
+
.map(block => block.text)
|
|
92
|
+
.join('');
|
|
93
|
+
inputTokens = response.usage?.input_tokens ?? 0;
|
|
94
|
+
outputTokens = response.usage?.output_tokens ?? 0;
|
|
95
|
+
result.totalInputTokens += inputTokens;
|
|
96
|
+
result.totalOutputTokens += outputTokens;
|
|
97
|
+
result.totalCost += (0, tokens_1.estimateCost)(model, inputTokens, outputTokens);
|
|
98
|
+
}
|
|
99
|
+
catch (err) {
|
|
100
|
+
logger_1.logger.error(`LLM API call failed: ${err.message}`);
|
|
101
|
+
for (const pf of uncachedFunctions) {
|
|
102
|
+
const mapping = functionMap.get(pf.function_name);
|
|
103
|
+
if (mapping) {
|
|
104
|
+
(0, queries_1.updateAnalysisStatus)(db, mapping.queueId, 'failed');
|
|
105
|
+
result.failed++;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return result;
|
|
109
|
+
}
|
|
110
|
+
// Validate response
|
|
111
|
+
let validation = (0, validator_1.validateSemanticResponse)(responseText);
|
|
112
|
+
// Retry once on failure
|
|
113
|
+
if (!validation.valid && validation.results.length === 0) {
|
|
114
|
+
logger_1.logger.warn(`Validation failed, retrying. Errors: ${validation.errors.join('; ')}`);
|
|
115
|
+
try {
|
|
116
|
+
const retryResponse = await client.messages.create({
|
|
117
|
+
model,
|
|
118
|
+
max_tokens: uncachedFunctions.length * 200,
|
|
119
|
+
messages: [
|
|
120
|
+
{ role: 'user', content: batchPrompt },
|
|
121
|
+
{ role: 'assistant', content: responseText },
|
|
122
|
+
{ role: 'user', content: `Your previous response had JSON errors: ${validation.errors.join('; ')}. Please respond with ONLY a valid JSON array.` },
|
|
123
|
+
],
|
|
124
|
+
});
|
|
125
|
+
const retryText = retryResponse.content
|
|
126
|
+
.filter(block => block.type === 'text')
|
|
127
|
+
.map(block => block.text)
|
|
128
|
+
.join('');
|
|
129
|
+
result.totalInputTokens += retryResponse.usage?.input_tokens ?? 0;
|
|
130
|
+
result.totalOutputTokens += retryResponse.usage?.output_tokens ?? 0;
|
|
131
|
+
result.totalCost += (0, tokens_1.estimateCost)(model, retryResponse.usage?.input_tokens ?? 0, retryResponse.usage?.output_tokens ?? 0);
|
|
132
|
+
validation = (0, validator_1.validateSemanticResponse)(retryText);
|
|
133
|
+
if (validation.valid || validation.results.length > 0) {
|
|
134
|
+
responseText = retryText;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
catch (retryErr) {
|
|
138
|
+
logger_1.logger.error(`Retry failed: ${retryErr.message}`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
// Apply results
|
|
142
|
+
for (const semanticResult of validation.results) {
|
|
143
|
+
const mapping = functionMap.get(semanticResult.function_name);
|
|
144
|
+
if (!mapping) {
|
|
145
|
+
logger_1.logger.warn(`No mapping found for function: ${semanticResult.function_name}`);
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
applySemanticResult(db, mapping.functionId, semanticResult);
|
|
149
|
+
(0, queries_1.updateAnalysisStatus)(db, mapping.queueId, 'done');
|
|
150
|
+
// Cache the result
|
|
151
|
+
(0, queries_1.insertCachedResponse)(db, mapping.functionId, batchPromptHash, model, inputTokens, outputTokens, result.totalCost, JSON.stringify(semanticResult));
|
|
152
|
+
result.analyzed++;
|
|
153
|
+
}
|
|
154
|
+
// Mark any unmatched as failed
|
|
155
|
+
for (const pf of uncachedFunctions) {
|
|
156
|
+
const mapping = functionMap.get(pf.function_name);
|
|
157
|
+
if (!mapping)
|
|
158
|
+
continue;
|
|
159
|
+
const matched = validation.results.some(r => r.function_name === pf.function_name);
|
|
160
|
+
if (!matched) {
|
|
161
|
+
(0, queries_1.updateAnalysisStatus)(db, mapping.queueId, 'failed');
|
|
162
|
+
result.failed++;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return result;
|
|
166
|
+
}
|
|
167
|
+
function applySemanticResult(db, functionId, result) {
|
|
168
|
+
(0, queries_1.updateSemanticFields)(db, functionId, {
|
|
169
|
+
purpose: result.purpose,
|
|
170
|
+
behavior_summary: result.behavior,
|
|
171
|
+
side_effects_json: JSON.stringify(result.side_effects),
|
|
172
|
+
domain: result.domain,
|
|
173
|
+
complexity: result.complexity,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
function rebuildSearchIndex(db) {
|
|
177
|
+
(0, queries_1.rebuildFtsIndex)(db);
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=analyzer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyzer.js","sourceRoot":"","sources":["../../src/semantic/analyzer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface CostEstimate {
|
|
2
|
+
totalFunctions: number;
|
|
3
|
+
batches: number;
|
|
4
|
+
estimatedInputTokens: number;
|
|
5
|
+
estimatedOutputTokens: number;
|
|
6
|
+
estimatedCost: number;
|
|
7
|
+
model: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function estimateAnalysisCost(functionCount: number, batchSize: number, model: string): CostEstimate;
|
|
10
|
+
export declare function formatCostEstimate(estimate: CostEstimate): string;
|
|
11
|
+
//# sourceMappingURL=cost.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cost.d.ts","sourceRoot":"","sources":["../../src/semantic/cost.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,YAAY;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,qBAAqB,EAAE,MAAM,CAAC;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,oBAAoB,CAClC,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,GACZ,YAAY,CAoBd;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,CAOjE"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.estimateAnalysisCost = estimateAnalysisCost;
|
|
4
|
+
exports.formatCostEstimate = formatCostEstimate;
|
|
5
|
+
const tokens_1 = require("../utils/tokens");
|
|
6
|
+
function estimateAnalysisCost(functionCount, batchSize, model) {
|
|
7
|
+
const batches = Math.ceil(functionCount / batchSize);
|
|
8
|
+
// ~400 input tokens per function + 200 overhead per batch
|
|
9
|
+
const inputTokensPerBatch = batchSize * 400 + 200;
|
|
10
|
+
const estimatedInputTokens = batches * inputTokensPerBatch;
|
|
11
|
+
// ~100 output tokens per function
|
|
12
|
+
const estimatedOutputTokens = functionCount * 100;
|
|
13
|
+
const estimatedCost = (0, tokens_1.estimateCost)(model, estimatedInputTokens, estimatedOutputTokens);
|
|
14
|
+
return {
|
|
15
|
+
totalFunctions: functionCount,
|
|
16
|
+
batches,
|
|
17
|
+
estimatedInputTokens,
|
|
18
|
+
estimatedOutputTokens,
|
|
19
|
+
estimatedCost,
|
|
20
|
+
model,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function formatCostEstimate(estimate) {
|
|
24
|
+
return [
|
|
25
|
+
`Functions to analyze: ${estimate.totalFunctions}`,
|
|
26
|
+
`Batches: ${estimate.batches}`,
|
|
27
|
+
`Estimated tokens: ~${(estimate.estimatedInputTokens + estimate.estimatedOutputTokens).toLocaleString()} total`,
|
|
28
|
+
`Estimated cost: $${estimate.estimatedCost.toFixed(4)} (using ${estimate.model})`,
|
|
29
|
+
].join('\n');
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=cost.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cost.js","sourceRoot":"","sources":["../../src/semantic/cost.ts"],"names":[],"mappings":";;AAWA,oDAwBC;AAED,gDAOC;AA5CD,4CAA+D;AAW/D,SAAgB,oBAAoB,CAClC,aAAqB,EACrB,SAAiB,EACjB,KAAa;IAEb,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,GAAG,SAAS,CAAC,CAAC;IAErD,0DAA0D;IAC1D,MAAM,mBAAmB,GAAG,SAAS,GAAG,GAAG,GAAG,GAAG,CAAC;IAClD,MAAM,oBAAoB,GAAG,OAAO,GAAG,mBAAmB,CAAC;IAE3D,kCAAkC;IAClC,MAAM,qBAAqB,GAAG,aAAa,GAAG,GAAG,CAAC;IAElD,MAAM,aAAa,GAAG,IAAA,qBAAY,EAAC,KAAK,EAAE,oBAAoB,EAAE,qBAAqB,CAAC,CAAC;IAEvF,OAAO;QACL,cAAc,EAAE,aAAa;QAC7B,OAAO;QACP,oBAAoB;QACpB,qBAAqB;QACrB,aAAa;QACb,KAAK;KACN,CAAC;AACJ,CAAC;AAED,SAAgB,kBAAkB,CAAC,QAAsB;IACvD,OAAO;QACL,yBAAyB,QAAQ,CAAC,cAAc,EAAE;QAClD,YAAY,QAAQ,CAAC,OAAO,EAAE;QAC9B,sBAAsB,CAAC,QAAQ,CAAC,oBAAoB,GAAG,QAAQ,CAAC,qBAAqB,CAAC,CAAC,cAAc,EAAE,QAAQ;QAC/G,oBAAoB,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,QAAQ,CAAC,KAAK,GAAG;KAClF,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface PromptFunction {
|
|
2
|
+
function_name: string;
|
|
3
|
+
location: string;
|
|
4
|
+
signature: string;
|
|
5
|
+
code: string;
|
|
6
|
+
calls: string[];
|
|
7
|
+
called_by: string[];
|
|
8
|
+
}
|
|
9
|
+
export declare function buildBatchPrompt(functions: PromptFunction[]): string;
|
|
10
|
+
export declare function hashPrompt(prompt: string): string;
|
|
11
|
+
//# sourceMappingURL=prompt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../src/semantic/prompt.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,cAAc;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,cAAc,EAAE,GAAG,MAAM,CA6BpE;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEjD"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.buildBatchPrompt = buildBatchPrompt;
|
|
37
|
+
exports.hashPrompt = hashPrompt;
|
|
38
|
+
const crypto = __importStar(require("crypto"));
|
|
39
|
+
function buildBatchPrompt(functions) {
|
|
40
|
+
const functionsBlock = functions.map((fn, i) => `
|
|
41
|
+
Function ${i + 1}: ${fn.function_name}
|
|
42
|
+
Location: ${fn.location}
|
|
43
|
+
Signature: ${fn.signature}
|
|
44
|
+
Code:
|
|
45
|
+
\`\`\`typescript
|
|
46
|
+
${fn.code}
|
|
47
|
+
\`\`\`
|
|
48
|
+
Context:
|
|
49
|
+
- Calls: ${fn.calls.length > 0 ? fn.calls.join(', ') : 'none'}
|
|
50
|
+
- Called by: ${fn.called_by.length > 0 ? fn.called_by.join(', ') : 'none'}
|
|
51
|
+
`).join('\n---\n');
|
|
52
|
+
return `Analyze the following TypeScript functions. For each function, extract structured metadata.
|
|
53
|
+
|
|
54
|
+
${functionsBlock}
|
|
55
|
+
|
|
56
|
+
Respond ONLY with a JSON array, no markdown, no explanation:
|
|
57
|
+
[
|
|
58
|
+
{
|
|
59
|
+
"function_name": "exact_name_from_above",
|
|
60
|
+
"purpose": "One sentence describing what this function does",
|
|
61
|
+
"side_effects": ["list of side effects like DB writes, network calls, console output"],
|
|
62
|
+
"behavior": "2-3 sentence description of how the function works step by step",
|
|
63
|
+
"domain": "one of: authentication, database, validation, routing, middleware, utility, logging, session, crypto, ui, api, config, testing, other",
|
|
64
|
+
"complexity": "low | medium | high"
|
|
65
|
+
}
|
|
66
|
+
]`;
|
|
67
|
+
}
|
|
68
|
+
function hashPrompt(prompt) {
|
|
69
|
+
return crypto.createHash('sha256').update(prompt).digest('hex');
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=prompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../src/semantic/prompt.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAYA,4CA6BC;AAED,gCAEC;AA5CD,+CAAiC;AAWjC,SAAgB,gBAAgB,CAAC,SAA2B;IAC1D,MAAM,cAAc,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;WACvC,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,aAAa;YACzB,EAAE,CAAC,QAAQ;aACV,EAAE,CAAC,SAAS;;;EAGvB,EAAE,CAAC,IAAI;;;WAGE,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM;eAC9C,EAAE,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM;CACxE,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAEjB,OAAO;;EAEP,cAAc;;;;;;;;;;;;EAYd,CAAC;AACH,CAAC;AAED,SAAgB,UAAU,CAAC,MAAc;IACvC,OAAO,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAClE,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface SemanticResult {
|
|
2
|
+
function_name: string;
|
|
3
|
+
purpose: string;
|
|
4
|
+
side_effects: string[];
|
|
5
|
+
behavior: string;
|
|
6
|
+
domain: string;
|
|
7
|
+
complexity: string;
|
|
8
|
+
}
|
|
9
|
+
export interface ValidationResult {
|
|
10
|
+
valid: boolean;
|
|
11
|
+
results: SemanticResult[];
|
|
12
|
+
errors: string[];
|
|
13
|
+
}
|
|
14
|
+
export declare function validateSemanticResponse(responseText: string): ValidationResult;
|
|
15
|
+
//# sourceMappingURL=validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/semantic/validator.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,cAAc;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,wBAAgB,wBAAwB,CAAC,YAAY,EAAE,MAAM,GAAG,gBAAgB,CAuF/E"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateSemanticResponse = validateSemanticResponse;
|
|
4
|
+
const VALID_DOMAINS = new Set([
|
|
5
|
+
'authentication', 'database', 'validation', 'routing', 'middleware',
|
|
6
|
+
'utility', 'logging', 'session', 'crypto', 'ui', 'api', 'config',
|
|
7
|
+
'testing', 'other',
|
|
8
|
+
]);
|
|
9
|
+
const VALID_COMPLEXITY = new Set(['low', 'medium', 'high']);
|
|
10
|
+
function validateSemanticResponse(responseText) {
|
|
11
|
+
const errors = [];
|
|
12
|
+
// Try to extract JSON from the response
|
|
13
|
+
let parsed;
|
|
14
|
+
try {
|
|
15
|
+
// Handle cases where LLM wraps in markdown code blocks
|
|
16
|
+
const cleaned = responseText
|
|
17
|
+
.replace(/^```json?\s*/m, '')
|
|
18
|
+
.replace(/```\s*$/m, '')
|
|
19
|
+
.trim();
|
|
20
|
+
parsed = JSON.parse(cleaned);
|
|
21
|
+
}
|
|
22
|
+
catch (e) {
|
|
23
|
+
return { valid: false, results: [], errors: [`JSON parse error: ${e.message}`] };
|
|
24
|
+
}
|
|
25
|
+
if (!Array.isArray(parsed)) {
|
|
26
|
+
return { valid: false, results: [], errors: ['Response is not a JSON array'] };
|
|
27
|
+
}
|
|
28
|
+
const results = [];
|
|
29
|
+
const required = ['function_name', 'purpose', 'side_effects', 'behavior', 'domain', 'complexity'];
|
|
30
|
+
for (let i = 0; i < parsed.length; i++) {
|
|
31
|
+
const item = parsed[i];
|
|
32
|
+
// Check required fields
|
|
33
|
+
const missing = required.filter(f => !(f in item));
|
|
34
|
+
if (missing.length > 0) {
|
|
35
|
+
errors.push(`Item ${i}: missing fields: ${missing.join(', ')}`);
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
// Validate types
|
|
39
|
+
if (typeof item.function_name !== 'string' || !item.function_name.trim()) {
|
|
40
|
+
errors.push(`Item ${i}: function_name must be a non-empty string`);
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
if (typeof item.purpose !== 'string') {
|
|
44
|
+
errors.push(`Item ${i}: purpose must be a string`);
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
if (!Array.isArray(item.side_effects)) {
|
|
48
|
+
// Auto-fix: wrap in array if it's a string
|
|
49
|
+
if (typeof item.side_effects === 'string') {
|
|
50
|
+
item.side_effects = item.side_effects ? [item.side_effects] : [];
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
errors.push(`Item ${i}: side_effects must be an array`);
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
if (typeof item.behavior !== 'string') {
|
|
58
|
+
errors.push(`Item ${i}: behavior must be a string`);
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
// Normalize domain
|
|
62
|
+
const domain = item.domain?.toLowerCase().trim() || 'other';
|
|
63
|
+
if (!VALID_DOMAINS.has(domain)) {
|
|
64
|
+
item.domain = 'other';
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
item.domain = domain;
|
|
68
|
+
}
|
|
69
|
+
// Normalize complexity
|
|
70
|
+
const complexity = item.complexity?.toLowerCase().trim() || 'medium';
|
|
71
|
+
if (!VALID_COMPLEXITY.has(complexity)) {
|
|
72
|
+
item.complexity = 'medium';
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
item.complexity = complexity;
|
|
76
|
+
}
|
|
77
|
+
results.push({
|
|
78
|
+
function_name: item.function_name.trim(),
|
|
79
|
+
purpose: sanitizeText(item.purpose),
|
|
80
|
+
side_effects: item.side_effects.map((s) => sanitizeText(String(s))),
|
|
81
|
+
behavior: sanitizeText(item.behavior),
|
|
82
|
+
domain: item.domain,
|
|
83
|
+
complexity: item.complexity,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
valid: errors.length === 0 && results.length > 0,
|
|
88
|
+
results,
|
|
89
|
+
errors,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function sanitizeText(text) {
|
|
93
|
+
return text.replace(/\s+/g, ' ').trim();
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validator.js","sourceRoot":"","sources":["../../src/semantic/validator.ts"],"names":[],"mappings":";;AAuBA,4DAuFC;AA9GD,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC;IAC5B,gBAAgB,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,YAAY;IACnE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ;IAChE,SAAS,EAAE,OAAO;CACnB,CAAC,CAAC;AAEH,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;AAiB5D,SAAgB,wBAAwB,CAAC,YAAoB;IAC3D,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,wCAAwC;IACxC,IAAI,MAAW,CAAC;IAChB,IAAI,CAAC;QACH,uDAAuD;QACvD,MAAM,OAAO,GAAG,YAAY;aACzB,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC;aAC5B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;aACvB,IAAI,EAAE,CAAC;QACV,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,qBAAqB,CAAC,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;IACnF,CAAC;IAED,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3B,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,8BAA8B,CAAC,EAAE,CAAC;IACjF,CAAC;IAED,MAAM,OAAO,GAAqB,EAAE,CAAC;IACrC,MAAM,QAAQ,GAAG,CAAC,eAAe,EAAE,SAAS,EAAE,cAAc,EAAE,UAAU,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC;IAElG,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QAEvB,wBAAwB;QACxB,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;QACnD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,qBAAqB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAChE,SAAS;QACX,CAAC;QAED,iBAAiB;QACjB,IAAI,OAAO,IAAI,CAAC,aAAa,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,EAAE,CAAC;YACzE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,4CAA4C,CAAC,CAAC;YACnE,SAAS;QACX,CAAC;QACD,IAAI,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;YACrC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,4BAA4B,CAAC,CAAC;YACnD,SAAS;QACX,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;YACtC,2CAA2C;YAC3C,IAAI,OAAO,IAAI,CAAC,YAAY,KAAK,QAAQ,EAAE,CAAC;gBAC1C,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACnE,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,iCAAiC,CAAC,CAAC;gBACxD,SAAS;YACX,CAAC;QACH,CAAC;QACD,IAAI,OAAO,IAAI,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YACtC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,6BAA6B,CAAC,CAAC;YACpD,SAAS;QACX,CAAC;QAED,mBAAmB;QACnB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,OAAO,CAAC;QAC5D,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YAC/B,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC;QACxB,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACvB,CAAC;QAED,uBAAuB;QACvB,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,EAAE,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,QAAQ,CAAC;QACrE,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;YACtC,IAAI,CAAC,UAAU,GAAG,QAAQ,CAAC;QAC7B,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC/B,CAAC;QAED,OAAO,CAAC,IAAI,CAAC;YACX,aAAa,EAAE,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE;YACxC,OAAO,EAAE,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC;YACnC,YAAY,EAAE,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;YACxE,QAAQ,EAAE,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC;YACrC,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,UAAU,EAAE,IAAI,CAAC,UAAU;SAC5B,CAAC,CAAC;IACL,CAAC;IAED,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QAChD,OAAO;QACP,MAAM;KACP,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,IAAY;IAChC,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;AAC1C,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
2
|
+
export declare function setLogLevel(level: LogLevel): void;
|
|
3
|
+
export declare const logger: {
|
|
4
|
+
debug(message: string, data?: Record<string, unknown>): void;
|
|
5
|
+
info(message: string, data?: Record<string, unknown>): void;
|
|
6
|
+
warn(message: string, data?: Record<string, unknown>): void;
|
|
7
|
+
error(message: string, data?: Record<string, unknown>): void;
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAW3D,wBAAgB,WAAW,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,CAEjD;AAeD,eAAO,MAAM,MAAM;mBACF,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;kBAM9C,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;kBAM7C,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;mBAM5C,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;CAK7D,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.logger = void 0;
|
|
4
|
+
exports.setLogLevel = setLogLevel;
|
|
5
|
+
const LOG_LEVELS = {
|
|
6
|
+
debug: 0,
|
|
7
|
+
info: 1,
|
|
8
|
+
warn: 2,
|
|
9
|
+
error: 3,
|
|
10
|
+
};
|
|
11
|
+
let currentLevel = 'info';
|
|
12
|
+
function setLogLevel(level) {
|
|
13
|
+
currentLevel = level;
|
|
14
|
+
}
|
|
15
|
+
function shouldLog(level) {
|
|
16
|
+
return LOG_LEVELS[level] >= LOG_LEVELS[currentLevel];
|
|
17
|
+
}
|
|
18
|
+
function formatMessage(level, message, data) {
|
|
19
|
+
const timestamp = new Date().toISOString();
|
|
20
|
+
const base = `[${timestamp}] [${level.toUpperCase()}] ${message}`;
|
|
21
|
+
if (data && Object.keys(data).length > 0) {
|
|
22
|
+
return `${base} ${JSON.stringify(data)}`;
|
|
23
|
+
}
|
|
24
|
+
return base;
|
|
25
|
+
}
|
|
26
|
+
exports.logger = {
|
|
27
|
+
debug(message, data) {
|
|
28
|
+
if (shouldLog('debug')) {
|
|
29
|
+
console.debug(formatMessage('debug', message, data));
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
info(message, data) {
|
|
33
|
+
if (shouldLog('info')) {
|
|
34
|
+
console.log(formatMessage('info', message, data));
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
warn(message, data) {
|
|
38
|
+
if (shouldLog('warn')) {
|
|
39
|
+
console.warn(formatMessage('warn', message, data));
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
error(message, data) {
|
|
43
|
+
if (shouldLog('error')) {
|
|
44
|
+
console.error(formatMessage('error', message, data));
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":";;;AAWA,kCAEC;AAXD,MAAM,UAAU,GAA6B;IAC3C,KAAK,EAAE,CAAC;IACR,IAAI,EAAE,CAAC;IACP,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,CAAC;CACT,CAAC;AAEF,IAAI,YAAY,GAAa,MAAM,CAAC;AAEpC,SAAgB,WAAW,CAAC,KAAe;IACzC,YAAY,GAAG,KAAK,CAAC;AACvB,CAAC;AAED,SAAS,SAAS,CAAC,KAAe;IAChC,OAAO,UAAU,CAAC,KAAK,CAAC,IAAI,UAAU,CAAC,YAAY,CAAC,CAAC;AACvD,CAAC;AAED,SAAS,aAAa,CAAC,KAAe,EAAE,OAAe,EAAE,IAA8B;IACrF,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC3C,MAAM,IAAI,GAAG,IAAI,SAAS,MAAM,KAAK,CAAC,WAAW,EAAE,KAAK,OAAO,EAAE,CAAC;IAClE,IAAI,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzC,OAAO,GAAG,IAAI,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;IAC3C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAEY,QAAA,MAAM,GAAG;IACpB,KAAK,CAAC,OAAe,EAAE,IAA8B;QACnD,IAAI,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;YACvB,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,IAA8B;QAClD,IAAI,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;YACtB,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,IAA8B;QAClD,IAAI,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;YACtB,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;QACrD,CAAC;IACH,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,IAA8B;QACnD,IAAI,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;YACvB,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../src/utils/tokens.ts"],"names":[],"mappings":"AAGA,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAQD,wBAAgB,YAAY,CAC1B,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,GACnB,MAAM,CAKR"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Simple token estimation without external dependencies.
|
|
3
|
+
// Rough heuristic: ~4 characters per token for English/code.
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.estimateTokens = estimateTokens;
|
|
6
|
+
exports.estimateCost = estimateCost;
|
|
7
|
+
function estimateTokens(text) {
|
|
8
|
+
return Math.ceil(text.length / 4);
|
|
9
|
+
}
|
|
10
|
+
// Pricing per million tokens (as of 2025)
|
|
11
|
+
const PRICING = {
|
|
12
|
+
'claude-haiku-4-5-20251001': { input: 0.80, output: 4.00 },
|
|
13
|
+
'claude-sonnet-4-5-20250929': { input: 3.00, output: 15.00 },
|
|
14
|
+
};
|
|
15
|
+
function estimateCost(model, inputTokens, outputTokens) {
|
|
16
|
+
const price = PRICING[model] ?? { input: 1.0, output: 5.0 };
|
|
17
|
+
const inputCost = (inputTokens / 1_000_000) * price.input;
|
|
18
|
+
const outputCost = (outputTokens / 1_000_000) * price.output;
|
|
19
|
+
return inputCost + outputCost;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=tokens.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokens.js","sourceRoot":"","sources":["../../src/utils/tokens.ts"],"names":[],"mappings":";AAAA,yDAAyD;AACzD,6DAA6D;;AAE7D,wCAEC;AAQD,oCASC;AAnBD,SAAgB,cAAc,CAAC,IAAY;IACzC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACpC,CAAC;AAED,0CAA0C;AAC1C,MAAM,OAAO,GAAsD;IACjE,2BAA2B,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;IAC1D,4BAA4B,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE;CAC7D,CAAC;AAEF,SAAgB,YAAY,CAC1B,KAAa,EACb,WAAmB,EACnB,YAAoB;IAEpB,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;IAC5D,MAAM,SAAS,GAAG,CAAC,WAAW,GAAG,SAAS,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC;IAC1D,MAAM,UAAU,GAAG,CAAC,YAAY,GAAG,SAAS,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC;IAC7D,OAAO,SAAS,GAAG,UAAU,CAAC;AAChC,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "structx",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"main": "dist/cli.js",
|
|
5
|
+
"bin": {
|
|
6
|
+
"structx": "dist/cli.js"
|
|
7
|
+
},
|
|
8
|
+
"files": [
|
|
9
|
+
"dist",
|
|
10
|
+
"README.md"
|
|
11
|
+
],
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "tsc && node scripts/copy-assets.js",
|
|
14
|
+
"dev": "tsx src/cli.ts",
|
|
15
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"code-intelligence",
|
|
19
|
+
"typescript",
|
|
20
|
+
"ast",
|
|
21
|
+
"llm"
|
|
22
|
+
],
|
|
23
|
+
"author": "",
|
|
24
|
+
"license": "ISC",
|
|
25
|
+
"description": "Graph-powered code intelligence CLI for TypeScript",
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@anthropic-ai/sdk": "^0.74.0",
|
|
28
|
+
"better-sqlite3": "^12.6.2",
|
|
29
|
+
"commander": "^14.0.3",
|
|
30
|
+
"dotenv": "^17.2.4",
|
|
31
|
+
"ts-morph": "^27.0.2"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
35
|
+
"@types/node": "^25.2.3",
|
|
36
|
+
"tsx": "^4.21.0",
|
|
37
|
+
"typescript": "^5.9.3"
|
|
38
|
+
}
|
|
39
|
+
}
|