pi-harness-runtime 1.1.385 → 1.1.387

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 (147) hide show
  1. package/index.ts +42 -24
  2. package/package.json +3 -2
  3. package/packages/a2a-adapter/package.json +1 -1
  4. package/packages/agent-policy/package.json +1 -1
  5. package/packages/architecture-generator/package.json +1 -1
  6. package/packages/auth/package.json +1 -1
  7. package/packages/autonomous-refactor/package.json +1 -1
  8. package/packages/autonomous-runtime/package.json +1 -1
  9. package/packages/cache-strategy/package.json +1 -1
  10. package/packages/capability-registry/package.json +1 -1
  11. package/packages/checkpoint/package.json +1 -1
  12. package/packages/cli-plugin-sdk/package.json +1 -1
  13. package/packages/clipboard/package.json +1 -1
  14. package/packages/clipboard-plugin/package.json +1 -1
  15. package/packages/code-generation/package.json +1 -1
  16. package/packages/code-review/package.json +1 -1
  17. package/packages/codex-adapter/package.json +1 -1
  18. package/packages/codex-watcher/package.json +1 -1
  19. package/packages/config-capture/package.json +1 -1
  20. package/packages/connection-runtime/package.json +1 -1
  21. package/packages/context-compiler/package.json +1 -1
  22. package/packages/context-discovery/package.json +1 -1
  23. package/packages/context-manager/package.json +1 -1
  24. package/packages/contracts/package.json +1 -1
  25. package/packages/cookie-sanitizer/package.json +1 -1
  26. package/packages/cost-optimizer/package.json +1 -1
  27. package/packages/dependency-analyzer/package.json +1 -1
  28. package/packages/django-plugin/package.json +1 -1
  29. package/packages/doc-generator/package.json +1 -1
  30. package/packages/durable-review/package.json +1 -1
  31. package/packages/e2e-tester/package.json +1 -1
  32. package/packages/evaluation-engine/package.json +1 -1
  33. package/packages/evaluation-runner/package.json +1 -1
  34. package/packages/event-bus/package.json +1 -1
  35. package/packages/event-sink/package.json +1 -1
  36. package/packages/event-store/package.json +1 -1
  37. package/packages/experience-replay/package.json +1 -1
  38. package/packages/feedback-collector/package.json +1 -1
  39. package/packages/file-copy-helper/package.json +1 -1
  40. package/packages/framework-detector/package.json +1 -1
  41. package/packages/framework-plugin-sdk/package.json +1 -1
  42. package/packages/frappe-plugin/package.json +1 -1
  43. package/packages/generic-web-plugin/package.json +1 -1
  44. package/packages/health-monitor/package.json +1 -1
  45. package/packages/intent-analyzer/package.json +1 -1
  46. package/packages/jev-judge/dist/auto-continue.d.ts.map +1 -1
  47. package/packages/jev-judge/dist/auto-continue.js +26 -0
  48. package/packages/jev-judge/dist/auto-continue.js.map +1 -1
  49. package/packages/jev-judge/dist/environment-judge.d.ts.map +1 -1
  50. package/packages/jev-judge/dist/environment-judge.js +7 -4
  51. package/packages/jev-judge/dist/environment-judge.js.map +1 -1
  52. package/packages/jev-judge/dist/index.d.ts +87 -12
  53. package/packages/jev-judge/dist/index.d.ts.map +1 -1
  54. package/packages/jev-judge/dist/index.js +291 -75
  55. package/packages/jev-judge/dist/index.js.map +1 -1
  56. package/packages/jev-judge/dist/provider-error.d.ts +61 -0
  57. package/packages/jev-judge/dist/provider-error.d.ts.map +1 -0
  58. package/packages/jev-judge/dist/provider-error.js +165 -0
  59. package/packages/jev-judge/dist/provider-error.js.map +1 -0
  60. package/packages/jev-judge/dist/task-intake.d.ts.map +1 -1
  61. package/packages/jev-judge/dist/task-intake.js +3 -2
  62. package/packages/jev-judge/dist/task-intake.js.map +1 -1
  63. package/packages/jev-judge/dist/types.d.ts +56 -2
  64. package/packages/jev-judge/dist/types.d.ts.map +1 -1
  65. package/packages/jev-judge/dist/typesafe-provider.d.ts +26 -1
  66. package/packages/jev-judge/dist/typesafe-provider.d.ts.map +1 -1
  67. package/packages/jev-judge/dist/typesafe-provider.js +153 -62
  68. package/packages/jev-judge/dist/typesafe-provider.js.map +1 -1
  69. package/packages/jev-judge/dist/typesafe-request.d.ts +65 -0
  70. package/packages/jev-judge/dist/typesafe-request.d.ts.map +1 -0
  71. package/packages/jev-judge/dist/typesafe-request.js +138 -0
  72. package/packages/jev-judge/dist/typesafe-request.js.map +1 -0
  73. package/packages/jev-judge/package.json +1 -1
  74. package/packages/jev-judge/src/auto-continue.ts +26 -0
  75. package/packages/jev-judge/src/environment-judge.ts +7 -4
  76. package/packages/jev-judge/src/index.ts +617 -333
  77. package/packages/jev-judge/src/provider-error.ts +190 -0
  78. package/packages/jev-judge/src/task-intake.ts +3 -2
  79. package/packages/jev-judge/src/types.ts +62 -5
  80. package/packages/jev-judge/src/typesafe-provider.ts +452 -318
  81. package/packages/jev-judge/src/typesafe-request.ts +181 -0
  82. package/packages/jev-judge/tests/jev-provider-chain.test.ts +536 -0
  83. package/packages/jev-judge/tests/typesafe-provider.test.ts +504 -44
  84. package/packages/knowledge-graph/package.json +1 -1
  85. package/packages/knowledge-retrieval/package.json +1 -1
  86. package/packages/laravel-plugin/package.json +1 -1
  87. package/packages/learning-engine/package.json +1 -1
  88. package/packages/mcp-adapter/package.json +1 -1
  89. package/packages/memory-engine/package.json +1 -1
  90. package/packages/milestone-manager/package.json +1 -1
  91. package/packages/model-registry/package.json +1 -1
  92. package/packages/nextjs-plugin/package.json +1 -1
  93. package/packages/notification/package.json +1 -1
  94. package/packages/observability/package.json +1 -1
  95. package/packages/okf-indexer/package.json +1 -1
  96. package/packages/paperclip-integration/package.json +1 -1
  97. package/packages/performance-optimizer/package.json +1 -1
  98. package/packages/permission-mode/package.json +1 -1
  99. package/packages/privilege-broker/package.json +1 -1
  100. package/packages/project-analyzer/package.json +1 -1
  101. package/packages/project-bootstrap/package.json +1 -1
  102. package/packages/projection-engine/package.json +1 -1
  103. package/packages/prompt-compiler/package.json +1 -1
  104. package/packages/prompt-versioning/package.json +1 -1
  105. package/packages/provider-adapter-sdk/package.json +1 -1
  106. package/packages/provider-router/package.json +1 -1
  107. package/packages/provider-selector/package.json +1 -1
  108. package/packages/providers/package.json +1 -1
  109. package/packages/qdrant-skills/package.json +1 -1
  110. package/packages/quota-manager/package.json +1 -1
  111. package/packages/rate-limiter/package.json +1 -1
  112. package/packages/react-vite-plugin/package.json +1 -1
  113. package/packages/relay/package.json +1 -1
  114. package/packages/release-manager/package.json +1 -1
  115. package/packages/requirement-compiler/package.json +1 -1
  116. package/packages/runtime/package.json +1 -1
  117. package/packages/scheduler/package.json +1 -1
  118. package/packages/scheduler-adapter/package.json +1 -1
  119. package/packages/session/package.json +1 -1
  120. package/packages/session-api/package.json +1 -1
  121. package/packages/session-export/package.json +1 -1
  122. package/packages/shared-context/package.json +1 -1
  123. package/packages/skill-mcp-client/package.json +1 -1
  124. package/packages/skill-registry/package.json +1 -1
  125. package/packages/skills/package.json +1 -1
  126. package/packages/sprint-planner/package.json +1 -1
  127. package/packages/subscription-engine/package.json +1 -1
  128. package/packages/task-compiler/package.json +1 -1
  129. package/packages/telegram/package.json +1 -1
  130. package/packages/tencentdb-memory/package.json +1 -1
  131. package/packages/tencentdb-sync/package.json +1 -1
  132. package/packages/test-data-generator/package.json +1 -1
  133. package/packages/test-generator/package.json +1 -1
  134. package/packages/todo-bd-sync/package.json +1 -1
  135. package/packages/token-estimation/package.json +1 -1
  136. package/packages/token-optimizer/package.json +1 -1
  137. package/packages/trajectory/package.json +1 -1
  138. package/packages/tui/package.json +1 -1
  139. package/packages/types/package.json +1 -1
  140. package/packages/voice-api/package.json +1 -1
  141. package/packages/webmcp-tester/package.json +1 -1
  142. package/packages/wiki/package.json +1 -1
  143. package/packages/workflow-events/package.json +1 -1
  144. package/packages/workspace-scanner/package.json +1 -1
  145. package/packages/worktree/package.json +1 -1
  146. package/packages/write-review/package.json +1 -1
  147. package/scripts/run-root-tests.mjs +207 -0
