@mknightzzz/stw 0.1.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.
Files changed (250) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +277 -0
  3. package/dist/agentic-fallback.d.ts +3 -0
  4. package/dist/agentic-fallback.js +32 -0
  5. package/dist/agentic-fallback.js.map +1 -0
  6. package/dist/agentic-prompt.d.ts +2 -0
  7. package/dist/agentic-prompt.js +68 -0
  8. package/dist/agentic-prompt.js.map +1 -0
  9. package/dist/agentic-runtime.d.ts +48 -0
  10. package/dist/agentic-runtime.js +149 -0
  11. package/dist/agentic-runtime.js.map +1 -0
  12. package/dist/agentic-types.d.ts +37 -0
  13. package/dist/agentic-types.js +2 -0
  14. package/dist/agentic-types.js.map +1 -0
  15. package/dist/agents.d.ts +7 -0
  16. package/dist/agents.js +2 -0
  17. package/dist/agents.js.map +1 -0
  18. package/dist/assignments.d.ts +7 -0
  19. package/dist/assignments.js +125 -0
  20. package/dist/assignments.js.map +1 -0
  21. package/dist/checkpoint.d.ts +35 -0
  22. package/dist/checkpoint.js +78 -0
  23. package/dist/checkpoint.js.map +1 -0
  24. package/dist/circuit-breaker.d.ts +17 -0
  25. package/dist/circuit-breaker.js +65 -0
  26. package/dist/circuit-breaker.js.map +1 -0
  27. package/dist/claim.d.ts +6 -0
  28. package/dist/claim.js +135 -0
  29. package/dist/claim.js.map +1 -0
  30. package/dist/clarity-gate.d.ts +12 -0
  31. package/dist/clarity-gate.js +83 -0
  32. package/dist/clarity-gate.js.map +1 -0
  33. package/dist/cli.d.ts +2 -0
  34. package/dist/cli.js +38 -0
  35. package/dist/cli.js.map +1 -0
  36. package/dist/command-dispatch.d.ts +45 -0
  37. package/dist/command-dispatch.js +206 -0
  38. package/dist/command-dispatch.js.map +1 -0
  39. package/dist/command-parser.d.ts +11 -0
  40. package/dist/command-parser.js +101 -0
  41. package/dist/command-parser.js.map +1 -0
  42. package/dist/commands/clean.d.ts +10 -0
  43. package/dist/commands/clean.js +133 -0
  44. package/dist/commands/clean.js.map +1 -0
  45. package/dist/commands/execution.d.ts +2 -0
  46. package/dist/commands/execution.js +327 -0
  47. package/dist/commands/execution.js.map +1 -0
  48. package/dist/commands/go.d.ts +2 -0
  49. package/dist/commands/go.js +197 -0
  50. package/dist/commands/go.js.map +1 -0
  51. package/dist/commands/helpers.d.ts +44 -0
  52. package/dist/commands/helpers.js +231 -0
  53. package/dist/commands/helpers.js.map +1 -0
  54. package/dist/commands/idea.d.ts +2 -0
  55. package/dist/commands/idea.js +89 -0
  56. package/dist/commands/idea.js.map +1 -0
  57. package/dist/commands/init.d.ts +2 -0
  58. package/dist/commands/init.js +94 -0
  59. package/dist/commands/init.js.map +1 -0
  60. package/dist/commands/integration.d.ts +7 -0
  61. package/dist/commands/integration.js +139 -0
  62. package/dist/commands/integration.js.map +1 -0
  63. package/dist/commands/maintenance.d.ts +2 -0
  64. package/dist/commands/maintenance.js +301 -0
  65. package/dist/commands/maintenance.js.map +1 -0
  66. package/dist/commands/run.d.ts +2 -0
  67. package/dist/commands/run.js +356 -0
  68. package/dist/commands/run.js.map +1 -0
  69. package/dist/commands/setup.d.ts +2 -0
  70. package/dist/commands/setup.js +198 -0
  71. package/dist/commands/setup.js.map +1 -0
  72. package/dist/commands/spec.d.ts +2 -0
  73. package/dist/commands/spec.js +35 -0
  74. package/dist/commands/spec.js.map +1 -0
  75. package/dist/commands/stats.d.ts +2 -0
  76. package/dist/commands/stats.js +80 -0
  77. package/dist/commands/stats.js.map +1 -0
  78. package/dist/commands/task-ops.d.ts +2 -0
  79. package/dist/commands/task-ops.js +406 -0
  80. package/dist/commands/task-ops.js.map +1 -0
  81. package/dist/config.d.ts +18 -0
  82. package/dist/config.js +338 -0
  83. package/dist/config.js.map +1 -0
  84. package/dist/cost.d.ts +30 -0
  85. package/dist/cost.js +167 -0
  86. package/dist/cost.js.map +1 -0
  87. package/dist/crash-recovery.d.ts +9 -0
  88. package/dist/crash-recovery.js +42 -0
  89. package/dist/crash-recovery.js.map +1 -0
  90. package/dist/diagnostic.d.ts +48 -0
  91. package/dist/diagnostic.js +328 -0
  92. package/dist/diagnostic.js.map +1 -0
  93. package/dist/doctor.d.ts +31 -0
  94. package/dist/doctor.js +225 -0
  95. package/dist/doctor.js.map +1 -0
  96. package/dist/drift.d.ts +11 -0
  97. package/dist/drift.js +57 -0
  98. package/dist/drift.js.map +1 -0
  99. package/dist/git-utils.d.ts +20 -0
  100. package/dist/git-utils.js +206 -0
  101. package/dist/git-utils.js.map +1 -0
  102. package/dist/gitlab.d.ts +54 -0
  103. package/dist/gitlab.js +101 -0
  104. package/dist/gitlab.js.map +1 -0
  105. package/dist/idea.d.ts +35 -0
  106. package/dist/idea.js +251 -0
  107. package/dist/idea.js.map +1 -0
  108. package/dist/import-resolution.d.ts +13 -0
  109. package/dist/import-resolution.js +111 -0
  110. package/dist/import-resolution.js.map +1 -0
  111. package/dist/inbox-renderer.d.ts +2 -0
  112. package/dist/inbox-renderer.js +67 -0
  113. package/dist/inbox-renderer.js.map +1 -0
  114. package/dist/init.d.ts +105 -0
  115. package/dist/init.js +235 -0
  116. package/dist/init.js.map +1 -0
  117. package/dist/llm-reviewer.d.ts +14 -0
  118. package/dist/llm-reviewer.js +109 -0
  119. package/dist/llm-reviewer.js.map +1 -0
  120. package/dist/lock.d.ts +26 -0
  121. package/dist/lock.js +76 -0
  122. package/dist/lock.js.map +1 -0
  123. package/dist/logger.d.ts +24 -0
  124. package/dist/logger.js +40 -0
  125. package/dist/logger.js.map +1 -0
  126. package/dist/math-utils.d.ts +2 -0
  127. package/dist/math-utils.js +7 -0
  128. package/dist/math-utils.js.map +1 -0
  129. package/dist/mechanical-review.d.ts +30 -0
  130. package/dist/mechanical-review.js +76 -0
  131. package/dist/mechanical-review.js.map +1 -0
  132. package/dist/merge.d.ts +83 -0
  133. package/dist/merge.js +363 -0
  134. package/dist/merge.js.map +1 -0
  135. package/dist/parallel.d.ts +35 -0
  136. package/dist/parallel.js +214 -0
  137. package/dist/parallel.js.map +1 -0
  138. package/dist/plan-validation.d.ts +19 -0
  139. package/dist/plan-validation.js +253 -0
  140. package/dist/plan-validation.js.map +1 -0
  141. package/dist/planner-prompt.d.ts +33 -0
  142. package/dist/planner-prompt.js +244 -0
  143. package/dist/planner-prompt.js.map +1 -0
  144. package/dist/planner.d.ts +29 -0
  145. package/dist/planner.js +511 -0
  146. package/dist/planner.js.map +1 -0
  147. package/dist/poller.d.ts +34 -0
  148. package/dist/poller.js +91 -0
  149. package/dist/poller.js.map +1 -0
  150. package/dist/progress.d.ts +34 -0
  151. package/dist/progress.js +122 -0
  152. package/dist/progress.js.map +1 -0
  153. package/dist/prompt-builder.d.ts +51 -0
  154. package/dist/prompt-builder.js +481 -0
  155. package/dist/prompt-builder.js.map +1 -0
  156. package/dist/provider.d.ts +14 -0
  157. package/dist/provider.js +278 -0
  158. package/dist/provider.js.map +1 -0
  159. package/dist/question-handler.d.ts +18 -0
  160. package/dist/question-handler.js +154 -0
  161. package/dist/question-handler.js.map +1 -0
  162. package/dist/question-triage.d.ts +31 -0
  163. package/dist/question-triage.js +175 -0
  164. package/dist/question-triage.js.map +1 -0
  165. package/dist/repo-detection.d.ts +8 -0
  166. package/dist/repo-detection.js +18 -0
  167. package/dist/repo-detection.js.map +1 -0
  168. package/dist/retry-context.d.ts +2 -0
  169. package/dist/retry-context.js +196 -0
  170. package/dist/retry-context.js.map +1 -0
  171. package/dist/router.d.ts +18 -0
  172. package/dist/router.js +137 -0
  173. package/dist/router.js.map +1 -0
  174. package/dist/run-artifact-types.d.ts +43 -0
  175. package/dist/run-artifact-types.js +2 -0
  176. package/dist/run-artifact-types.js.map +1 -0
  177. package/dist/run-summary.d.ts +14 -0
  178. package/dist/run-summary.js +347 -0
  179. package/dist/run-summary.js.map +1 -0
  180. package/dist/run-sync.d.ts +11 -0
  181. package/dist/run-sync.js +110 -0
  182. package/dist/run-sync.js.map +1 -0
  183. package/dist/run.d.ts +26 -0
  184. package/dist/run.js +150 -0
  185. package/dist/run.js.map +1 -0
  186. package/dist/scope-expansion.d.ts +10 -0
  187. package/dist/scope-expansion.js +117 -0
  188. package/dist/scope-expansion.js.map +1 -0
  189. package/dist/scope.d.ts +4 -0
  190. package/dist/scope.js +37 -0
  191. package/dist/scope.js.map +1 -0
  192. package/dist/scorecard.d.ts +18 -0
  193. package/dist/scorecard.js +128 -0
  194. package/dist/scorecard.js.map +1 -0
  195. package/dist/spec-templates.d.ts +2 -0
  196. package/dist/spec-templates.js +285 -0
  197. package/dist/spec-templates.js.map +1 -0
  198. package/dist/spec-validator.d.ts +8 -0
  199. package/dist/spec-validator.js +144 -0
  200. package/dist/spec-validator.js.map +1 -0
  201. package/dist/status.d.ts +68 -0
  202. package/dist/status.js +261 -0
  203. package/dist/status.js.map +1 -0
  204. package/dist/storage.d.ts +9 -0
  205. package/dist/storage.js +35 -0
  206. package/dist/storage.js.map +1 -0
  207. package/dist/task-executor-completion.d.ts +12 -0
  208. package/dist/task-executor-completion.js +67 -0
  209. package/dist/task-executor-completion.js.map +1 -0
  210. package/dist/task-executor-fallback.d.ts +20 -0
  211. package/dist/task-executor-fallback.js +12 -0
  212. package/dist/task-executor-fallback.js.map +1 -0
  213. package/dist/task-executor.d.ts +34 -0
  214. package/dist/task-executor.js +521 -0
  215. package/dist/task-executor.js.map +1 -0
  216. package/dist/task-graph.d.ts +11 -0
  217. package/dist/task-graph.js +226 -0
  218. package/dist/task-graph.js.map +1 -0
  219. package/dist/task-pipeline-helpers.d.ts +45 -0
  220. package/dist/task-pipeline-helpers.js +160 -0
  221. package/dist/task-pipeline-helpers.js.map +1 -0
  222. package/dist/task-review.d.ts +51 -0
  223. package/dist/task-review.js +410 -0
  224. package/dist/task-review.js.map +1 -0
  225. package/dist/transitions.d.ts +13 -0
  226. package/dist/transitions.js +104 -0
  227. package/dist/transitions.js.map +1 -0
  228. package/dist/types.d.ts +405 -0
  229. package/dist/types.js +101 -0
  230. package/dist/types.js.map +1 -0
  231. package/dist/utils.d.ts +1 -0
  232. package/dist/utils.js +23 -0
  233. package/dist/utils.js.map +1 -0
  234. package/dist/validation.d.ts +19 -0
  235. package/dist/validation.js +73 -0
  236. package/dist/validation.js.map +1 -0
  237. package/dist/worker-response.d.ts +12 -0
  238. package/dist/worker-response.js +60 -0
  239. package/dist/worker-response.js.map +1 -0
  240. package/dist/worker-runner.d.ts +19 -0
  241. package/dist/worker-runner.js +347 -0
  242. package/dist/worker-runner.js.map +1 -0
  243. package/dist/worktree-cleanup.d.ts +44 -0
  244. package/dist/worktree-cleanup.js +325 -0
  245. package/dist/worktree-cleanup.js.map +1 -0
  246. package/dist/worktree.d.ts +22 -0
  247. package/dist/worktree.js +213 -0
  248. package/dist/worktree.js.map +1 -0
  249. package/examples/spec.md +58 -0
  250. package/package.json +66 -0
