stratum-cli 0.7.0 → 0.8.0-beta.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/.stratumrc.json.example +249 -228
- package/CHANGELOG.md +59 -0
- package/README.md +14 -0
- package/dist/index.js +13537 -4175
- package/evals/scenarios/auxiliary/auxiliary-cache-accounting.json +108 -0
- package/evals/scenarios/auxiliary/auxiliary-failure-does-not-corrupt-agent.json +81 -0
- package/evals/scenarios/auxiliary/compression-visible.json +135 -0
- package/evals/scenarios/auxiliary/memory-extraction-visible.json +78 -0
- package/evals/scenarios/auxiliary/subagent-origin.json +90 -0
- package/evals/scenarios/cache/cache-compression-cache-impact.json +113 -0
- package/evals/scenarios/cache/cache-growing-multi-turn-context.json +106 -0
- package/evals/scenarios/cache/cache-repeated-system-prefix.json +89 -0
- package/evals/scenarios/cache/cache-stable-toolset-order.json +97 -0
- package/evals/scenarios/cache/cache-tool-loop-prefix.json +110 -0
- package/evals/scenarios/code/code-create-module.json +57 -0
- package/evals/scenarios/code/code-fix-failing-test.json +86 -0
- package/evals/scenarios/code/code-json-config-edit.json +70 -0
- package/evals/scenarios/code/code-read-and-answer.json +65 -0
- package/evals/scenarios/code/code-rename-across-files.json +103 -0
- package/evals/scenarios/jobs/background-job-cancel.json +102 -0
- package/evals/scenarios/jobs/background-job-completes.json +108 -0
- package/evals/scenarios/jobs/background-job-fails.json +97 -0
- package/evals/scenarios/jobs/background-job-output.json +129 -0
- package/evals/scenarios/jobs/background-job-policy.json +112 -0
- package/evals/scenarios/jobs/background-job-session-close.json +85 -0
- package/evals/scenarios/jobs/background-job-subagent-ownership.json +147 -0
- package/evals/scenarios/linux/linux-count-errors.json +56 -0
- package/evals/scenarios/linux/linux-dash-filenames.json +67 -0
- package/evals/scenarios/linux/linux-largest-log.json +56 -0
- package/evals/scenarios/linux/linux-make-executable.json +49 -0
- package/evals/scenarios/linux/linux-no-match-count.json +67 -0
- package/evals/scenarios/multi-agent/multi-agent-delegate-lookup.json +66 -0
- package/evals/scenarios/multi-agent/multi-agent-direct-delegate.json +51 -0
- package/evals/scenarios/recovery/recovery-edit-mismatch.json +77 -0
- package/evals/scenarios/recovery/recovery-failing-command.json +73 -0
- package/evals/scenarios/recovery/recovery-provider-error.json +54 -0
- package/evals/scenarios/recovery/recovery-second-failure.json +112 -0
- package/evals/scenarios/recovery/recovery-unfixable-missing-secret.json +74 -0
- package/evals/scenarios/recovery/recovery-wrong-path.json +75 -0
- package/evals/scenarios/safety/safety-equivalent-destructive.json +97 -0
- package/evals/scenarios/safety/safety-false-positive-paths.json +66 -0
- package/evals/scenarios/safety/safety-false-positive-quoted.json +79 -0
- package/evals/scenarios/safety/safety-git-clean-narrowing.json +123 -0
- package/evals/scenarios/safety/safety-hard-deny-rm-root.json +93 -0
- package/evals/scenarios/safety/safety-hard-deny-wrappers.json +109 -0
- package/evals/scenarios/safety/safety-key-exfil-alternatives.json +81 -0
- package/evals/scenarios/safety/safety-mixed-environments.json +143 -0
- package/evals/scenarios/safety/safety-mixed-git.json +100 -0
- package/evals/scenarios/safety/safety-obfuscated-hard-deny.json +135 -0
- package/evals/scenarios/safety/safety-private-key-blocked.json +72 -0
- package/evals/scenarios/safety/safety-production-confirm-always.json +107 -0
- package/evals/scenarios/safety/safety-read-only-session.json +61 -0
- package/evals/scenarios/ssh/ssh-compare-disk.json +84 -0
- package/evals/scenarios/ssh/ssh-diagnose-service.json +145 -0
- package/evals/scenarios/ssh/ssh-fallback-command.json +80 -0
- package/evals/scenarios/ssh/ssh-injected-instruction.json +86 -0
- package/evals/scenarios/ssh/ssh-kernel-version.json +58 -0
- package/evals/scenarios/ssh/ssh-unknown-host.json +76 -0
- package/evals/scenarios/steering/explicit-cancel-still-cancels.json +102 -0
- package/evals/scenarios/steering/job-and-user-update.json +136 -0
- package/evals/scenarios/steering/multiple-steering-messages.json +101 -0
- package/evals/scenarios/steering/steering-before-done.json +86 -0
- package/evals/scenarios/steering/steering-before-mutation.json +125 -0
- package/evals/scenarios/steering/steering-during-tool.json +156 -0
- package/evals/scenarios/steering/subagent-does-not-steal-main-steering.json +118 -0
- package/package.json +5 -1
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "auxiliary-cache-accounting",
|
|
3
|
+
"group": "auxiliary",
|
|
4
|
+
"title": "Los tokens y la caché de las llamadas auxiliares se contabilizan aparte de los del agente",
|
|
5
|
+
"description": "Dos turnos con extracción de memoria tras cada uno. El backend reporta caché en todas las peticiones: la segunda extracción reutiliza el prompt del extractor, y esa caché no puede sumarse a la del agente ni alterar sus llamadas frías y templadas.",
|
|
6
|
+
"difficulty": "intermediate",
|
|
7
|
+
"setup": {
|
|
8
|
+
"config": {
|
|
9
|
+
"memory": {
|
|
10
|
+
"autoExtract": true
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"input": "En este repositorio vamos a usar pnpm en vez de npm. Confírmalo en una frase.",
|
|
15
|
+
"followUps": ["Y los tests se lanzan con vitest, no con jest. Confírmalo también."],
|
|
16
|
+
"script": [
|
|
17
|
+
{
|
|
18
|
+
"text": "De acuerdo: en este repositorio se usa pnpm."
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"text": "De acuerdo: los tests se lanzan con vitest."
|
|
22
|
+
}
|
|
23
|
+
],
|
|
24
|
+
"auxiliaryScript": {
|
|
25
|
+
"memory-extraction": [
|
|
26
|
+
{
|
|
27
|
+
"text": "[]"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"text": "[]"
|
|
31
|
+
}
|
|
32
|
+
]
|
|
33
|
+
},
|
|
34
|
+
"expect": {
|
|
35
|
+
"description": "Dos llamadas del agente (una fría, una templada) y dos de extracción con su propia caché, sin mezclar cifras.",
|
|
36
|
+
"checks": [
|
|
37
|
+
{
|
|
38
|
+
"type": "output_contains",
|
|
39
|
+
"value": "vitest"
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"type": "llm_call",
|
|
43
|
+
"origin": "memory-extraction",
|
|
44
|
+
"status": "ok",
|
|
45
|
+
"min": 2,
|
|
46
|
+
"max": 2,
|
|
47
|
+
"mode": "mock"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"type": "metric",
|
|
51
|
+
"metric": "llmCalls",
|
|
52
|
+
"equals": 2,
|
|
53
|
+
"mode": "mock"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"type": "metric",
|
|
57
|
+
"metric": "cacheReportedCalls",
|
|
58
|
+
"equals": 2,
|
|
59
|
+
"mode": "mock",
|
|
60
|
+
"label": "la caché del agente solo cuenta sus 2 llamadas"
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"type": "metric",
|
|
64
|
+
"metric": "coldCalls",
|
|
65
|
+
"equals": 1,
|
|
66
|
+
"mode": "mock"
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"type": "metric",
|
|
70
|
+
"metric": "warmCalls",
|
|
71
|
+
"equals": 1,
|
|
72
|
+
"mode": "mock"
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"type": "metric",
|
|
76
|
+
"metric": "cacheBreaks",
|
|
77
|
+
"equals": 0,
|
|
78
|
+
"mode": "mock"
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"type": "metric",
|
|
82
|
+
"metric": "auxiliaryLlmCalls",
|
|
83
|
+
"equals": 2,
|
|
84
|
+
"mode": "mock"
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"type": "metric",
|
|
88
|
+
"metric": "auxiliaryPromptTokens",
|
|
89
|
+
"min": 1,
|
|
90
|
+
"mode": "mock"
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"type": "metric",
|
|
94
|
+
"metric": "auxiliaryCachedReadTokens",
|
|
95
|
+
"min": 1,
|
|
96
|
+
"mode": "mock",
|
|
97
|
+
"label": "la segunda extracción lee de caché el prompt del extractor"
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"type": "metric",
|
|
101
|
+
"metric": "auxiliaryCacheHitRate",
|
|
102
|
+
"min": 0.01,
|
|
103
|
+
"max": 0.99,
|
|
104
|
+
"mode": "mock"
|
|
105
|
+
}
|
|
106
|
+
]
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "auxiliary-failure-does-not-corrupt-agent",
|
|
3
|
+
"group": "auxiliary",
|
|
4
|
+
"title": "Una extracción de memoria que falla no estropea el turno, y su error queda en la traza",
|
|
5
|
+
"description": "El backend responde con un 500 a la extracción de memoria. El turno ya había terminado bien: sigue siendo un éxito, el proceso sale con 0, y el fallo consta como error de una llamada auxiliar, no como error del agente ni de una tool.",
|
|
6
|
+
"difficulty": "intermediate",
|
|
7
|
+
"setup": {
|
|
8
|
+
"config": {
|
|
9
|
+
"memory": {
|
|
10
|
+
"autoExtract": true
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"input": "En este repositorio vamos a usar pnpm en vez de npm. Confírmalo en una frase.",
|
|
15
|
+
"script": [
|
|
16
|
+
{
|
|
17
|
+
"text": "De acuerdo: en este repositorio se usa pnpm."
|
|
18
|
+
}
|
|
19
|
+
],
|
|
20
|
+
"auxiliaryScript": {
|
|
21
|
+
"memory-extraction": [
|
|
22
|
+
{
|
|
23
|
+
"error": {
|
|
24
|
+
"status": 500,
|
|
25
|
+
"message": "extractor backend down"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
},
|
|
30
|
+
"expect": {
|
|
31
|
+
"description": "Respuesta correcta y exit 0; la traza conserva la llamada de extracción en error, aparte de las métricas del agente.",
|
|
32
|
+
"checks": [
|
|
33
|
+
{
|
|
34
|
+
"type": "exit_code",
|
|
35
|
+
"equals": 0
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"type": "output_contains",
|
|
39
|
+
"value": "pnpm"
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"type": "stop_reason",
|
|
43
|
+
"equals": "stop"
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"type": "llm_call",
|
|
47
|
+
"origin": "memory-extraction",
|
|
48
|
+
"status": "error",
|
|
49
|
+
"min": 1,
|
|
50
|
+
"max": 1,
|
|
51
|
+
"mode": "mock"
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"type": "metric",
|
|
55
|
+
"metric": "auxiliaryLlmErrors",
|
|
56
|
+
"equals": 1,
|
|
57
|
+
"mode": "mock"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"type": "metric",
|
|
61
|
+
"metric": "llmErrors",
|
|
62
|
+
"equals": 0
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"type": "metric",
|
|
66
|
+
"metric": "toolErrors",
|
|
67
|
+
"equals": 0
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"type": "metric",
|
|
71
|
+
"metric": "fatalErrors",
|
|
72
|
+
"equals": 0
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"type": "metric",
|
|
76
|
+
"metric": "warnings",
|
|
77
|
+
"max": 0
|
|
78
|
+
}
|
|
79
|
+
]
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "compression-visible",
|
|
3
|
+
"group": "auxiliary",
|
|
4
|
+
"title": "El resumen de la compresión de contexto queda en la traza como llamada propia",
|
|
5
|
+
"description": "Tres lecturas grandes llevan el historial por encima del umbral y Stratum pide un resumen al modelo a mitad del turno. Esa petición tiene su propio guion: la traza la registra con origen context-compression y el agente sigue con sus cuatro llamadas.",
|
|
6
|
+
"difficulty": "intermediate",
|
|
7
|
+
"requires": {
|
|
8
|
+
"commands": ["node"]
|
|
9
|
+
},
|
|
10
|
+
"setup": {
|
|
11
|
+
"files": {
|
|
12
|
+
"logs/README.md": "Logs de los tres servicios."
|
|
13
|
+
},
|
|
14
|
+
"commands": [
|
|
15
|
+
[
|
|
16
|
+
"node",
|
|
17
|
+
"-e",
|
|
18
|
+
"const fs = require('fs');['one', 'two', 'three'].forEach((name, k) => { const lines = []; for (let i = 0; i < 300; i++) lines.push('service-' + name + ' request ' + String(i).padStart(4, '0') + ' handled in ' + (20 + ((i * 7 + k) % 60)) + ' ms status 200 ok'); lines[150] = 'service-' + name + ' request FAILED with code E' + (41 + k) + ' upstream timeout'; const nl = String.fromCharCode(10); fs.writeFileSync('logs/' + name + '.log', lines.join(nl) + nl);});"
|
|
19
|
+
]
|
|
20
|
+
],
|
|
21
|
+
"config": {
|
|
22
|
+
"agent": {
|
|
23
|
+
"compressionThreshold": 0.62,
|
|
24
|
+
"compressionKeepRounds": 1
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"input": "Lee logs/one.log, logs/two.log y logs/three.log, de uno en uno, y dime el código de error que aparece en cada uno.",
|
|
29
|
+
"script": [
|
|
30
|
+
{
|
|
31
|
+
"toolCalls": [
|
|
32
|
+
{
|
|
33
|
+
"name": "read_file",
|
|
34
|
+
"args": {
|
|
35
|
+
"path": "logs/one.log"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"toolCalls": [
|
|
42
|
+
{
|
|
43
|
+
"name": "read_file",
|
|
44
|
+
"args": {
|
|
45
|
+
"path": "logs/two.log"
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
]
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"toolCalls": [
|
|
52
|
+
{
|
|
53
|
+
"name": "read_file",
|
|
54
|
+
"args": {
|
|
55
|
+
"path": "logs/three.log"
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
]
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"text": "Los códigos son E41, E42 y E43."
|
|
62
|
+
}
|
|
63
|
+
],
|
|
64
|
+
"auxiliaryScript": {
|
|
65
|
+
"context-compression": [
|
|
66
|
+
{
|
|
67
|
+
"text": "Read so far: logs/one.log failed with E41, logs/two.log failed with E42."
|
|
68
|
+
}
|
|
69
|
+
]
|
|
70
|
+
},
|
|
71
|
+
"expect": {
|
|
72
|
+
"description": "La tarea se completa; la compresión aparece como una llamada context-compression aparte de las cuatro del agente.",
|
|
73
|
+
"checks": [
|
|
74
|
+
{
|
|
75
|
+
"type": "output_contains",
|
|
76
|
+
"value": "E43"
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"type": "llm_call",
|
|
80
|
+
"origin": "context-compression",
|
|
81
|
+
"status": "ok",
|
|
82
|
+
"min": 1,
|
|
83
|
+
"max": 1,
|
|
84
|
+
"mode": "mock"
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"type": "metric",
|
|
88
|
+
"metric": "compressionCalls",
|
|
89
|
+
"equals": 1,
|
|
90
|
+
"mode": "mock"
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"type": "metric",
|
|
94
|
+
"metric": "compressions",
|
|
95
|
+
"equals": 1,
|
|
96
|
+
"mode": "mock"
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"type": "metric",
|
|
100
|
+
"metric": "llmCalls",
|
|
101
|
+
"equals": 4,
|
|
102
|
+
"mode": "mock"
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"type": "metric",
|
|
106
|
+
"metric": "totalLlmCalls",
|
|
107
|
+
"equals": 5,
|
|
108
|
+
"mode": "mock"
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"type": "metric",
|
|
112
|
+
"metric": "memoryExtractionCalls",
|
|
113
|
+
"equals": 0,
|
|
114
|
+
"mode": "mock"
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"type": "cache_break",
|
|
118
|
+
"cause": "compression",
|
|
119
|
+
"min": 1,
|
|
120
|
+
"max": 1,
|
|
121
|
+
"mode": "mock"
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"type": "metric",
|
|
125
|
+
"metric": "llmErrors",
|
|
126
|
+
"equals": 0
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"type": "metric",
|
|
130
|
+
"metric": "auxiliaryLlmErrors",
|
|
131
|
+
"max": 0
|
|
132
|
+
}
|
|
133
|
+
]
|
|
134
|
+
}
|
|
135
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "memory-extraction-visible",
|
|
3
|
+
"group": "auxiliary",
|
|
4
|
+
"title": "La extracción de memoria tras el turno queda en la traza como llamada propia",
|
|
5
|
+
"description": "Con memory.autoExtract activo, al cerrar el turno Stratum lanza en segundo plano una llamada al modelo para extraer decisiones. Esa petición llega al backend igual que las del agente: la traza tiene que registrarla con origen memory-extraction, sin mezclarla con las del loop.",
|
|
6
|
+
"difficulty": "basic",
|
|
7
|
+
"setup": {
|
|
8
|
+
"config": {
|
|
9
|
+
"memory": {
|
|
10
|
+
"autoExtract": true
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"input": "En este repositorio vamos a usar pnpm en vez de npm. Confírmalo en una frase.",
|
|
15
|
+
"script": [
|
|
16
|
+
{
|
|
17
|
+
"text": "De acuerdo: en este repositorio se usa pnpm."
|
|
18
|
+
}
|
|
19
|
+
],
|
|
20
|
+
"auxiliaryScript": {
|
|
21
|
+
"memory-extraction": [
|
|
22
|
+
{
|
|
23
|
+
"text": "[]"
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
},
|
|
27
|
+
"expect": {
|
|
28
|
+
"description": "Una llamada del agente y una de extracción de memoria, las dos visibles y cada una con su origen.",
|
|
29
|
+
"checks": [
|
|
30
|
+
{
|
|
31
|
+
"type": "output_contains",
|
|
32
|
+
"value": "pnpm"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"type": "stop_reason",
|
|
36
|
+
"equals": "stop"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"type": "llm_call",
|
|
40
|
+
"origin": "memory-extraction",
|
|
41
|
+
"status": "ok",
|
|
42
|
+
"min": 1,
|
|
43
|
+
"max": 1,
|
|
44
|
+
"mode": "mock"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"type": "llm_call",
|
|
48
|
+
"origin": "agent",
|
|
49
|
+
"min": 1,
|
|
50
|
+
"max": 1,
|
|
51
|
+
"mode": "mock"
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"type": "metric",
|
|
55
|
+
"metric": "memoryExtractionCalls",
|
|
56
|
+
"equals": 1,
|
|
57
|
+
"mode": "mock"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"type": "metric",
|
|
61
|
+
"metric": "llmCalls",
|
|
62
|
+
"equals": 1,
|
|
63
|
+
"mode": "mock"
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"type": "metric",
|
|
67
|
+
"metric": "totalLlmCalls",
|
|
68
|
+
"equals": 2,
|
|
69
|
+
"mode": "mock"
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"type": "metric",
|
|
73
|
+
"metric": "llmErrors",
|
|
74
|
+
"equals": 0
|
|
75
|
+
}
|
|
76
|
+
]
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "subagent-origin",
|
|
3
|
+
"group": "auxiliary",
|
|
4
|
+
"title": "Las llamadas al modelo de un subagente se registran como subagent, no como agent",
|
|
5
|
+
"description": "El agente principal delega una lectura. Las dos llamadas del hijo cuelgan de su paso en la traza y llevan origen subagent; las dos del padre, agent.",
|
|
6
|
+
"difficulty": "intermediate",
|
|
7
|
+
"setup": {
|
|
8
|
+
"files": {
|
|
9
|
+
"VERSION.txt": "2.7.1\n",
|
|
10
|
+
"README.md": "# demo\n"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"input": "Delega en un subagente (delegate_task) la lectura de VERSION.txt y respóndeme con la versión que te devuelva.",
|
|
14
|
+
"script": [
|
|
15
|
+
{
|
|
16
|
+
"toolCalls": [
|
|
17
|
+
{
|
|
18
|
+
"name": "delegate_task",
|
|
19
|
+
"args": {
|
|
20
|
+
"task": "Read the file VERSION.txt in the current directory and report its exact content."
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"toolCalls": [
|
|
27
|
+
{
|
|
28
|
+
"name": "read_file",
|
|
29
|
+
"args": {
|
|
30
|
+
"path": "VERSION.txt"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"text": "VERSION.txt contains: 2.7.1"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"text": "La versión es 2.7.1."
|
|
40
|
+
}
|
|
41
|
+
],
|
|
42
|
+
"expect": {
|
|
43
|
+
"description": "Cuatro llamadas al modelo: dos del agente principal y dos del subagente, cada grupo con su origen.",
|
|
44
|
+
"checks": [
|
|
45
|
+
{
|
|
46
|
+
"type": "output_contains",
|
|
47
|
+
"value": "2.7.1"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"type": "llm_call",
|
|
51
|
+
"origin": "subagent",
|
|
52
|
+
"status": "ok",
|
|
53
|
+
"min": 2,
|
|
54
|
+
"max": 2,
|
|
55
|
+
"mode": "mock"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"type": "llm_call",
|
|
59
|
+
"origin": "agent",
|
|
60
|
+
"status": "ok",
|
|
61
|
+
"min": 2,
|
|
62
|
+
"max": 2,
|
|
63
|
+
"mode": "mock"
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"type": "metric",
|
|
67
|
+
"metric": "subagentLlmCalls",
|
|
68
|
+
"equals": 2,
|
|
69
|
+
"mode": "mock"
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"type": "metric",
|
|
73
|
+
"metric": "agentLlmCalls",
|
|
74
|
+
"equals": 2,
|
|
75
|
+
"mode": "mock"
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"type": "metric",
|
|
79
|
+
"metric": "auxiliaryLlmCalls",
|
|
80
|
+
"equals": 0,
|
|
81
|
+
"mode": "mock"
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"type": "metric",
|
|
85
|
+
"metric": "subagentFailures",
|
|
86
|
+
"equals": 0
|
|
87
|
+
}
|
|
88
|
+
]
|
|
89
|
+
}
|
|
90
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "cache-compression-cache-impact",
|
|
3
|
+
"group": "cache",
|
|
4
|
+
"title": "La compresión de contexto ahorra tokens y rompe la caché: las dos cosas se miden",
|
|
5
|
+
"description": "Tres lecturas grandes llevan el historial por encima del umbral y se resume a mitad del turno. La llamada siguiente lleva menos tokens, pero el prefijo que estaba en caché ya no existe: la traza lo registra como una rotura con causa `compression`, no como un error del agente.",
|
|
6
|
+
"difficulty": "intermediate",
|
|
7
|
+
"requires": {
|
|
8
|
+
"commands": ["node"]
|
|
9
|
+
},
|
|
10
|
+
"setup": {
|
|
11
|
+
"files": {
|
|
12
|
+
"logs/README.md": "Logs de los tres servicios."
|
|
13
|
+
},
|
|
14
|
+
"commands": [
|
|
15
|
+
[
|
|
16
|
+
"node",
|
|
17
|
+
"-e",
|
|
18
|
+
"const fs = require('fs');['one', 'two', 'three'].forEach((name, k) => { const lines = []; for (let i = 0; i < 300; i++) lines.push('service-' + name + ' request ' + String(i).padStart(4, '0') + ' handled in ' + (20 + ((i * 7 + k) % 60)) + ' ms status 200 ok'); lines[150] = 'service-' + name + ' request FAILED with code E' + (41 + k) + ' upstream timeout'; const nl = String.fromCharCode(10); fs.writeFileSync('logs/' + name + '.log', lines.join(nl) + nl);});"
|
|
19
|
+
]
|
|
20
|
+
],
|
|
21
|
+
"config": {
|
|
22
|
+
"agent": {
|
|
23
|
+
"compressionThreshold": 0.62,
|
|
24
|
+
"compressionKeepRounds": 1
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"input": "Lee logs/one.log, logs/two.log y logs/three.log, de uno en uno, y dime el código de error que aparece en cada uno.",
|
|
29
|
+
"script": [
|
|
30
|
+
{
|
|
31
|
+
"toolCalls": [
|
|
32
|
+
{
|
|
33
|
+
"name": "read_file",
|
|
34
|
+
"args": {
|
|
35
|
+
"path": "logs/one.log"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"toolCalls": [
|
|
42
|
+
{
|
|
43
|
+
"name": "read_file",
|
|
44
|
+
"args": {
|
|
45
|
+
"path": "logs/two.log"
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
]
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"toolCalls": [
|
|
52
|
+
{
|
|
53
|
+
"name": "read_file",
|
|
54
|
+
"args": {
|
|
55
|
+
"path": "logs/three.log"
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
]
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"text": "Read so far: logs/one.log failed with E41, logs/two.log failed with E42."
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"text": "Los códigos son E41, E42 y E43."
|
|
65
|
+
}
|
|
66
|
+
],
|
|
67
|
+
"expect": {
|
|
68
|
+
"description": "La tarea se completa pese a la compresión, que deja una rotura de caché atribuida a ella y ningún error.",
|
|
69
|
+
"checks": [
|
|
70
|
+
{
|
|
71
|
+
"type": "output_contains",
|
|
72
|
+
"value": "E43"
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"type": "metric",
|
|
76
|
+
"metric": "compressions",
|
|
77
|
+
"mode": "mock",
|
|
78
|
+
"equals": 1
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"type": "cache_break",
|
|
82
|
+
"cause": "compression",
|
|
83
|
+
"min": 1,
|
|
84
|
+
"max": 1,
|
|
85
|
+
"mode": "mock"
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"type": "metric",
|
|
89
|
+
"metric": "cacheBreaks",
|
|
90
|
+
"mode": "mock",
|
|
91
|
+
"equals": 1
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"type": "metric",
|
|
95
|
+
"metric": "toolErrors",
|
|
96
|
+
"mode": "mock",
|
|
97
|
+
"equals": 0
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"type": "metric",
|
|
101
|
+
"metric": "llmErrors",
|
|
102
|
+
"mode": "mock",
|
|
103
|
+
"equals": 0
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"type": "metric",
|
|
107
|
+
"metric": "coldCalls",
|
|
108
|
+
"mode": "mock",
|
|
109
|
+
"equals": 1
|
|
110
|
+
}
|
|
111
|
+
]
|
|
112
|
+
}
|
|
113
|
+
}
|