@zhivex-ai/harness 1.1.1 → 1.2.0-rc.13

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 (119) hide show
  1. package/CHANGELOG.md +160 -0
  2. package/README.md +14 -7
  3. package/SECURITY.md +1 -1
  4. package/SUPPORT.md +3 -3
  5. package/benchmarks/README.md +17 -0
  6. package/contracts/public-api.json +95 -5
  7. package/contracts/stable-api-signatures.json +38 -38
  8. package/dist/acp-cli.d.ts +2 -0
  9. package/dist/acp-cli.js +15938 -0
  10. package/dist/cli/arguments.d.ts +7 -1
  11. package/dist/cli/cli-credentials.d.ts +6 -1
  12. package/dist/cli/cli-options.d.ts +1 -1
  13. package/dist/cli/cli-profiles.d.ts +15 -0
  14. package/dist/cli/cli-stream.d.ts +3 -3
  15. package/dist/cli/console/console-budget.d.ts +9 -0
  16. package/dist/cli/console/console-commands.d.ts +3 -3
  17. package/dist/cli/console/console-compaction.d.ts +18 -0
  18. package/dist/cli/console/console-input.d.ts +22 -3
  19. package/dist/cli/console/console-navigation.d.ts +3 -0
  20. package/dist/cli/console/console-presentation.d.ts +9 -2
  21. package/dist/cli/console/console-progress.d.ts +6 -0
  22. package/dist/cli/console/console-reasoning.d.ts +3 -0
  23. package/dist/cli/doctor.d.ts +2 -2
  24. package/dist/cli/presentation.d.ts +8 -1
  25. package/dist/cli/qwen-connection.d.ts +23 -0
  26. package/dist/cli/run-document.d.ts +4 -4
  27. package/dist/cli/terminal/activity-history.d.ts +15 -0
  28. package/dist/cli/terminal/session-grants.d.ts +4 -0
  29. package/dist/cli/terminal/terminal-markdown.d.ts +7 -4
  30. package/dist/cli/terminal/terminal-table.d.ts +6 -0
  31. package/dist/cli/terminal/terminal-ui.d.ts +3 -0
  32. package/dist/cli/terminal/tool-activity.d.ts +21 -10
  33. package/dist/cli/tool-execution.d.ts +1 -0
  34. package/dist/cli-3jmy4h5h.js +5798 -0
  35. package/dist/cli-entry-1bx83sw4.js +4 -0
  36. package/dist/cli-entry-427869g9.js +2009 -0
  37. package/dist/cli-entry-64pdp3k5.js +17 -0
  38. package/dist/cli-entry-b1mfvmxe.js +376 -0
  39. package/dist/cli-entry-c2f58zj2.js +13602 -0
  40. package/dist/cli-entry.d.ts +2 -0
  41. package/dist/cli.d.ts +1 -0
  42. package/dist/cli.js +15 -19168
  43. package/dist/client/acp-stdio.d.ts +9 -0
  44. package/dist/client/acp.d.ts +18 -0
  45. package/dist/client/index.d.ts +2 -0
  46. package/dist/client/json-contracts.d.ts +22 -8
  47. package/dist/config-1k9t4jhh.js +59 -0
  48. package/dist/context/adaptive-compaction.d.ts +2 -0
  49. package/dist/context/compaction.d.ts +3 -1
  50. package/dist/context/qwen-reasoning.d.ts +5 -0
  51. package/dist/context/scoped-context.d.ts +61 -0
  52. package/dist/context/semantic-compaction.d.ts +21 -0
  53. package/dist/context/task-memory.d.ts +13 -8
  54. package/dist/execution/execution-environment.d.ts +5 -0
  55. package/dist/execution/oci-observability.d.ts +2 -0
  56. package/dist/execution/patch-diagnostics.d.ts +6 -0
  57. package/dist/hostile-repository-demo.js +4614 -1930
  58. package/dist/index.d.ts +13 -1
  59. package/dist/index.js +16435 -12486
  60. package/dist/integrations/mcp.d.ts +23 -3
  61. package/dist/models/catalog.d.ts +76 -0
  62. package/dist/models/compaction-recommendations.d.ts +28 -0
  63. package/dist/models/sdk-catalog-adapter.d.ts +7 -0
  64. package/dist/persistence/operations.d.ts +10 -6
  65. package/dist/persistence/state-backup-stream.d.ts +4 -0
  66. package/dist/persistence/state-backup.d.ts +52 -0
  67. package/dist/persistence/state-gitignore.d.ts +2 -0
  68. package/dist/persistence/workspace-checkpoints.d.ts +149 -0
  69. package/dist/providers/meta-continuation.d.ts +1 -1
  70. package/dist/providers/meta-errors.d.ts +2 -0
  71. package/dist/providers/meta-replay.d.ts +2 -0
  72. package/dist/providers/qwen-context.d.ts +2 -0
  73. package/dist/providers/qwen-hosted-policy.d.ts +5 -0
  74. package/dist/providers/reasoning.d.ts +18 -0
  75. package/dist/runtime/config.d.ts +12 -3
  76. package/dist/runtime/context-runtime.d.ts +12 -0
  77. package/dist/runtime/error-diagnostics.d.ts +641 -0
  78. package/dist/runtime/harness.d.ts +13 -4
  79. package/dist/runtime/model-edit-references.d.ts +8 -0
  80. package/dist/runtime/oci-delivery.d.ts +17 -0
  81. package/dist/runtime/progress-monitor.d.ts +33 -0
  82. package/dist/runtime/provider-diagnostics.d.ts +35 -0
  83. package/dist/runtime/runtime-checkpoints.d.ts +3 -0
  84. package/dist/runtime/runtime-diagnostics.d.ts +5 -5
  85. package/dist/runtime/runtime-policy.d.ts +14 -6
  86. package/dist/runtime/time-to-safe-fix.d.ts +308 -1
  87. package/dist/runtime/tool-execution.d.ts +11 -0
  88. package/dist/runtime/tool-policy.d.ts +55 -0
  89. package/dist/runtime/tool-scheduling.d.ts +5 -0
  90. package/dist/runtime/usage-ledger.d.ts +1 -0
  91. package/dist/service-cli.js +9422 -6622
  92. package/dist/service-client-cli-yx56n0hc.js +1086 -0
  93. package/dist/tools/dependency-read.d.ts +63 -0
  94. package/dist/tools/execution.d.ts +8 -8
  95. package/dist/tools/workspace.d.ts +31 -15
  96. package/dist/verify-historical-migrations.js +5272 -2437
  97. package/dist/workspace/file-security.d.ts +6 -0
  98. package/dist/zhx.js +15 -19168
  99. package/docs/ACP.md +55 -0
  100. package/docs/CLI.md +292 -29
  101. package/docs/CONTEXT_ENGINEERING.md +184 -20
  102. package/docs/CREDENTIALS.md +38 -6
  103. package/docs/DURABLE_OPERATIONS.md +10 -0
  104. package/docs/EXTENSIBILITY.md +101 -4
  105. package/docs/FIRST_USE.md +7 -5
  106. package/docs/MODEL_CATALOG.md +52 -1
  107. package/docs/README.md +1 -0
  108. package/docs/REPOSITORY_EDITING.md +42 -0
  109. package/docs/STABILITY.md +2 -0
  110. package/docs/SUPPORT_MATRIX_1_1.md +17 -0
  111. package/docs/USAGE.md +9 -0
  112. package/docs/WORKSPACE_CHECKPOINTS.md +27 -0
  113. package/docs/images/cli-conversation.png +0 -0
  114. package/docs/support-matrix-1.1.json +29 -0
  115. package/evaluations/golden-expectations.json +5 -0
  116. package/evaluations/representative-assembly-matrix.json +145 -1
  117. package/evaluations/representative-repositories-v2.jsonl +7 -0
  118. package/examples/README.md +2 -2
  119. package/package.json +19 -13