@@ -0,0 +1,190 @@
1
+ /**
2
+ * Provider errors for the Jev judge.
3
+ *
4
+ * The judge can talk to more than one provider (TypeSafe direct API first,
5
+ * OpenRouter as a fallback). A failure therefore carries the information the
6
+ * fallback logic needs: which provider failed, whether the failure was an
7
+ * HTTP error, and whether ANOTHER provider could still serve the request.
8
+ */
9
+
10
+ import type { JevProviderName } from "./types.js";
11
+
12
+ export interface JevProviderErrorOptions {
13
+ provider: JevProviderName;
14
+ /** HTTP status, when the failure came from an HTTP response. */
15
+ status?: number;
16
+ /**
17
+ * True when another provider could still serve the request.
18
+ *
19
+ * Retryable: network failures, timeouts, rate limits, auth failures and
20
+ * 5xx. NOT retryable: 400/422 - those are contract errors in the request
21
+ * we build, and falling back would hide the bug.
22
+ */
23
+ retryable: boolean;
24
+ cause?: unknown;
25
+ }
26
+
27
+ /**
28
+ * Error raised by a single Jev provider call.
29
+ */
30
+ export class JevProviderError extends Error {
31
+ readonly provider: JevProviderName;
32
+ readonly status?: number;
33
+ readonly retryable: boolean;
34
+
35
+ constructor(message: string, options: JevProviderErrorOptions) {
36
+ super(message, options.cause !== undefined ? { cause: options.cause } : undefined);
37
+ this.name = "JevProviderError";
38
+ this.provider = options.provider;
39
+ this.status = options.status;
40
+ this.retryable = options.retryable;
41
+ }
42
+ }
43
+
44
+ /**
45
+ * HTTP statuses where another provider (or a later attempt) can still help.
46
+ */
47
+ export function isRetryableStatus(status: number): boolean {
48
+ if (status === 401 || status === 402 || status === 403) return true; // auth / quota
49
+ if (status === 408 || status === 429) return true; // timeout / rate limit
50
+ if (status >= 500) return true; // server side
51
+ return false;
52
+ }
53
+
54
+ /**
55
+ * Extract an HTTP status from an unknown error value.
56
+ */
57
+ export function extractStatus(error: unknown): number | undefined {
58
+ if (typeof error !== "object" || error === null) return undefined;
59
+ const status = (error as { status?: unknown }).status;
60
+ return typeof status === "number" ? status : undefined;
61
+ }
62
+
63
+ /**
64
+ * Error names of the known TRANSPORT failures: the request never reached a
65
+ * server that could reject it, so another provider can still serve it.
66
+ */
67
+ const TRANSPORT_ERROR_NAMES = new Set([
68
+ "AbortError",
69
+ "TimeoutError",
70
+ "APIConnectionError",
71
+ "APIConnectionTimeoutError",
72
+ "APITimeoutError",
73
+ "FetchError",
74
+ "ECONNABORTED",
75
+ "ECONNREFUSED",
76
+ "ECONNRESET",
77
+ "EAI_AGAIN",
78
+ "ENOTFOUND",
79
+ "ETIMEDOUT",
80
+ "UND_ERR_CONNECT_TIMEOUT",
81
+ "UND_ERR_HEADERS_TIMEOUT",
82
+ "UND_ERR_SOCKET",
83
+ ]);
84
+
85
+ /** Error codes of the known transport failures. */
86
+ const TRANSPORT_ERROR_CODES = new Set([
87
+ "ECONNABORTED",
88
+ "ECONNREFUSED",
89
+ "ECONNRESET",
90
+ "EAI_AGAIN",
91
+ "ENETDOWN",
92
+ "ENETUNREACH",
93
+ "EHOSTDOWN",
94
+ "EHOSTUNREACH",
95
+ "ENOTFOUND",
96
+ "EPROTO",
97
+ "EPIPE",
98
+ "ETIMEDOUT",
99
+ "ERR_STREAM_PREMATURE_CLOSE",
100
+ "UND_ERR_CONNECT_TIMEOUT",
101
+ "UND_ERR_HEADERS_TIMEOUT",
102
+ "UND_ERR_SOCKET",
103
+ // Certificate verification failures: the endpoint is unreachable for us.
104
+ "CERT_HAS_EXPIRED",
105
+ "SELF_SIGNED_CERT_IN_CHAIN",
106
+ "DEPTH_ZERO_SELF_SIGNED_CERT",
107
+ "UNABLE_TO_VERIFY_LEAF_SIGNATURE",
108
+ ]);
109
+
110
+ /**
111
+ * Prefixes of the error codes that always describe a transport failure.
112
+ *
113
+ * undici reports its own failures as UND_ERR_*, the TLS stack as ERR_TLS_*
114
+ * and the network stack as ECONN / EHOST / ENET.
115
+ */
116
+ const TRANSPORT_ERROR_CODE_PREFIXES = [
117
+ "UND_ERR_",
118
+ "ERR_TLS_",
119
+ "ECONN",
120
+ "EHOST",
121
+ "ENET",
122
+ "CERT_",
123
+ "SELF_SIGNED_CERT_",
124
+ "DEPTH_ZERO_",
125
+ "UNABLE_TO_VERIFY_",
126
+ ];
127
+
128
+ /**
129
+ * True when the error is a known transport failure (network, timeout, abort).
130
+ *
131
+ * Only these are retryable without an HTTP status: they never reached a
132
+ * server that could have rejected the request. Everything else without a
133
+ * status (a bug in our own code, a malformed response, a parse error) is NOT
134
+ * retryable - a contract bug must stay visible instead of being hidden behind
135
+ * a fallback to another provider.
136
+ */
137
+ export function isTransportError(error: unknown): boolean {
138
+ if (typeof error !== "object" || error === null) return false;
139
+
140
+ const named = error as {
141
+ name?: unknown;
142
+ code?: unknown;
143
+ cause?: unknown;
144
+ errors?: unknown;
145
+ };
146
+ if (typeof named.name === "string" && TRANSPORT_ERROR_NAMES.has(named.name)) return true;
147
+ if (typeof named.code === "string" && isTransportCode(named.code)) return true;
148
+
149
+ // An AggregateError collects the failures of several addresses (undici
150
+ // tries them one after the other) - one of them being a transport
151
+ // failure makes the whole attempt a transport failure.
152
+ if (Array.isArray(named.errors) && named.errors.some((entry) => isTransportError(entry))) {
153
+ return true;
154
+ }
155
+
156
+ // Node/undici wrap the real cause (e.g. ECONNREFUSED) one level deeper.
157
+ if (named.cause !== undefined && named.cause !== error) {
158
+ return isTransportError(named.cause);
159
+ }
160
+ return false;
161
+ }
162
+
163
+ /**
164
+ * True when the error code describes a transport failure.
165
+ */
166
+ function isTransportCode(code: string): boolean {
167
+ if (TRANSPORT_ERROR_CODES.has(code)) return true;
168
+ return TRANSPORT_ERROR_CODE_PREFIXES.some((prefix) => code.startsWith(prefix));
169
+ }
170
+
171
+ /**
172
+ * Wrap any thrown value into a JevProviderError.
173
+ *
174
+ * A failure with an HTTP status is retryable when the status says so (see
175
+ * `isRetryableStatus`). A failure WITHOUT a status is only retryable when it
176
+ * is a known transport failure (network, timeout, abort) - an unknown error
177
+ * is most likely a bug in our own code and must not disappear behind a
178
+ * fallback to another provider.
179
+ */
180
+ export function toProviderError(error: unknown, provider: JevProviderName): JevProviderError {
181
+ if (error instanceof JevProviderError) return error;
182
+ const status = extractStatus(error);
183
+ const message = error instanceof Error ? error.message : String(error);
184
+ return new JevProviderError(`${provider} provider failed: ${message}`, {
185
+ provider,
186
+ status,
187
+ retryable: status === undefined ? isTransportError(error) : isRetryableStatus(status),
188
+ cause: error,
189
+ });
190
+ }
@@ -62,8 +62,9 @@ export class TaskIntakeController {
62
62
  ...config,
63
63
  } as Required<TaskIntakeConfig>;
