@mcp-graph-workflow/mcp-graph 5.22.0 → 5.25.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/api/routes/benchmark.d.ts.map +1 -1
- package/dist/api/routes/benchmark.js +22 -6
- package/dist/api/routes/benchmark.js.map +1 -1
- package/dist/api/routes/code-graph.d.ts.map +1 -1
- package/dist/api/routes/code-graph.js +2 -1
- package/dist/api/routes/code-graph.js.map +1 -1
- package/dist/api/routes/folder.d.ts +6 -0
- package/dist/api/routes/folder.d.ts.map +1 -1
- package/dist/api/routes/folder.js +53 -8
- package/dist/api/routes/folder.js.map +1 -1
- package/dist/api/routes/import.js +2 -1
- package/dist/api/routes/import.js.map +1 -1
- package/dist/api/routes/siebel.d.ts.map +1 -1
- package/dist/api/routes/siebel.js +4 -2
- package/dist/api/routes/siebel.js.map +1 -1
- package/dist/api/routes/skills.d.ts.map +1 -1
- package/dist/api/routes/skills.js +5 -2
- package/dist/api/routes/skills.js.map +1 -1
- package/dist/api/routes/translation.d.ts.map +1 -1
- package/dist/api/routes/translation.js +33 -9
- package/dist/api/routes/translation.js.map +1 -1
- package/dist/core/context/context-assembler.d.ts.map +1 -1
- package/dist/core/context/context-assembler.js +7 -0
- package/dist/core/context/context-assembler.js.map +1 -1
- package/dist/core/docs/docs-cache-store.js +1 -1
- package/dist/core/docs/docs-cache-store.js.map +1 -1
- package/dist/core/docs/stack-detector.js +6 -3
- package/dist/core/docs/stack-detector.js.map +1 -1
- package/dist/core/events/event-bus.d.ts +1 -1
- package/dist/core/events/event-bus.d.ts.map +1 -1
- package/dist/core/events/event-bus.js +13 -3
- package/dist/core/events/event-bus.js.map +1 -1
- package/dist/core/importer/prd-to-graph.d.ts.map +1 -1
- package/dist/core/importer/prd-to-graph.js +20 -5
- package/dist/core/importer/prd-to-graph.js.map +1 -1
- package/dist/core/integrations/integration-orchestrator.d.ts +1 -0
- package/dist/core/integrations/integration-orchestrator.d.ts.map +1 -1
- package/dist/core/integrations/integration-orchestrator.js +40 -19
- package/dist/core/integrations/integration-orchestrator.js.map +1 -1
- package/dist/core/knowledge/knowledge-packager.d.ts +44 -0
- package/dist/core/knowledge/knowledge-packager.d.ts.map +1 -0
- package/dist/core/knowledge/knowledge-packager.js +311 -0
- package/dist/core/knowledge/knowledge-packager.js.map +1 -0
- package/dist/core/parser/classify.js +2 -2
- package/dist/core/parser/classify.js.map +1 -1
- package/dist/core/parser/file-reader.d.ts.map +1 -1
- package/dist/core/parser/file-reader.js +9 -2
- package/dist/core/parser/file-reader.js.map +1 -1
- package/dist/core/parser/read-pdf.d.ts.map +1 -1
- package/dist/core/parser/read-pdf.js +5 -1
- package/dist/core/parser/read-pdf.js.map +1 -1
- package/dist/core/rag/knowledge-synthesizer.js +2 -2
- package/dist/core/rag/knowledge-synthesizer.js.map +1 -1
- package/dist/core/rag/node-indexer.d.ts.map +1 -1
- package/dist/core/rag/node-indexer.js +3 -2
- package/dist/core/rag/node-indexer.js.map +1 -1
- package/dist/core/store/migrations.d.ts.map +1 -1
- package/dist/core/store/migrations.js +10 -0
- package/dist/core/store/migrations.js.map +1 -1
- package/dist/core/store/sqlite-store.d.ts.map +1 -1
- package/dist/core/store/sqlite-store.js +39 -19
- package/dist/core/store/sqlite-store.js.map +1 -1
- package/dist/core/translation/chunked-analyzer.d.ts +36 -0
- package/dist/core/translation/chunked-analyzer.d.ts.map +1 -0
- package/dist/core/translation/chunked-analyzer.js +146 -0
- package/dist/core/translation/chunked-analyzer.js.map +1 -0
- package/dist/core/translation/confidence/ambiguity-detector.d.ts.map +1 -1
- package/dist/core/translation/confidence/ambiguity-detector.js +3 -1
- package/dist/core/translation/confidence/ambiguity-detector.js.map +1 -1
- package/dist/core/translation/language-detect.d.ts.map +1 -1
- package/dist/core/translation/language-detect.js +131 -0
- package/dist/core/translation/language-detect.js.map +1 -1
- package/dist/core/translation/memory/translation-memory.d.ts +14 -0
- package/dist/core/translation/memory/translation-memory.d.ts.map +1 -1
- package/dist/core/translation/memory/translation-memory.js +93 -0
- package/dist/core/translation/memory/translation-memory.js.map +1 -1
- package/dist/core/translation/parsers/cpp-parser-adapter.d.ts +9 -0
- package/dist/core/translation/parsers/cpp-parser-adapter.d.ts.map +1 -0
- package/dist/core/translation/parsers/cpp-parser-adapter.js +45 -0
- package/dist/core/translation/parsers/cpp-parser-adapter.js.map +1 -0
- package/dist/core/translation/parsers/csharp-parser-adapter.d.ts.map +1 -1
- package/dist/core/translation/parsers/csharp-parser-adapter.js +19 -22
- package/dist/core/translation/parsers/csharp-parser-adapter.js.map +1 -1
- package/dist/core/translation/parsers/dart-parser-adapter.d.ts +9 -0
- package/dist/core/translation/parsers/dart-parser-adapter.d.ts.map +1 -0
- package/dist/core/translation/parsers/dart-parser-adapter.js +44 -0
- package/dist/core/translation/parsers/dart-parser-adapter.js.map +1 -0
- package/dist/core/translation/parsers/elixir-parser-adapter.d.ts +9 -0
- package/dist/core/translation/parsers/elixir-parser-adapter.d.ts.map +1 -0
- package/dist/core/translation/parsers/elixir-parser-adapter.js +45 -0
- package/dist/core/translation/parsers/elixir-parser-adapter.js.map +1 -0
- package/dist/core/translation/parsers/go-parser-adapter.d.ts.map +1 -1
- package/dist/core/translation/parsers/go-parser-adapter.js +5 -2
- package/dist/core/translation/parsers/go-parser-adapter.js.map +1 -1
- package/dist/core/translation/parsers/haskell-parser-adapter.d.ts +9 -0
- package/dist/core/translation/parsers/haskell-parser-adapter.d.ts.map +1 -0
- package/dist/core/translation/parsers/haskell-parser-adapter.js +38 -0
- package/dist/core/translation/parsers/haskell-parser-adapter.js.map +1 -0
- package/dist/core/translation/parsers/java-parser-adapter.d.ts.map +1 -1
- package/dist/core/translation/parsers/java-parser-adapter.js +6 -1
- package/dist/core/translation/parsers/java-parser-adapter.js.map +1 -1
- package/dist/core/translation/parsers/kotlin-parser-adapter.d.ts +9 -0
- package/dist/core/translation/parsers/kotlin-parser-adapter.d.ts.map +1 -0
- package/dist/core/translation/parsers/kotlin-parser-adapter.js +43 -0
- package/dist/core/translation/parsers/kotlin-parser-adapter.js.map +1 -0
- package/dist/core/translation/parsers/lua-parser-adapter.d.ts +9 -0
- package/dist/core/translation/parsers/lua-parser-adapter.d.ts.map +1 -0
- package/dist/core/translation/parsers/lua-parser-adapter.js +42 -0
- package/dist/core/translation/parsers/lua-parser-adapter.js.map +1 -0
- package/dist/core/translation/parsers/php-parser-adapter.d.ts +9 -0
- package/dist/core/translation/parsers/php-parser-adapter.d.ts.map +1 -0
- package/dist/core/translation/parsers/php-parser-adapter.js +44 -0
- package/dist/core/translation/parsers/php-parser-adapter.js.map +1 -0
- package/dist/core/translation/parsers/rust-parser-adapter.js +1 -1
- package/dist/core/translation/parsers/scala-parser-adapter.d.ts +9 -0
- package/dist/core/translation/parsers/scala-parser-adapter.d.ts.map +1 -0
- package/dist/core/translation/parsers/scala-parser-adapter.js +43 -0
- package/dist/core/translation/parsers/scala-parser-adapter.js.map +1 -0
- package/dist/core/translation/parsers/swift-parser-adapter.d.ts +9 -0
- package/dist/core/translation/parsers/swift-parser-adapter.d.ts.map +1 -0
- package/dist/core/translation/parsers/swift-parser-adapter.js +44 -0
- package/dist/core/translation/parsers/swift-parser-adapter.js.map +1 -0
- package/dist/core/translation/pre-indexed-analyzer.d.ts +19 -0
- package/dist/core/translation/pre-indexed-analyzer.d.ts.map +1 -0
- package/dist/core/translation/pre-indexed-analyzer.js +100 -0
- package/dist/core/translation/pre-indexed-analyzer.js.map +1 -0
- package/dist/core/translation/prompt-builder.d.ts +2 -0
- package/dist/core/translation/prompt-builder.d.ts.map +1 -1
- package/dist/core/translation/prompt-builder.js +56 -8
- package/dist/core/translation/prompt-builder.js.map +1 -1
- package/dist/core/translation/prompt-paginator.d.ts +20 -0
- package/dist/core/translation/prompt-paginator.d.ts.map +1 -0
- package/dist/core/translation/prompt-paginator.js +108 -0
- package/dist/core/translation/prompt-paginator.js.map +1 -0
- package/dist/core/translation/translation-orchestrator.d.ts +9 -2
- package/dist/core/translation/translation-orchestrator.d.ts.map +1 -1
- package/dist/core/translation/translation-orchestrator.js +116 -16
- package/dist/core/translation/translation-orchestrator.js.map +1 -1
- package/dist/core/translation/translation-store.d.ts +6 -0
- package/dist/core/translation/translation-store.d.ts.map +1 -1
- package/dist/core/translation/translation-store.js +28 -0
- package/dist/core/translation/translation-store.js.map +1 -1
- package/dist/core/utils/circularity.d.ts +13 -0
- package/dist/core/utils/circularity.d.ts.map +1 -0
- package/dist/core/utils/circularity.js +30 -0
- package/dist/core/utils/circularity.js.map +1 -0
- package/dist/mcp/code-intelligence-wrapper.d.ts.map +1 -1
- package/dist/mcp/code-intelligence-wrapper.js +4 -2
- package/dist/mcp/code-intelligence-wrapper.js.map +1 -1
- package/dist/mcp/init-project.d.ts.map +1 -1
- package/dist/mcp/init-project.js +4 -2
- package/dist/mcp/init-project.js.map +1 -1
- package/dist/mcp/server.js +21 -4
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tool-classification.d.ts.map +1 -1
- package/dist/mcp/tool-classification.js +0 -1
- package/dist/mcp/tool-classification.js.map +1 -1
- package/dist/mcp/tools/analyze-translation.d.ts.map +1 -1
- package/dist/mcp/tools/analyze-translation.js +48 -8
- package/dist/mcp/tools/analyze-translation.js.map +1 -1
- package/dist/mcp/tools/clone-node.d.ts.map +1 -1
- package/dist/mcp/tools/clone-node.js +8 -3
- package/dist/mcp/tools/clone-node.js.map +1 -1
- package/dist/mcp/tools/edge.js +1 -1
- package/dist/mcp/tools/edge.js.map +1 -1
- package/dist/mcp/tools/import-graph.d.ts.map +1 -1
- package/dist/mcp/tools/import-graph.js +4 -2
- package/dist/mcp/tools/import-graph.js.map +1 -1
- package/dist/mcp/tools/index.d.ts.map +1 -1
- package/dist/mcp/tools/index.js +4 -0
- package/dist/mcp/tools/index.js.map +1 -1
- package/dist/mcp/tools/knowledge-export.d.ts +8 -0
- package/dist/mcp/tools/knowledge-export.d.ts.map +1 -0
- package/dist/mcp/tools/knowledge-export.js +100 -0
- package/dist/mcp/tools/knowledge-export.js.map +1 -0
- package/dist/mcp/tools/memory.d.ts.map +1 -1
- package/dist/mcp/tools/memory.js +1 -0
- package/dist/mcp/tools/memory.js.map +1 -1
- package/dist/mcp/tools/move-node.d.ts.map +1 -1
- package/dist/mcp/tools/move-node.js +4 -14
- package/dist/mcp/tools/move-node.js.map +1 -1
- package/dist/mcp/tools/node.d.ts.map +1 -1
- package/dist/mcp/tools/node.js +5 -16
- package/dist/mcp/tools/node.js.map +1 -1
- package/dist/mcp/tools/siebel-generate-sif.js +4 -2
- package/dist/mcp/tools/siebel-generate-sif.js.map +1 -1
- package/dist/mcp/tools/translate-code.d.ts.map +1 -1
- package/dist/mcp/tools/translate-code.js +54 -7
- package/dist/mcp/tools/translate-code.js.map +1 -1
- package/dist/mcp/tools/translation-jobs.d.ts +8 -0
- package/dist/mcp/tools/translation-jobs.d.ts.map +1 -0
- package/dist/mcp/tools/translation-jobs.js +100 -0
- package/dist/mcp/tools/translation-jobs.js.map +1 -0
- package/dist/schemas/knowledge-package.schema.d.ts +87 -0
- package/dist/schemas/knowledge-package.schema.d.ts.map +1 -0
- package/dist/schemas/knowledge-package.schema.js +48 -0
- package/dist/schemas/knowledge-package.schema.js.map +1 -0
- package/dist/web/dashboard/dist/assets/benchmark-tab-sjsZBd-4.js +1 -0
- package/dist/web/dashboard/dist/assets/{circle-alert-vaRHjxbG.js → circle-alert-DcTbCUEa.js} +1 -1
- package/dist/web/dashboard/dist/assets/{context-tab-DRUGmBRL.js → context-tab-DNMJ2Pv-.js} +1 -1
- package/dist/web/dashboard/dist/assets/{gitnexus-tab-h8BwIua3.js → gitnexus-tab-CZ9LJbwz.js} +1 -1
- package/dist/web/dashboard/dist/assets/{graph-section-C4ymXtzh.js → graph-section-BdcXKKoS.js} +1 -1
- package/dist/web/dashboard/dist/assets/{graph-tab-C6nWMQkR.js → graph-tab-CFzux3kf.js} +1 -1
- package/dist/web/dashboard/dist/assets/{graph-utils-DkRXfigF.js → graph-utils-_8jpWA5z.js} +1 -1
- package/dist/web/dashboard/dist/assets/{index-DmT4Jne7.js → index-Bny20bel.js} +1 -1
- package/dist/web/dashboard/dist/assets/index-CITYTuX5.js +218 -0
- package/dist/web/dashboard/dist/assets/{index-BW0cq1-5.js → index-DSI2SYWO.js} +1 -1
- package/dist/web/dashboard/dist/assets/{insights-tab-CL9LCuow.js → insights-tab-DUA76KUY.js} +2 -2
- package/dist/web/dashboard/dist/assets/{journey-tab-CbJSfdpz.js → journey-tab-FTd6jBta.js} +1 -1
- package/dist/web/dashboard/dist/assets/{languages-tab-Vjkz6r99.js → languages-tab-B_nhFL2q.js} +1 -1
- package/dist/web/dashboard/dist/assets/{loader-circle-CrUmRfZB.js → loader-circle-D1DpGd2u.js} +1 -1
- package/dist/web/dashboard/dist/assets/{logs-tab-CeH_wY9u.js → logs-tab-CzL36_Qy.js} +1 -1
- package/dist/web/dashboard/dist/assets/{lsp-tab-BLIpJrAk.js → lsp-tab-DdHhJq_H.js} +1 -1
- package/dist/web/dashboard/dist/assets/memories-tab-CzgCahnV.js +1 -0
- package/dist/web/dashboard/dist/assets/{prd-backlog-tab-BBUG4V7M.js → prd-backlog-tab-C8Cl7swI.js} +1 -1
- package/dist/web/dashboard/dist/assets/{refresh-cw-DRsAUgYq.js → refresh-cw-DSYiHmbh.js} +1 -1
- package/dist/web/dashboard/dist/assets/{siebel-tab-DZXhcoUu.js → siebel-tab-B4XOaUGz.js} +3 -3
- package/dist/web/dashboard/dist/assets/{skills-tab-_A8OYt_b.js → skills-tab-CkpnwPJY.js} +1 -1
- package/dist/web/dashboard/dist/assets/{style-DpBYmOVU.js → style-BOQDk6qp.js} +1 -1
- package/dist/web/dashboard/dist/assets/{triangle-alert-N0TixBQV.js → triangle-alert-Bf6Ly19h.js} +1 -1
- package/dist/web/dashboard/dist/index.html +1 -1
- package/package.json +2 -2
- package/dist/web/dashboard/dist/assets/benchmark-tab-D7nae4k4.js +0 -1
- package/dist/web/dashboard/dist/assets/index-DSPPavjF.js +0 -218
- package/dist/web/dashboard/dist/assets/memories-tab-BHOvEW0o.js +0 -1
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pre-indexed Analysis — leverages Code Intelligence symbol table
|
|
3
|
+
* to provide instant translation analysis for already-indexed files.
|
|
4
|
+
*
|
|
5
|
+
* Maps code intelligence symbol kinds to UCR constructs:
|
|
6
|
+
* function → uc_fn_def, class → uc_class_def, interface → uc_interface, etc.
|
|
7
|
+
*/
|
|
8
|
+
import { logger } from "../utils/logger.js";
|
|
9
|
+
/** Map Code Intelligence symbol kind → UCR construct ID */
|
|
10
|
+
const KIND_TO_CONSTRUCT = {
|
|
11
|
+
function: "uc_fn_def",
|
|
12
|
+
method: "uc_fn_def",
|
|
13
|
+
class: "uc_class_def",
|
|
14
|
+
interface: "uc_interface",
|
|
15
|
+
enum: "uc_type_enum",
|
|
16
|
+
variable: "uc_var_const",
|
|
17
|
+
type: "uc_type_alias",
|
|
18
|
+
property: "uc_fn_def",
|
|
19
|
+
};
|
|
20
|
+
/** File extension → detected language */
|
|
21
|
+
const EXT_TO_LANGUAGE = {
|
|
22
|
+
".ts": "typescript",
|
|
23
|
+
".tsx": "typescript",
|
|
24
|
+
".js": "javascript",
|
|
25
|
+
".jsx": "javascript",
|
|
26
|
+
".py": "python",
|
|
27
|
+
".java": "java",
|
|
28
|
+
".go": "go",
|
|
29
|
+
".rs": "rust",
|
|
30
|
+
".cs": "csharp",
|
|
31
|
+
".rb": "ruby",
|
|
32
|
+
".php": "php",
|
|
33
|
+
".swift": "swift",
|
|
34
|
+
".kt": "kotlin",
|
|
35
|
+
".scala": "scala",
|
|
36
|
+
".lua": "lua",
|
|
37
|
+
".cpp": "cpp",
|
|
38
|
+
".cc": "cpp",
|
|
39
|
+
".c": "c",
|
|
40
|
+
".dart": "dart",
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Try to build a TranslationAnalysis from the Code Intelligence index.
|
|
44
|
+
* Returns null if the file is not indexed or the index is stale.
|
|
45
|
+
*/
|
|
46
|
+
export function analyzeFromIndex(codeStore, projectId, filePath) {
|
|
47
|
+
try {
|
|
48
|
+
const meta = codeStore.getIndexMeta(projectId);
|
|
49
|
+
if (!meta)
|
|
50
|
+
return null;
|
|
51
|
+
// Get symbols for this specific file
|
|
52
|
+
const allSymbols = codeStore.getAllSymbols(projectId, 10000);
|
|
53
|
+
const fileSymbols = allSymbols.filter((s) => s.file === filePath);
|
|
54
|
+
if (fileSymbols.length === 0)
|
|
55
|
+
return null;
|
|
56
|
+
// Detect language from file extension
|
|
57
|
+
const parts = filePath.split(".");
|
|
58
|
+
const ext = parts.length > 1 ? "." + parts[parts.length - 1].toLowerCase() : "";
|
|
59
|
+
const detectedLanguage = EXT_TO_LANGUAGE[ext] ?? "unknown";
|
|
60
|
+
// Map symbols to constructs
|
|
61
|
+
const constructCounts = new Map();
|
|
62
|
+
for (const sym of fileSymbols) {
|
|
63
|
+
const constructId = KIND_TO_CONSTRUCT[sym.kind];
|
|
64
|
+
if (constructId) {
|
|
65
|
+
constructCounts.set(constructId, (constructCounts.get(constructId) ?? 0) + 1);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
const constructs = Array.from(constructCounts.entries()).map(([canonicalName, count]) => ({
|
|
69
|
+
canonicalName,
|
|
70
|
+
count,
|
|
71
|
+
confidence: 0.9, // slightly lower than direct parsing since we're mapping kinds
|
|
72
|
+
}));
|
|
73
|
+
const totalConstructs = constructs.reduce((sum, c) => sum + c.count, 0);
|
|
74
|
+
const uniqueConstructs = constructs.length;
|
|
75
|
+
const complexityScore = Math.min(uniqueConstructs / 15, 1);
|
|
76
|
+
const analysis = {
|
|
77
|
+
detectedLanguage,
|
|
78
|
+
detectedConfidence: 1.0, // file extension is definitive
|
|
79
|
+
constructs,
|
|
80
|
+
complexityScore,
|
|
81
|
+
estimatedTranslatability: totalConstructs > 0 ? 0.95 : 0,
|
|
82
|
+
ambiguousConstructs: [],
|
|
83
|
+
totalConstructs,
|
|
84
|
+
};
|
|
85
|
+
logger.debug("pre-indexed-analysis", {
|
|
86
|
+
file: filePath,
|
|
87
|
+
language: detectedLanguage,
|
|
88
|
+
symbols: fileSymbols.length,
|
|
89
|
+
constructs: totalConstructs,
|
|
90
|
+
});
|
|
91
|
+
return { analysis, fromIndex: true };
|
|
92
|
+
}
|
|
93
|
+
catch (err) {
|
|
94
|
+
logger.debug("pre-indexed-analysis:failed", {
|
|
95
|
+
error: err instanceof Error ? err.message : String(err),
|
|
96
|
+
});
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=pre-indexed-analyzer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pre-indexed-analyzer.js","sourceRoot":"","sources":["../../../src/core/translation/pre-indexed-analyzer.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,6 +14,8 @@ export interface PromptContext {
|
|
|
14
14
|
sourceCode: string;
|
|
15
15
|
scores: TranslationScore[];
|
|
16
16
|
ambiguities: AmbiguityReport[];
|
|
17
|
+
/** Max prompt token budget (default: 8000). */
|
|
18
|
+
maxPromptTokens?: number;
|
|
17
19
|
}
|
|
18
20
|
/**
|
|
19
21
|
* Build a mapping prompt — asks the LLM to analyze constructs and choose mappings.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompt-builder.d.ts","sourceRoot":"","sources":["../../../src/core/translation/prompt-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"prompt-builder.d.ts","sourceRoot":"","sources":["../../../src/core/translation/prompt-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AASlF,MAAM,WAAW,aAAa;IAC5B,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC3B,WAAW,EAAE,eAAe,EAAE,CAAC;IAC/B,+CAA+C;IAC/C,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAmC7D;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAiGjE;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,aAAa,EAClB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EAAE,GACf,MAAM,CAkBR;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,GAAG,EAAE,aAAa,EAClB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EAAE,GACf,MAAM,CAuBR"}
|
|
@@ -7,6 +7,11 @@
|
|
|
7
7
|
* - syntactic repair: fix syntax errors in generated code
|
|
8
8
|
* - semantic repair: fix semantic issues preserving meaning
|
|
9
9
|
*/
|
|
10
|
+
import { estimateTokens } from "../context/token-estimator.js";
|
|
11
|
+
/** Default max prompt token budget (~32KB). */
|
|
12
|
+
const DEFAULT_MAX_PROMPT_TOKENS = 8000;
|
|
13
|
+
/** Max constructs to show in the table when truncating. */
|
|
14
|
+
const MAX_CONSTRUCTS_ON_TRUNCATE = 20;
|
|
10
15
|
/**
|
|
11
16
|
* Build a mapping prompt — asks the LLM to analyze constructs and choose mappings.
|
|
12
17
|
*/
|
|
@@ -24,7 +29,7 @@ export function buildMappingPrompt(ctx) {
|
|
|
24
29
|
if (ctx.ambiguities.length > 0) {
|
|
25
30
|
sections.push(``, `### Ambiguities Requiring Decision`, ``);
|
|
26
31
|
for (const amb of ctx.ambiguities) {
|
|
27
|
-
sections.push(`- **${amb.canonicalName}** (${amb.ambiguityType}): ${amb.candidates.length} candidates`);
|
|
32
|
+
sections.push(`- **${amb.canonicalName ?? amb.constructId}** (${amb.ambiguityType}): ${amb.candidates.length} candidates`);
|
|
28
33
|
for (const c of amb.candidates) {
|
|
29
34
|
sections.push(` - ${c.tradeoff} (confidence: ${c.confidence})`);
|
|
30
35
|
}
|
|
@@ -40,25 +45,39 @@ export function buildMappingPrompt(ctx) {
|
|
|
40
45
|
* Build a full translation prompt — asks the LLM to translate the code.
|
|
41
46
|
*/
|
|
42
47
|
export function buildTranslationPrompt(ctx) {
|
|
43
|
-
const
|
|
44
|
-
|
|
48
|
+
const maxTokens = ctx.maxPromptTokens ?? DEFAULT_MAX_PROMPT_TOKENS;
|
|
49
|
+
let truncated = false;
|
|
50
|
+
// Possibly truncate scores to top N by count (we don't have count here, so limit by total)
|
|
51
|
+
let effectiveScores = ctx.scores;
|
|
52
|
+
if (effectiveScores.length > MAX_CONSTRUCTS_ON_TRUNCATE) {
|
|
53
|
+
// Sort by finalConfidence desc, keep top N
|
|
54
|
+
effectiveScores = [...effectiveScores]
|
|
55
|
+
.sort((a, b) => b.finalConfidence - a.finalConfidence)
|
|
56
|
+
.slice(0, MAX_CONSTRUCTS_ON_TRUNCATE);
|
|
57
|
+
truncated = true;
|
|
58
|
+
}
|
|
59
|
+
const deterministicCount = effectiveScores.filter((s) => !s.needsAiAssist).length;
|
|
60
|
+
const aiAssistCount = effectiveScores.filter((s) => s.needsAiAssist).length;
|
|
61
|
+
// Possibly truncate source code to fit budget
|
|
62
|
+
let sourceBlock = ctx.sourceCode;
|
|
63
|
+
const sourceLines = ctx.sourceCode.split("\n");
|
|
45
64
|
const sections = [
|
|
46
65
|
`## Code Translation: ${ctx.sourceLanguage} → ${ctx.targetLanguage}`,
|
|
47
66
|
``,
|
|
48
67
|
`### Source Code`,
|
|
49
68
|
"```" + ctx.sourceLanguage,
|
|
50
|
-
|
|
69
|
+
sourceBlock,
|
|
51
70
|
"```",
|
|
52
71
|
``,
|
|
53
72
|
`### Construct Analysis`,
|
|
54
73
|
`- **Deterministic mappings**: ${deterministicCount} (high confidence, direct translation)`,
|
|
55
74
|
`- **AI-assisted mappings**: ${aiAssistCount} (require judgment)`,
|
|
56
75
|
``,
|
|
57
|
-
formatScoresTable(
|
|
76
|
+
formatScoresTable(effectiveScores),
|
|
58
77
|
];
|
|
59
78
|
if (aiAssistCount > 0) {
|
|
60
79
|
sections.push(``, `### Constructs Requiring AI Judgment`);
|
|
61
|
-
for (const score of
|
|
80
|
+
for (const score of effectiveScores.filter((s) => s.needsAiAssist)) {
|
|
62
81
|
sections.push(`- **${score.constructId}** (confidence: ${score.finalConfidence.toFixed(2)})`);
|
|
63
82
|
if (score.alternatives.length > 0) {
|
|
64
83
|
for (const alt of score.alternatives) {
|
|
@@ -70,11 +89,40 @@ export function buildTranslationPrompt(ctx) {
|
|
|
70
89
|
if (ctx.ambiguities.length > 0) {
|
|
71
90
|
sections.push(``, `### Ambiguity Warnings`);
|
|
72
91
|
for (const amb of ctx.ambiguities) {
|
|
73
|
-
|
|
92
|
+
const name = amb.canonicalName ?? amb.constructId;
|
|
93
|
+
sections.push(`- **${name}**: ${amb.ambiguityType} — ${amb.recommendation ?? "review needed"}`);
|
|
74
94
|
}
|
|
75
95
|
}
|
|
76
96
|
sections.push(``, `### Instructions`, `Translate the source code to ${ctx.targetLanguage}.`, `Use the construct mappings above. For AI-assisted constructs, choose the best mapping.`, `Preserve semantics, follow ${ctx.targetLanguage} conventions (naming, idioms).`, `Return ONLY the translated code.`);
|
|
77
|
-
|
|
97
|
+
// Check token budget — if over, truncate source code block
|
|
98
|
+
let result = sections.join("\n");
|
|
99
|
+
if (estimateTokens(result) > maxTokens) {
|
|
100
|
+
// Binary search for max lines that fit within budget
|
|
101
|
+
let lo = 1;
|
|
102
|
+
let hi = sourceLines.length;
|
|
103
|
+
while (lo < hi) {
|
|
104
|
+
const mid = Math.ceil((lo + hi) / 2);
|
|
105
|
+
const candidate = sourceLines.slice(0, mid).join("\n")
|
|
106
|
+
+ `\n... [truncated — showing first ${mid} lines of ${sourceLines.length} total]`;
|
|
107
|
+
sections[4] = candidate; // replace source code block content
|
|
108
|
+
const candidateResult = sections.join("\n");
|
|
109
|
+
if (estimateTokens(candidateResult) <= maxTokens) {
|
|
110
|
+
lo = mid;
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
hi = mid - 1;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
sourceBlock = sourceLines.slice(0, lo).join("\n")
|
|
117
|
+
+ `\n... [truncated — showing first ${lo} lines of ${sourceLines.length} total]`;
|
|
118
|
+
sections[4] = sourceBlock;
|
|
119
|
+
truncated = true;
|
|
120
|
+
result = sections.join("\n");
|
|
121
|
+
}
|
|
122
|
+
if (truncated) {
|
|
123
|
+
result += `\n<!-- truncated: true -->`;
|
|
124
|
+
}
|
|
125
|
+
return result;
|
|
78
126
|
}
|
|
79
127
|
/**
|
|
80
128
|
* Build a syntactic repair prompt — fix syntax errors in generated code.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompt-builder.js","sourceRoot":"","sources":["../../../src/core/translation/prompt-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;
|
|
1
|
+
{"version":3,"file":"prompt-builder.js","sourceRoot":"","sources":["../../../src/core/translation/prompt-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAE/D,+CAA+C;AAC/C,MAAM,yBAAyB,GAAG,IAAI,CAAC;AAEvC,2DAA2D;AAC3D,MAAM,0BAA0B,GAAG,EAAE,CAAC;AAYtC;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAAkB;IACnD,MAAM,QAAQ,GAAa;QACzB,+BAA+B;QAC/B,EAAE;QACF,wBAAwB,GAAG,CAAC,cAAc,EAAE;QAC5C,wBAAwB,GAAG,CAAC,cAAc,EAAE;QAC5C,EAAE;QACF,yBAAyB;QACzB,EAAE;QACF,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC;KAC9B,CAAC;IAEF,IAAI,GAAG,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,oCAAoC,EAAE,EAAE,CAAC,CAAC;QAC5D,KAAK,MAAM,GAAG,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC;YAClC,QAAQ,CAAC,IAAI,CACX,OAAO,GAAG,CAAC,aAAa,IAAI,GAAG,CAAC,WAAW,OAAO,GAAG,CAAC,aAAa,MAAM,GAAG,CAAC,UAAU,CAAC,MAAM,aAAa,CAC5G,CAAC;YACF,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;gBAC/B,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,QAAQ,iBAAiB,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC;YACnE,CAAC;YACD,IAAI,GAAG,CAAC,cAAc,EAAE,CAAC;gBACvB,QAAQ,CAAC,IAAI,CAAC,uBAAuB,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC;YAC7D,CAAC;QACH,CAAC;IACH,CAAC;IAED,QAAQ,CAAC,IAAI,CACX,EAAE,EACF,kBAAkB,EAClB,qEAAqE,EACrE,gDAAgD,CACjD,CAAC;IAEF,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC7B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,sBAAsB,CAAC,GAAkB;IACvD,MAAM,SAAS,GAAG,GAAG,CAAC,eAAe,IAAI,yBAAyB,CAAC;IACnE,IAAI,SAAS,GAAG,KAAK,CAAC;IAEtB,2FAA2F;IAC3F,IAAI,eAAe,GAAG,GAAG,CAAC,MAAM,CAAC;IACjC,IAAI,eAAe,CAAC,MAAM,GAAG,0BAA0B,EAAE,CAAC;QACxD,2CAA2C;QAC3C,eAAe,GAAG,CAAC,GAAG,eAAe,CAAC;aACnC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,eAAe,GAAG,CAAC,CAAC,eAAe,CAAC;aACrD,KAAK,CAAC,CAAC,EAAE,0BAA0B,CAAC,CAAC;QACxC,SAAS,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,MAAM,kBAAkB,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC;IAClF,MAAM,aAAa,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC;IAE5E,8CAA8C;IAC9C,IAAI,WAAW,GAAG,GAAG,CAAC,UAAU,CAAC;IACjC,MAAM,WAAW,GAAG,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAE/C,MAAM,QAAQ,GAAa;QACzB,wBAAwB,GAAG,CAAC,cAAc,MAAM,GAAG,CAAC,cAAc,EAAE;QACpE,EAAE;QACF,iBAAiB;QACjB,KAAK,GAAG,GAAG,CAAC,cAAc;QAC1B,WAAW;QACX,KAAK;QACL,EAAE;QACF,wBAAwB;QACxB,iCAAiC,kBAAkB,wCAAwC;QAC3F,+BAA+B,aAAa,qBAAqB;QACjE,EAAE;QACF,iBAAiB,CAAC,eAAe,CAAC;KACnC,CAAC;IAEF,IAAI,aAAa,GAAG,CAAC,EAAE,CAAC;QACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,sCAAsC,CAAC,CAAC;QAC1D,KAAK,MAAM,KAAK,IAAI,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,CAAC;YACnE,QAAQ,CAAC,IAAI,CACX,OAAO,KAAK,CAAC,WAAW,mBAAmB,KAAK,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAC/E,CAAC;YACF,IAAI,KAAK,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAClC,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;oBACrC,QAAQ,CAAC,IAAI,CAAC,oBAAoB,GAAG,CAAC,MAAM,KAAK,GAAG,CAAC,UAAU,GAAG,CAAC,CAAC;gBACtE,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,GAAG,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,wBAAwB,CAAC,CAAC;QAC5C,KAAK,MAAM,GAAG,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC;YAClC,MAAM,IAAI,GAAG,GAAG,CAAC,aAAa,IAAI,GAAG,CAAC,WAAW,CAAC;YAClD,QAAQ,CAAC,IAAI,CAAC,OAAO,IAAI,OAAO,GAAG,CAAC,aAAa,MAAM,GAAG,CAAC,cAAc,IAAI,eAAe,EAAE,CAAC,CAAC;QAClG,CAAC;IACH,CAAC;IAED,QAAQ,CAAC,IAAI,CACX,EAAE,EACF,kBAAkB,EAClB,gCAAgC,GAAG,CAAC,cAAc,GAAG,EACrD,wFAAwF,EACxF,8BAA8B,GAAG,CAAC,cAAc,gCAAgC,EAChF,kCAAkC,CACnC,CAAC;IAEF,2DAA2D;IAC3D,IAAI,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,cAAc,CAAC,MAAM,CAAC,GAAG,SAAS,EAAE,CAAC;QACvC,qDAAqD;QACrD,IAAI,EAAE,GAAG,CAAC,CAAC;QACX,IAAI,EAAE,GAAG,WAAW,CAAC,MAAM,CAAC;QAC5B,OAAO,EAAE,GAAG,EAAE,EAAE,CAAC;YACf,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;YACrC,MAAM,SAAS,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;kBAClD,oCAAoC,GAAG,aAAa,WAAW,CAAC,MAAM,SAAS,CAAC;YACpF,QAAQ,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,oCAAoC;YAC7D,MAAM,eAAe,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC5C,IAAI,cAAc,CAAC,eAAe,CAAC,IAAI,SAAS,EAAE,CAAC;gBACjD,EAAE,GAAG,GAAG,CAAC;YACX,CAAC;iBAAM,CAAC;gBACN,EAAE,GAAG,GAAG,GAAG,CAAC,CAAC;YACf,CAAC;QACH,CAAC;QACD,WAAW,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;cAC7C,oCAAoC,EAAE,aAAa,WAAW,CAAC,MAAM,SAAS,CAAC;QACnF,QAAQ,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC;QAC1B,SAAS,GAAG,IAAI,CAAC;QACjB,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,IAAI,4BAA4B,CAAC;IACzC,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,0BAA0B,CACxC,GAAkB,EAClB,UAAkB,EAClB,MAAgB;IAEhB,OAAO;QACL,wBAAwB,GAAG,CAAC,cAAc,EAAE;QAC5C,EAAE;QACF,iBAAiB,GAAG,CAAC,cAAc,wEAAwE;QAC3G,EAAE;QACF,sBAAsB;QACtB,KAAK,GAAG,GAAG,CAAC,cAAc;QAC1B,UAAU;QACV,KAAK;QACL,EAAE;QACF,YAAY;QACZ,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9B,EAAE;QACF,kBAAkB;QAClB,+DAA+D;QAC/D,4BAA4B;KAC7B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,yBAAyB,CACvC,GAAkB,EAClB,UAAkB,EAClB,MAAgB;IAEhB,OAAO;QACL,uBAAuB,GAAG,CAAC,cAAc,MAAM,GAAG,CAAC,cAAc,EAAE;QACnE,EAAE;QACF,sFAAsF;QACtF,EAAE;QACF,wBAAwB,GAAG,CAAC,cAAc,GAAG;QAC7C,KAAK,GAAG,GAAG,CAAC,cAAc;QAC1B,GAAG,CAAC,UAAU;QACd,KAAK;QACL,EAAE;QACF,4BAA4B,GAAG,CAAC,cAAc,GAAG;QACjD,KAAK,GAAG,GAAG,CAAC,cAAc;QAC1B,UAAU;QACV,KAAK;QACL,EAAE;QACF,qBAAqB;QACrB,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9B,EAAE;QACF,kBAAkB;QAClB,yCAAyC,GAAG,CAAC,cAAc,oCAAoC,GAAG,CAAC,cAAc,UAAU;QAC3H,4BAA4B;KAC7B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,SAAS,iBAAiB,CAAC,MAA0B;IACnD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,2BAA2B,CAAC;IAC5D,MAAM,KAAK,GAAG,CAAC,wCAAwC,EAAE,wCAAwC,CAAC,CAAC;IACnG,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,WAAW,MAAM,CAAC,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC;IAC3G,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prompt Paginator — splits large translation prompts into numbered pages.
|
|
3
|
+
*
|
|
4
|
+
* When a prompt exceeds the token budget (default 8K tokens), it splits
|
|
5
|
+
* at natural boundaries (code sections) and returns paginated results.
|
|
6
|
+
* Each page is self-contained with construct context header.
|
|
7
|
+
*/
|
|
8
|
+
export interface PromptPage {
|
|
9
|
+
content: string;
|
|
10
|
+
currentPage: number;
|
|
11
|
+
totalPages: number;
|
|
12
|
+
tokenEstimate: number;
|
|
13
|
+
truncated: boolean;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Paginate a prompt if it exceeds the token budget.
|
|
17
|
+
* Returns a single page if within budget (no pagination needed).
|
|
18
|
+
*/
|
|
19
|
+
export declare function paginatePrompt(prompt: string, pageTokenBudget?: number, requestedPage?: number): PromptPage;
|
|
20
|
+
//# sourceMappingURL=prompt-paginator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt-paginator.d.ts","sourceRoot":"","sources":["../../../src/core/translation/prompt-paginator.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,MAAM,EACd,eAAe,GAAE,MAAkC,EACnD,aAAa,GAAE,MAAU,GACxB,UAAU,CAoCZ"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prompt Paginator — splits large translation prompts into numbered pages.
|
|
3
|
+
*
|
|
4
|
+
* When a prompt exceeds the token budget (default 8K tokens), it splits
|
|
5
|
+
* at natural boundaries (code sections) and returns paginated results.
|
|
6
|
+
* Each page is self-contained with construct context header.
|
|
7
|
+
*/
|
|
8
|
+
import { estimateTokens } from "../context/token-estimator.js";
|
|
9
|
+
import { logger } from "../utils/logger.js";
|
|
10
|
+
const DEFAULT_PAGE_TOKEN_BUDGET = 8000;
|
|
11
|
+
/**
|
|
12
|
+
* Paginate a prompt if it exceeds the token budget.
|
|
13
|
+
* Returns a single page if within budget (no pagination needed).
|
|
14
|
+
*/
|
|
15
|
+
export function paginatePrompt(prompt, pageTokenBudget = DEFAULT_PAGE_TOKEN_BUDGET, requestedPage = 1) {
|
|
16
|
+
const totalTokens = estimateTokens(prompt);
|
|
17
|
+
// If within budget, return as single page
|
|
18
|
+
if (totalTokens <= pageTokenBudget) {
|
|
19
|
+
return {
|
|
20
|
+
content: prompt,
|
|
21
|
+
currentPage: 1,
|
|
22
|
+
totalPages: 1,
|
|
23
|
+
tokenEstimate: totalTokens,
|
|
24
|
+
truncated: false,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
// Split prompt into sections at markdown headers or code block boundaries
|
|
28
|
+
const sections = splitPromptSections(prompt);
|
|
29
|
+
const pages = buildPages(sections, pageTokenBudget);
|
|
30
|
+
const totalPages = pages.length;
|
|
31
|
+
const pageIndex = Math.max(0, Math.min(requestedPage - 1, totalPages - 1));
|
|
32
|
+
const page = pages[pageIndex];
|
|
33
|
+
logger.debug("prompt:paginated", {
|
|
34
|
+
totalTokens,
|
|
35
|
+
totalPages,
|
|
36
|
+
requestedPage,
|
|
37
|
+
pageTokens: estimateTokens(page),
|
|
38
|
+
});
|
|
39
|
+
return {
|
|
40
|
+
content: page,
|
|
41
|
+
currentPage: pageIndex + 1,
|
|
42
|
+
totalPages,
|
|
43
|
+
tokenEstimate: estimateTokens(page),
|
|
44
|
+
truncated: true,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Split a prompt into logical sections (headers, code blocks, tables).
|
|
49
|
+
*/
|
|
50
|
+
function splitPromptSections(prompt) {
|
|
51
|
+
const sections = [];
|
|
52
|
+
const lines = prompt.split("\n");
|
|
53
|
+
let current = [];
|
|
54
|
+
for (const line of lines) {
|
|
55
|
+
// Split at markdown headers (##, ###)
|
|
56
|
+
if (/^#{2,3}\s/.test(line) && current.length > 0) {
|
|
57
|
+
sections.push(current.join("\n"));
|
|
58
|
+
current = [];
|
|
59
|
+
}
|
|
60
|
+
current.push(line);
|
|
61
|
+
}
|
|
62
|
+
if (current.length > 0) {
|
|
63
|
+
sections.push(current.join("\n"));
|
|
64
|
+
}
|
|
65
|
+
return sections;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Build pages from sections, respecting token budget per page.
|
|
69
|
+
* First section (header/metadata) is included in every page.
|
|
70
|
+
*/
|
|
71
|
+
function buildPages(sections, pageTokenBudget) {
|
|
72
|
+
if (sections.length === 0)
|
|
73
|
+
return [""];
|
|
74
|
+
if (sections.length === 1)
|
|
75
|
+
return [sections[0]];
|
|
76
|
+
const header = sections[0]; // Always include first section as context
|
|
77
|
+
const headerTokens = estimateTokens(header);
|
|
78
|
+
const availablePerPage = pageTokenBudget - headerTokens - 100; // 100 tokens for pagination metadata
|
|
79
|
+
const pages = [];
|
|
80
|
+
let currentPageSections = [];
|
|
81
|
+
let currentTokens = 0;
|
|
82
|
+
for (let i = 1; i < sections.length; i++) {
|
|
83
|
+
const sectionTokens = estimateTokens(sections[i]);
|
|
84
|
+
if (currentTokens + sectionTokens > availablePerPage && currentPageSections.length > 0) {
|
|
85
|
+
// Flush current page
|
|
86
|
+
const pageNum = pages.length + 1;
|
|
87
|
+
const pageHeader = `${header}\n\n_Page ${pageNum} of translation prompt_\n`;
|
|
88
|
+
pages.push(pageHeader + currentPageSections.join("\n\n"));
|
|
89
|
+
currentPageSections = [];
|
|
90
|
+
currentTokens = 0;
|
|
91
|
+
}
|
|
92
|
+
currentPageSections.push(sections[i]);
|
|
93
|
+
currentTokens += sectionTokens;
|
|
94
|
+
}
|
|
95
|
+
// Flush remaining
|
|
96
|
+
if (currentPageSections.length > 0) {
|
|
97
|
+
const pageNum = pages.length + 1;
|
|
98
|
+
const pageHeader = `${header}\n\n_Page ${pageNum} of translation prompt_\n`;
|
|
99
|
+
pages.push(pageHeader + currentPageSections.join("\n\n"));
|
|
100
|
+
}
|
|
101
|
+
// If everything fit in one page, return as-is
|
|
102
|
+
if (pages.length === 0) {
|
|
103
|
+
return [sections.join("\n\n")];
|
|
104
|
+
}
|
|
105
|
+
// Update total pages count in each page
|
|
106
|
+
return pages.map((p) => p.replace(/Page (\d+) of translation prompt/, `Page $1 of ${pages.length} — translation prompt`));
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=prompt-paginator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt-paginator.js","sourceRoot":"","sources":["../../../src/core/translation/prompt-paginator.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,MAAM,yBAAyB,GAAG,IAAI,CAAC;AAUvC;;;GAGG;AACH,MAAM,UAAU,cAAc,CAC5B,MAAc,EACd,kBAA0B,yBAAyB,EACnD,gBAAwB,CAAC;IAEzB,MAAM,WAAW,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IAE3C,0CAA0C;IAC1C,IAAI,WAAW,IAAI,eAAe,EAAE,CAAC;QACnC,OAAO;YACL,OAAO,EAAE,MAAM;YACf,WAAW,EAAE,CAAC;YACd,UAAU,EAAE,CAAC;YACb,aAAa,EAAE,WAAW;YAC1B,SAAS,EAAE,KAAK;SACjB,CAAC;IACJ,CAAC;IAED,0EAA0E;IAC1E,MAAM,QAAQ,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG,UAAU,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;IACpD,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC;IAEhC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,aAAa,GAAG,CAAC,EAAE,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC;IAC3E,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC;IAE9B,MAAM,CAAC,KAAK,CAAC,kBAAkB,EAAE;QAC/B,WAAW;QACX,UAAU;QACV,aAAa;QACb,UAAU,EAAE,cAAc,CAAC,IAAI,CAAC;KACjC,CAAC,CAAC;IAEH,OAAO;QACL,OAAO,EAAE,IAAI;QACb,WAAW,EAAE,SAAS,GAAG,CAAC;QAC1B,UAAU;QACV,aAAa,EAAE,cAAc,CAAC,IAAI,CAAC;QACnC,SAAS,EAAE,IAAI;KAChB,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,mBAAmB,CAAC,MAAc;IACzC,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,OAAO,GAAa,EAAE,CAAC;IAE3B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,sCAAsC;QACtC,IAAI,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACjD,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YAClC,OAAO,GAAG,EAAE,CAAC;QACf,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrB,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACpC,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;GAGG;AACH,SAAS,UAAU,CAAC,QAAkB,EAAE,eAAuB;IAC7D,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,EAAE,CAAC,CAAC;IACvC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAEhD,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,0CAA0C;IACtE,MAAM,YAAY,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IAC5C,MAAM,gBAAgB,GAAG,eAAe,GAAG,YAAY,GAAG,GAAG,CAAC,CAAC,qCAAqC;IAEpG,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,mBAAmB,GAAa,EAAE,CAAC;IACvC,IAAI,aAAa,GAAG,CAAC,CAAC;IAEtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,MAAM,aAAa,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QAElD,IAAI,aAAa,GAAG,aAAa,GAAG,gBAAgB,IAAI,mBAAmB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvF,qBAAqB;YACrB,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;YACjC,MAAM,UAAU,GAAG,GAAG,MAAM,aAAa,OAAO,2BAA2B,CAAC;YAC5E,KAAK,CAAC,IAAI,CAAC,UAAU,GAAG,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;YAC1D,mBAAmB,GAAG,EAAE,CAAC;YACzB,aAAa,GAAG,CAAC,CAAC;QACpB,CAAC;QAED,mBAAmB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QACtC,aAAa,IAAI,aAAa,CAAC;IACjC,CAAC;IAED,kBAAkB;IAClB,IAAI,mBAAmB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnC,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;QACjC,MAAM,UAAU,GAAG,GAAG,MAAM,aAAa,OAAO,2BAA2B,CAAC;QAC5E,KAAK,CAAC,IAAI,CAAC,UAAU,GAAG,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IAC5D,CAAC;IAED,8CAA8C;IAC9C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IACjC,CAAC;IAED,wCAAwC;IACxC,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACrB,CAAC,CAAC,OAAO,CACP,kCAAkC,EAClC,cAAc,KAAK,CAAC,MAAM,uBAAuB,CAClD,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { ConstructRegistry } from "./ucr/construct-registry.js";
|
|
7
7
|
import { TranslationStore } from "./translation-store.js";
|
|
8
|
+
import type { CodeStore } from "../code/code-store.js";
|
|
8
9
|
import type { TranslationAnalysis, TranslationScope } from "./translation-types.js";
|
|
9
10
|
interface AnalyzeHints {
|
|
10
11
|
languageHint?: string;
|
|
@@ -49,11 +50,17 @@ interface FinalizeResult {
|
|
|
49
50
|
export declare class TranslationOrchestrator {
|
|
50
51
|
private readonly registry;
|
|
51
52
|
private readonly store;
|
|
52
|
-
|
|
53
|
+
private readonly codeStore?;
|
|
54
|
+
constructor(registry: ConstructRegistry, store: TranslationStore, codeStore?: CodeStore | undefined);
|
|
53
55
|
/**
|
|
54
56
|
* Analyze source code — detect language, identify constructs, compute complexity.
|
|
57
|
+
* Results are cached with SHA-256 content hash (TTL 60min, max 100 entries).
|
|
58
|
+
* When filePath + projectId are provided and Code Intelligence has indexed the file,
|
|
59
|
+
* uses pre-indexed analysis (instant, zero parsing cost).
|
|
55
60
|
*/
|
|
56
|
-
analyzeSource(code: string, hints?: AnalyzeHints): TranslationAnalysis
|
|
61
|
+
analyzeSource(code: string, hints?: AnalyzeHints, filePath?: string, projectId?: string): TranslationAnalysis & {
|
|
62
|
+
cacheHit: boolean;
|
|
63
|
+
};
|
|
57
64
|
/**
|
|
58
65
|
* Prepare a translation job — creates the job, analyzes source, builds prompt.
|
|
59
66
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"translation-orchestrator.d.ts","sourceRoot":"","sources":["../../../src/core/translation/translation-orchestrator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"translation-orchestrator.d.ts","sourceRoot":"","sources":["../../../src/core/translation/translation-orchestrator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,KAAK,EAAE,mBAAmB,EAAkB,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAqEpG,UAAU,YAAY;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,UAAU,YAAY;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,gBAAgB,CAAC;CACzB;AAED,UAAU,aAAa;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,mBAAmB,CAAC;CAC/B;AAED,UAAU,YAAY;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,oBAAoB,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChF,KAAK,EAAE,KAAK,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACvE,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED,UAAU,cAAc;IACtB,GAAG,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,eAAe,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACnF,QAAQ,EAAE,YAAY,CAAC;CACxB;AAqBD,qBAAa,uBAAuB;IAEhC,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC;gBAFV,QAAQ,EAAE,iBAAiB,EAC3B,KAAK,EAAE,gBAAgB,EACvB,SAAS,CAAC,EAAE,SAAS,YAAA;IAGxC;;;;;OAKG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,YAAY,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,mBAAmB,GAAG;QAAE,QAAQ,EAAE,OAAO,CAAA;KAAE;IAqFrI;;OAEG;IACH,kBAAkB,CAAC,KAAK,EAAE,YAAY,GAAG,aAAa;IA+CtD;;OAEG;IACH,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,cAAc;CAkD1E"}
|
|
@@ -3,28 +3,111 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Flow: analyzeSource → prepareTranslation → (AI generates code) → finalizeTranslation
|
|
5
5
|
*/
|
|
6
|
+
import { createHash } from "node:crypto";
|
|
7
|
+
import { analyzeFromIndex } from "./pre-indexed-analyzer.js";
|
|
6
8
|
import { detectLanguageFromCode } from "./language-detect.js";
|
|
7
9
|
import { TsParserAdapter } from "./parsers/ts-parser-adapter.js";
|
|
8
10
|
import { PythonParserAdapter } from "./parsers/python-parser-adapter.js";
|
|
11
|
+
import { JavaParserAdapter } from "./parsers/java-parser-adapter.js";
|
|
12
|
+
import { GoParserAdapter } from "./parsers/go-parser-adapter.js";
|
|
13
|
+
import { CSharpParserAdapter } from "./parsers/csharp-parser-adapter.js";
|
|
14
|
+
import { RustParserAdapter } from "./parsers/rust-parser-adapter.js";
|
|
15
|
+
import { RubyParserAdapter } from "./parsers/ruby-parser-adapter.js";
|
|
16
|
+
import { PhpParserAdapter } from "./parsers/php-parser-adapter.js";
|
|
17
|
+
import { SwiftParserAdapter } from "./parsers/swift-parser-adapter.js";
|
|
18
|
+
import { KotlinParserAdapter } from "./parsers/kotlin-parser-adapter.js";
|
|
19
|
+
import { ScalaParserAdapter } from "./parsers/scala-parser-adapter.js";
|
|
20
|
+
import { ElixirParserAdapter } from "./parsers/elixir-parser-adapter.js";
|
|
21
|
+
import { DartParserAdapter } from "./parsers/dart-parser-adapter.js";
|
|
22
|
+
import { HaskellParserAdapter } from "./parsers/haskell-parser-adapter.js";
|
|
23
|
+
import { CppParserAdapter } from "./parsers/cpp-parser-adapter.js";
|
|
24
|
+
import { LuaParserAdapter } from "./parsers/lua-parser-adapter.js";
|
|
9
25
|
import { scoreConstructs } from "./confidence/equivalence-scorer.js";
|
|
10
26
|
import { detectAmbiguities } from "./confidence/ambiguity-detector.js";
|
|
11
27
|
import { buildTranslationPrompt } from "./prompt-builder.js";
|
|
12
28
|
import { TranslationError } from "../utils/errors.js";
|
|
29
|
+
/**
|
|
30
|
+
* Mapping of equivalent constructs across languages.
|
|
31
|
+
* When source construct X translates to target construct Y,
|
|
32
|
+
* both are valid equivalents and should not be flagged as risk.
|
|
33
|
+
*/
|
|
34
|
+
const EQUIVALENT_CONSTRUCTS = new Map([
|
|
35
|
+
["uc_for_each", "uc_for_loop"],
|
|
36
|
+
["uc_for_loop", "uc_for_each"],
|
|
37
|
+
["uc_fn_def", "uc_arrow_fn"],
|
|
38
|
+
["uc_arrow_fn", "uc_fn_def"],
|
|
39
|
+
]);
|
|
40
|
+
// ── Analysis Cache (LRU, SHA-256 keyed) ────────────
|
|
41
|
+
const ANALYSIS_CACHE_TTL_MS = 3_600_000; // 60 minutes
|
|
42
|
+
const ANALYSIS_CACHE_MAX_ENTRIES = 100;
|
|
43
|
+
const analysisCache = new Map();
|
|
44
|
+
function computeCacheKey(code, targetLanguage) {
|
|
45
|
+
return createHash("sha256")
|
|
46
|
+
.update(code + "|" + (targetLanguage ?? ""))
|
|
47
|
+
.digest("hex");
|
|
48
|
+
}
|
|
49
|
+
function evictOldestIfNeeded() {
|
|
50
|
+
if (analysisCache.size <= ANALYSIS_CACHE_MAX_ENTRIES)
|
|
51
|
+
return;
|
|
52
|
+
let oldestKey;
|
|
53
|
+
let oldestTs = Infinity;
|
|
54
|
+
for (const [key, entry] of analysisCache) {
|
|
55
|
+
if (entry.timestamp < oldestTs) {
|
|
56
|
+
oldestTs = entry.timestamp;
|
|
57
|
+
oldestKey = key;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (oldestKey)
|
|
61
|
+
analysisCache.delete(oldestKey);
|
|
62
|
+
}
|
|
13
63
|
const PARSERS = new Map([
|
|
14
64
|
["typescript", new TsParserAdapter()],
|
|
15
65
|
["python", new PythonParserAdapter()],
|
|
66
|
+
["java", new JavaParserAdapter()],
|
|
67
|
+
["go", new GoParserAdapter()],
|
|
68
|
+
["csharp", new CSharpParserAdapter()],
|
|
69
|
+
["rust", new RustParserAdapter()],
|
|
70
|
+
["ruby", new RubyParserAdapter()],
|
|
71
|
+
["php", new PhpParserAdapter()],
|
|
72
|
+
["swift", new SwiftParserAdapter()],
|
|
73
|
+
["kotlin", new KotlinParserAdapter()],
|
|
74
|
+
["scala", new ScalaParserAdapter()],
|
|
75
|
+
["elixir", new ElixirParserAdapter()],
|
|
76
|
+
["dart", new DartParserAdapter()],
|
|
77
|
+
["haskell", new HaskellParserAdapter()],
|
|
78
|
+
["cpp", new CppParserAdapter()],
|
|
79
|
+
["lua", new LuaParserAdapter()],
|
|
16
80
|
]);
|
|
17
81
|
export class TranslationOrchestrator {
|
|
18
82
|
registry;
|
|
19
83
|
store;
|
|
20
|
-
|
|
84
|
+
codeStore;
|
|
85
|
+
constructor(registry, store, codeStore) {
|
|
21
86
|
this.registry = registry;
|
|
22
87
|
this.store = store;
|
|
88
|
+
this.codeStore = codeStore;
|
|
23
89
|
}
|
|
24
90
|
/**
|
|
25
91
|
* Analyze source code — detect language, identify constructs, compute complexity.
|
|
92
|
+
* Results are cached with SHA-256 content hash (TTL 60min, max 100 entries).
|
|
93
|
+
* When filePath + projectId are provided and Code Intelligence has indexed the file,
|
|
94
|
+
* uses pre-indexed analysis (instant, zero parsing cost).
|
|
26
95
|
*/
|
|
27
|
-
analyzeSource(code, hints) {
|
|
96
|
+
analyzeSource(code, hints, filePath, projectId) {
|
|
97
|
+
// Try pre-indexed analysis (Layer 5) when file context is available
|
|
98
|
+
if (filePath && projectId && this.codeStore) {
|
|
99
|
+
const preIndexed = analyzeFromIndex(this.codeStore, projectId, filePath);
|
|
100
|
+
if (preIndexed) {
|
|
101
|
+
const result = { ...preIndexed.analysis, cacheHit: false };
|
|
102
|
+
return result;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
// Check cache
|
|
106
|
+
const cacheKey = computeCacheKey(code, hints?.targetLanguage);
|
|
107
|
+
const cached = analysisCache.get(cacheKey);
|
|
108
|
+
if (cached && Date.now() - cached.timestamp < ANALYSIS_CACHE_TTL_MS) {
|
|
109
|
+
return { ...cached.result, cacheHit: true };
|
|
110
|
+
}
|
|
28
111
|
// Detect language
|
|
29
112
|
const detection = detectLanguageFromCode(code);
|
|
30
113
|
const lang = hints?.languageHint ?? detection.languageId;
|
|
@@ -68,7 +151,7 @@ export class TranslationOrchestrator {
|
|
|
68
151
|
const estimatedTranslatability = scores.length > 0
|
|
69
152
|
? scores.reduce((sum, s) => sum + s.finalConfidence, 0) / scores.length
|
|
70
153
|
: 0;
|
|
71
|
-
|
|
154
|
+
const result = {
|
|
72
155
|
detectedLanguage: lang,
|
|
73
156
|
detectedConfidence: confidence,
|
|
74
157
|
constructs,
|
|
@@ -76,13 +159,19 @@ export class TranslationOrchestrator {
|
|
|
76
159
|
estimatedTranslatability,
|
|
77
160
|
ambiguousConstructs: ambiguities.map((a) => a.constructId),
|
|
78
161
|
totalConstructs: parsed.length,
|
|
162
|
+
cacheHit: false,
|
|
79
163
|
};
|
|
164
|
+
// Store in cache
|
|
165
|
+
analysisCache.set(cacheKey, { result, timestamp: Date.now() });
|
|
166
|
+
evictOldestIfNeeded();
|
|
167
|
+
return result;
|
|
80
168
|
}
|
|
81
169
|
/**
|
|
82
170
|
* Prepare a translation job — creates the job, analyzes source, builds prompt.
|
|
83
171
|
*/
|
|
84
172
|
prepareTranslation(input) {
|
|
85
|
-
const
|
|
173
|
+
const sourceCode = input.sourceCode ?? "";
|
|
174
|
+
const analysis = this.analyzeSource(sourceCode, {
|
|
86
175
|
languageHint: input.sourceLanguage,
|
|
87
176
|
targetLanguage: input.targetLanguage,
|
|
88
177
|
});
|
|
@@ -91,7 +180,7 @@ export class TranslationOrchestrator {
|
|
|
91
180
|
projectId: input.projectId,
|
|
92
181
|
sourceLanguage: analysis.detectedLanguage,
|
|
93
182
|
targetLanguage: input.targetLanguage,
|
|
94
|
-
sourceCode
|
|
183
|
+
sourceCode,
|
|
95
184
|
scope: input.scope,
|
|
96
185
|
});
|
|
97
186
|
// Update to analyzing status
|
|
@@ -100,17 +189,21 @@ export class TranslationOrchestrator {
|
|
|
100
189
|
analysis: analysis,
|
|
101
190
|
});
|
|
102
191
|
// Build scores + ambiguities for prompt
|
|
192
|
+
// Guard: if registry has no seed data, scoreConstructs returns [] safely
|
|
103
193
|
const parser = PARSERS.get(analysis.detectedLanguage);
|
|
104
|
-
const parsed = parser ? parser.parseSnippet(
|
|
105
|
-
const constructIds = [...new Set(parsed.map((p) => p.constructId))];
|
|
194
|
+
const parsed = parser ? parser.parseSnippet(sourceCode) : [];
|
|
195
|
+
const constructIds = [...new Set(parsed.map((p) => p.constructId))].filter(Boolean);
|
|
106
196
|
const scores = scoreConstructs(this.registry, constructIds, analysis.detectedLanguage, input.targetLanguage);
|
|
107
197
|
const ambiguities = detectAmbiguities(scores, this.registry, analysis.detectedLanguage, input.targetLanguage);
|
|
198
|
+
// Filter out scores/ambiguities with undefined construct data
|
|
199
|
+
const safeScores = scores.filter((s) => s.constructId != null);
|
|
200
|
+
const safeAmbiguities = ambiguities.filter((a) => a.constructId != null && a.canonicalName != null);
|
|
108
201
|
const promptCtx = {
|
|
109
202
|
sourceLanguage: analysis.detectedLanguage,
|
|
110
203
|
targetLanguage: input.targetLanguage,
|
|
111
|
-
sourceCode
|
|
112
|
-
scores,
|
|
113
|
-
ambiguities,
|
|
204
|
+
sourceCode,
|
|
205
|
+
scores: safeScores,
|
|
206
|
+
ambiguities: safeAmbiguities,
|
|
114
207
|
};
|
|
115
208
|
const prompt = buildTranslationPrompt(promptCtx);
|
|
116
209
|
return { jobId: job.id, prompt, analysis };
|
|
@@ -175,12 +268,19 @@ function buildEvidence(source, target, sourceLang, targetLang) {
|
|
|
175
268
|
translated.push({ source: id, target: id, method: "direct" });
|
|
176
269
|
}
|
|
177
270
|
else {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
}
|
|
183
|
-
|
|
271
|
+
// Check if an equivalent construct exists in target (e.g. uc_for_each ↔ uc_for_loop)
|
|
272
|
+
const equivalent = EQUIVALENT_CONSTRUCTS.get(id);
|
|
273
|
+
if (equivalent && targetIds.has(equivalent)) {
|
|
274
|
+
translated.push({ source: id, target: equivalent, method: "equivalent" });
|
|
275
|
+
}
|
|
276
|
+
else {
|
|
277
|
+
risks.push({
|
|
278
|
+
construct: id,
|
|
279
|
+
severity: "medium",
|
|
280
|
+
message: `${id} from ${sourceLang} has no direct equivalent detected in ${targetLang} output`,
|
|
281
|
+
});
|
|
282
|
+
reviewPoints.push(`Review mapping of ${id}`);
|
|
283
|
+
}
|
|
184
284
|
}
|
|
185
285
|
}
|
|
186
286
|
// Coverage-based confidence
|