@zhivex-ai/harness 1.4.0-rc.8 → 1.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 (55) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +124 -72
  3. package/SECURITY.md +1 -1
  4. package/SUPPORT.md +2 -2
  5. package/dist/acp-cli.js +13 -12
  6. package/dist/{cli-3bzvq594.js → cli-2h37qyvg.js} +4 -4
  7. package/dist/{cli-entry-yqwa1943.js → cli-entry-20w6nh0k.js} +321 -16
  8. package/dist/{cli-entry-25xefnws.js → cli-entry-4ngptr62.js} +3 -3
  9. package/dist/{cli-entry-qav71mxw.js → cli-entry-w0hterjs.js} +1 -1
  10. package/dist/cli.js +2 -2
  11. package/dist/compat/code-support.js +8 -7
  12. package/dist/{config-pwbnze4g.js → config-j9624t6t.js} +1 -1
  13. package/dist/{config-depqpsae.js → config-qt69hkqj.js} +4 -3
  14. package/dist/engine/acp.js +12 -11
  15. package/dist/engine/client.js +11 -10
  16. package/dist/engine/desktop-providers-v1.js +2 -1
  17. package/dist/engine/desktop-state-v1.js +8 -7
  18. package/dist/engine/index.js +15 -14
  19. package/dist/engine/mcp-stdio-v1.js +7 -6
  20. package/dist/engine/protocol.js +12 -0
  21. package/dist/engine/service.js +12 -11
  22. package/dist/hostile-repository-demo.js +322 -17
  23. package/dist/{index-1k248k0w.js → index-5jhgatga.js} +5 -5
  24. package/dist/{index-pcn2bk8j.js → index-61gthdz6.js} +1 -1
  25. package/dist/{index-sbzvrpm7.js → index-6dft2vev.js} +2 -2
  26. package/dist/{index-09zphhwt.js → index-8zjmnyw5.js} +2 -2
  27. package/dist/{index-txrqqd2r.js → index-937cb7y8.js} +6 -6
  28. package/dist/{index-jdb1q8yn.js → index-bpc596v3.js} +15 -10
  29. package/dist/index-fm84men1.js +239 -0
  30. package/dist/{index-zmx264xy.js → index-m34q25jj.js} +2 -2
  31. package/dist/index-m49jx72n.js +220 -0
  32. package/dist/{index-9v72fpya.js → index-m82cfspw.js} +16 -10
  33. package/dist/{index-ngg2168h.js → index-nmjdwd4p.js} +1 -1
  34. package/dist/{index-w9pjt7td.js → index-pdmevfxv.js} +3 -3
  35. package/dist/{index-nqhnh1hz.js → index-pp474137.js} +5 -5
  36. package/dist/{index-vga76vmb.js → index-rkbf7dqg.js} +2 -2
  37. package/dist/{index-fny13znr.js → index-s2k2edts.js} +3 -3
  38. package/dist/{index-7y6b4yjx.js → index-tfzta544.js} +4 -4
  39. package/dist/index.js +15 -14
  40. package/dist/providers/vertex-auth.d.ts +5 -1
  41. package/dist/runtime/error-diagnostics.d.ts +8 -0
  42. package/dist/runtime/provider-transient.d.ts +33 -0
  43. package/dist/runtime/time-to-safe-fix.d.ts +8 -0
  44. package/dist/service-cli.js +12 -11
  45. package/dist/{service-client-cli-ra3yzvjg.js → service-client-cli-fn54ev6w.js} +3 -3
  46. package/dist/verify-historical-migrations.js +322 -17
  47. package/dist/zhx.js +2 -2
  48. package/docs/CLI.md +1 -1
  49. package/docs/CODE_RELEASE.md +38 -1
  50. package/docs/FIRST_USE.md +6 -6
  51. package/docs/PROJECT_MEMORY.md +1 -1
  52. package/evaluations/representative-assembly-matrix.json +10 -1
  53. package/examples/README.md +5 -5
  54. package/package.json +1 -1
  55. package/dist/index-8705zxpr.js +0 -145
