harness-dispatch 0.4.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 (157) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +582 -0
  3. package/config.default.yaml +397 -0
  4. package/data/coding_benchmarks.json +431 -0
  5. package/dist/auth.d.ts +9 -0
  6. package/dist/auth.d.ts.map +1 -0
  7. package/dist/auth.js +73 -0
  8. package/dist/auth.js.map +1 -0
  9. package/dist/billing.d.ts +7 -0
  10. package/dist/billing.d.ts.map +1 -0
  11. package/dist/billing.js +201 -0
  12. package/dist/billing.js.map +1 -0
  13. package/dist/bin.d.ts +6 -0
  14. package/dist/bin.d.ts.map +1 -0
  15. package/dist/bin.js +488 -0
  16. package/dist/bin.js.map +1 -0
  17. package/dist/breaker-store.d.ts +31 -0
  18. package/dist/breaker-store.d.ts.map +1 -0
  19. package/dist/breaker-store.js +103 -0
  20. package/dist/breaker-store.js.map +1 -0
  21. package/dist/circuit-breaker.d.ts +47 -0
  22. package/dist/circuit-breaker.d.ts.map +1 -0
  23. package/dist/circuit-breaker.js +102 -0
  24. package/dist/circuit-breaker.js.map +1 -0
  25. package/dist/config.d.ts +48 -0
  26. package/dist/config.d.ts.map +1 -0
  27. package/dist/config.js +1248 -0
  28. package/dist/config.js.map +1 -0
  29. package/dist/dashboard/live.d.ts +49 -0
  30. package/dist/dashboard/live.d.ts.map +1 -0
  31. package/dist/dashboard/live.js +149 -0
  32. package/dist/dashboard/live.js.map +1 -0
  33. package/dist/dispatch-log.d.ts +46 -0
  34. package/dist/dispatch-log.d.ts.map +1 -0
  35. package/dist/dispatch-log.js +89 -0
  36. package/dist/dispatch-log.js.map +1 -0
  37. package/dist/dispatchers/base.d.ts +55 -0
  38. package/dist/dispatchers/base.d.ts.map +1 -0
  39. package/dist/dispatchers/base.js +80 -0
  40. package/dist/dispatchers/base.js.map +1 -0
  41. package/dist/dispatchers/generic-cli.d.ts +30 -0
  42. package/dist/dispatchers/generic-cli.d.ts.map +1 -0
  43. package/dist/dispatchers/generic-cli.js +471 -0
  44. package/dist/dispatchers/generic-cli.js.map +1 -0
  45. package/dist/dispatchers/openai-compatible.d.ts +57 -0
  46. package/dist/dispatchers/openai-compatible.d.ts.map +1 -0
  47. package/dist/dispatchers/openai-compatible.js +662 -0
  48. package/dist/dispatchers/openai-compatible.js.map +1 -0
  49. package/dist/dispatchers/shared/kill-tree.d.ts +21 -0
  50. package/dist/dispatchers/shared/kill-tree.d.ts.map +1 -0
  51. package/dist/dispatchers/shared/kill-tree.js +35 -0
  52. package/dist/dispatchers/shared/kill-tree.js.map +1 -0
  53. package/dist/dispatchers/shared/rate-limit-headers.d.ts +22 -0
  54. package/dist/dispatchers/shared/rate-limit-headers.d.ts.map +1 -0
  55. package/dist/dispatchers/shared/rate-limit-headers.js +124 -0
  56. package/dist/dispatchers/shared/rate-limit-headers.js.map +1 -0
  57. package/dist/dispatchers/shared/stream-subprocess.d.ts +53 -0
  58. package/dist/dispatchers/shared/stream-subprocess.d.ts.map +1 -0
  59. package/dist/dispatchers/shared/stream-subprocess.js +274 -0
  60. package/dist/dispatchers/shared/stream-subprocess.js.map +1 -0
  61. package/dist/dispatchers/shared/subprocess.d.ts +25 -0
  62. package/dist/dispatchers/shared/subprocess.d.ts.map +1 -0
  63. package/dist/dispatchers/shared/subprocess.js +110 -0
  64. package/dist/dispatchers/shared/subprocess.js.map +1 -0
  65. package/dist/dispatchers/shared/which-available.d.ts +2 -0
  66. package/dist/dispatchers/shared/which-available.d.ts.map +1 -0
  67. package/dist/dispatchers/shared/which-available.js +8 -0
  68. package/dist/dispatchers/shared/which-available.js.map +1 -0
  69. package/dist/dispatchers/shared/windows-cmd.d.ts +38 -0
  70. package/dist/dispatchers/shared/windows-cmd.d.ts.map +1 -0
  71. package/dist/dispatchers/shared/windows-cmd.js +91 -0
  72. package/dist/dispatchers/shared/windows-cmd.js.map +1 -0
  73. package/dist/http/server.d.ts +15 -0
  74. package/dist/http/server.d.ts.map +1 -0
  75. package/dist/http/server.js +495 -0
  76. package/dist/http/server.js.map +1 -0
  77. package/dist/index.d.ts +27 -0
  78. package/dist/index.d.ts.map +1 -0
  79. package/dist/index.js +29 -0
  80. package/dist/index.js.map +1 -0
  81. package/dist/job-runner.d.ts +19 -0
  82. package/dist/job-runner.d.ts.map +1 -0
  83. package/dist/job-runner.js +42 -0
  84. package/dist/job-runner.js.map +1 -0
  85. package/dist/jobs.d.ts +116 -0
  86. package/dist/jobs.d.ts.map +1 -0
  87. package/dist/jobs.js +542 -0
  88. package/dist/jobs.js.map +1 -0
  89. package/dist/leaderboard.d.ts +62 -0
  90. package/dist/leaderboard.d.ts.map +1 -0
  91. package/dist/leaderboard.js +287 -0
  92. package/dist/leaderboard.js.map +1 -0
  93. package/dist/mcp/config-hot-reload.d.ts +64 -0
  94. package/dist/mcp/config-hot-reload.d.ts.map +1 -0
  95. package/dist/mcp/config-hot-reload.js +144 -0
  96. package/dist/mcp/config-hot-reload.js.map +1 -0
  97. package/dist/mcp/dispatcher-factory.d.ts +20 -0
  98. package/dist/mcp/dispatcher-factory.d.ts.map +1 -0
  99. package/dist/mcp/dispatcher-factory.js +30 -0
  100. package/dist/mcp/dispatcher-factory.js.map +1 -0
  101. package/dist/mcp/resources.d.ts +8 -0
  102. package/dist/mcp/resources.d.ts.map +1 -0
  103. package/dist/mcp/resources.js +45 -0
  104. package/dist/mcp/resources.js.map +1 -0
  105. package/dist/mcp/server.d.ts +36 -0
  106. package/dist/mcp/server.d.ts.map +1 -0
  107. package/dist/mcp/server.js +80 -0
  108. package/dist/mcp/server.js.map +1 -0
  109. package/dist/mcp/tools.d.ts +171 -0
  110. package/dist/mcp/tools.d.ts.map +1 -0
  111. package/dist/mcp/tools.js +658 -0
  112. package/dist/mcp/tools.js.map +1 -0
  113. package/dist/observability/index.d.ts +52 -0
  114. package/dist/observability/index.d.ts.map +1 -0
  115. package/dist/observability/index.js +111 -0
  116. package/dist/observability/index.js.map +1 -0
  117. package/dist/observability/spans.d.ts +47 -0
  118. package/dist/observability/spans.d.ts.map +1 -0
  119. package/dist/observability/spans.js +72 -0
  120. package/dist/observability/spans.js.map +1 -0
  121. package/dist/quota.d.ts +91 -0
  122. package/dist/quota.d.ts.map +1 -0
  123. package/dist/quota.js +331 -0
  124. package/dist/quota.js.map +1 -0
  125. package/dist/route-policy.d.ts +24 -0
  126. package/dist/route-policy.d.ts.map +1 -0
  127. package/dist/route-policy.js +92 -0
  128. package/dist/route-policy.js.map +1 -0
  129. package/dist/router.d.ts +162 -0
  130. package/dist/router.d.ts.map +1 -0
  131. package/dist/router.js +878 -0
  132. package/dist/router.js.map +1 -0
  133. package/dist/safety.d.ts +7 -0
  134. package/dist/safety.d.ts.map +1 -0
  135. package/dist/safety.js +33 -0
  136. package/dist/safety.js.map +1 -0
  137. package/dist/status.d.ts +100 -0
  138. package/dist/status.d.ts.map +1 -0
  139. package/dist/status.js +228 -0
  140. package/dist/status.js.map +1 -0
  141. package/dist/types.d.ts +402 -0
  142. package/dist/types.d.ts.map +1 -0
  143. package/dist/types.js +9 -0
  144. package/dist/types.js.map +1 -0
  145. package/dist/version.d.ts +2 -0
  146. package/dist/version.d.ts.map +1 -0
  147. package/dist/version.js +13 -0
  148. package/dist/version.js.map +1 -0
  149. package/dist/working-dir.d.ts +15 -0
  150. package/dist/working-dir.d.ts.map +1 -0
  151. package/dist/working-dir.js +22 -0
  152. package/dist/working-dir.js.map +1 -0
  153. package/dist/workspaces.d.ts +19 -0
  154. package/dist/workspaces.d.ts.map +1 -0
  155. package/dist/workspaces.js +352 -0
  156. package/dist/workspaces.js.map +1 -0
  157. package/package.json +96 -0
