@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
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  openWorkspaceCheckpointStore
3
- } from "./index-sbzvrpm7.js";
3
+ } from "./index-6dft2vev.js";
4
4
  import {
5
5
  APPROVAL_HISTORY_KEY,
6
6
  appendUserMessage,
@@ -16,7 +16,7 @@ import {
16
16
  readApprovalDecisions,
17
17
  requiresExplicitHostReview,
18
18
  runHarness
19
- } from "./index-nqhnh1hz.js";
19
+ } from "./index-pp474137.js";
20
20
  import {
21
21
  ASSISTANT_RESPONSE_KEY,
22
22
  SESSION_RUN_STATUSES,
@@ -25,21 +25,21 @@ import {
25
25
  cancelHarnessRun,
26
26
  inspectUsageLedger,
27
27
  openCliSessionStore
28
- } from "./index-fny13znr.js";
28
+ } from "./index-s2k2edts.js";
29
29
  import {
30
30
  createEditProposal,
31
31
  editProposalInputSchema,
32
32
  fileDigestSchema
33
- } from "./index-zmx264xy.js";
33
+ } from "./index-m34q25jj.js";
34
34
  import {
35
35
  CLI_JSON_SCHEMA_VERSION,
36
36
  harnessClientRequestSchema
37
- } from "./index-ngg2168h.js";
37
+ } from "./index-nmjdwd4p.js";
38
38
  import {
39
39
  HarnessStateConflictError,
40
40
  harnessErrorDocument,
41
41
  providerStreamDiagnostic
42
- } from "./index-jdb1q8yn.js";
42
+ } from "./index-bpc596v3.js";
43
43
 
44
44
  // src/client/continuation.ts
45
45
  function terminalContinuationMessages(messages) {
@@ -1,3 +1,8 @@
1
+ import {
2
+ classifyProviderFailure,
3
+ providerDiagnostic
4
+ } from "./index-fm84men1.js";
5
+
1
6
  // src/runtime/errors.ts
2
7
  var HARNESS_ERROR_CODES = [
3
8
  "CONFIG_INVALID",
@@ -117,13 +122,6 @@ var harnessErrorDocument = (error) => {
117
122
  }
118
123
  };
119
124
  };
