offrouter-core 0.2.1 → 0.2.2
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/dist/audit.d.ts +137 -0
- package/dist/audit.d.ts.map +1 -0
- package/dist/audit.js +320 -0
- package/dist/audit.js.map +1 -0
- package/dist/auth/credential-chain.d.ts +84 -0
- package/dist/auth/credential-chain.d.ts.map +1 -0
- package/dist/auth/credential-chain.js +150 -0
- package/dist/auth/credential-chain.js.map +1 -0
- package/dist/auth/index.d.ts +10 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +7 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/keychain.d.ts +60 -0
- package/dist/auth/keychain.d.ts.map +1 -0
- package/dist/auth/keychain.js +104 -0
- package/dist/auth/keychain.js.map +1 -0
- package/dist/auth/oauth-pkce.d.ts +138 -0
- package/dist/auth/oauth-pkce.d.ts.map +1 -0
- package/dist/auth/oauth-pkce.js +375 -0
- package/dist/auth/oauth-pkce.js.map +1 -0
- package/dist/auth/oauth-server.d.ts +36 -0
- package/dist/auth/oauth-server.d.ts.map +1 -0
- package/dist/auth/oauth-server.js +210 -0
- package/dist/auth/oauth-server.js.map +1 -0
- package/dist/config.d.ts +76 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +355 -0
- package/dist/config.js.map +1 -0
- package/dist/delegation.d.ts +123 -0
- package/dist/delegation.d.ts.map +1 -0
- package/dist/delegation.js +455 -0
- package/dist/delegation.js.map +1 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/policy.d.ts +45 -0
- package/dist/policy.d.ts.map +1 -0
- package/dist/policy.js +318 -0
- package/dist/policy.js.map +1 -0
- package/{src/protocol.ts → dist/protocol.d.ts} +2 -2
- package/dist/protocol.d.ts.map +1 -0
- package/dist/protocol.js +6 -0
- package/dist/protocol.js.map +1 -0
- package/dist/providers/adapter.d.ts +137 -0
- package/dist/providers/adapter.d.ts.map +1 -0
- package/dist/providers/adapter.js +163 -0
- package/dist/providers/adapter.js.map +1 -0
- package/dist/providers/catalog-data.d.ts +128 -0
- package/dist/providers/catalog-data.d.ts.map +1 -0
- package/dist/providers/catalog-data.js +397 -0
- package/dist/providers/catalog-data.js.map +1 -0
- package/dist/providers/catalog.d.ts +63 -0
- package/dist/providers/catalog.d.ts.map +1 -0
- package/dist/providers/catalog.js +394 -0
- package/dist/providers/catalog.js.map +1 -0
- package/dist/providers/fake.d.ts +46 -0
- package/dist/providers/fake.d.ts.map +1 -0
- package/dist/providers/fake.js +234 -0
- package/dist/providers/fake.js.map +1 -0
- package/dist/providers/openai-compatible.d.ts +65 -0
- package/dist/providers/openai-compatible.d.ts.map +1 -0
- package/dist/providers/openai-compatible.js +434 -0
- package/dist/providers/openai-compatible.js.map +1 -0
- package/dist/proxy/responses-mapper.d.ts +366 -0
- package/dist/proxy/responses-mapper.d.ts.map +1 -0
- package/dist/proxy/responses-mapper.js +517 -0
- package/dist/proxy/responses-mapper.js.map +1 -0
- package/dist/proxy/responses-server.d.ts +29 -0
- package/dist/proxy/responses-server.d.ts.map +1 -0
- package/dist/proxy/responses-server.js +360 -0
- package/dist/proxy/responses-server.js.map +1 -0
- package/dist/router.d.ts +18 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.js +296 -0
- package/dist/router.js.map +1 -0
- package/dist/schemas.d.ts +560 -0
- package/dist/schemas.d.ts.map +1 -0
- package/{src/schemas.ts → dist/schemas.js} +83 -103
- package/dist/schemas.js.map +1 -0
- package/dist/secrets.d.ts +112 -0
- package/dist/secrets.d.ts.map +1 -0
- package/dist/secrets.js +326 -0
- package/dist/secrets.js.map +1 -0
- package/dist/types.d.ts +117 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/dist/usage-file.d.ts +59 -0
- package/dist/usage-file.d.ts.map +1 -0
- package/dist/usage-file.js +316 -0
- package/dist/usage-file.js.map +1 -0
- package/dist/usage.d.ts +235 -0
- package/dist/usage.d.ts.map +1 -0
- package/dist/usage.js +517 -0
- package/dist/usage.js.map +1 -0
- package/package.json +7 -2
- package/src/audit.test.ts +0 -302
- package/src/audit.ts +0 -553
- package/src/auth/credential-chain.test.ts +0 -326
- package/src/auth/credential-chain.ts +0 -235
- package/src/auth/index.ts +0 -45
- package/src/auth/keychain.test.ts +0 -265
- package/src/auth/keychain.ts +0 -168
- package/src/auth/oauth-pkce.test.ts +0 -329
- package/src/auth/oauth-pkce.ts +0 -571
- package/src/auth/oauth-server.test.ts +0 -83
- package/src/auth/oauth-server.ts +0 -296
- package/src/config.test.ts +0 -479
- package/src/config.ts +0 -505
- package/src/delegation.test.ts +0 -368
- package/src/delegation.ts +0 -605
- package/src/index.ts +0 -280
- package/src/policy.test.ts +0 -634
- package/src/policy.ts +0 -420
- package/src/providers/adapter.test.ts +0 -293
- package/src/providers/adapter.ts +0 -328
- package/src/providers/catalog-data.test.ts +0 -258
- package/src/providers/catalog-data.ts +0 -498
- package/src/providers/catalog.test.ts +0 -84
- package/src/providers/catalog.ts +0 -483
- package/src/providers/fake.ts +0 -312
- package/src/providers/openai-compatible.test.ts +0 -366
- package/src/providers/openai-compatible.ts +0 -554
- package/src/proxy/responses-mapper.test.ts +0 -290
- package/src/proxy/responses-mapper.ts +0 -736
- package/src/proxy/responses-server.test.ts +0 -322
- package/src/proxy/responses-server.ts +0 -469
- package/src/router.test.ts +0 -699
- package/src/router.ts +0 -352
- package/src/schemas.test.ts +0 -291
- package/src/secrets.test.ts +0 -271
- package/src/secrets.ts +0 -461
- package/src/types.ts +0 -173
- package/src/usage-file.test.ts +0 -243
- package/src/usage-file.ts +0 -435
- package/src/usage.test.ts +0 -335
- package/src/usage.ts +0 -859
- package/tsconfig.json +0 -9
package/src/delegation.test.ts
DELETED
|
@@ -1,368 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it, vi } from "vitest";
|
|
2
|
-
import { InMemoryAuditStore } from "./audit.js";
|
|
3
|
-
import { DelegationRuntime, type DelegationRequest } from "./delegation.js";
|
|
4
|
-
import type { PolicyConfig } from "./policy.js";
|
|
5
|
-
import { createFakeProvider } from "./providers/fake.js";
|
|
6
|
-
import type { ProviderCandidate, RouteRequest } from "./types.js";
|
|
7
|
-
|
|
8
|
-
const personalConfig: PolicyConfig = {
|
|
9
|
-
allowlistedProfiles: ["claude-personal", "codex-personal", "gemini-personal"],
|
|
10
|
-
deniedProfilePatterns: ["*-work"],
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
function routeBase(
|
|
14
|
-
overrides: Partial<RouteRequest> & {
|
|
15
|
-
harness?: Partial<RouteRequest["harness"]>;
|
|
16
|
-
task?: Partial<RouteRequest["task"]>;
|
|
17
|
-
workspace?: Partial<RouteRequest["workspace"]>;
|
|
18
|
-
constraints?: Partial<RouteRequest["constraints"]>;
|
|
19
|
-
} = {},
|
|
20
|
-
): RouteRequest {
|
|
21
|
-
return {
|
|
22
|
-
protocolVersion: "offrouter.route.v1",
|
|
23
|
-
requestId: overrides.requestId ?? "req_delegate_1",
|
|
24
|
-
harness: {
|
|
25
|
-
kind: "claude",
|
|
26
|
-
profile: "claude-personal",
|
|
27
|
-
...overrides.harness,
|
|
28
|
-
},
|
|
29
|
-
task: {
|
|
30
|
-
promptPreview: "short preview",
|
|
31
|
-
promptDigest: "sha256:deadbeef",
|
|
32
|
-
kind: "explain",
|
|
33
|
-
risk: "low",
|
|
34
|
-
...overrides.task,
|
|
35
|
-
},
|
|
36
|
-
workspace: {
|
|
37
|
-
cwd: "/tmp/project",
|
|
38
|
-
trusted: true,
|
|
39
|
-
...overrides.workspace,
|
|
40
|
-
},
|
|
41
|
-
constraints: {
|
|
42
|
-
maxCostUsd: 1,
|
|
43
|
-
localOnly: false,
|
|
44
|
-
subscriptionFirst: true,
|
|
45
|
-
allowApiKeyFallback: true,
|
|
46
|
-
...overrides.constraints,
|
|
47
|
-
},
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function candidate(
|
|
52
|
-
partial: Partial<ProviderCandidate> &
|
|
53
|
-
Pick<ProviderCandidate, "providerId" | "modelId" | "authTier">,
|
|
54
|
-
): ProviderCandidate {
|
|
55
|
-
return {
|
|
56
|
-
authScope: "third-party",
|
|
57
|
-
health: "healthy",
|
|
58
|
-
supportsTools: true,
|
|
59
|
-
supportsStreaming: true,
|
|
60
|
-
supportsJson: true,
|
|
61
|
-
supportsImages: false,
|
|
62
|
-
estimatedCostUsd: 0.01,
|
|
63
|
-
...partial,
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
function makeRequest(
|
|
68
|
-
partial: Partial<DelegationRequest> & {
|
|
69
|
-
route?: Partial<RouteRequest>;
|
|
70
|
-
} = {},
|
|
71
|
-
): DelegationRequest {
|
|
72
|
-
const route = routeBase(partial.route ?? {});
|
|
73
|
-
return {
|
|
74
|
-
taskId: partial.taskId ?? "task_1",
|
|
75
|
-
mode: partial.mode ?? "oneshot",
|
|
76
|
-
output: partial.output ?? "text",
|
|
77
|
-
prompt: partial.prompt ?? "FULL SECRET PROMPT TEXT FOR DELEGATION",
|
|
78
|
-
route,
|
|
79
|
-
...partial,
|
|
80
|
-
route,
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
describe("DelegationRuntime", () => {
|
|
85
|
-
it("returns a one-shot fake provider response", async () => {
|
|
86
|
-
const adapter = createFakeProvider({
|
|
87
|
-
id: "fake",
|
|
88
|
-
responseText: "one-shot body",
|
|
89
|
-
});
|
|
90
|
-
const candidates = [
|
|
91
|
-
candidate({
|
|
92
|
-
providerId: "fake",
|
|
93
|
-
modelId: "fake-coder",
|
|
94
|
-
authTier: "api-key",
|
|
95
|
-
}),
|
|
96
|
-
];
|
|
97
|
-
const runtime = new DelegationRuntime({
|
|
98
|
-
adapters: { fake: adapter },
|
|
99
|
-
candidates,
|
|
100
|
-
policy: personalConfig,
|
|
101
|
-
audit: new InMemoryAuditStore(),
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
const result = await runtime.delegate(makeRequest({ mode: "oneshot" }));
|
|
105
|
-
|
|
106
|
-
expect(result.status).toBe("completed");
|
|
107
|
-
expect(result.text).toBe("one-shot body");
|
|
108
|
-
expect(result.events.some((e) => e.type === "done")).toBe(true);
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
it("streams fake provider events", async () => {
|
|
112
|
-
const adapter = createFakeProvider({
|
|
113
|
-
id: "fake",
|
|
114
|
-
streamChunks: ["hello ", "world"],
|
|
115
|
-
});
|
|
116
|
-
const candidates = [
|
|
117
|
-
candidate({
|
|
118
|
-
providerId: "fake",
|
|
119
|
-
modelId: "fake-coder",
|
|
120
|
-
authTier: "api-key",
|
|
121
|
-
}),
|
|
122
|
-
];
|
|
123
|
-
const runtime = new DelegationRuntime({
|
|
124
|
-
adapters: { fake: adapter },
|
|
125
|
-
candidates,
|
|
126
|
-
policy: personalConfig,
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
const events = [];
|
|
130
|
-
for await (const event of runtime.stream(
|
|
131
|
-
makeRequest({ mode: "stream", taskId: "task_stream" }),
|
|
132
|
-
)) {
|
|
133
|
-
events.push(event);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
const deltas = events.filter((e) => e.type === "text-delta");
|
|
137
|
-
expect(deltas.map((e) => ("text" in e ? e.text : "")).join("")).toBe(
|
|
138
|
-
"hello world",
|
|
139
|
-
);
|
|
140
|
-
expect(events.some((e) => e.type === "done")).toBe(true);
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
it("tracks background task status", async () => {
|
|
144
|
-
const adapter = createFakeProvider({
|
|
145
|
-
id: "fake",
|
|
146
|
-
responseText: "bg-done",
|
|
147
|
-
streamDelayMs: 5,
|
|
148
|
-
streamChunks: ["a", "b"],
|
|
149
|
-
});
|
|
150
|
-
const candidates = [
|
|
151
|
-
candidate({
|
|
152
|
-
providerId: "fake",
|
|
153
|
-
modelId: "fake-coder",
|
|
154
|
-
authTier: "api-key",
|
|
155
|
-
}),
|
|
156
|
-
];
|
|
157
|
-
const runtime = new DelegationRuntime({
|
|
158
|
-
adapters: { fake: adapter },
|
|
159
|
-
candidates,
|
|
160
|
-
policy: personalConfig,
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
const task = await runtime.startBackground(
|
|
164
|
-
makeRequest({ mode: "background", taskId: "task_bg" }),
|
|
165
|
-
);
|
|
166
|
-
expect(task.status === "running" || task.status === "queued").toBe(true);
|
|
167
|
-
|
|
168
|
-
const settled = await runtime.wait(task.taskId);
|
|
169
|
-
expect(settled.status).toBe("completed");
|
|
170
|
-
expect(settled.text).toBe("ab");
|
|
171
|
-
expect(runtime.getTask(task.taskId)?.status).toBe("completed");
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
it("cancels an active same-process task via adapter.cancel", async () => {
|
|
175
|
-
const adapter = createFakeProvider({
|
|
176
|
-
id: "fake",
|
|
177
|
-
hangUntilCancel: true,
|
|
178
|
-
});
|
|
179
|
-
const cancelSpy = vi.spyOn(adapter, "cancel");
|
|
180
|
-
const candidates = [
|
|
181
|
-
candidate({
|
|
182
|
-
providerId: "fake",
|
|
183
|
-
modelId: "fake-coder",
|
|
184
|
-
authTier: "api-key",
|
|
185
|
-
}),
|
|
186
|
-
];
|
|
187
|
-
const runtime = new DelegationRuntime({
|
|
188
|
-
adapters: { fake: adapter },
|
|
189
|
-
candidates,
|
|
190
|
-
policy: personalConfig,
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
const task = await runtime.startBackground(
|
|
194
|
-
makeRequest({ mode: "background", taskId: "task_cancel" }),
|
|
195
|
-
);
|
|
196
|
-
expect(task.status).toBe("running");
|
|
197
|
-
|
|
198
|
-
const cancelled = await runtime.cancel(task.taskId);
|
|
199
|
-
expect(cancelled?.status).toBe("cancelled");
|
|
200
|
-
expect(cancelSpy).toHaveBeenCalledWith(task.callId);
|
|
201
|
-
|
|
202
|
-
const settled = await runtime.wait(task.taskId);
|
|
203
|
-
expect(settled.status).toBe("cancelled");
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
it("rejects full prompt text when policy denies the provider (before invoke)", async () => {
|
|
207
|
-
let invokeCount = 0;
|
|
208
|
-
const base = createFakeProvider({ id: "evil" });
|
|
209
|
-
const adapter = {
|
|
210
|
-
...base,
|
|
211
|
-
id: "evil",
|
|
212
|
-
listModels: () => base.listModels(),
|
|
213
|
-
checkAuth: () => base.checkAuth(),
|
|
214
|
-
queryLimits: (t: Parameters<typeof base.queryLimits>[0]) =>
|
|
215
|
-
base.queryLimits(t),
|
|
216
|
-
estimate: (
|
|
217
|
-
r: Parameters<typeof base.estimate>[0],
|
|
218
|
-
m: string,
|
|
219
|
-
t: Parameters<typeof base.estimate>[2],
|
|
220
|
-
) => base.estimate(r, m, t),
|
|
221
|
-
async *invoke(
|
|
222
|
-
req: Parameters<typeof base.invoke>[0],
|
|
223
|
-
): ReturnType<typeof base.invoke> {
|
|
224
|
-
invokeCount += 1;
|
|
225
|
-
yield* base.invoke(req);
|
|
226
|
-
},
|
|
227
|
-
cancel: (id: string) => base.cancel(id),
|
|
228
|
-
};
|
|
229
|
-
|
|
230
|
-
const candidates = [
|
|
231
|
-
candidate({
|
|
232
|
-
providerId: "evil",
|
|
233
|
-
modelId: "evil-model",
|
|
234
|
-
authTier: "api-key",
|
|
235
|
-
}),
|
|
236
|
-
];
|
|
237
|
-
const runtime = new DelegationRuntime({
|
|
238
|
-
adapters: { evil: adapter },
|
|
239
|
-
candidates,
|
|
240
|
-
policy: {
|
|
241
|
-
...personalConfig,
|
|
242
|
-
deniedProviders: ["evil"],
|
|
243
|
-
},
|
|
244
|
-
audit: new InMemoryAuditStore(),
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
const secret = "TOP_SECRET_PROMPT_NEVER_LEAVE";
|
|
248
|
-
await expect(
|
|
249
|
-
runtime.delegate(
|
|
250
|
-
makeRequest({
|
|
251
|
-
taskId: "task_denied",
|
|
252
|
-
prompt: secret,
|
|
253
|
-
}),
|
|
254
|
-
),
|
|
255
|
-
).rejects.toThrow(/policy|denied|blocked/i);
|
|
256
|
-
|
|
257
|
-
expect(invokeCount).toBe(0);
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
it("rejects provider/model overrides that do not match the policy-selected route", async () => {
|
|
261
|
-
let evilInvokeCount = 0;
|
|
262
|
-
const fake = createFakeProvider({ id: "fake" });
|
|
263
|
-
const evilBase = createFakeProvider({ id: "evil" });
|
|
264
|
-
const evil = {
|
|
265
|
-
...evilBase,
|
|
266
|
-
id: "evil",
|
|
267
|
-
listModels: () => evilBase.listModels(),
|
|
268
|
-
checkAuth: () => evilBase.checkAuth(),
|
|
269
|
-
queryLimits: (t: Parameters<typeof evilBase.queryLimits>[0]) =>
|
|
270
|
-
evilBase.queryLimits(t),
|
|
271
|
-
estimate: (
|
|
272
|
-
r: Parameters<typeof evilBase.estimate>[0],
|
|
273
|
-
m: string,
|
|
274
|
-
t: Parameters<typeof evilBase.estimate>[2],
|
|
275
|
-
) => evilBase.estimate(r, m, t),
|
|
276
|
-
async *invoke(
|
|
277
|
-
req: Parameters<typeof evilBase.invoke>[0],
|
|
278
|
-
): ReturnType<typeof evilBase.invoke> {
|
|
279
|
-
evilInvokeCount += 1;
|
|
280
|
-
yield* evilBase.invoke(req);
|
|
281
|
-
},
|
|
282
|
-
cancel: (id: string) => evilBase.cancel(id),
|
|
283
|
-
};
|
|
284
|
-
|
|
285
|
-
const candidates = [
|
|
286
|
-
candidate({
|
|
287
|
-
providerId: "fake",
|
|
288
|
-
modelId: "fake-coder",
|
|
289
|
-
authTier: "api-key",
|
|
290
|
-
}),
|
|
291
|
-
];
|
|
292
|
-
const runtime = new DelegationRuntime({
|
|
293
|
-
adapters: { fake, evil },
|
|
294
|
-
candidates,
|
|
295
|
-
policy: personalConfig,
|
|
296
|
-
audit: new InMemoryAuditStore(),
|
|
297
|
-
});
|
|
298
|
-
|
|
299
|
-
await expect(
|
|
300
|
-
runtime.delegate(
|
|
301
|
-
makeRequest({
|
|
302
|
-
taskId: "task_override",
|
|
303
|
-
prompt: "FULL PROMPT MUST NOT REACH EVIL",
|
|
304
|
-
providerId: "evil",
|
|
305
|
-
model: "evil-model",
|
|
306
|
-
}),
|
|
307
|
-
),
|
|
308
|
-
).rejects.toThrow(/override|policy|selected/i);
|
|
309
|
-
|
|
310
|
-
expect(evilInvokeCount).toBe(0);
|
|
311
|
-
expect(runtime.getTask("task_override")?.status).toBe("failed");
|
|
312
|
-
});
|
|
313
|
-
|
|
314
|
-
it("writes audit with digest and redacted preview, never the raw prompt", async () => {
|
|
315
|
-
const adapter = createFakeProvider({
|
|
316
|
-
id: "fake",
|
|
317
|
-
responseText: "ok",
|
|
318
|
-
});
|
|
319
|
-
const candidates = [
|
|
320
|
-
candidate({
|
|
321
|
-
providerId: "fake",
|
|
322
|
-
modelId: "fake-coder",
|
|
323
|
-
authTier: "api-key",
|
|
324
|
-
}),
|
|
325
|
-
];
|
|
326
|
-
const audit = new InMemoryAuditStore();
|
|
327
|
-
const runtime = new DelegationRuntime({
|
|
328
|
-
adapters: { fake: adapter },
|
|
329
|
-
candidates,
|
|
330
|
-
policy: personalConfig,
|
|
331
|
-
audit,
|
|
332
|
-
});
|
|
333
|
-
|
|
334
|
-
const raw = "FULL RAW PROMPT sk-abcdefghijklmnopqrstuvwxyz0123456789SECRET";
|
|
335
|
-
await runtime.delegate(
|
|
336
|
-
makeRequest({
|
|
337
|
-
taskId: "task_audit",
|
|
338
|
-
prompt: raw,
|
|
339
|
-
route: {
|
|
340
|
-
requestId: "req_audit",
|
|
341
|
-
task: {
|
|
342
|
-
promptPreview: raw.slice(0, 40),
|
|
343
|
-
promptDigest: "sha256:audit_digest",
|
|
344
|
-
kind: "explain",
|
|
345
|
-
risk: "low",
|
|
346
|
-
},
|
|
347
|
-
},
|
|
348
|
-
}),
|
|
349
|
-
);
|
|
350
|
-
|
|
351
|
-
const records = await audit.list({ requestId: "req_audit" });
|
|
352
|
-
expect(records.length).toBeGreaterThan(0);
|
|
353
|
-
|
|
354
|
-
const joined = JSON.stringify(records);
|
|
355
|
-
expect(joined).not.toContain(raw);
|
|
356
|
-
expect(joined).not.toContain("sk-abcdefghijklmnopqrstuvwxyz0123456789");
|
|
357
|
-
|
|
358
|
-
const withDigest = records.find((r) => r.promptDigest);
|
|
359
|
-
expect(withDigest?.promptDigest).toBe("sha256:audit_digest");
|
|
360
|
-
|
|
361
|
-
const withPreview = records.find((r) => r.promptPreviewRedacted);
|
|
362
|
-
expect(withPreview?.promptPreviewRedacted).toBeDefined();
|
|
363
|
-
expect(withPreview?.promptPreviewRedacted).not.toBe(raw);
|
|
364
|
-
expect(withPreview?.promptPreviewRedacted).not.toContain(
|
|
365
|
-
"sk-abcdefghijklmnopqrstuvwxyz0123456789",
|
|
366
|
-
);
|
|
367
|
-
});
|
|
368
|
-
});
|