@zhivex-ai/harness 1.4.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +32 -10
- package/README.md +7 -5
- package/SUPPORT.md +2 -2
- package/contracts/client-protocol-v1.schema.json +593 -0
- package/contracts/engine-api.json +156 -0
- package/contracts/public-api.json +12 -0
- package/contracts/stable-api-signatures.json +36 -36
- package/dist/acp-cli.js +54 -20
- package/dist/approvals/approval-diff.d.ts +2 -1
- package/dist/approvals/approval-preview.d.ts +1 -1
- package/dist/audit/index.d.ts +3 -0
- package/dist/audit/index.js +482 -0
- package/dist/audit/pack.d.ts +72 -0
- package/dist/audit-pack-kvw7ng34.js +532 -0
- package/dist/cli/arguments.d.ts +3 -1
- package/dist/cli/audit-pack.d.ts +24 -0
- package/dist/cli/cli-credentials.d.ts +6 -0
- package/dist/cli/cli-profiles.d.ts +4 -2
- package/dist/cli/node-engine.d.ts +2 -0
- package/dist/cli-entry-75j3r49b.js +484 -0
- package/dist/cli-entry-928p8h41.js +10067 -0
- package/dist/cli-entry-h2yc9x37.js +10350 -0
- package/dist/{cli-entry-20w6nh0k.js → cli-entry-hdtfef27.js} +439 -19
- package/dist/{cli-entry-w0hterjs.js → cli-entry-q8bgkn9m.js} +40 -13
- package/dist/{cli-2h37qyvg.js → cli-vyrytn3m.js} +253 -644
- package/dist/cli.js +27 -2
- package/dist/client/json-contracts.d.ts +4 -0
- package/dist/client/protocol.d.ts +133 -0
- package/dist/client/task-control-host.d.ts +400 -0
- package/dist/client/task-projection-host.d.ts +12 -0
- package/dist/client/task-projection.d.ts +168 -0
- package/dist/compat/code-support.js +28 -22
- package/dist/{config-qt69hkqj.js → config-r9fdhce6.js} +3 -3
- package/dist/{config-j9624t6t.js → config-vyajmksy.js} +1 -1
- package/dist/engine/acp.js +15 -11
- package/dist/engine/client.js +14 -10
- package/dist/engine/desktop-providers-v1.d.ts +2 -0
- package/dist/engine/desktop-providers-v1.js +23 -3
- package/dist/engine/desktop-state-v1.js +11 -8
- package/dist/engine/index.d.ts +3 -0
- package/dist/engine/index.js +101 -554
- package/dist/engine/mcp-stdio-v1.js +8 -6
- package/dist/engine/models.js +76 -4
- package/dist/engine/protocol.d.ts +2 -0
- package/dist/engine/protocol.js +110 -0
- package/dist/engine/service.js +15 -11
- package/dist/hostile-repository-demo.js +1232 -564
- package/dist/{index-8zjmnyw5.js → index-1265j7t2.js} +73 -6
- package/dist/{index-nmjdwd4p.js → index-4gt045j0.js} +109 -1
- package/dist/{index-pdmevfxv.js → index-5zbq9ztj.js} +5 -259
- package/dist/{index-6dft2vev.js → index-63gbp0cz.js} +5 -3
- package/dist/index-6dxrbnxm.js +719 -0
- package/dist/{index-pp474137.js → index-6fp7kdpx.js} +769 -933
- package/dist/{index-61gthdz6.js → index-8sm2a1wa.js} +1 -1
- package/dist/{index-rkbf7dqg.js → index-96ezrvg2.js} +57 -13
- package/dist/index-bt2p8x7r.js +329 -0
- package/dist/index-c39197wq.js +552 -0
- package/dist/{index-m82cfspw.js → index-eps3c3g6.js} +877 -963
- package/dist/{index-s2k2edts.js → index-fqqz1yt8.js} +110 -1544
- package/dist/{index-m34q25jj.js → index-ggstwr0v.js} +192 -838
- package/dist/index-jpdvn09j.js +490 -0
- package/dist/{index-xqxeypt5.js → index-mzydbzp8.js} +76 -4
- package/dist/index-pq3kz1r8.js +269 -0
- package/dist/{index-wg1sd3at.js → index-qfsrrnz6.js} +1 -1
- package/dist/{index-937cb7y8.js → index-vc7yxz50.js} +561 -35
- package/dist/{index-5jhgatga.js → index-vvzc5ezz.js} +7 -6
- package/dist/index-wwthv10a.js +1507 -0
- package/dist/{index-tfzta544.js → index-xfedewpt.js} +17 -9
- package/dist/index-yx52bt4a.js +511 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +93 -77
- package/dist/integrations/mcp-stdio-tools.d.ts +4 -1
- package/dist/internal/desktop/providers.d.ts +2 -0
- package/dist/models/catalog.d.ts +2 -0
- package/dist/persistence/sqlite-database.d.ts +1 -0
- package/dist/providers/azure-openai.d.ts +14 -0
- package/dist/providers/bedrock.d.ts +23 -0
- package/dist/providers/providers.d.ts +1 -1
- package/dist/runtime/budget-ledger-scope.d.ts +14 -0
- package/dist/runtime/durable-review-group.d.ts +33 -0
- package/dist/runtime/harness.d.ts +11 -0
- package/dist/runtime/run-interruption.d.ts +7 -0
- package/dist/runtime/shared-budget.d.ts +30 -0
- package/dist/runtime/task-continuity.d.ts +300 -77
- package/dist/service-cli.js +15 -11
- package/dist/{service-client-cli-fn54ev6w.js → service-client-cli-v6qptg9x.js} +400 -305
- package/dist/tools/workspace.d.ts +2 -2
- package/dist/verify-historical-migrations.js +1237 -566
- package/dist/workspace/edit-contracts.d.ts +2 -2
- package/dist/workspace/path-policy.d.ts +2 -1
- package/dist/workspace/workspace.d.ts +13 -0
- package/dist/zhx.js +27 -2
- package/docs/AUDIT_PACK.md +99 -0
- package/docs/AZURE_OPENAI.md +53 -0
- package/docs/BEDROCK.md +56 -0
- package/docs/CLI.md +15 -0
- package/docs/CLIENT_PROTOCOL.md +178 -0
- package/docs/CODE_RELEASE.md +59 -7
- package/docs/CODE_WEB_TASKS.md +116 -0
- package/docs/CONTEXT_ENGINEERING.md +59 -0
- package/docs/CREDENTIALS.md +21 -0
- package/docs/DURABLE_OPERATIONS.md +93 -1
- package/docs/ENGINE_API.md +5 -2
- package/docs/EXTENSIBILITY.md +8 -4
- package/docs/FIRST_USE.md +6 -6
- package/docs/MINIMUM_TASK_AUTHORITY.md +3 -3
- package/docs/PROJECT_MEMORY.md +1 -1
- package/docs/PUBLIC_SECURITY.md +14 -1
- package/docs/README.md +6 -1
- package/docs/REPOSITORY_EDITING.md +1 -1
- package/docs/STABILITY.md +3 -1
- package/docs/SUPPORT_MATRIX.md +1 -1
- package/docs/SUPPORT_MATRIX_1_1.md +1 -1
- package/docs/TOOL_POLICY.md +4 -1
- package/docs/USAGE.md +3 -1
- package/docs/VERTEX.md +2 -2
- package/docs/WEB_LIMITS.md +4 -3
- package/docs/adr/0002-isolated-mcp-stdio.md +7 -4
- package/docs/support-matrix-1.1.json +3 -1
- package/docs/support-matrix.json +6 -4
- package/evaluations/code-task-ui.json +20 -0
- package/evaluations/representative-assembly-matrix.json +19 -1
- package/evaluations/task-projection.json +10 -0
- package/evaluations/task-recovery-lab.json +60 -0
- package/examples/README.md +3 -3
- package/package.json +23 -13
- package/dist/cli-entry-4ngptr62.js +0 -19900
- package/dist/index-m49jx72n.js +0 -220
|
@@ -0,0 +1,532 @@
|
|
|
1
|
+
import {
|
|
2
|
+
exportHarnessGovernanceReport,
|
|
3
|
+
harnessGovernanceReportSchema
|
|
4
|
+
} from "./cli-entry-75j3r49b.js";
|
|
5
|
+
import {
|
|
6
|
+
APPROVAL_HISTORY_KEY,
|
|
7
|
+
CliUsageError,
|
|
8
|
+
TASK_BUDGET_ACCOUNT_KEY,
|
|
9
|
+
TaskBudget,
|
|
10
|
+
USAGE_LEDGER_KEY,
|
|
11
|
+
UsageLedger,
|
|
12
|
+
approvalDecisionViews,
|
|
13
|
+
harnessPolicyDecisionEventSchema,
|
|
14
|
+
inspectUsageLedger,
|
|
15
|
+
openCliSessionStore,
|
|
16
|
+
openHarnessActivityStore,
|
|
17
|
+
openHarnessPersistence,
|
|
18
|
+
readRegularFileNoFollow,
|
|
19
|
+
validateStateDirectory
|
|
20
|
+
} from "./cli-entry-928p8h41.js";
|
|
21
|
+
import {
|
|
22
|
+
HARNESS_VERSION
|
|
23
|
+
} from "./cli-entry-q8bgkn9m.js";
|
|
24
|
+
import {
|
|
25
|
+
resolveHarnessConfig
|
|
26
|
+
} from "./cli-entry-hdtfef27.js";
|
|
27
|
+
import"./cli-entry-1bx83sw4.js";
|
|
28
|
+
|
|
29
|
+
// src/cli/audit-pack.ts
|
|
30
|
+
import path2 from "node:path";
|
|
31
|
+
|
|
32
|
+
// src/audit/pack.ts
|
|
33
|
+
import { createHash, createHmac, timingSafeEqual } from "node:crypto";
|
|
34
|
+
import { lstat, mkdir, readdir, rm, writeFile } from "node:fs/promises";
|
|
35
|
+
import path from "node:path";
|
|
36
|
+
import { z } from "zod";
|
|
37
|
+
import { createRedactionPolicy } from "@zhivex-ai/agents";
|
|
38
|
+
var MAX_FILE_BYTES = 8 * 1024 * 1024;
|
|
39
|
+
var MAX_PACK_BYTES = 32 * 1024 * 1024;
|
|
40
|
+
var MAX_ACTIVITY_EVENTS = 2000;
|
|
41
|
+
var COMPONENT_NAMES = ["governance-report.json", "approvals.json", "policy-decisions.json", "redaction.jsonl", "usage-ledger.json"];
|
|
42
|
+
var digest = z.string().regex(/^[a-f0-9]{64}$/);
|
|
43
|
+
var relativePath = z.string().regex(/^[A-Za-z0-9._-]{1,80}(?:\/[A-Za-z0-9._-]{1,80}){0,3}$/);
|
|
44
|
+
var fileEntry = z.strictObject({ path: relativePath, sha256: digest, bytes: z.number().int().nonnegative().safe() });
|
|
45
|
+
var subjectSchema = z.strictObject({
|
|
46
|
+
kind: z.enum(["run", "task"]),
|
|
47
|
+
id: z.string().min(1).max(256),
|
|
48
|
+
runIds: z.array(z.string().min(1).max(256)).min(1).max(64)
|
|
49
|
+
});
|
|
50
|
+
var unsignedManifestSchema = z.strictObject({
|
|
51
|
+
schemaVersion: z.literal(1),
|
|
52
|
+
kind: z.literal("zhivex-harness-audit-pack"),
|
|
53
|
+
integrity: z.literal("hmac-sha256"),
|
|
54
|
+
exporterVersion: z.string().regex(/^\d+\.\d+\.\d+(?:[-+][a-zA-Z0-9.-]+)?$/),
|
|
55
|
+
createdAt: z.iso.datetime(),
|
|
56
|
+
subject: subjectSchema,
|
|
57
|
+
files: z.array(fileEntry).min(5).max(320)
|
|
58
|
+
}).superRefine((value, ctx) => {
|
|
59
|
+
const seen = new Set;
|
|
60
|
+
for (const file of value.files) {
|
|
61
|
+
if (seen.has(file.path) || file.path === "manifest.json")
|
|
62
|
+
ctx.addIssue({ code: "custom", message: "Duplicate or reserved audit pack path." });
|
|
63
|
+
seen.add(file.path);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
var signatureSchema = z.strictObject({
|
|
67
|
+
algorithm: z.literal("hmac-sha256"),
|
|
68
|
+
keyId: z.string().regex(/^[a-f0-9]{16}$/),
|
|
69
|
+
value: z.string().regex(/^[A-Za-z0-9+/]{43}=$/)
|
|
70
|
+
});
|
|
71
|
+
var auditPackManifestSchema = unsignedManifestSchema.extend({ signature: signatureSchema });
|
|
72
|
+
var accountView = z.object({
|
|
73
|
+
taskId: z.string().min(1).max(256),
|
|
74
|
+
runs: z.array(z.string().min(1).max(256)).max(64)
|
|
75
|
+
}).passthrough();
|
|
76
|
+
function fail(code) {
|
|
77
|
+
throw new Error(code);
|
|
78
|
+
}
|
|
79
|
+
var canonical = (value) => Array.isArray(value) ? `[${value.map(canonical).join(",")}]` : value && typeof value === "object" ? `{${Object.entries(value).filter(([, item]) => item !== undefined).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, item]) => `${JSON.stringify(key)}:${canonical(item)}`).join(",")}}` : JSON.stringify(value) ?? "null";
|
|
80
|
+
var canonicalizeAuditPackManifest = (value) => canonical(unsignedManifestSchema.parse(value));
|
|
81
|
+
var keyIdFor = (key) => createHash("sha256").update(key).digest("hex").slice(0, 16);
|
|
82
|
+
var signManifest = (unsigned, key) => createHmac("sha256", key).update(canonicalizeAuditPackManifest(unsigned)).digest("base64");
|
|
83
|
+
var assertKey = (key) => {
|
|
84
|
+
if (key.byteLength < 32 || key.byteLength > 4096)
|
|
85
|
+
fail("AUDIT_PACK_KEY_INVALID");
|
|
86
|
+
};
|
|
87
|
+
var redaction = createRedactionPolicy({ includeEmails: true });
|
|
88
|
+
var redactText = (value) => redaction.redactText(value).replace(/\b(?:sk|ghp|github_pat|xox[baprs])[-_][A-Za-z0-9_-]+/gi, "[REDACTED]");
|
|
89
|
+
var redactValue = (value) => typeof value === "string" ? redactText(value) : Array.isArray(value) ? value.map(redactValue) : value && typeof value === "object" ? Object.fromEntries(Object.entries(value).map(([key, item]) => [key, redactValue(item)])) : value;
|
|
90
|
+
var sameScope = (state, scope) => !state.scope || state.scope.tenantId === scope?.tenantId && state.scope.userId === scope?.userId && state.scope.namespace === scope?.namespace;
|
|
91
|
+
var contained = (root, relativePath2) => {
|
|
92
|
+
if (relativePath2.includes("\\") || path.isAbsolute(relativePath2) || relativePath2.split("/").some((part) => part === "" || part === "." || part === ".."))
|
|
93
|
+
fail("AUDIT_PACK_PATH_INVALID");
|
|
94
|
+
const target = path.resolve(root, relativePath2);
|
|
95
|
+
const relative = path.relative(root, target);
|
|
96
|
+
if (relative.startsWith("..") || path.isAbsolute(relative))
|
|
97
|
+
fail("AUDIT_PACK_PATH_INVALID");
|
|
98
|
+
return target;
|
|
99
|
+
};
|
|
100
|
+
var runSegment = (runId, used) => {
|
|
101
|
+
const base = /^[A-Za-z0-9._-]{1,64}$/.test(runId) ? runId : `run-${createHash("sha256").update(runId).digest("hex").slice(0, 16)}`;
|
|
102
|
+
let name = base;
|
|
103
|
+
for (let suffix = 2;used.has(name); suffix += 1)
|
|
104
|
+
name = `${base}-${suffix}`;
|
|
105
|
+
used.add(name);
|
|
106
|
+
return name;
|
|
107
|
+
};
|
|
108
|
+
async function loadRun(store, scope, runId) {
|
|
109
|
+
const state = await store.load(runId, scope);
|
|
110
|
+
if (!state || state.runId !== runId || !sameScope(state, scope))
|
|
111
|
+
fail("AUDIT_PACK_SUBJECT_UNAVAILABLE");
|
|
112
|
+
return structuredClone(state);
|
|
113
|
+
}
|
|
114
|
+
async function readJournal(store, scope, runId) {
|
|
115
|
+
if (!store.listToolCalls)
|
|
116
|
+
return;
|
|
117
|
+
const listed = await store.listToolCalls(runId, scope);
|
|
118
|
+
return listed ? structuredClone(listed) : undefined;
|
|
119
|
+
}
|
|
120
|
+
async function captureRun(store, scope, runId) {
|
|
121
|
+
return { state: await loadRun(store, scope, runId), journal: await readJournal(store, scope, runId) };
|
|
122
|
+
}
|
|
123
|
+
var sameJson = (left, right) => JSON.stringify(left) === JSON.stringify(right);
|
|
124
|
+
async function assertCaptured(store, scope, captured) {
|
|
125
|
+
const current = await store.load(captured.state.runId, scope);
|
|
126
|
+
const currentJournal = store.listToolCalls ? await store.listToolCalls(captured.state.runId, scope) : undefined;
|
|
127
|
+
if (!current || !sameJson(current, captured.state) || !sameJson(currentJournal, captured.journal))
|
|
128
|
+
fail("AUDIT_PACK_STATE_CHANGED");
|
|
129
|
+
}
|
|
130
|
+
function snapshotStore(real, captured) {
|
|
131
|
+
return {
|
|
132
|
+
async load(id, scope) {
|
|
133
|
+
const snap = captured.get(id);
|
|
134
|
+
if (snap)
|
|
135
|
+
return structuredClone(snap.state);
|
|
136
|
+
return real.load(id, scope);
|
|
137
|
+
},
|
|
138
|
+
...real.listToolCalls ? { async listToolCalls(id, scope) {
|
|
139
|
+
const snap = captured.get(id);
|
|
140
|
+
if (snap)
|
|
141
|
+
return snap.journal ? structuredClone(snap.journal) : undefined;
|
|
142
|
+
return real.listToolCalls(id, scope);
|
|
143
|
+
} } : {}
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
async function resolveSubject(store, scope, subjectId) {
|
|
147
|
+
const direct = await store.load(subjectId, scope);
|
|
148
|
+
const accountOf = (state) => {
|
|
149
|
+
const parsed = accountView.safeParse(state?.metadata?.[TASK_BUDGET_ACCOUNT_KEY]);
|
|
150
|
+
return parsed.success && state?.runId.startsWith("task_budget_") ? parsed.data : undefined;
|
|
151
|
+
};
|
|
152
|
+
const directAccount = direct && direct.runId === subjectId && sameScope(direct, scope) ? accountOf(direct) : undefined;
|
|
153
|
+
if (direct && direct.runId === subjectId && sameScope(direct, scope) && !directAccount) {
|
|
154
|
+
return { kind: "run", id: subjectId, runs: [{ state: structuredClone(direct), journal: await readJournal(store, scope, subjectId) }], accountState: undefined };
|
|
155
|
+
}
|
|
156
|
+
let account = directAccount;
|
|
157
|
+
let taskId = account?.taskId;
|
|
158
|
+
let accountState = direct && directAccount ? structuredClone(direct) : undefined;
|
|
159
|
+
if (!account && scope) {
|
|
160
|
+
const loaded = await store.load(TaskBudget.accountId(scope, subjectId), scope);
|
|
161
|
+
const parsed = loaded && sameScope(loaded, scope) ? accountOf(loaded) : undefined;
|
|
162
|
+
if (parsed && parsed.taskId === subjectId) {
|
|
163
|
+
account = parsed;
|
|
164
|
+
taskId = parsed.taskId;
|
|
165
|
+
accountState = structuredClone(loaded);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if (!account || !taskId || !accountState || account.runs.length === 0)
|
|
169
|
+
fail("AUDIT_PACK_SUBJECT_UNAVAILABLE");
|
|
170
|
+
const runs = [];
|
|
171
|
+
for (const runId of account.runs)
|
|
172
|
+
runs.push(await captureRun(store, scope, runId));
|
|
173
|
+
return { kind: "task", id: taskId, runs, accountState };
|
|
174
|
+
}
|
|
175
|
+
function collectActivity(session, runIds) {
|
|
176
|
+
if (!session?.history)
|
|
177
|
+
return { availability: "unavailable", truncated: false, retention: "unknown", events: [] };
|
|
178
|
+
const events = [];
|
|
179
|
+
let cursor = 0;
|
|
180
|
+
let truncated = false;
|
|
181
|
+
let retention = "retained";
|
|
182
|
+
for (let pageIndex = 0;pageIndex < 50; pageIndex += 1) {
|
|
183
|
+
const page = session.history.replay(session.id, cursor);
|
|
184
|
+
if (page.schemaVersion !== 1 || !Number.isSafeInteger(page.nextCursor) || page.nextCursor < cursor)
|
|
185
|
+
fail("AUDIT_PACK_HISTORY_INVALID");
|
|
186
|
+
if (page.cursorExpired || page.policyEvidenceIncomplete)
|
|
187
|
+
retention = "expired";
|
|
188
|
+
let last = cursor;
|
|
189
|
+
for (const event of page.events) {
|
|
190
|
+
if (event.sessionId !== session.id || !Number.isSafeInteger(event.sequence) || event.sequence <= last || event.sequence > page.nextCursor)
|
|
191
|
+
fail("AUDIT_PACK_HISTORY_INVALID");
|
|
192
|
+
last = event.sequence;
|
|
193
|
+
if (!runIds.has(event.runId))
|
|
194
|
+
continue;
|
|
195
|
+
if (events.length >= MAX_ACTIVITY_EVENTS) {
|
|
196
|
+
truncated = true;
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
events.push({ sequence: event.sequence, runId: event.runId, ...typeof event.at === "number" ? { at: event.at } : {}, activity: event.activity });
|
|
200
|
+
}
|
|
201
|
+
if (page.cursorExpired || !page.hasMore)
|
|
202
|
+
break;
|
|
203
|
+
if (page.nextCursor === cursor)
|
|
204
|
+
fail("AUDIT_PACK_HISTORY_INVALID");
|
|
205
|
+
cursor = page.nextCursor;
|
|
206
|
+
if (pageIndex === 49)
|
|
207
|
+
truncated = true;
|
|
208
|
+
}
|
|
209
|
+
return { availability: truncated || retention === "expired" ? "incomplete" : "recorded", truncated, retention, events };
|
|
210
|
+
}
|
|
211
|
+
function approvalPages(state, journal) {
|
|
212
|
+
const decisions = [];
|
|
213
|
+
for (let offset = 0;offset < 512; offset += 25) {
|
|
214
|
+
const rows = approvalDecisionViews(state, journal, offset);
|
|
215
|
+
decisions.push(...rows);
|
|
216
|
+
if (rows.length < 25)
|
|
217
|
+
break;
|
|
218
|
+
}
|
|
219
|
+
return decisions;
|
|
220
|
+
}
|
|
221
|
+
async function componentFiles(captured, store, scope, session, activity, ledger) {
|
|
222
|
+
const state = captured.state;
|
|
223
|
+
const rows = captured.journal ?? [];
|
|
224
|
+
let approvals;
|
|
225
|
+
try {
|
|
226
|
+
const decisions = approvalPages(state, rows);
|
|
227
|
+
approvals = { schemaVersion: 1, kind: "zhivex-audit-approvals", runId: state.runId, availability: state.metadata?.[APPROVAL_HISTORY_KEY] === undefined && decisions.length === 0 ? "unavailable" : "recorded", decisions: redactValue(decisions) };
|
|
228
|
+
} catch {
|
|
229
|
+
approvals = { schemaVersion: 1, kind: "zhivex-audit-approvals", runId: state.runId, availability: "invalid", decisions: [] };
|
|
230
|
+
}
|
|
231
|
+
const policyEvents = [];
|
|
232
|
+
let invalid = 0;
|
|
233
|
+
for (const event of activity.events) {
|
|
234
|
+
if (event.runId !== state.runId || event.activity.type !== "policy-decision")
|
|
235
|
+
continue;
|
|
236
|
+
const parsed = harnessPolicyDecisionEventSchema.safeParse(event.activity);
|
|
237
|
+
if (!parsed.success) {
|
|
238
|
+
invalid += 1;
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
policyEvents.push({ sequence: event.sequence, event: parsed.data });
|
|
242
|
+
}
|
|
243
|
+
const policy = {
|
|
244
|
+
schemaVersion: 1,
|
|
245
|
+
kind: "zhivex-audit-policy-decisions",
|
|
246
|
+
runId: state.runId,
|
|
247
|
+
availability: activity.availability === "unavailable" ? "unavailable" : invalid > 0 || activity.availability === "incomplete" ? "incomplete" : "recorded",
|
|
248
|
+
invalid,
|
|
249
|
+
decisions: policyEvents
|
|
250
|
+
};
|
|
251
|
+
const own = activity.events.filter((event) => event.runId === state.runId);
|
|
252
|
+
const header = { schemaVersion: 1, kind: "zhivex-redaction-log", availability: activity.availability, count: own.length, truncated: activity.truncated, retention: activity.retention };
|
|
253
|
+
const lines = [header, ...own.map((event) => ({ schemaVersion: 1, kind: "zhivex-redacted-activity", sequence: event.sequence, runId: event.runId, ...event.at === undefined ? {} : { at: event.at }, activity: event.activity }))];
|
|
254
|
+
const redactionLog = `${lines.map((line) => JSON.stringify(line)).join(`
|
|
255
|
+
`)}
|
|
256
|
+
`;
|
|
257
|
+
let transport = null;
|
|
258
|
+
let transportAvailability = "unavailable";
|
|
259
|
+
if (ledger) {
|
|
260
|
+
try {
|
|
261
|
+
transport = ledger.summary(state.runId);
|
|
262
|
+
transportAvailability = "recorded";
|
|
263
|
+
} catch {
|
|
264
|
+
transport = null;
|
|
265
|
+
transportAvailability = "unavailable";
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
const usage = {
|
|
269
|
+
schemaVersion: 1,
|
|
270
|
+
kind: "zhivex-audit-usage-ledger",
|
|
271
|
+
runId: state.runId,
|
|
272
|
+
projection: inspectUsageLedger(state.metadata?.[USAGE_LEDGER_KEY]),
|
|
273
|
+
transport,
|
|
274
|
+
transportAvailability
|
|
275
|
+
};
|
|
276
|
+
const report = await exportHarnessGovernanceReport(store, scope, state.runId, session ? { session } : {});
|
|
277
|
+
return new Map([
|
|
278
|
+
["governance-report.json", Buffer.from(`${JSON.stringify(report, null, 2)}
|
|
279
|
+
`)],
|
|
280
|
+
["approvals.json", Buffer.from(`${JSON.stringify(approvals, null, 2)}
|
|
281
|
+
`)],
|
|
282
|
+
["policy-decisions.json", Buffer.from(`${JSON.stringify(policy, null, 2)}
|
|
283
|
+
`)],
|
|
284
|
+
["redaction.jsonl", Buffer.from(redactionLog)],
|
|
285
|
+
["usage-ledger.json", Buffer.from(`${JSON.stringify(usage, null, 2)}
|
|
286
|
+
`)]
|
|
287
|
+
]);
|
|
288
|
+
}
|
|
289
|
+
async function loadAuditSigningKey(input) {
|
|
290
|
+
let bytes;
|
|
291
|
+
if (input.file) {
|
|
292
|
+
const data = await readRegularFileNoFollow(path.resolve(input.file), { label: "Audit signing key", maxBytes: 4096 });
|
|
293
|
+
bytes = data.contents;
|
|
294
|
+
if (bytes.at(-1) === 10)
|
|
295
|
+
bytes = bytes.subarray(0, -1);
|
|
296
|
+
if (bytes.at(-1) === 13)
|
|
297
|
+
bytes = bytes.subarray(0, -1);
|
|
298
|
+
} else if (input.value !== undefined)
|
|
299
|
+
bytes = Buffer.from(input.value, "utf8");
|
|
300
|
+
else
|
|
301
|
+
fail("AUDIT_PACK_KEY_INVALID");
|
|
302
|
+
assertKey(bytes);
|
|
303
|
+
return Buffer.from(bytes);
|
|
304
|
+
}
|
|
305
|
+
async function exportHarnessAuditPack(options) {
|
|
306
|
+
assertKey(options.signingKey);
|
|
307
|
+
const subject = await resolveSubject(options.store, options.scope, options.subjectId);
|
|
308
|
+
const runIds = new Set(subject.runs.map((run) => run.state.runId));
|
|
309
|
+
const activity = collectActivity(options.session, runIds);
|
|
310
|
+
let ledger;
|
|
311
|
+
if (options.config) {
|
|
312
|
+
try {
|
|
313
|
+
ledger = await UsageLedger.open(options.config);
|
|
314
|
+
} catch {
|
|
315
|
+
ledger = undefined;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
try {
|
|
319
|
+
const files = new Map;
|
|
320
|
+
const segments = new Set;
|
|
321
|
+
const frozen = snapshotStore(options.store, new Map(subject.runs.map((run) => [run.state.runId, run])));
|
|
322
|
+
const prefixFor = subject.runs.length === 1 ? (_runId) => "" : (runId) => `runs/${runSegment(runId, segments)}/`;
|
|
323
|
+
for (const captured of subject.runs) {
|
|
324
|
+
const prefix = prefixFor(captured.state.runId);
|
|
325
|
+
const parts = await componentFiles(captured, frozen, options.scope, options.session, activity, ledger);
|
|
326
|
+
for (const name of COMPONENT_NAMES) {
|
|
327
|
+
const bytes = parts.get(name);
|
|
328
|
+
if (!bytes)
|
|
329
|
+
fail("AUDIT_PACK_CONTENT_INVALID");
|
|
330
|
+
if (bytes.byteLength > MAX_FILE_BYTES)
|
|
331
|
+
fail("AUDIT_PACK_LIMIT");
|
|
332
|
+
files.set(`${prefix}${name}`, bytes);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
const listed = [...files.keys()].sort();
|
|
336
|
+
let total = 0;
|
|
337
|
+
const entries = listed.map((file) => {
|
|
338
|
+
const bytes = files.get(file);
|
|
339
|
+
total += bytes.byteLength;
|
|
340
|
+
return { path: file, sha256: createHash("sha256").update(bytes).digest("hex"), bytes: bytes.byteLength };
|
|
341
|
+
});
|
|
342
|
+
for (const captured of subject.runs)
|
|
343
|
+
await assertCaptured(options.store, options.scope, captured);
|
|
344
|
+
if (subject.accountState) {
|
|
345
|
+
const currentAccount = await options.store.load(subject.accountState.runId, options.scope);
|
|
346
|
+
if (!currentAccount || !sameJson(currentAccount, subject.accountState))
|
|
347
|
+
fail("AUDIT_PACK_STATE_CHANGED");
|
|
348
|
+
}
|
|
349
|
+
const unsigned = {
|
|
350
|
+
schemaVersion: 1,
|
|
351
|
+
kind: "zhivex-harness-audit-pack",
|
|
352
|
+
integrity: "hmac-sha256",
|
|
353
|
+
exporterVersion: HARNESS_VERSION,
|
|
354
|
+
createdAt: new Date(options.now ?? Date.now()).toISOString(),
|
|
355
|
+
subject: { kind: subject.kind, id: subject.id, runIds: subject.runs.map((run) => run.state.runId) },
|
|
356
|
+
files: entries
|
|
357
|
+
};
|
|
358
|
+
const manifest = auditPackManifestSchema.parse({
|
|
359
|
+
...unsigned,
|
|
360
|
+
signature: { algorithm: "hmac-sha256", keyId: keyIdFor(options.signingKey), value: signManifest(unsigned, options.signingKey) }
|
|
361
|
+
});
|
|
362
|
+
const manifestBytes = Buffer.from(`${JSON.stringify(manifest, null, 2)}
|
|
363
|
+
`);
|
|
364
|
+
if (manifestBytes.byteLength > MAX_FILE_BYTES || total + manifestBytes.byteLength > MAX_PACK_BYTES)
|
|
365
|
+
fail("AUDIT_PACK_LIMIT");
|
|
366
|
+
const directory = path.resolve(options.directory);
|
|
367
|
+
const parent = await lstat(path.dirname(directory)).catch(() => fail("AUDIT_PACK_OUTPUT_UNAVAILABLE"));
|
|
368
|
+
if (!parent.isDirectory() || parent.isSymbolicLink())
|
|
369
|
+
fail("AUDIT_PACK_OUTPUT_UNAVAILABLE");
|
|
370
|
+
await mkdir(directory, { mode: 448 }).catch((error) => fail(error.code === "EEXIST" ? "AUDIT_PACK_OUTPUT_EXISTS" : "AUDIT_PACK_OUTPUT_UNAVAILABLE"));
|
|
371
|
+
try {
|
|
372
|
+
for (const file of listed) {
|
|
373
|
+
const target = contained(directory, file);
|
|
374
|
+
await mkdir(path.dirname(target), { recursive: true, mode: 448 });
|
|
375
|
+
await writeFile(target, files.get(file), { flag: "wx", mode: 384 });
|
|
376
|
+
}
|
|
377
|
+
await writeFile(path.join(directory, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
|
|
378
|
+
`, { flag: "wx", mode: 384 });
|
|
379
|
+
} catch (error) {
|
|
380
|
+
await rm(directory, { recursive: true, force: true });
|
|
381
|
+
if (error instanceof Error && error.message.startsWith("AUDIT_PACK_"))
|
|
382
|
+
throw error;
|
|
383
|
+
fail("AUDIT_PACK_WRITE_FAILED");
|
|
384
|
+
}
|
|
385
|
+
return manifest;
|
|
386
|
+
} finally {
|
|
387
|
+
ledger?.close();
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
var kindSchema = (kind) => z.object({ schemaVersion: z.literal(1), kind: z.literal(kind) }).passthrough();
|
|
391
|
+
async function verifyHarnessAuditPack(options) {
|
|
392
|
+
assertKey(options.signingKey);
|
|
393
|
+
const directory = path.resolve(options.directory);
|
|
394
|
+
const root = await lstat(directory).catch(() => fail("AUDIT_PACK_UNAVAILABLE"));
|
|
395
|
+
if (!root.isDirectory() || root.isSymbolicLink())
|
|
396
|
+
fail("AUDIT_PACK_UNAVAILABLE");
|
|
397
|
+
const manifestBytes = await readRegularFileNoFollow(path.join(directory, "manifest.json"), { label: "Audit manifest", maxBytes: MAX_FILE_BYTES });
|
|
398
|
+
let manifest;
|
|
399
|
+
try {
|
|
400
|
+
manifest = auditPackManifestSchema.parse(JSON.parse(manifestBytes.contents.toString("utf8")));
|
|
401
|
+
} catch {
|
|
402
|
+
fail("AUDIT_PACK_MANIFEST_INVALID");
|
|
403
|
+
}
|
|
404
|
+
const present = [];
|
|
405
|
+
const walk = async (current, prefix) => {
|
|
406
|
+
const entries = await readdir(current, { withFileTypes: true });
|
|
407
|
+
for (const entry of entries.sort((a, b) => a.name < b.name ? -1 : 1)) {
|
|
408
|
+
const relative = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
409
|
+
if (entry.isSymbolicLink())
|
|
410
|
+
fail("AUDIT_PACK_PATH_INVALID");
|
|
411
|
+
const full = path.join(current, entry.name);
|
|
412
|
+
if (entry.isDirectory())
|
|
413
|
+
await walk(full, relative);
|
|
414
|
+
else if (entry.isFile())
|
|
415
|
+
present.push(relative);
|
|
416
|
+
else
|
|
417
|
+
fail("AUDIT_PACK_PATH_INVALID");
|
|
418
|
+
}
|
|
419
|
+
};
|
|
420
|
+
await walk(directory, "");
|
|
421
|
+
present.sort();
|
|
422
|
+
const expected = ["manifest.json", ...manifest.files.map((file) => file.path)].sort();
|
|
423
|
+
if (present.length !== expected.length || present.some((file, index) => file !== expected[index]))
|
|
424
|
+
fail("AUDIT_PACK_FILES_MISMATCH");
|
|
425
|
+
let total = manifestBytes.contents.byteLength;
|
|
426
|
+
for (const file of manifest.files) {
|
|
427
|
+
const target = contained(directory, file.path);
|
|
428
|
+
const contents = await readRegularFileNoFollow(target, { label: "Audit pack file", maxBytes: MAX_FILE_BYTES }).catch((error) => {
|
|
429
|
+
if (error instanceof Error && error.message.startsWith("AUDIT_PACK_"))
|
|
430
|
+
throw error;
|
|
431
|
+
fail("AUDIT_PACK_HASH_MISMATCH");
|
|
432
|
+
});
|
|
433
|
+
total += contents.contents.byteLength;
|
|
434
|
+
if (contents.contents.byteLength !== file.bytes || createHash("sha256").update(contents.contents).digest("hex") !== file.sha256)
|
|
435
|
+
fail("AUDIT_PACK_HASH_MISMATCH");
|
|
436
|
+
try {
|
|
437
|
+
if (file.path.endsWith("governance-report.json")) {
|
|
438
|
+
if (!harnessGovernanceReportSchema.safeParse(JSON.parse(contents.contents.toString("utf8"))).success)
|
|
439
|
+
fail("AUDIT_PACK_CONTENT_INVALID");
|
|
440
|
+
} else if (file.path.endsWith("approvals.json")) {
|
|
441
|
+
if (!kindSchema("zhivex-audit-approvals").safeParse(JSON.parse(contents.contents.toString("utf8"))).success)
|
|
442
|
+
fail("AUDIT_PACK_CONTENT_INVALID");
|
|
443
|
+
} else if (file.path.endsWith("policy-decisions.json")) {
|
|
444
|
+
if (!kindSchema("zhivex-audit-policy-decisions").safeParse(JSON.parse(contents.contents.toString("utf8"))).success)
|
|
445
|
+
fail("AUDIT_PACK_CONTENT_INVALID");
|
|
446
|
+
} else if (file.path.endsWith("usage-ledger.json")) {
|
|
447
|
+
if (!kindSchema("zhivex-audit-usage-ledger").safeParse(JSON.parse(contents.contents.toString("utf8"))).success)
|
|
448
|
+
fail("AUDIT_PACK_CONTENT_INVALID");
|
|
449
|
+
} else if (file.path.endsWith("redaction.jsonl")) {
|
|
450
|
+
const lines = contents.contents.toString("utf8").split(`
|
|
451
|
+
`);
|
|
452
|
+
if (lines.at(-1) !== "")
|
|
453
|
+
fail("AUDIT_PACK_CONTENT_INVALID");
|
|
454
|
+
for (const line of lines.slice(0, -1)) {
|
|
455
|
+
if (!kindSchema("zhivex-redaction-log").or(kindSchema("zhivex-redacted-activity")).safeParse(JSON.parse(line)).success)
|
|
456
|
+
fail("AUDIT_PACK_CONTENT_INVALID");
|
|
457
|
+
}
|
|
458
|
+
} else
|
|
459
|
+
fail("AUDIT_PACK_PATH_INVALID");
|
|
460
|
+
} catch (error) {
|
|
461
|
+
if (error instanceof Error && error.message.startsWith("AUDIT_PACK_"))
|
|
462
|
+
throw error;
|
|
463
|
+
fail("AUDIT_PACK_CONTENT_INVALID");
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
if (total > MAX_PACK_BYTES)
|
|
467
|
+
fail("AUDIT_PACK_LIMIT");
|
|
468
|
+
if (manifest.signature.keyId !== keyIdFor(options.signingKey))
|
|
469
|
+
fail("AUDIT_PACK_KEY_MISMATCH");
|
|
470
|
+
const { signature, ...unsigned } = manifest;
|
|
471
|
+
const expectedSignature = Buffer.from(signManifest(unsigned, options.signingKey), "base64");
|
|
472
|
+
const actualSignature = Buffer.from(signature.value, "base64");
|
|
473
|
+
if (actualSignature.length !== expectedSignature.length || actualSignature.toString("base64") !== signature.value || !timingSafeEqual(actualSignature, expectedSignature)) {
|
|
474
|
+
fail("AUDIT_PACK_SIGNATURE_INVALID");
|
|
475
|
+
}
|
|
476
|
+
return { schemaVersion: 1, kind: "zhivex-audit-pack-verification", subject: manifest.subject, fileCount: manifest.files.length, keyId: signature.keyId };
|
|
477
|
+
}
|
|
478
|
+
// src/cli/audit-pack.ts
|
|
479
|
+
var signingKey = async (file) => {
|
|
480
|
+
if (!file && process.env.ZHIVEX_AUDIT_SIGNING_KEY === undefined) {
|
|
481
|
+
throw new CliUsageError("Set ZHIVEX_AUDIT_SIGNING_KEY or pass --signing-key-file. The key is not stored in the pack.");
|
|
482
|
+
}
|
|
483
|
+
try {
|
|
484
|
+
return await loadAuditSigningKey({ ...file ? { file } : {}, ...file ? {} : { value: process.env.ZHIVEX_AUDIT_SIGNING_KEY ?? "" } });
|
|
485
|
+
} catch (error) {
|
|
486
|
+
if (error instanceof Error && (error.message === "AUDIT_PACK_KEY_INVALID" || error.name === "UnsafeFileTypeError" || error.name === "FileSizeLimitError")) {
|
|
487
|
+
throw new CliUsageError("Audit signing key must be a regular file or environment value of 32 to 4096 bytes.");
|
|
488
|
+
}
|
|
489
|
+
throw error;
|
|
490
|
+
}
|
|
491
|
+
};
|
|
492
|
+
async function auditPackCli(options) {
|
|
493
|
+
const key = await signingKey(options.signingKeyFile);
|
|
494
|
+
if (options.command === "verify-audit") {
|
|
495
|
+
const result = await verifyHarnessAuditPack({ directory: path2.resolve(options.auditOut), signingKey: key });
|
|
496
|
+
process.stdout.write(options.json ? `${JSON.stringify(result, null, 2)}
|
|
497
|
+
` : `Audit pack verified: ${result.subject.kind} ${result.subject.id} (${result.fileCount} files, key ${result.keyId}).
|
|
498
|
+
`);
|
|
499
|
+
return result;
|
|
500
|
+
}
|
|
501
|
+
const config = resolveHarnessConfig(options);
|
|
502
|
+
await validateStateDirectory(config.workspace, config.stateDirectory);
|
|
503
|
+
const persistence = await openHarnessPersistence(config);
|
|
504
|
+
let index;
|
|
505
|
+
let history;
|
|
506
|
+
try {
|
|
507
|
+
if (options.sessionId) {
|
|
508
|
+
index = await openCliSessionStore({ workspace: config.workspace, stateDirectory: config.stateDirectory, scope: config.scope });
|
|
509
|
+
history = await openHarnessActivityStore(config);
|
|
510
|
+
}
|
|
511
|
+
const manifest = await exportHarnessAuditPack({
|
|
512
|
+
store: persistence.store,
|
|
513
|
+
scope: config.scope,
|
|
514
|
+
subjectId: options.runId,
|
|
515
|
+
directory: path2.resolve(options.auditOut),
|
|
516
|
+
signingKey: key,
|
|
517
|
+
config,
|
|
518
|
+
...index && history && options.sessionId ? { session: { id: options.sessionId, index, history } } : {}
|
|
519
|
+
});
|
|
520
|
+
process.stdout.write(options.json ? `${JSON.stringify(manifest, null, 2)}
|
|
521
|
+
` : `Audit pack written to ${path2.resolve(options.auditOut)} (${manifest.subject.kind} ${manifest.subject.id}, ${manifest.files.length} files).
|
|
522
|
+
`);
|
|
523
|
+
return manifest;
|
|
524
|
+
} finally {
|
|
525
|
+
history?.close();
|
|
526
|
+
index?.close();
|
|
527
|
+
persistence.close();
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
export {
|
|
531
|
+
auditPackCli
|
|
532
|
+
};
|
package/dist/cli/arguments.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { type HarnessReasoningEffort } from "../providers/reasoning.js";
|
|
|
2
2
|
import { type AgentStatus } from "@zhivex-ai/agents";
|
|
3
3
|
import { type HarnessSubagentProfile } from "../runtime/config.js";
|
|
4
4
|
import { HarnessError } from "../runtime/errors.js";
|
|
5
|
-
export declare const CLI_COMMANDS: readonly ["init", "run", "review", "chat", "providers", "doctor", "policy", "resume", "runs", "sessions", "checkpoints", "changes", "state", "memory", "help", "version"];
|
|
5
|
+
export declare const CLI_COMMANDS: readonly ["init", "run", "review", "chat", "providers", "doctor", "policy", "resume", "runs", "sessions", "checkpoints", "changes", "state", "memory", "export-audit", "verify-audit", "help", "version"];
|
|
6
6
|
export declare const CLI_RUNS_COMMANDS: readonly ["list", "inspect", "cancel", "cleanup", "export", "report"];
|
|
7
7
|
export declare const CLI_SESSIONS_COMMANDS: readonly ["list", "inspect", "rename", "fork", "archive"];
|
|
8
8
|
export declare const CLI_CHANGES_COMMANDS: readonly ["create", "verify"];
|
|
@@ -114,6 +114,8 @@ export interface CliOptions {
|
|
|
114
114
|
approve?: boolean;
|
|
115
115
|
json: boolean;
|
|
116
116
|
jsonl: boolean;
|
|
117
|
+
auditOut?: string;
|
|
118
|
+
signingKeyFile?: string;
|
|
117
119
|
}
|
|
118
120
|
export declare class CliUsageError extends HarnessError {
|
|
119
121
|
constructor(message: string);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type CliOptions } from "./arguments.js";
|
|
2
|
+
/** Experimental operator command. Verification reads the pack and key only. Export reads durable state and writes a new directory. */
|
|
3
|
+
export declare function auditPackCli(options: CliOptions): Promise<import("../audit/pack.js").AuditPackVerification | {
|
|
4
|
+
schemaVersion: 1;
|
|
5
|
+
kind: "zhivex-harness-audit-pack";
|
|
6
|
+
integrity: "hmac-sha256";
|
|
7
|
+
exporterVersion: string;
|
|
8
|
+
createdAt: string;
|
|
9
|
+
subject: {
|
|
10
|
+
kind: "run" | "task";
|
|
11
|
+
id: string;
|
|
12
|
+
runIds: string[];
|
|
13
|
+
};
|
|
14
|
+
files: {
|
|
15
|
+
path: string;
|
|
16
|
+
sha256: string;
|
|
17
|
+
bytes: number;
|
|
18
|
+
}[];
|
|
19
|
+
signature: {
|
|
20
|
+
algorithm: "hmac-sha256";
|
|
21
|
+
keyId: string;
|
|
22
|
+
value: string;
|
|
23
|
+
};
|
|
24
|
+
}>;
|
|
@@ -43,8 +43,14 @@ export declare class CliCredentials {
|
|
|
43
43
|
private endpointOverride;
|
|
44
44
|
/** Presence only: never contacts a provider or returns a secret. */
|
|
45
45
|
inspect(provider: HarnessProvider): Promise<CredentialStatus>;
|
|
46
|
+
private inspectBedrock;
|
|
47
|
+
private inspectAzure;
|
|
48
|
+
private inspectSecret;
|
|
46
49
|
configure(provider: HarnessProvider, input: CredentialInput): Promise<boolean>;
|
|
47
50
|
private configureOnce;
|
|
51
|
+
private managedSecret;
|
|
52
|
+
private bedrockProviderEnvironment;
|
|
53
|
+
private azureProviderEnvironment;
|
|
48
54
|
providerEnvironment(provider: HarnessProvider, input: CredentialInput): Promise<NodeJS.ProcessEnv>;
|
|
49
55
|
clear(): void;
|
|
50
56
|
}
|
|
@@ -8,6 +8,8 @@ export declare const cliProfileSchema: z.ZodObject<{
|
|
|
8
8
|
schemaVersion: z.ZodLiteral<1>;
|
|
9
9
|
provider: z.ZodEnum<{
|
|
10
10
|
anthropic: "anthropic";
|
|
11
|
+
"azure-openai": "azure-openai";
|
|
12
|
+
bedrock: "bedrock";
|
|
11
13
|
gemini: "gemini";
|
|
12
14
|
meta: "meta";
|
|
13
15
|
openai: "openai";
|
|
@@ -44,7 +46,7 @@ export declare const createCliProfile: (name: string, input: {
|
|
|
44
46
|
path: string;
|
|
45
47
|
profile: {
|
|
46
48
|
schemaVersion: 1;
|
|
47
|
-
provider: "anthropic" | "gemini" | "meta" | "openai" | "qwen" | "vertex";
|
|
49
|
+
provider: "anthropic" | "azure-openai" | "bedrock" | "gemini" | "meta" | "openai" | "qwen" | "vertex";
|
|
48
50
|
reasoningEffort?: "default" | "high" | "low" | "max" | "medium" | "minimal" | "none" | "xhigh" | undefined;
|
|
49
51
|
model: string;
|
|
50
52
|
};
|
|
@@ -58,7 +60,7 @@ export declare const updateCliProfile: (name: string, input: {
|
|
|
58
60
|
path: string;
|
|
59
61
|
profile: {
|
|
60
62
|
schemaVersion: 1;
|
|
61
|
-
provider: "anthropic" | "gemini" | "meta" | "openai" | "qwen" | "vertex";
|
|
63
|
+
provider: "anthropic" | "azure-openai" | "bedrock" | "gemini" | "meta" | "openai" | "qwen" | "vertex";
|
|
62
64
|
reasoningEffort?: "default" | "high" | "low" | "max" | "medium" | "minimal" | "none" | "xhigh" | undefined;
|
|
63
65
|
model: string;
|
|
64
66
|
};
|