120
- var numericStatuses = (error) => {
121
- if (!error || typeof error !== "object")
122
- return;
123
- const record = error;
124
- const values = [record.status, record.statusCode].filter((value) => typeof value === "number" && Number.isSafeInteger(value));
125
- return values.length > 0 ? values : undefined;
126
- };
127
125
  var normalizeHarnessError = (error) => {
128
126
  const diagnostic = providerStreamDiagnostic(error);
129
127
  if (diagnostic)
@@ -131,9 +129,16 @@ var normalizeHarnessError = (error) => {
131
129
  if (error instanceof HarnessError)
132
130
  return error;
133
131
  const message = error instanceof Error ? error.message : "Harness execution failed.";
134
- const statuses = numericStatuses(error) ?? [];
135
- if (statuses.some((status) => status === 429 || status >= 500 && status <= 599)) {
136
- return new HarnessProviderError(message, { cause: error, retryable: true });
132
+ const failure = classifyProviderFailure(error);
133
+ if (failure.retryable) {
134
+ const record = error && typeof error === "object" ? error : {};
135
+ const body = typeof record.responseBody === "string" ? record.responseBody : typeof record.body === "string" ? record.body : undefined;
136
+ const providerError = new HarnessProviderError("Provider request failed.", { cause: error, retryable: true });
137
+ return Object.assign(providerError, {
138
+ ...failure.httpStatus !== undefined ? { status: failure.httpStatus } : {},
139
+ ...failure.providerStatus ? { providerStatus: failure.providerStatus } : {},
140
+ provider: providerDiagnostic(body, failure.httpStatus)
141
+ });
137
142
  }
138
143
  const name = error && typeof error === "object" && typeof error.name === "string" ? error.name : "";
139
144
  const code = error && typeof error === "object" && typeof error.code === "string" ? error.code : "";
@@ -0,0 +1,239 @@
1
+ // src/runtime/provider-diagnostics.ts
2
+ import { z } from "zod";
3
+ var providerDiagnosticSchema = z.strictObject({
4
+ reason: z.enum(["previous_response_unavailable", "context_length_exceeded", "authentication", "payment_required", "permission", "rate_limit", "model_unavailable", "invalid_request", "server_error", "unknown"]),
5
+ parameter: z.enum(["previous_response_id", "input", "messages", "tools", "model", "max_output_tokens", "max_tokens", "temperature", "other", "none"]),
6
+ bodyState: z.enum(["parsed", "malformed", "too_large", "unavailable", "read_timeout"])
7
+ });
8
+ function providerDiagnostic(body, status) {
9
+ let reason = status === 401 ? "authentication" : status === 402 ? "payment_required" : status === 403 ? "permission" : status === 429 ? "rate_limit" : status && status >= 500 ? "server_error" : "unknown";
10
+ let parameter = "none";
11
+ if (typeof body !== "string")
12
+ return { reason, parameter, bodyState: "unavailable" };
13
+ if (Buffer.byteLength(body) > 8192)
14
+ return { reason, parameter, bodyState: "too_large" };
15
+ try {
16
+ const parsed = JSON.parse(body);
17
+ const detail = parsed?.error ?? parsed;
18
+ const code = [detail?.code, detail?.status, detail?.type].find((value) => typeof value === "string") ?? "";
19
+ const message = typeof detail?.message === "string" ? detail.message : "";
20
+ const param = providerDiagnosticSchema.shape.parameter.safeParse(detail?.param);
21
+ parameter = param.success ? param.data : detail?.param == null ? "none" : "other";
22
+ if (/response/i.test(message) && /not found|expired/i.test(message) && (parameter === "previous_response_id" || parameter === "none"))
23
+ reason = "previous_response_unavailable";
24
+ else if (["context_length_exceeded", "context_window_exceeded"].includes(code))
25
+ reason = "context_length_exceeded";
26
+ else if (["invalid_api_key", "authentication_error", "UNAUTHENTICATED"].includes(code))
27
+ reason = "authentication";
28
+ else if (["permission_denied", "permission_error", "PERMISSION_DENIED"].includes(code))
29
+ reason = "permission";
30
+ else if (["rate_limit_exceeded", "rate_limit_error", "RESOURCE_EXHAUSTED"].includes(code))
31
+ reason = "rate_limit";
32
+ else if (["UNAVAILABLE", "DEADLINE_EXCEEDED", "ABORTED", "INTERNAL"].includes(code))
33
+ reason = "server_error";
34
+ else if (["model_not_found", "model_not_available", "NOT_FOUND"].includes(code))
35
+ reason = "model_unavailable";
36
+ else if (["invalid_request_error", "INVALID_ARGUMENT"].includes(code) || status === 400 || status === 422)
37
+ reason = "invalid_request";
38
+ return { reason, parameter, bodyState: "parsed" };
39
+ } catch {
40
+ return { reason, parameter, bodyState: "malformed" };
41
+ }
42
+ }
43
+
44
+ // src/runtime/provider-transient.ts
45
+ var PROVIDER_STATUS_CATEGORIES = [
46
+ "ABORTED",
47
+ "RESOURCE_EXHAUSTED",
48
+ "UNAVAILABLE",
49
+ "DEADLINE_EXCEEDED",
50
+ "INTERNAL",
51
+ "STREAM_RESET"
52
+ ];
53
+ var VERTEX_TRANSIENT_ATTEMPTS = 3;
54
+ var TRANSIENT_HTTP = {
55
+ 408: "DEADLINE_EXCEEDED",
56
+ 409: "ABORTED",
57
+ 425: "UNAVAILABLE",
58
+ 429: "RESOURCE_EXHAUSTED",
59
+ 500: "INTERNAL",
60
+ 502: "UNAVAILABLE",
61
+ 503: "UNAVAILABLE",
62
+ 504: "DEADLINE_EXCEEDED"
63
+ };
64
+ var TRANSIENT_GRPC = {
65
+ 4: "DEADLINE_EXCEEDED",
66
+ 8: "RESOURCE_EXHAUSTED",
67
+ 10: "ABORTED",
68
+ 13: "INTERNAL",
69
+ 14: "UNAVAILABLE"
70
+ };
71
+ var CATEGORY_HTTP = {
72
+ ABORTED: 409,
73
+ RESOURCE_EXHAUSTED: 429,
74
+ UNAVAILABLE: 503,
75
+ DEADLINE_EXCEEDED: 504,
76
+ INTERNAL: 500,
77
+ STREAM_RESET: undefined
78
+ };
79
+ var SYMBOLIC = new Set(["ABORTED", "RESOURCE_EXHAUSTED", "UNAVAILABLE", "DEADLINE_EXCEEDED", "INTERNAL"]);
80
+ var STREAM_RESET_CODES = new Set(["ECONNRESET", "ECONNABORTED", "EPIPE", "ETIMEDOUT", "UND_ERR_SOCKET", "ERR_STREAM_PREMATURE_CLOSE"]);
81
+ var HTTP_IN_MESSAGE = /(?:^|[^\d])(408|409|425|429|500|502|503|504)(?=$|[^\d])/;
82
+ var STREAM_RESET_MESSAGE = /stream reset|RST_STREAM|ECONNRESET|socket hang up|ERR_STREAM_PREMATURE_CLOSE|UND_ERR_SOCKET/i;
83
+ var isProviderStatus = (value) => typeof value === "string" && PROVIDER_STATUS_CATEGORIES.includes(value);
84
+ var httpStatusValue = (value) => typeof value === "number" && Number.isInteger(value) && value >= 100 && value <= 599 ? value : undefined;
85
+ var definitiveClientStatus = (status) => status !== undefined && status >= 400 && status < 500 && TRANSIENT_HTTP[status] === undefined;
86
+ function readProviderFailureRecord(record, depth = 0) {
87
+ let retryable = false;
88
+ let clientError = false;
89
+ let httpStatus;
90
+ let providerStatus;
91
+ const noteHttp = (status) => {
92
+ if (status === undefined)
93
+ return;
94
+ httpStatus ??= status;
95
+ const category = TRANSIENT_HTTP[status];
96
+ if (category) {
97
+ retryable = true;
98
+ providerStatus ??= category;
99
+ } else if (status >= 400 && status < 500)
100
+ clientError = true;
101
+ };
102
+ const noteCategory = (category) => {
103
+ if (!category || clientError)
104
+ return;
105
+ retryable = true;
106
+ providerStatus ??= category;
107
+ if (httpStatus === undefined)
108
+ httpStatus = CATEGORY_HTTP[category];
109
+ };
110
+ const absorb = (value) => {
111
+ if (depth >= 2 || !value || typeof value !== "object" || value === record)
112
+ return;
113
+ const signals = readProviderFailureRecord(value, depth + 1);
114
+ noteHttp(signals.httpStatus);
115
+ noteCategory(signals.providerStatus);
116
+ };
117
+ noteHttp(httpStatusValue(record.status) ?? httpStatusValue(record.statusCode) ?? httpStatusValue(record.httpStatusCode));
118
+ if (typeof record.status === "string" && /^\d{3}$/.test(record.status))
119
+ noteHttp(Number(record.status));
120
+ if (typeof record.code === "number" && record.code >= 100 && record.code <= 599)
121
+ noteHttp(record.code);
122
+ if (typeof record.code === "number" && record.code >= 0 && record.code <= 16)
123
+ noteCategory(TRANSIENT_GRPC[record.code]);
124
+ if (typeof record.code === "string") {
125
+ if (STREAM_RESET_CODES.has(record.code))
126
+ noteCategory("STREAM_RESET");
127
+ else if (SYMBOLIC.has(record.code))
128
+ noteCategory(record.code);
129
+ }
130
+ if (typeof record.status === "string" && SYMBOLIC.has(record.status))
131
+ noteCategory(record.status);
132
+ if (isProviderStatus(record.providerStatus))
133
+ noteCategory(record.providerStatus);
134
+ if (record.diagnosticCode === "VERTEX_STREAM_TOOL_TRUNCATED" || record.reason === "stream_truncated")
135
+ noteCategory("STREAM_RESET");
136
+ if (record.code === "PROVIDER_UNAVAILABLE" && record.retryable === true)
137
+ retryable = true;
138
+ const body = record.responseBody ?? record.body;
139
+ if (!clientError) {
140
+ if (typeof body === "string")
141
+ noteCategory(categoryFromBody(body));
142
+ else
143
+ absorb(body);
144
+ absorb(record.error);
145
+ }
146
+ if (!retryable && !clientError && typeof record.message === "string") {
147
+ const match = record.message.match(HTTP_IN_MESSAGE);
148
+ if (match?.[1])
149
+ noteHttp(Number(match[1]));
150
+ else if (STREAM_RESET_MESSAGE.test(record.message))
151
+ noteCategory("STREAM_RESET");
152
+ }
153
+ if (httpStatus !== undefined && definitiveClientStatus(httpStatus))
154
+ return { retryable: false, httpStatus };
155
+ return { retryable, ...httpStatus !== undefined ? { httpStatus } : {}, ...providerStatus ? { providerStatus } : {} };
156
+ }
157
+ function categoryFromBody(body) {
158
+ if (Buffer.byteLength(body) > 8192)
159
+ return;
160
+ try {
161
+ const parsed = JSON.parse(body);
162
+ if (!parsed || typeof parsed !== "object")
163
+ return;
164
+ const detail = parsed.error;
165
+ const source = detail && typeof detail === "object" ? detail : parsed;
166
+ return readProviderFailureRecord(source).providerStatus;
167
+ } catch {
168
+ return;
169
+ }
170
+ }
171
+ function classifyProviderFailure(error) {
172
+ if (error && typeof error === "object") {
173
+ const top = readProviderFailureRecord(error);
174
+ if (top.httpStatus !== undefined && definitiveClientStatus(top.httpStatus))
175
+ return { retryable: false, httpStatus: top.httpStatus };
176
+ }
177
+ const seen = new Set;
178
+ let retryable = false;
179
+ let httpStatus;
180
+ let providerStatus;
181
+ const visit = (current, depth) => {
182
+ if (!current || typeof current !== "object" || depth > 5 || seen.has(current))
183
+ return;
184
+ seen.add(current);
185
+ const record = current;
186
+ const signals = readProviderFailureRecord(record);
187
+ httpStatus ??= signals.httpStatus;
188
+ providerStatus ??= signals.providerStatus;
189
+ if (httpStatus !== undefined && providerStatus === undefined)
190
+ providerStatus = TRANSIENT_HTTP[httpStatus];
191
+ if (record.retryable === false)
192
+ return;
193
+ if (signals.retryable)
194
+ retryable = true;
195
+ visit(record.cause, depth + 1);
196
+ if (record.error && typeof record.error === "object")
197
+ visit(record.error, depth + 1);
198
+ if (record.details && typeof record.details === "object")
199
+ visit(record.details, depth + 1);
200
+ if (Array.isArray(record.chain))
201
+ for (const entry of record.chain)
202
+ visit(entry, depth + 1);
203
+ };
204
+ visit(error, 0);
205
+ if (retryable && httpStatus === undefined && providerStatus)
206
+ httpStatus = CATEGORY_HTTP[providerStatus];
207
+ return { retryable, ...httpStatus !== undefined ? { httpStatus } : {}, ...providerStatus ? { providerStatus } : {} };
208
+ }
209
+ function isRetryableProviderFailure(error) {
210
+ return classifyProviderFailure(error).retryable;
211
+ }
212
+ function transientBackoffMs(attempt, baseMs = 250) {
213
+ const exponential = Math.min(baseMs * 2 ** Math.max(0, attempt), 1e4);
214
+ return exponential + Math.floor(Math.random() * exponential);
215
+ }
216
+ var thoughtOnlyText = (text) => {
217
+ try {
218
+ const parsed = JSON.parse(text);
219
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
220
+ return false;
221
+ const record = parsed;
222
+ return record.thought === true && Object.keys(record).every((key) => key === "thought" || key === "thoughtSignature");
223
+ } catch {
224
+ return false;
225
+ }
226
+ };
227
+ function isEmptyModelTurn(result) {
228
+ if (result.finishReason === "content-filter" || result.finishReason === "error")
229
+ return false;
230
+ if ((result.images?.length ?? 0) > 0 || (result.audio?.length ?? 0) > 0)
231
+ return false;
232
+ const parts = result.messages?.flatMap((message) => message.parts ?? []) ?? [];
233
+ if (parts.some((part) => part.type === "tool-call" || part.type === "image" || part.type === "audio"))
234
+ return false;
235
+ const texts = [result.text ?? "", ...parts.filter((part) => part.type === "text").map((part) => part.text ?? "")];
236
+ return texts.every((text) => text.trim().length === 0 || thoughtOnlyText(text.trim()));
237
+ }
238
+
239
+ export { providerDiagnosticSchema, providerDiagnostic, PROVIDER_STATUS_CATEGORIES, VERTEX_TRANSIENT_ATTEMPTS, readProviderFailureRecord, classifyProviderFailure, isRetryableProviderFailure, transientBackoffMs, isEmptyModelTurn };
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  HARNESS_EXECUTION_POLICY_VERSION
3
- } from "./index-09zphhwt.js";
3
+ } from "./index-8zjmnyw5.js";
4
4
  import {
5
5
  HarnessError,
6
6
  HarnessExecutionError,
7
7
  HarnessStateConflictError,
8
8
  HarnessWorkspaceError
9
- } from "./index-jdb1q8yn.js";
9
+ } from "./index-bpc596v3.js";
10
10
 