package/dist/config.js ADDED
@@ -0,0 +1,338 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { delimiter, isAbsolute, join } from 'node:path';
3
+ import yaml from 'js-yaml';
4
+ import { EXECUTION_MODES, MODEL_TIERS, RETRY_CONTEXT_LEVELS, RISK_LEVELS, } from './types.js';
5
+ import { AGENTIC_BACKENDS, } from './agentic-types.js';
6
+ const DEFAULT_RETRY_CONTEXT = 'full';
7
+ const DEFAULT_EXECUTION_MODE = 'conservative';
8
+ const KNOWN_WORKER_MODE_KEYS = ['fresh_context', 'retry_with_context'];
9
+ const DEFAULT_AGENTIC_BACKEND = 'opencode';
10
+ const AGENTIC_BACKEND_DEFAULTS = {
11
+ opencode: {
12
+ command: 'opencode',
13
+ configPath: '.opencode.json',
14
+ installHint: 'Install OpenCode and ensure the `opencode` command is on PATH, or set defaults.agentic.backends.opencode.command in config.yml.',
15
+ },
16
+ 'claude-code': {
17
+ command: 'claude',
18
+ configPath: '.claude/settings.json',
19
+ installHint: 'Install Claude Code and ensure the `claude` command is on PATH, or set defaults.agentic.backends.claude-code.command in config.yml.',
20
+ },
21
+ };
22
+ export function loadConfig(configPath) {
23
+ const raw = readFileSync(configPath, 'utf-8');
24
+ const parsed = yaml.load(raw);
25
+ return validateConfig(parsed);
26
+ }
27
+ export function validateConfig(raw) {
28
+ if (typeof raw !== 'object' || raw === null) {
29
+ throw new Error('Config must be a YAML object');
30
+ }
31
+ const obj = raw;
32
+ if (!obj.providers || typeof obj.providers !== 'object')
33
+ throw new Error('Config must have a "providers" section');
34
+ if (!obj.routing_policy || typeof obj.routing_policy !== 'object')
35
+ throw new Error('Config must have a "routing_policy" section');
36
+ if (!obj.defaults || typeof obj.defaults !== 'object')
37
+ throw new Error('Config must have a "defaults" section');
38
+ const defaults = obj.defaults;
39
+ for (const numField of [
40
+ 'poll_interval_seconds',
41
+ 'api_timeout_seconds',
42
+ 'task_timeout_minutes',
43
+ 'max_concurrent_workers',
44
+ 'max_retries',
45
+ 'max_questions_per_task',
46
+ ]) {
47
+ if (numField in defaults && typeof defaults[numField] !== 'number')
48
+ throw new Error(`defaults.${numField} must be a number`);
49
+ }
50
+ if ('max_prompt_tokens' in defaults &&
51
+ defaults.max_prompt_tokens !== undefined &&
52
+ typeof defaults.max_prompt_tokens !== 'number') {
53
+ throw new Error('defaults.max_prompt_tokens must be a number');
54
+ }
55
+ if ('max_scope_files_per_task' in defaults &&
56
+ defaults.max_scope_files_per_task !== undefined &&
57
+ typeof defaults.max_scope_files_per_task !== 'number') {
58
+ throw new Error('defaults.max_scope_files_per_task must be a number');
59
+ }
60
+ if ('max_tasks_per_spec' in defaults &&
61
+ defaults.max_tasks_per_spec !== undefined &&
62
+ typeof defaults.max_tasks_per_spec !== 'number') {
63
+ throw new Error('defaults.max_tasks_per_spec must be a number');
64
+ }
65
+ if ('authorized_commenters' in defaults && defaults.authorized_commenters !== undefined) {
66
+ if (!Array.isArray(defaults.authorized_commenters))
67
+ throw new Error('defaults.authorized_commenters must be an array');
68
+ for (const item of defaults.authorized_commenters) {
69
+ if (typeof item !== 'string')
70
+ throw new Error('defaults.authorized_commenters must be an array of strings');
71
+ }
72
+ }
73
+ const normalizedDefaults = { ...defaults };
74
+ if ('retry_context' in defaults && defaults.retry_context !== undefined) {
75
+ if (typeof defaults.retry_context !== 'string')
76
+ throw new Error('defaults.retry_context must be a string');
77
+ if (!RETRY_CONTEXT_LEVELS.includes(defaults.retry_context)) {
78
+ console.warn(`Unknown defaults.retry_context value "${String(defaults.retry_context)}"; falling back to "${DEFAULT_RETRY_CONTEXT}"`);
79
+ normalizedDefaults.retry_context = DEFAULT_RETRY_CONTEXT;
80
+ }
81
+ }
82
+ if (normalizedDefaults.retry_context === undefined)
83
+ normalizedDefaults.retry_context = DEFAULT_RETRY_CONTEXT;
84
+ if ('execution_mode' in defaults && defaults.execution_mode !== undefined) {
85
+ if (typeof defaults.execution_mode !== 'string')
86
+ throw new Error('defaults.execution_mode must be a string');
87
+ if (!EXECUTION_MODES.includes(defaults.execution_mode)) {
88
+ console.warn(`Unknown defaults.execution_mode value "${String(defaults.execution_mode)}"; falling back to "${DEFAULT_EXECUTION_MODE}"`);
89
+ normalizedDefaults.execution_mode = DEFAULT_EXECUTION_MODE;
90
+ }
91
+ }
92
+ if (normalizedDefaults.execution_mode === undefined)
93
+ normalizedDefaults.execution_mode = DEFAULT_EXECUTION_MODE;
94
+ if ('worker_modes' in defaults && defaults.worker_modes !== undefined) {
95
+ if (typeof defaults.worker_modes !== 'object' ||
96
+ defaults.worker_modes === null ||
97
+ Array.isArray(defaults.worker_modes)) {
98
+ throw new Error('defaults.worker_modes must be an object');
99
+ }
100
+ const workerModes = defaults.worker_modes;
101
+ const normalizedWorkerModes = {};
102
+ for (const [key, value] of Object.entries(workerModes)) {
103
+ if (!KNOWN_WORKER_MODE_KEYS.includes(key)) {
104
+ console.warn(`Unknown defaults.worker_modes key "${key}"; ignoring`);
105
+ continue;
106
+ }
107
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
108
+ throw new Error(`defaults.worker_modes.${key} must be an object`);
109
+ }
110
+ const modeConfig = value;
111
+ if ('enabled' in modeConfig && modeConfig.enabled !== undefined && typeof modeConfig.enabled !== 'boolean') {
112
+ throw new Error(`defaults.worker_modes.${key}.enabled must be a boolean`);
113
+ }
114
+ normalizedWorkerModes[key] = { ...modeConfig };
115
+ }
116
+ normalizedDefaults.worker_modes = normalizedWorkerModes;
117
+ }
118
+ if ('agentic_fallback' in defaults && defaults.agentic_fallback !== undefined) {
119
+ normalizedDefaults.agentic_fallback = validateAgenticFallback(defaults.agentic_fallback);
120
+ }
121
+ if ('agentic' in defaults && defaults.agentic !== undefined) {
122
+ normalizedDefaults.agentic = validateAgenticConfig(defaults.agentic);
123
+ }
124
+ for (const [name, provider] of Object.entries(obj.providers)) {
125
+ if (typeof provider !== 'object' || provider === null)
126
+ throw new Error(`Provider "${name}" must be an object`);
127
+ const p = provider;
128
+ if (!p.api_key_env)
129
+ throw new Error(`Provider "${name}" missing api_key_env`);
130
+ if (!p.base_url)
131
+ throw new Error(`Provider "${name}" missing base_url`);
132
+ if (!p.models || typeof p.models !== 'object')
133
+ throw new Error(`Provider "${name}" must have at least one model`);
134
+ }
135
+ if ('models' in obj) {
136
+ if (typeof obj.models !== 'object' || obj.models === null)
137
+ throw new Error('Config "models" section must be an object');
138
+ for (const [id, entry] of Object.entries(obj.models)) {
139
+ if (typeof entry !== 'object' || entry === null)
140
+ throw new Error(`Model "${id}" must be an object`);
141
+ const modelEntry = entry;
142
+ if (typeof modelEntry.provider !== 'string' || modelEntry.provider.length === 0)
143
+ throw new Error(`Model "${id}" missing provider`);
144
+ if (!(modelEntry.provider in obj.providers))
145
+ throw new Error(`Model "${id}" references unknown provider "${String(modelEntry.provider)}"`);
146
+ if (typeof modelEntry.model !== 'string' || modelEntry.model.length === 0)
147
+ throw new Error(`Model "${id}" missing model`);
148
+ if (typeof modelEntry.tier !== 'string' || !MODEL_TIERS.includes(modelEntry.tier))
149
+ throw new Error(`Model "${id}" has invalid tier`);
150
+ if (typeof modelEntry.input_cost_per_mtok !== 'number' || typeof modelEntry.output_cost_per_mtok !== 'number')
151
+ throw new Error(`Model "${id}" missing cost fields`);
152
+ }
153
+ }
154
+ if ('routing_policy' in obj)
155
+ validateRoutingPolicy(obj.routing_policy);
156
+ return { ...obj, defaults: normalizedDefaults };
157
+ }
158
+ export function resolveModel(config, tierOrId) {
159
+ const exactMatch = config.models?.[tierOrId];
160
+ if (exactMatch)
161
+ return { id: tierOrId, ...exactMatch };
162
+ if (!config.models)
163
+ return null;
164
+ for (const [id, entry] of Object.entries(config.models)) {
165
+ if (entry.tier === tierOrId)
166
+ return { id, ...entry };
167
+ }
168
+ return null;
169
+ }
170
+ function validateRoutingPolicy(raw) {
171
+ if ('conservative_execution_task_types' in raw && raw.conservative_execution_task_types !== undefined) {
172
+ if (!Array.isArray(raw.conservative_execution_task_types))
173
+ throw new Error('routing_policy.conservative_execution_task_types must be an array of strings');
174
+ for (const value of raw.conservative_execution_task_types) {
175
+ if (typeof value !== 'string')
176
+ throw new Error('routing_policy.conservative_execution_task_types must be an array of strings');
177
+ }
178
+ }
179
+ }
180
+ function validateAgenticFallback(raw) {
181
+ if (typeof raw !== 'object' || raw === null || Array.isArray(raw))
182
+ throw new Error('defaults.agentic_fallback must be an object');
183
+ const fallback = raw;
184
+ if ('enabled' in fallback && fallback.enabled !== undefined && typeof fallback.enabled !== 'boolean')
185
+ throw new Error('defaults.agentic_fallback.enabled must be a boolean');
186
+ if ('task_types' in fallback && fallback.task_types !== undefined) {
187
+ if (!Array.isArray(fallback.task_types) || fallback.task_types.some((value) => typeof value !== 'string'))
188
+ throw new Error('defaults.agentic_fallback.task_types must be an array of strings');
189
+ }
190
+ if ('risk_levels' in fallback && fallback.risk_levels !== undefined) {
191
+ if (!Array.isArray(fallback.risk_levels))
192
+ throw new Error('defaults.agentic_fallback.risk_levels must be an array');
193
+ for (const value of fallback.risk_levels) {
194
+ if (typeof value !== 'string' || !RISK_LEVELS.includes(value))
195
+ throw new Error('defaults.agentic_fallback.risk_levels must contain valid risk levels');
196
+ }
197
+ }
198
+ return { ...fallback };
199
+ }
200
+ function validateAgenticConfig(raw) {
201
+ if (typeof raw !== 'object' || raw === null || Array.isArray(raw))
202
+ throw new Error('defaults.agentic must be an object');
203
+ const agentic = raw;
204
+ const normalized = {};
205
+ if ('default_backend' in agentic && agentic.default_backend !== undefined) {
206
+ if (typeof agentic.default_backend !== 'string')
207
+ throw new Error('defaults.agentic.default_backend must be a string');
208
+ if (!AGENTIC_BACKENDS.includes(agentic.default_backend))
209
+ throw new Error('defaults.agentic.default_backend must be a valid backend');
210
+ normalized.default_backend = agentic.default_backend;
211
+ }
212
+ if ('backends' in agentic && agentic.backends !== undefined) {
213
+ if (typeof agentic.backends !== 'object' || agentic.backends === null || Array.isArray(agentic.backends))
214
+ throw new Error('defaults.agentic.backends must be an object');
215
+ const backendsRaw = agentic.backends;
216
+ const backends = {};
217
+ for (const [key, value] of Object.entries(backendsRaw)) {
218
+ if (!AGENTIC_BACKENDS.includes(key)) {
219
+ console.warn(`Unknown defaults.agentic.backends key "${key}"; ignoring`);
220
+ continue;
221
+ }
222
+ if (typeof value !== 'object' || value === null || Array.isArray(value))
223
+ throw new Error(`defaults.agentic.backends.${key} must be an object`);
224
+ const backendConfig = value;
225
+ const normalizedBackend = {};
226
+ if ('enabled' in backendConfig && backendConfig.enabled !== undefined) {
227
+ if (typeof backendConfig.enabled !== 'boolean')
228
+ throw new Error(`defaults.agentic.backends.${key}.enabled must be a boolean`);
229
+ normalizedBackend.enabled = backendConfig.enabled;
230
+ }
231
+ if ('command' in backendConfig && backendConfig.command !== undefined) {
232
+ if (typeof backendConfig.command === 'string') {
233
+ normalizedBackend.command = [backendConfig.command];
234
+ }
235
+ else if (Array.isArray(backendConfig.command) &&
236
+ backendConfig.command.every((item) => typeof item === 'string')) {
237
+ normalizedBackend.command = [...backendConfig.command];
238
+ }
239
+ else {
240
+ throw new Error(`defaults.agentic.backends.${key}.command must be an array of strings`);
241
+ }
242
+ }
243
+ if ('transcript_format' in backendConfig && backendConfig.transcript_format !== undefined) {
244
+ if (backendConfig.transcript_format !== 'plain' && backendConfig.transcript_format !== 'jsonl')
245
+ throw new Error(`defaults.agentic.backends.${key}.transcript_format must be "plain" or "jsonl"`);
246
+ normalizedBackend.transcript_format = backendConfig.transcript_format;
247
+ }
248
+ backends[key] = normalizedBackend;
249
+ }
250
+ normalized.backends = backends;
251
+ }
252
+ if ('tiers' in agentic && agentic.tiers !== undefined) {
253
+ if (typeof agentic.tiers !== 'object' || agentic.tiers === null || Array.isArray(agentic.tiers)) {
254
+ throw new Error('defaults.agentic.tiers must be an object');
255
+ }
256
+ const tiersRaw = agentic.tiers;
257
+ const tiers = {};
258
+ for (const [key, value] of Object.entries(tiersRaw)) {
259
+ if (!MODEL_TIERS.includes(key)) {
260
+ console.warn(`Unknown defaults.agentic.tiers key "${key}"; ignoring`);
261
+ continue;
262
+ }
263
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
264
+ throw new Error(`defaults.agentic.tiers.${key} must be an object`);
265
+ }
266
+ const tierConfig = value;
267
+ if (typeof tierConfig.backend !== 'string' || !AGENTIC_BACKENDS.includes(tierConfig.backend)) {
268
+ throw new Error(`defaults.agentic.tiers.${key}.backend must be a valid backend`);
269
+ }
270
+ if ('model' in tierConfig && tierConfig.model !== undefined && typeof tierConfig.model !== 'string') {
271
+ throw new Error(`defaults.agentic.tiers.${key}.model must be a string`);
272
+ }
273
+ tiers[key] = {
274
+ backend: tierConfig.backend,
275
+ model: typeof tierConfig.model === 'string' ? tierConfig.model : undefined,
276
+ };
277
+ }
278
+ normalized.tiers = tiers;
279
+ }
280
+ return normalized;
281
+ }
282
+ function getAgenticConfig(config) {
283
+ return config?.defaults?.agentic;
284
+ }
285
+ export function getDefaultAgenticBackend(config) {
286
+ return getAgenticConfig(config)?.default_backend ?? DEFAULT_AGENTIC_BACKEND;
287
+ }
288
+ export function resolveAgenticBackend(backend, config, options) {
289
+ const backendConfig = getAgenticConfig(config)?.backends?.[backend];
290
+ const defaults = AGENTIC_BACKEND_DEFAULTS[backend];
291
+ const command = backendConfig?.command && backendConfig.command.length > 0 ? backendConfig.command[0] : defaults.command;
292
+ const commandSource = backendConfig?.command && backendConfig.command.length > 0 ? 'config' : 'default';
293
+ const configPath = defaults.configPath;
294
+ const configPathSource = configPath ? 'default' : 'none';
295
+ const available = isCommandAvailable(command, options?.pathEnv);
296
+ const resolvedConfigPath = configPath ? requireLikeResolve(options?.cwd ?? process.cwd(), configPath) : null;
297
+ const configExists = resolvedConfigPath ? existsSync(resolvedConfigPath) : null;
298
+ return {
299
+ backend,
300
+ available,
301
+ command,
302
+ commandSource,
303
+ configPath,
304
+ configPathSource,
305
+ resolvedConfigPath,
306
+ configExists,
307
+ installHint: defaults.installHint,
308
+ error: available
309
+ ? undefined
310
+ : `Selected backend "${backend}" is unavailable: command "${command}" was not found on PATH. ${defaults.installHint}`,
311
+ };
312
+ }
313
+ export function resolveAllAgenticBackends(config, options) {
314
+ return AGENTIC_BACKENDS.map((backend) => resolveAgenticBackend(backend, config, options));
315
+ }
316
+ export function ensureAgenticBackendAvailable(requirement, config, options) {
317
+ const resolution = resolveAgenticBackend(requirement.backend, config, options);
318
+ if (!resolution.available) {
319
+ const prefix = requirement.context ? `${requirement.context}: ` : '';
320
+ throw new Error(`${prefix}${resolution.error ?? `Selected backend "${requirement.backend}" is unavailable.`}`);
321
+ }
322
+ return resolution;
323
+ }
324
+ function requireLikeResolve(cwd, target) {
325
+ return isAbsolute(target) ? target : join(cwd, target);
326
+ }
327
+ function isCommandAvailable(command, pathEnv = process.env.PATH ?? '') {
328
+ if (command.trim() === '')
329
+ return false;
330
+ if (command.includes('/') || command.includes('\\'))
331
+ return existsSync(command);
332
+ for (const entry of pathEnv.split(delimiter).filter((value) => value.trim() !== '')) {
333
+ if (existsSync(`${entry.replace(/[\\/]$/, '')}/${command}`))
334
+ return true;
335
+ }
336
+ return false;
337
+ }
338
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
package/dist/cost.d.ts ADDED
@@ -0,0 +1,30 @@
1
+ import type { BudgetConfig, CostEntry, CostsFile, PricingConfig } from './types.js';
2
+ export declare const DEFAULT_BUDGET_WARNING_THRESHOLD_PCT = 80;
3
+ export declare const DEFAULT_MAX_RUN_RETRIES = 10;
4
+ export type BudgetStatus = 'ok' | 'warning' | 'exceeded';
5
+ export interface RetryBudgetResult {
6
+ status: BudgetStatus;
7
+ totalRetries: number;
8
+ taskRetries: number;
9
+ runRetryBudget: number;
10
+ taskRetryConsumers?: string[];
11
+ }
12
+ export interface BudgetResult {
13
+ status: BudgetStatus;
14
+ totalCost: number;
15
+ taskCost: number;
16
+ runBudget: number;
17
+ taskBudget: number;
18
+ action?: 'warn' | 'pause';
19
+ warningThresholdPct?: number;
20
+ }
21
+ export declare function estimateCost(pricing: PricingConfig, model: string, inputTokens: number, outputTokens: number): number;
22
+ export declare function recordCost(stwRoot: string, runId: string, taskId: string, entry: Omit<CostEntry, 'timestamp'>): CostsFile;
23
+ export declare function loadCosts(stwRoot: string, runId: string): CostsFile | null;
24
+ export declare function checkBudget(stwRoot: string, runId: string, taskId: string, config: {
25
+ budget?: BudgetConfig;
26
+ }): BudgetResult;
27
+ export declare function recordRetry(stwRoot: string, runId: string, taskId: string): CostsFile;
28
+ export declare function checkRetryBudget(stwRoot: string, runId: string, config: {
29
+ budget?: BudgetConfig;
30
+ }): RetryBudgetResult;
package/dist/cost.js ADDED
@@ -0,0 +1,167 @@
1
+ import { join } from 'node:path';
2
+ import { ensureDir, fileExists, readJson, runDir, writeJson } from './storage.js';
3
+ import { normalizeModelName } from './provider.js';
4
+ export const DEFAULT_BUDGET_WARNING_THRESHOLD_PCT = 80;
5
+ export const DEFAULT_MAX_RUN_RETRIES = 10;
6
+ export function estimateCost(pricing, model, inputTokens, outputTokens) {
7
+ const entry = pricing[model];
8
+ if (entry) {
9
+ const inputCost = (inputTokens / 1_000_000) * entry.input_cost_per_mtok;
10
+ const outputCost = (outputTokens / 1_000_000) * entry.output_cost_per_mtok;
11
+ return inputCost + outputCost;
12
+ }
13
+ if (model) {
14
+ const configuredModels = Object.keys(pricing);
15
+ const normalizedModel = normalizeModelName(model, configuredModels);
16
+ const normalizedEntry = pricing[normalizedModel];
17
+ if (normalizedEntry && normalizedModel !== model) {
18
+ const inputCost = (inputTokens / 1_000_000) * normalizedEntry.input_cost_per_mtok;
19
+ const outputCost = (outputTokens / 1_000_000) * normalizedEntry.output_cost_per_mtok;
20
+ return inputCost + outputCost;
21
+ }
22
+ if (normalizedModel === model && configuredModels.length > 0) {
23
+ console.warn(`[cost] No pricing entry for model "${model}" — cost recorded as 0`);
24
+ }
25
+ }
26
+ return 0;
27
+ }
28
+ export function recordCost(stwRoot, runId, taskId, entry) {
29
+ const costsPath = join(runDir(stwRoot, runId), 'costs.json');
30
+ let costsFile;
31
+ if (fileExists(costsPath)) {
32
+ costsFile = readJson(costsPath);
33
+ }
34
+ else {
35
+ ensureDir(runDir(stwRoot, runId));
36
+ costsFile = {
37
+ schema_version: 1,
38
+ run_id: runId,
39
+ costs: [],
40
+ total_cost_usd: 0,
41
+ task_costs: {},
42
+ };
43
+ }
44
+ const costEntry = {
45
+ ...entry,
46
+ timestamp: new Date().toISOString(),
47
+ };
48
+ costsFile.costs.push(costEntry);
49
+ costsFile.total_cost_usd = Number((costsFile.total_cost_usd + entry.cost_usd).toFixed(6));
50
+ costsFile.task_costs[taskId] = Number(((costsFile.task_costs[taskId] ?? 0) + entry.cost_usd).toFixed(6));
51
+ writeJson(costsPath, costsFile);
52
+ return costsFile;
53
+ }
54
+ export function loadCosts(stwRoot, runId) {
55
+ const costsPath = join(runDir(stwRoot, runId), 'costs.json');
56
+ if (!fileExists(costsPath)) {
57
+ return null;
58
+ }
59
+ return readJson(costsPath);
60
+ }
61
+ export function checkBudget(stwRoot, runId, taskId, config) {
62
+ const budget = config.budget;
63
+ if (!budget) {
64
+ return {
65
+ status: 'ok',
66
+ totalCost: 0,
67
+ taskCost: 0,
68
+ runBudget: Infinity,
69
+ taskBudget: Infinity,
70
+ warningThresholdPct: DEFAULT_BUDGET_WARNING_THRESHOLD_PCT,
71
+ };
72
+ }
73
+ const warningThresholdPct = Number.isFinite(budget.warn_threshold_pct) && budget.warn_threshold_pct > 0
74
+ ? budget.warn_threshold_pct
75
+ : DEFAULT_BUDGET_WARNING_THRESHOLD_PCT;
76
+ const costs = loadCosts(stwRoot, runId);
77
+ const totalCost = costs?.total_cost_usd ?? 0;
78
+ const taskCost = costs?.task_costs[taskId] ?? 0;
79
+ const runExceeded = totalCost >= budget.max_run_usd;
80
+ const taskExceeded = taskCost >= budget.max_task_usd;
81
+ if (runExceeded || taskExceeded) {
82
+ return {
83
+ status: 'exceeded',
84
+ totalCost,
85
+ taskCost,
86
+ runBudget: budget.max_run_usd,
87
+ taskBudget: budget.max_task_usd,
88
+ action: budget.on_exceed,
89
+ warningThresholdPct,
90
+ };
91
+ }
92
+ const effectiveWarningThresholdPct = warningThresholdPct >= DEFAULT_BUDGET_WARNING_THRESHOLD_PCT
93
+ ? warningThresholdPct
94
+ : DEFAULT_BUDGET_WARNING_THRESHOLD_PCT;
95
+ const runWarnThreshold = budget.max_run_usd * (effectiveWarningThresholdPct / 100);
96
+ const taskWarnThreshold = budget.max_task_usd * (effectiveWarningThresholdPct / 100);
97
+ if (totalCost >= runWarnThreshold || taskCost >= taskWarnThreshold) {
98
+ return {
99
+ status: 'warning',
100
+ totalCost,
101
+ taskCost,
102
+ runBudget: budget.max_run_usd,
103
+ taskBudget: budget.max_task_usd,
104
+ action: 'warn',
105
+ warningThresholdPct,
106
+ };
107
+ }
108
+ return {
109
+ status: 'ok',
110
+ totalCost,
111
+ taskCost,
112
+ runBudget: budget.max_run_usd,
113
+ taskBudget: budget.max_task_usd,
114
+ warningThresholdPct,
115
+ };
116
+ }
117
+ export function recordRetry(stwRoot, runId, taskId) {
118
+ const costsPath = join(runDir(stwRoot, runId), 'costs.json');
119
+ let costsFile;
120
+ if (fileExists(costsPath)) {
121
+ costsFile = readJson(costsPath);
122
+ }
123
+ else {
124
+ ensureDir(runDir(stwRoot, runId));
125
+ costsFile = {
126
+ schema_version: 1,
127
+ run_id: runId,
128
+ costs: [],
129
+ total_cost_usd: 0,
130
+ task_costs: {},
131
+ total_retries: 0,
132
+ task_retries: {},
133
+ };
134
+ }
135
+ costsFile.total_retries = (costsFile.total_retries ?? 0) + 1;
136
+ costsFile.task_retries = costsFile.task_retries ?? {};
137
+ costsFile.task_retries[taskId] = (costsFile.task_retries[taskId] ?? 0) + 1;
138
+ writeJson(costsPath, costsFile);
139
+ return costsFile;
140
+ }
141
+ export function checkRetryBudget(stwRoot, runId, config) {
142
+ const budget = config.budget;
143
+ const maxRunRetries = budget?.max_run_retries ?? DEFAULT_MAX_RUN_RETRIES;
144
+ const costs = loadCosts(stwRoot, runId);
145
+ const totalRetries = costs?.total_retries ?? 0;
146
+ const taskRetries = costs?.task_retries ?? {};
147
+ if (totalRetries >= maxRunRetries) {
148
+ const taskRetryConsumers = Object.entries(taskRetries)
149
+ .filter(([, count]) => count > 0)
150
+ .sort((a, b) => b[1] - a[1])
151
+ .map(([taskId, count]) => `${taskId}: ${count}`);
152
+ return {
153
+ status: 'exceeded',
154
+ totalRetries,
155
+ taskRetries: 0,
156
+ runRetryBudget: maxRunRetries,
157
+ taskRetryConsumers,
158
+ };
159
+ }
160
+ return {
161
+ status: 'ok',
162
+ totalRetries,
163
+ taskRetries: 0,
164
+ runRetryBudget: maxRunRetries,
165
+ };
166
+ }
167
+ //# sourceMappingURL=cost.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost.js","sourceRoot":"","sources":["../src/cost.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { TaskGraph, TaskState } from './types.js';
2
+ export interface RecoveredTask {
3
+ taskId: string;
4
+ previousState: TaskState;
5
+ }
6
+ export interface RecoveryResult {
7
+ recoveredTasks: RecoveredTask[];
8
+ }
9
+ export declare function recoverOrphanedTasks(stwRoot: string, runId: string, graph: TaskGraph): RecoveryResult;
@@ -0,0 +1,42 @@
1
+ import { unlinkSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { readTaskState } from './status.js';
4
+ import { taskDir } from './storage.js';
5
+ const NON_TERMINAL_STATES = [
6
+ 'working',
7
+ 'reviewing',
8
+ 'diagnosing',
9
+ 'retrying',
10
+ 'validating',
11
+ 'revision_requested',
12
+ 'question_pending',
13
+ ];
14
+ function deleteTaskFiles(td) {
15
+ const filesToDelete = ['status.json', 'state.json', 'claim.lock'];
16
+ for (const name of filesToDelete) {
17
+ const filePath = join(td, name);
18
+ try {
19
+ unlinkSync(filePath);
20
+ }
21
+ catch { }
22
+ }
23
+ }
24
+ export function recoverOrphanedTasks(stwRoot, runId, graph) {
25
+ const recoveredTasks = [];
26
+ for (const task of graph.tasks) {
27
+ const td = taskDir(stwRoot, runId, task.id);
28
+ const taskStateRecord = readTaskState(stwRoot, runId, task.id);
29
+ const state = taskStateRecord?.state ?? task.state;
30
+ if (!NON_TERMINAL_STATES.includes(state)) {
31
+ continue;
32
+ }
33
+ console.warn(`[crash-recovery] Task ${task.id} was in non-terminal state "${state}". Resetting to pending.`);
34
+ deleteTaskFiles(td);
35
+ recoveredTasks.push({
36
+ taskId: task.id,
37
+ previousState: state,
38
+ });
39
+ }
40
+ return { recoveredTasks };
41
+ }
42
+ //# sourceMappingURL=crash-recovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crash-recovery.js","sourceRoot":"","sources":["../src/crash-recovery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,MAAM,mBAAmB,GAAyB;IAChD,SAAS;IACT,WAAW;IACX,YAAY;IACZ,UAAU;IACV,YAAY;IACZ,oBAAoB;IACpB,kBAAkB;CACnB,CAAC;AAWF,SAAS,eAAe,CAAC,EAAU;IACjC,MAAM,aAAa,GAAG,CAAC,aAAa,EAAE,YAAY,EAAE,YAAY,CAAC,CAAC;IAClE,KAAK,MAAM,IAAI,IAAI,aAAa,EAAE,CAAC;QACjC,MAAM,QAAQ,GAAG,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QAChC,IAAI,CAAC;YACH,UAAU,CAAC,QAAQ,CAAC,CAAC;QACvB,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,OAAe,EAAE,KAAa,EAAE,KAAgB;IACnF,MAAM,cAAc,GAAoB,EAAE,CAAC;IAE3C,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAC/B,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;QAC5C,MAAM,eAAe,GAAG,aAAa,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;QAE/D,MAAM,KAAK,GAAc,eAAe,EAAE,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC;QAE9D,IAAI,CAAC,mBAAmB,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACzC,SAAS;QACX,CAAC;QAED,OAAO,CAAC,IAAI,CAAC,yBAAyB,IAAI,CAAC,EAAE,+BAA+B,KAAK,0BAA0B,CAAC,CAAC;QAE7G,eAAe,CAAC,EAAE,CAAC,CAAC;QAEpB,cAAc,CAAC,IAAI,CAAC;YAClB,MAAM,EAAE,IAAI,CAAC,EAAE;YACf,aAAa,EAAE,KAAK;SACrB,CAAC,CAAC;IACL,CAAC;IAED,OAAO,EAAE,cAAc,EAAE,CAAC;AAC5B,CAAC"}