@kodax-ai/kodax 0.7.95 → 0.7.96-alpha.2
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/CHANGELOG.md +178 -1
- package/LICENSE +158 -158
- package/README.md +149 -24
- package/README_CN.md +117 -24
- package/config-templates/config.example.jsonc +2 -1
- package/config-templates/integrations/a2a.example.jsonc +91 -91
- package/config-templates/integrations/extensions.example.jsonc +7 -7
- package/config-templates/integrations/mcp.example.jsonc +16 -16
- package/dist/builtin/code-review/SKILL.md +82 -82
- package/dist/builtin/git-workflow/SKILL.md +84 -84
- package/dist/builtin/skill-creator/SKILL.md +127 -127
- package/dist/builtin/skill-creator/agents/analyzer.md +12 -12
- package/dist/builtin/skill-creator/agents/comparator.md +13 -13
- package/dist/builtin/skill-creator/agents/grader.md +13 -13
- package/dist/builtin/skill-creator/references/schemas.md +227 -227
- package/dist/builtin/skill-creator/scripts/aggregate-benchmark.d.ts +46 -46
- package/dist/builtin/skill-creator/scripts/aggregate-benchmark.js +208 -208
- package/dist/builtin/skill-creator/scripts/analyze-benchmark.d.ts +46 -46
- package/dist/builtin/skill-creator/scripts/analyze-benchmark.js +286 -286
- package/dist/builtin/skill-creator/scripts/compare-runs.d.ts +62 -62
- package/dist/builtin/skill-creator/scripts/compare-runs.js +330 -330
- package/dist/builtin/skill-creator/scripts/generate-review.d.ts +33 -33
- package/dist/builtin/skill-creator/scripts/generate-review.js +414 -414
- package/dist/builtin/skill-creator/scripts/grade-evals.d.ts +73 -73
- package/dist/builtin/skill-creator/scripts/grade-evals.js +402 -402
- package/dist/builtin/skill-creator/scripts/improve-description.d.ts +23 -23
- package/dist/builtin/skill-creator/scripts/improve-description.js +160 -160
- package/dist/builtin/skill-creator/scripts/init-skill.d.ts +14 -14
- package/dist/builtin/skill-creator/scripts/init-skill.js +155 -155
- package/dist/builtin/skill-creator/scripts/install-skill.d.ts +29 -29
- package/dist/builtin/skill-creator/scripts/install-skill.js +173 -173
- package/dist/builtin/skill-creator/scripts/package-skill.d.ts +38 -38
- package/dist/builtin/skill-creator/scripts/package-skill.js +121 -121
- package/dist/builtin/skill-creator/scripts/quick-validate.d.ts +8 -8
- package/dist/builtin/skill-creator/scripts/quick-validate.js +163 -163
- package/dist/builtin/skill-creator/scripts/run-eval.d.ts +66 -66
- package/dist/builtin/skill-creator/scripts/run-eval.js +353 -353
- package/dist/builtin/skill-creator/scripts/run-loop.d.ts +49 -49
- package/dist/builtin/skill-creator/scripts/run-loop.js +242 -242
- package/dist/builtin/skill-creator/scripts/run-trigger-eval.d.ts +58 -58
- package/dist/builtin/skill-creator/scripts/run-trigger-eval.js +224 -224
- package/dist/builtin/tdd/SKILL.md +56 -56
- package/dist/chunks/agent-4FABF6WK.js +2 -0
- package/dist/chunks/argument-completer-72VHB2VL.js +2 -0
- package/dist/chunks/{chunk-7JXA3533.js → chunk-4OIQZWA5.js} +223 -226
- package/dist/chunks/{chunk-BNVSKIAB.js → chunk-6BVF3HZ7.js} +136 -136
- package/dist/chunks/chunk-7JZZIFZH.js +501 -0
- package/dist/chunks/chunk-AC7Z2OIY.js +2 -0
- package/dist/chunks/{chunk-JS452J2F.js → chunk-C4KYZAFU.js} +2 -2
- package/dist/chunks/chunk-CHUPIWIF.js +251 -0
- package/dist/chunks/{chunk-C4DTUKTR.js → chunk-GYUU7XLH.js} +5 -4
- package/dist/chunks/{chunk-OK4AXDC5.js → chunk-HAX55GOQ.js} +1 -1
- package/dist/chunks/chunk-JKTJCGO2.js +418 -0
- package/dist/chunks/{chunk-O743AJ5V.js → chunk-LQYETRFK.js} +171 -175
- package/dist/chunks/{chunk-2PEDBGKN.js → chunk-LTUZTQ6W.js} +1 -1
- package/dist/chunks/chunk-LYWDUSKO.js +2 -0
- package/dist/chunks/chunk-NGH6T4FD.js +92 -0
- package/dist/chunks/{chunk-SRIJX5ZP.js → chunk-NVRWCSA5.js} +1 -1
- package/dist/chunks/chunk-O4DS7RIQ.js +384 -0
- package/dist/chunks/chunk-ORXU6OWZ.js +2 -0
- package/dist/chunks/chunk-POTW3O65.js +124 -0
- package/dist/chunks/{chunk-2TM3W3GK.js → chunk-RIQSS56Y.js} +1 -1
- package/dist/chunks/chunk-U27XKEN5.js +407 -0
- package/dist/chunks/{chunk-6ABQJUK6.js → chunk-XUX6OUCA.js} +2 -2
- package/dist/chunks/{client-JDOS3YJR.js → client-4C456K4O.js} +1 -1
- package/dist/chunks/compaction-config-3VQRDFF4.js +2 -0
- package/dist/chunks/{construction-bootstrap-YCWHHUYO.js → construction-bootstrap-AHN7EDGG.js} +1 -1
- package/dist/chunks/dist-BCBQXAGI.js +2 -0
- package/dist/chunks/dist-QK2YDWU6.js +2 -0
- package/dist/chunks/host-VIHV7ADG.js +2 -0
- package/dist/chunks/run-manager-NBVMU3KV.js +2 -0
- package/dist/chunks/utils-MEJZ2IGI.js +2 -0
- package/dist/index.d.ts +22 -21
- package/dist/index.js +7 -7
- package/dist/kodax_bootstrap.js +26 -26
- package/dist/kodax_cli.js +1905 -1882
- package/dist/native/darwin-arm64/LICENSE-APACHE.txt +13 -0
- package/dist/native/darwin-arm64/kodax-text-transaction.node +0 -0
- package/dist/native/darwin-arm64/manifest.json +16 -0
- package/dist/native/darwin-x64/LICENSE-APACHE.txt +13 -0
- package/dist/native/darwin-x64/kodax-text-transaction.node +0 -0
- package/dist/native/darwin-x64/manifest.json +16 -0
- package/dist/native/linux-arm64/LICENSE-APACHE.txt +13 -0
- package/dist/native/linux-arm64/kodax-text-transaction.node +0 -0
- package/dist/native/linux-arm64/manifest.json +16 -0
- package/dist/native/linux-x64/LICENSE-APACHE.txt +13 -0
- package/dist/native/linux-x64/kodax-text-transaction.node +0 -0
- package/dist/native/linux-x64/manifest.json +16 -0
- package/dist/native/win32-x64/LICENSE-APACHE.txt +13 -0
- package/dist/native/win32-x64/NOTICE-windows-sandbox.txt +8 -0
- package/dist/native/win32-x64/kodax-windows-sandbox.exe +0 -0
- package/dist/native/win32-x64/kodax-windows-text-transaction.node +0 -0
- package/dist/native/win32-x64/manifest.json +30 -0
- package/dist/provider-capabilities.json +108 -2
- package/dist/runtime-worker.js +1745 -1727
- package/dist/sandbox-network-broker.js +1715 -0
- package/dist/sdk-a2a.d.ts +13 -12
- package/dist/sdk-a2a.js +1 -1
- package/dist/sdk-agent.d.ts +27 -18
- package/dist/sdk-agent.js +1 -1
- package/dist/sdk-coding.d.ts +107 -58
- package/dist/sdk-coding.js +1 -1
- package/dist/sdk-experimental-memory.d.ts +4 -4
- package/dist/sdk-experimental-memory.js +1 -1
- package/dist/sdk-llm.d.ts +9 -10
- package/dist/sdk-llm.js +1 -1
- package/dist/sdk-mcp.js +1 -1
- package/dist/sdk-media.d.ts +1 -1
- package/dist/sdk-media.js +1 -1
- package/dist/sdk-repl.d.ts +25 -17
- package/dist/sdk-repl.js +1 -1
- package/dist/sdk-runtime.d.ts +41 -17
- package/dist/sdk-runtime.js +1 -1
- package/dist/sdk-sandbox.d.ts +17 -3
- package/dist/sdk-sandbox.js +1 -1
- package/dist/sdk-session.d.ts +8 -7
- package/dist/sdk-session.js +1 -1
- package/dist/sdk-skills.js +1 -1
- package/dist/semantic-worker.js +61 -61
- package/dist/types-chunks/{base.d-vopO1rml.d.ts → base.d-COo8E2dk.d.ts} +18 -27
- package/dist/types-chunks/{bash-prefix-extractor.d-B2rxNI4L.d.ts → bash-prefix-extractor.d-DQOlA8cy.d.ts} +72 -52
- package/dist/types-chunks/{capability-learning.d-CE1tm29C.d.ts → capability-learning.d-lRPgA3Or.d.ts} +1 -1
- package/dist/types-chunks/{capsule.d-Y7QRS4J2.d.ts → capsule.d-0zxsgXg_.d.ts} +3 -3
- package/dist/types-chunks/{controller.d-BR-UVeUR.d.ts → controller.d-BTtyIIC1.d.ts} +1 -1
- package/dist/types-chunks/{controller.d-C5noq5-w.d.ts → controller.d-C7tXUcXo.d.ts} +2 -2
- package/dist/types-chunks/{guardrail.d-DqHD-61O.d.ts → guardrail.d-DKTyEHJa.d.ts} +5 -5
- package/dist/types-chunks/{history-retrieval.d-CKU8zmt_.d.ts → history-retrieval.d-CHnL99S7.d.ts} +2 -2
- package/dist/types-chunks/{public-api.d-D7fXaWW8.d.ts → public-api.d-Dx3L3W4Z.d.ts} +7 -4
- package/dist/types-chunks/{repl.d-BYDb14s6.d.ts → repl.d-mO01olIa.d.ts} +5 -5
- package/dist/types-chunks/{resolver.d-CwHUwbdE.d.ts → resolver.d-DlXPjeyx.d.ts} +38 -6
- package/dist/types-chunks/{review-inbox.d-BSgFewyj.d.ts → review-inbox.d-WDSe1nze.d.ts} +1 -1
- package/dist/types-chunks/{run-manager.d-BVJSntpS.d.ts → run-manager.d-DENbbzgR.d.ts} +1 -1
- package/dist/types-chunks/{sdk-session-CqEG84oP.d.ts → sdk-session-DYHGXXH4.d.ts} +3 -3
- package/dist/types-chunks/{shell-command-sets.d-DqaaBwhU.d.ts → shell-command-sets.d-CjFqS4dp.d.ts} +1 -1
- package/dist/types-chunks/{side-query.d-iH0P9ASy.d.ts → side-query.d-j8A3sFv_.d.ts} +2 -2
- package/dist/types-chunks/{types.d-rUOjXych.d.ts → types.d-BbZjR0Wr.d.ts} +1 -1
- package/dist/types-chunks/{types.d-CaTXAW_Q.d.ts → types.d-BkTIKdH6.d.ts} +2 -2
- package/dist/types-chunks/{types.d-C5xQEFcj.d.ts → types.d-DncLrpu_.d.ts} +4 -4
- package/dist/types-chunks/{types.d-CK9A9rpP.d.ts → types.d-Xy0f3x4i.d.ts} +9 -0
- package/dist/types-chunks/{utils.d-CWUyLiXo.d.ts → utils.d-CnxefMos.d.ts} +6 -6
- package/package.json +10 -3
- package/public_docs/README.md +130 -0
- package/public_docs/configuration/sandbox.md +289 -0
- package/public_docs/sdk/embedder-guide.md +6674 -0
- package/scripts/kodax-bin.cjs +28 -28
- package/scripts/production-env.cjs +25 -25
- package/dist/chunks/agent-XXZMXKKA.js +0 -2
- package/dist/chunks/argument-completer-KCYDGTQW.js +0 -2
- package/dist/chunks/chunk-77PNP27P.js +0 -92
- package/dist/chunks/chunk-7QBWHCIZ.js +0 -2
- package/dist/chunks/chunk-BHE66SP3.js +0 -123
- package/dist/chunks/chunk-BR2OSB2I.js +0 -722
- package/dist/chunks/chunk-DSMONSVB.js +0 -407
- package/dist/chunks/chunk-Q5VRWSKG.js +0 -418
- package/dist/chunks/chunk-XWRPOGJN.js +0 -4
- package/dist/chunks/chunk-Y5VIQBT6.js +0 -383
- package/dist/chunks/compaction-config-EGS4577X.js +0 -2
- package/dist/chunks/dist-ITTXQHRJ.js +0 -2
- package/dist/chunks/dist-KFYN3OKD.js +0 -2
- package/dist/chunks/host-VAYADIPW.js +0 -2
- package/dist/chunks/run-manager-52IJZMZJ.js +0 -2
- package/dist/chunks/utils-P7PBSL3R.js +0 -2
- package/dist/sandbox-workspace-session.js +0 -1705
|
@@ -1,58 +1,58 @@
|
|
|
1
|
-
export interface TriggerEvalAttempt {
|
|
2
|
-
trigger: boolean;
|
|
3
|
-
reason: string;
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
export interface TriggerEvalItemResult {
|
|
7
|
-
query: string;
|
|
8
|
-
should_trigger: boolean;
|
|
9
|
-
triggers: number;
|
|
10
|
-
runs: number;
|
|
11
|
-
trigger_rate: number;
|
|
12
|
-
predicted_trigger: boolean;
|
|
13
|
-
pass: boolean;
|
|
14
|
-
attempts: TriggerEvalAttempt[];
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export interface TriggerEvalSummary {
|
|
18
|
-
passed: number;
|
|
19
|
-
failed: number;
|
|
20
|
-
total: number;
|
|
21
|
-
pass_rate: number;
|
|
22
|
-
precision: number;
|
|
23
|
-
recall: number;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export interface TriggerEvalReport {
|
|
27
|
-
skill_name: string;
|
|
28
|
-
description: string;
|
|
29
|
-
results: TriggerEvalItemResult[];
|
|
30
|
-
summary: TriggerEvalSummary;
|
|
31
|
-
meta: {
|
|
32
|
-
provider?: string;
|
|
33
|
-
model?: string | null;
|
|
34
|
-
runs_per_query: number;
|
|
35
|
-
trigger_threshold: number;
|
|
36
|
-
note: string;
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export interface TriggerEvalOptions {
|
|
41
|
-
skillPath: string;
|
|
42
|
-
evalsPath: string;
|
|
43
|
-
provider?: string;
|
|
44
|
-
model?: string;
|
|
45
|
-
output?: string;
|
|
46
|
-
runsPerQuery?: number;
|
|
47
|
-
triggerThreshold?: number;
|
|
48
|
-
maxIter?: number;
|
|
49
|
-
reasoningMode?: string;
|
|
50
|
-
descriptionOverride?: string;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export function parseTriggerDecision(text: string): TriggerEvalAttempt;
|
|
54
|
-
export function summarizeTriggerResults(results: TriggerEvalItemResult[]): TriggerEvalSummary;
|
|
55
|
-
export function runTriggerEval(
|
|
56
|
-
options: TriggerEvalOptions,
|
|
57
|
-
runner?: (prompt: string, options: TriggerEvalOptions) => Promise<string>
|
|
58
|
-
): Promise<TriggerEvalReport>;
|
|
1
|
+
export interface TriggerEvalAttempt {
|
|
2
|
+
trigger: boolean;
|
|
3
|
+
reason: string;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export interface TriggerEvalItemResult {
|
|
7
|
+
query: string;
|
|
8
|
+
should_trigger: boolean;
|
|
9
|
+
triggers: number;
|
|
10
|
+
runs: number;
|
|
11
|
+
trigger_rate: number;
|
|
12
|
+
predicted_trigger: boolean;
|
|
13
|
+
pass: boolean;
|
|
14
|
+
attempts: TriggerEvalAttempt[];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface TriggerEvalSummary {
|
|
18
|
+
passed: number;
|
|
19
|
+
failed: number;
|
|
20
|
+
total: number;
|
|
21
|
+
pass_rate: number;
|
|
22
|
+
precision: number;
|
|
23
|
+
recall: number;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface TriggerEvalReport {
|
|
27
|
+
skill_name: string;
|
|
28
|
+
description: string;
|
|
29
|
+
results: TriggerEvalItemResult[];
|
|
30
|
+
summary: TriggerEvalSummary;
|
|
31
|
+
meta: {
|
|
32
|
+
provider?: string;
|
|
33
|
+
model?: string | null;
|
|
34
|
+
runs_per_query: number;
|
|
35
|
+
trigger_threshold: number;
|
|
36
|
+
note: string;
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface TriggerEvalOptions {
|
|
41
|
+
skillPath: string;
|
|
42
|
+
evalsPath: string;
|
|
43
|
+
provider?: string;
|
|
44
|
+
model?: string;
|
|
45
|
+
output?: string;
|
|
46
|
+
runsPerQuery?: number;
|
|
47
|
+
triggerThreshold?: number;
|
|
48
|
+
maxIter?: number;
|
|
49
|
+
reasoningMode?: string;
|
|
50
|
+
descriptionOverride?: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function parseTriggerDecision(text: string): TriggerEvalAttempt;
|
|
54
|
+
export function summarizeTriggerResults(results: TriggerEvalItemResult[]): TriggerEvalSummary;
|
|
55
|
+
export function runTriggerEval(
|
|
56
|
+
options: TriggerEvalOptions,
|
|
57
|
+
runner?: (prompt: string, options: TriggerEvalOptions) => Promise<string>
|
|
58
|
+
): Promise<TriggerEvalReport>;
|
|
@@ -1,226 +1,226 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { readFile, writeFile } from 'node:fs/promises';
|
|
4
|
-
import path from 'node:path';
|
|
5
|
-
import { fileURLToPath } from 'node:url';
|
|
6
|
-
import {
|
|
7
|
-
extractJsonObject,
|
|
8
|
-
loadKodaXSDK,
|
|
9
|
-
loadSkill,
|
|
10
|
-
} from './utils.js';
|
|
11
|
-
|
|
12
|
-
function buildTriggerEvalPrompt(skillName, description, query) {
|
|
13
|
-
return [
|
|
14
|
-
'You are evaluating whether a KodaX skill description should trigger for a user request.',
|
|
15
|
-
'Decide whether the skill should be used based only on the skill name, description, and query.',
|
|
16
|
-
'Return JSON only with this exact shape:',
|
|
17
|
-
'{"trigger": true, "reason": "short explanation"}',
|
|
18
|
-
'',
|
|
19
|
-
`Skill name: ${skillName}`,
|
|
20
|
-
`Skill description: ${description}`,
|
|
21
|
-
`User query: ${query}`,
|
|
22
|
-
].join('\n');
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export function parseTriggerDecision(text) {
|
|
26
|
-
const parsed = extractJsonObject(text);
|
|
27
|
-
if (!parsed || typeof parsed !== 'object') {
|
|
28
|
-
throw new Error('Could not parse trigger decision JSON');
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
return {
|
|
32
|
-
trigger: parsed.trigger === true,
|
|
33
|
-
reason: typeof parsed.reason === 'string' ? parsed.reason.trim() : '',
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
async function defaultRunPrompt(prompt, options) {
|
|
38
|
-
const { runKodaX } = await loadKodaXSDK();
|
|
39
|
-
const result = await runKodaX(
|
|
40
|
-
{
|
|
41
|
-
provider: options.provider,
|
|
42
|
-
maxIter: options.maxIter ?? 12,
|
|
43
|
-
model: options.model,
|
|
44
|
-
reasoningMode: options.reasoningMode ?? 'off',
|
|
45
|
-
thinking: options.reasoningMode ? options.reasoningMode !== 'off' : false,
|
|
46
|
-
},
|
|
47
|
-
prompt
|
|
48
|
-
);
|
|
49
|
-
|
|
50
|
-
return result.lastText;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export function summarizeTriggerResults(results) {
|
|
54
|
-
const positives = results.filter((result) => result.should_trigger);
|
|
55
|
-
const negatives = results.filter((result) => !result.should_trigger);
|
|
56
|
-
const predictedPositives = results.filter((result) => result.predicted_trigger);
|
|
57
|
-
const truePositives = positives.filter((result) => result.predicted_trigger).length;
|
|
58
|
-
const falsePositives = negatives.filter((result) => result.predicted_trigger).length;
|
|
59
|
-
|
|
60
|
-
const summary = {
|
|
61
|
-
passed: 0,
|
|
62
|
-
failed: 0,
|
|
63
|
-
total: results.length,
|
|
64
|
-
pass_rate: 0,
|
|
65
|
-
precision: 0,
|
|
66
|
-
recall: 0,
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
for (const result of results) {
|
|
70
|
-
if (result.pass) {
|
|
71
|
-
summary.passed += 1;
|
|
72
|
-
} else {
|
|
73
|
-
summary.failed += 1;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
summary.pass_rate = summary.total === 0 ? 0 : summary.passed / summary.total;
|
|
78
|
-
summary.precision = predictedPositives.length === 0
|
|
79
|
-
? 0
|
|
80
|
-
: truePositives / predictedPositives.length;
|
|
81
|
-
summary.recall = positives.length === 0 ? 0 : truePositives / positives.length;
|
|
82
|
-
|
|
83
|
-
return summary;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
export async function runTriggerEval(options, runner = defaultRunPrompt) {
|
|
87
|
-
const skill = await loadSkill(options.skillPath);
|
|
88
|
-
const currentDescription = options.descriptionOverride
|
|
89
|
-
?? String(skill.frontmatter.description ?? '').trim();
|
|
90
|
-
const evalFile = JSON.parse(await readFile(options.evalsPath, 'utf8'));
|
|
91
|
-
const evals = Array.isArray(evalFile.evals) ? evalFile.evals : [];
|
|
92
|
-
const runsPerQuery = Number.isFinite(options.runsPerQuery) && options.runsPerQuery > 0
|
|
93
|
-
? Math.floor(options.runsPerQuery)
|
|
94
|
-
: 1;
|
|
95
|
-
const threshold = Number.isFinite(options.triggerThreshold)
|
|
96
|
-
? Math.min(Math.max(options.triggerThreshold, 0), 1)
|
|
97
|
-
: 0.5;
|
|
98
|
-
const results = [];
|
|
99
|
-
|
|
100
|
-
for (const item of evals) {
|
|
101
|
-
const query = String(item.query ?? item.prompt ?? '').trim();
|
|
102
|
-
if (!query) {
|
|
103
|
-
continue;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const shouldTrigger = item.should_trigger === true;
|
|
107
|
-
let triggers = 0;
|
|
108
|
-
const attempts = [];
|
|
109
|
-
|
|
110
|
-
for (let runIndex = 0; runIndex < runsPerQuery; runIndex += 1) {
|
|
111
|
-
const response = await runner(
|
|
112
|
-
buildTriggerEvalPrompt(skill.frontmatter.name, currentDescription, query),
|
|
113
|
-
options
|
|
114
|
-
);
|
|
115
|
-
const parsed = parseTriggerDecision(response);
|
|
116
|
-
if (parsed.trigger) {
|
|
117
|
-
triggers += 1;
|
|
118
|
-
}
|
|
119
|
-
attempts.push(parsed);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
const triggerRate = triggers / runsPerQuery;
|
|
123
|
-
const predictedTrigger = triggerRate >= threshold;
|
|
124
|
-
const pass = shouldTrigger
|
|
125
|
-
? predictedTrigger
|
|
126
|
-
: !predictedTrigger;
|
|
127
|
-
|
|
128
|
-
results.push({
|
|
129
|
-
query,
|
|
130
|
-
should_trigger: shouldTrigger,
|
|
131
|
-
triggers,
|
|
132
|
-
runs: runsPerQuery,
|
|
133
|
-
trigger_rate: triggerRate,
|
|
134
|
-
predicted_trigger: predictedTrigger,
|
|
135
|
-
pass,
|
|
136
|
-
attempts,
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
const summary = summarizeTriggerResults(results);
|
|
141
|
-
|
|
142
|
-
return {
|
|
143
|
-
skill_name: skill.frontmatter.name,
|
|
144
|
-
description: currentDescription,
|
|
145
|
-
results,
|
|
146
|
-
summary,
|
|
147
|
-
meta: {
|
|
148
|
-
provider: options.provider,
|
|
149
|
-
model: options.model ?? null,
|
|
150
|
-
runs_per_query: runsPerQuery,
|
|
151
|
-
trigger_threshold: threshold,
|
|
152
|
-
note: 'This is a KodaX-native description eval, not a Claude Code tool-trace replay.',
|
|
153
|
-
},
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
function parseArgs(argv) {
|
|
158
|
-
const args = {
|
|
159
|
-
skillPath: '',
|
|
160
|
-
evalsPath: '',
|
|
161
|
-
provider: 'anthropic',
|
|
162
|
-
model: undefined,
|
|
163
|
-
output: undefined,
|
|
164
|
-
runsPerQuery: 1,
|
|
165
|
-
triggerThreshold: 0.5,
|
|
166
|
-
maxIter: 12,
|
|
167
|
-
reasoningMode: 'off',
|
|
168
|
-
descriptionOverride: undefined,
|
|
169
|
-
};
|
|
170
|
-
|
|
171
|
-
for (let index = 2; index < argv.length; index += 1) {
|
|
172
|
-
const token = argv[index];
|
|
173
|
-
if (token === '--skill-path' && argv[index + 1]) {
|
|
174
|
-
args.skillPath = argv[++index];
|
|
175
|
-
} else if (token === '--evals' && argv[index + 1]) {
|
|
176
|
-
args.evalsPath = argv[++index];
|
|
177
|
-
} else if (token === '--provider' && argv[index + 1]) {
|
|
178
|
-
args.provider = argv[++index];
|
|
179
|
-
} else if (token === '--model' && argv[index + 1]) {
|
|
180
|
-
args.model = argv[++index];
|
|
181
|
-
} else if (token === '--output' && argv[index + 1]) {
|
|
182
|
-
args.output = argv[++index];
|
|
183
|
-
} else if (token === '--runs-per-query' && argv[index + 1]) {
|
|
184
|
-
args.runsPerQuery = Number(argv[++index]);
|
|
185
|
-
} else if (token === '--trigger-threshold' && argv[index + 1]) {
|
|
186
|
-
args.triggerThreshold = Number(argv[++index]);
|
|
187
|
-
} else if (token === '--max-iter' && argv[index + 1]) {
|
|
188
|
-
args.maxIter = Number(argv[++index]);
|
|
189
|
-
} else if (token === '--reasoning' && argv[index + 1]) {
|
|
190
|
-
args.reasoningMode = argv[++index];
|
|
191
|
-
} else if (token === '--description' && argv[index + 1]) {
|
|
192
|
-
args.descriptionOverride = argv[++index];
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
return args;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
async function main() {
|
|
200
|
-
const args = parseArgs(process.argv);
|
|
201
|
-
if (!args.skillPath || !args.evalsPath) {
|
|
202
|
-
console.error('Usage: node scripts/run-trigger-eval.js --skill-path <dir> --evals <evals.json> [--provider anthropic] [--output results.json]');
|
|
203
|
-
process.exit(1);
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
const results = await runTriggerEval(args);
|
|
207
|
-
const outputText = `${JSON.stringify(results, null, 2)}\n`;
|
|
208
|
-
|
|
209
|
-
if (args.output) {
|
|
210
|
-
await writeFile(args.output, outputText, 'utf8');
|
|
211
|
-
console.log(`Wrote ${path.resolve(args.output)}`);
|
|
212
|
-
} else {
|
|
213
|
-
process.stdout.write(outputText);
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
import {
|
|
7
|
+
extractJsonObject,
|
|
8
|
+
loadKodaXSDK,
|
|
9
|
+
loadSkill,
|
|
10
|
+
} from './utils.js';
|
|
11
|
+
|
|
12
|
+
function buildTriggerEvalPrompt(skillName, description, query) {
|
|
13
|
+
return [
|
|
14
|
+
'You are evaluating whether a KodaX skill description should trigger for a user request.',
|
|
15
|
+
'Decide whether the skill should be used based only on the skill name, description, and query.',
|
|
16
|
+
'Return JSON only with this exact shape:',
|
|
17
|
+
'{"trigger": true, "reason": "short explanation"}',
|
|
18
|
+
'',
|
|
19
|
+
`Skill name: ${skillName}`,
|
|
20
|
+
`Skill description: ${description}`,
|
|
21
|
+
`User query: ${query}`,
|
|
22
|
+
].join('\n');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function parseTriggerDecision(text) {
|
|
26
|
+
const parsed = extractJsonObject(text);
|
|
27
|
+
if (!parsed || typeof parsed !== 'object') {
|
|
28
|
+
throw new Error('Could not parse trigger decision JSON');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
trigger: parsed.trigger === true,
|
|
33
|
+
reason: typeof parsed.reason === 'string' ? parsed.reason.trim() : '',
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async function defaultRunPrompt(prompt, options) {
|
|
38
|
+
const { runKodaX } = await loadKodaXSDK();
|
|
39
|
+
const result = await runKodaX(
|
|
40
|
+
{
|
|
41
|
+
provider: options.provider,
|
|
42
|
+
maxIter: options.maxIter ?? 12,
|
|
43
|
+
model: options.model,
|
|
44
|
+
reasoningMode: options.reasoningMode ?? 'off',
|
|
45
|
+
thinking: options.reasoningMode ? options.reasoningMode !== 'off' : false,
|
|
46
|
+
},
|
|
47
|
+
prompt
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
return result.lastText;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function summarizeTriggerResults(results) {
|
|
54
|
+
const positives = results.filter((result) => result.should_trigger);
|
|
55
|
+
const negatives = results.filter((result) => !result.should_trigger);
|
|
56
|
+
const predictedPositives = results.filter((result) => result.predicted_trigger);
|
|
57
|
+
const truePositives = positives.filter((result) => result.predicted_trigger).length;
|
|
58
|
+
const falsePositives = negatives.filter((result) => result.predicted_trigger).length;
|
|
59
|
+
|
|
60
|
+
const summary = {
|
|
61
|
+
passed: 0,
|
|
62
|
+
failed: 0,
|
|
63
|
+
total: results.length,
|
|
64
|
+
pass_rate: 0,
|
|
65
|
+
precision: 0,
|
|
66
|
+
recall: 0,
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
for (const result of results) {
|
|
70
|
+
if (result.pass) {
|
|
71
|
+
summary.passed += 1;
|
|
72
|
+
} else {
|
|
73
|
+
summary.failed += 1;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
summary.pass_rate = summary.total === 0 ? 0 : summary.passed / summary.total;
|
|
78
|
+
summary.precision = predictedPositives.length === 0
|
|
79
|
+
? 0
|
|
80
|
+
: truePositives / predictedPositives.length;
|
|
81
|
+
summary.recall = positives.length === 0 ? 0 : truePositives / positives.length;
|
|
82
|
+
|
|
83
|
+
return summary;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export async function runTriggerEval(options, runner = defaultRunPrompt) {
|
|
87
|
+
const skill = await loadSkill(options.skillPath);
|
|
88
|
+
const currentDescription = options.descriptionOverride
|
|
89
|
+
?? String(skill.frontmatter.description ?? '').trim();
|
|
90
|
+
const evalFile = JSON.parse(await readFile(options.evalsPath, 'utf8'));
|
|
91
|
+
const evals = Array.isArray(evalFile.evals) ? evalFile.evals : [];
|
|
92
|
+
const runsPerQuery = Number.isFinite(options.runsPerQuery) && options.runsPerQuery > 0
|
|
93
|
+
? Math.floor(options.runsPerQuery)
|
|
94
|
+
: 1;
|
|
95
|
+
const threshold = Number.isFinite(options.triggerThreshold)
|
|
96
|
+
? Math.min(Math.max(options.triggerThreshold, 0), 1)
|
|
97
|
+
: 0.5;
|
|
98
|
+
const results = [];
|
|
99
|
+
|
|
100
|
+
for (const item of evals) {
|
|
101
|
+
const query = String(item.query ?? item.prompt ?? '').trim();
|
|
102
|
+
if (!query) {
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const shouldTrigger = item.should_trigger === true;
|
|
107
|
+
let triggers = 0;
|
|
108
|
+
const attempts = [];
|
|
109
|
+
|
|
110
|
+
for (let runIndex = 0; runIndex < runsPerQuery; runIndex += 1) {
|
|
111
|
+
const response = await runner(
|
|
112
|
+
buildTriggerEvalPrompt(skill.frontmatter.name, currentDescription, query),
|
|
113
|
+
options
|
|
114
|
+
);
|
|
115
|
+
const parsed = parseTriggerDecision(response);
|
|
116
|
+
if (parsed.trigger) {
|
|
117
|
+
triggers += 1;
|
|
118
|
+
}
|
|
119
|
+
attempts.push(parsed);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const triggerRate = triggers / runsPerQuery;
|
|
123
|
+
const predictedTrigger = triggerRate >= threshold;
|
|
124
|
+
const pass = shouldTrigger
|
|
125
|
+
? predictedTrigger
|
|
126
|
+
: !predictedTrigger;
|
|
127
|
+
|
|
128
|
+
results.push({
|
|
129
|
+
query,
|
|
130
|
+
should_trigger: shouldTrigger,
|
|
131
|
+
triggers,
|
|
132
|
+
runs: runsPerQuery,
|
|
133
|
+
trigger_rate: triggerRate,
|
|
134
|
+
predicted_trigger: predictedTrigger,
|
|
135
|
+
pass,
|
|
136
|
+
attempts,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const summary = summarizeTriggerResults(results);
|
|
141
|
+
|
|
142
|
+
return {
|
|
143
|
+
skill_name: skill.frontmatter.name,
|
|
144
|
+
description: currentDescription,
|
|
145
|
+
results,
|
|
146
|
+
summary,
|
|
147
|
+
meta: {
|
|
148
|
+
provider: options.provider,
|
|
149
|
+
model: options.model ?? null,
|
|
150
|
+
runs_per_query: runsPerQuery,
|
|
151
|
+
trigger_threshold: threshold,
|
|
152
|
+
note: 'This is a KodaX-native description eval, not a Claude Code tool-trace replay.',
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function parseArgs(argv) {
|
|
158
|
+
const args = {
|
|
159
|
+
skillPath: '',
|
|
160
|
+
evalsPath: '',
|
|
161
|
+
provider: 'anthropic',
|
|
162
|
+
model: undefined,
|
|
163
|
+
output: undefined,
|
|
164
|
+
runsPerQuery: 1,
|
|
165
|
+
triggerThreshold: 0.5,
|
|
166
|
+
maxIter: 12,
|
|
167
|
+
reasoningMode: 'off',
|
|
168
|
+
descriptionOverride: undefined,
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
for (let index = 2; index < argv.length; index += 1) {
|
|
172
|
+
const token = argv[index];
|
|
173
|
+
if (token === '--skill-path' && argv[index + 1]) {
|
|
174
|
+
args.skillPath = argv[++index];
|
|
175
|
+
} else if (token === '--evals' && argv[index + 1]) {
|
|
176
|
+
args.evalsPath = argv[++index];
|
|
177
|
+
} else if (token === '--provider' && argv[index + 1]) {
|
|
178
|
+
args.provider = argv[++index];
|
|
179
|
+
} else if (token === '--model' && argv[index + 1]) {
|
|
180
|
+
args.model = argv[++index];
|
|
181
|
+
} else if (token === '--output' && argv[index + 1]) {
|
|
182
|
+
args.output = argv[++index];
|
|
183
|
+
} else if (token === '--runs-per-query' && argv[index + 1]) {
|
|
184
|
+
args.runsPerQuery = Number(argv[++index]);
|
|
185
|
+
} else if (token === '--trigger-threshold' && argv[index + 1]) {
|
|
186
|
+
args.triggerThreshold = Number(argv[++index]);
|
|
187
|
+
} else if (token === '--max-iter' && argv[index + 1]) {
|
|
188
|
+
args.maxIter = Number(argv[++index]);
|
|
189
|
+
} else if (token === '--reasoning' && argv[index + 1]) {
|
|
190
|
+
args.reasoningMode = argv[++index];
|
|
191
|
+
} else if (token === '--description' && argv[index + 1]) {
|
|
192
|
+
args.descriptionOverride = argv[++index];
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return args;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
async function main() {
|
|
200
|
+
const args = parseArgs(process.argv);
|
|
201
|
+
if (!args.skillPath || !args.evalsPath) {
|
|
202
|
+
console.error('Usage: node scripts/run-trigger-eval.js --skill-path <dir> --evals <evals.json> [--provider anthropic] [--output results.json]');
|
|
203
|
+
process.exit(1);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const results = await runTriggerEval(args);
|
|
207
|
+
const outputText = `${JSON.stringify(results, null, 2)}\n`;
|
|
208
|
+
|
|
209
|
+
if (args.output) {
|
|
210
|
+
await writeFile(args.output, outputText, 'utf8');
|
|
211
|
+
console.log(`Wrote ${path.resolve(args.output)}`);
|
|
212
|
+
} else {
|
|
213
|
+
process.stdout.write(outputText);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
217
|
const isDirectRun = process.env.KODAX_MODULE_BUNDLE !== 'true'
|
|
218
218
|
&& process.argv[1]
|
|
219
|
-
&& fileURLToPath(import.meta.url) === path.resolve(process.argv[1]);
|
|
220
|
-
|
|
221
|
-
if (isDirectRun) {
|
|
222
|
-
main().catch((error) => {
|
|
223
|
-
console.error(error instanceof Error ? error.message : String(error));
|
|
224
|
-
process.exit(1);
|
|
225
|
-
});
|
|
226
|
-
}
|
|
219
|
+
&& fileURLToPath(import.meta.url) === path.resolve(process.argv[1]);
|
|
220
|
+
|
|
221
|
+
if (isDirectRun) {
|
|
222
|
+
main().catch((error) => {
|
|
223
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
224
|
+
process.exit(1);
|
|
225
|
+
});
|
|
226
|
+
}
|