11
11
  // src/workspace/edit-contracts.ts
12
12
  import { createHash } from "node:crypto";
@@ -0,0 +1,220 @@
1
+ import {
2
+ VERTEX_TRANSIENT_ATTEMPTS,
3
+ classifyProviderFailure,
4
+ isEmptyModelTurn,
5
+ isRetryableProviderFailure,
6
+ providerDiagnostic,
7
+ providerDiagnosticSchema,
8
+ transientBackoffMs
9
+ } from "./index-fm84men1.js";
10
+
11
+ // src/providers/vertex-auth.ts
12
+ import { GoogleAuth } from "google-auth-library";
13
+ import { createVertex } from "@zhivex-ai/vertex";
14
+ import { wrapLanguageModel } from "@zhivex-ai/core";
15
+ var CLOUD_PLATFORM_SCOPE = "https://www.googleapis.com/auth/cloud-platform";
16
+ function vertexRoute(env) {
17
+ const projectId = (env.GOOGLE_CLOUD_PROJECT ?? "").trim();
18
+ const location = (env.VERTEX_LOCATION ?? "").trim();
19
+ if (!/^(?:[a-z][a-z0-9-]{4,61}[a-z0-9]|[0-9]{6,20})$/.test(projectId)) {
20
+ throw new Error("Vertex requires a valid GOOGLE_CLOUD_PROJECT.");
21
+ }
22
+ if (!/^(?:global|us|eu|[a-z]+-[a-z]+[0-9]+)$/.test(location)) {
23
+ throw new Error("Vertex requires an explicit valid VERTEX_LOCATION.");
24
+ }
25
+ return Object.freeze({ projectId, location });
26
+ }
27
+ function vertexConfigured(env) {
28
+ try {
29
+ vertexRoute(env);
30
+ return true;
31
+ } catch {
32
+ return false;
33
+ }
34
+ }
35
+ var VERTEX_ENVIRONMENT = ["GOOGLE_CLOUD_PROJECT", "VERTEX_LOCATION", "GOOGLE_APPLICATION_CREDENTIALS"];
36
+ function vertexEnvironment(env) {
37
+ return Object.fromEntries(VERTEX_ENVIRONMENT.flatMap((name) => env[name] ? [[name, env[name]]] : []));
38
+ }
39
+ function vertexTokenSource(env, route, createAuth = (options) => new GoogleAuth(options)) {
40
+ const keyFilename = env.GOOGLE_APPLICATION_CREDENTIALS?.trim();
41
+ const auth = createAuth({
42
+ projectId: route.projectId,
43
+ scopes: [CLOUD_PLATFORM_SCOPE],
44
+ ...keyFilename ? { keyFilename } : {}
45
+ });
46
+ return async () => {
47
+ try {
48
+ const token = await auth.getAccessToken();
49
+ if (!token)
50
+ throw new Error("Empty ADC token");
51
+ return token;
52
+ } catch {
53
+ throw new VertexAuthenticationError;
54
+ }
55
+ };
56
+ }
57
+
58
+ class VertexAuthenticationError extends Error {
59
+ status = 401;
60
+ retryable = false;
61
+ constructor() {
62
+ super("Vertex ADC credentials are unavailable or could not be refreshed. Configure Application Default Credentials and retry.");
63
+ this.name = "VertexAuthenticationError";
64
+ }
65
+ }
66
+ function createVertexModel(model, env, createAuth, retry) {
67
+ const route = vertexRoute(env);
68
+ const adapter = createVertex({
69
+ ...route,
70
+ getAccessToken: vertexTokenSource(env, route, createAuth)
71
+ })(model);
72
+ const attempts = retry?.attempts ?? VERTEX_TRANSIENT_ATTEMPTS;
73
+ const delayFor = (input) => retry?.delayMs ?? ((attempt) => input.retryBackoffMs === 0 ? 0 : transientBackoffMs(attempt, input.retryBackoffMs ?? 250));
74
+ const generate = async (input) => withVertexAttempts(input.abortSignal, vertexAttemptBudget(input, attempts), delayFor(input), async () => {
75
+ try {
76
+ return await adapter.generate({ ...input, maxRetries: 0 });
77
+ } catch (error) {
78
+ throw safeVertexError(error);
79
+ }
80
+ }, (result) => !isEmptyModelTurn(result));
81
+ const innerStream = adapter.stream?.bind(adapter);
82
+ const retrying = innerStream ? {
83
+ ...adapter,
84
+ generate,
85
+ async stream(input) {
86
+ const events = await withVertexAttempts(input.abortSignal, vertexAttemptBudget(input, attempts), delayFor(input), () => collectVertexStream(() => innerStream({ ...input, maxRetries: 0 })), (events2) => !isEmptyVertexStream(events2));
87
+ return replayVertexStream(events);
88
+ }
89
+ } : { ...adapter, generate };
90
+ return wrapLanguageModel(retrying, [{
91
+ name: "harness-vertex-sanitized-errors",
92
+ async wrapGenerate(_context, next) {
93
+ try {
94
+ return await next();
95
+ } catch (error) {
96
+ throw safeVertexError(error);
97
+ }
98
+ },
99
+ async wrapStream(_context, next) {
100
+ let stream;
101
+ try {
102
+ stream = await next();
103
+ } catch (error) {
104
+ throw safeVertexError(error);
105
+ }
106
+ return async function* () {
107
+ try {
108
+ yield* stream;
109
+ } catch (error) {
110
+ throw safeVertexError(error);
111
+ }
112
+ }();
113
+ }
114
+ }]);
115
+ }
116
+ async function collectVertexStream(next) {
117
+ let stream;
118
+ try {
119
+ stream = await next();
120
+ } catch (error) {
121
+ throw safeVertexError(error);
122
+ }
123
+ const events = [];
124
+ try {
125
+ for await (const event of stream) {
126
+ if (event.type === "error")
127
+ throw safeVertexError(event.error);
128
+ events.push(event);
129
+ }
130
+ } catch (error) {
131
+ throw error instanceof Error && error.message.startsWith("Vertex request failed.") ? error : safeVertexError(error);
132
+ }
133
+ return events;
134
+ }
135
+ function isEmptyVertexStream(events) {
136
+ let text = "";
137
+ let finishReason;
138
+ let tools = false;
139
+ let media = false;
140
+ for (const event of events) {
141
+ if (event.type === "text-delta")
142
+ text += event.textDelta;
143
+ else if (event.type === "tool-call" || event.type === "tool-approval-request")
144
+ tools = true;
145
+ else if (event.type === "image-generation")
146
+ media = true;
147
+ else if (event.type === "finish")
148
+ finishReason = event.finishReason;
149
+ }
150
+ return isEmptyModelTurn({
151
+ text,
152
+ finishReason,
153
+ ...tools ? { messages: [{ parts: [{ type: "tool-call" }] }] } : {},
154
+ ...media ? { images: [{}] } : {}
155
+ });
156
+ }
157
+ function replayVertexStream(events) {
158
+ return async function* () {
159
+ yield* events;
160
+ }();
161
+ }
162
+ async function withVertexAttempts(abortSignal, attempts, delayMs, run, accept) {
163
+ let last;
164
+ for (let attempt = 0;attempt < attempts; attempt += 1) {
165
+ if (abortSignal?.aborted)
166
+ throw new DOMException("Vertex request cancelled.", "AbortError");
167
+ try {
168
+ const value = await run();
169
+ if (accept(value) || attempt === attempts - 1)
170
+ return value;
171
+ last = value;
172
+ } catch (error) {
173
+ const safe = error instanceof Error && (error.name === "AbortError" || error.message.startsWith("Vertex request failed.")) ? error : safeVertexError(error);
174
+ if (safe.name === "AbortError" || abortSignal?.aborted || attempt === attempts - 1 || !isRetryableProviderFailure(safe))
175
+ throw safe;
176
+ }
177
+ await sleep(delayMs(attempt));
178
+ }
179
+ return last;
180
+ }
181
+ var sleep = (ms) => ms > 0 ? new Promise((resolve) => setTimeout(resolve, ms)) : Promise.resolve();
182
+ function vertexAttemptBudget(input, fallback) {
183
+ const requested = [
184
+ typeof input.maxProviderRequests === "number" ? input.maxProviderRequests : undefined,
185
+ typeof input.maxRetries === "number" ? input.maxRetries + 1 : undefined
186
+ ].filter((value) => value !== undefined);
187
+ if (requested.length === 0)
188
+ return Math.max(1, fallback);
189
+ return Math.max(1, Math.min(...requested));
190
+ }
191
+ function safeVertexError(error) {
192
+ if (error instanceof VertexAuthenticationError)
193
+ return error;
194
+ const record = error && typeof error === "object" ? error : {};
195
+ if (record.name === "AbortError")
196
+ return new DOMException("Vertex request cancelled.", "AbortError");
197
+ const failure = classifyProviderFailure(error);
198
+ const body = providerBody(record.responseBody) ?? providerBody(record.body);
199
+ const preserved = providerDiagnosticSchema.safeParse(record.provider);
200
+ const provider = body !== undefined ? providerDiagnostic(body, failure.httpStatus) : preserved.success ? preserved.data : providerDiagnostic(undefined, failure.httpStatus);
201
+ return Object.assign(new Error("Vertex request failed. Check the sanitized provider diagnosis."), {
202
+ ...failure.httpStatus !== undefined ? { status: failure.httpStatus } : {},
203
+ ...failure.providerStatus ? { providerStatus: failure.providerStatus } : {},
204
+ provider,
205
+ retryable: failure.retryable
206
+ });
207
+ }
208
+ function providerBody(value) {
209
+ if (typeof value === "string")
210
+ return value;
211
+ if (!value || typeof value !== "object")
212
+ return;
213
+ try {
214
+ return JSON.stringify(value).slice(0, 8192);
215
+ } catch {
216
+ return;
217
+ }
218
+ }
219
+
220
+ export { vertexRoute, vertexConfigured, VERTEX_ENVIRONMENT, vertexEnvironment, vertexTokenSource, createVertexModel };
@@ -1,23 +1,25 @@
1
1
  import {
2
2
  fileDigestSchema
3
- } from "./index-zmx264xy.js";
3
+ } from "./index-m34q25jj.js";
4
4
  import {
5
5
  PROVIDERS,
6
6
  reasoningEffortSchema
7
- } from "./index-09zphhwt.js";
8
- import {
9
- providerDiagnostic,
10
- providerDiagnosticSchema
11
- } from "./index-8705zxpr.js";
7
+ } from "./index-8zjmnyw5.js";
12
8
  import {
13
9
  CLI_EVENT_SCHEMA_VERSION,
14
10
  CLI_JSON_SCHEMA_VERSION
15
- } from "./index-ngg2168h.js";
11
+ } from "./index-nmjdwd4p.js";
16
12
  import {
17
13
  HARNESS_ERROR_CODES,
18
14
  HARNESS_ERROR_SCHEMA_VERSION,
19
15
  HarnessError
20
- } from "./index-jdb1q8yn.js";
16
+ } from "./index-bpc596v3.js";
17
+ import {
18
+ PROVIDER_STATUS_CATEGORIES,
19
+ providerDiagnostic,
20
+ providerDiagnosticSchema,
21
+ readProviderFailureRecord
22
+ } from "./index-fm84men1.js";
21
23
 