@@ -62,7 +62,7 @@ import {
62
62
  timeToSafeFixLatencyStatistics,
63
63
  timeToSafeFixTaskSchema,
64
64
  verifyChangeEnvelope
65
- } from "../index-9v72fpya.js";
65
+ } from "../index-m82cfspw.js";
66
66
  import {
67
67
  HARNESS_STATE_BACKUP_MAX_BYTES,
68
68
  HARNESS_STATE_BACKUP_SCHEMA_VERSION,
@@ -73,7 +73,7 @@ import {
73
73
  inspectHarnessState,
74
74
  readHarnessStateBackup,
75
75
  stateBackupBundleSchema
76
- } from "../index-7y6b4yjx.js";
76
+ } from "../index-tfzta544.js";
77
77
  import {
78
78
  CLI_COMMAND_OPTION_CONTRACTS,
79
79
  CLI_OPTION_DEFINITIONS,
@@ -83,7 +83,7 @@ import {
83
83
  resolveHarnessModelRoutes,
84
84
  serializeHarnessModelRoutes,
85
85
  validateCliCommandOptions
86
- } from "../index-pcn2bk8j.js";
86
+ } from "../index-61gthdz6.js";
87
87
  import {
88
88
  harnessLocalCredentialsSchema,
89
89
  openHarnessActivityStore,
@@ -91,17 +91,17 @@ import {
91
91
  recoverHarnessLocalService,
92
92
  requestHarnessLocalService,
93
93
  startHarnessLocalService
94
- } from "../index-1k248k0w.js";
94
+ } from "../index-5jhgatga.js";
95
95
  import {
96
96
  createAcpConnection,
97
97
  serveAcpStdio
98
98
  } from "../index-3ah1f369.js";
99
99
  import {
100
100
  createHarnessClientAdapter
101
- } from "../index-txrqqd2r.js";
101
+ } from "../index-937cb7y8.js";
102
102
  import {
103
103
  openWorkspaceCheckpointStore
104
- } from "../index-sbzvrpm7.js";
104
+ } from "../index-6dft2vev.js";
105
105
  import {
106
106
  APPROVAL_HISTORY_KEY,
107
107
  DEFAULT_HARNESS_CONTEXT_MANIFEST,
@@ -149,7 +149,7 @@ import {
149
149
  runHarness,
150
150
  runHarnessReviewGroup,
151
151
  selectHarnessModel
152
- } from "../index-nqhnh1hz.js";
152
+ } from "../index-pp474137.js";
153
153
  import {
154
154
  HARNESS_OPERATIONS_SCHEMA_VERSION,
155
155
  HARNESS_PROJECT_MEMORY_LIMITS,
@@ -177,7 +177,7 @@ import {
177
177
  readTaskAcceptanceLedger,
178
178
  taskAcceptanceContractSchema,
179
179
  validateStateDirectory
180
- } from "../index-fny13znr.js";
180
+ } from "../index-s2k2edts.js";
181
181
  import {
182
182
  BUN_ENGINE_RANGE,
183
183
  HARNESS_MCP_CONFIG_SCHEMA_VERSION,
@@ -188,7 +188,7 @@ import {
188
188
  createHttpMcpClient,
189
189
  loadHarnessMcpConfiguration,
190
190
  normalizeHarnessMcpConfiguration
191
- } from "../index-w9pjt7td.js";
191
+ } from "../index-pdmevfxv.js";
192
192
  import {
193
193
  CliOciRuntimeAdapter,
194
194
  EDIT_CONTRACT_SCHEMA_VERSION,
@@ -222,7 +222,7 @@ import {
222
222
  taskCheckReceiptSchema,
223
223
  validateEditProposal,
224
224
  workspaceFilePathSchema
225
- } from "../index-zmx264xy.js";
225
+ } from "../index-m34q25jj.js";
226
226
  import {
227
227
  BUILTIN_PROVIDER_REGISTRATIONS,
228
228
  DEFAULT_ALLOWED_CHECKS,
@@ -247,8 +247,8 @@ import {
247
247
  providerAvailability,
248
248
  providerDescriptor,
249
249
  resolveHarnessConfig
250
- } from "../index-09zphhwt.js";
251
- import"../index-8705zxpr.js";
250
+ } from "../index-8zjmnyw5.js";
251
+ import"../index-m49jx72n.js";
252
252
  import"../index-xqxeypt5.js";
253
253
  import {
254
254
  CLI_EVENT_SCHEMA_VERSION,
@@ -260,7 +260,7 @@ import {
260
260
  serializeStreamResult,
261
261
  streamEventDocument,
262
262
  streamResultDocument
263
- } from "../index-ngg2168h.js";
263
+ } from "../index-nmjdwd4p.js";
264
264
  import {
265
265
  HARNESS_ERROR_CODES,
266
266
  HARNESS_ERROR_SCHEMA_VERSION,
@@ -273,7 +273,8 @@ import {
273
273
  HarnessWorkspaceError,
274
274
  harnessErrorDocument,
275
275
  normalizeHarnessError
276
- } from "../index-jdb1q8yn.js";
276
+ } from "../index-bpc596v3.js";
277
+ import"../index-fm84men1.js";
277
278
  import"../index-1bx83sw4.js";