@@ -0,0 +1,402 @@
1
+ /**
2
+ * Core types for harness-dispatch.
3
+ *
4
+ * These are the cross-cutting types used by dispatchers, the router, the
5
+ * quota tracker, and the MCP surface. Downstream modules (R2/R3/R4) import
6
+ * from here.
7
+ */
8
+ export type TaskType = "execute" | "plan" | "review" | "local" | "";
9
+ export type ThinkingLevel = "low" | "medium" | "high";
10
+ export type SafetyProfile = "read_only" | "workspace_edit" | "full_auto";
11
+ export type RoutePolicy = "standard" | "local_only" | "approval_required" | "blocked";
12
+ export type BillingProvider = "anthropic" | "openai" | "cursor" | "google" | "local" | "custom";
13
+ export type BillingSurface = "claude_code" | "claude_agent_sdk" | "anthropic_api" | "codex_cli" | "codex_sdk" | "openai_api" | "cursor_agent_cli" | "antigravity_cli" | "gemini_api" | "vertex_ai" | "openai_compatible" | "local_endpoint" | "custom";
14
+ export type AuthSource = "product_login" | "api_key" | "oauth_session" | "local_network" | "configured_endpoint" | "unknown";
15
+ export type BillingKind = "local_compute" | "included_plan_usage" | "included_plan_then_flexible_credits" | "included_credit_then_optional_overage" | "included_usage_then_on_demand" | "metered_api" | "free_quota" | "unknown";
16
+ export type BillingConfidence = "documented" | "inferred" | "unknown" | "unsupported";
17
+ export type EndpointMode = "provider_cloud" | "direct_openai_compatible" | "harness_native_endpoint";
18
+ export type EndpointProvider = "ollama" | "lmstudio" | "openai_compatible" | "anthropic_gateway" | "gemini_proxy" | "custom";
19
+ export type WireProtocol = "openai_chat_completions" | "anthropic_messages" | "gemini_generate_content" | "provider_native" | "unknown";
20
+ export type WorkspacePolicy = "shared" | "shared_locked" | "git_worktree" | "copy";
21
+ export type WorkspaceChangeKind = "added" | "modified" | "deleted";
22
+ export interface WorkspaceFileChange {
23
+ path: string;
24
+ kind: WorkspaceChangeKind;
25
+ }
26
+ export interface WorkspaceRun {
27
+ policy: WorkspacePolicy;
28
+ originalWorkingDir: string;
29
+ effectiveWorkingDir: string;
30
+ isolated: boolean;
31
+ securityBoundary: "none" | "project_state" | "project_state_and_process_cwd";
32
+ workspaceRoot?: string;
33
+ changedFiles?: WorkspaceFileChange[];
34
+ diffSummary?: string;
35
+ cleanupHint?: string;
36
+ notes?: string[];
37
+ }
38
+ export interface RouteBilling {
39
+ provider: BillingProvider;
40
+ surface: BillingSurface;
41
+ authSource: AuthSource;
42
+ kind: BillingKind;
43
+ paidUsagePossible: boolean;
44
+ allowPaidUsage: boolean;
45
+ paidUsageRequiresOptIn: boolean | "unknown";
46
+ confidence: BillingConfidence;
47
+ notes?: string;
48
+ }
49
+ export interface RouteSkip {
50
+ route: string;
51
+ code: "disabled" | "no_dispatcher" | "unavailable" | "circuit_broken" | "paid_blocked" | "unknown_billing" | "route_policy" | "approval_required" | "safety_incompatible" | "workspace_isolation_required";
52
+ message: string;
53
+ }
54
+ export interface DispatchResult {
55
+ output: string;
56
+ service: string;
57
+ success: boolean;
58
+ error?: string;
59
+ rateLimited?: boolean;
60
+ retryAfter?: number;
61
+ rateLimitHeaders?: Record<string, string>;
62
+ durationMs?: number;
63
+ tokensUsed?: {
64
+ input: number;
65
+ output: number;
66
+ };
67
+ skippedRoutes?: RouteSkip[];
68
+ workspace?: WorkspaceRun;
69
+ }
70
+ export interface QuotaInfo {
71
+ service: string;
72
+ used?: number;
73
+ limit?: number;
74
+ remaining?: number;
75
+ resetAt?: string;
76
+ source: "headers" | "api" | "unknown";
77
+ }
78
+ /**
79
+ * One line-matching rule for `output.mode: "jsonl_stream"` (see below). A
80
+ * parsed JSON line is tested against `when` (every listed dotted field path
81
+ * must equal the given string); on match, `emit` says what to do with it.
82
+ * Rules are checked in order per line; a line can match more than one rule
83
+ * (e.g. a line can carry both a text field and a usage field).
84
+ */
85
+ export interface CliEventRule {
86
+ /** Dotted field path -> exact string it must equal, e.g. {"type": "thinking"}. */
87
+ when: Record<string, string>;
88
+ emit: "text" | "tool_use" | "thinking" | "usage" | "error";
89
+ /** For emit: "text" — dotted path to the text; becomes the run's output-so-far. */
90
+ textField?: string;
91
+ /** For emit: "tool_use". */
92
+ nameField?: string;
93
+ inputField?: string;
94
+ /** For emit: "thinking". */
95
+ chunkField?: string;
96
+ /** For emit: "usage" — dotted paths, checked in order, first present wins. */
97
+ inputTokenFields?: string[];
98
+ outputTokenFields?: string[];
99
+ /**
100
+ * For emit: "error" — dotted path to the human-readable error message
101
+ * (e.g. Codex's real `{"type":"error","message":"You've hit your usage
102
+ * limit..."}` frame). Without a rule for this, a structured error frame
103
+ * is silently invisible to the dispatcher — it falls through to raw
104
+ * stdout/stderr text heuristics, which lose the message entirely if
105
+ * stderr happens to carry unrelated CLI banner noise (confirmed
106
+ * 2026-07-24: Codex's real stderr is just "Reading additional input from
107
+ * stdin...", which was shadowing the actual JSON error in stdout).
108
+ */
109
+ messageField?: string;
110
+ }
111
+ /**
112
+ * Config-driven CLI invocation template — lets a subprocess-based CLI
113
+ * harness be added or redefined with zero bespoke TypeScript, the same way
114
+ * `endpoints:` already does for HTTP-based ones.
115
+ *
116
+ * `args` is a literal command-line argument list, written the same way
117
+ * you'd type it by hand. A handful of reserved `{{name}}` tokens are
118
+ * substituted (or expanded to zero or more real tokens) at dispatch time;
119
+ * everything else passes through verbatim:
120
+ *
121
+ * {{prompt}} the prompt text (one token) — omitted if `stdin: true`
122
+ * {{model}} [model.flag, value] if a model is set, else nothing
123
+ * {{safety}} safety[requested profile] (zero or more tokens)
124
+ * {{working_dir}} [workingDir.flag, dir, ...extraArgsWhenSet] if set, else nothing
125
+ * {{file_dirs}} [fileDirs.flag, dir] repeated once per included file's directory
126
+ * {{native_args}} endpointNativeArgs[endpoint_provider], only when this route
127
+ * is dispatched as endpoint_mode: harness_native_endpoint
128
+ *
129
+ * e.g. Claude Code's real invocation is just:
130
+ * args: ["-p", "{{prompt}}", "--output-format", "json", "{{safety}}", "{{model}}"]
131
+ */
132
+ export interface CliProtocolConfig {
133
+ args: string[];
134
+ /** Write the prompt to the child's stdin instead of substituting {{prompt}} into args. */
135
+ stdin?: boolean;
136
+ /** Omit if the CLI has no model-override flag. Falls back to the route's static `model:` when no per-call override is given. */
137
+ model?: {
138
+ flag: string;
139
+ };
140
+ /**
141
+ * Omit to rely on the subprocess's cwd only (no explicit flag, e.g. Claude
142
+ * Code). `extraArgsWhenSet` appends more static args only when workingDir
143
+ * is actually non-empty (e.g. Codex's `--skip-git-repo-check`).
144
+ * `fallback: "home"` substitutes the user's home directory when the
145
+ * caller passes an empty workingDir and this CLI has no "just use the
146
+ * current directory" default of its own (e.g. Cursor).
147
+ */
148
+ workingDir?: {
149
+ flag: string;
150
+ extraArgsWhenSet?: string[];
151
+ fallback?: "home";
152
+ };
153
+ /**
154
+ * Flag repeated once per unique file directory (e.g. Antigravity's
155
+ * `--add-dir <dir>`) — computed the same way for every harness: unique
156
+ * parent directories of absolute `files` entries, excluding workingDir
157
+ * itself. Omit if the CLI has no such concept.
158
+ */
159
+ fileDirs?: {
160
+ flag: string;
161
+ };
162
+ /** Args appended per requested safety profile (permission-mode flags etc.), via {{safety}}. */
163
+ safety?: Partial<Record<SafetyProfile, string[]>>;
164
+ /**
165
+ * Env var to set to the route's configured `api_key` when present (e.g.
166
+ * "CURSOR_API_KEY", "OPENAI_API_KEY"). If unset in config AND the var is
167
+ * already present in the parent environment, it's explicitly cleared for
168
+ * the child — matches the built-ins' "never leak an ambient key into a
169
+ * subscription-auth call" behavior.
170
+ */
171
+ apiKeyEnvVar?: string;
172
+ /** Header/bullet used when appending a file list to the prompt text. Omit fileListHeader to skip the append entirely. */
173
+ fileListHeader?: string;
174
+ fileListBullet?: string;
175
+ /** How to turn stdout into a DispatchResult. */
176
+ output: {
177
+ /**
178
+ * - "text": raw stdout is the output, verbatim.
179
+ * - "json_field": parse stdout as one JSON object once the process
180
+ * exits; `fields` (in priority order, dotted paths supported) picks
181
+ * which field holds the answer.
182
+ * - "jsonl_stream": each stdout line is parsed as JSON as it arrives.
183
+ * Without `eventRules`, falls back to concatenating `fields` from
184
+ * every line (a poor-man's approximation). WITH `eventRules`,
185
+ * supports real mid-run tool_use/thinking event surfacing and usage
186
+ * aggregation, declaratively (see CliEventRule).
187
+ */
188
+ mode: "text" | "json_field" | "jsonl_stream";
189
+ /** Candidate field names to check, in priority order, for json_field/jsonl_stream (dotted paths supported). */
190
+ fields?: string[];
191
+ /**
192
+ * Token-usage extraction for "text"/"json_field" modes (jsonl_stream
193
+ * uses eventRules' emit: "usage" instead).
194
+ */
195
+ usage?: {
196
+ input: string[];
197
+ output: string[];
198
+ };
199
+ /** jsonl_stream only — see CliEventRule. */
200
+ eventRules?: CliEventRule[];
201
+ /**
202
+ * Explicit error detection for "text"/"json_field" modes (jsonl_stream
203
+ * uses eventRules' emit: "error" instead) — a CLI can exit 0 while its
204
+ * JSON body reports an API-level failure (confirmed 2026-07-24: Claude
205
+ * Code's `is_error`/`api_error_status` fields on an otherwise-0-exit
206
+ * response). `field` is a dotted path to a boolean; when true, the
207
+ * dispatch is forced to success: false regardless of exit code or
208
+ * `successRequiresOutput`, with the message from `messageFields`
209
+ * (falls back to `fields` if omitted).
210
+ */
211
+ error?: {
212
+ field: string;
213
+ messageFields?: string[];
214
+ };
215
+ };
216
+ /**
217
+ * Default true (matches most CLIs, and Cursor specifically): success
218
+ * requires BOTH exitCode === 0 AND a non-empty parsed output — an exit-0
219
+ * run with nothing parseable is treated as a failure. Set false to match
220
+ * Claude Code / Codex / Antigravity's more lenient contract: success is
221
+ * exitCode === 0 alone, and the output falls back to raw stdout/stderr
222
+ * text when the configured parsing yields nothing.
223
+ */
224
+ successRequiresOutput?: boolean;
225
+ /**
226
+ * Extra args to prepend when this route is configured with
227
+ * `endpoint_mode: harness_native_endpoint` against a matching
228
+ * `endpoint_provider` (e.g. Codex's `--oss --local-provider ollama`) —
229
+ * config-dependent, not a fixed property of any particular harness.
230
+ */
231
+ endpointNativeArgs?: Partial<Record<EndpointProvider, string[]>>;
232
+ }
233
+ export interface ServiceConfig {
234
+ name: string;
235
+ enabled: boolean;
236
+ type: "cli" | "openai_compatible";
237
+ harness?: string;
238
+ command?: string;
239
+ apiKey?: string;
240
+ baseUrl?: string;
241
+ model?: string;
242
+ tier: number;
243
+ weight: number;
244
+ cliCapability: number;
245
+ leaderboardModel?: string;
246
+ thinkingLevel?: ThinkingLevel;
247
+ escalateModel?: string;
248
+ escalateOn: TaskType[];
249
+ capabilities: Partial<Record<"execute" | "plan" | "review", number>>;
250
+ /**
251
+ * Maximum output tokens the model can produce in a single dispatch.
252
+ * Callers (Planners, Workers, Reconcilers) use this to size work so it fits
253
+ * without mid-call truncation. A value of `undefined` means "unknown /
254
+ * assume the provider default" — callers that need to chunk conservatively
255
+ * should treat absence as a low bound.
256
+ */
257
+ maxOutputTokens?: number;
258
+ /**
259
+ * Context window (input + output) in tokens. Used by the
260
+ * `preferLargeContext` route hint and by planners sizing up prompt payloads.
261
+ * Advertised by the provider; may be model-specific when `escalateModel` is
262
+ * in effect — consult the resolved model at dispatch time.
263
+ */
264
+ maxInputTokens?: number;
265
+ provider?: BillingProvider;
266
+ surface?: BillingSurface;
267
+ authSource?: AuthSource;
268
+ billingKind?: BillingKind;
269
+ paidUsagePossible?: boolean;
270
+ allowPaidUsage?: boolean;
271
+ billingConfidence?: BillingConfidence;
272
+ billingNotes?: string;
273
+ safetyProfile?: SafetyProfile;
274
+ /**
275
+ * The safety level this route ACTUALLY runs at regardless of what's
276
+ * requested — a capability floor, not a preference. E.g. Cursor's print
277
+ * mode always has write+shell capability, so its shipped entry declares
278
+ * `effective_safety: full_auto` and the route is skipped for stricter
279
+ * requests. Declared in config (shipped or user), not hardcoded per
280
+ * harness anywhere in code.
281
+ */
282
+ effectiveSafety?: SafetyProfile;
283
+ /**
284
+ * Operator-declared known-good model ids for this route (`models:` in
285
+ * config) — surfaced verbatim in status/usage so a calling agent can pick
286
+ * one without guessing. Optional and advisory: hints.model is still
287
+ * forwarded even if it's not in this list.
288
+ */
289
+ models?: string[];
290
+ /**
291
+ * Free-text pointer to where this route's REAL model catalog lives
292
+ * (`model_hint:` in config) — a docs URL, a CLI command like
293
+ * `cursor-agent --list-models`, or "GET {base_url}/models". Surfaced in
294
+ * status/usage; declared per entry in the shipped config, not hardcoded
295
+ * per harness in code.
296
+ */
297
+ modelHint?: string;
298
+ endpointMode?: EndpointMode;
299
+ endpointProvider?: EndpointProvider;
300
+ wireProtocol?: WireProtocol;
301
+ workspacePolicy?: WorkspacePolicy;
302
+ /** Required when `harness: "generic"` — see CliProtocolConfig. Ignored otherwise. */
303
+ protocol?: CliProtocolConfig;
304
+ /**
305
+ * Per-service dispatch timeout override in milliseconds. Every dispatcher
306
+ * hard-codes its own default (10 minutes for CLI harnesses, 2 minutes for
307
+ * openai_compatible) with no way to raise it — a long-running review or
308
+ * audit routed to a CLI harness gets killed and its result discarded at
309
+ * exactly the default, regardless of how the caller invoked the task
310
+ * (`code` or `job`). Set this to raise (or lower) the ceiling for a
311
+ * specific route; a per-call `hints.timeoutMs` takes precedence over this.
312
+ */
313
+ timeoutMs?: number;
314
+ }
315
+ export interface RouterConfig {
316
+ services: Record<string, ServiceConfig>;
317
+ disabled?: readonly string[];
318
+ /**
319
+ * OpenTelemetry traces. OFF by default — purely operator-facing local
320
+ * observability (OTLP to localhost unless redirected); enable only if you
321
+ * run a collector. `HARNESS_DISPATCH_TELEMETRY=1` is the env equivalent.
322
+ */
323
+ telemetry?: {
324
+ enabled: boolean;
325
+ };
326
+ /** Local artifact retention. jobsDays: how long ~/.harness-dispatch/jobs entries live (default 7). */
327
+ retention?: {
328
+ jobsDays?: number;
329
+ };
330
+ /**
331
+ * Config entries that were silently ignored rather than failing to load —
332
+ * a disabled:/overrides: name that doesn't match any auto-detected route
333
+ * (e.g. left over from before the claude_code -> claude_code_cli-style
334
+ * rename), or a clis: entry with a missing/unrecognized harness or name.
335
+ * Surfaced by `doctor`/`configure` so a stale or typo'd config doesn't go
336
+ * unnoticed forever.
337
+ */
338
+ configWarnings?: readonly string[];
339
+ }
340
+ export interface RoutingDecision {
341
+ service: string;
342
+ tier: number;
343
+ quotaScore: number;
344
+ qualityScore: number;
345
+ cliCapability: number;
346
+ capabilityScore: number;
347
+ taskType: TaskType;
348
+ model: string | undefined;
349
+ /**
350
+ * Set only when hints.model was provided. true if it matched something
351
+ * this route statically declares (model/leaderboardModel/escalateModel/
352
+ * route name) — false if it was passed through to the dispatcher "blind"
353
+ * because nothing recognized it, which can still work (CLIs often accept
354
+ * arbitrary --model values) or can fail at dispatch time with the
355
+ * harness's own rejection. hints.model is unvalidated by design (see the
356
+ * `code` tool's own description) — this field is how a caller
357
+ * distinguishes "the router picked exactly what I asked for" from "I
358
+ * might have a typo" without guessing from `model` alone.
359
+ */
360
+ modelHintMatched?: boolean;
361
+ elo: number | undefined;
362
+ finalScore: number;
363
+ reason: string;
364
+ skippedRoutes?: RouteSkip[];
365
+ safetyProfile?: SafetyProfile;
366
+ effectiveSafetyProfile?: SafetyProfile;
367
+ billing?: RouteBilling;
368
+ workspacePolicy?: WorkspacePolicy;
369
+ }
370
+ export interface RouteHints {
371
+ model?: string;
372
+ service?: string;
373
+ preferLargeContext?: boolean;
374
+ taskType?: TaskType;
375
+ harness?: string;
376
+ safetyProfile?: SafetyProfile;
377
+ workspacePolicy?: WorkspacePolicy;
378
+ routePolicy?: RoutePolicy;
379
+ /** Per-call dispatch timeout override in milliseconds. See ServiceConfig.timeoutMs. */
380
+ timeoutMs?: number;
381
+ }
382
+ export type DispatcherEvent = {
383
+ type: "stdout";
384
+ chunk: string;
385
+ } | {
386
+ type: "stderr";
387
+ chunk: string;
388
+ } | {
389
+ type: "tool_use";
390
+ name: string;
391
+ input: unknown;
392
+ } | {
393
+ type: "thinking";
394
+ chunk: string;
395
+ } | {
396
+ type: "completion";
397
+ result: DispatchResult;
398
+ } | {
399
+ type: "error";
400
+ error: string;
401
+ };
402
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Core types for harness-dispatch.
3
+ *
4
+ * These are the cross-cutting types used by dispatchers, the router, the
5
+ * quota tracker, and the MCP surface. Downstream modules (R2/R3/R4) import
6
+ * from here.
7
+ */
8
+ export {};
9
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
@@ -0,0 +1,2 @@
1
+ export declare const VERSION: string;
2
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAaA,eAAO,MAAM,OAAO,QAAuB,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { createRequire } from "node:module";
2
+ const require = createRequire(import.meta.url);
3
+ function readPackageVersion() {
4
+ try {
5
+ const pkg = require("../package.json");
6
+ return typeof pkg.version === "string" ? pkg.version : "0.0.0";
7
+ }
8
+ catch {
9
+ return "0.0.0";
10
+ }
11
+ }
12
+ export const VERSION = readPackageVersion();
13
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAE/C,SAAS,kBAAkB;IACzB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,OAAO,CAAC,iBAAiB,CAA0B,CAAC;QAChE,OAAO,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;IACjE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC;IACjB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,OAAO,GAAG,kBAAkB,EAAE,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * `workingDir` is effectively required on every dispatch entry point (MCP
3
+ * tools, jobs, HTTP): when the caller omits it, the task runs in the router
4
+ * server's own process cwd, almost never the project the caller means. That
5
+ * silent wrong-directory execution was a review finding — this resolves the
6
+ * value the same way everywhere and reports back whether it was defaulted so
7
+ * callers can surface a visible warning instead of failing quietly.
8
+ */
9
+ export interface ResolvedWorkingDir {
10
+ workingDir: string;
11
+ defaulted: boolean;
12
+ }
13
+ export declare function resolveWorkingDir(input: string | undefined): ResolvedWorkingDir;
14
+ export declare function workingDirWarning(resolved: ResolvedWorkingDir): string | undefined;
15
+ //# sourceMappingURL=working-dir.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"working-dir.d.ts","sourceRoot":"","sources":["../src/working-dir.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,kBAAkB,CAK/E;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,kBAAkB,GAAG,MAAM,GAAG,SAAS,CAOlF"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * `workingDir` is effectively required on every dispatch entry point (MCP
3
+ * tools, jobs, HTTP): when the caller omits it, the task runs in the router
4
+ * server's own process cwd, almost never the project the caller means. That
5
+ * silent wrong-directory execution was a review finding — this resolves the
6
+ * value the same way everywhere and reports back whether it was defaulted so
7
+ * callers can surface a visible warning instead of failing quietly.
8
+ */
9
+ export function resolveWorkingDir(input) {
10
+ if (input !== undefined && input !== "") {
11
+ return { workingDir: input, defaulted: false };
12
+ }
13
+ return { workingDir: process.cwd(), defaulted: true };
14
+ }
15
+ export function workingDirWarning(resolved) {
16
+ if (!resolved.defaulted)
17
+ return undefined;
18
+ return (`workingDir was not provided — ran in the router server's own directory ` +
19
+ `(${resolved.workingDir}), which is almost certainly not the intended project. ` +
20
+ `Pass an absolute workingDir on the next call.`);
21
+ }
22
+ //# sourceMappingURL=working-dir.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"working-dir.js","sourceRoot":"","sources":["../src/working-dir.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAOH,MAAM,UAAU,iBAAiB,CAAC,KAAyB;IACzD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;QACxC,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;IACjD,CAAC;IACD,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;AACxD,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,QAA4B;IAC5D,IAAI,CAAC,QAAQ,CAAC,SAAS;QAAE,OAAO,SAAS,CAAC;IAC1C,OAAO,CACL,yEAAyE;QACzE,IAAI,QAAQ,CAAC,UAAU,yDAAyD;QAChF,+CAA+C,CAChD,CAAC;AACJ,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { DispatchResult, SafetyProfile, ServiceConfig, WorkspacePolicy } from "./types.js";
2
+ export interface PreparedWorkspace {
3
+ policy: WorkspacePolicy;
4
+ originalWorkingDir: string;
5
+ effectiveWorkingDir: string;
6
+ files: string[];
7
+ isolated: boolean;
8
+ workspaceRoot?: string;
9
+ finish(result: DispatchResult): Promise<DispatchResult>;
10
+ }
11
+ export declare function workspacePolicyFor(svc: ServiceConfig, safetyProfile: SafetyProfile | undefined, requestedPolicy?: WorkspacePolicy): WorkspacePolicy;
12
+ export declare function isIsolatedWorkspacePolicy(policy: WorkspacePolicy): boolean;
13
+ export declare function prepareWorkspace(opts: {
14
+ routeName: string;
15
+ policy: WorkspacePolicy;
16
+ workingDir: string;
17
+ files: string[];
18
+ }): Promise<PreparedWorkspace>;
19
+ //# sourceMappingURL=workspaces.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspaces.d.ts","sourceRoot":"","sources":["../src/workspaces.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EACb,aAAa,EAEb,eAAe,EAEhB,MAAM,YAAY,CAAC;AA2BpB,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,eAAe,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;CACzD;AAED,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,aAAa,EAClB,aAAa,EAAE,aAAa,GAAG,SAAS,EACxC,eAAe,CAAC,EAAE,eAAe,GAChC,eAAe,CAIjB;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAE1E;AA4UD,wBAAsB,gBAAgB,CAAC,IAAI,EAAE;IAC3C,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,eAAe,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAU7B"}