oh-my-knowledge 0.28.0 → 0.30.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/README.md +49 -3
- package/README.zh.md +49 -3
- package/dist/src/analysis/failure-clusterer.js +1 -1
- package/dist/src/analysis/failure-clusterer.js.map +1 -1
- package/dist/src/analysis/gap-analyzer.d.ts +8 -1
- package/dist/src/analysis/gap-analyzer.d.ts.map +1 -1
- package/dist/src/analysis/gap-analyzer.js +65 -33
- package/dist/src/analysis/gap-analyzer.js.map +1 -1
- package/dist/src/analysis/report-diagnostics.js +2 -0
- package/dist/src/analysis/report-diagnostics.js.map +1 -1
- package/dist/src/analysis/sample-diagnostics.js +14 -14
- package/dist/src/analysis/sample-diagnostics.js.map +1 -1
- package/dist/src/authoring/evolver.d.ts +7 -1
- package/dist/src/authoring/evolver.d.ts.map +1 -1
- package/dist/src/authoring/evolver.js +8 -5
- package/dist/src/authoring/evolver.js.map +1 -1
- package/dist/src/authoring/generator.d.ts +21 -23
- package/dist/src/authoring/generator.d.ts.map +1 -1
- package/dist/src/authoring/generator.js +621 -40
- package/dist/src/authoring/generator.js.map +1 -1
- package/dist/src/authoring/sample-fixer.d.ts +45 -0
- package/dist/src/authoring/sample-fixer.d.ts.map +1 -0
- package/dist/src/authoring/sample-fixer.js +186 -0
- package/dist/src/authoring/sample-fixer.js.map +1 -0
- package/dist/src/cli/commands/evolve.d.ts.map +1 -1
- package/dist/src/cli/commands/evolve.js +17 -0
- package/dist/src/cli/commands/evolve.js.map +1 -1
- package/dist/src/cli/commands/observe.d.ts.map +1 -1
- package/dist/src/cli/commands/observe.js +170 -0
- package/dist/src/cli/commands/observe.js.map +1 -1
- package/dist/src/cli/commands/registry.d.ts.map +1 -1
- package/dist/src/cli/commands/registry.js +9 -1
- package/dist/src/cli/commands/registry.js.map +1 -1
- package/dist/src/cli/commands/sample.d.ts +13 -0
- package/dist/src/cli/commands/sample.d.ts.map +1 -1
- package/dist/src/cli/commands/sample.js +307 -13
- package/dist/src/cli/commands/sample.js.map +1 -1
- package/dist/src/cli/commands/studio.d.ts.map +1 -1
- package/dist/src/cli/commands/studio.js +8 -0
- package/dist/src/cli/commands/studio.js.map +1 -1
- package/dist/src/cli/i18n-dict.d.ts +1 -1
- package/dist/src/cli/i18n-dict.d.ts.map +1 -1
- package/dist/src/cli/i18n-dict.js +189 -17
- package/dist/src/cli/i18n-dict.js.map +1 -1
- package/dist/src/cli/parse-run-config.d.ts +14 -2
- package/dist/src/cli/parse-run-config.d.ts.map +1 -1
- package/dist/src/cli/parse-run-config.js +62 -10
- package/dist/src/cli/parse-run-config.js.map +1 -1
- package/dist/src/doctor/health/builtin-dimensions.d.ts.map +1 -1
- package/dist/src/doctor/health/builtin-dimensions.js +20 -23
- package/dist/src/doctor/health/builtin-dimensions.js.map +1 -1
- package/dist/src/doctor/health/composer.d.ts.map +1 -1
- package/dist/src/doctor/health/composer.js +7 -3
- package/dist/src/doctor/health/composer.js.map +1 -1
- package/dist/src/doctor/health/dimension-spec.d.ts +1 -0
- package/dist/src/doctor/health/dimension-spec.d.ts.map +1 -1
- package/dist/src/doctor/health/parser.d.ts.map +1 -1
- package/dist/src/doctor/health/parser.js +1 -0
- package/dist/src/doctor/health/parser.js.map +1 -1
- package/dist/src/doctor/health/prompt-builder.js +25 -17
- package/dist/src/doctor/health/prompt-builder.js.map +1 -1
- package/dist/src/doctor/html-renderer.d.ts.map +1 -1
- package/dist/src/doctor/html-renderer.js +76 -66
- package/dist/src/doctor/html-renderer.js.map +1 -1
- package/dist/src/doctor/rules.d.ts.map +1 -1
- package/dist/src/doctor/rules.js +32 -0
- package/dist/src/doctor/rules.js.map +1 -1
- package/dist/src/eval-core/cache.d.ts +16 -2
- package/dist/src/eval-core/cache.d.ts.map +1 -1
- package/dist/src/eval-core/cache.js +86 -15
- package/dist/src/eval-core/cache.js.map +1 -1
- package/dist/src/eval-core/evaluation-execution.d.ts +11 -1
- package/dist/src/eval-core/evaluation-execution.d.ts.map +1 -1
- package/dist/src/eval-core/evaluation-execution.js +78 -6
- package/dist/src/eval-core/evaluation-execution.js.map +1 -1
- package/dist/src/eval-core/evaluation-job.d.ts +2 -1
- package/dist/src/eval-core/evaluation-job.d.ts.map +1 -1
- package/dist/src/eval-core/evaluation-job.js +2 -1
- package/dist/src/eval-core/evaluation-job.js.map +1 -1
- package/dist/src/eval-core/evaluation-reporting.d.ts +7 -0
- package/dist/src/eval-core/evaluation-reporting.d.ts.map +1 -1
- package/dist/src/eval-core/evaluation-reporting.js +19 -2
- package/dist/src/eval-core/evaluation-reporting.js.map +1 -1
- package/dist/src/eval-core/execution-strategy.d.ts +1 -1
- package/dist/src/eval-core/execution-strategy.d.ts.map +1 -1
- package/dist/src/eval-core/execution-strategy.js +12 -1
- package/dist/src/eval-core/execution-strategy.js.map +1 -1
- package/dist/src/eval-core/mock-hook.cjs +203 -0
- package/dist/src/eval-core/mocks-runtime.d.ts +96 -0
- package/dist/src/eval-core/mocks-runtime.d.ts.map +1 -0
- package/dist/src/eval-core/mocks-runtime.js +323 -0
- package/dist/src/eval-core/mocks-runtime.js.map +1 -0
- package/dist/src/eval-core/schema.d.ts.map +1 -1
- package/dist/src/eval-core/schema.js +18 -5
- package/dist/src/eval-core/schema.js.map +1 -1
- package/dist/src/eval-core/task-planner.d.ts +9 -1
- package/dist/src/eval-core/task-planner.d.ts.map +1 -1
- package/dist/src/eval-core/task-planner.js +40 -1
- package/dist/src/eval-core/task-planner.js.map +1 -1
- package/dist/src/eval-workflows/batch-evaluation-workflow.d.ts +5 -1
- package/dist/src/eval-workflows/batch-evaluation-workflow.d.ts.map +1 -1
- package/dist/src/eval-workflows/batch-evaluation-workflow.js +2 -1
- package/dist/src/eval-workflows/batch-evaluation-workflow.js.map +1 -1
- package/dist/src/eval-workflows/evaluation-pipeline.d.ts +22 -1
- package/dist/src/eval-workflows/evaluation-pipeline.d.ts.map +1 -1
- package/dist/src/eval-workflows/evaluation-pipeline.js +39 -12
- package/dist/src/eval-workflows/evaluation-pipeline.js.map +1 -1
- package/dist/src/eval-workflows/evaluation-preparation.d.ts +5 -0
- package/dist/src/eval-workflows/evaluation-preparation.d.ts.map +1 -1
- package/dist/src/eval-workflows/evaluation-preparation.js +3 -1
- package/dist/src/eval-workflows/evaluation-preparation.js.map +1 -1
- package/dist/src/eval-workflows/run-evaluation.d.ts +12 -2
- package/dist/src/eval-workflows/run-evaluation.d.ts.map +1 -1
- package/dist/src/eval-workflows/run-evaluation.js +17 -5
- package/dist/src/eval-workflows/run-evaluation.js.map +1 -1
- package/dist/src/executors/claude-cli.d.ts +1 -1
- package/dist/src/executors/claude-cli.d.ts.map +1 -1
- package/dist/src/executors/claude-cli.js +57 -6
- package/dist/src/executors/claude-cli.js.map +1 -1
- package/dist/src/executors/claude-sdk-trace.d.ts.map +1 -1
- package/dist/src/executors/claude-sdk-trace.js +10 -4
- package/dist/src/executors/claude-sdk-trace.js.map +1 -1
- package/dist/src/executors/claude-sdk.d.ts +1 -1
- package/dist/src/executors/claude-sdk.d.ts.map +1 -1
- package/dist/src/executors/claude-sdk.js +25 -2
- package/dist/src/executors/claude-sdk.js.map +1 -1
- package/dist/src/executors/shared.d.ts +1 -1
- package/dist/src/executors/shared.d.ts.map +1 -1
- package/dist/src/executors/shared.js +6 -1
- package/dist/src/executors/shared.js.map +1 -1
- package/dist/src/grading/assertions.d.ts +5 -0
- package/dist/src/grading/assertions.d.ts.map +1 -1
- package/dist/src/grading/assertions.js +27 -1
- package/dist/src/grading/assertions.js.map +1 -1
- package/dist/src/grading/debias-validate.js +4 -4
- package/dist/src/grading/debias-validate.js.map +1 -1
- package/dist/src/grading/diagnostic.d.ts +40 -0
- package/dist/src/grading/diagnostic.d.ts.map +1 -0
- package/dist/src/grading/diagnostic.js +450 -0
- package/dist/src/grading/diagnostic.js.map +1 -0
- package/dist/src/grading/gold-cli.js +2 -2
- package/dist/src/grading/gold-cli.js.map +1 -1
- package/dist/src/grading/index.d.ts +5 -0
- package/dist/src/grading/index.d.ts.map +1 -1
- package/dist/src/grading/judge.d.ts.map +1 -1
- package/dist/src/grading/judge.js +54 -2
- package/dist/src/grading/judge.js.map +1 -1
- package/dist/src/grading/layered-scores.d.ts.map +1 -1
- package/dist/src/grading/layered-scores.js +1 -0
- package/dist/src/grading/layered-scores.js.map +1 -1
- package/dist/src/inputs/eval-config.js +19 -0
- package/dist/src/inputs/eval-config.js.map +1 -1
- package/dist/src/inputs/load-samples.d.ts +22 -2
- package/dist/src/inputs/load-samples.d.ts.map +1 -1
- package/dist/src/inputs/load-samples.js +193 -22
- package/dist/src/inputs/load-samples.js.map +1 -1
- package/dist/src/inputs/skill-loader.d.ts.map +1 -1
- package/dist/src/inputs/skill-loader.js +11 -3
- package/dist/src/inputs/skill-loader.js.map +1 -1
- package/dist/src/observability/experience.d.ts +260 -0
- package/dist/src/observability/experience.d.ts.map +1 -0
- package/dist/src/observability/experience.js +1233 -0
- package/dist/src/observability/experience.js.map +1 -0
- package/dist/src/observability/inbox-view-model.d.ts +27 -0
- package/dist/src/observability/inbox-view-model.d.ts.map +1 -0
- package/dist/src/observability/inbox-view-model.js +135 -0
- package/dist/src/observability/inbox-view-model.js.map +1 -0
- package/dist/src/observability/inbox.d.ts +125 -0
- package/dist/src/observability/inbox.d.ts.map +1 -0
- package/dist/src/observability/inbox.js +741 -0
- package/dist/src/observability/inbox.js.map +1 -0
- package/dist/src/observability/problem-patterns.d.ts +51 -0
- package/dist/src/observability/problem-patterns.d.ts.map +1 -0
- package/dist/src/observability/problem-patterns.js +205 -0
- package/dist/src/observability/problem-patterns.js.map +1 -0
- package/dist/src/observability/review-state.d.ts +54 -0
- package/dist/src/observability/review-state.d.ts.map +1 -0
- package/dist/src/observability/review-state.js +131 -0
- package/dist/src/observability/review-state.js.map +1 -0
- package/dist/src/observability/skill-chain-advisories.d.ts +25 -0
- package/dist/src/observability/skill-chain-advisories.d.ts.map +1 -0
- package/dist/src/observability/skill-chain-advisories.js +69 -0
- package/dist/src/observability/skill-chain-advisories.js.map +1 -0
- package/dist/src/observability/skill-chain.d.ts +61 -0
- package/dist/src/observability/skill-chain.d.ts.map +1 -0
- package/dist/src/observability/skill-chain.js +233 -0
- package/dist/src/observability/skill-chain.js.map +1 -0
- package/dist/src/observability/text-signals.d.ts +7 -0
- package/dist/src/observability/text-signals.d.ts.map +1 -0
- package/dist/src/observability/text-signals.js +22 -0
- package/dist/src/observability/text-signals.js.map +1 -0
- package/dist/src/observability/trace-adapter.d.ts +12 -64
- package/dist/src/observability/trace-adapter.d.ts.map +1 -1
- package/dist/src/observability/trace-adapter.js +9 -355
- package/dist/src/observability/trace-adapter.js.map +1 -1
- package/dist/src/observability/trace-attribution.d.ts +56 -0
- package/dist/src/observability/trace-attribution.d.ts.map +1 -0
- package/dist/src/observability/trace-attribution.js +200 -0
- package/dist/src/observability/trace-attribution.js.map +1 -0
- package/dist/src/observability/trace-segmenter.d.ts +52 -0
- package/dist/src/observability/trace-segmenter.d.ts.map +1 -0
- package/dist/src/observability/trace-segmenter.js +320 -0
- package/dist/src/observability/trace-segmenter.js.map +1 -0
- package/dist/src/observability/trace-source.d.ts +99 -0
- package/dist/src/observability/trace-source.d.ts.map +1 -0
- package/dist/src/observability/trace-source.js +492 -0
- package/dist/src/observability/trace-source.js.map +1 -0
- package/dist/src/renderer/html-renderer.d.ts.map +1 -1
- package/dist/src/renderer/html-renderer.js +324 -218
- package/dist/src/renderer/html-renderer.js.map +1 -1
- package/dist/src/renderer/layout.d.ts.map +1 -1
- package/dist/src/renderer/layout.js +155 -71
- package/dist/src/renderer/layout.js.map +1 -1
- package/dist/src/renderer/observation-inbox-renderer.d.ts +4 -0
- package/dist/src/renderer/observation-inbox-renderer.d.ts.map +1 -0
- package/dist/src/renderer/observation-inbox-renderer.js +5376 -0
- package/dist/src/renderer/observation-inbox-renderer.js.map +1 -0
- package/dist/src/renderer/skill-detail-renderer.d.ts +15 -0
- package/dist/src/renderer/skill-detail-renderer.d.ts.map +1 -0
- package/dist/src/renderer/skill-detail-renderer.js +1234 -0
- package/dist/src/renderer/skill-detail-renderer.js.map +1 -0
- package/dist/src/renderer/skill-list-renderer.d.ts +4 -0
- package/dist/src/renderer/skill-list-renderer.d.ts.map +1 -0
- package/dist/src/renderer/skill-list-renderer.js +327 -0
- package/dist/src/renderer/skill-list-renderer.js.map +1 -0
- package/dist/src/renderer/summary.d.ts +17 -0
- package/dist/src/renderer/summary.d.ts.map +1 -1
- package/dist/src/renderer/summary.js +346 -74
- package/dist/src/renderer/summary.js.map +1 -1
- package/dist/src/renderer/table.d.ts.map +1 -1
- package/dist/src/renderer/table.js +213 -167
- package/dist/src/renderer/table.js.map +1 -1
- package/dist/src/renderer/test-view.d.ts +66 -0
- package/dist/src/renderer/test-view.d.ts.map +1 -0
- package/dist/src/renderer/test-view.js +905 -0
- package/dist/src/renderer/test-view.js.map +1 -0
- package/dist/src/renderer/trends.d.ts.map +1 -1
- package/dist/src/renderer/trends.js +3 -1
- package/dist/src/renderer/trends.js.map +1 -1
- package/dist/src/server/report-server.d.ts +6 -1
- package/dist/src/server/report-server.d.ts.map +1 -1
- package/dist/src/server/report-server.js +182 -6
- package/dist/src/server/report-server.js.map +1 -1
- package/dist/src/server/report-store.d.ts.map +1 -1
- package/dist/src/server/report-store.js +33 -1
- package/dist/src/server/report-store.js.map +1 -1
- package/dist/src/server/skill-index.d.ts +77 -0
- package/dist/src/server/skill-index.d.ts.map +1 -0
- package/dist/src/server/skill-index.js +331 -0
- package/dist/src/server/skill-index.js.map +1 -0
- package/dist/src/server/skill-insights.d.ts +92 -0
- package/dist/src/server/skill-insights.d.ts.map +1 -0
- package/dist/src/server/skill-insights.js +676 -0
- package/dist/src/server/skill-insights.js.map +1 -0
- package/dist/src/shared/hard-rules.d.ts +40 -0
- package/dist/src/shared/hard-rules.d.ts.map +1 -0
- package/dist/src/shared/hard-rules.js +200 -0
- package/dist/src/shared/hard-rules.js.map +1 -0
- package/dist/src/shared/time.d.ts +2 -0
- package/dist/src/shared/time.d.ts.map +1 -0
- package/dist/src/shared/time.js +10 -0
- package/dist/src/shared/time.js.map +1 -0
- package/dist/src/shared/tool-search.d.ts +9 -0
- package/dist/src/shared/tool-search.d.ts.map +1 -0
- package/dist/src/shared/tool-search.js +104 -0
- package/dist/src/shared/tool-search.js.map +1 -0
- package/dist/src/types/eval.d.ts +83 -0
- package/dist/src/types/eval.d.ts.map +1 -1
- package/dist/src/types/executor.d.ts +47 -0
- package/dist/src/types/executor.d.ts.map +1 -1
- package/dist/src/types/judge.d.ts +76 -0
- package/dist/src/types/judge.d.ts.map +1 -1
- package/dist/src/types/judge.js +3 -1
- package/dist/src/types/judge.js.map +1 -1
- package/dist/src/types/report.d.ts +63 -3
- package/dist/src/types/report.d.ts.map +1 -1
- package/dist/src/util/safe-slice.d.ts +23 -0
- package/dist/src/util/safe-slice.d.ts.map +1 -0
- package/dist/src/util/safe-slice.js +33 -0
- package/dist/src/util/safe-slice.js.map +1 -0
- package/package.json +5 -4
|
@@ -1,362 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* cc session JSONL → omk ResultEntry adapter
|
|
2
|
+
* cc session JSONL / agent markdown log → omk ResultEntry adapter.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* 2. 按 session 拆分、按 skill 信号切段(见 docs/skill-health-spec.md §四)
|
|
7
|
-
* 3. 每段输出为一个 ResultEntry, variant key = skill 名
|
|
8
|
-
*
|
|
9
|
-
* skill 归属信号(spec §四):
|
|
10
|
-
* - 信号 1: tool_use name="Skill" 的 input.skill
|
|
11
|
-
* - 信号 2: user message 里的 <command-name>/X</command-name>
|
|
12
|
-
* - 无任何信号 → 'general'(裸 cc 对话,不丢弃)
|
|
13
|
-
*
|
|
14
|
-
* v0.18 不处理:
|
|
15
|
-
* - Skill tool 嵌套调用(扁平切段)
|
|
16
|
-
* - 信号 3 (Read .claude/skills/X/SKILL.md,留 v0.19)
|
|
17
|
-
* - 版本对齐(全部归到 skill 名下)
|
|
18
|
-
*/
|
|
19
|
-
import { readFileSync, readdirSync, statSync } from 'node:fs';
|
|
20
|
-
import { join } from 'node:path';
|
|
21
|
-
// ---------- Load ----------
|
|
22
|
-
/**
|
|
23
|
-
* 加载一个目录(或单个 JSONL 文件)下的所有 cc session。目录递归只一层(cc 的实际布局)。
|
|
24
|
-
*/
|
|
25
|
-
export function loadCcSessions(path) {
|
|
26
|
-
const stat = statSync(path);
|
|
27
|
-
if (stat.isFile()) {
|
|
28
|
-
return [parseCcSessionFile(path)];
|
|
29
|
-
}
|
|
30
|
-
const entries = readdirSync(path)
|
|
31
|
-
.filter((f) => f.endsWith('.jsonl'))
|
|
32
|
-
.map((f) => join(path, f));
|
|
33
|
-
return entries.map(parseCcSessionFile).filter((s) => s !== null);
|
|
34
|
-
}
|
|
35
|
-
function parseCcSessionFile(filePath) {
|
|
36
|
-
const content = readFileSync(filePath, 'utf-8');
|
|
37
|
-
const records = [];
|
|
38
|
-
for (const line of content.split('\n')) {
|
|
39
|
-
const trimmed = line.trim();
|
|
40
|
-
if (!trimmed)
|
|
41
|
-
continue;
|
|
42
|
-
try {
|
|
43
|
-
records.push(JSON.parse(trimmed));
|
|
44
|
-
}
|
|
45
|
-
catch {
|
|
46
|
-
// malformed line → skip. cc 有罕见的截断 record, 不让单行 fail 整个 session
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
const first = records.find((r) => 'sessionId' in r && typeof r.sessionId === 'string');
|
|
50
|
-
const last = [...records].reverse().find((r) => 'timestamp' in r && typeof r.timestamp === 'string');
|
|
51
|
-
return {
|
|
52
|
-
sessionId: first?.sessionId ?? filePath.split('/').pop().replace('.jsonl', ''),
|
|
53
|
-
sourcePath: filePath,
|
|
54
|
-
records,
|
|
55
|
-
cwd: first?.cwd,
|
|
56
|
-
gitBranch: first?.gitBranch,
|
|
57
|
-
startTimestamp: first?.timestamp,
|
|
58
|
-
endTimestamp: last?.timestamp,
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
// ---------- Skill signal detection ----------
|
|
62
|
-
const COMMAND_NAME_RE = /<command-name>\/([^<]+)<\/command-name>/;
|
|
63
|
-
// cc 内置 CLI 命令(不是 skill)。dogfood 数据中这些词频繁以 <command-name> 出现,
|
|
64
|
-
// 必须过滤掉才能得到真实 skill 分布。列表基于实测 + cc 常规命令集。
|
|
65
|
-
const CC_BUILTIN_COMMANDS = new Set([
|
|
66
|
-
'clear', 'exit', 'quit', 'help', 'fast', 'effort', 'model',
|
|
67
|
-
'plugin', 'stats', 'doctor', 'compact', 'cost', 'agents', 'init',
|
|
68
|
-
'config', 'permissions', 'resume', 'continue', 'memory',
|
|
69
|
-
]);
|
|
70
|
-
/**
|
|
71
|
-
* 归一化 skill 名: 去掉 plugin 前缀, 过滤 cc 内置命令。
|
|
72
|
-
* - "impeccable:audit" → "audit"
|
|
73
|
-
* - "pbakaus/impeccable:audit" → "audit"
|
|
74
|
-
* - "clear" / "exit" 等 → null(表示不是 skill)
|
|
4
|
+
* This file is intentionally thin: source parsing, attribution, and segmentation
|
|
5
|
+
* live in sibling modules so studio/report code does not inherit one large adapter.
|
|
75
6
|
*/
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
return null;
|
|
82
|
-
return name;
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* 从 user message 里提取 slash-command skill 名字(信号 2)。
|
|
86
|
-
* 返回 null 表示没命中。
|
|
87
|
-
*/
|
|
88
|
-
function extractCommandSkill(record) {
|
|
89
|
-
const content = record.message.content;
|
|
90
|
-
let raw = null;
|
|
91
|
-
if (typeof content === 'string') {
|
|
92
|
-
const m = COMMAND_NAME_RE.exec(content);
|
|
93
|
-
raw = m ? m[1] : null;
|
|
94
|
-
}
|
|
95
|
-
else {
|
|
96
|
-
for (const part of content) {
|
|
97
|
-
if (part.type === 'text') {
|
|
98
|
-
const m = COMMAND_NAME_RE.exec(part.text);
|
|
99
|
-
if (m) {
|
|
100
|
-
raw = m[1];
|
|
101
|
-
break;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
return raw ? normalizeSkillName(raw) : null;
|
|
107
|
-
}
|
|
108
|
-
/**
|
|
109
|
-
* 从 assistant message 的 tool_use 里提取 Skill tool 调用的 skill 名字(信号 1)。
|
|
110
|
-
* 返回 null 表示没命中。
|
|
111
|
-
*/
|
|
112
|
-
function extractSkillToolUse(record) {
|
|
113
|
-
for (const part of record.message.content) {
|
|
114
|
-
if (part.type === 'tool_use' && part.name === 'Skill') {
|
|
115
|
-
const skill = part.input?.skill;
|
|
116
|
-
if (typeof skill === 'string')
|
|
117
|
-
return normalizeSkillName(skill);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
return null;
|
|
121
|
-
}
|
|
122
|
-
const SKILL_READ_FILE_RE = /\.claude\/skills\/([^/]+)\/SKILL\.md$/;
|
|
123
|
-
/**
|
|
124
|
-
* 从 assistant message 的 Read tool_use 里提取 skill 名字(信号 3, fallback)。
|
|
125
|
-
* 匹配 file_path 形如 ".claude/skills/<name>/SKILL.md" 的模式。
|
|
126
|
-
* 返回 null 表示没命中。
|
|
127
|
-
*/
|
|
128
|
-
function extractSkillReadFile(record) {
|
|
129
|
-
for (const part of record.message.content) {
|
|
130
|
-
if (part.type === 'tool_use' && part.name === 'Read') {
|
|
131
|
-
const filePath = part.input?.file_path;
|
|
132
|
-
if (typeof filePath === 'string') {
|
|
133
|
-
const m = SKILL_READ_FILE_RE.exec(filePath);
|
|
134
|
-
if (m)
|
|
135
|
-
return normalizeSkillName(m[1]);
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
return null;
|
|
140
|
-
}
|
|
141
|
-
// ---------- Segment by skill ----------
|
|
142
|
-
/**
|
|
143
|
-
* 扫描 session records, 按 skill 信号把 tool calls 切成多段。
|
|
144
|
-
* 一个 session 可能产生 1-N 个 SkillSegment。
|
|
145
|
-
*/
|
|
146
|
-
export function segmentBySkill(session) {
|
|
147
|
-
const segments = [];
|
|
148
|
-
let currentSkill = 'general';
|
|
149
|
-
let currentSegment = createEmptySegment(session, currentSkill, 0);
|
|
150
|
-
let segmentIndex = 0;
|
|
151
|
-
// 用 tool_use_id → ToolCallInfo 的映射, 收到 tool_result 时回填 output / success
|
|
152
|
-
const pendingToolUses = new Map();
|
|
153
|
-
const flushCurrent = () => {
|
|
154
|
-
if (currentSegment.turns.length > 0 || currentSegment.toolCalls.length > 0) {
|
|
155
|
-
segments.push(currentSegment);
|
|
156
|
-
return true;
|
|
157
|
-
}
|
|
158
|
-
return false;
|
|
159
|
-
};
|
|
160
|
-
const startNewSegment = (skillName, timestamp) => {
|
|
161
|
-
// 空段被新信号替换时,不推进 segmentIndex(保持整洁的 0-based 编号)
|
|
162
|
-
const wasNonEmpty = flushCurrent();
|
|
163
|
-
if (wasNonEmpty)
|
|
164
|
-
segmentIndex += 1;
|
|
165
|
-
currentSegment = createEmptySegment(session, skillName, segmentIndex, timestamp);
|
|
166
|
-
currentSkill = skillName;
|
|
167
|
-
};
|
|
168
|
-
for (const raw of session.records) {
|
|
169
|
-
// records 是 unknown[], 按 type 字段做 structural type guard
|
|
170
|
-
if (!raw || typeof raw !== 'object' || !('type' in raw))
|
|
171
|
-
continue;
|
|
172
|
-
const rec = raw;
|
|
173
|
-
if (rec.type === 'user') {
|
|
174
|
-
const u = rec;
|
|
175
|
-
// 检测 skill 信号 2 (slash command)
|
|
176
|
-
const cmdSkill = extractCommandSkill(u);
|
|
177
|
-
if (cmdSkill && cmdSkill !== currentSkill) {
|
|
178
|
-
startNewSegment(cmdSkill, u.timestamp);
|
|
179
|
-
}
|
|
180
|
-
// 处理 tool_result(回填之前的 tool_use)
|
|
181
|
-
if (typeof u.message.content !== 'string') {
|
|
182
|
-
for (const part of u.message.content) {
|
|
183
|
-
if (part.type === 'tool_result') {
|
|
184
|
-
const pending = pendingToolUses.get(part.tool_use_id);
|
|
185
|
-
if (pending) {
|
|
186
|
-
pending.toolCall.output = part.content;
|
|
187
|
-
pending.toolCall.success = part.is_error !== true;
|
|
188
|
-
if (part.is_error === true) {
|
|
189
|
-
pending.segmentRef.metrics.numToolFailures += 1;
|
|
190
|
-
}
|
|
191
|
-
pendingToolUses.delete(part.tool_use_id);
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
// user text 合并到 tool turn(简化处理, 不强区分角色)
|
|
197
|
-
const textContent = extractUserText(u);
|
|
198
|
-
if (textContent) {
|
|
199
|
-
currentSegment.turns.push({ role: 'tool', content: textContent });
|
|
200
|
-
currentSegment.metrics.numTurns += 1;
|
|
201
|
-
}
|
|
202
|
-
updateSegmentTimestamp(currentSegment, u.timestamp);
|
|
203
|
-
continue;
|
|
204
|
-
}
|
|
205
|
-
if (rec.type === 'assistant') {
|
|
206
|
-
const a = rec;
|
|
207
|
-
// 检测 skill 信号 1 (Skill tool_use); 信号 3 (Read SKILL.md) 作 fallback,
|
|
208
|
-
// 仅在当前段仍是 'general'(未被信号 1/2 命中过)时触发,避免压过更强信号。
|
|
209
|
-
const skillTool = extractSkillToolUse(a);
|
|
210
|
-
if (skillTool && skillTool !== currentSkill) {
|
|
211
|
-
startNewSegment(skillTool, a.timestamp);
|
|
212
|
-
}
|
|
213
|
-
else if (!skillTool && currentSkill === 'general') {
|
|
214
|
-
const readSkill = extractSkillReadFile(a);
|
|
215
|
-
if (readSkill) {
|
|
216
|
-
startNewSegment(readSkill, a.timestamp);
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
// 提取 tool_use → ToolCallInfo(success 先标 true, 等 tool_result 回填)
|
|
220
|
-
const toolCalls = [];
|
|
221
|
-
let assistantText = '';
|
|
222
|
-
for (const part of a.message.content) {
|
|
223
|
-
if (part.type === 'text' && part.text)
|
|
224
|
-
assistantText += part.text;
|
|
225
|
-
if (part.type === 'tool_use' && part.id && part.name) {
|
|
226
|
-
const tc = {
|
|
227
|
-
tool: part.name,
|
|
228
|
-
input: part.input ?? {},
|
|
229
|
-
output: '',
|
|
230
|
-
success: true,
|
|
231
|
-
};
|
|
232
|
-
toolCalls.push(tc);
|
|
233
|
-
pendingToolUses.set(part.id, { toolCall: tc, segmentRef: currentSegment });
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
if (toolCalls.length > 0 || assistantText) {
|
|
237
|
-
currentSegment.turns.push({
|
|
238
|
-
role: 'assistant',
|
|
239
|
-
content: assistantText,
|
|
240
|
-
toolCalls: toolCalls.length > 0 ? toolCalls : undefined,
|
|
241
|
-
});
|
|
242
|
-
currentSegment.metrics.numTurns += 1;
|
|
243
|
-
currentSegment.toolCalls.push(...toolCalls);
|
|
244
|
-
currentSegment.metrics.numToolCalls += toolCalls.length;
|
|
245
|
-
}
|
|
246
|
-
// 累加 token usage
|
|
247
|
-
const usage = a.message.usage;
|
|
248
|
-
if (usage) {
|
|
249
|
-
currentSegment.metrics.inputTokens += usage.input_tokens ?? 0;
|
|
250
|
-
currentSegment.metrics.outputTokens += usage.output_tokens ?? 0;
|
|
251
|
-
currentSegment.metrics.cacheReadTokens += usage.cache_read_input_tokens ?? 0;
|
|
252
|
-
currentSegment.metrics.cacheCreationTokens += usage.cache_creation_input_tokens ?? 0;
|
|
253
|
-
}
|
|
254
|
-
updateSegmentTimestamp(currentSegment, a.timestamp);
|
|
255
|
-
continue;
|
|
256
|
-
}
|
|
257
|
-
// 其他 type(permission-mode / file-history-snapshot) 直接 skip
|
|
258
|
-
}
|
|
259
|
-
flushCurrent();
|
|
260
|
-
// 孤儿 tool_use(没对应 tool_result 的)保持 success=true, 但标记为未闭合
|
|
261
|
-
return segments;
|
|
262
|
-
}
|
|
263
|
-
function createEmptySegment(session, skillName, index, timestamp) {
|
|
264
|
-
const ts = timestamp ?? session.startTimestamp ?? new Date().toISOString();
|
|
265
|
-
return {
|
|
266
|
-
skillName,
|
|
267
|
-
sessionId: session.sessionId,
|
|
268
|
-
segmentIndex: index,
|
|
269
|
-
startTimestamp: ts,
|
|
270
|
-
endTimestamp: ts,
|
|
271
|
-
cwd: session.cwd,
|
|
272
|
-
turns: [],
|
|
273
|
-
toolCalls: [],
|
|
274
|
-
metrics: {
|
|
275
|
-
durationMs: 0,
|
|
276
|
-
inputTokens: 0,
|
|
277
|
-
outputTokens: 0,
|
|
278
|
-
cacheReadTokens: 0,
|
|
279
|
-
cacheCreationTokens: 0,
|
|
280
|
-
numTurns: 0,
|
|
281
|
-
numToolCalls: 0,
|
|
282
|
-
numToolFailures: 0,
|
|
283
|
-
},
|
|
284
|
-
};
|
|
285
|
-
}
|
|
286
|
-
function updateSegmentTimestamp(seg, timestamp) {
|
|
287
|
-
if (!timestamp)
|
|
288
|
-
return;
|
|
289
|
-
if (!seg.endTimestamp || timestamp > seg.endTimestamp)
|
|
290
|
-
seg.endTimestamp = timestamp;
|
|
291
|
-
// 重算 durationMs
|
|
292
|
-
try {
|
|
293
|
-
const start = new Date(seg.startTimestamp).getTime();
|
|
294
|
-
const end = new Date(seg.endTimestamp).getTime();
|
|
295
|
-
if (!Number.isNaN(start) && !Number.isNaN(end))
|
|
296
|
-
seg.metrics.durationMs = Math.max(0, end - start);
|
|
297
|
-
}
|
|
298
|
-
catch { /* skip */ }
|
|
299
|
-
}
|
|
300
|
-
function extractUserText(record) {
|
|
301
|
-
const content = record.message.content;
|
|
302
|
-
if (typeof content === 'string')
|
|
303
|
-
return content;
|
|
304
|
-
const parts = [];
|
|
305
|
-
for (const p of content) {
|
|
306
|
-
if (p.type === 'text')
|
|
307
|
-
parts.push(p.text);
|
|
308
|
-
if (p.type === 'tool_result' && typeof p.content === 'string')
|
|
309
|
-
parts.push(p.content);
|
|
310
|
-
}
|
|
311
|
-
return parts.join('\n');
|
|
312
|
-
}
|
|
313
|
-
// ---------- Segment → ResultEntry ----------
|
|
314
|
-
/**
|
|
315
|
-
* SkillSegment[] → ResultEntry[] (omk 内部分析路径的标准输入)。
|
|
316
|
-
*
|
|
317
|
-
* 映射规则(详见 docs/skill-health-spec.md):
|
|
318
|
-
* - 每 segment 一个 ResultEntry
|
|
319
|
-
* - sample_id = `${sessionId}:${segmentIndex}`
|
|
320
|
-
* - variant key = skill 名(复用 omk 的 variant 维度作为 skill 分组维度)
|
|
321
|
-
*/
|
|
322
|
-
export function segmentsToResultEntries(segments) {
|
|
323
|
-
return segments.map((seg) => ({
|
|
324
|
-
sample_id: `${seg.sessionId}:${seg.segmentIndex}`,
|
|
325
|
-
variants: {
|
|
326
|
-
[seg.skillName]: buildVariantResult(seg),
|
|
327
|
-
},
|
|
328
|
-
}));
|
|
329
|
-
}
|
|
330
|
-
function buildVariantResult(seg) {
|
|
331
|
-
const totalTokens = seg.metrics.inputTokens + seg.metrics.outputTokens;
|
|
332
|
-
const toolSuccessRate = seg.metrics.numToolCalls > 0
|
|
333
|
-
? (seg.metrics.numToolCalls - seg.metrics.numToolFailures) / seg.metrics.numToolCalls
|
|
334
|
-
: 1;
|
|
335
|
-
return {
|
|
336
|
-
ok: true,
|
|
337
|
-
durationMs: seg.metrics.durationMs,
|
|
338
|
-
durationApiMs: seg.metrics.durationMs,
|
|
339
|
-
inputTokens: seg.metrics.inputTokens,
|
|
340
|
-
outputTokens: seg.metrics.outputTokens,
|
|
341
|
-
totalTokens,
|
|
342
|
-
cacheReadTokens: seg.metrics.cacheReadTokens,
|
|
343
|
-
cacheCreationTokens: seg.metrics.cacheCreationTokens,
|
|
344
|
-
execCostUSD: 0,
|
|
345
|
-
judgeCostUSD: 0,
|
|
346
|
-
costUSD: 0,
|
|
347
|
-
numTurns: seg.metrics.numTurns,
|
|
348
|
-
numToolCalls: seg.metrics.numToolCalls,
|
|
349
|
-
numToolFailures: seg.metrics.numToolFailures,
|
|
350
|
-
toolSuccessRate,
|
|
351
|
-
toolNames: Array.from(new Set(seg.toolCalls.map((tc) => tc.tool))),
|
|
352
|
-
outputPreview: null,
|
|
353
|
-
turns: seg.turns,
|
|
354
|
-
toolCalls: seg.toolCalls,
|
|
355
|
-
};
|
|
356
|
-
}
|
|
357
|
-
// ---------- 顶层便捷入口 ----------
|
|
7
|
+
import { loadCcSessions } from './trace-source.js';
|
|
8
|
+
import { segmentBySkill, segmentsToResultEntries } from './trace-segmenter.js';
|
|
9
|
+
export { loadCcSessions } from './trace-source.js';
|
|
10
|
+
export { extractAttributionSkill, extractAttributionSkillRef, extractCommandSkill, extractCommandSkillRef, extractCommandEnvelopeText, extractMarkdownLogSkill, extractSkillReadFileRef, extractSkillReadFile, extractSkillToolUse, extractSkillToolUseRef, normalizeSkillName, parseSkillRef, stripCommandEnvelopeText, } from './trace-attribution.js';
|
|
11
|
+
export { segmentBySkill, segmentsToResultEntries } from './trace-segmenter.js';
|
|
358
12
|
/**
|
|
359
|
-
*
|
|
13
|
+
* One-stop conversion: trace path → ResultEntry[].
|
|
360
14
|
*/
|
|
361
15
|
export function ccTracesToResultEntries(path) {
|
|
362
16
|
const sessions = loadCcSessions(path);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trace-adapter.js","sourceRoot":"","sources":["../../../src/observability/trace-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC9D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAmGjC,6BAA6B;AAE7B;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC5B,IAAI,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;QAClB,OAAO,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC;IACpC,CAAC;IACD,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC;SAC9B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;SACnC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC7B,OAAO,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAkB,EAAE,CAAC,CAAC,KAAK,IAAI,CAAgB,CAAC;AAClG,CAAC;AAED,SAAS,kBAAkB,CAAC,QAAgB;IAC1C,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAChD,MAAM,OAAO,GAAe,EAAE,CAAC;IAC/B,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACvC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,OAAO;YAAE,SAAS;QACvB,IAAI,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAa,CAAC,CAAC;QAChD,CAAC;QAAC,MAAM,CAAC;YACP,gEAAgE;QAClE,CAAC;IACH,CAAC;IACD,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,IAAI,CAAC,IAAI,OAAO,CAAC,CAAC,SAAS,KAAK,QAAQ,CAExE,CAAC;IACd,MAAM,IAAI,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,IAAI,CAAC,IAAI,OAAO,CAAC,CAAC,SAAS,KAAK,QAAQ,CAEtF,CAAC;IACd,OAAO;QACL,SAAS,EAAE,KAAK,EAAE,SAAS,IAAI,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC;QAC/E,UAAU,EAAE,QAAQ;QACpB,OAAO;QACP,GAAG,EAAE,KAAK,EAAE,GAAG;QACf,SAAS,EAAE,KAAK,EAAE,SAAS;QAC3B,cAAc,EAAE,KAAK,EAAE,SAAS;QAChC,YAAY,EAAE,IAAI,EAAE,SAAS;KAC9B,CAAC;AACJ,CAAC;AAED,+CAA+C;AAE/C,MAAM,eAAe,GAAG,yCAAyC,CAAC;AAElE,8DAA8D;AAC9D,0CAA0C;AAC1C,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC;IAClC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO;IAC1D,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;IAChE,QAAQ,EAAE,aAAa,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ;CACxD,CAAC,CAAC;AAEH;;;;;GAKG;AACH,SAAS,kBAAkB,CAAC,GAAW;IACrC,uEAAuE;IACvE,MAAM,QAAQ,GAAG,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACtC,MAAM,IAAI,GAAG,QAAQ,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IAC3D,IAAI,mBAAmB,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/C,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,SAAS,mBAAmB,CAAC,MAAoB;IAC/C,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC;IACvC,IAAI,GAAG,GAAkB,IAAI,CAAC;IAC9B,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAChC,MAAM,CAAC,GAAG,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACxC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACxB,CAAC;SAAM,CAAC;QACN,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;YAC3B,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBACzB,MAAM,CAAC,GAAG,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC1C,IAAI,CAAC,EAAE,CAAC;oBAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;oBAAC,MAAM;gBAAC,CAAC;YAC/B,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC,CAAC,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAC9C,CAAC;AAED;;;GAGG;AACH,SAAS,mBAAmB,CAAC,MAAyB;IACpD,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QAC1C,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YACtD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC;YAChC,IAAI,OAAO,KAAK,KAAK,QAAQ;gBAAE,OAAO,kBAAkB,CAAC,KAAK,CAAC,CAAC;QAClE,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,kBAAkB,GAAG,uCAAuC,CAAC;AAEnE;;;;GAIG;AACH,SAAS,oBAAoB,CAAC,MAAyB;IACrD,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QAC1C,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACrD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,EAAE,SAAS,CAAC;YACvC,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;gBACjC,MAAM,CAAC,GAAG,kBAAkB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAC5C,IAAI,CAAC;oBAAE,OAAO,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACzC,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,yCAAyC;AAEzC;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,OAAkB;IAC/C,MAAM,QAAQ,GAAmB,EAAE,CAAC;IACpC,IAAI,YAAY,GAAG,SAAS,CAAC;IAC7B,IAAI,cAAc,GAAG,kBAAkB,CAAC,OAAO,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC;IAClE,IAAI,YAAY,GAAG,CAAC,CAAC;IAErB,wEAAwE;IACxE,MAAM,eAAe,GAAG,IAAI,GAAG,EAAgE,CAAC;IAEhG,MAAM,YAAY,GAAG,GAAY,EAAE;QACjC,IAAI,cAAc,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,cAAc,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3E,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAC9B,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;IAEF,MAAM,eAAe,GAAG,CAAC,SAAiB,EAAE,SAAkB,EAAQ,EAAE;QACtE,+CAA+C;QAC/C,MAAM,WAAW,GAAG,YAAY,EAAE,CAAC;QACnC,IAAI,WAAW;YAAE,YAAY,IAAI,CAAC,CAAC;QACnC,cAAc,GAAG,kBAAkB,CAAC,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC;QACjF,YAAY,GAAG,SAAS,CAAC;IAC3B,CAAC,CAAC;IAEF,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QAClC,wDAAwD;QACxD,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,IAAI,GAAG,CAAC;YAAE,SAAS;QAClE,MAAM,GAAG,GAAG,GAAuB,CAAC;QACpC,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACxB,MAAM,CAAC,GAAG,GAAmB,CAAC;YAC9B,gCAAgC;YAChC,MAAM,QAAQ,GAAG,mBAAmB,CAAC,CAAC,CAAC,CAAC;YACxC,IAAI,QAAQ,IAAI,QAAQ,KAAK,YAAY,EAAE,CAAC;gBAC1C,eAAe,CAAC,QAAQ,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC;YACzC,CAAC;YACD,iCAAiC;YACjC,IAAI,OAAO,CAAC,CAAC,OAAO,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;gBAC1C,KAAK,MAAM,IAAI,IAAI,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;oBACrC,IAAI,IAAI,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;wBAChC,MAAM,OAAO,GAAG,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;wBACtD,IAAI,OAAO,EAAE,CAAC;4BACZ,OAAO,CAAC,QAAQ,CAAC,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC;4BACvC,OAAO,CAAC,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC;4BAClD,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;gCAC3B,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,eAAe,IAAI,CAAC,CAAC;4BAClD,CAAC;4BACD,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;wBAC3C,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;YACD,wCAAwC;YACxC,MAAM,WAAW,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC;YACvC,IAAI,WAAW,EAAE,CAAC;gBAChB,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;gBAClE,cAAc,CAAC,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAC;YACvC,CAAC;YACD,sBAAsB,CAAC,cAAc,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC;YACpD,SAAS;QACX,CAAC;QACD,IAAI,GAAG,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YAC7B,MAAM,CAAC,GAAG,GAAwB,CAAC;YACnC,mEAAmE;YACnE,+CAA+C;YAC/C,MAAM,SAAS,GAAG,mBAAmB,CAAC,CAAC,CAAC,CAAC;YACzC,IAAI,SAAS,IAAI,SAAS,KAAK,YAAY,EAAE,CAAC;gBAC5C,eAAe,CAAC,SAAS,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC;YAC1C,CAAC;iBAAM,IAAI,CAAC,SAAS,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;gBACpD,MAAM,SAAS,GAAG,oBAAoB,CAAC,CAAC,CAAC,CAAC;gBAC1C,IAAI,SAAS,EAAE,CAAC;oBACd,eAAe,CAAC,SAAS,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC;gBAC1C,CAAC;YACH,CAAC;YACD,gEAAgE;YAChE,MAAM,SAAS,GAAmB,EAAE,CAAC;YACrC,IAAI,aAAa,GAAG,EAAE,CAAC;YACvB,KAAK,MAAM,IAAI,IAAI,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;gBACrC,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,IAAI;oBAAE,aAAa,IAAI,IAAI,CAAC,IAAI,CAAC;gBAClE,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,IAAI,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;oBACrD,MAAM,EAAE,GAAiB;wBACvB,IAAI,EAAE,IAAI,CAAC,IAAI;wBACf,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,EAAE;wBACvB,MAAM,EAAE,EAAE;wBACV,OAAO,EAAE,IAAI;qBACd,CAAC;oBACF,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;oBACnB,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,UAAU,EAAE,cAAc,EAAE,CAAC,CAAC;gBAC7E,CAAC;YACH,CAAC;YACD,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,aAAa,EAAE,CAAC;gBAC1C,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC;oBACxB,IAAI,EAAE,WAAW;oBACjB,OAAO,EAAE,aAAa;oBACtB,SAAS,EAAE,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;iBACxD,CAAC,CAAC;gBACH,cAAc,CAAC,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAC;gBACrC,cAAc,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,CAAC;gBAC5C,cAAc,CAAC,OAAO,CAAC,YAAY,IAAI,SAAS,CAAC,MAAM,CAAC;YAC1D,CAAC;YACD,iBAAiB;YACjB,MAAM,KAAK,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC;YAC9B,IAAI,KAAK,EAAE,CAAC;gBACV,cAAc,CAAC,OAAO,CAAC,WAAW,IAAI,KAAK,CAAC,YAAY,IAAI,CAAC,CAAC;gBAC9D,cAAc,CAAC,OAAO,CAAC,YAAY,IAAI,KAAK,CAAC,aAAa,IAAI,CAAC,CAAC;gBAChE,cAAc,CAAC,OAAO,CAAC,eAAe,IAAI,KAAK,CAAC,uBAAuB,IAAI,CAAC,CAAC;gBAC7E,cAAc,CAAC,OAAO,CAAC,mBAAmB,IAAI,KAAK,CAAC,2BAA2B,IAAI,CAAC,CAAC;YACvF,CAAC;YACD,sBAAsB,CAAC,cAAc,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC;YACpD,SAAS;QACX,CAAC;QACD,2DAA2D;IAC7D,CAAC;IAED,YAAY,EAAE,CAAC;IACf,yDAAyD;IACzD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,kBAAkB,CAAC,OAAkB,EAAE,SAAiB,EAAE,KAAa,EAAE,SAAkB;IAClG,MAAM,EAAE,GAAG,SAAS,IAAI,OAAO,CAAC,cAAc,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC3E,OAAO;QACL,SAAS;QACT,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,YAAY,EAAE,KAAK;QACnB,cAAc,EAAE,EAAE;QAClB,YAAY,EAAE,EAAE;QAChB,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,KAAK,EAAE,EAAE;QACT,SAAS,EAAE,EAAE;QACb,OAAO,EAAE;YACP,UAAU,EAAE,CAAC;YACb,WAAW,EAAE,CAAC;YACd,YAAY,EAAE,CAAC;YACf,eAAe,EAAE,CAAC;YAClB,mBAAmB,EAAE,CAAC;YACtB,QAAQ,EAAE,CAAC;YACX,YAAY,EAAE,CAAC;YACf,eAAe,EAAE,CAAC;SACnB;KACF,CAAC;AACJ,CAAC;AAED,SAAS,sBAAsB,CAAC,GAAiB,EAAE,SAAkB;IACnE,IAAI,CAAC,SAAS;QAAE,OAAO;IACvB,IAAI,CAAC,GAAG,CAAC,YAAY,IAAI,SAAS,GAAG,GAAG,CAAC,YAAY;QAAE,GAAG,CAAC,YAAY,GAAG,SAAS,CAAC;IACpF,gBAAgB;IAChB,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,OAAO,EAAE,CAAC;QACrD,MAAM,GAAG,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE,CAAC;QACjD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC;YAAE,GAAG,CAAC,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,KAAK,CAAC,CAAC;IACpG,CAAC;IAAC,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC;AACxB,CAAC;AAED,SAAS,eAAe,CAAC,MAAoB;IAC3C,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC;IACvC,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,OAAO,CAAC;IAChD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM;YAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC1C,IAAI,CAAC,CAAC,IAAI,KAAK,aAAa,IAAI,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ;YAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IACvF,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,8CAA8C;AAE9C;;;;;;;GAOG;AACH,MAAM,UAAU,uBAAuB,CAAC,QAAwB;IAC9D,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,EAAe,EAAE,CAAC,CAAC;QACzC,SAAS,EAAE,GAAG,GAAG,CAAC,SAAS,IAAI,GAAG,CAAC,YAAY,EAAE;QACjD,QAAQ,EAAE;YACR,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,kBAAkB,CAAC,GAAG,CAAC;SACzC;KACF,CAAC,CAAC,CAAC;AACN,CAAC;AAED,SAAS,kBAAkB,CAAC,GAAiB;IAC3C,MAAM,WAAW,GAAG,GAAG,CAAC,OAAO,CAAC,WAAW,GAAG,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC;IACvE,MAAM,eAAe,GAAG,GAAG,CAAC,OAAO,CAAC,YAAY,GAAG,CAAC;QAClD,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,YAAY,GAAG,GAAG,CAAC,OAAO,CAAC,eAAe,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,YAAY;QACrF,CAAC,CAAC,CAAC,CAAC;IACN,OAAO;QACL,EAAE,EAAE,IAAI;QACR,UAAU,EAAE,GAAG,CAAC,OAAO,CAAC,UAAU;QAClC,aAAa,EAAE,GAAG,CAAC,OAAO,CAAC,UAAU;QACrC,WAAW,EAAE,GAAG,CAAC,OAAO,CAAC,WAAW;QACpC,YAAY,EAAE,GAAG,CAAC,OAAO,CAAC,YAAY;QACtC,WAAW;QACX,eAAe,EAAE,GAAG,CAAC,OAAO,CAAC,eAAe;QAC5C,mBAAmB,EAAE,GAAG,CAAC,OAAO,CAAC,mBAAmB;QACpD,WAAW,EAAE,CAAC;QACd,YAAY,EAAE,CAAC;QACf,OAAO,EAAE,CAAC;QACV,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,QAAQ;QAC9B,YAAY,EAAE,GAAG,CAAC,OAAO,CAAC,YAAY;QACtC,eAAe,EAAE,GAAG,CAAC,OAAO,CAAC,eAAe;QAC5C,eAAe;QACf,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;QAClE,aAAa,EAAE,IAAI;QACnB,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,SAAS,EAAE,GAAG,CAAC,SAAS;KACzB,CAAC;AACJ,CAAC;AAED,+BAA+B;AAE/B;;GAEG;AACH,MAAM,UAAU,uBAAuB,CAAC,IAAY;IAClD,MAAM,QAAQ,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IAClD,MAAM,OAAO,GAAG,uBAAuB,CAAC,QAAQ,CAAC,CAAC;IAClD,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;AACzC,CAAC"}
|
|
1
|
+
{"version":3,"file":"trace-adapter.js","sourceRoot":"","sources":["../../../src/observability/trace-adapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,cAAc,EAAkB,MAAM,mBAAmB,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,uBAAuB,EAAqB,MAAM,sBAAsB,CAAC;AAWlG,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EACL,uBAAuB,EACvB,0BAA0B,EAC1B,mBAAmB,EACnB,sBAAsB,EACtB,0BAA0B,EAC1B,uBAAuB,EACvB,uBAAuB,EACvB,oBAAoB,EACpB,mBAAmB,EACnB,sBAAsB,EACtB,kBAAkB,EAClB,aAAa,EACb,wBAAwB,GACzB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,cAAc,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAE/E;;GAEG;AACH,MAAM,UAAU,uBAAuB,CAAC,IAAY;IAClD,MAAM,QAAQ,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IAClD,MAAM,OAAO,GAAG,uBAAuB,CAAC,QAAQ,CAAC,CAAC;IAClD,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;AACzC,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/** Skill attribution rules for trace records. */
|
|
2
|
+
import type { CcAssistantRecord, CcUserRecord } from './trace-source.js';
|
|
3
|
+
export interface SkillRef {
|
|
4
|
+
skillName: string;
|
|
5
|
+
rawSkillRef: string;
|
|
6
|
+
pluginName?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function extractMarkdownLogSkill(text: string): string | null;
|
|
9
|
+
/**
|
|
10
|
+
* 归一化 skill 名: 去掉 plugin 前缀, 过滤 cc 内置命令。
|
|
11
|
+
* - "impeccable:audit" → "audit"
|
|
12
|
+
* - "pbakaus/impeccable:audit" → "audit"
|
|
13
|
+
* - "clear" / "exit" 等 → null(表示不是 skill)
|
|
14
|
+
*/
|
|
15
|
+
export declare function normalizeSkillName(raw: string): string | null;
|
|
16
|
+
export declare function parseSkillRef(raw: string): SkillRef | null;
|
|
17
|
+
export declare function stripCommandEnvelopeText(text: string): string;
|
|
18
|
+
export declare function extractCommandEnvelopeText(text: string): string | null;
|
|
19
|
+
/**
|
|
20
|
+
* 从 user message 里提取 slash-command skill 名字(信号 2)。
|
|
21
|
+
* 返回 null 表示没命中。
|
|
22
|
+
*/
|
|
23
|
+
export declare function extractCommandSkill(record: CcUserRecord): string | null;
|
|
24
|
+
export declare function extractCommandSkillRef(record: CcUserRecord): SkillRef | null;
|
|
25
|
+
/**
|
|
26
|
+
* 从 OpenClaw / AIMA user message 里提取 aima-cmd skill 名字(信号 4)。
|
|
27
|
+
*
|
|
28
|
+
* 注意: 真实 OpenClaw 数据里 name 可能是业务动作展示名, 例如 "生成PRD" / "生成Demo",
|
|
29
|
+
* 这不是稳定 skill id。只有 name 本身像 "prd-create" 这种 slug 时才用于 skill 归因;
|
|
30
|
+
* 中文动作名继续保留在 sourceMetadata.aimaCommands 里, 不切 skill。
|
|
31
|
+
*/
|
|
32
|
+
export declare function extractAimaCmdSkillRef(record: CcUserRecord): SkillRef | null;
|
|
33
|
+
/**
|
|
34
|
+
* 从 assistant message 的 tool_use 里提取 Skill tool 调用的 skill 名字(信号 1)。
|
|
35
|
+
* 返回 null 表示没命中。
|
|
36
|
+
*/
|
|
37
|
+
export declare function extractSkillToolUse(record: CcAssistantRecord): string | null;
|
|
38
|
+
export declare function extractSkillToolUseRef(record: CcAssistantRecord): SkillRef | null;
|
|
39
|
+
export declare function extractAttributionSkill(record: CcAssistantRecord): string | null;
|
|
40
|
+
export declare function extractAttributionSkillRef(record: CcAssistantRecord): SkillRef | null;
|
|
41
|
+
/**
|
|
42
|
+
* 从 assistant message 的 Read tool_use 里提取 skill 名字(信号 3, fallback)。
|
|
43
|
+
* 匹配 file_path 形如 ".claude/skills/<name>/SKILL.md"
|
|
44
|
+
* 或 ".openclaw/workspace/skills/<name>/SKILL.md" 的模式。
|
|
45
|
+
* 返回 null 表示没命中。
|
|
46
|
+
*/
|
|
47
|
+
export declare function extractSkillReadFile(record: CcAssistantRecord): string | null;
|
|
48
|
+
export declare function extractSkillReadFileRef(record: CcAssistantRecord): SkillRef | null;
|
|
49
|
+
/**
|
|
50
|
+
* 从 OpenClaw cron/user 文本或 Bash/exec tool command 里提取 skill 脚本路径。
|
|
51
|
+
*
|
|
52
|
+
* cron 型 OpenClaw session 通常没有 <aima-cmd> 或 Skill tool_use,
|
|
53
|
+
* 只会直接执行 ~/.openclaw/workspace-main/skills/<skill>/scripts/*.sh。
|
|
54
|
+
*/
|
|
55
|
+
export declare function extractSkillScriptCommandRef(record: CcUserRecord | CcAssistantRecord): SkillRef | null;
|
|
56
|
+
//# sourceMappingURL=trace-attribution.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trace-attribution.d.ts","sourceRoot":"","sources":["../../../src/observability/trace-attribution.ts"],"names":[],"mappings":"AAAA,iDAAiD;AAEjD,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAIzE,MAAM,WAAW,QAAQ;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAenE;AAcD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAE7D;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAa1D;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGtE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,GAAG,IAAI,CAEvE;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,YAAY,GAAG,QAAQ,GAAG,IAAI,CAe5E;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,YAAY,GAAG,QAAQ,GAAG,IAAI,CAe5E;AAOD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,GAAG,IAAI,CAE5E;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,iBAAiB,GAAG,QAAQ,GAAG,IAAI,CASjF;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,GAAG,IAAI,CAEhF;AAED,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,iBAAiB,GAAG,QAAQ,GAAG,IAAI,CAErF;AAMD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,GAAG,IAAI,CAE7E;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,iBAAiB,GAAG,QAAQ,GAAG,IAAI,CAYlF;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,YAAY,GAAG,iBAAiB,GAAG,QAAQ,GAAG,IAAI,CAoBtG"}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
/** Skill attribution rules for trace records. */
|
|
2
|
+
export function extractMarkdownLogSkill(text) {
|
|
3
|
+
const patterns = [
|
|
4
|
+
/\b(?:prefer|use|call|invoke)\s+`?([a-zA-Z0-9][\w.-]*)`?\s+skill\b/i,
|
|
5
|
+
/优先调用\s+`?([a-zA-Z0-9][\w.-]*)`?\s+skill/i,
|
|
6
|
+
/调用\s+`?([a-zA-Z0-9][\w.-]*)`?\s+skill/i,
|
|
7
|
+
/使用\s+`?([a-zA-Z0-9][\w.-]*)`?\s+skill/i,
|
|
8
|
+
/`([a-zA-Z0-9][\w.-]*)`\s+skill/i,
|
|
9
|
+
/\b([a-zA-Z0-9][\w.-]*-[\w.-]*)\s+skill\b/i,
|
|
10
|
+
];
|
|
11
|
+
for (const pattern of patterns) {
|
|
12
|
+
const match = text.match(pattern);
|
|
13
|
+
const normalized = match?.[1] ? normalizeSkillName(match[1]) : null;
|
|
14
|
+
if (normalized)
|
|
15
|
+
return normalized;
|
|
16
|
+
}
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
const COMMAND_NAME_RE = /<command-name>\/([^<]+)<\/command-name>/;
|
|
20
|
+
const AIMA_CMD_RE = /<aima-cmd\b[^>]*\bname=["']([^"']+)["'][^>]*>/;
|
|
21
|
+
const COMMAND_ENVELOPE_RE = /<command-(?:name|message)>[\s\S]*?<\/command-(?:name|message)>/g;
|
|
22
|
+
// cc 内置 CLI 命令(不是 skill)。dogfood 数据中这些词频繁以 <command-name> 出现,
|
|
23
|
+
// 必须过滤掉才能得到真实 skill 分布。列表基于实测 + cc 常规命令集。
|
|
24
|
+
const CC_BUILTIN_COMMANDS = new Set([
|
|
25
|
+
'clear', 'exit', 'quit', 'help', 'fast', 'effort', 'model',
|
|
26
|
+
'plugin', 'stats', 'doctor', 'compact', 'cost', 'agents', 'init',
|
|
27
|
+
'config', 'permissions', 'resume', 'continue', 'memory',
|
|
28
|
+
]);
|
|
29
|
+
/**
|
|
30
|
+
* 归一化 skill 名: 去掉 plugin 前缀, 过滤 cc 内置命令。
|
|
31
|
+
* - "impeccable:audit" → "audit"
|
|
32
|
+
* - "pbakaus/impeccable:audit" → "audit"
|
|
33
|
+
* - "clear" / "exit" 等 → null(表示不是 skill)
|
|
34
|
+
*/
|
|
35
|
+
export function normalizeSkillName(raw) {
|
|
36
|
+
return parseSkillRef(raw)?.skillName ?? null;
|
|
37
|
+
}
|
|
38
|
+
export function parseSkillRef(raw) {
|
|
39
|
+
const trimmed = raw.trim();
|
|
40
|
+
if (!trimmed)
|
|
41
|
+
return null;
|
|
42
|
+
// plugin-prefixed: pbakaus/impeccable:audit / impeccable:audit → 取最后一段
|
|
43
|
+
const colonIdx = trimmed.lastIndexOf(':');
|
|
44
|
+
const name = colonIdx >= 0 ? trimmed.slice(colonIdx + 1) : trimmed;
|
|
45
|
+
if (CC_BUILTIN_COMMANDS.has(name))
|
|
46
|
+
return null;
|
|
47
|
+
const pluginName = colonIdx >= 0 ? trimmed.slice(0, colonIdx) : undefined;
|
|
48
|
+
return {
|
|
49
|
+
skillName: name,
|
|
50
|
+
rawSkillRef: trimmed,
|
|
51
|
+
pluginName: pluginName || undefined,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
export function stripCommandEnvelopeText(text) {
|
|
55
|
+
return text.replace(COMMAND_ENVELOPE_RE, '').replace(/\n{3,}/g, '\n\n').trim();
|
|
56
|
+
}
|
|
57
|
+
export function extractCommandEnvelopeText(text) {
|
|
58
|
+
const matches = text.match(COMMAND_ENVELOPE_RE);
|
|
59
|
+
return matches?.join('\n') ?? null;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* 从 user message 里提取 slash-command skill 名字(信号 2)。
|
|
63
|
+
* 返回 null 表示没命中。
|
|
64
|
+
*/
|
|
65
|
+
export function extractCommandSkill(record) {
|
|
66
|
+
return extractCommandSkillRef(record)?.skillName ?? null;
|
|
67
|
+
}
|
|
68
|
+
export function extractCommandSkillRef(record) {
|
|
69
|
+
const content = record.message.content;
|
|
70
|
+
let raw = null;
|
|
71
|
+
if (typeof content === 'string') {
|
|
72
|
+
const m = COMMAND_NAME_RE.exec(content);
|
|
73
|
+
raw = m ? m[1] : null;
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
for (const part of content) {
|
|
77
|
+
if (part.type === 'text') {
|
|
78
|
+
const m = COMMAND_NAME_RE.exec(part.text);
|
|
79
|
+
if (m) {
|
|
80
|
+
raw = m[1];
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return raw ? parseSkillRef(raw) : null;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* 从 OpenClaw / AIMA user message 里提取 aima-cmd skill 名字(信号 4)。
|
|
90
|
+
*
|
|
91
|
+
* 注意: 真实 OpenClaw 数据里 name 可能是业务动作展示名, 例如 "生成PRD" / "生成Demo",
|
|
92
|
+
* 这不是稳定 skill id。只有 name 本身像 "prd-create" 这种 slug 时才用于 skill 归因;
|
|
93
|
+
* 中文动作名继续保留在 sourceMetadata.aimaCommands 里, 不切 skill。
|
|
94
|
+
*/
|
|
95
|
+
export function extractAimaCmdSkillRef(record) {
|
|
96
|
+
const content = record.message.content;
|
|
97
|
+
let raw = null;
|
|
98
|
+
if (typeof content === 'string') {
|
|
99
|
+
const m = AIMA_CMD_RE.exec(content);
|
|
100
|
+
raw = m ? m[1] : null;
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
for (const part of content) {
|
|
104
|
+
if (part.type === 'text') {
|
|
105
|
+
const m = AIMA_CMD_RE.exec(part.text);
|
|
106
|
+
if (m) {
|
|
107
|
+
raw = m[1];
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return raw && isStableSkillSlug(raw) ? parseSkillRef(raw) : null;
|
|
114
|
+
}
|
|
115
|
+
function isStableSkillSlug(raw) {
|
|
116
|
+
const trimmed = raw.trim();
|
|
117
|
+
return /^[a-zA-Z0-9][a-zA-Z0-9_.-]*$/.test(trimmed) && /[-_.]/.test(trimmed);
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* 从 assistant message 的 tool_use 里提取 Skill tool 调用的 skill 名字(信号 1)。
|
|
121
|
+
* 返回 null 表示没命中。
|
|
122
|
+
*/
|
|
123
|
+
export function extractSkillToolUse(record) {
|
|
124
|
+
return extractSkillToolUseRef(record)?.skillName ?? null;
|
|
125
|
+
}
|
|
126
|
+
export function extractSkillToolUseRef(record) {
|
|
127
|
+
const content = Array.isArray(record.message.content) ? record.message.content : [];
|
|
128
|
+
for (const part of content) {
|
|
129
|
+
if (part.type === 'tool_use' && part.name === 'Skill') {
|
|
130
|
+
const skill = part.input?.skill;
|
|
131
|
+
if (typeof skill === 'string')
|
|
132
|
+
return parseSkillRef(skill);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
export function extractAttributionSkill(record) {
|
|
138
|
+
return extractAttributionSkillRef(record)?.skillName ?? null;
|
|
139
|
+
}
|
|
140
|
+
export function extractAttributionSkillRef(record) {
|
|
141
|
+
return record.attributionSkill ? parseSkillRef(record.attributionSkill) : null;
|
|
142
|
+
}
|
|
143
|
+
// OpenClaw traces may point at either workspace root; both layouts store skills under <workspace>/skills.
|
|
144
|
+
const SKILL_READ_FILE_RE = /(?:\.claude\/skills|\.openclaw\/workspace(?:-main)?\/skills)\/([^/]+)\/SKILL\.md$/;
|
|
145
|
+
const SKILL_SCRIPT_PATH_RE = /(?:^|[\s"'`(\[{:,])(?:~|\.|\/)?[^\s"'`]*\/skills\/([^/\s"'`]+)\/scripts\/[^\s"'`]*/;
|
|
146
|
+
/**
|
|
147
|
+
* 从 assistant message 的 Read tool_use 里提取 skill 名字(信号 3, fallback)。
|
|
148
|
+
* 匹配 file_path 形如 ".claude/skills/<name>/SKILL.md"
|
|
149
|
+
* 或 ".openclaw/workspace/skills/<name>/SKILL.md" 的模式。
|
|
150
|
+
* 返回 null 表示没命中。
|
|
151
|
+
*/
|
|
152
|
+
export function extractSkillReadFile(record) {
|
|
153
|
+
return extractSkillReadFileRef(record)?.skillName ?? null;
|
|
154
|
+
}
|
|
155
|
+
export function extractSkillReadFileRef(record) {
|
|
156
|
+
const content = Array.isArray(record.message.content) ? record.message.content : [];
|
|
157
|
+
for (const part of content) {
|
|
158
|
+
if (part.type === 'tool_use' && part.name === 'Read') {
|
|
159
|
+
const filePath = part.input?.file_path;
|
|
160
|
+
if (typeof filePath === 'string') {
|
|
161
|
+
const m = SKILL_READ_FILE_RE.exec(filePath);
|
|
162
|
+
if (m)
|
|
163
|
+
return parseSkillRef(m[1]);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* 从 OpenClaw cron/user 文本或 Bash/exec tool command 里提取 skill 脚本路径。
|
|
171
|
+
*
|
|
172
|
+
* cron 型 OpenClaw session 通常没有 <aima-cmd> 或 Skill tool_use,
|
|
173
|
+
* 只会直接执行 ~/.openclaw/workspace-main/skills/<skill>/scripts/*.sh。
|
|
174
|
+
*/
|
|
175
|
+
export function extractSkillScriptCommandRef(record) {
|
|
176
|
+
const texts = [];
|
|
177
|
+
const content = record.message.content;
|
|
178
|
+
if (typeof content === 'string') {
|
|
179
|
+
texts.push(content);
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
for (const part of content) {
|
|
183
|
+
if (part.type === 'text' && typeof part.text === 'string') {
|
|
184
|
+
texts.push(part.text);
|
|
185
|
+
}
|
|
186
|
+
else if (part.type === 'tool_use') {
|
|
187
|
+
const command = part.input?.command;
|
|
188
|
+
if (typeof command === 'string')
|
|
189
|
+
texts.push(command);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
for (const text of texts) {
|
|
194
|
+
const match = SKILL_SCRIPT_PATH_RE.exec(text);
|
|
195
|
+
if (match?.[1])
|
|
196
|
+
return parseSkillRef(match[1]);
|
|
197
|
+
}
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
//# sourceMappingURL=trace-attribution.js.map
|