278
279
  // src/persistence/project-memory-command.ts
279
280
  var HARNESS_MEMORY_COMMANDS = ["remember", "list", "read", "update", "forget", "suggest", "accept", "clear", "enable", "disable", "context"];
@@ -8,13 +8,14 @@ import {
8
8
  mcpResourcePlanSchema,
9
9
  prepareMcpWorkspaceSnapshot,
10
10
  recoverDockerMcpResources
11
- } from "../index-vga76vmb.js";
12
- import"../index-w9pjt7td.js";
13
- import"../index-zmx264xy.js";
14
- import"../index-09zphhwt.js";
15
- import"../index-8705zxpr.js";
11
+ } from "../index-rkbf7dqg.js";
12
+ import"../index-pdmevfxv.js";
13
+ import"../index-m34q25jj.js";
14
+ import"../index-8zjmnyw5.js";
15
+ import"../index-m49jx72n.js";
16
16
  import"../index-xqxeypt5.js";
17
- import"../index-jdb1q8yn.js";
17
+ import"../index-bpc596v3.js";
18
+ import"../index-fm84men1.js";
18
19
  import"../index-1bx83sw4.js";
19
20
  // src/persistence/mcp-reconciliation.ts
20
21
  import { z } from "zod";
@@ -54,6 +54,18 @@ var harnessClientRequestSchema = z.object({
54
54
  connectionId: id,
55
55
  command: harnessClientCommandSchema
56
56
  }).strict();
57
+ // src/runtime/provider-diagnostics.ts
58
+ import { z as z2 } from "zod";
59
+ var providerDiagnosticSchema = z2.strictObject({
60
+ reason: z2.enum(["previous_response_unavailable", "context_length_exceeded", "authentication", "payment_required", "permission", "rate_limit", "model_unavailable", "invalid_request", "server_error", "unknown"]),
61
+ parameter: z2.enum(["previous_response_id", "input", "messages", "tools", "model", "max_output_tokens", "max_tokens", "temperature", "other", "none"]),
62
+ bodyState: z2.enum(["parsed", "malformed", "too_large", "unavailable", "read_timeout"])
63
+ });
64
+
65
+ // src/runtime/provider-transient.ts
66
+ var SYMBOLIC = new Set(["ABORTED", "RESOURCE_EXHAUSTED", "UNAVAILABLE", "DEADLINE_EXCEEDED", "INTERNAL"]);
67
+ var STREAM_RESET_CODES = new Set(["ECONNRESET", "ECONNABORTED", "EPIPE", "ETIMEDOUT", "UND_ERR_SOCKET", "ERR_STREAM_PREMATURE_CLOSE"]);
68
+
57
69
  // src/runtime/errors.ts
58
70
  var providerStreamDiagnostic = (error) => {
59
71
  const seen = new Set;
@@ -5,18 +5,19 @@ import {
5
5
  recoverHarnessLocalService,
6
6
  requestHarnessLocalService,
7
7
  startHarnessLocalService
8
- } from "../index-1k248k0w.js";
9
- import"../index-txrqqd2r.js";
10
- import"../index-sbzvrpm7.js";
11
- import"../index-nqhnh1hz.js";
12
- import"../index-fny13znr.js";
13
- import"../index-w9pjt7td.js";
14
- import"../index-zmx264xy.js";
15
- import"../index-09zphhwt.js";
16
- import"../index-8705zxpr.js";
8
+ } from "../index-5jhgatga.js";
9
+ import"../index-937cb7y8.js";
10
+ import"../index-6dft2vev.js";
11
+ import"../index-pp474137.js";
12
+ import"../index-s2k2edts.js";
13
+ import"../index-pdmevfxv.js";
14
+ import"../index-m34q25jj.js";
15
+ import"../index-8zjmnyw5.js";
16
+ import"../index-m49jx72n.js";
17
17
  import"../index-xqxeypt5.js";
18
- import"../index-ngg2168h.js";
19
- import"../index-jdb1q8yn.js";
18
+ import"../index-nmjdwd4p.js";
19
+ import"../index-bpc596v3.js";
20
+ import"../index-fm84men1.js";
20
21
  import"../index-1bx83sw4.js";