22
24
  // src/workspace/change-envelope.ts
23
25
  import { createHash } from "node:crypto";
@@ -1245,6 +1247,7 @@ var errorDetailsSchema = z3.strictObject({
1245
1247
  checkpoint: z3.enum(checkpoints).optional(),
1246
1248
  code: z3.enum([...HARNESS_ERROR_CODES, ...systemCodes]).optional(),
1247
1249
  provider: providerDiagnosticSchema.optional(),
1250
+ providerStatus: z3.enum(PROVIDER_STATUS_CATEGORIES).optional(),
1248
1251
  status: z3.number().int().min(100).max(599).optional(),
1249
1252
  retryable: z3.boolean().optional(),
1250
1253
  acceptanceReason: z3.enum(acceptanceReasons).optional(),
@@ -1335,11 +1338,14 @@ var sanitizedErrorDetails = (error) => {
1335
1338
  const allowedCodes = [...HARNESS_ERROR_CODES, ...systemCodes];
1336
1339
  if (allowedCodes.includes(record.code))
1337
1340
  entry.code = record.code;
1338
- const status = [record.status, record.statusCode].find((value) => typeof value === "number" && Number.isInteger(value) && value >= 100 && value <= 599);
1341
+ const signals = readProviderFailureRecord(record);
1342
+ const status = [record.status, record.statusCode, record.httpStatusCode, signals.httpStatus].find((value) => typeof value === "number" && Number.isInteger(value) && value >= 100 && value <= 599);
1339
1343
  if (typeof status === "number") {
1340
1344
  entry.status = status;
1341
- entry.provider = providerDiagnostic(record.responseBody ?? record.body, status);
1345
+ entry.provider = providerDiagnostic(typeof record.responseBody === "string" || typeof record.body === "string" ? record.responseBody ?? record.body : undefined, status);
1342
1346
  }
1347
+ if (signals.providerStatus)
1348
+ entry.providerStatus = signals.providerStatus;
1343
1349
  const provider = providerDiagnosticSchema.safeParse(record.provider);
1344
1350
  if (provider.success)
1345
1351
  entry.provider = provider.data;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  providerStreamDiagnostic
3
- } from "./index-jdb1q8yn.js";
3
+ } from "./index-bpc596v3.js";
4
4
 
5
5
  // src/client/stream.ts
6
6
  var CLI_JSON_SCHEMA_VERSION = 1;
@@ -1,17 +1,17 @@
1
1
  import {
2
2
  readRegularFileNoFollow
3
- } from "./index-zmx264xy.js";
3
+ } from "./index-m34q25jj.js";
4
4
  import {
5
5
  HarnessConfigError,
6
6
  HarnessError,
7
7
  HarnessExecutionError,
8
8
  HarnessProviderError,
9
9
  HarnessWorkspaceError
10
- } from "./index-jdb1q8yn.js";
10
+ } from "./index-bpc596v3.js";
11
11
  // package.json
12
12
  var package_default = {
13
13
  name: "@zhivex-ai/harness",
14
- version: "1.4.0-rc.8",
14
+ version: "1.4.0",
15
15
  description: "Governed, provider-portable runtime for coding agents with durable approvals and isolated repository execution.",
16
16
  type: "module",
17
17
  license: "MIT",