64
64
 
65
- // Initialize Jev if API key is available
66
- if (config.apiKey) {
65
+ // Initialize Jev when a provider is available (an explicit provider
66
+ // chain or a legacy single key)
67
+ if ((config.providers && config.providers.length > 0) || config.apiKey) {
67
68
  this.jev = new JevJudge(config as JevJudgeConfig);
68
69
  }
69
70
  }
@@ -18,15 +18,42 @@ export interface JevNoulQuestion {
18
18
  export interface JevChoiceQuestion<T extends string = string> {
19
19
  type: "choice";
20
20
  instructions: string;
21
- options: T[];
21
+ /**
22
+ * Candidate names.
23
+ *
24
+ * The TypeSafe API does not know about `options`: it expects `criteria` as a
25
+ * DICTIONARY of `name -> description` (a list is rejected by the API with
26
+ * 422 "Input should be a valid dictionary"). `options` stays the ergonomic
27
+ * way to name the candidates.
28
+ */
29
+ options?: T[];
30
+ /**
31
+ * Choice criteria. A dictionary is used as-is; a list of names is converted
32
+ * to a dictionary whose description is the name itself. Takes precedence
33
+ * over `options`.
34
+ */
35
+ criteria?: Record<string, string> | string[];
36
+ /** Optional description per option name (used together with `options`). */
37
+ optionDescriptions?: Record<string, string>;
22
38
  }
23
39
 
24
- // Score: Rate something 0-100
40
+ // Score: Rate something on a scale
25
41
  export interface JevScoreQuestion {
26
42
  type: "score";
27
43
  instructions: string;
44
+ /** Lower bound of the reported scale (default 0). */
28
45
  min?: number;
46
+ /** Upper bound of the reported scale (default 100). */
29
47
  max?: number;
48
+ /**
49
+ * Ordered rubric levels, lowest first.
50
+ *
51
+ * The TypeSafe API requires a rubric for score questions: the answer is the
52
+ * probability-weighted POSITION in this list (0 .. levels-1), never an
53
+ * arbitrary number. `min`/`max` only describe the scale the answer is
54
+ * reported on; when no rubric is given one is derived from them.
55
+ */
56
+ criteria?: string[];
30
57
  }
31
58
 
32
59
  // Any question type
@@ -76,6 +103,8 @@ export interface JevEvaluationResult<T extends string = string> {
76
103
  state: string;
77
104
  latencyMs: number;
78
105
  model: string;
106
+ /** The provider that served the request (when a provider chain is used). */
107
+ provider?: JevProviderName;
79
108
  }
80
109
 
81
110
  // Threshold-based action decision
@@ -86,11 +115,39 @@ export interface ThresholdDecision {
86
115
  action: "proceed" | "review" | "block";
87
116
  }
88
117
 
118
+ // Provider identity
119
+ export type JevProviderName = "typesafe" | "openrouter";
120
+
121
+ /**
122
+ * A provider bound to its OWN credential.
123
+ *
124
+ * Credentials are never shared between providers: a TypeSafe key is only ever
125
+ * sent to the TypeSafe API and an OpenRouter key only to OpenRouter.
126
+ */
127
+ export interface JevProviderConfig {
128
+ provider: JevProviderName;
129
+ apiKey: string;
130
+ baseUrl: string;
131
+ model: string;
132
+ }
133
+
89
134
  // Config
90
135
  export interface JevJudgeConfig {
91
- apiKey: string;
92
- baseUrl?: string; // Defaults to OpenRouter
93
- model?: string; // Defaults to typesafe/jev-1.13
136
+ /**
137
+ * Legacy single-provider key. Prefer `providers`: a bare key cannot be
138
+ * bound to a provider, which is how an OpenRouter key used to end up being
139
+ * sent to the TypeSafe API.
140
+ */
141
+ apiKey?: string;
142
+ baseUrl?: string; // Defaults to the TypeSafe API
143
+ model?: string; // Defaults to the provider's own model
144
+ /**
145
+ * Explicit provider chain, tried in order. A provider is only used for the
146
+ * next attempt when the previous one failed with a retryable error
147
+ * (network, timeout, rate limit, auth, 5xx) - never for a request contract
148
+ * error, which is a bug that must stay visible.
149
+ */
150
+ providers?: JevProviderConfig[];
94
151
  defaultThreshold?: number; // Default 0.7
95
152
  timeoutMs?: number;
96
153
  }