@arnilo/prism 0.0.15 → 0.0.16
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 +11 -0
- package/dist/agent-definitions.js +2 -3
- package/dist/agent-loops.js +12 -7
- package/dist/agent-run-lifecycle.d.ts +1 -2
- package/dist/agent-run-lifecycle.js +1 -1
- package/dist/agent-run-state.js +16 -3
- package/dist/agents.d.ts +1 -1
- package/dist/agents.js +121 -51
- package/dist/cache-helpers.js +18 -9
- package/dist/checkpoints.js +5 -9
- package/dist/cli-init.js +3 -7
- package/dist/cli-runner.d.ts +1 -1
- package/dist/cli-runner.js +74 -13
- package/dist/compaction.js +5 -4
- package/dist/config.js +7 -4
- package/dist/content.js +26 -24
- package/dist/context-budget.js +12 -8
- package/dist/contracts.d.ts +3 -3
- package/dist/contracts.js +4 -1
- package/dist/contribution-parsing.js +6 -2
- package/dist/conversations.js +2 -1
- package/dist/credentials.d.ts +1 -1
- package/dist/credentials.js +3 -1
- package/dist/event-multiplexer.js +1 -3
- package/dist/feedback.js +11 -9
- package/dist/guardrails.d.ts +1 -1
- package/dist/guardrails.js +17 -14
- package/dist/identity.js +10 -2
- package/dist/index.d.ts +82 -83
- package/dist/index.js +42 -42
- package/dist/input.d.ts +2 -2
- package/dist/input.js +40 -24
- package/dist/instruction-injection.d.ts +1 -1
- package/dist/node/agent-definitions.js +16 -8
- package/dist/node/contribution-discovery.d.ts +1 -2
- package/dist/node/contribution-discovery.js +3 -3
- package/dist/node/session-store-jsonl.js +10 -7
- package/dist/node/settings.d.ts +1 -1
- package/dist/node/settings.js +1 -1
- package/dist/node/system-project-prompts.js +2 -4
- package/dist/node/trust.js +1 -1
- package/dist/persistence-lifecycle.js +1 -3
- package/dist/provider-events.js +3 -1
- package/dist/provider-request-policy.js +3 -4
- package/dist/providers/media.d.ts +1 -1
- package/dist/providers/openai-compatible.js +3 -4
- package/dist/providers/openai-primitives.js +7 -7
- package/dist/redaction.d.ts +1 -0
- package/dist/redaction.js +5 -2
- package/dist/resources.d.ts +2 -2
- package/dist/resources.js +2 -2
- package/dist/rpc.js +42 -9
- package/dist/run-ledger.js +13 -4
- package/dist/run-limits.js +49 -10
- package/dist/secure-agent.js +1 -1
- package/dist/security.js +7 -2
- package/dist/session-stores.d.ts +1 -1
- package/dist/session-stores.js +13 -13
- package/dist/structured-output.js +2 -2
- package/dist/system-prompts.js +7 -2
- package/dist/testing/compaction-conformance.js +5 -1
- package/dist/testing/extension-conformance.js +15 -3
- package/dist/testing/feedback.d.ts +1 -3
- package/dist/testing/feedback.js +1 -1
- package/dist/testing/persistence-schema.js +206 -37
- package/dist/testing/provider-conformance.js +3 -3
- package/dist/testing/run-ledger-conformance.js +1 -1
- package/dist/testing/session-store-conformance.js +1 -1
- package/dist/testing/tool-conformance.js +30 -5
- package/dist/thinking.js +4 -1
- package/dist/tools.d.ts +2 -2
- package/dist/tools.js +24 -5
- package/docs/0.1.0-readiness.md +139 -0
- package/docs/index.md +3 -1
- package/docs/migration.md +29 -0
- package/docs/performance.md +33 -0
- package/docs/public-contracts.md +1 -1
- package/docs/release-and-install.md +106 -17
- package/package.json +14 -6
- package/docs/review-coverage-2026-07-14.md +0 -260
- package/docs/review-coverage-2026-07-15.md +0 -193
- package/docs/review-coverage-2026-07-17-provider-validation.md +0 -192
- package/docs/review-coverage-2026-07-19-phase-3.md +0 -174
- package/docs/review-coverage-2026-07-20-phase-4.md +0 -175
- package/docs/review-coverage-2026-07-21-phase-5.md +0 -172
- package/docs/review-coverage-2026-07-22-phase-6.md +0 -209
- package/docs/review-coverage-2026-07-22-phase-7.md +0 -173
- package/docs/review-coverage-2026-07-23-phase-8.md +0 -245
- package/docs/review-coverage-2026-07-25-phase-9.md +0 -256
- package/docs/review-coverage-2026-07-26-phase-10.md +0 -132
package/dist/cli-runner.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import process from "node:process";
|
|
2
|
-
import { createAgent, createMockProvider, providerDone, providerTextDelta, resolveInstructionInjectors, createContributionRegistry } from "./index.js";
|
|
3
1
|
import { readFile } from "node:fs/promises";
|
|
4
2
|
import { basename, dirname } from "node:path";
|
|
3
|
+
import process from "node:process";
|
|
4
|
+
import { initUsage, runInitCommand } from "./cli-init.js";
|
|
5
5
|
import { createContributionRegistries, registerDiscoveredContributions } from "./contributions.js";
|
|
6
|
-
import {
|
|
7
|
-
import { discoverContributions } from "./node/contribution-discovery.js";
|
|
6
|
+
import { createAgent, createContributionRegistry, createMockProvider, providerDone, providerTextDelta, resolveInstructionInjectors, } from "./index.js";
|
|
8
7
|
import { discoverAgentBundles } from "./node/agent-definitions.js";
|
|
8
|
+
import { discoverContributions } from "./node/contribution-discovery.js";
|
|
9
9
|
import { registerDiscoveredInstructionInjectors } from "./node/instruction-injectors.js";
|
|
10
10
|
import { loadSystemPromptFiles } from "./node/system-project-prompts.js";
|
|
11
11
|
import { createPathTrustPolicy } from "./node/trust.js";
|
|
12
12
|
import { runRpcServer } from "./rpc.js";
|
|
13
|
-
import {
|
|
13
|
+
import { createSkillRegistry } from "./skills.js";
|
|
14
14
|
export const usage = `Usage: prism [--mode print|json|rpc] [-p prompt] [options]
|
|
15
15
|
prism init <dir> [--provider <name>] [--with-workflows] [--with-evals] [--force]
|
|
16
16
|
|
|
@@ -37,7 +37,27 @@ Options:
|
|
|
37
37
|
--system-md-file <path> Read SYSTEM.md from <path> instead (source: user)
|
|
38
38
|
-h, --help Show this help
|
|
39
39
|
`;
|
|
40
|
-
const valueFlags = new Set([
|
|
40
|
+
const valueFlags = new Set([
|
|
41
|
+
"--prompt",
|
|
42
|
+
"--mode",
|
|
43
|
+
"--provider",
|
|
44
|
+
"--model",
|
|
45
|
+
"--session",
|
|
46
|
+
"--config",
|
|
47
|
+
"--resource",
|
|
48
|
+
"--extension",
|
|
49
|
+
"--tool",
|
|
50
|
+
"--system",
|
|
51
|
+
"--context",
|
|
52
|
+
"--compact",
|
|
53
|
+
"--max-tool-rounds",
|
|
54
|
+
"--discover-kinds",
|
|
55
|
+
"--instruction",
|
|
56
|
+
"--injector-file",
|
|
57
|
+
"--agents-md-file",
|
|
58
|
+
"--system-md-file",
|
|
59
|
+
"--agents-config",
|
|
60
|
+
]);
|
|
41
61
|
const boolFlags = new Set(["--discover", "--no-discovery", "--no-agents-md", "--no-system-md"]);
|
|
42
62
|
const ALL_KINDS = ["skill", "tool", "context", "instructions"];
|
|
43
63
|
export function parseCliArgs(argv) {
|
|
@@ -157,10 +177,43 @@ export function parseCliArgs(argv) {
|
|
|
157
177
|
break;
|
|
158
178
|
}
|
|
159
179
|
}
|
|
160
|
-
return {
|
|
180
|
+
return {
|
|
181
|
+
mode,
|
|
182
|
+
prompt,
|
|
183
|
+
provider,
|
|
184
|
+
model,
|
|
185
|
+
session,
|
|
186
|
+
config,
|
|
187
|
+
resources,
|
|
188
|
+
extensions,
|
|
189
|
+
tools,
|
|
190
|
+
system,
|
|
191
|
+
context,
|
|
192
|
+
compact,
|
|
193
|
+
maxToolRounds,
|
|
194
|
+
help,
|
|
195
|
+
discover,
|
|
196
|
+
discoverKinds,
|
|
197
|
+
noDiscovery,
|
|
198
|
+
agentsConfig,
|
|
199
|
+
discoveredSkills: [],
|
|
200
|
+
discoveredInjectors: [],
|
|
201
|
+
discoveredAgents: [],
|
|
202
|
+
instructions,
|
|
203
|
+
injectorFiles,
|
|
204
|
+
resolvedInstructionInjectors: [],
|
|
205
|
+
noAgentsMd,
|
|
206
|
+
noSystemMd,
|
|
207
|
+
agentsMdFile,
|
|
208
|
+
systemMdFile,
|
|
209
|
+
systemPromptLayers: [],
|
|
210
|
+
};
|
|
161
211
|
}
|
|
162
212
|
function parseKinds(csv, flag) {
|
|
163
|
-
const kinds = csv
|
|
213
|
+
const kinds = csv
|
|
214
|
+
.split(",")
|
|
215
|
+
.map((k) => k.trim())
|
|
216
|
+
.filter(Boolean);
|
|
164
217
|
if (kinds.length === 0)
|
|
165
218
|
throw new CliUsageError(`Invalid value for ${flag}: ${csv}`);
|
|
166
219
|
const invalid = kinds.filter((k) => !ALL_KINDS.includes(k));
|
|
@@ -193,7 +246,12 @@ export async function runCli(argv, runtime) {
|
|
|
193
246
|
}
|
|
194
247
|
try {
|
|
195
248
|
if (options.mode === "rpc") {
|
|
196
|
-
await runRpcServer({
|
|
249
|
+
await runRpcServer({
|
|
250
|
+
stdin: runtime.stdin,
|
|
251
|
+
stdout: runtime.stdout,
|
|
252
|
+
createSession: (id) => (runtime.createSession ?? defaultCreateSession)({ ...options, session: id ?? options.session }),
|
|
253
|
+
commands: runtime.commands,
|
|
254
|
+
});
|
|
197
255
|
return 0;
|
|
198
256
|
}
|
|
199
257
|
if (!options.prompt)
|
|
@@ -248,7 +306,12 @@ export async function runCli(argv, runtime) {
|
|
|
248
306
|
// the containment check (the user named it, so it's trusted by that act).
|
|
249
307
|
const layers = await loadSystemPromptFiles({
|
|
250
308
|
...(options.noAgentsMd ? {} : { workspaceRoot, trust, ...(options.agentsMdFile ? { agentsMdPath: options.agentsMdFile } : {}) }),
|
|
251
|
-
...(options.noSystemMd
|
|
309
|
+
...(options.noSystemMd
|
|
310
|
+
? {}
|
|
311
|
+
: {
|
|
312
|
+
...(runtime.globalRoot !== undefined ? { globalRoot: runtime.globalRoot } : {}),
|
|
313
|
+
...(options.systemMdFile ? { systemMdPath: options.systemMdFile } : {}),
|
|
314
|
+
}),
|
|
252
315
|
});
|
|
253
316
|
options = { ...options, systemPromptLayers: layers };
|
|
254
317
|
}
|
|
@@ -306,9 +369,7 @@ function runOptions(options) {
|
|
|
306
369
|
...(options.discover && !options.noDiscovery && options.discoveredSkills.length > 0
|
|
307
370
|
? { activeSkills: options.discoveredSkills.map((s) => s.name) }
|
|
308
371
|
: {}),
|
|
309
|
-
...(options.resolvedInstructionInjectors.length > 0
|
|
310
|
-
? { instructionInjectors: options.resolvedInstructionInjectors }
|
|
311
|
-
: {}),
|
|
372
|
+
...(options.resolvedInstructionInjectors.length > 0 ? { instructionInjectors: options.resolvedInstructionInjectors } : {}),
|
|
312
373
|
};
|
|
313
374
|
}
|
|
314
375
|
// ponytail: resolve --instruction names against discovered injectors (fail-closed) and load
|
package/dist/compaction.js
CHANGED
|
@@ -27,10 +27,11 @@ export function isCompactionEntryData(value) {
|
|
|
27
27
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
28
28
|
return false;
|
|
29
29
|
const data = value;
|
|
30
|
-
return (data.throughEntryId === undefined || typeof data.throughEntryId === "string")
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
return ((data.throughEntryId === undefined || typeof data.throughEntryId === "string") &&
|
|
31
|
+
(data.keepEntryIds === undefined ||
|
|
32
|
+
(Array.isArray(data.keepEntryIds) && data.keepEntryIds.every((item) => typeof item === "string"))) &&
|
|
33
|
+
(data.strategy === undefined || typeof data.strategy === "string") &&
|
|
34
|
+
(data.trigger === undefined || typeof data.trigger === "string"));
|
|
34
35
|
}
|
|
35
36
|
function summarize(entries) {
|
|
36
37
|
const lines = entries.flatMap((entry) => entryText(entry));
|
package/dist/config.js
CHANGED
|
@@ -31,9 +31,10 @@ function mergeObjects(base, override, path = "config") {
|
|
|
31
31
|
const childPath = `${path}.${key}`;
|
|
32
32
|
assertSafeJsonKey(key, childPath);
|
|
33
33
|
const current = result[key];
|
|
34
|
-
result[key] =
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
result[key] =
|
|
35
|
+
isPlainObject(current) && isPlainObject(value)
|
|
36
|
+
? mergeObjects(current, value, childPath)
|
|
37
|
+
: cloneJsonValue(value, childPath);
|
|
37
38
|
}
|
|
38
39
|
return result;
|
|
39
40
|
}
|
|
@@ -77,7 +78,9 @@ function isSafeJsonValue(value) {
|
|
|
77
78
|
}
|
|
78
79
|
function assertSafeJsonValue(value, path) {
|
|
79
80
|
if (Array.isArray(value)) {
|
|
80
|
-
value.forEach((entry, index) =>
|
|
81
|
+
value.forEach((entry, index) => {
|
|
82
|
+
assertSafeJsonValue(entry, `${path}[${index}]`);
|
|
83
|
+
});
|
|
81
84
|
return;
|
|
82
85
|
}
|
|
83
86
|
if (!isPlainObject(value))
|
package/dist/content.js
CHANGED
|
@@ -112,12 +112,12 @@ export function assertSsrfAllowedUrl(url, policy = {}) {
|
|
|
112
112
|
}
|
|
113
113
|
if (policy.denyPrivateHosts === false)
|
|
114
114
|
return;
|
|
115
|
-
if (hostname === "localhost"
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
115
|
+
if (hostname === "localhost" ||
|
|
116
|
+
hostname.endsWith(".localhost") ||
|
|
117
|
+
hostname.endsWith(".local") ||
|
|
118
|
+
hostname === "metadata" ||
|
|
119
|
+
hostname === "metadata.google.internal" ||
|
|
120
|
+
hostname === "instance-data") {
|
|
121
121
|
throw new MediaContentError("ssrf_denied", `Media URL host ${hostname} is not allowed`);
|
|
122
122
|
}
|
|
123
123
|
if (isBlockedIp(hostname)) {
|
|
@@ -306,9 +306,7 @@ async function fetchBoundedMediaUrl(url, options) {
|
|
|
306
306
|
assertSsrfAllowedUrl(url, options.ssrf);
|
|
307
307
|
const timeoutController = new AbortController();
|
|
308
308
|
const timeout = setTimeout(() => timeoutController.abort(), options.timeoutMs);
|
|
309
|
-
const signal = options.signal
|
|
310
|
-
? AbortSignal.any([options.signal, timeoutController.signal])
|
|
311
|
-
: timeoutController.signal;
|
|
309
|
+
const signal = options.signal ? AbortSignal.any([options.signal, timeoutController.signal]) : timeoutController.signal;
|
|
312
310
|
try {
|
|
313
311
|
if (options.fetch)
|
|
314
312
|
return await readFetchResponse(await options.fetch(url, { signal, redirect: "error" }), options.maxBytes);
|
|
@@ -372,7 +370,13 @@ async function raceAbort(promise, signal) {
|
|
|
372
370
|
reject(signal.reason);
|
|
373
371
|
};
|
|
374
372
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
375
|
-
promise.then((value) => {
|
|
373
|
+
promise.then((value) => {
|
|
374
|
+
cleanup();
|
|
375
|
+
resolve(value);
|
|
376
|
+
}, (error) => {
|
|
377
|
+
cleanup();
|
|
378
|
+
reject(error);
|
|
379
|
+
});
|
|
376
380
|
});
|
|
377
381
|
}
|
|
378
382
|
async function readFetchResponse(response, maxBytes) {
|
|
@@ -479,22 +483,22 @@ function isBlockedIp(hostname) {
|
|
|
479
483
|
}
|
|
480
484
|
function isBlockedIpv4(address) {
|
|
481
485
|
const [a, b] = address.split(".").map(Number);
|
|
482
|
-
return a === 0
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
486
|
+
return (a === 0 ||
|
|
487
|
+
a === 10 ||
|
|
488
|
+
a === 127 ||
|
|
489
|
+
(a === 100 && b >= 64 && b <= 127) ||
|
|
490
|
+
(a === 169 && b === 254) ||
|
|
491
|
+
(a === 172 && b >= 16 && b <= 31) ||
|
|
492
|
+
(a === 192 && (b === 0 || b === 168)) ||
|
|
493
|
+
(a === 198 && (b === 18 || b === 19 || b === 51)) ||
|
|
494
|
+
(a === 203 && b === 0) ||
|
|
495
|
+
a >= 224);
|
|
492
496
|
}
|
|
493
497
|
function isBlockedIpv6(address) {
|
|
494
498
|
const words = parseIpv6Words(address);
|
|
495
499
|
if (!words)
|
|
496
500
|
return true;
|
|
497
|
-
if (words.every((word) => word === 0) || words.slice(0, 7).every((word) => word === 0) && words[7] === 1)
|
|
501
|
+
if (words.every((word) => word === 0) || (words.slice(0, 7).every((word) => word === 0) && words[7] === 1))
|
|
498
502
|
return true;
|
|
499
503
|
if ((words[0] & 0xfe00) === 0xfc00)
|
|
500
504
|
return true;
|
|
@@ -517,9 +521,7 @@ function parseIpv6Words(address) {
|
|
|
517
521
|
if (missing < 0 || (parts.length === 1 && missing !== 0))
|
|
518
522
|
return undefined;
|
|
519
523
|
const words = [...left, ...Array.from({ length: missing }, () => "0"), ...right].map((part) => Number.parseInt(part, 16));
|
|
520
|
-
return words.length === 8 && words.every((word) => Number.isInteger(word) && word >= 0 && word <= 0xffff)
|
|
521
|
-
? words
|
|
522
|
-
: undefined;
|
|
524
|
+
return words.length === 8 && words.every((word) => Number.isInteger(word) && word >= 0 && word <= 0xffff) ? words : undefined;
|
|
523
525
|
}
|
|
524
526
|
function startsWith(bytes, prefix) {
|
|
525
527
|
if (bytes.length < prefix.length)
|
package/dist/context-budget.js
CHANGED
|
@@ -197,13 +197,14 @@ function isContextBudgetReport(value) {
|
|
|
197
197
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
198
198
|
return false;
|
|
199
199
|
const report = value;
|
|
200
|
-
return Array.isArray(report.omitted)
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
200
|
+
return (Array.isArray(report.omitted) &&
|
|
201
|
+
typeof report.keptTokens === "number" &&
|
|
202
|
+
typeof report.keptBytes === "number" &&
|
|
203
|
+
typeof report.truncated === "boolean");
|
|
204
204
|
}
|
|
205
205
|
function messageText(message) {
|
|
206
|
-
return message.content
|
|
206
|
+
return message.content
|
|
207
|
+
.map((part) => {
|
|
207
208
|
if (part.type === "text" || part.type === "thinking")
|
|
208
209
|
return part.text;
|
|
209
210
|
if (part.type === "tool_result")
|
|
@@ -221,15 +222,18 @@ function messageText(message) {
|
|
|
221
222
|
if (part.type === "document")
|
|
222
223
|
return part.transcript ?? part.name ?? part.url ?? part.resourceUri ?? part.mediaType ?? "[document]";
|
|
223
224
|
return "[content]";
|
|
224
|
-
})
|
|
225
|
+
})
|
|
226
|
+
.join("\n");
|
|
225
227
|
}
|
|
226
228
|
function contextBlockText(block) {
|
|
227
229
|
if (typeof block.content === "string")
|
|
228
230
|
return block.content;
|
|
229
|
-
return block.content
|
|
231
|
+
return block.content
|
|
232
|
+
.map((part) => {
|
|
230
233
|
if (part.type === "text" || part.type === "thinking")
|
|
231
234
|
return part.text;
|
|
232
235
|
return "[content]";
|
|
233
|
-
})
|
|
236
|
+
})
|
|
237
|
+
.join("\n");
|
|
234
238
|
}
|
|
235
239
|
//# sourceMappingURL=context-budget.js.map
|
package/dist/contracts.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { AudioContent, DocumentContent, FileContent } from "./content.js";
|
|
2
2
|
import type { ContributionRegistries } from "./contributions.js";
|
|
3
|
+
import type { AgentInput } from "./input.js";
|
|
4
|
+
import type { ManifestContributionDeclaration } from "./manifests.js";
|
|
3
5
|
import type { Middleware, MiddlewareHookName, MiddlewareRegistry } from "./middleware.js";
|
|
4
6
|
import type { SecretRedactor } from "./redaction.js";
|
|
5
7
|
import type { PermissionPolicy, TrustPolicy } from "./security.js";
|
|
6
|
-
import type { ManifestContributionDeclaration } from "./manifests.js";
|
|
7
8
|
import type { ToolValidator } from "./tools.js";
|
|
8
|
-
import type { AudioContent, DocumentContent, FileContent } from "./content.js";
|
|
9
9
|
export type JsonPrimitive = string | number | boolean | null;
|
|
10
10
|
export type JsonValue = JsonPrimitive | JsonObject | JsonValue[];
|
|
11
11
|
export interface JsonObject {
|
package/dist/contracts.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
export class AgentRunStateError extends Error {
|
|
2
2
|
code = "ERR_PRISM_AGENT_RUN_STATE";
|
|
3
|
-
constructor(message) {
|
|
3
|
+
constructor(message) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.name = "AgentRunStateError";
|
|
6
|
+
}
|
|
4
7
|
}
|
|
5
8
|
export class AgentRunError extends Error {
|
|
6
9
|
result;
|
|
@@ -50,7 +50,11 @@ function parseFrontBlock(lines) {
|
|
|
50
50
|
out.set(key, items);
|
|
51
51
|
}
|
|
52
52
|
else if (value.startsWith("[") && value.endsWith("]")) {
|
|
53
|
-
out.set(key, value
|
|
53
|
+
out.set(key, value
|
|
54
|
+
.slice(1, -1)
|
|
55
|
+
.split(",")
|
|
56
|
+
.map((s) => s.trim())
|
|
57
|
+
.filter((s) => s.length > 0));
|
|
54
58
|
}
|
|
55
59
|
else {
|
|
56
60
|
out.set(key, value);
|
|
@@ -63,7 +67,7 @@ function parseFrontBlock(lines) {
|
|
|
63
67
|
// plain string split instead of `node:path`. Expects `.../<name>/SKILL.md`.
|
|
64
68
|
function parentDirName(path) {
|
|
65
69
|
const parts = path.split(/[/\\]+/).filter(Boolean);
|
|
66
|
-
return parts.length >= 2 ? parts[parts.length - 2] : parts[parts.length - 1] ?? "";
|
|
70
|
+
return parts.length >= 2 ? parts[parts.length - 2] : (parts[parts.length - 1] ?? "");
|
|
67
71
|
}
|
|
68
72
|
const NAME_RE = /^[A-Za-z0-9 _-]+$/;
|
|
69
73
|
/** Parse a `SKILL.md` into a {@link Skill}. Frontmatter keys map to `name`
|
package/dist/conversations.js
CHANGED
|
@@ -56,7 +56,8 @@ export function conversationThreadFromRecord(record) {
|
|
|
56
56
|
const branches = [];
|
|
57
57
|
if (Array.isArray(value.branches)) {
|
|
58
58
|
for (const item of value.branches) {
|
|
59
|
-
if (item &&
|
|
59
|
+
if (item &&
|
|
60
|
+
typeof item === "object" &&
|
|
60
61
|
typeof item.leafId === "string" &&
|
|
61
62
|
typeof item.createdAt === "string") {
|
|
62
63
|
branches.push({
|
package/dist/credentials.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Credential,
|
|
1
|
+
import type { Credential, CredentialRequest, CredentialResolver, CredentialResolverSource, OAuthCredentialStore, OAuthCredentials, OAuthProvider } from "./contracts.js";
|
|
2
2
|
export type CredentialValueSource = string | (() => string | undefined | Promise<string | undefined>) | CredentialResolver;
|
|
3
3
|
export interface CredentialRecord {
|
|
4
4
|
readonly name: string;
|
package/dist/credentials.js
CHANGED
|
@@ -37,7 +37,9 @@ export function createExplicitCredentialResolver(sources) {
|
|
|
37
37
|
export function createEnvCredentialResolver(env, map) {
|
|
38
38
|
return {
|
|
39
39
|
resolve(request) {
|
|
40
|
-
const envName = map[credentialMapKey(request.name, request.provider)] ??
|
|
40
|
+
const envName = map[credentialMapKey(request.name, request.provider)] ??
|
|
41
|
+
(request.provider ? map[request.provider] : undefined) ??
|
|
42
|
+
map[request.name];
|
|
41
43
|
const value = envName ? env[envName] : undefined;
|
|
42
44
|
return value ? { type: "api_key", value, metadata: { source: "env", envName } } : undefined;
|
|
43
45
|
},
|
|
@@ -27,9 +27,7 @@ export function createEventMultiplexer(options = {}) {
|
|
|
27
27
|
return;
|
|
28
28
|
}
|
|
29
29
|
droppedEvents += 1;
|
|
30
|
-
const notice = !overflowNotified && options.overflowEvent
|
|
31
|
-
? options.overflowEvent({ droppedEvents, maxQueuedEvents, policy: overflow })
|
|
32
|
-
: undefined;
|
|
30
|
+
const notice = !overflowNotified && options.overflowEvent ? options.overflowEvent({ droppedEvents, maxQueuedEvents, policy: overflow }) : undefined;
|
|
33
31
|
overflowNotified = true;
|
|
34
32
|
if (overflow === "close") {
|
|
35
33
|
queue.length = 0;
|
package/dist/feedback.js
CHANGED
|
@@ -48,10 +48,14 @@ export async function prepareRunFeedback(input, options) {
|
|
|
48
48
|
const tags = normalizeList(input.tags, maxTags, MAX_FEEDBACK_TAG_LENGTH, "tag");
|
|
49
49
|
const scorerIds = normalizeList(input.scorerIds, maxLinks, MAX_FEEDBACK_ID_LENGTH, "scorer id", true);
|
|
50
50
|
const evaluationIds = normalizeList(input.evaluationIds, maxLinks, MAX_FEEDBACK_ID_LENGTH, "evaluation id", true);
|
|
51
|
-
if (input.rating === undefined &&
|
|
51
|
+
if (input.rating === undefined &&
|
|
52
|
+
input.comment === undefined &&
|
|
53
|
+
tags.length === 0 &&
|
|
54
|
+
scorerIds.length === 0 &&
|
|
55
|
+
evaluationIds.length === 0) {
|
|
52
56
|
throw new RunFeedbackError("feedback requires rating, comment, tag, scorer, or evaluation", "ERR_PRISM_RUN_FEEDBACK_EMPTY");
|
|
53
57
|
}
|
|
54
|
-
const redact = (value) => options.redactor ? options.redactor.redact(value) : value;
|
|
58
|
+
const redact = (value) => (options.redactor ? options.redactor.redact(value) : value);
|
|
55
59
|
const comment = input.comment === undefined ? undefined : redact(input.comment);
|
|
56
60
|
const safeTags = Object.freeze(normalizeList(redact(tags), maxTags, MAX_FEEDBACK_TAG_LENGTH, "tag"));
|
|
57
61
|
const metadata = input.metadata === undefined ? undefined : redact(input.metadata);
|
|
@@ -121,18 +125,16 @@ export function runFeedbackPageLimit(limit, maximum = HARD_FEEDBACK_PAGE_SIZE) {
|
|
|
121
125
|
return pageLimit(limit, maximum);
|
|
122
126
|
}
|
|
123
127
|
function requireOwnership(input) {
|
|
124
|
-
if (!input.tenantId?.trim()
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
+
if (!input.tenantId?.trim() ||
|
|
129
|
+
(input.accountId !== undefined && !input.accountId.trim()) ||
|
|
130
|
+
(input.userId !== undefined && !input.userId.trim()) ||
|
|
131
|
+
(!input.accountId && !input.userId)) {
|
|
128
132
|
throw new RunFeedbackError("tenantId and non-empty accountId or userId are required", "ERR_PRISM_RUN_FEEDBACK_OWNERSHIP");
|
|
129
133
|
}
|
|
130
134
|
return { tenantId: input.tenantId, accountId: input.accountId, userId: input.userId };
|
|
131
135
|
}
|
|
132
136
|
function sameOwnership(expected, actual) {
|
|
133
|
-
return expected.tenantId === actual.tenantId
|
|
134
|
-
&& expected.accountId === actual.accountId
|
|
135
|
-
&& expected.userId === actual.userId;
|
|
137
|
+
return expected.tenantId === actual.tenantId && expected.accountId === actual.accountId && expected.userId === actual.userId;
|
|
136
138
|
}
|
|
137
139
|
function requireId(value, label) {
|
|
138
140
|
if (!value || value.length > MAX_FEEDBACK_ID_LENGTH || !/^[A-Za-z0-9][A-Za-z0-9._:-]*$/.test(value)) {
|
package/dist/guardrails.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AgentEvent, GuardrailContext, GuardrailRecord,
|
|
1
|
+
import type { AgentEvent, GuardrailContext, GuardrailRecord, GuardrailStage, Guardrails, GuardrailValue } from "./contracts.js";
|
|
2
2
|
import type { SecretRedactor } from "./redaction.js";
|
|
3
3
|
export declare const MAX_GUARDRAIL_CONCURRENCY = 16;
|
|
4
4
|
export declare class GuardrailError extends Error {
|
package/dist/guardrails.js
CHANGED
|
@@ -7,9 +7,7 @@ export class GuardrailError extends Error {
|
|
|
7
7
|
constructor(record) {
|
|
8
8
|
super(record.action === "interrupt" ? "Guardrail interruption is unavailable" : "Guardrail blocked run");
|
|
9
9
|
this.name = "GuardrailError";
|
|
10
|
-
this.code = record.action === "interrupt"
|
|
11
|
-
? "ERR_PRISM_GUARDRAIL_INTERRUPT_UNAVAILABLE"
|
|
12
|
-
: "ERR_PRISM_GUARDRAIL_BLOCKED";
|
|
10
|
+
this.code = record.action === "interrupt" ? "ERR_PRISM_GUARDRAIL_INTERRUPT_UNAVAILABLE" : "ERR_PRISM_GUARDRAIL_BLOCKED";
|
|
13
11
|
this.record = record;
|
|
14
12
|
}
|
|
15
13
|
}
|
|
@@ -20,9 +18,7 @@ export async function runGuardrails(options) {
|
|
|
20
18
|
return { records: [] };
|
|
21
19
|
const maxConcurrency = resolveConcurrency(options.guardrails?.maxConcurrency);
|
|
22
20
|
const controller = new AbortController();
|
|
23
|
-
const signal = options.context.signal
|
|
24
|
-
? AbortSignal.any([options.context.signal, controller.signal])
|
|
25
|
-
: controller.signal;
|
|
21
|
+
const signal = options.context.signal ? AbortSignal.any([options.context.signal, controller.signal]) : controller.signal;
|
|
26
22
|
const records = new Array(guards.length);
|
|
27
23
|
let next = 0;
|
|
28
24
|
let stopped = false;
|
|
@@ -66,14 +62,23 @@ function stageGuards(guardrails, stage) {
|
|
|
66
62
|
if (!guardrails)
|
|
67
63
|
return [];
|
|
68
64
|
switch (stage) {
|
|
69
|
-
case "input":
|
|
70
|
-
|
|
71
|
-
case "
|
|
72
|
-
|
|
65
|
+
case "input":
|
|
66
|
+
return (guardrails.input ?? []);
|
|
67
|
+
case "output":
|
|
68
|
+
return (guardrails.output ?? []);
|
|
69
|
+
case "tool_input":
|
|
70
|
+
return (guardrails.toolInput ?? []);
|
|
71
|
+
case "tool_output":
|
|
72
|
+
return (guardrails.toolOutput ?? []);
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
75
|
async function evaluate(guardrail, options, signal) {
|
|
76
|
-
if (!guardrail ||
|
|
76
|
+
if (!guardrail ||
|
|
77
|
+
typeof guardrail.name !== "string" ||
|
|
78
|
+
!guardrail.name ||
|
|
79
|
+
guardrail.name.length > 128 ||
|
|
80
|
+
guardrail.stage !== options.stage ||
|
|
81
|
+
typeof guardrail.evaluate !== "function") {
|
|
77
82
|
return record(guardrail?.name ?? "invalid", options.stage, "tripwire", "guardrail_invalid", undefined, options.redactor);
|
|
78
83
|
}
|
|
79
84
|
try {
|
|
@@ -115,9 +120,7 @@ function boundedMetadata(value, redactor) {
|
|
|
115
120
|
if (!json || byteLength(json) > MAX_METADATA_BYTES)
|
|
116
121
|
return { truncated: true };
|
|
117
122
|
const parsed = JSON.parse(json);
|
|
118
|
-
return parsed && typeof parsed === "object" && !Array.isArray(parsed)
|
|
119
|
-
? parsed
|
|
120
|
-
: undefined;
|
|
123
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : undefined;
|
|
121
124
|
}
|
|
122
125
|
catch {
|
|
123
126
|
return { invalid: true };
|
package/dist/identity.js
CHANGED
|
@@ -104,9 +104,17 @@ export function narrowIdentity(parent, options) {
|
|
|
104
104
|
scopes: Object.freeze([...options.scopes]),
|
|
105
105
|
credentialRefs: Object.freeze([...(options.credentialRefs ?? parent.credentialRefs ?? [])]),
|
|
106
106
|
issuedAt: parent.issuedAt,
|
|
107
|
-
...(options.expiresAt !== undefined
|
|
107
|
+
...(options.expiresAt !== undefined
|
|
108
|
+
? { expiresAt: options.expiresAt }
|
|
109
|
+
: parent.expiresAt !== undefined
|
|
110
|
+
? { expiresAt: parent.expiresAt }
|
|
111
|
+
: {}),
|
|
108
112
|
...(parent.revokedAt !== undefined ? { revokedAt: parent.revokedAt } : {}),
|
|
109
|
-
...(options.metadata !== undefined
|
|
113
|
+
...(options.metadata !== undefined
|
|
114
|
+
? { metadata: options.metadata }
|
|
115
|
+
: parent.metadata !== undefined
|
|
116
|
+
? { metadata: parent.metadata }
|
|
117
|
+
: {}),
|
|
110
118
|
verified: true,
|
|
111
119
|
};
|
|
112
120
|
assertIdentityActive(child, { limits: options.limits });
|