@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.
- package/CHANGELOG.md +160 -0
- package/README.md +14 -7
- package/SECURITY.md +1 -1
- package/SUPPORT.md +3 -3
- package/benchmarks/README.md +17 -0
- package/contracts/public-api.json +95 -5
- package/contracts/stable-api-signatures.json +38 -38
- package/dist/acp-cli.d.ts +2 -0
- package/dist/acp-cli.js +15938 -0
- package/dist/cli/arguments.d.ts +7 -1
- package/dist/cli/cli-credentials.d.ts +6 -1
- package/dist/cli/cli-options.d.ts +1 -1
- package/dist/cli/cli-profiles.d.ts +15 -0
- package/dist/cli/cli-stream.d.ts +3 -3
- package/dist/cli/console/console-budget.d.ts +9 -0
- package/dist/cli/console/console-commands.d.ts +3 -3
- package/dist/cli/console/console-compaction.d.ts +18 -0
- package/dist/cli/console/console-input.d.ts +22 -3
- package/dist/cli/console/console-navigation.d.ts +3 -0
- package/dist/cli/console/console-presentation.d.ts +9 -2
- package/dist/cli/console/console-progress.d.ts +6 -0
- package/dist/cli/console/console-reasoning.d.ts +3 -0
- package/dist/cli/doctor.d.ts +2 -2
- package/dist/cli/presentation.d.ts +8 -1
- package/dist/cli/qwen-connection.d.ts +23 -0
- package/dist/cli/run-document.d.ts +4 -4
- package/dist/cli/terminal/activity-history.d.ts +15 -0
- package/dist/cli/terminal/session-grants.d.ts +4 -0
- package/dist/cli/terminal/terminal-markdown.d.ts +7 -4
- package/dist/cli/terminal/terminal-table.d.ts +6 -0
- package/dist/cli/terminal/terminal-ui.d.ts +3 -0
- package/dist/cli/terminal/tool-activity.d.ts +21 -10
- package/dist/cli/tool-execution.d.ts +1 -0
- package/dist/cli-3jmy4h5h.js +5798 -0
- package/dist/cli-entry-1bx83sw4.js +4 -0
- package/dist/cli-entry-427869g9.js +2009 -0
- package/dist/cli-entry-64pdp3k5.js +17 -0
- package/dist/cli-entry-b1mfvmxe.js +376 -0
- package/dist/cli-entry-c2f58zj2.js +13602 -0
- package/dist/cli-entry.d.ts +2 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +15 -19168
- package/dist/client/acp-stdio.d.ts +9 -0
- package/dist/client/acp.d.ts +18 -0
- package/dist/client/index.d.ts +2 -0
- package/dist/client/json-contracts.d.ts +22 -8
- package/dist/config-1k9t4jhh.js +59 -0
- package/dist/context/adaptive-compaction.d.ts +2 -0
- package/dist/context/compaction.d.ts +3 -1
- package/dist/context/qwen-reasoning.d.ts +5 -0
- package/dist/context/scoped-context.d.ts +61 -0
- package/dist/context/semantic-compaction.d.ts +21 -0
- package/dist/context/task-memory.d.ts +13 -8
- package/dist/execution/execution-environment.d.ts +5 -0
- package/dist/execution/oci-observability.d.ts +2 -0
- package/dist/execution/patch-diagnostics.d.ts +6 -0
- package/dist/hostile-repository-demo.js +4614 -1930
- package/dist/index.d.ts +13 -1
- package/dist/index.js +16435 -12486
- package/dist/integrations/mcp.d.ts +23 -3
- package/dist/models/catalog.d.ts +76 -0
- package/dist/models/compaction-recommendations.d.ts +28 -0
- package/dist/models/sdk-catalog-adapter.d.ts +7 -0
- package/dist/persistence/operations.d.ts +10 -6
- package/dist/persistence/state-backup-stream.d.ts +4 -0
- package/dist/persistence/state-backup.d.ts +52 -0
- package/dist/persistence/state-gitignore.d.ts +2 -0
- package/dist/persistence/workspace-checkpoints.d.ts +149 -0
- package/dist/providers/meta-continuation.d.ts +1 -1
- package/dist/providers/meta-errors.d.ts +2 -0
- package/dist/providers/meta-replay.d.ts +2 -0
- package/dist/providers/qwen-context.d.ts +2 -0
- package/dist/providers/qwen-hosted-policy.d.ts +5 -0
- package/dist/providers/reasoning.d.ts +18 -0
- package/dist/runtime/config.d.ts +12 -3
- package/dist/runtime/context-runtime.d.ts +12 -0
- package/dist/runtime/error-diagnostics.d.ts +641 -0
- package/dist/runtime/harness.d.ts +13 -4
- package/dist/runtime/model-edit-references.d.ts +8 -0
- package/dist/runtime/oci-delivery.d.ts +17 -0
- package/dist/runtime/progress-monitor.d.ts +33 -0
- package/dist/runtime/provider-diagnostics.d.ts +35 -0
- package/dist/runtime/runtime-checkpoints.d.ts +3 -0
- package/dist/runtime/runtime-diagnostics.d.ts +5 -5
- package/dist/runtime/runtime-policy.d.ts +14 -6
- package/dist/runtime/time-to-safe-fix.d.ts +308 -1
- package/dist/runtime/tool-execution.d.ts +11 -0
- package/dist/runtime/tool-policy.d.ts +55 -0
- package/dist/runtime/tool-scheduling.d.ts +5 -0
- package/dist/runtime/usage-ledger.d.ts +1 -0
- package/dist/service-cli.js +9422 -6622
- package/dist/service-client-cli-yx56n0hc.js +1086 -0
- package/dist/tools/dependency-read.d.ts +63 -0
- package/dist/tools/execution.d.ts +8 -8
- package/dist/tools/workspace.d.ts +31 -15
- package/dist/verify-historical-migrations.js +5272 -2437
- package/dist/workspace/file-security.d.ts +6 -0
- package/dist/zhx.js +15 -19168
- package/docs/ACP.md +55 -0
- package/docs/CLI.md +292 -29
- package/docs/CONTEXT_ENGINEERING.md +184 -20
- package/docs/CREDENTIALS.md +38 -6
- package/docs/DURABLE_OPERATIONS.md +10 -0
- package/docs/EXTENSIBILITY.md +101 -4
- package/docs/FIRST_USE.md +7 -5
- package/docs/MODEL_CATALOG.md +52 -1
- package/docs/README.md +1 -0
- package/docs/REPOSITORY_EDITING.md +42 -0
- package/docs/STABILITY.md +2 -0
- package/docs/SUPPORT_MATRIX_1_1.md +17 -0
- package/docs/USAGE.md +9 -0
- package/docs/WORKSPACE_CHECKPOINTS.md +27 -0
- package/docs/images/cli-conversation.png +0 -0
- package/docs/support-matrix-1.1.json +29 -0
- package/evaluations/golden-expectations.json +5 -0
- package/evaluations/representative-assembly-matrix.json +145 -1
- package/evaluations/representative-repositories-v2.jsonl +7 -0
- package/examples/README.md +2 -2
- 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
|
+
};
|