@vainplex/openclaw-cortex 0.3.1 → 0.4.1
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/README.md +141 -46
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/config.js +3 -0
- package/dist/src/config.js.map +1 -1
- package/dist/src/hooks.d.ts.map +1 -1
- package/dist/src/hooks.js +13 -1
- package/dist/src/hooks.js.map +1 -1
- package/dist/src/trace-analyzer/analyzer.d.ts +59 -0
- package/dist/src/trace-analyzer/analyzer.d.ts.map +1 -0
- package/dist/src/trace-analyzer/analyzer.js +175 -0
- package/dist/src/trace-analyzer/analyzer.js.map +1 -0
- package/dist/src/trace-analyzer/chain-reconstructor.d.ts +52 -0
- package/dist/src/trace-analyzer/chain-reconstructor.d.ts.map +1 -0
- package/dist/src/trace-analyzer/chain-reconstructor.js +190 -0
- package/dist/src/trace-analyzer/chain-reconstructor.js.map +1 -0
- package/dist/src/trace-analyzer/classifier.d.ts +28 -0
- package/dist/src/trace-analyzer/classifier.d.ts.map +1 -0
- package/dist/src/trace-analyzer/classifier.js +271 -0
- package/dist/src/trace-analyzer/classifier.js.map +1 -0
- package/dist/src/trace-analyzer/config.d.ts +78 -0
- package/dist/src/trace-analyzer/config.d.ts.map +1 -0
- package/dist/src/trace-analyzer/config.js +161 -0
- package/dist/src/trace-analyzer/config.js.map +1 -0
- package/dist/src/trace-analyzer/events.d.ts +70 -0
- package/dist/src/trace-analyzer/events.d.ts.map +1 -0
- package/dist/src/trace-analyzer/events.js +228 -0
- package/dist/src/trace-analyzer/events.js.map +1 -0
- package/dist/src/trace-analyzer/hooks.d.ts +22 -0
- package/dist/src/trace-analyzer/hooks.d.ts.map +1 -0
- package/dist/src/trace-analyzer/hooks.js +151 -0
- package/dist/src/trace-analyzer/hooks.js.map +1 -0
- package/dist/src/trace-analyzer/index.d.ts +32 -0
- package/dist/src/trace-analyzer/index.d.ts.map +1 -0
- package/dist/src/trace-analyzer/index.js +30 -0
- package/dist/src/trace-analyzer/index.js.map +1 -0
- package/dist/src/trace-analyzer/nats-trace-source.d.ts +10 -0
- package/dist/src/trace-analyzer/nats-trace-source.d.ts.map +1 -0
- package/dist/src/trace-analyzer/nats-trace-source.js +151 -0
- package/dist/src/trace-analyzer/nats-trace-source.js.map +1 -0
- package/dist/src/trace-analyzer/output-generator.d.ts +29 -0
- package/dist/src/trace-analyzer/output-generator.d.ts.map +1 -0
- package/dist/src/trace-analyzer/output-generator.js +142 -0
- package/dist/src/trace-analyzer/output-generator.js.map +1 -0
- package/dist/src/trace-analyzer/redactor.d.ts +14 -0
- package/dist/src/trace-analyzer/redactor.d.ts.map +1 -0
- package/dist/src/trace-analyzer/redactor.js +137 -0
- package/dist/src/trace-analyzer/redactor.js.map +1 -0
- package/dist/src/trace-analyzer/report.d.ts +93 -0
- package/dist/src/trace-analyzer/report.d.ts.map +1 -0
- package/dist/src/trace-analyzer/report.js +108 -0
- package/dist/src/trace-analyzer/report.js.map +1 -0
- package/dist/src/trace-analyzer/signals/correction.d.ts +11 -0
- package/dist/src/trace-analyzer/signals/correction.d.ts.map +1 -0
- package/dist/src/trace-analyzer/signals/correction.js +54 -0
- package/dist/src/trace-analyzer/signals/correction.js.map +1 -0
- package/dist/src/trace-analyzer/signals/dissatisfied.d.ts +11 -0
- package/dist/src/trace-analyzer/signals/dissatisfied.d.ts.map +1 -0
- package/dist/src/trace-analyzer/signals/dissatisfied.js +60 -0
- package/dist/src/trace-analyzer/signals/dissatisfied.js.map +1 -0
- package/dist/src/trace-analyzer/signals/doom-loop.d.ts +13 -0
- package/dist/src/trace-analyzer/signals/doom-loop.d.ts.map +1 -0
- package/dist/src/trace-analyzer/signals/doom-loop.js +156 -0
- package/dist/src/trace-analyzer/signals/doom-loop.js.map +1 -0
- package/dist/src/trace-analyzer/signals/hallucination.d.ts +11 -0
- package/dist/src/trace-analyzer/signals/hallucination.d.ts.map +1 -0
- package/dist/src/trace-analyzer/signals/hallucination.js +67 -0
- package/dist/src/trace-analyzer/signals/hallucination.js.map +1 -0
- package/dist/src/trace-analyzer/signals/index.d.ts +16 -0
- package/dist/src/trace-analyzer/signals/index.d.ts.map +1 -0
- package/dist/src/trace-analyzer/signals/index.js +92 -0
- package/dist/src/trace-analyzer/signals/index.js.map +1 -0
- package/dist/src/trace-analyzer/signals/lang/index.d.ts +4 -0
- package/dist/src/trace-analyzer/signals/lang/index.d.ts.map +1 -0
- package/dist/src/trace-analyzer/signals/lang/index.js +2 -0
- package/dist/src/trace-analyzer/signals/lang/index.js.map +1 -0
- package/dist/src/trace-analyzer/signals/lang/registry.d.ts +41 -0
- package/dist/src/trace-analyzer/signals/lang/registry.d.ts.map +1 -0
- package/dist/src/trace-analyzer/signals/lang/registry.js +111 -0
- package/dist/src/trace-analyzer/signals/lang/registry.js.map +1 -0
- package/dist/src/trace-analyzer/signals/lang/signal-lang-de.d.ts +10 -0
- package/dist/src/trace-analyzer/signals/lang/signal-lang-de.d.ts.map +1 -0
- package/dist/src/trace-analyzer/signals/lang/signal-lang-de.js +60 -0
- package/dist/src/trace-analyzer/signals/lang/signal-lang-de.js.map +1 -0
- package/dist/src/trace-analyzer/signals/lang/signal-lang-en.d.ts +4 -0
- package/dist/src/trace-analyzer/signals/lang/signal-lang-en.d.ts.map +1 -0
- package/dist/src/trace-analyzer/signals/lang/signal-lang-en.js +55 -0
- package/dist/src/trace-analyzer/signals/lang/signal-lang-en.js.map +1 -0
- package/dist/src/trace-analyzer/signals/lang/signal-lang-es.d.ts +9 -0
- package/dist/src/trace-analyzer/signals/lang/signal-lang-es.d.ts.map +1 -0
- package/dist/src/trace-analyzer/signals/lang/signal-lang-es.js +59 -0
- package/dist/src/trace-analyzer/signals/lang/signal-lang-es.js.map +1 -0
- package/dist/src/trace-analyzer/signals/lang/signal-lang-fr.d.ts +10 -0
- package/dist/src/trace-analyzer/signals/lang/signal-lang-fr.d.ts.map +1 -0
- package/dist/src/trace-analyzer/signals/lang/signal-lang-fr.js +60 -0
- package/dist/src/trace-analyzer/signals/lang/signal-lang-fr.js.map +1 -0
- package/dist/src/trace-analyzer/signals/lang/signal-lang-it.d.ts +9 -0
- package/dist/src/trace-analyzer/signals/lang/signal-lang-it.d.ts.map +1 -0
- package/dist/src/trace-analyzer/signals/lang/signal-lang-it.js +59 -0
- package/dist/src/trace-analyzer/signals/lang/signal-lang-it.js.map +1 -0
- package/dist/src/trace-analyzer/signals/lang/signal-lang-ja.d.ts +9 -0
- package/dist/src/trace-analyzer/signals/lang/signal-lang-ja.d.ts.map +1 -0
- package/dist/src/trace-analyzer/signals/lang/signal-lang-ja.js +59 -0
- package/dist/src/trace-analyzer/signals/lang/signal-lang-ja.js.map +1 -0
- package/dist/src/trace-analyzer/signals/lang/signal-lang-ko.d.ts +9 -0
- package/dist/src/trace-analyzer/signals/lang/signal-lang-ko.d.ts.map +1 -0
- package/dist/src/trace-analyzer/signals/lang/signal-lang-ko.js +59 -0
- package/dist/src/trace-analyzer/signals/lang/signal-lang-ko.js.map +1 -0
- package/dist/src/trace-analyzer/signals/lang/signal-lang-pt.d.ts +9 -0
- package/dist/src/trace-analyzer/signals/lang/signal-lang-pt.d.ts.map +1 -0
- package/dist/src/trace-analyzer/signals/lang/signal-lang-pt.js +59 -0
- package/dist/src/trace-analyzer/signals/lang/signal-lang-pt.js.map +1 -0
- package/dist/src/trace-analyzer/signals/lang/signal-lang-ru.d.ts +9 -0
- package/dist/src/trace-analyzer/signals/lang/signal-lang-ru.d.ts.map +1 -0
- package/dist/src/trace-analyzer/signals/lang/signal-lang-ru.js +59 -0
- package/dist/src/trace-analyzer/signals/lang/signal-lang-ru.js.map +1 -0
- package/dist/src/trace-analyzer/signals/lang/signal-lang-zh.d.ts +8 -0
- package/dist/src/trace-analyzer/signals/lang/signal-lang-zh.d.ts.map +1 -0
- package/dist/src/trace-analyzer/signals/lang/signal-lang-zh.js +58 -0
- package/dist/src/trace-analyzer/signals/lang/signal-lang-zh.js.map +1 -0
- package/dist/src/trace-analyzer/signals/lang/types.d.ts +76 -0
- package/dist/src/trace-analyzer/signals/lang/types.d.ts.map +1 -0
- package/dist/src/trace-analyzer/signals/lang/types.js +12 -0
- package/dist/src/trace-analyzer/signals/lang/types.js.map +1 -0
- package/dist/src/trace-analyzer/signals/repeat-fail.d.ts +24 -0
- package/dist/src/trace-analyzer/signals/repeat-fail.d.ts.map +1 -0
- package/dist/src/trace-analyzer/signals/repeat-fail.js +112 -0
- package/dist/src/trace-analyzer/signals/repeat-fail.js.map +1 -0
- package/dist/src/trace-analyzer/signals/tool-fail.d.ts +10 -0
- package/dist/src/trace-analyzer/signals/tool-fail.d.ts.map +1 -0
- package/dist/src/trace-analyzer/signals/tool-fail.js +99 -0
- package/dist/src/trace-analyzer/signals/tool-fail.js.map +1 -0
- package/dist/src/trace-analyzer/signals/types.d.ts +54 -0
- package/dist/src/trace-analyzer/signals/types.d.ts.map +1 -0
- package/dist/src/trace-analyzer/signals/types.js +9 -0
- package/dist/src/trace-analyzer/signals/types.js.map +1 -0
- package/dist/src/trace-analyzer/signals/unverified-claim.d.ts +11 -0
- package/dist/src/trace-analyzer/signals/unverified-claim.d.ts.map +1 -0
- package/dist/src/trace-analyzer/signals/unverified-claim.js +84 -0
- package/dist/src/trace-analyzer/signals/unverified-claim.js.map +1 -0
- package/dist/src/trace-analyzer/trace-source.d.ts +31 -0
- package/dist/src/trace-analyzer/trace-source.d.ts.map +1 -0
- package/dist/src/trace-analyzer/trace-source.js +5 -0
- package/dist/src/trace-analyzer/trace-source.js.map +1 -0
- package/dist/src/trace-analyzer/util.d.ts +17 -0
- package/dist/src/trace-analyzer/util.d.ts.map +1 -0
- package/dist/src/trace-analyzer/util.js +26 -0
- package/dist/src/trace-analyzer/util.js.map +1 -0
- package/dist/src/types.d.ts +2 -0
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.js.map +1 -1
- package/openclaw.plugin.json +184 -2
- package/package.json +7 -4
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// Trace Analyzer — Configuration
|
|
3
|
+
// ============================================================
|
|
4
|
+
//
|
|
5
|
+
// TraceAnalyzerConfig type, defaults, and resolver.
|
|
6
|
+
// Follows the same pattern as the existing src/config.ts.
|
|
7
|
+
// ============================================================
|
|
8
|
+
/** Default trace analyzer configuration. */
|
|
9
|
+
export const TRACE_ANALYZER_DEFAULTS = {
|
|
10
|
+
enabled: false,
|
|
11
|
+
nats: {
|
|
12
|
+
url: "nats://localhost:4222",
|
|
13
|
+
stream: "openclaw-events",
|
|
14
|
+
subjectPrefix: "openclaw.events",
|
|
15
|
+
},
|
|
16
|
+
schedule: {
|
|
17
|
+
enabled: false,
|
|
18
|
+
intervalHours: 24,
|
|
19
|
+
},
|
|
20
|
+
chainGapMinutes: 30,
|
|
21
|
+
signals: {
|
|
22
|
+
"SIG-CORRECTION": { enabled: true },
|
|
23
|
+
"SIG-TOOL-FAIL": { enabled: true },
|
|
24
|
+
"SIG-DOOM-LOOP": { enabled: true },
|
|
25
|
+
"SIG-DISSATISFIED": { enabled: true },
|
|
26
|
+
"SIG-REPEAT-FAIL": { enabled: true },
|
|
27
|
+
"SIG-HALLUCINATION": { enabled: true },
|
|
28
|
+
"SIG-UNVERIFIED-CLAIM": { enabled: false },
|
|
29
|
+
},
|
|
30
|
+
llm: {
|
|
31
|
+
enabled: false,
|
|
32
|
+
},
|
|
33
|
+
output: {
|
|
34
|
+
maxFindings: 200,
|
|
35
|
+
},
|
|
36
|
+
redactPatterns: [],
|
|
37
|
+
incrementalContextWindow: 500,
|
|
38
|
+
fetchBatchSize: 500,
|
|
39
|
+
maxEventsPerRun: 100_000,
|
|
40
|
+
};
|
|
41
|
+
// ---- Typed extractors (same pattern as src/config.ts) ----
|
|
42
|
+
function bool(v, d) {
|
|
43
|
+
return typeof v === "boolean" ? v : d;
|
|
44
|
+
}
|
|
45
|
+
function int(v, d) {
|
|
46
|
+
return typeof v === "number" && Number.isFinite(v) ? Math.round(v) : d;
|
|
47
|
+
}
|
|
48
|
+
function str(v, d) {
|
|
49
|
+
return typeof v === "string" ? v : d;
|
|
50
|
+
}
|
|
51
|
+
function optStr(v) {
|
|
52
|
+
return typeof v === "string" ? v : undefined;
|
|
53
|
+
}
|
|
54
|
+
function optInt(v) {
|
|
55
|
+
return typeof v === "number" && Number.isFinite(v) ? Math.round(v) : undefined;
|
|
56
|
+
}
|
|
57
|
+
function strArr(v) {
|
|
58
|
+
if (!Array.isArray(v))
|
|
59
|
+
return undefined;
|
|
60
|
+
return v.filter((s) => typeof s === "string");
|
|
61
|
+
}
|
|
62
|
+
const VALID_SIGNAL_IDS = [
|
|
63
|
+
"SIG-CORRECTION",
|
|
64
|
+
"SIG-TOOL-FAIL",
|
|
65
|
+
"SIG-DOOM-LOOP",
|
|
66
|
+
"SIG-DISSATISFIED",
|
|
67
|
+
"SIG-REPEAT-FAIL",
|
|
68
|
+
"SIG-HALLUCINATION",
|
|
69
|
+
"SIG-UNVERIFIED-CLAIM",
|
|
70
|
+
];
|
|
71
|
+
const VALID_SEVERITIES = ["low", "medium", "high", "critical"];
|
|
72
|
+
function isValidSignalId(v) {
|
|
73
|
+
return VALID_SIGNAL_IDS.includes(v);
|
|
74
|
+
}
|
|
75
|
+
function isValidSeverity(v) {
|
|
76
|
+
return typeof v === "string" && VALID_SEVERITIES.includes(v);
|
|
77
|
+
}
|
|
78
|
+
function resolveSignalConfig(raw) {
|
|
79
|
+
const result = {};
|
|
80
|
+
// Start with defaults
|
|
81
|
+
for (const [id, config] of Object.entries(TRACE_ANALYZER_DEFAULTS.signals)) {
|
|
82
|
+
if (config) {
|
|
83
|
+
result[id] = { ...config };
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// Apply overrides
|
|
87
|
+
for (const [key, value] of Object.entries(raw)) {
|
|
88
|
+
if (!isValidSignalId(key))
|
|
89
|
+
continue;
|
|
90
|
+
if (typeof value !== "object" || value === null)
|
|
91
|
+
continue;
|
|
92
|
+
const sig = value;
|
|
93
|
+
const existing = result[key] ?? { enabled: true };
|
|
94
|
+
result[key] = {
|
|
95
|
+
enabled: bool(sig.enabled, existing.enabled),
|
|
96
|
+
severity: isValidSeverity(sig.severity) ? sig.severity : existing.severity,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
return result;
|
|
100
|
+
}
|
|
101
|
+
/** Resolve NATS sub-config from raw input. */
|
|
102
|
+
function resolveNatsConfig(natsRaw) {
|
|
103
|
+
return {
|
|
104
|
+
url: str(natsRaw.url, TRACE_ANALYZER_DEFAULTS.nats.url),
|
|
105
|
+
stream: str(natsRaw.stream, TRACE_ANALYZER_DEFAULTS.nats.stream),
|
|
106
|
+
subjectPrefix: str(natsRaw.subjectPrefix, TRACE_ANALYZER_DEFAULTS.nats.subjectPrefix),
|
|
107
|
+
credentials: optStr(natsRaw.credentials),
|
|
108
|
+
user: optStr(natsRaw.user),
|
|
109
|
+
password: optStr(natsRaw.password),
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
/** Resolve LLM sub-config from raw input. */
|
|
113
|
+
function resolveLlmConfig(llmRaw) {
|
|
114
|
+
const triageRaw = (llmRaw.triage ?? undefined);
|
|
115
|
+
return {
|
|
116
|
+
enabled: bool(llmRaw.enabled, TRACE_ANALYZER_DEFAULTS.llm.enabled),
|
|
117
|
+
endpoint: optStr(llmRaw.endpoint),
|
|
118
|
+
model: optStr(llmRaw.model),
|
|
119
|
+
apiKey: optStr(llmRaw.apiKey),
|
|
120
|
+
timeoutMs: optInt(llmRaw.timeoutMs),
|
|
121
|
+
triage: triageRaw ? {
|
|
122
|
+
endpoint: str(triageRaw.endpoint, ""),
|
|
123
|
+
model: str(triageRaw.model, ""),
|
|
124
|
+
apiKey: optStr(triageRaw.apiKey),
|
|
125
|
+
timeoutMs: optInt(triageRaw.timeoutMs),
|
|
126
|
+
} : undefined,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Resolve a raw config object into a fully-typed TraceAnalyzerConfig.
|
|
131
|
+
* Missing values are filled from TRACE_ANALYZER_DEFAULTS.
|
|
132
|
+
*/
|
|
133
|
+
export function resolveTraceAnalyzerConfig(raw) {
|
|
134
|
+
if (!raw)
|
|
135
|
+
return { ...TRACE_ANALYZER_DEFAULTS };
|
|
136
|
+
const natsRaw = (raw.nats ?? {});
|
|
137
|
+
const schedRaw = (raw.schedule ?? {});
|
|
138
|
+
const llmRaw = (raw.llm ?? {});
|
|
139
|
+
const outRaw = (raw.output ?? {});
|
|
140
|
+
const signalsRaw = (raw.signals ?? {});
|
|
141
|
+
return {
|
|
142
|
+
enabled: bool(raw.enabled, TRACE_ANALYZER_DEFAULTS.enabled),
|
|
143
|
+
nats: resolveNatsConfig(natsRaw),
|
|
144
|
+
schedule: {
|
|
145
|
+
enabled: bool(schedRaw.enabled, TRACE_ANALYZER_DEFAULTS.schedule.enabled),
|
|
146
|
+
intervalHours: int(schedRaw.intervalHours, TRACE_ANALYZER_DEFAULTS.schedule.intervalHours),
|
|
147
|
+
},
|
|
148
|
+
chainGapMinutes: int(raw.chainGapMinutes, TRACE_ANALYZER_DEFAULTS.chainGapMinutes),
|
|
149
|
+
signals: resolveSignalConfig(signalsRaw),
|
|
150
|
+
llm: resolveLlmConfig(llmRaw),
|
|
151
|
+
output: {
|
|
152
|
+
maxFindings: int(outRaw.maxFindings, TRACE_ANALYZER_DEFAULTS.output.maxFindings),
|
|
153
|
+
reportPath: optStr(outRaw.reportPath),
|
|
154
|
+
},
|
|
155
|
+
redactPatterns: strArr(raw.redactPatterns) ?? [],
|
|
156
|
+
incrementalContextWindow: int(raw.incrementalContextWindow, TRACE_ANALYZER_DEFAULTS.incrementalContextWindow),
|
|
157
|
+
fetchBatchSize: int(raw.fetchBatchSize, TRACE_ANALYZER_DEFAULTS.fetchBatchSize),
|
|
158
|
+
maxEventsPerRun: int(raw.maxEventsPerRun, TRACE_ANALYZER_DEFAULTS.maxEventsPerRun),
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/trace-analyzer/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/** Canonical event types understood by the analyzer. */
|
|
2
|
+
export type AnalyzerEventType = "msg.in" | "msg.out" | "tool.call" | "tool.result" | "session.start" | "session.end" | "run.start" | "run.end" | "run.error";
|
|
3
|
+
/**
|
|
4
|
+
* Normalized event — all source schemas are converted to this shape
|
|
5
|
+
* before entering the analysis pipeline.
|
|
6
|
+
*/
|
|
7
|
+
export type NormalizedEvent = {
|
|
8
|
+
/** Original event ID. */
|
|
9
|
+
id: string;
|
|
10
|
+
/** Timestamp in ms since epoch (extracted from `ts` or `timestamp`). */
|
|
11
|
+
ts: number;
|
|
12
|
+
/** Agent ID (e.g., "main", "forge", "viola"). */
|
|
13
|
+
agent: string;
|
|
14
|
+
/** Session identifier (normalized — "agent:main:uuid" → "uuid"). */
|
|
15
|
+
session: string;
|
|
16
|
+
/** Canonical event type. */
|
|
17
|
+
type: AnalyzerEventType;
|
|
18
|
+
/** Normalized payload. */
|
|
19
|
+
payload: NormalizedPayload;
|
|
20
|
+
/** NATS stream sequence number (for incremental tracking). */
|
|
21
|
+
seq: number;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Unified payload — consistent field names regardless of source schema.
|
|
25
|
+
* Detectors access ONLY these fields, never raw payloads.
|
|
26
|
+
*/
|
|
27
|
+
export type NormalizedPayload = {
|
|
28
|
+
content?: string;
|
|
29
|
+
role?: "user" | "assistant";
|
|
30
|
+
from?: string;
|
|
31
|
+
to?: string;
|
|
32
|
+
channel?: string;
|
|
33
|
+
success?: boolean;
|
|
34
|
+
toolName?: string;
|
|
35
|
+
toolParams?: Record<string, unknown>;
|
|
36
|
+
toolResult?: unknown;
|
|
37
|
+
toolError?: string;
|
|
38
|
+
toolDurationMs?: number;
|
|
39
|
+
toolIsError?: boolean;
|
|
40
|
+
sessionId?: string;
|
|
41
|
+
prompt?: string;
|
|
42
|
+
durationMs?: number;
|
|
43
|
+
error?: string;
|
|
44
|
+
};
|
|
45
|
+
/** Map a raw event type string to a canonical AnalyzerEventType. */
|
|
46
|
+
export declare function mapEventType(raw: string): AnalyzerEventType | null;
|
|
47
|
+
/**
|
|
48
|
+
* Detect which schema a raw event belongs to.
|
|
49
|
+
* - "A" = nats-eventstore (has `ts` as number, standard types)
|
|
50
|
+
* - "B" = session-sync (has `timestamp`, `conversation.*` types, `meta.source`)
|
|
51
|
+
* - null = unknown/unparseable
|
|
52
|
+
*/
|
|
53
|
+
export declare function detectSchema(raw: Record<string, unknown>): "A" | "B" | null;
|
|
54
|
+
/**
|
|
55
|
+
* Normalize a session string.
|
|
56
|
+
* Schema B uses "agent:main:uuid" format → extract the UUID portion.
|
|
57
|
+
* Schema A uses direct session keys ("main", "unknown", etc.).
|
|
58
|
+
*/
|
|
59
|
+
export declare function normalizeSession(raw: string): string;
|
|
60
|
+
/**
|
|
61
|
+
* Normalize a raw payload into the unified NormalizedPayload shape.
|
|
62
|
+
* Handles both Schema A and Schema B payload structures.
|
|
63
|
+
*/
|
|
64
|
+
export declare function normalizePayload(type: AnalyzerEventType, rawPayload: Record<string, unknown>, rawType: string): NormalizedPayload;
|
|
65
|
+
/**
|
|
66
|
+
* Normalize a raw event object (from any schema) into a NormalizedEvent.
|
|
67
|
+
* Returns null if the event cannot be normalized (unknown type, missing timestamp).
|
|
68
|
+
*/
|
|
69
|
+
export declare function normalizeEvent(raw: Record<string, unknown>, seq: number): NormalizedEvent | null;
|
|
70
|
+
//# sourceMappingURL=events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../../src/trace-analyzer/events.ts"],"names":[],"mappings":"AAUA,wDAAwD;AACxD,MAAM,MAAM,iBAAiB,GACzB,QAAQ,GACR,SAAS,GACT,WAAW,GACX,aAAa,GACb,eAAe,GACf,aAAa,GACb,WAAW,GACX,SAAS,GACT,WAAW,CAAC;AAEhB;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,yBAAyB;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,wEAAwE;IACxE,EAAE,EAAE,MAAM,CAAC;IACX,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,OAAO,EAAE,MAAM,CAAC;IAChB,4BAA4B;IAC5B,IAAI,EAAE,iBAAiB,CAAC;IACxB,0BAA0B;IAC1B,OAAO,EAAE,iBAAiB,CAAC;IAC3B,8DAA8D;IAC9D,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAE9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAGlB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,OAAO,CAAC;IAGtB,SAAS,CAAC,EAAE,MAAM,CAAC;IAGnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAwBF,oEAAoE;AACpE,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,iBAAiB,GAAG,IAAI,CAElE;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,IAAI,CAuB3E;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAMpD;AAqHD;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,iBAAiB,EACvB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,OAAO,EAAE,MAAM,GACd,iBAAiB,CAoBnB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CA6BhG"}
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// Trace Analyzer — Normalized Event Types
|
|
3
|
+
// ============================================================
|
|
4
|
+
//
|
|
5
|
+
// LOCAL event types for the trace analyzer.
|
|
6
|
+
// These are NOT imported from nats-eventstore — the analyzer
|
|
7
|
+
// normalizes both Schema A (nats-eventstore) and Schema B
|
|
8
|
+
// (session-sync) events into this unified shape.
|
|
9
|
+
// ============================================================
|
|
10
|
+
/**
|
|
11
|
+
* Map from raw event type strings (both schemas) to canonical types.
|
|
12
|
+
* Returns null for unknown/unhandled event types.
|
|
13
|
+
*/
|
|
14
|
+
const EVENT_TYPE_MAP = {
|
|
15
|
+
// Schema A (nats-eventstore hook events)
|
|
16
|
+
"msg.in": "msg.in",
|
|
17
|
+
"msg.out": "msg.out",
|
|
18
|
+
"tool.call": "tool.call",
|
|
19
|
+
"tool.result": "tool.result",
|
|
20
|
+
"session.start": "session.start",
|
|
21
|
+
"session.end": "session.end",
|
|
22
|
+
"run.start": "run.start",
|
|
23
|
+
"run.end": "run.end",
|
|
24
|
+
"run.error": "run.error",
|
|
25
|
+
// Schema B (session-sync conversation events)
|
|
26
|
+
"conversation.message.in": "msg.in",
|
|
27
|
+
"conversation.message.out": "msg.out",
|
|
28
|
+
"conversation.tool_call": "tool.call",
|
|
29
|
+
"conversation.tool_result": "tool.result",
|
|
30
|
+
};
|
|
31
|
+
/** Map a raw event type string to a canonical AnalyzerEventType. */
|
|
32
|
+
export function mapEventType(raw) {
|
|
33
|
+
return EVENT_TYPE_MAP[raw] ?? null;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Detect which schema a raw event belongs to.
|
|
37
|
+
* - "A" = nats-eventstore (has `ts` as number, standard types)
|
|
38
|
+
* - "B" = session-sync (has `timestamp`, `conversation.*` types, `meta.source`)
|
|
39
|
+
* - null = unknown/unparseable
|
|
40
|
+
*/
|
|
41
|
+
export function detectSchema(raw) {
|
|
42
|
+
if (typeof raw.type !== "string")
|
|
43
|
+
return null;
|
|
44
|
+
const rawType = raw.type;
|
|
45
|
+
// Schema B: conversation.* types OR meta.source === "session-sync"
|
|
46
|
+
if (rawType.startsWith("conversation."))
|
|
47
|
+
return "B";
|
|
48
|
+
const meta = raw.meta;
|
|
49
|
+
if (meta && typeof meta === "object" && meta.source === "session-sync") {
|
|
50
|
+
return "B";
|
|
51
|
+
}
|
|
52
|
+
// Schema A: has `ts` as number and standard event types
|
|
53
|
+
if (typeof raw.ts === "number" && EVENT_TYPE_MAP[rawType])
|
|
54
|
+
return "A";
|
|
55
|
+
// Schema B also uses `timestamp` instead of `ts`
|
|
56
|
+
if (typeof raw.timestamp === "number")
|
|
57
|
+
return "B";
|
|
58
|
+
// Fallback: if type is a known canonical type, assume A
|
|
59
|
+
if (EVENT_TYPE_MAP[rawType])
|
|
60
|
+
return "A";
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Normalize a session string.
|
|
65
|
+
* Schema B uses "agent:main:uuid" format → extract the UUID portion.
|
|
66
|
+
* Schema A uses direct session keys ("main", "unknown", etc.).
|
|
67
|
+
*/
|
|
68
|
+
export function normalizeSession(raw) {
|
|
69
|
+
if (raw.startsWith("agent:")) {
|
|
70
|
+
const parts = raw.split(":");
|
|
71
|
+
return parts[2] ?? parts[1] ?? raw;
|
|
72
|
+
}
|
|
73
|
+
return raw;
|
|
74
|
+
}
|
|
75
|
+
/** Extract optional string field. */
|
|
76
|
+
function optStr(raw, key) {
|
|
77
|
+
return typeof raw[key] === "string" ? raw[key] : undefined;
|
|
78
|
+
}
|
|
79
|
+
/** Normalize msg.in/msg.out payload — Schema B (conversation.*). */
|
|
80
|
+
function normalizeMessagePayloadB(rawPayload, role) {
|
|
81
|
+
const textPreview = rawPayload.text_preview;
|
|
82
|
+
let content;
|
|
83
|
+
if (Array.isArray(textPreview) && textPreview.length > 0) {
|
|
84
|
+
const first = textPreview[0];
|
|
85
|
+
if (first && typeof first.text === "string")
|
|
86
|
+
content = first.text;
|
|
87
|
+
}
|
|
88
|
+
return { content, role, sessionId: optStr(rawPayload, "sessionId") };
|
|
89
|
+
}
|
|
90
|
+
/** Normalize msg.in/msg.out payload — Schema A. */
|
|
91
|
+
function normalizeMessagePayloadA(rawPayload, role) {
|
|
92
|
+
return {
|
|
93
|
+
content: optStr(rawPayload, "content"),
|
|
94
|
+
role,
|
|
95
|
+
from: optStr(rawPayload, "from"),
|
|
96
|
+
to: optStr(rawPayload, "to"),
|
|
97
|
+
channel: optStr(rawPayload, "channel"),
|
|
98
|
+
success: typeof rawPayload.success === "boolean" ? rawPayload.success : undefined,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
/** Normalize tool.call payload. */
|
|
102
|
+
function normalizeToolCallPayload(rawPayload, isSchemaB) {
|
|
103
|
+
if (isSchemaB) {
|
|
104
|
+
const data = rawPayload.data;
|
|
105
|
+
return {
|
|
106
|
+
toolName: data && typeof data.name === "string" ? data.name : undefined,
|
|
107
|
+
toolParams: data && typeof data.args === "object" && data.args !== null
|
|
108
|
+
? data.args : undefined,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
toolName: optStr(rawPayload, "toolName"),
|
|
113
|
+
toolParams: typeof rawPayload.params === "object" && rawPayload.params !== null
|
|
114
|
+
? rawPayload.params : undefined,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
/** Normalize tool.result payload — Schema B. */
|
|
118
|
+
function normalizeToolResultPayloadB(rawPayload) {
|
|
119
|
+
const data = rawPayload.data;
|
|
120
|
+
let toolResult;
|
|
121
|
+
let toolError;
|
|
122
|
+
let toolIsError = false;
|
|
123
|
+
if (data) {
|
|
124
|
+
toolResult = data.result;
|
|
125
|
+
toolIsError = data.isError === true;
|
|
126
|
+
if (toolIsError && typeof data.result === "string")
|
|
127
|
+
toolError = data.result;
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
toolName: data && typeof data.name === "string" ? data.name : undefined,
|
|
131
|
+
toolResult, toolError, toolIsError,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
/** Normalize tool.result payload — Schema A. */
|
|
135
|
+
function normalizeToolResultPayloadA(rawPayload) {
|
|
136
|
+
return {
|
|
137
|
+
toolName: optStr(rawPayload, "toolName"),
|
|
138
|
+
toolParams: typeof rawPayload.params === "object" && rawPayload.params !== null
|
|
139
|
+
? rawPayload.params : undefined,
|
|
140
|
+
toolResult: rawPayload.result,
|
|
141
|
+
toolError: optStr(rawPayload, "error"),
|
|
142
|
+
toolIsError: typeof rawPayload.error === "string" ? true : undefined,
|
|
143
|
+
toolDurationMs: typeof rawPayload.durationMs === "number" ? rawPayload.durationMs : undefined,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
/** Normalize lifecycle events (session.*, run.*). */
|
|
147
|
+
function normalizeLifecyclePayload(type, rawPayload) {
|
|
148
|
+
switch (type) {
|
|
149
|
+
case "session.start":
|
|
150
|
+
return { sessionId: optStr(rawPayload, "sessionId") };
|
|
151
|
+
case "session.end":
|
|
152
|
+
return {
|
|
153
|
+
sessionId: optStr(rawPayload, "sessionId"),
|
|
154
|
+
durationMs: typeof rawPayload.durationMs === "number" ? rawPayload.durationMs : undefined,
|
|
155
|
+
};
|
|
156
|
+
case "run.start":
|
|
157
|
+
return { prompt: optStr(rawPayload, "prompt") };
|
|
158
|
+
case "run.end":
|
|
159
|
+
return {
|
|
160
|
+
success: typeof rawPayload.success === "boolean" ? rawPayload.success : undefined,
|
|
161
|
+
error: optStr(rawPayload, "error"),
|
|
162
|
+
durationMs: typeof rawPayload.durationMs === "number" ? rawPayload.durationMs : undefined,
|
|
163
|
+
};
|
|
164
|
+
case "run.error":
|
|
165
|
+
return {
|
|
166
|
+
error: optStr(rawPayload, "error"),
|
|
167
|
+
durationMs: typeof rawPayload.durationMs === "number" ? rawPayload.durationMs : undefined,
|
|
168
|
+
};
|
|
169
|
+
default:
|
|
170
|
+
return {};
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Normalize a raw payload into the unified NormalizedPayload shape.
|
|
175
|
+
* Handles both Schema A and Schema B payload structures.
|
|
176
|
+
*/
|
|
177
|
+
export function normalizePayload(type, rawPayload, rawType) {
|
|
178
|
+
const isSchemaB = rawType.startsWith("conversation.");
|
|
179
|
+
switch (type) {
|
|
180
|
+
case "msg.in":
|
|
181
|
+
case "msg.out": {
|
|
182
|
+
const role = type === "msg.in" ? "user" : "assistant";
|
|
183
|
+
return isSchemaB
|
|
184
|
+
? normalizeMessagePayloadB(rawPayload, role)
|
|
185
|
+
: normalizeMessagePayloadA(rawPayload, role);
|
|
186
|
+
}
|
|
187
|
+
case "tool.call":
|
|
188
|
+
return normalizeToolCallPayload(rawPayload, isSchemaB);
|
|
189
|
+
case "tool.result":
|
|
190
|
+
return isSchemaB
|
|
191
|
+
? normalizeToolResultPayloadB(rawPayload)
|
|
192
|
+
: normalizeToolResultPayloadA(rawPayload);
|
|
193
|
+
default:
|
|
194
|
+
return normalizeLifecyclePayload(type, rawPayload);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Normalize a raw event object (from any schema) into a NormalizedEvent.
|
|
199
|
+
* Returns null if the event cannot be normalized (unknown type, missing timestamp).
|
|
200
|
+
*/
|
|
201
|
+
export function normalizeEvent(raw, seq) {
|
|
202
|
+
const rawType = typeof raw.type === "string" ? raw.type : "";
|
|
203
|
+
const ts = typeof raw.ts === "number" ? raw.ts
|
|
204
|
+
: typeof raw.timestamp === "number" ? raw.timestamp
|
|
205
|
+
: 0;
|
|
206
|
+
if (ts === 0)
|
|
207
|
+
return null;
|
|
208
|
+
const type = mapEventType(rawType);
|
|
209
|
+
if (!type)
|
|
210
|
+
return null;
|
|
211
|
+
const agent = typeof raw.agent === "string" ? raw.agent : "unknown";
|
|
212
|
+
const rawSession = typeof raw.session === "string" ? raw.session : "unknown";
|
|
213
|
+
const session = normalizeSession(rawSession);
|
|
214
|
+
const rawPayload = (typeof raw.payload === "object" && raw.payload !== null)
|
|
215
|
+
? raw.payload
|
|
216
|
+
: {};
|
|
217
|
+
const payload = normalizePayload(type, rawPayload, rawType);
|
|
218
|
+
return {
|
|
219
|
+
id: typeof raw.id === "string" ? raw.id : "",
|
|
220
|
+
ts,
|
|
221
|
+
agent,
|
|
222
|
+
session,
|
|
223
|
+
type,
|
|
224
|
+
payload,
|
|
225
|
+
seq,
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
//# sourceMappingURL=events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.js","sourceRoot":"","sources":["../../../src/trace-analyzer/events.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,0CAA0C;AAC1C,+DAA+D;AAC/D,EAAE;AACF,4CAA4C;AAC5C,6DAA6D;AAC7D,0DAA0D;AAC1D,iDAAiD;AACjD,+DAA+D;AAiE/D;;;GAGG;AACH,MAAM,cAAc,GAAsC;IACxD,yCAAyC;IACzC,QAAQ,EAAE,QAAQ;IAClB,SAAS,EAAE,SAAS;IACpB,WAAW,EAAE,WAAW;IACxB,aAAa,EAAE,aAAa;IAC5B,eAAe,EAAE,eAAe;IAChC,aAAa,EAAE,aAAa;IAC5B,WAAW,EAAE,WAAW;IACxB,SAAS,EAAE,SAAS;IACpB,WAAW,EAAE,WAAW;IACxB,8CAA8C;IAC9C,yBAAyB,EAAE,QAAQ;IACnC,0BAA0B,EAAE,SAAS;IACrC,wBAAwB,EAAE,WAAW;IACrC,0BAA0B,EAAE,aAAa;CAC1C,CAAC;AAEF,oEAAoE;AACpE,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,OAAO,cAAc,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;AACrC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,GAA4B;IACvD,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAE9C,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC;IAEzB,mEAAmE;IACnE,IAAI,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC;QAAE,OAAO,GAAG,CAAC;IAEpD,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC;IACtB,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAK,IAAgC,CAAC,MAAM,KAAK,cAAc,EAAE,CAAC;QACpG,OAAO,GAAG,CAAC;IACb,CAAC;IAED,wDAAwD;IACxD,IAAI,OAAO,GAAG,CAAC,EAAE,KAAK,QAAQ,IAAI,cAAc,CAAC,OAAO,CAAC;QAAE,OAAO,GAAG,CAAC;IAEtE,iDAAiD;IACjD,IAAI,OAAO,GAAG,CAAC,SAAS,KAAK,QAAQ;QAAE,OAAO,GAAG,CAAC;IAElD,wDAAwD;IACxD,IAAI,cAAc,CAAC,OAAO,CAAC;QAAE,OAAO,GAAG,CAAC;IAExC,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,IAAI,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC7B,OAAO,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC;IACrC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,qCAAqC;AACrC,SAAS,MAAM,CAAC,GAA4B,EAAE,GAAW;IACvD,OAAO,OAAO,GAAG,CAAC,GAAG,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC7D,CAAC;AAED,oEAAoE;AACpE,SAAS,wBAAwB,CAC/B,UAAmC,EACnC,IAA0B;IAE1B,MAAM,WAAW,GAAG,UAAU,CAAC,YAAY,CAAC;IAC5C,IAAI,OAA2B,CAAC;IAChC,IAAI,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzD,MAAM,KAAK,GAAG,WAAW,CAAC,CAAC,CAAwC,CAAC;QACpE,IAAI,KAAK,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC;IACpE,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,CAAC,UAAU,EAAE,WAAW,CAAC,EAAE,CAAC;AACvE,CAAC;AAED,mDAAmD;AACnD,SAAS,wBAAwB,CAC/B,UAAmC,EACnC,IAA0B;IAE1B,OAAO;QACL,OAAO,EAAE,MAAM,CAAC,UAAU,EAAE,SAAS,CAAC;QACtC,IAAI;QACJ,IAAI,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC;QAChC,EAAE,EAAE,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC;QAC5B,OAAO,EAAE,MAAM,CAAC,UAAU,EAAE,SAAS,CAAC;QACtC,OAAO,EAAE,OAAO,UAAU,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;KAClF,CAAC;AACJ,CAAC;AAED,mCAAmC;AACnC,SAAS,wBAAwB,CAC/B,UAAmC,EACnC,SAAkB;IAElB,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,IAAI,GAAG,UAAU,CAAC,IAA2C,CAAC;QACpE,OAAO;YACL,QAAQ,EAAE,IAAI,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;YACvE,UAAU,EAAE,IAAI,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI;gBACrE,CAAC,CAAC,IAAI,CAAC,IAA+B,CAAC,CAAC,CAAC,SAAS;SACrD,CAAC;IACJ,CAAC;IACD,OAAO;QACL,QAAQ,EAAE,MAAM,CAAC,UAAU,EAAE,UAAU,CAAC;QACxC,UAAU,EAAE,OAAO,UAAU,CAAC,MAAM,KAAK,QAAQ,IAAI,UAAU,CAAC,MAAM,KAAK,IAAI;YAC7E,CAAC,CAAC,UAAU,CAAC,MAAiC,CAAC,CAAC,CAAC,SAAS;KAC7D,CAAC;AACJ,CAAC;AAED,gDAAgD;AAChD,SAAS,2BAA2B,CAAC,UAAmC;IACtE,MAAM,IAAI,GAAG,UAAU,CAAC,IAA2C,CAAC;IACpE,IAAI,UAAmB,CAAC;IACxB,IAAI,SAA6B,CAAC;IAClC,IAAI,WAAW,GAAG,KAAK,CAAC;IACxB,IAAI,IAAI,EAAE,CAAC;QACT,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC;QACzB,WAAW,GAAG,IAAI,CAAC,OAAO,KAAK,IAAI,CAAC;QACpC,IAAI,WAAW,IAAI,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ;YAAE,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC;IAC9E,CAAC;IACD,OAAO;QACL,QAAQ,EAAE,IAAI,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;QACvE,UAAU,EAAE,SAAS,EAAE,WAAW;KACnC,CAAC;AACJ,CAAC;AAED,gDAAgD;AAChD,SAAS,2BAA2B,CAAC,UAAmC;IACtE,OAAO;QACL,QAAQ,EAAE,MAAM,CAAC,UAAU,EAAE,UAAU,CAAC;QACxC,UAAU,EAAE,OAAO,UAAU,CAAC,MAAM,KAAK,QAAQ,IAAI,UAAU,CAAC,MAAM,KAAK,IAAI;YAC7E,CAAC,CAAC,UAAU,CAAC,MAAiC,CAAC,CAAC,CAAC,SAAS;QAC5D,UAAU,EAAE,UAAU,CAAC,MAAM;QAC7B,SAAS,EAAE,MAAM,CAAC,UAAU,EAAE,OAAO,CAAC;QACtC,WAAW,EAAE,OAAO,UAAU,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;QACpE,cAAc,EAAE,OAAO,UAAU,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS;KAC9F,CAAC;AACJ,CAAC;AAED,qDAAqD;AACrD,SAAS,yBAAyB,CAChC,IAAuB,EACvB,UAAmC;IAEnC,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,eAAe;YAClB,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,UAAU,EAAE,WAAW,CAAC,EAAE,CAAC;QACxD,KAAK,aAAa;YAChB,OAAO;gBACL,SAAS,EAAE,MAAM,CAAC,UAAU,EAAE,WAAW,CAAC;gBAC1C,UAAU,EAAE,OAAO,UAAU,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS;aAC1F,CAAC;QACJ,KAAK,WAAW;YACd,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,UAAU,EAAE,QAAQ,CAAC,EAAE,CAAC;QAClD,KAAK,SAAS;YACZ,OAAO;gBACL,OAAO,EAAE,OAAO,UAAU,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;gBACjF,KAAK,EAAE,MAAM,CAAC,UAAU,EAAE,OAAO,CAAC;gBAClC,UAAU,EAAE,OAAO,UAAU,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS;aAC1F,CAAC;QACJ,KAAK,WAAW;YACd,OAAO;gBACL,KAAK,EAAE,MAAM,CAAC,UAAU,EAAE,OAAO,CAAC;gBAClC,UAAU,EAAE,OAAO,UAAU,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS;aAC1F,CAAC;QACJ;YACE,OAAO,EAAE,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAC9B,IAAuB,EACvB,UAAmC,EACnC,OAAe;IAEf,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;IAEtD,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,QAAQ,CAAC;QACd,KAAK,SAAS,CAAC,CAAC,CAAC;YACf,MAAM,IAAI,GAAyB,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC;YAC5E,OAAO,SAAS;gBACd,CAAC,CAAC,wBAAwB,CAAC,UAAU,EAAE,IAAI,CAAC;gBAC5C,CAAC,CAAC,wBAAwB,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QACjD,CAAC;QACD,KAAK,WAAW;YACd,OAAO,wBAAwB,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;QACzD,KAAK,aAAa;YAChB,OAAO,SAAS;gBACd,CAAC,CAAC,2BAA2B,CAAC,UAAU,CAAC;gBACzC,CAAC,CAAC,2BAA2B,CAAC,UAAU,CAAC,CAAC;QAC9C;YACE,OAAO,yBAAyB,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IACvD,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,GAA4B,EAAE,GAAW;IACtE,MAAM,OAAO,GAAG,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IAE7D,MAAM,EAAE,GAAG,OAAO,GAAG,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE;QAC5C,CAAC,CAAC,OAAO,GAAG,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS;YACnD,CAAC,CAAC,CAAC,CAAC;IACN,IAAI,EAAE,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAE1B,MAAM,IAAI,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;IACnC,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IAEvB,MAAM,KAAK,GAAG,OAAO,GAAG,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IACpE,MAAM,UAAU,GAAG,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IAC7E,MAAM,OAAO,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAE7C,MAAM,UAAU,GAAG,CAAC,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,IAAI,GAAG,CAAC,OAAO,KAAK,IAAI,CAAC;QAC1E,CAAC,CAAC,GAAG,CAAC,OAAkC;QACxC,CAAC,CAAC,EAAE,CAAC;IACP,MAAM,OAAO,GAAG,gBAAgB,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;IAE5D,OAAO;QACL,EAAE,EAAE,OAAO,GAAG,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE;QAC5C,EAAE;QACF,KAAK;QACL,OAAO;QACP,IAAI;QACJ,OAAO;QACP,GAAG;KACJ,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { OpenClawPluginApi, CortexConfig } from "../types.js";
|
|
2
|
+
import { TraceAnalyzer } from "./analyzer.js";
|
|
3
|
+
/** State shared across hook registrations for cleanup. */
|
|
4
|
+
export type TraceAnalyzerHookState = {
|
|
5
|
+
/** Scheduled analysis timer (if any). */
|
|
6
|
+
timer: ReturnType<typeof setInterval> | null;
|
|
7
|
+
/** The analyzer instance (lazy, created on first command/schedule run). */
|
|
8
|
+
analyzer: TraceAnalyzer | null;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Register trace analyzer hooks (commands + optional scheduled runs).
|
|
12
|
+
*
|
|
13
|
+
* Called from the main `registerCortexHooks()` when
|
|
14
|
+
* `config.traceAnalyzer.enabled` is true.
|
|
15
|
+
*/
|
|
16
|
+
export declare function registerTraceAnalyzerHooks(api: OpenClawPluginApi, config: CortexConfig, state: TraceAnalyzerHookState): void;
|
|
17
|
+
/**
|
|
18
|
+
* Clean up trace analyzer resources.
|
|
19
|
+
* Called when the plugin stops.
|
|
20
|
+
*/
|
|
21
|
+
export declare function cleanupTraceAnalyzerHooks(state: TraceAnalyzerHookState): void;
|
|
22
|
+
//# sourceMappingURL=hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../../src/trace-analyzer/hooks.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAgB,MAAM,aAAa,CAAC;AAGjF,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAK9C,0DAA0D;AAC1D,MAAM,MAAM,sBAAsB,GAAG;IACnC,yCAAyC;IACzC,KAAK,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,GAAG,IAAI,CAAC;IAC7C,2EAA2E;IAC3E,QAAQ,EAAE,aAAa,GAAG,IAAI,CAAC;CAChC,CAAC;AAsIF;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,iBAAiB,EACtB,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,sBAAsB,GAC5B,IAAI,CAsBN;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,sBAAsB,GAAG,IAAI,CAM7E"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// Trace Analyzer — Hook Registration
|
|
3
|
+
// ============================================================
|
|
4
|
+
//
|
|
5
|
+
// Registers trace analyzer commands and scheduled runs with
|
|
6
|
+
// the OpenClaw plugin API. Called from src/hooks.ts when
|
|
7
|
+
// config.traceAnalyzer.enabled is true.
|
|
8
|
+
//
|
|
9
|
+
// Implements R-010 (batch only, not in hook path) and R-013
|
|
10
|
+
// (graceful deactivation when no TraceSource is available).
|
|
11
|
+
// ============================================================
|
|
12
|
+
import { resolveWorkspace } from "../config.js";
|
|
13
|
+
import { TraceAnalyzer } from "./analyzer.js";
|
|
14
|
+
import { createNatsTraceSource } from "./nats-trace-source.js";
|
|
15
|
+
import { SignalPatternRegistry } from "./signals/lang/index.js";
|
|
16
|
+
/**
|
|
17
|
+
* Create a TraceAnalyzer instance from config.
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Resolve language codes from CortexConfig patterns.language.
|
|
21
|
+
* Mirrors the resolveLanguageCodes logic from src/patterns.ts.
|
|
22
|
+
*/
|
|
23
|
+
function resolveLanguageCodes(language) {
|
|
24
|
+
if (language === "both")
|
|
25
|
+
return ["en", "de"];
|
|
26
|
+
if (language === "all")
|
|
27
|
+
return ["en", "de", "fr", "es", "pt", "it", "zh", "ja", "ko", "ru"];
|
|
28
|
+
if (typeof language === "string")
|
|
29
|
+
return [language];
|
|
30
|
+
if (Array.isArray(language))
|
|
31
|
+
return language;
|
|
32
|
+
return ["en", "de"];
|
|
33
|
+
}
|
|
34
|
+
async function createAnalyzer(config, workspace, logger) {
|
|
35
|
+
// Load signal patterns for configured languages
|
|
36
|
+
const langCodes = resolveLanguageCodes(config.patterns.language);
|
|
37
|
+
const signalRegistry = new SignalPatternRegistry();
|
|
38
|
+
await signalRegistry.load(langCodes);
|
|
39
|
+
const signalPatterns = signalRegistry.getPatterns();
|
|
40
|
+
logger.info(`[trace-analyzer] Loaded signal patterns for: ${signalRegistry.getLoadedLanguages().join(", ")}`);
|
|
41
|
+
return new TraceAnalyzer({
|
|
42
|
+
config: config.traceAnalyzer,
|
|
43
|
+
logger,
|
|
44
|
+
workspace,
|
|
45
|
+
topLevelLlm: config.llm,
|
|
46
|
+
createSource: () => createNatsTraceSource(config.traceAnalyzer.nats, logger),
|
|
47
|
+
signalPatterns,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Ensure the analyzer is initialized. Lazy to avoid work if never called.
|
|
52
|
+
*/
|
|
53
|
+
async function ensureAnalyzer(state, config, workspace, logger) {
|
|
54
|
+
if (!state.analyzer) {
|
|
55
|
+
state.analyzer = await createAnalyzer(config, workspace, logger);
|
|
56
|
+
}
|
|
57
|
+
return state.analyzer;
|
|
58
|
+
}
|
|
59
|
+
/** Handle the /trace-analyze command. */
|
|
60
|
+
async function handleTraceAnalyze(api, state, config, workspace, args) {
|
|
61
|
+
const logger = api.logger;
|
|
62
|
+
const full = args?.full === true || args?.full === "true";
|
|
63
|
+
try {
|
|
64
|
+
const analyzer = await ensureAnalyzer(state, config, workspace, logger);
|
|
65
|
+
const report = await analyzer.run({ full });
|
|
66
|
+
return {
|
|
67
|
+
text: [
|
|
68
|
+
`Trace analysis complete.`,
|
|
69
|
+
`Events: ${report.stats.eventsProcessed}`,
|
|
70
|
+
`Chains: ${report.stats.chainsReconstructed}`,
|
|
71
|
+
`Findings: ${report.stats.findingsDetected}`,
|
|
72
|
+
`Classified: ${report.stats.findingsClassified}`,
|
|
73
|
+
`Outputs: ${report.stats.outputsGenerated}`,
|
|
74
|
+
].join(" | "),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
logger.warn(`[trace-analyzer] Command error: ${err instanceof Error ? err.message : String(err)}`);
|
|
79
|
+
return { text: `Trace analysis failed: ${err instanceof Error ? err.message : String(err)}` };
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/** Handle the /trace-status command. */
|
|
83
|
+
async function handleTraceStatus(api, state, config, workspace) {
|
|
84
|
+
const logger = api.logger;
|
|
85
|
+
try {
|
|
86
|
+
const analyzer = await ensureAnalyzer(state, config, workspace, logger);
|
|
87
|
+
const status = await analyzer.getStatus();
|
|
88
|
+
return {
|
|
89
|
+
text: [
|
|
90
|
+
`Trace Analyzer Status`,
|
|
91
|
+
`Last run: ${status.lastRun ?? "never"}`,
|
|
92
|
+
`Total findings: ${status.findings}`,
|
|
93
|
+
`Events processed: ${status.state.totalEventsProcessed ?? 0}`,
|
|
94
|
+
].join(" | "),
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
catch (err) {
|
|
98
|
+
return { text: `Failed to get status: ${err instanceof Error ? err.message : String(err)}` };
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/** Set up the scheduled analysis interval timer. */
|
|
102
|
+
function setupSchedule(api, state, config, workspace) {
|
|
103
|
+
const intervalMs = config.traceAnalyzer.schedule.intervalHours * 60 * 60 * 1000;
|
|
104
|
+
const timer = setInterval(() => {
|
|
105
|
+
const logger = api.logger;
|
|
106
|
+
logger.info("[trace-analyzer] Running scheduled analysis...");
|
|
107
|
+
ensureAnalyzer(state, config, workspace, logger)
|
|
108
|
+
.then(analyzer => analyzer.run())
|
|
109
|
+
.catch(err => {
|
|
110
|
+
logger.warn(`[trace-analyzer] Scheduled analysis failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
111
|
+
});
|
|
112
|
+
}, intervalMs);
|
|
113
|
+
timer.unref();
|
|
114
|
+
state.timer = timer;
|
|
115
|
+
api.logger.info(`[trace-analyzer] Scheduled analysis every ${config.traceAnalyzer.schedule.intervalHours}h`);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Register trace analyzer hooks (commands + optional scheduled runs).
|
|
119
|
+
*
|
|
120
|
+
* Called from the main `registerCortexHooks()` when
|
|
121
|
+
* `config.traceAnalyzer.enabled` is true.
|
|
122
|
+
*/
|
|
123
|
+
export function registerTraceAnalyzerHooks(api, config, state) {
|
|
124
|
+
const workspace = resolveWorkspace(config);
|
|
125
|
+
api.registerCommand({
|
|
126
|
+
name: "trace-analyze",
|
|
127
|
+
description: "Run the trace analyzer pipeline (batch analysis of agent event traces)",
|
|
128
|
+
handler: (args) => handleTraceAnalyze(api, state, config, workspace, args),
|
|
129
|
+
});
|
|
130
|
+
api.registerCommand({
|
|
131
|
+
name: "trace-status",
|
|
132
|
+
description: "Show trace analyzer status (last run, findings count, processing state)",
|
|
133
|
+
handler: () => handleTraceStatus(api, state, config, workspace),
|
|
134
|
+
});
|
|
135
|
+
if (config.traceAnalyzer.schedule.enabled) {
|
|
136
|
+
setupSchedule(api, state, config, workspace);
|
|
137
|
+
}
|
|
138
|
+
api.logger.info(`[trace-analyzer] Hooks registered — schedule:${config.traceAnalyzer.schedule.enabled} llm:${config.traceAnalyzer.llm.enabled}`);
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Clean up trace analyzer resources.
|
|
142
|
+
* Called when the plugin stops.
|
|
143
|
+
*/
|
|
144
|
+
export function cleanupTraceAnalyzerHooks(state) {
|
|
145
|
+
if (state.timer) {
|
|
146
|
+
clearInterval(state.timer);
|
|
147
|
+
state.timer = null;
|
|
148
|
+
}
|
|
149
|
+
state.analyzer = null;
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=hooks.js.map
|