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,47 @@
1
+ /**
2
+ * Per-service circuit breaker with dynamic cooldown from provider responses.
3
+ *
4
+ * Ported from the Python `coding_agent.router.CircuitBreaker` class.
5
+ * Uses `performance.now()` for monotonic seconds (equivalent to Python's
6
+ * `time.monotonic()`), independent of wall-clock adjustments.
7
+ */
8
+ export declare const CIRCUIT_BREAKER_THRESHOLD = 5;
9
+ export declare const CIRCUIT_BREAKER_DEFAULT_COOLDOWN_SEC = 300;
10
+ export interface CircuitBreakerStatus {
11
+ tripped: boolean;
12
+ failures: number;
13
+ cooldownRemainingSec?: number;
14
+ }
15
+ export interface CircuitBreakerSnapshot {
16
+ failures: number;
17
+ /** Wall-clock epoch ms when the current cooldown ends; null when not tripped. */
18
+ blockedUntilMs: number | null;
19
+ }
20
+ export declare class CircuitBreaker {
21
+ private failures;
22
+ private trippedAt;
23
+ private cooldown;
24
+ get isTripped(): boolean;
25
+ recordFailure(retryAfterSec?: number): void;
26
+ recordSuccess(): void;
27
+ /** Immediately trip — use on 429 or explicit rate-limit response. */
28
+ trip(retryAfterSec?: number): void;
29
+ cooldownRemaining(): number;
30
+ status(): CircuitBreakerStatus;
31
+ /**
32
+ * Wall-clock snapshot for cross-process persistence. `trippedAt`/`cooldown`
33
+ * are deliberately monotonic (performance.now(), immune to clock
34
+ * adjustments mid-run) so they can't be written to disk as-is; this
35
+ * converts the live state to an absolute deadline a future process (after
36
+ * a restart) can compare against its own Date.now().
37
+ */
38
+ snapshot(): CircuitBreakerSnapshot;
39
+ /**
40
+ * Hydrate from a snapshot persisted by a previous process. A
41
+ * `blockedUntilMs` already in the past is treated as expired, matching
42
+ * this class's own auto-reset-on-expiry semantics.
43
+ */
44
+ restore(snapshot: CircuitBreakerSnapshot): void;
45
+ private reset;
46
+ }
47
+ //# sourceMappingURL=circuit-breaker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"circuit-breaker.d.ts","sourceRoot":"","sources":["../src/circuit-breaker.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAC3C,eAAO,MAAM,oCAAoC,MAAM,CAAC;AAMxD,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,iFAAiF;IACjF,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,QAAQ,CAAgD;IAEhE,IAAI,SAAS,IAAI,OAAO,CASvB;IAED,aAAa,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI;IAW3C,aAAa,IAAI,IAAI;IAIrB,qEAAqE;IACrE,IAAI,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI;IAQlC,iBAAiB,IAAI,MAAM;IAO3B,MAAM,IAAI,oBAAoB;IAW9B;;;;;;OAMG;IACH,QAAQ,IAAI,sBAAsB;IAOlC;;;;OAIG;IACH,OAAO,CAAC,QAAQ,EAAE,sBAAsB,GAAG,IAAI;IAe/C,OAAO,CAAC,KAAK;CAKd"}
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Per-service circuit breaker with dynamic cooldown from provider responses.
3
+ *
4
+ * Ported from the Python `coding_agent.router.CircuitBreaker` class.
5
+ * Uses `performance.now()` for monotonic seconds (equivalent to Python's
6
+ * `time.monotonic()`), independent of wall-clock adjustments.
7
+ */
8
+ export const CIRCUIT_BREAKER_THRESHOLD = 5;
9
+ export const CIRCUIT_BREAKER_DEFAULT_COOLDOWN_SEC = 300;
10
+ function monotonicSec() {
11
+ return performance.now() / 1000;
12
+ }
13
+ export class CircuitBreaker {
14
+ failures = 0;
15
+ trippedAt = null;
16
+ cooldown = CIRCUIT_BREAKER_DEFAULT_COOLDOWN_SEC;
17
+ get isTripped() {
18
+ if (this.trippedAt === null) {
19
+ return false;
20
+ }
21
+ if (monotonicSec() - this.trippedAt >= this.cooldown) {
22
+ this.reset();
23
+ return false;
24
+ }
25
+ return true;
26
+ }
27
+ recordFailure(retryAfterSec) {
28
+ this.failures += 1;
29
+ if (this.failures >= CIRCUIT_BREAKER_THRESHOLD) {
30
+ this.trippedAt = monotonicSec();
31
+ this.cooldown =
32
+ retryAfterSec && retryAfterSec > 0
33
+ ? retryAfterSec
34
+ : CIRCUIT_BREAKER_DEFAULT_COOLDOWN_SEC;
35
+ }
36
+ }
37
+ recordSuccess() {
38
+ this.reset();
39
+ }
40
+ /** Immediately trip — use on 429 or explicit rate-limit response. */
41
+ trip(retryAfterSec) {
42
+ this.trippedAt = monotonicSec();
43
+ this.cooldown =
44
+ retryAfterSec && retryAfterSec > 0
45
+ ? retryAfterSec
46
+ : CIRCUIT_BREAKER_DEFAULT_COOLDOWN_SEC;
47
+ }
48
+ cooldownRemaining() {
49
+ if (!this.isTripped || this.trippedAt === null) {
50
+ return 0;
51
+ }
52
+ return Math.max(0, this.cooldown - (monotonicSec() - this.trippedAt));
53
+ }
54
+ status() {
55
+ if (!this.isTripped) {
56
+ return { tripped: false, failures: this.failures };
57
+ }
58
+ return {
59
+ tripped: true,
60
+ failures: this.failures,
61
+ cooldownRemainingSec: Math.round(this.cooldownRemaining() * 10) / 10,
62
+ };
63
+ }
64
+ /**
65
+ * Wall-clock snapshot for cross-process persistence. `trippedAt`/`cooldown`
66
+ * are deliberately monotonic (performance.now(), immune to clock
67
+ * adjustments mid-run) so they can't be written to disk as-is; this
68
+ * converts the live state to an absolute deadline a future process (after
69
+ * a restart) can compare against its own Date.now().
70
+ */
71
+ snapshot() {
72
+ if (!this.isTripped) {
73
+ return { failures: this.failures, blockedUntilMs: null };
74
+ }
75
+ return { failures: this.failures, blockedUntilMs: Date.now() + this.cooldownRemaining() * 1000 };
76
+ }
77
+ /**
78
+ * Hydrate from a snapshot persisted by a previous process. A
79
+ * `blockedUntilMs` already in the past is treated as expired, matching
80
+ * this class's own auto-reset-on-expiry semantics.
81
+ */
82
+ restore(snapshot) {
83
+ this.failures = snapshot.failures;
84
+ if (snapshot.blockedUntilMs === null) {
85
+ this.trippedAt = null;
86
+ return;
87
+ }
88
+ const remainingSec = (snapshot.blockedUntilMs - Date.now()) / 1000;
89
+ if (remainingSec <= 0) {
90
+ this.trippedAt = null;
91
+ return;
92
+ }
93
+ this.cooldown = remainingSec;
94
+ this.trippedAt = monotonicSec();
95
+ }
96
+ reset() {
97
+ this.failures = 0;
98
+ this.trippedAt = null;
99
+ this.cooldown = CIRCUIT_BREAKER_DEFAULT_COOLDOWN_SEC;
100
+ }
101
+ }
102
+ //# sourceMappingURL=circuit-breaker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"circuit-breaker.js","sourceRoot":"","sources":["../src/circuit-breaker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Configuration loading for harness-dispatch.
3
+ *
4
+ * Two entry points:
5
+ * loadConfig(path?) — if no path, auto-detects installed CLIs on PATH.
6
+ * If path points to a legacy YAML with a `services:`
7
+ * key, returns it verbatim. Otherwise merges minimal
8
+ * overrides onto auto-detected defaults.
9
+ * watchConfig(path) — poll the file's mtime once a second and reload on
10
+ * change. Returns {stop} to cancel the poller.
11
+ *
12
+ * All string values are scanned for ${ENV_VAR} references and replaced with
13
+ * the corresponding environment variable.
14
+ */
15
+ import type { CliProtocolConfig, RouterConfig } from "./types.js";
16
+ /** Named, selectable protocols — every harness in CLI_DEFAULTS that defines one, keyed by its harness name (see protocolFrom()'s string/`extends:` handling). */
17
+ export declare const PROTOCOL_PRESETS: Record<string, CliProtocolConfig>;
18
+ /** Injection seam for tests. Set via loadConfig({ whichFn }) if needed. */
19
+ export type WhichFn = (cmd: string) => Promise<string | null>;
20
+ export interface LoadConfigOptions {
21
+ /** Override `which` for tests — return null when a CLI is "not found". */
22
+ whichFn?: WhichFn;
23
+ }
24
+ /**
25
+ * Load a RouterConfig.
26
+ *
27
+ * If `path` is omitted (or the file doesn't exist), auto-detect CLIs on PATH
28
+ * and use built-in defaults. If the file has a top-level `services:` key,
29
+ * parse it in legacy mode. Otherwise auto-detect and merge `overrides`.
30
+ *
31
+ * Supports ${ENV_VAR} interpolation for any string value.
32
+ */
33
+ export declare function loadConfig(path?: string, opts?: LoadConfigOptions): Promise<RouterConfig>;
34
+ export interface ConfigWatcher {
35
+ stop(): void;
36
+ }
37
+ /**
38
+ * Poll the config file's mtime once per second. When it changes, reload and
39
+ * invoke `onChange`. The returned handle's stop() cancels the poller.
40
+ *
41
+ * Errors from reload are swallowed so a transient parse error doesn't kill
42
+ * the watcher — the next successful poll will pick up a repaired file.
43
+ */
44
+ export declare function watchConfig(path: string, onChange: (c: RouterConfig) => void, opts?: {
45
+ intervalMs?: number;
46
+ whichFn?: WhichFn;
47
+ }): ConfigWatcher;
48
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAWH,OAAO,KAAK,EAOV,iBAAiB,EAGjB,YAAY,EAOb,MAAM,YAAY,CAAC;AA+EpB,iKAAiK;AACjK,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAI9D,CAAC;AA4DF,2EAA2E;AAC3E,MAAM,MAAM,OAAO,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;AA09B9D,MAAM,WAAW,iBAAiB;IAChC,0EAA0E;IAC1E,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;GAQG;AACH,wBAAsB,UAAU,CAC9B,IAAI,CAAC,EAAE,MAAM,EACb,IAAI,GAAE,iBAAsB,GAC3B,OAAO,CAAC,YAAY,CAAC,CAwEvB;AAMD,MAAM,WAAW,aAAa;IAC5B,IAAI,IAAI,IAAI,CAAC;CACd;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,CAAC,CAAC,EAAE,YAAY,KAAK,IAAI,EACnC,IAAI,GAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,GACpD,aAAa,CAkCf"}