@@ -0,0 +1,1086 @@
1
+ import {
2
+ ActivityHistory,
3
+ CLI_EVENT_SCHEMA_VERSION,
4
+ CLI_JSON_SCHEMA_VERSION,
5
+ ConsoleInput,
6
+ ToolActivity,
7
+ changeEnvelopeSchema,
8
+ formatAppliedFiles,
9
+ formatConsoleHelp,
10
+ formatConsoleWelcome,
11
+ navigateConsole,
12
+ sanitizeTerminalText,
13
+ serializeStreamResult
14
+ } from "./cli-entry-c2f58zj2.js";
15
+ import {
16
+ HARNESS_VERSION
17
+ } from "./cli-entry-64pdp3k5.js";
18
+ import {
19
+ HARNESS_ERROR_CODES,
20
+ HARNESS_ERROR_SCHEMA_VERSION,
21
+ HarnessConfigError,
22
+ HarnessStateConflictError,
23
+ PROVIDERS,
24
+ reasoningEffortSchema
25
+ } from "./cli-entry-427869g9.js";
26
+ import {
27
+ __require
28
+ } from "./cli-entry-1bx83sw4.js";
29
+
30
+ // src/cli/service-client-cli.ts
31
+ import { randomUUID, createHash } from "node:crypto";
32
+ import { setTimeout as delay } from "node:timers/promises";
33
+
34
+ // src/client/local-service.ts
35
+ import { createServer, request as httpRequest } from "node:http";
36
+ import { mkdir, lstat, realpath, open, unlink, chmod } from "node:fs/promises";
37
+ import path from "node:path";
38
+ import { z as z5 } from "zod";
39
+
40
+ // src/client/protocol.ts
41
+ import { z } from "zod";
42
+ var HARNESS_CLIENT_PROTOCOL_VERSION = 1;
43
+ var id = z.string().regex(/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/);
44
+ var revision = z.number().int().nonnegative().safe();
45
+ var scoped = { projectId: id };
46
+ var session = { ...scoped, sessionId: id };
47
+ var run = { ...session, runId: id };
48
+ var mutation = { idempotencyKey: id };
49
+ var harnessClientCommandSchema = z.discriminatedUnion("method", [
50
+ z.object({ method: z.literal("project.get"), ...scoped }).strict(),
51
+ z.object({ method: z.literal("session.list"), ...scoped, search: z.string().max(256).optional() }).strict(),
52
+ z.object({ method: z.literal("session.create"), ...scoped, ...mutation, title: z.string().max(256).optional() }).strict(),
53
+ z.object({ method: z.literal("session.get"), ...session }).strict(),
54
+ z.object({ method: z.literal("session.rename"), ...session, ...mutation, expectedRevision: revision, title: z.string().max(256) }).strict(),
55
+ z.object({ method: z.literal("run.start"), ...session, ...mutation, expectedRevision: revision, prompt: z.string().min(1).max(64 * 1024) }).strict(),
56
+ z.object({ method: z.literal("run.get"), ...run, includeReview: z.boolean().optional(), includeDiff: z.boolean().optional(), decisionOffset: z.number().int().min(0).max(512).optional() }).strict(),
57
+ z.object({
58
+ method: z.literal("approval.resolve"),
59
+ ...run,
60
+ ...mutation,
61
+ expectedRevision: revision,
62
+ decisions: z.array(z.object({ approvalId: z.string().min(1).max(256), digest: z.string().regex(/^[a-f0-9]{64}$/), approve: z.boolean() }).strict()).min(1).max(64)
63
+ }).strict(),
64
+ z.object({ method: z.literal("run.cancel"), ...run, ...mutation, expectedRevision: revision }).strict()
65
+ ]);
66
+ var harnessClientRequestSchema = z.object({
67
+ protocolVersion: z.literal(HARNESS_CLIENT_PROTOCOL_VERSION),
68
+ requestId: id,
69
+ connectionId: id,
70
+ command: harnessClientCommandSchema
71
+ }).strict();
72
+
73
+ // src/approvals/approval-history.ts
74
+ import { z as z2 } from "zod";
75
+ var rowSchema = z2.object({ approvalId: z2.string().max(256), digest: z2.string().regex(/^[a-f0-9]{64}$/), toolCallId: z2.string().max(256).optional(), name: z2.string().max(256), inputDigest: z2.string().regex(/^[a-f0-9]{64}$/).optional(), approved: z2.boolean(), decidedAt: z2.number().int().nonnegative(), reviewedRevision: z2.number().int().nonnegative() }).strict();
76
+
77
+ // src/approvals/approval-diff.ts
78
+ import { z as z3 } from "zod";
79
+ var sha = z3.string().regex(/^sha256:[a-f0-9]{64}$/);
80
+ var file = z3.object({ path: z3.string().max(1024), expectedDigest: sha.nullable(), before: z3.string().nullable(), after: z3.string().nullable(), afterDigest: sha.nullable(), beforeMode: z3.number().int().optional(), afterMode: z3.number().int().optional(), operation: z3.enum(["create", "update", "delete"]).optional() }).strict();
81
+ var archive = z3.object({ approvalId: z3.string().max(256), digest: z3.string().regex(/^[a-f0-9]{64}$/), proposalId: sha, files: z3.array(file).min(1).max(50) }).strict();
82
+ var archives = z3.array(archive).max(512);
83
+ var maxBytes = 2 * 1024 * 1024;
84
+
85
+ // src/approvals/approval-preview.ts
86
+ import { z as z4 } from "zod";
87
+
88
+ // src/client/service-events.ts
89
+ import { createRedactionPolicy } from "@zhivex-ai/agents";
90
+
91
+ // src/client/local-service.ts
92
+ var harnessLocalCredentialsSchema = z5.object({ schemaVersion: z5.literal(1), socketPath: z5.string().min(1), token: z5.string().regex(/^[a-f0-9]{64}$/) }).strict();
93
+ var readHarnessLocalCredentials = async (filename) => {
94
+ const { constants } = await import("node:fs");
95
+ const file2 = await open(filename, constants.O_RDONLY | constants.O_NOFOLLOW);
96
+ try {
97
+ const info = await file2.stat();
98
+ if (!info.isFile() || (info.mode & 63) !== 0 || info.uid !== process.getuid?.() || info.size > 4096)
99
+ throw new Error("LOCAL_SERVICE_CREDENTIALS_UNSAFE");
100
+ return harnessLocalCredentialsSchema.parse(JSON.parse(await file2.readFile("utf8")));
101
+ } finally {
102
+ await file2.close();
103
+ }
104
+ };
105
+ var requestHarnessLocalService = async (credentials, endpoint, payload) => {
106
+ const parsed = harnessLocalCredentialsSchema.parse(credentials);
107
+ if (!path.isAbsolute(parsed.socketPath) || process.platform === "win32")
108
+ throw new Error("LOCAL_SERVICE_SOCKET_INVALID");
109
+ const encoded = JSON.stringify(payload);
110
+ if (Buffer.byteLength(encoded) > 131072)
111
+ throw new Error("REQUEST_TOO_LARGE");
112
+ return new Promise((resolve, reject) => {
113
+ const req = httpRequest({ socketPath: parsed.socketPath, path: `/${endpoint}`, method: "POST", headers: {
114
+ authorization: `Bearer ${parsed.token}`,
115
+ "content-type": "application/json",
116
+ "content-length": Buffer.byteLength(encoded)
117
+ } }, (res) => {
118
+ const chunks = [];
119
+ let size = 0;
120
+ res.on("data", (chunk) => {
121
+ size += chunk.length;
122
+ if (size > 4194304)
123
+ res.destroy(new Error("RESPONSE_TOO_LARGE"));
124
+ else
125
+ chunks.push(chunk);
126
+ });
127
+ res.on("error", reject);
128
+ res.on("end", () => {
129
+ try {
130
+ if (res.statusCode !== 200)
131
+ return reject(new Error(`LOCAL_SERVICE_HTTP_${res.statusCode}`));
132
+ resolve(JSON.parse(Buffer.concat(chunks).toString("utf8")));
133
+ } catch {
134
+ reject(new Error("LOCAL_SERVICE_RESPONSE_INVALID"));
135
+ }
136
+ });
137
+ });
138
+ req.on("error", () => reject(new Error("LOCAL_SERVICE_UNAVAILABLE")));
139
+ req.end(encoded);
140
+ });
141
+ };
142
+
143
+ // src/client/json-contracts.ts
144
+ import { z as z6 } from "zod";
145
+ var observationalDocument = (shape) => z6.object(shape).passthrough();
146
+ var jsonBase = { schemaVersion: z6.literal(CLI_JSON_SCHEMA_VERSION) };
147
+ var eventBase = {
148
+ schemaVersion: z6.literal(CLI_EVENT_SCHEMA_VERSION),
149
+ sequence: z6.number().int().nonnegative()
150
+ };
151
+ var nonnegativeInteger = z6.number().int().nonnegative();
152
+ var digestSchema = z6.string().regex(/^sha256:[a-f0-9]{64}$/);
153
+ var jsonObjectSchema = observationalDocument({});
154
+ var scopeSchema = observationalDocument({
155
+ tenantId: z6.string().min(1),
156
+ userId: z6.string().min(1).optional(),
157
+ namespace: z6.string().min(1).optional()
158
+ });
159
+ var runIdentity = {
160
+ runId: z6.string().min(1),
161
+ status: z6.string().min(1),
162
+ provider: z6.string().min(1),
163
+ model: z6.string().min(1)
164
+ };
165
+ var runSummarySchema = observationalDocument({
166
+ ...runIdentity,
167
+ revision: nonnegativeInteger,
168
+ scope: scopeSchema,
169
+ steps: nonnegativeInteger,
170
+ toolCalls: nonnegativeInteger,
171
+ toolErrors: nonnegativeInteger,
172
+ pendingApprovals: nonnegativeInteger,
173
+ compactions: nonnegativeInteger,
174
+ childRuns: nonnegativeInteger,
175
+ startedAt: nonnegativeInteger,
176
+ updatedAt: nonnegativeInteger
177
+ });
178
+ var sessionRunSchema = observationalDocument({
179
+ turnId: z6.string().min(1),
180
+ sequence: nonnegativeInteger,
181
+ runId: z6.string().min(1),
182
+ provider: z6.string().min(1),
183
+ model: z6.string().min(1),
184
+ status: z6.string().min(1),
185
+ createdAt: nonnegativeInteger,
186
+ updatedAt: nonnegativeInteger
187
+ });
188
+ var sessionSchema = observationalDocument({
189
+ schemaVersion: z6.literal(1),
190
+ sessionId: z6.string().min(1),
191
+ workspaceKey: z6.string().min(1),
192
+ scopeKey: z6.string().min(1),
193
+ revision: nonnegativeInteger,
194
+ createdAt: nonnegativeInteger,
195
+ updatedAt: nonnegativeInteger,
196
+ runs: z6.array(sessionRunSchema)
197
+ });
198
+ var tokenUsageSchema = observationalDocument({
199
+ inputTokens: nonnegativeInteger.optional(),
200
+ cachedInputTokens: nonnegativeInteger.optional(),
201
+ cacheWriteTokens: nonnegativeInteger.optional(),
202
+ outputTokens: nonnegativeInteger.optional(),
203
+ reasoningTokens: nonnegativeInteger.optional(),
204
+ totalTokens: nonnegativeInteger.optional(),
205
+ speed: z6.enum(["standard", "fast"]).optional()
206
+ });
207
+ var budgetConfigSchema = observationalDocument({
208
+ unlimitedTokens: z6.boolean().optional(),
209
+ maxSteps: nonnegativeInteger,
210
+ maxToolCalls: nonnegativeInteger,
211
+ maxToolErrors: nonnegativeInteger,
212
+ maxInputTokens: nonnegativeInteger,
213
+ maxOutputTokens: nonnegativeInteger,
214
+ maxTotalTokens: nonnegativeInteger,
215
+ includeChildRuns: z6.boolean()
216
+ });
217
+ var budgetConsumptionSchema = observationalDocument({
218
+ steps: nonnegativeInteger,
219
+ toolCalls: nonnegativeInteger,
220
+ toolErrors: nonnegativeInteger,
221
+ inputTokens: nonnegativeInteger,
222
+ outputTokens: nonnegativeInteger,
223
+ totalTokens: nonnegativeInteger
224
+ });
225
+ var budgetRemainingSchema = observationalDocument({
226
+ steps: nonnegativeInteger.optional(),
227
+ toolCalls: nonnegativeInteger.optional(),
228
+ toolErrors: nonnegativeInteger.optional(),
229
+ inputTokens: nonnegativeInteger.optional(),
230
+ outputTokens: nonnegativeInteger.optional(),
231
+ totalTokens: nonnegativeInteger.optional()
232
+ });
233
+ var budgetStatusSchema = observationalDocument({
234
+ consumption: budgetConsumptionSchema,
235
+ remaining: budgetRemainingSchema,
236
+ includeChildRuns: z6.boolean()
237
+ });
238
+ var costEstimateSchema = observationalDocument({
239
+ inputCost: z6.number().nonnegative().optional(),
240
+ outputCost: z6.number().nonnegative().optional(),
241
+ totalCost: z6.number().nonnegative().optional(),
242
+ currency: z6.string().min(1).optional(),
243
+ usage: tokenUsageSchema.optional()
244
+ });
245
+ var mutationAuditSchema = observationalDocument({
246
+ id: z6.string().min(1),
247
+ operation: z6.enum(["create", "update", "move", "quarantine", "restore"]),
248
+ path: z6.string().min(1),
249
+ destination: z6.string().min(1).optional(),
250
+ beforeDigest: digestSchema.optional(),
251
+ afterDigest: digestSchema.optional(),
252
+ timestamp: z6.iso.datetime(),
253
+ quarantineId: z6.string().min(1).optional()
254
+ });
255
+ var approvalSummarySchema = observationalDocument({
256
+ id: z6.string().min(1),
257
+ kind: z6.string().min(1),
258
+ name: z6.string().min(1),
259
+ arguments: z6.json(),
260
+ childRunId: z6.string().min(1).optional(),
261
+ childAgentId: z6.string().min(1).optional()
262
+ });
263
+ var childRunSummarySchema = observationalDocument({
264
+ runId: z6.string().min(1),
265
+ agentId: z6.string().min(1).optional(),
266
+ toolName: z6.string().min(1).optional(),
267
+ status: z6.string().min(1),
268
+ steps: nonnegativeInteger,
269
+ toolCalls: nonnegativeInteger,
270
+ toolErrors: nonnegativeInteger,
271
+ usage: tokenUsageSchema.optional()
272
+ });
273
+ var capabilityReportSchema = observationalDocument({
274
+ provider: z6.string().min(1),
275
+ model: z6.string().min(1),
276
+ supportTier: z6.string().min(1).optional(),
277
+ capabilities: observationalDocument({
278
+ streaming: z6.boolean(),
279
+ tools: z6.boolean(),
280
+ "structured-output": z6.boolean(),
281
+ "parallel-tools": z6.boolean(),
282
+ reasoning: z6.boolean(),
283
+ "web-search": z6.boolean()
284
+ })
285
+ });
286
+ var providerConfigurationSchema = z6.object({
287
+ customEndpoint: z6.boolean(),
288
+ endpointValid: z6.boolean(),
289
+ endpointSecure: z6.boolean()
290
+ }).catchall(z6.boolean());
291
+ var providerAvailabilitySchema = observationalDocument({
292
+ id: z6.string().min(1),
293
+ name: z6.string().min(1),
294
+ defaultModel: z6.string().min(1),
295
+ credentialNames: z6.array(z6.string().min(1)),
296
+ capabilities: z6.array(z6.enum(["streaming", "tool-calling", "approval-resume"])),
297
+ support: z6.enum(["certified", "provisional"]),
298
+ configured: z6.boolean(),
299
+ credentials: z6.array(observationalDocument({
300
+ name: z6.string().min(1),
301
+ present: z6.boolean()
302
+ })),
303
+ configuration: providerConfigurationSchema
304
+ });
305
+ var orchestrationConfigSchema = observationalDocument({
306
+ profiles: z6.array(z6.enum(["explorer", "implementer", "tester", "reviewer"])),
307
+ childBudget: budgetConfigSchema,
308
+ childTimeoutMs: nonnegativeInteger,
309
+ maxParallelReviews: nonnegativeInteger
310
+ });
311
+ var executionConfigSchema = z6.discriminatedUnion("backend", [
312
+ observationalDocument({ backend: z6.literal("none") }),
313
+ observationalDocument({
314
+ backend: z6.literal("oci"),
315
+ policyVersion: z6.string().min(1),
316
+ runtime: z6.enum(["docker", "podman"]),
317
+ image: z6.string().min(1),
318
+ allowedCommands: z6.array(z6.string().min(1)),
319
+ shellMode: z6.enum(["deny", "ask"]),
320
+ maxProcessRuntimeMs: nonnegativeInteger,
321
+ maxProcessOutputBytes: nonnegativeInteger,
322
+ maxMemoryMb: nonnegativeInteger,
323
+ maxPids: nonnegativeInteger,
324
+ maxCpus: z6.number().positive(),
325
+ maxWorkspaceBytes: nonnegativeInteger,
326
+ maxFileWriteBytes: nonnegativeInteger,
327
+ tmpfsMb: nonnegativeInteger
328
+ })
329
+ ]);
330
+ var executionBindingSchema = observationalDocument({
331
+ environmentId: z6.string().min(1),
332
+ environmentVersion: z6.string().min(1).optional(),
333
+ fingerprint: z6.string().min(1),
334
+ workspaceId: z6.string().min(1).optional()
335
+ });
336
+ var ociImageSchema = observationalDocument({
337
+ runtime: z6.enum(["docker", "podman"]),
338
+ runtimeVersion: z6.string().min(1),
339
+ imageReference: z6.string().min(1),
340
+ imageId: z6.string().min(1),
341
+ imageDigest: z6.string().min(1)
342
+ });
343
+ var runExecutionSchema = z6.discriminatedUnion("backend", [
344
+ observationalDocument({ backend: z6.literal("none") }),
345
+ observationalDocument({
346
+ backend: z6.literal("oci"),
347
+ binding: executionBindingSchema,
348
+ image: ociImageSchema
349
+ })
350
+ ]);
351
+ var migrationResultSchema = observationalDocument({
352
+ scannedRuns: nonnegativeInteger,
353
+ migratedRuns: nonnegativeInteger,
354
+ migratedToolCalls: nonnegativeInteger
355
+ });
356
+ var runStoreSchema = observationalDocument({
357
+ backend: z6.enum(["sqlite", "file"]),
358
+ stateDirectory: z6.string().min(1),
359
+ migration: migrationResultSchema.optional()
360
+ });
361
+ var doctorCheckSchema = observationalDocument({
362
+ id: z6.string().min(1),
363
+ status: z6.enum(["pass", "warn", "fail"]),
364
+ message: z6.string(),
365
+ details: z6.record(z6.string(), z6.union([
366
+ z6.boolean(),
367
+ z6.number(),
368
+ z6.string(),
369
+ z6.array(z6.string())
370
+ ]))
371
+ });
372
+ var doctorConfigurationSchema = observationalDocument({
373
+ requireVerifiedDelivery: z6.boolean().optional(),
374
+ provider: z6.string().min(1),
375
+ model: z6.string().min(1),
376
+ workspace: z6.string().min(1),
377
+ stateDirectory: z6.string().min(1),
378
+ storeBackend: z6.enum(["sqlite", "file"]),
379
+ scope: scopeSchema,
380
+ maxSteps: nonnegativeInteger,
381
+ timeoutMs: nonnegativeInteger,
382
+ budget: budgetConfigSchema,
383
+ costBudget: observationalDocument({
384
+ maxCostUsd: z6.number().nonnegative(),
385
+ inputCostPer1kTokens: z6.number().nonnegative(),
386
+ outputCostPer1kTokens: z6.number().nonnegative()
387
+ }).optional(),
388
+ compaction: observationalDocument({
389
+ maxMessages: nonnegativeInteger,
390
+ maxEstimatedInputTokens: nonnegativeInteger,
391
+ keepRecentMessages: nonnegativeInteger
392
+ }),
393
+ allowedChecks: z6.array(z6.string().min(1)),
394
+ requiredCapabilities: z6.array(z6.enum([
395
+ "streaming",
396
+ "tools",
397
+ "structured-output",
398
+ "parallel-tools",
399
+ "reasoning",
400
+ "web-search"
401
+ ])),
402
+ orchestration: orchestrationConfigSchema,
403
+ context: observationalDocument({ enabled: z6.boolean(), configPath: z6.string().min(1) }),
404
+ execution: executionConfigSchema,
405
+ mcpConfigPath: z6.string().min(1).optional()
406
+ });
407
+ var cliRunResultDocumentSchema = observationalDocument({
408
+ ...jsonBase,
409
+ kind: z6.literal("run-result"),
410
+ ...runIdentity,
411
+ output: z6.string(),
412
+ steps: nonnegativeInteger,
413
+ toolCalls: nonnegativeInteger,
414
+ mutations: z6.array(mutationAuditSchema),
415
+ pendingApprovals: z6.array(approvalSummarySchema),
416
+ children: z6.array(childRunSummarySchema),
417
+ usage: tokenUsageSchema.optional(),
418
+ budget: budgetStatusSchema,
419
+ costBudget: observationalDocument({
420
+ limitUsd: z6.number().nonnegative(),
421
+ estimate: costEstimateSchema
422
+ }).optional(),
423
+ scope: scopeSchema,
424
+ capabilities: capabilityReportSchema,
425
+ orchestration: observationalDocument({
426
+ profiles: orchestrationConfigSchema.shape.profiles,
427
+ childBudget: budgetConfigSchema,
428
+ mcpServers: z6.array(z6.string().min(1))
429
+ }),
430
+ execution: runExecutionSchema,
431
+ store: runStoreSchema,
432
+ stateDirectory: z6.string()
433
+ });
434
+ var cliProviderDocumentSchema = observationalDocument({
435
+ ...jsonBase,
436
+ kind: z6.literal("providers"),
437
+ providers: z6.array(providerAvailabilitySchema)
438
+ });
439
+ var cliInitDocumentSchema = observationalDocument({
440
+ ...jsonBase,
441
+ kind: z6.literal("init"),
442
+ profile: observationalDocument({
443
+ name: z6.string().min(1),
444
+ path: z6.string().min(1),
445
+ schemaVersion: nonnegativeInteger,
446
+ provider: z6.enum(PROVIDERS),
447
+ model: z6.string().min(1),
448
+ reasoningEffort: reasoningEffortSchema.optional()
449
+ }),
450
+ credential: observationalDocument({
451
+ configured: z6.boolean(),
452
+ names: z6.array(z6.string().min(1))
453
+ }),
454
+ next: observationalDocument({
455
+ doctor: z6.string().min(1),
456
+ run: z6.string().min(1)
457
+ })
458
+ });
459
+ var cliDoctorDocumentSchema = observationalDocument({
460
+ ...jsonBase,
461
+ kind: z6.literal("doctor"),
462
+ ok: z6.boolean(),
463
+ harnessVersion: z6.string().min(1),
464
+ configSchemaVersion: nonnegativeInteger,
465
+ configuration: doctorConfigurationSchema,
466
+ checks: z6.array(doctorCheckSchema),
467
+ providers: z6.array(providerAvailabilitySchema)
468
+ });
469
+ var cliReviewGroupDocumentSchema = observationalDocument({
470
+ ...jsonBase,
471
+ kind: z6.literal("review-group"),
472
+ groupId: z6.string().min(1),
473
+ status: z6.enum(["completed", "failed"]),
474
+ profiles: z6.array(z6.string().min(1)).min(1),
475
+ outputs: z6.array(observationalDocument({
476
+ status: z6.enum(["fulfilled", "rejected"]),
477
+ name: z6.string().min(1).optional(),
478
+ agentId: z6.string().min(1).optional(),
479
+ runId: z6.string().min(1).optional(),
480
+ runStatus: z6.string().min(1).optional(),
481
+ output: z6.string().optional(),
482
+ steps: nonnegativeInteger.optional(),
483
+ usage: tokenUsageSchema.optional(),
484
+ error: observationalDocument({
485
+ code: z6.enum(HARNESS_ERROR_CODES),
486
+ category: z6.enum([
487
+ "configuration",
488
+ "usage",
489
+ "workspace",
490
+ "state",
491
+ "provider",
492
+ "approval",
493
+ "execution"
494
+ ]),
495
+ retryable: z6.boolean()
496
+ }).optional()
497
+ }))
498
+ });
499
+ var cliRunListDocumentSchema = observationalDocument({
500
+ ...jsonBase,
501
+ kind: z6.literal("run-list"),
502
+ scope: scopeSchema,
503
+ backend: z6.string().min(1),
504
+ runs: z6.array(runSummarySchema)
505
+ });
506
+ var runInspectionShape = {
507
+ run: runSummarySchema,
508
+ budget: jsonObjectSchema,
509
+ snapshot: jsonObjectSchema,
510
+ trace: jsonObjectSchema,
511
+ hierarchy: jsonObjectSchema,
512
+ ledger: jsonObjectSchema,
513
+ toolJournal: z6.array(jsonObjectSchema)
514
+ };
515
+ var cliRunInspectionDocumentSchema = observationalDocument({
516
+ ...jsonBase,
517
+ kind: z6.literal("run-inspection"),
518
+ ...runInspectionShape
519
+ });
520
+ var cliRunExportDocumentSchema = observationalDocument({
521
+ ...jsonBase,
522
+ kind: z6.literal("run-export"),
523
+ ...runInspectionShape
524
+ });
525
+ var cliRunCancellationDocumentSchema = observationalDocument({
526
+ ...jsonBase,
527
+ kind: z6.literal("run-cancellation"),
528
+ cascade: z6.boolean(),
529
+ run: runSummarySchema.optional(),
530
+ parent: runSummarySchema.optional(),
531
+ children: z6.array(runSummarySchema).optional()
532
+ }).superRefine((document, context) => {
533
+ if (!document.cascade && !document.run || document.cascade && (!document.parent || !document.children)) {
534
+ context.addIssue({ code: "custom", message: "Cancellation payload does not match cascade mode." });
535
+ }
536
+ });
537
+ var cliRunCleanupDocumentSchema = observationalDocument({
538
+ ...jsonBase,
539
+ kind: z6.literal("run-cleanup"),
540
+ before: nonnegativeInteger,
541
+ statuses: z6.array(z6.string().min(1)),
542
+ deleted: nonnegativeInteger
543
+ });
544
+ var cliSessionListDocumentSchema = observationalDocument({
545
+ ...jsonBase,
546
+ kind: z6.literal("session-list"),
547
+ sessions: z6.array(sessionSchema)
548
+ });
549
+ var cliSessionDocumentSchema = observationalDocument({
550
+ ...jsonBase,
551
+ kind: z6.literal("session"),
552
+ session: sessionSchema
553
+ });
554
+ var cliChangeEnvelopeVerificationDocumentSchema = observationalDocument({
555
+ ...jsonBase,
556
+ kind: z6.literal("change-envelope-verification"),
557
+ valid: z6.boolean(),
558
+ verificationScope: z6.literal("integrity-expiration-and-preconditions-only"),
559
+ issues: z6.array(jsonObjectSchema),
560
+ integrity: jsonObjectSchema,
561
+ expiration: jsonObjectSchema,
562
+ checks: jsonObjectSchema,
563
+ approvals: jsonObjectSchema,
564
+ externalAttestations: jsonObjectSchema
565
+ });
566
+ var cliStateStatusDocumentSchema = observationalDocument({
567
+ ...jsonBase,
568
+ kind: z6.literal("state-status"),
569
+ compatible: z6.boolean(),
570
+ schemas: jsonObjectSchema,
571
+ counts: z6.record(z6.string(), nonnegativeInteger)
572
+ });
573
+ var cliStateExportDocumentSchema = observationalDocument({
574
+ ...jsonBase,
575
+ kind: z6.literal("state-export"),
576
+ path: z6.string().min(1),
577
+ checksum: digestSchema,
578
+ counts: z6.record(z6.string(), nonnegativeInteger)
579
+ });
580
+ var cliStateImportDocumentSchema = observationalDocument({
581
+ ...jsonBase,
582
+ kind: z6.literal("state-import"),
583
+ dryRun: z6.boolean(),
584
+ checksum: digestSchema,
585
+ inserted: z6.record(z6.string(), nonnegativeInteger),
586
+ identical: nonnegativeInteger
587
+ });
588
+ var cliErrorDocumentSchema = observationalDocument({
589
+ schemaVersion: z6.literal(HARNESS_ERROR_SCHEMA_VERSION),
590
+ kind: z6.literal("error"),
591
+ error: observationalDocument({
592
+ code: z6.enum(HARNESS_ERROR_CODES),
593
+ category: z6.enum([
594
+ "configuration",
595
+ "usage",
596
+ "workspace",
597
+ "state",
598
+ "provider",
599
+ "approval",
600
+ "execution"
601
+ ]),
602
+ retryable: z6.boolean()
603
+ })
604
+ });
605
+ var cliJsonDocumentSchema = z6.union([
606
+ cliRunResultDocumentSchema,
607
+ cliInitDocumentSchema,
608
+ cliProviderDocumentSchema,
609
+ cliDoctorDocumentSchema,
610
+ cliReviewGroupDocumentSchema,
611
+ cliRunListDocumentSchema,
612
+ cliRunInspectionDocumentSchema,
613
+ cliRunExportDocumentSchema,
614
+ cliRunCancellationDocumentSchema,
615
+ cliRunCleanupDocumentSchema,
616
+ cliSessionListDocumentSchema,
617
+ cliSessionDocumentSchema,
618
+ cliChangeEnvelopeVerificationDocumentSchema,
619
+ cliStateStatusDocumentSchema,
620
+ cliStateExportDocumentSchema,
621
+ cliStateImportDocumentSchema,
622
+ cliErrorDocumentSchema,
623
+ changeEnvelopeSchema
624
+ ]);
625
+ var runEvent = (type, shape) => observationalDocument({
626
+ ...eventBase,
627
+ kind: z6.literal("run-event"),
628
+ type: z6.literal(type),
629
+ ...shape
630
+ });
631
+ var cliRunEventDocumentSchema = z6.discriminatedUnion("type", [
632
+ runEvent("text-delta", { textDelta: z6.string() }),
633
+ runEvent("tool-call", {
634
+ toolCallId: z6.string().min(1),
635
+ toolName: z6.string().min(1)
636
+ }),
637
+ runEvent("tool-result", {
638
+ toolCallId: z6.string().min(1),
639
+ toolName: z6.string().min(1),
640
+ isError: z6.boolean()
641
+ }),
642
+ runEvent("tool-approval-request", {
643
+ approvalRequestId: z6.string().min(1),
644
+ approvalKind: z6.string().min(1),
645
+ toolName: z6.string().min(1)
646
+ }),
647
+ runEvent("agent-approval-request", {
648
+ approvalRequestId: z6.string().min(1),
649
+ approvalKind: z6.string().min(1),
650
+ toolName: z6.string().min(1)
651
+ }),
652
+ runEvent("agent-approval-resolved", {
653
+ approvalRequestId: z6.string().min(1),
654
+ approved: z6.boolean()
655
+ }),
656
+ runEvent("provider-data", { provider: z6.string().min(1) }),
657
+ runEvent("image-generation", {
658
+ provider: z6.string().min(1),
659
+ partial: z6.boolean(),
660
+ id: z6.string().min(1).optional(),
661
+ index: nonnegativeInteger.optional()
662
+ }),
663
+ runEvent("finish", {
664
+ finishReason: z6.string().min(1).optional(),
665
+ usage: jsonObjectSchema.optional()
666
+ }),
667
+ runEvent("error", { error: z6.literal("Provider stream failed.") }),
668
+ runEvent("agent-run-start", {
669
+ currentStep: nonnegativeInteger,
670
+ maxSteps: nonnegativeInteger
671
+ }),
672
+ runEvent("agent-step-start", { stepIndex: nonnegativeInteger }),
673
+ runEvent("agent-step-finish", {
674
+ stepIndex: nonnegativeInteger,
675
+ status: z6.string().min(1),
676
+ toolCalls: nonnegativeInteger
677
+ }),
678
+ runEvent("agent-compaction", {
679
+ compactionId: z6.string().min(1),
680
+ reasons: z6.array(z6.string().min(1)),
681
+ messageCountBefore: nonnegativeInteger,
682
+ messageCountAfter: nonnegativeInteger
683
+ }),
684
+ runEvent("agent-run-finish", {
685
+ runId: z6.string().min(1),
686
+ status: z6.string().min(1),
687
+ provider: z6.string().min(1),
688
+ model: z6.string().min(1)
689
+ })
690
+ ]);
691
+ var cliStreamResultDocumentSchema = observationalDocument({
692
+ ...eventBase,
693
+ kind: z6.literal("run-stream-result"),
694
+ ...runIdentity,
695
+ steps: nonnegativeInteger,
696
+ toolCalls: nonnegativeInteger,
697
+ pendingApprovals: z6.array(observationalDocument({
698
+ id: z6.string().min(1),
699
+ kind: z6.string().min(1),
700
+ name: z6.string().min(1),
701
+ childRunId: z6.string().min(1).optional(),
702
+ childAgentId: z6.string().min(1).optional()
703
+ })),
704
+ children: z6.array(observationalDocument({
705
+ runId: z6.string().min(1),
706
+ status: z6.string().min(1)
707
+ }))
708
+ });
709
+ var cliStreamErrorDocumentSchema = observationalDocument({
710
+ ...eventBase,
711
+ kind: z6.literal("run-stream-error"),
712
+ error: cliErrorDocumentSchema.shape.error
713
+ });
714
+ var cliJsonLineDocumentSchema = z6.union([
715
+ cliRunEventDocumentSchema,
716
+ cliStreamResultDocumentSchema,
717
+ cliStreamErrorDocumentSchema
718
+ ]);
719
+
720
+ // src/cli/service-client-cli.ts
721
+ var runServiceCli = async (options, annotate) => {
722
+ const credentials = await readHarnessLocalCredentials(options.serviceFile);
723
+ const hello = await requestHarnessLocalService(credentials, "hello", { versions: [1] });
724
+ if (!hello.ok)
725
+ throw new HarnessStateConflictError("Service negotiation failed.");
726
+ const projectId = hello.projectId;
727
+ let sequence = 0;
728
+ const key = (purpose, supplied) => createHash("sha256").update(`${purpose}:${supplied ?? randomUUID()}`).digest("hex");
729
+ const call = async (command) => {
730
+ const r = await requestHarnessLocalService(credentials, "command", { protocolVersion: 1, requestId: `request_${randomUUID()}`, connectionId: hello.connectionId, command: { projectId, ...command } });
731
+ if (!r.ok)
732
+ throw new HarnessStateConflictError(`Service command failed: ${r.error.code}. Inspect durable state before retrying.`);
733
+ return r.data;
734
+ };
735
+ const getSession = async (sessionId) => {
736
+ const r = await call({ method: "session.get", sessionId });
737
+ if (r.kind !== "session")
738
+ throw new HarnessStateConflictError("Unexpected service response.");
739
+ return r.session;
740
+ };
741
+ const list = async (search) => {
742
+ const r = await call({ method: "session.list", ...search ? { search } : {} });
743
+ if (r.kind !== "sessions")
744
+ throw new HarnessStateConflictError("Unexpected service response.");
745
+ return r.sessions;
746
+ };
747
+ const create = async (idempotencyKey) => {
748
+ const r = await call({ method: "session.create", idempotencyKey: key("session", idempotencyKey) });
749
+ if (r.kind !== "session")
750
+ throw new HarnessStateConflictError("Unexpected service response.");
751
+ return r.session;
752
+ };
753
+ const print = (document) => process.stdout.write((options.json ? JSON.stringify(document, null, 2) : sanitizeTerminalText(JSON.stringify(document, null, 2))) + `
754
+ `);
755
+ if (options.command === "sessions") {
756
+ if (options.sessionsCommand === "list") {
757
+ const sessions = await list(options.sessionSearch);
758
+ print({ schemaVersion: 1, kind: "session-list", sessions });
759
+ return;
760
+ }
761
+ let session3 = await getSession(options.sessionId);
762
+ if (options.sessionsCommand === "rename") {
763
+ const renamed = await call({ method: "session.rename", sessionId: session3.sessionId, expectedRevision: session3.revision, idempotencyKey: key("rename"), title: options.sessionTitle });
764
+ if (renamed.kind !== "session")
765
+ throw new HarnessStateConflictError("Unexpected response.");
766
+ session3 = renamed.session;
767
+ } else if (options.sessionsCommand !== "inspect")
768
+ throw new HarnessConfigError("Unsupported service session command.");
769
+ print({ schemaVersion: 1, kind: "session", session: session3 });
770
+ return;
771
+ }
772
+ if (!["run", "resume", "chat"].includes(options.command))
773
+ throw new HarnessConfigError("This command does not support service mode.");
774
+ let session2;
775
+ if (options.sessionId)
776
+ session2 = await getSession(options.sessionId);
777
+ else if (options.command === "resume") {
778
+ const found = (await list()).find((s) => s.runs.some((r) => r.runId === options.runId));
779
+ if (!found)
780
+ throw new HarnessStateConflictError("Run session not found; supply --session.");
781
+ session2 = found;
782
+ } else if (options.continueSession) {
783
+ const latest = (await list())[0];
784
+ if (!latest)
785
+ throw new HarnessStateConflictError("No session to continue.");
786
+ session2 = latest;
787
+ } else
788
+ session2 = await create(options.idempotencyKey);
789
+ let activeRun;
790
+ let consoleInput;
791
+ const history = new ActivityHistory;
792
+ const seenMutations = new Set;
793
+ const currentRun = async (runId = activeRun ?? session2.runs.at(-1)?.runId) => {
794
+ if (!runId)
795
+ return;
796
+ const r = await call({ method: "run.get", sessionId: session2.sessionId, runId });
797
+ if (r.kind !== "run")
798
+ throw new HarnessStateConflictError("Unexpected run response.");
799
+ return r.run;
800
+ };
801
+ const cancel = async () => {
802
+ const run2 = await currentRun();
803
+ if (run2)
804
+ await call({ method: "run.cancel", sessionId: session2.sessionId, runId: run2.runId, expectedRevision: run2.revision, idempotencyKey: key("cancel") });
805
+ };
806
+ const cursorAtEnd = async () => {
807
+ let after = 0;
808
+ for (;; ) {
809
+ const page = await requestHarnessLocalService(credentials, "events", { projectId, sessionId: session2.sessionId, after });
810
+ after = page.nextCursor;
811
+ if (page.cursorExpired || page.events.length < 200)
812
+ return after;
813
+ }
814
+ };
815
+ const invoke = async (command) => {
816
+ let cursor = await cursorAtEnd();
817
+ let finished = false, streamed = false;
818
+ consoleInput?.startBackground();
819
+ const activity = new ToolActivity((text) => {
820
+ process.stderr.write(text);
821
+ }, Boolean(consoleInput && process.stdout.isTTY), () => process.stdout.columns || 80, () => consoleInput?.backgroundStatus ?? "");
822
+ const observe = (a) => {
823
+ if (options.json || options.jsonl)
824
+ return;
825
+ history.observeService(a);
826
+ if (a.type === "agent-step-start" || a.type === "agent-run-start")
827
+ activity.phase("Waiting for model response");
828
+ else if (a.type === "agent-compaction")
829
+ activity.phase("Updating context");
830
+ else if (a.type === "tool-call")
831
+ activity.start(typeof a.toolName === "string" ? a.toolName : undefined);
832
+ else if (a.type === "tool-result")
833
+ activity.finish(typeof a.toolName === "string" ? a.toolName : "tool", a.isError !== true);
834
+ else if (["agent-run-finish", "tool-approval-request", "agent-approval-request"].includes(String(a.type)))
835
+ activity.flush();
836
+ else if (a.type === "text-delta")
837
+ activity.pause();
838
+ };
839
+ const pending = call(command).finally(() => {
840
+ finished = true;
841
+ });
842
+ pending.catch(() => {
843
+ return;
844
+ });
845
+ try {
846
+ do {
847
+ const page = await requestHarnessLocalService(credentials, "events", { projectId, sessionId: session2.sessionId, after: cursor });
848
+ if (page.cursorExpired)
849
+ throw new HarnessStateConflictError("Service activity cursor expired; reopen the session snapshot.");
850
+ cursor = page.nextCursor;
851
+ for (const event of page.events) {
852
+ activeRun = event.runId;
853
+ const a = event.activity;
854
+ if (a.type === "checkpoint" || a.type === "user-message")
855
+ continue;
856
+ observe(a);
857
+ if (options.jsonl)
858
+ process.stdout.write(JSON.stringify({ ...a, schemaVersion: 1, kind: "run-event", sequence: ++sequence }) + `
859
+ `);
860
+ else if (!options.json && typeof a.textDelta === "string") {
861
+ process.stdout.write(sanitizeTerminalText(a.textDelta));
862
+ streamed = true;
863
+ }
864
+ }
865
+ if (!finished)
866
+ await Promise.race([pending.then(() => {
867
+ return;
868
+ }, () => {
869
+ return;
870
+ }), delay(40)]);
871
+ } while (!finished);
872
+ for (;; ) {
873
+ const tail = await requestHarnessLocalService(credentials, "events", { projectId, sessionId: session2.sessionId, after: cursor });
874
+ if (tail.cursorExpired)
875
+ throw new HarnessStateConflictError("Service activity cursor expired; inspect session.");
876
+ for (const event of tail.events) {
877
+ const a = event.activity;
878
+ if (a.type === "checkpoint" || a.type === "user-message")
879
+ continue;
880
+ observe(a);
881
+ if (options.jsonl)
882
+ process.stdout.write(JSON.stringify({ ...a, schemaVersion: 1, kind: "run-event", sequence: ++sequence }) + `
883
+ `);
884
+ else if (!options.json && typeof a.textDelta === "string") {
885
+ process.stdout.write(sanitizeTerminalText(a.textDelta));
886
+ streamed = true;
887
+ }
888
+ }
889
+ cursor = tail.nextCursor;
890
+ if (tail.events.length < 200)
891
+ break;
892
+ }
893
+ const result = await pending;
894
+ if (result.kind !== "run")
895
+ throw new HarnessStateConflictError("Unexpected run response.");
896
+ session2 = result.session;
897
+ return { run: result.run, streamed };
898
+ } catch (e) {
899
+ throw annotate(e, sequence);
900
+ } finally {
901
+ activity.flush();
902
+ consoleInput?.stopBackground();
903
+ activeRun = undefined;
904
+ }
905
+ };
906
+ const finish = (run2, streamed) => {
907
+ const document = cliRunResultDocumentSchema.parse(run2.cliResult);
908
+ if (options.jsonl)
909
+ process.stdout.write(serializeStreamResult({ runId: document.runId, status: document.status, provider: document.provider, model: document.model, steps: document.steps, toolCalls: document.toolCalls, pendingApprovals: document.pendingApprovals.map((a) => ({ id: a.id, kind: a.kind, name: a.name, ...a.childRunId ? { childRunId: a.childRunId } : {}, ...a.childAgentId ? { childAgentId: a.childAgentId } : {} })), children: document.children.map((c) => ({ runId: c.runId, status: c.status })) }, ++sequence) + `
910
+ `);
911
+ else if (options.json)
912
+ print({ ...document, sessionId: session2.sessionId });
913
+ else {
914
+ if (!streamed)
915
+ process.stdout.write(sanitizeTerminalText(document.output));
916
+ process.stdout.write(`
917
+ Run ${run2.runId} · ${run2.status} · session ${session2.sessionId}
918
+ `);
919
+ }
920
+ if (!options.json && !options.jsonl) {
921
+ const fresh = document.mutations.filter((entry) => !seenMutations.has(entry.id));
922
+ for (const entry of fresh)
923
+ seenMutations.add(entry.id);
924
+ while (seenMutations.size > 2000)
925
+ seenMutations.delete(seenMutations.values().next().value);
926
+ const receipt = formatAppliedFiles(fresh, "Review changes in the host workspace");
927
+ if (receipt) {
928
+ process.stdout.write(receipt);
929
+ history.add(receipt.trim());
930
+ }
931
+ }
932
+ if (["failed", "cancelled", "timed_out"].includes(run2.status))
933
+ process.exitCode = 1;
934
+ };
935
+ const decision = async (run2, approve) => invoke({ method: "approval.resolve", sessionId: session2.sessionId, runId: run2.runId, expectedRevision: run2.revision, idempotencyKey: key("decision"), decisions: run2.approvals.map((a) => ({ approvalId: a.approvalId, digest: a.digest, approve })) });
936
+ const start = async (prompt) => {
937
+ session2 = await getSession(session2.sessionId);
938
+ let result = await invoke({ method: "run.start", sessionId: session2.sessionId, expectedRevision: session2.revision, idempotencyKey: key("run", options.idempotencyKey), prompt });
939
+ while (options.yes && result.run.status === "waiting_approval")
940
+ result = await decision(result.run, true);
941
+ finish(result.run, result.streamed);
942
+ };
943
+ const interrupt = () => {
944
+ if (!activeRun)
945
+ return;
946
+ cancel().catch(() => process.stderr.write(`Cancellation conflicted; inspect the run before retrying.
947
+ `));
948
+ };
949
+ process.on("SIGINT", interrupt);
950
+ try {
951
+ if (options.command === "resume") {
952
+ const run2 = await currentRun(options.runId);
953
+ if (!run2)
954
+ throw new HarnessStateConflictError("Run not found.");
955
+ const result = await decision(run2, options.approve === true);
956
+ finish(result.run, result.streamed);
957
+ return;
958
+ }
959
+ if (options.command === "run") {
960
+ let prompt = options.prompt ?? "";
961
+ if (!prompt && !process.stdin.isTTY) {
962
+ for await (const chunk of process.stdin) {
963
+ prompt += chunk.toString();
964
+ if (Buffer.byteLength(prompt) > 64 * 1024)
965
+ throw new HarnessConfigError("Prompt exceeds 64 KiB.");
966
+ }
967
+ }
968
+ if (!prompt.trim())
969
+ throw new HarnessConfigError("A prompt is required.");
970
+ await start(prompt);
971
+ return;
972
+ }
973
+ const input = new ConsoleInput(process.stdin, process.stdout, Boolean(process.stdin.isTTY), "service");
974
+ input.onInterrupt = interrupt;
975
+ consoleInput = input;
976
+ try {
977
+ process.stdout.write(formatConsoleWelcome({ version: HARNESS_VERSION, workspace: projectId, sessionId: session2.sessionId, service: true }, { columns: process.stdout.columns ?? 80 }) + `
978
+ `);
979
+ const previous = await currentRun();
980
+ if (previous)
981
+ print(previous);
982
+ for (;; ) {
983
+ input.setQueueEnabled(!session2.runs.some((run2) => ["created", "running", "waiting_approval"].includes(run2.status)));
984
+ const raw = await input.compose({ model: "local service", status: session2.runs.at(-1)?.status === "waiting_approval" ? "approval pending · /pending" : "ready", ...session2.title ? { title: session2.title } : {}, automaticApprovals: options.yes === true }).catch((e) => {
985
+ if (input.isClosed)
986
+ return "/exit";
987
+ if (e instanceof Error && e.name === "AbortError")
988
+ return "";
989
+ throw e;
990
+ });
991
+ const literal = input.lastSubmissionWasPaste || raw.includes(`
992
+ `);
993
+ let text = literal ? raw : raw.trim();
994
+ if (!text)
995
+ continue;
996
+ if (!literal && ["/exit", "/quit"].includes(text))
997
+ break;
998
+ try {
999
+ if (!literal && text.startsWith("/")) {
1000
+ if (text === "/menu") {
1001
+ const selected = await navigateConsole(input, { entry: "menu", current: { provider: "service", model: "host" }, providers: [], service: true, sessions: async () => (await list()).map((s) => ({ value: s.sessionId, label: s.title ?? "Untitled conversation", detail: s.sessionId })) });
1002
+ if (!selected || !("command" in selected))
1003
+ continue;
1004
+ text = selected.command;
1005
+ }
1006
+ if (text === "/help" || text === "/help all")
1007
+ process.stdout.write(formatConsoleHelp("service", text === "/help all"));
1008
+ else if (text === "/activity" || text === "/activity clear") {
1009
+ if (text.endsWith(" clear"))
1010
+ history.clear();
1011
+ process.stdout.write(history.render());
1012
+ } else if (text === "/queue clear") {
1013
+ input.clearQueue();
1014
+ process.stdout.write(`Queued tasks cleared.
1015
+ `);
1016
+ } else if (text === "/queue")
1017
+ process.stdout.write(input.queueSummary());
1018
+ else if (text === "/sessions" || text.startsWith("/sessions "))
1019
+ print(await list(text.slice(9).trim() || undefined));
1020
+ else if (text === "/new") {
1021
+ session2 = await create();
1022
+ input.clearHistory();
1023
+ history.clear();
1024
+ seenMutations.clear();
1025
+ process.stdout.write(`Session ${session2.sessionId}.
1026
+ `);
1027
+ } else if (text === "/resume" || text.startsWith("/resume ")) {
1028
+ let id2 = text.slice(7).trim();
1029
+ if (!id2) {
1030
+ const selected = await input.select("Zhivex / Conversations", (await list()).map((s) => ({ value: s.sessionId, label: s.title ?? "Untitled conversation", detail: s.sessionId })));
1031
+ if (!selected)
1032
+ continue;
1033
+ id2 = selected;
1034
+ }
1035
+ session2 = await getSession(id2);
1036
+ input.clearHistory();
1037
+ history.clear();
1038
+ seenMutations.clear();
1039
+ print(await currentRun());
1040
+ } else if (text.startsWith("/rename ")) {
1041
+ const r = await call({ method: "session.rename", sessionId: session2.sessionId, expectedRevision: session2.revision, idempotencyKey: key("rename"), title: text.slice(8) });
1042
+ if (r.kind === "session")
1043
+ session2 = r.session;
1044
+ } else if (["/status", "/pending"].includes(text))
1045
+ print(await currentRun() ?? { message: "No run yet." });
1046
+ else if (text === "/paste") {
1047
+ const draft = await input.multiline();
1048
+ process.stdout.write(`Draft preview:
1049
+ ${sanitizeTerminalText(draft)}
1050
+ `);
1051
+ if ((await input.question("Send this draft? Type send: ")).trim() === "send" && draft.trim()) {
1052
+ input.rememberPrompt(draft, true);
1053
+ await start(draft);
1054
+ }
1055
+ } else if (text === "/cancel")
1056
+ await cancel();
1057
+ else if (["/approve", "/deny"].includes(text)) {
1058
+ const run2 = await currentRun();
1059
+ if (run2) {
1060
+ const r = await decision(run2, text === "/approve");
1061
+ finish(r.run, r.streamed);
1062
+ }
1063
+ } else
1064
+ process.stdout.write(`Unsupported service command. Use /help.
1065
+ `);
1066
+ } else {
1067
+ input.rememberPrompt(text, literal);
1068
+ await start(text);
1069
+ }
1070
+ } catch {
1071
+ if (input.isClosed)
1072
+ break;
1073
+ process.stderr.write(`Service operation failed. Inspect /status before retrying.
1074
+ `);
1075
+ }
1076
+ }
1077
+ } finally {
1078
+ input.close();
1079
+ }
1080
+ } finally {
1081
+ process.off("SIGINT", interrupt);
1082
+ }
1083
+ };
1084
+ export {
1085
+ runServiceCli
1086
+ };