21
22
  export {
22
23
  harnessLocalCredentialsSchema,
@@ -96,6 +96,8 @@ function providerDiagnostic(body, status) {
96
96
  reason = "permission";
97
97
  else if (["rate_limit_exceeded", "rate_limit_error", "RESOURCE_EXHAUSTED"].includes(code))
98
98
  reason = "rate_limit";
99
+ else if (["UNAVAILABLE", "DEADLINE_EXCEEDED", "ABORTED", "INTERNAL"].includes(code))
100
+ reason = "server_error";
99
101
  else if (["model_not_found", "model_not_available", "NOT_FOUND"].includes(code))
100
102
  reason = "model_unavailable";
101
103
  else if (["invalid_request_error", "INVALID_ARGUMENT"].includes(code) || status === 400 || status === 422)
@@ -106,6 +108,201 @@ function providerDiagnostic(body, status) {
106
108
  }
107
109
  }
108
110
 
111
+ // src/runtime/provider-transient.ts
112
+ var PROVIDER_STATUS_CATEGORIES = [
113
+ "ABORTED",
114
+ "RESOURCE_EXHAUSTED",
115
+ "UNAVAILABLE",
116
+ "DEADLINE_EXCEEDED",
117
+ "INTERNAL",
118
+ "STREAM_RESET"
119
+ ];
120
+ var VERTEX_TRANSIENT_ATTEMPTS = 3;
121
+ var TRANSIENT_HTTP = {
122
+ 408: "DEADLINE_EXCEEDED",
123
+ 409: "ABORTED",
124
+ 425: "UNAVAILABLE",
125
+ 429: "RESOURCE_EXHAUSTED",
126
+ 500: "INTERNAL",
127
+ 502: "UNAVAILABLE",
128
+ 503: "UNAVAILABLE",
129
+ 504: "DEADLINE_EXCEEDED"
130
+ };
131
+ var TRANSIENT_GRPC = {
132
+ 4: "DEADLINE_EXCEEDED",
133
+ 8: "RESOURCE_EXHAUSTED",
134
+ 10: "ABORTED",
135
+ 13: "INTERNAL",
136
+ 14: "UNAVAILABLE"
137
+ };
138
+ var CATEGORY_HTTP = {
139
+ ABORTED: 409,
140
+ RESOURCE_EXHAUSTED: 429,
141
+ UNAVAILABLE: 503,
142
+ DEADLINE_EXCEEDED: 504,
143
+ INTERNAL: 500,
144
+ STREAM_RESET: undefined
145
+ };
146
+ var SYMBOLIC = new Set(["ABORTED", "RESOURCE_EXHAUSTED", "UNAVAILABLE", "DEADLINE_EXCEEDED", "INTERNAL"]);
147
+ var STREAM_RESET_CODES = new Set(["ECONNRESET", "ECONNABORTED", "EPIPE", "ETIMEDOUT", "UND_ERR_SOCKET", "ERR_STREAM_PREMATURE_CLOSE"]);
148
+ var HTTP_IN_MESSAGE = /(?:^|[^\d])(408|409|425|429|500|502|503|504)(?=$|[^\d])/;
149
+ var STREAM_RESET_MESSAGE = /stream reset|RST_STREAM|ECONNRESET|socket hang up|ERR_STREAM_PREMATURE_CLOSE|UND_ERR_SOCKET/i;
150
+ var isProviderStatus = (value) => typeof value === "string" && PROVIDER_STATUS_CATEGORIES.includes(value);
151
+ var httpStatusValue = (value) => typeof value === "number" && Number.isInteger(value) && value >= 100 && value <= 599 ? value : undefined;
152
+ var definitiveClientStatus = (status) => status !== undefined && status >= 400 && status < 500 && TRANSIENT_HTTP[status] === undefined;
153
+ function readProviderFailureRecord(record, depth = 0) {
154
+ let retryable = false;
155
+ let clientError = false;
156
+ let httpStatus;
157
+ let providerStatus;
158
+ const noteHttp = (status) => {
159
+ if (status === undefined)
160
+ return;
161
+ httpStatus ??= status;
162
+ const category = TRANSIENT_HTTP[status];
163
+ if (category) {
164
+ retryable = true;
165
+ providerStatus ??= category;
166
+ } else if (status >= 400 && status < 500)
167
+ clientError = true;
168
+ };
169
+ const noteCategory = (category) => {
170
+ if (!category || clientError)
171
+ return;
172
+ retryable = true;
173
+ providerStatus ??= category;
174
+ if (httpStatus === undefined)
175
+ httpStatus = CATEGORY_HTTP[category];
176
+ };
177
+ const absorb = (value) => {
178
+ if (depth >= 2 || !value || typeof value !== "object" || value === record)
179
+ return;
180
+ const signals = readProviderFailureRecord(value, depth + 1);
181
+ noteHttp(signals.httpStatus);
182
+ noteCategory(signals.providerStatus);
183
+ };
184
+ noteHttp(httpStatusValue(record.status) ?? httpStatusValue(record.statusCode) ?? httpStatusValue(record.httpStatusCode));
185
+ if (typeof record.status === "string" && /^\d{3}$/.test(record.status))
186
+ noteHttp(Number(record.status));
187
+ if (typeof record.code === "number" && record.code >= 100 && record.code <= 599)
188
+ noteHttp(record.code);
189
+ if (typeof record.code === "number" && record.code >= 0 && record.code <= 16)
190
+ noteCategory(TRANSIENT_GRPC[record.code]);
191
+ if (typeof record.code === "string") {
192
+ if (STREAM_RESET_CODES.has(record.code))
193
+ noteCategory("STREAM_RESET");
194
+ else if (SYMBOLIC.has(record.code))
195
+ noteCategory(record.code);
196
+ }
197
+ if (typeof record.status === "string" && SYMBOLIC.has(record.status))
198
+ noteCategory(record.status);
199
+ if (isProviderStatus(record.providerStatus))
200
+ noteCategory(record.providerStatus);
201
+ if (record.diagnosticCode === "VERTEX_STREAM_TOOL_TRUNCATED" || record.reason === "stream_truncated")
202
+ noteCategory("STREAM_RESET");
203
+ if (record.code === "PROVIDER_UNAVAILABLE" && record.retryable === true)
204
+ retryable = true;
205
+ const body = record.responseBody ?? record.body;
206
+ if (!clientError) {
207
+ if (typeof body === "string")
208
+ noteCategory(categoryFromBody(body));
209
+ else
210
+ absorb(body);
211
+ absorb(record.error);
212
+ }
213
+ if (!retryable && !clientError && typeof record.message === "string") {
214
+ const match = record.message.match(HTTP_IN_MESSAGE);
215
+ if (match?.[1])
216
+ noteHttp(Number(match[1]));
217
+ else if (STREAM_RESET_MESSAGE.test(record.message))
218
+ noteCategory("STREAM_RESET");
219
+ }
220
+ if (httpStatus !== undefined && definitiveClientStatus(httpStatus))
221
+ return { retryable: false, httpStatus };
222
+ return { retryable, ...httpStatus !== undefined ? { httpStatus } : {}, ...providerStatus ? { providerStatus } : {} };
223
+ }
224
+ function categoryFromBody(body) {
225
+ if (Buffer.byteLength(body) > 8192)
226
+ return;
227
+ try {
228
+ const parsed = JSON.parse(body);
229
+ if (!parsed || typeof parsed !== "object")
230
+ return;
231
+ const detail = parsed.error;
232
+ const source = detail && typeof detail === "object" ? detail : parsed;
233
+ return readProviderFailureRecord(source).providerStatus;
234
+ } catch {
235
+ return;
236
+ }
237
+ }
238
+ function classifyProviderFailure(error) {
239
+ if (error && typeof error === "object") {
240
+ const top = readProviderFailureRecord(error);
241
+ if (top.httpStatus !== undefined && definitiveClientStatus(top.httpStatus))
242
+ return { retryable: false, httpStatus: top.httpStatus };
243
+ }
244
+ const seen = new Set;
245
+ let retryable = false;
246
+ let httpStatus;
247
+ let providerStatus;
248
+ const visit = (current, depth) => {
249
+ if (!current || typeof current !== "object" || depth > 5 || seen.has(current))
250
+ return;
251
+ seen.add(current);
252
+ const record = current;
253
+ const signals = readProviderFailureRecord(record);
254
+ httpStatus ??= signals.httpStatus;
255
+ providerStatus ??= signals.providerStatus;
256
+ if (httpStatus !== undefined && providerStatus === undefined)
257
+ providerStatus = TRANSIENT_HTTP[httpStatus];
258
+ if (record.retryable === false)
259
+ return;
260
+ if (signals.retryable)
261
+ retryable = true;
262
+ visit(record.cause, depth + 1);
263
+ if (record.error && typeof record.error === "object")
264
+ visit(record.error, depth + 1);
265
+ if (record.details && typeof record.details === "object")
266
+ visit(record.details, depth + 1);
267
+ if (Array.isArray(record.chain))
268
+ for (const entry of record.chain)
269
+ visit(entry, depth + 1);
270
+ };
271
+ visit(error, 0);
272
+ if (retryable && httpStatus === undefined && providerStatus)
273
+ httpStatus = CATEGORY_HTTP[providerStatus];
274
+ return { retryable, ...httpStatus !== undefined ? { httpStatus } : {}, ...providerStatus ? { providerStatus } : {} };
275
+ }
276
+ function isRetryableProviderFailure(error) {
277
+ return classifyProviderFailure(error).retryable;
278
+ }
279
+ function transientBackoffMs(attempt, baseMs = 250) {
280
+ const exponential = Math.min(baseMs * 2 ** Math.max(0, attempt), 1e4);
281
+ return exponential + Math.floor(Math.random() * exponential);
282
+ }
283
+ var thoughtOnlyText = (text) => {
284
+ try {
285
+ const parsed = JSON.parse(text);
286
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
287
+ return false;
288
+ const record = parsed;
289
+ return record.thought === true && Object.keys(record).every((key) => key === "thought" || key === "thoughtSignature");
290
+ } catch {
291
+ return false;
292
+ }
293
+ };
294
+ function isEmptyModelTurn(result) {
295
+ if (result.finishReason === "content-filter" || result.finishReason === "error")
296
+ return false;
297
+ if ((result.images?.length ?? 0) > 0 || (result.audio?.length ?? 0) > 0)
298
+ return false;
299
+ const parts = result.messages?.flatMap((message) => message.parts ?? []) ?? [];
300
+ if (parts.some((part) => part.type === "tool-call" || part.type === "image" || part.type === "audio"))
301
+ return false;
302
+ const texts = [result.text ?? "", ...parts.filter((part) => part.type === "text").map((part) => part.text ?? "")];
303
+ return texts.every((text) => text.trim().length === 0 || thoughtOnlyText(text.trim()));
304
+ }
305
+
109
306
  // src/providers/vertex-auth.ts
110
307
  var CLOUD_PLATFORM_SCOPE = "https://www.googleapis.com/auth/cloud-platform";
111
308
  function vertexRoute(env) {
@@ -155,13 +352,31 @@ class VertexAuthenticationError extends Error {
155
352
  this.name = "VertexAuthenticationError";
156
353
  }
157
354
  }
158
- function createVertexModel(model, env, createAuth) {
355
+ function createVertexModel(model, env, createAuth, retry) {
159
356
  const route = vertexRoute(env);
160
357
  const adapter = createVertex({
161
358
  ...route,
162
359
  getAccessToken: vertexTokenSource(env, route, createAuth)
163
360
  })(model);
164
- return wrapLanguageModel2(adapter, [{
361
+ const attempts = retry?.attempts ?? VERTEX_TRANSIENT_ATTEMPTS;
362
+ const delayFor = (input) => retry?.delayMs ?? ((attempt) => input.retryBackoffMs === 0 ? 0 : transientBackoffMs(attempt, input.retryBackoffMs ?? 250));
363
+ const generate = async (input) => withVertexAttempts(input.abortSignal, vertexAttemptBudget(input, attempts), delayFor(input), async () => {
364
+ try {
365
+ return await adapter.generate({ ...input, maxRetries: 0 });
366
+ } catch (error) {
367
+ throw safeVertexError(error);
368
+ }
369
+ }, (result) => !isEmptyModelTurn(result));
370
+ const innerStream = adapter.stream?.bind(adapter);
371
+ const retrying = innerStream ? {
372
+ ...adapter,
373
+ generate,
374
+ async stream(input) {
375
+ const events = await withVertexAttempts(input.abortSignal, vertexAttemptBudget(input, attempts), delayFor(input), () => collectVertexStream(() => innerStream({ ...input, maxRetries: 0 })), (events2) => !isEmptyVertexStream(events2));
376
+ return replayVertexStream(events);
377
+ }
378
+ } : { ...adapter, generate };
379
+ return wrapLanguageModel2(retrying, [{
165
380
  name: "harness-vertex-sanitized-errors",
166
381
  async wrapGenerate(_context, next) {
167
382
  try {
@@ -187,19 +402,109 @@ function createVertexModel(model, env, createAuth) {
187
402
  }
188
403
  }]);
189
404
  }
405
+ async function collectVertexStream(next) {
406
+ let stream;
407
+ try {
408
+ stream = await next();
409
+ } catch (error) {
410
+ throw safeVertexError(error);
411
+ }
412
+ const events = [];
413
+ try {
414
+ for await (const event of stream) {
415
+ if (event.type === "error")
416
+ throw safeVertexError(event.error);
417
+ events.push(event);
418
+ }
419
+ } catch (error) {
420
+ throw error instanceof Error && error.message.startsWith("Vertex request failed.") ? error : safeVertexError(error);
421
+ }
422
+ return events;
423
+ }
424
+ function isEmptyVertexStream(events) {
425
+ let text = "";
426
+ let finishReason;
427
+ let tools = false;
428
+ let media = false;
429
+ for (const event of events) {
430
+ if (event.type === "text-delta")
431
+ text += event.textDelta;
432
+ else if (event.type === "tool-call" || event.type === "tool-approval-request")
433
+ tools = true;
434
+ else if (event.type === "image-generation")
435
+ media = true;
436
+ else if (event.type === "finish")
437
+ finishReason = event.finishReason;
438
+ }
439
+ return isEmptyModelTurn({
440
+ text,
441
+ finishReason,
442
+ ...tools ? { messages: [{ parts: [{ type: "tool-call" }] }] } : {},
443
+ ...media ? { images: [{}] } : {}
444
+ });
445
+ }
446
+ function replayVertexStream(events) {
447
+ return async function* () {
448
+ yield* events;
449
+ }();
450
+ }
451
+ async function withVertexAttempts(abortSignal, attempts, delayMs, run, accept) {
452
+ let last;
453
+ for (let attempt = 0;attempt < attempts; attempt += 1) {
454
+ if (abortSignal?.aborted)
455
+ throw new DOMException("Vertex request cancelled.", "AbortError");
456
+ try {
457
+ const value = await run();
458
+ if (accept(value) || attempt === attempts - 1)
459
+ return value;
460
+ last = value;
461
+ } catch (error) {
462
+ const safe = error instanceof Error && (error.name === "AbortError" || error.message.startsWith("Vertex request failed.")) ? error : safeVertexError(error);
463
+ if (safe.name === "AbortError" || abortSignal?.aborted || attempt === attempts - 1 || !isRetryableProviderFailure(safe))
464
+ throw safe;
465
+ }
466
+ await sleep(delayMs(attempt));
467
+ }
468
+ return last;
469
+ }
470
+ var sleep = (ms) => ms > 0 ? new Promise((resolve) => setTimeout(resolve, ms)) : Promise.resolve();
471
+ function vertexAttemptBudget(input, fallback) {
472
+ const requested = [
473
+ typeof input.maxProviderRequests === "number" ? input.maxProviderRequests : undefined,
474
+ typeof input.maxRetries === "number" ? input.maxRetries + 1 : undefined
475
+ ].filter((value) => value !== undefined);
476
+ if (requested.length === 0)
477
+ return Math.max(1, fallback);
478
+ return Math.max(1, Math.min(...requested));
479
+ }
190
480
  function safeVertexError(error) {
191
481
  if (error instanceof VertexAuthenticationError)
192
482
  return error;
193
483
  const record = error && typeof error === "object" ? error : {};
194
484
  if (record.name === "AbortError")
195
485
  return new DOMException("Vertex request cancelled.", "AbortError");
196
- const status = typeof record.status === "number" && Number.isInteger(record.status) && record.status >= 100 && record.status <= 599 ? record.status : undefined;
486
+ const failure = classifyProviderFailure(error);
487
+ const body = providerBody(record.responseBody) ?? providerBody(record.body);
488
+ const preserved = providerDiagnosticSchema.safeParse(record.provider);
489
+ const provider = body !== undefined ? providerDiagnostic(body, failure.httpStatus) : preserved.success ? preserved.data : providerDiagnostic(undefined, failure.httpStatus);
197
490
  return Object.assign(new Error("Vertex request failed. Check the sanitized provider diagnosis."), {
198
- ...status ? { status } : {},
199
- provider: providerDiagnostic(record.responseBody ?? record.body, status),
200
- retryable: record.retryable === true
491
+ ...failure.httpStatus !== undefined ? { status: failure.httpStatus } : {},
492
+ ...failure.providerStatus ? { providerStatus: failure.providerStatus } : {},
493
+ provider,
494
+ retryable: failure.retryable
201
495
  });
202
496
  }
497
+ function providerBody(value) {
498
+ if (typeof value === "string")
499
+ return value;
500
+ if (!value || typeof value !== "object")
501
+ return;
502
+ try {
503
+ return JSON.stringify(value).slice(0, 8192);
504
+ } catch {
505
+ return;
506
+ }
507
+ }
203
508
 
204
509
  // src/providers/qwen-hosted-policy.ts
205
510
  import { wrapLanguageModel as wrapLanguageModel3 } from "@zhivex-ai/core";
@@ -1921,13 +2226,6 @@ class HarnessExecutionError extends HarnessError {
1921
2226
  this.name = "HarnessExecutionError";
1922
2227
  }
1923
2228
  }
1924
- var numericStatuses = (error) => {
1925
- if (!error || typeof error !== "object")
1926
- return;
1927
- const record = error;
1928
- const values = [record.status, record.statusCode].filter((value) => typeof value === "number" && Number.isSafeInteger(value));
1929
- return values.length > 0 ? values : undefined;
1930
- };
1931
2229
  var normalizeHarnessError = (error) => {
1932
2230
  const diagnostic = providerStreamDiagnostic(error);
1933
2231
  if (diagnostic)
@@ -1935,9 +2233,16 @@ var normalizeHarnessError = (error) => {
1935
2233
  if (error instanceof HarnessError)
1936
2234
  return error;
1937
2235
  const message = error instanceof Error ? error.message : "Harness execution failed.";
1938
- const statuses = numericStatuses(error) ?? [];
1939
- if (statuses.some((status) => status === 429 || status >= 500 && status <= 599)) {
1940
- return new HarnessProviderError(message, { cause: error, retryable: true });
2236
+ const failure = classifyProviderFailure(error);
2237
+ if (failure.retryable) {
2238
+ const record = error && typeof error === "object" ? error : {};
2239
+ const body = typeof record.responseBody === "string" ? record.responseBody : typeof record.body === "string" ? record.body : undefined;
2240
+ const providerError = new HarnessProviderError("Provider request failed.", { cause: error, retryable: true });
2241
+ return Object.assign(providerError, {
2242
+ ...failure.httpStatus !== undefined ? { status: failure.httpStatus } : {},
2243
+ ...failure.providerStatus ? { providerStatus: failure.providerStatus } : {},
2244
+ provider: providerDiagnostic(body, failure.httpStatus)
2245
+ });
1941
2246
  }
1942
2247
  const name = error && typeof error === "object" && typeof error.name === "string" ? error.name : "";
1943
2248
  const code = error && typeof error === "object" && typeof error.code === "string" ? error.code : "";
@@ -13920,7 +14225,7 @@ import { z as z32 } from "zod";
13920
14225
  // package.json
13921
14226
  var package_default = {
13922
14227
  name: "@zhivex-ai/harness",
13923
- version: "1.4.0-rc.8",
14228
+ version: "1.4.0",
13924
14229
  description: "Governed, provider-portable runtime for coding agents with durable approvals and isolated repository execution.",
13925
14230
  type: "module",
13926
14231
  license: "MIT",
@@ -1,19 +1,19 @@
1
1
  import {
2
2
  createHarnessClientAdapter
3
- } from "./index-txrqqd2r.js";
3
+ } from "./index-937cb7y8.js";
4
4
  import {
5
5
  harnessPolicyDecisionEventSchema
6
- } from "./index-nqhnh1hz.js";
6
+ } from "./index-pp474137.js";
7
7
  import {
8
8
  openCliSessionStore
9
- } from "./index-fny13znr.js";
9
+ } from "./index-s2k2edts.js";
10
10
  import {
11
11
  SqliteDatabase
12
- } from "./index-zmx264xy.js";
12
+ } from "./index-m34q25jj.js";
13
13
  import {
14
14
  harnessClientRequestSchema,
15
15
  streamEventDocument
16
- } from "./index-ngg2168h.js";
16
+ } from "./index-nmjdwd4p.js";
17
17
  import {
18
18
  __require
19
19
  } from "./index-1bx83sw4.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  DEFAULT_PROVIDER_REGISTRY,
3
3
  HARNESS_SUBAGENT_PROFILES
4
- } from "./index-09zphhwt.js";
4
+ } from "./index-8zjmnyw5.js";
5
5
 
6
6
  // src/providers/routing.ts
7
7
  var routeError = (value) => new Error(`Invalid route: ${value}. Use <profile>=<provider>[:<model>].`);
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  TERMINAL_SESSION_RUN_STATUSES
3
- } from "./index-fny13znr.js";
3
+ } from "./index-s2k2edts.js";
4
4
  import {
5
5
  SqliteDatabase,
6
6
  createEditProposal,
@@ -9,7 +9,7 @@ import {
9
9
  statRegularFileNoFollow,
10
10
  withWorkspaceMutation,
11
11
  workspaceFilePathSchema
12
- } from "./index-zmx264xy.js";
12
+ } from "./index-m34q25jj.js";
13
13
 
14
14
  // src/persistence/workspace-checkpoints.ts
15
15
  import { createHash, randomUUID } from "node:crypto";
@@ -2,14 +2,14 @@ import {
2
2
  VERTEX_ENVIRONMENT,
3
3
  createVertexModel,
4
4
  vertexConfigured
5
- } from "./index-8705zxpr.js";
5
+ } from "./index-m49jx72n.js";
6
6
  import {
7
7
  bundledDefaultModel
8
8
  } from "./index-xqxeypt5.js";
9
9
  import {
10
10
  HarnessConfigError,
11
11
  HarnessProviderError
12
- } from "./index-jdb1q8yn.js";
12
+ } from "./index-bpc596v3.js";
13
13
 
14
14
  // src/providers/reasoning.ts
15
15
  import { z } from "zod";