- DAPProxyServer: DAP JSON dispatcher, routes by command, default handlers for all standard DAP commands, response envelope with seq/type/request_seq/success - DebugAdapterRouter: per-language adapter capability registry; routeCommand gates on active language AND adapter support - PolyglotStackTraceDecoder: infers language from source extension, marks boundary frames where adjacent frames differ in language, sets astNodeId per frame - LanguageSeamFrameDetector: detectSeams/primarySeam/seamCount/frameLanguages/ crossesBoundary over decoded polyglot stacks - Sprint279IntegrationSummary: poly-sort (Python+Rust) end-to-end DAP pipeline 26/26 tests passing (5+5+5+5+6). All new headers well under 600 lines. LoRA recorded: sprint279-2026-03-01 (7 calls, 5535 tokens). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
66 lines
2.1 KiB
C++
66 lines
2.1 KiB
C++
#pragma once
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
namespace whetstone {
|
|
|
|
struct RawFrame {
|
|
int id = 0;
|
|
std::string name;
|
|
std::string source;
|
|
int line = 0;
|
|
};
|
|
|
|
struct StackFrame {
|
|
int id = 0;
|
|
std::string name;
|
|
std::string source;
|
|
int line = 0;
|
|
std::string language;
|
|
std::string astNodeId;
|
|
bool isBoundary = false;
|
|
};
|
|
|
|
class PolyglotStackTraceDecoder {
|
|
public:
|
|
std::vector<StackFrame> decode(const std::vector<RawFrame>& raw) const {
|
|
std::vector<StackFrame> frames;
|
|
frames.reserve(raw.size());
|
|
|
|
for (const auto& r : raw) {
|
|
StackFrame f;
|
|
f.id = r.id;
|
|
f.name = r.name;
|
|
f.source = r.source;
|
|
f.line = r.line;
|
|
f.language = languageFromSource(r.source);
|
|
f.astNodeId = f.language + ":" + r.name;
|
|
frames.push_back(f);
|
|
}
|
|
|
|
// Mark boundary frames: frame i is a boundary if adjacent frame differs in language
|
|
for (std::size_t i = 0; i < frames.size(); ++i) {
|
|
bool prevDiff = (i > 0 && frames[i-1].language != frames[i].language);
|
|
bool nextDiff = (i + 1 < frames.size() && frames[i].language != frames[i+1].language);
|
|
frames[i].isBoundary = prevDiff || nextDiff;
|
|
}
|
|
|
|
return frames;
|
|
}
|
|
|
|
static std::string languageFromSource(const std::string& source) {
|
|
auto dot = source.rfind('.');
|
|
if (dot == std::string::npos) return "Unknown";
|
|
std::string ext = source.substr(dot);
|
|
if (ext == ".py") return "Python";
|
|
if (ext == ".rs") return "Rust";
|
|
if (ext == ".go") return "Go";
|
|
if (ext == ".ts" || ext == ".js") return "TypeScript";
|
|
if (ext == ".cpp" || ext == ".cc" ||
|
|
ext == ".h" || ext == ".hpp") return "C++";
|
|
return "Unknown";
|
|
}
|
|
};
|
|
|
|
} // namespace whetstone
|