@arnilo/prism 0.8.0 → 0.10.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 +62 -1
- package/README.md +13 -12
- package/dist/agent-approval.d.ts +17 -2
- package/dist/agent-approval.js +15 -6
- package/dist/agent-event-source.d.ts +9 -1
- package/dist/agent-event-source.js +10 -3
- package/dist/agent-loops.js +7 -4
- package/dist/agent-run-lifecycle.d.ts +15 -1
- package/dist/agent-run-lifecycle.js +82 -11
- package/dist/agent-run-state.d.ts +47 -6
- package/dist/agent-run-state.js +154 -6
- package/dist/agent-session/event-subscriber.d.ts +2 -0
- package/dist/agent-session/event-subscriber.js +3 -0
- package/dist/agent-session/helpers.js +14 -0
- package/dist/agent-session/session/assemble.js +281 -32
- package/dist/agent-session/session/persist.d.ts +11 -0
- package/dist/agent-session/session/persist.js +48 -16
- package/dist/agent-session/session/provider-round.d.ts +14 -4
- package/dist/agent-session/session/provider-round.js +226 -19
- package/dist/agent-session/session/tool-round.d.ts +2 -2
- package/dist/agent-session/session/tool-round.js +78 -6
- package/dist/agent-session/session/types.d.ts +44 -3
- package/dist/agent-session/session.d.ts +100 -5
- package/dist/agent-session/session.js +224 -13
- package/dist/attention-compiler.d.ts +51 -2
- package/dist/attention-compiler.js +282 -21
- package/dist/cache-helpers.d.ts +4 -2
- package/dist/cache-helpers.js +8 -6
- package/dist/checkpoint-restore.d.ts +45 -0
- package/dist/checkpoint-restore.js +54 -0
- package/dist/context-budget.d.ts +13 -1
- package/dist/context-budget.js +57 -4
- package/dist/contracts-core/agent.d.ts +52 -1
- package/dist/contracts-core/attention.d.ts +95 -0
- package/dist/contracts-core/content.d.ts +10 -0
- package/dist/contracts-core/extensions.d.ts +3 -0
- package/dist/contracts-core/guardrail-packs.d.ts +46 -0
- package/dist/contracts-core/guardrail-packs.js +2 -0
- package/dist/contracts-core/loop.d.ts +36 -0
- package/dist/contracts-core/provider.d.ts +30 -0
- package/dist/contracts-core/run-limits.d.ts +29 -1
- package/dist/contracts-core/session.d.ts +23 -5
- package/dist/contracts-core/session.js +21 -2
- package/dist/contracts-core/usage.d.ts +40 -0
- package/dist/contracts-core/usage.js +8 -0
- package/dist/contracts-core.d.ts +2 -0
- package/dist/contracts-core.js +2 -0
- package/dist/contracts-protocol.d.ts +81 -5
- package/dist/contracts-run-state.d.ts +91 -2
- package/dist/contributions.d.ts +2 -1
- package/dist/contributions.js +1 -0
- package/dist/extensions.d.ts +15 -1
- package/dist/extensions.js +68 -0
- package/dist/guardrail-packs/coding-standard.d.ts +3 -0
- package/dist/guardrail-packs/coding-standard.js +63 -0
- package/dist/guardrail-packs/destructive-commands.d.ts +3 -0
- package/dist/guardrail-packs/destructive-commands.js +46 -0
- package/dist/guardrail-packs/errors.d.ts +7 -0
- package/dist/guardrail-packs/errors.js +9 -0
- package/dist/guardrail-packs/index.d.ts +4 -0
- package/dist/guardrail-packs/index.js +15 -0
- package/dist/guardrail-packs/secrets-hygiene.d.ts +3 -0
- package/dist/guardrail-packs/secrets-hygiene.js +23 -0
- package/dist/guardrail-packs/types.d.ts +26 -0
- package/dist/guardrail-packs/types.js +2 -0
- package/dist/guardrail-packs/validation-respect.d.ts +3 -0
- package/dist/guardrail-packs/validation-respect.js +69 -0
- package/dist/guardrails.d.ts +61 -1
- package/dist/guardrails.js +377 -0
- package/dist/index.d.ts +16 -11
- package/dist/index.js +10 -7
- package/dist/input.d.ts +8 -1
- package/dist/input.js +68 -6
- package/dist/middleware.d.ts +37 -2
- package/dist/middleware.js +41 -0
- package/dist/node/session-store-jsonl.js +18 -3
- package/dist/observability.js +6 -0
- package/dist/provider-events.d.ts +8 -2
- package/dist/provider-events.js +60 -2
- package/dist/providers/openai-compatible.js +6 -3
- package/dist/run-bundle.d.ts +6 -1
- package/dist/run-bundle.js +5 -1
- package/dist/run-limits.d.ts +11 -1
- package/dist/run-limits.js +59 -0
- package/dist/session-stores.d.ts +12 -1
- package/dist/session-stores.js +21 -4
- package/dist/testing/agent-event-source-conformance.js +41 -2
- package/dist/testing/prefix-stability-conformance.d.ts +59 -0
- package/dist/testing/prefix-stability-conformance.js +172 -0
- package/dist/testing/session-store-conformance.d.ts +3 -2
- package/dist/testing/session-store-conformance.js +48 -0
- package/dist/tools.d.ts +5 -0
- package/dist/tools.js +21 -6
- package/dist/usage-estimation.d.ts +29 -0
- package/dist/usage-estimation.js +79 -0
- package/docs/agent-events.md +75 -4
- package/docs/agent-session-runtime.md +10 -6
- package/docs/attention-compiler.md +89 -8
- package/docs/caveman.md +1 -1
- package/docs/coding-agent-tools.md +1 -1
- package/docs/compaction-and-retry.md +1 -1
- package/docs/compaction-llm.md +2 -0
- package/docs/compaction-observational-memory.md +54 -7
- package/docs/durable-runs.md +46 -3
- package/docs/embeddings.md +9 -0
- package/docs/evaluations.md +5 -0
- package/docs/execution-timeline.md +79 -1
- package/docs/extensions.md +20 -3
- package/docs/guardrails.md +50 -4
- package/docs/hooks.md +282 -0
- package/docs/index.md +37 -15
- package/docs/input-and-prompt-assembly.md +4 -4
- package/docs/instruction-injection.md +1 -0
- package/docs/knowledge-sync.md +4 -0
- package/docs/live-testing.md +3 -1
- package/docs/memory-fabric.md +28 -0
- package/docs/middleware-hooks.md +90 -4
- package/docs/migrate-to-0.9.md +210 -0
- package/docs/migration.md +26 -0
- package/docs/multi-agent-patterns.md +25 -2
- package/docs/node-jsonl-session-store.md +7 -1
- package/docs/observability.md +7 -3
- package/docs/options-index.md +4 -1
- package/docs/policy-and-audit.md +26 -1
- package/docs/prefix-stability-conformance.md +143 -0
- package/docs/provider-caching.md +4 -4
- package/docs/provider-conformance.md +16 -0
- package/docs/provider-packages.md +20 -20
- package/docs/public-contracts.md +3 -2
- package/docs/rag.md +188 -3
- package/docs/release-and-install.md +45 -40
- package/docs/runs-and-usage.md +56 -10
- package/docs/scoped-agent-memory.md +270 -0
- package/docs/scoped-memory.md +138 -0
- package/docs/session-store-conformance.md +1 -2
- package/docs/session-stores.md +17 -17
- package/docs/supervisors.md +32 -12
- package/docs/tools.md +18 -1
- package/docs/wiki.md +4 -2
- package/docs/workflows.md +5 -0
- package/package.json +8 -2
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { resolve as resolvePath, sep } from "node:path";
|
|
2
|
+
import { GuardrailPackError } from "./errors.js";
|
|
3
|
+
/** File-mutating prism coding tool names (plan 092 Task 1: `shell`/`read` are not mutations). */
|
|
4
|
+
const MUTATING_TOOLS = ["write", "edit", "delete", "move"];
|
|
5
|
+
const PATH_ARGS = ["path", "paths", "from", "to"];
|
|
6
|
+
const TEST_FILE_PATTERN = /(^|[\\/])(?:__tests__|tests?|specs?)[\\/]|\.(?:test|spec)\.[cm]?[jt]sx?$/;
|
|
7
|
+
const MAX_ROOTS = 16;
|
|
8
|
+
function pathStrings(args) {
|
|
9
|
+
const paths = [];
|
|
10
|
+
for (const key of PATH_ARGS) {
|
|
11
|
+
const value = args[key];
|
|
12
|
+
if (typeof value === "string")
|
|
13
|
+
paths.push(value);
|
|
14
|
+
else if (Array.isArray(value))
|
|
15
|
+
paths.push(...value.filter((item) => typeof item === "string"));
|
|
16
|
+
}
|
|
17
|
+
return paths;
|
|
18
|
+
}
|
|
19
|
+
function readRoots(value, cwd) {
|
|
20
|
+
if (value === undefined)
|
|
21
|
+
return [cwd];
|
|
22
|
+
if (!Array.isArray(value) || value.length === 0 || value.length > MAX_ROOTS) {
|
|
23
|
+
throw new GuardrailPackError(`coding-standard options.roots must be a non-empty string array (max ${MAX_ROOTS})`);
|
|
24
|
+
}
|
|
25
|
+
return value.map((root) => {
|
|
26
|
+
if (typeof root !== "string" || !root.trim())
|
|
27
|
+
throw new GuardrailPackError("coding-standard options.roots entries must be non-empty strings");
|
|
28
|
+
return resolvePath(cwd, root);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
/** Lazy containment: no symlink resolution (a link inside a root can still point out); execution policy/sandbox remains the hard boundary. */
|
|
32
|
+
function outsideRoots(candidate, roots, cwd) {
|
|
33
|
+
const resolved = resolvePath(cwd, candidate);
|
|
34
|
+
return !roots.some((root) => resolved === root || resolved.startsWith(root.endsWith(sep) ? root : `${root}${sep}`));
|
|
35
|
+
}
|
|
36
|
+
/** Canned coding hygiene: file mutations confined to configured roots, test files read-only. */
|
|
37
|
+
export const codingStandardPack = {
|
|
38
|
+
id: "coding-standard",
|
|
39
|
+
version: 1,
|
|
40
|
+
description: "Restricts file mutation to configured workspace roots and blocks test-file rewrites.",
|
|
41
|
+
build(options) {
|
|
42
|
+
const cwd = resolvePath(typeof options.cwd === "string" ? options.cwd : process.cwd());
|
|
43
|
+
const roots = readRoots(options.roots, cwd);
|
|
44
|
+
return {
|
|
45
|
+
rules: [
|
|
46
|
+
{
|
|
47
|
+
id: "no-unrelated-file-edits",
|
|
48
|
+
tool: MUTATING_TOOLS,
|
|
49
|
+
reason: "File edits are restricted to the configured workspace roots",
|
|
50
|
+
deny: (args) => pathStrings(args).some((candidate) => outsideRoots(candidate, roots, cwd)),
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
id: "no-test-rewrites",
|
|
54
|
+
tool: MUTATING_TOOLS,
|
|
55
|
+
pattern: TEST_FILE_PATTERN,
|
|
56
|
+
argPath: PATH_ARGS,
|
|
57
|
+
reason: "Test files are read-only under this pack",
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
};
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
//# sourceMappingURL=coding-standard.js.map
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/** Shell commands that destroy data or history. Denies `--force-with-lease` too: both rewrite remote history. */
|
|
2
|
+
const DESTRUCTIVE_COMMANDS = [
|
|
3
|
+
{
|
|
4
|
+
id: "no-recursive-force-delete",
|
|
5
|
+
pattern: /\brm\s+(?:[^\n;&|]*?\s)?-(?=[a-z]*r)(?=[a-z]*f)[a-z]+/i,
|
|
6
|
+
reason: "Recursive force delete is not allowed",
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
id: "no-long-flag-force-delete",
|
|
10
|
+
pattern: /\brm\s+[^\n;&|]*--recursive\b[^\n;&|]*--force\b|\brm\s+[^\n;&|]*--force\b[^\n;&|]*--recursive\b/i,
|
|
11
|
+
reason: "Recursive force delete is not allowed",
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
id: "no-force-push",
|
|
15
|
+
pattern: /\bgit\s+push\b[^\n;&|]*(?:--force\b|(?:^|\s)-f(?:\s|$))/i,
|
|
16
|
+
reason: "Force push is not allowed",
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
id: "no-destructive-sql",
|
|
20
|
+
pattern: /\b(?:drop|truncate)\s+table\b/i,
|
|
21
|
+
reason: "Destructive SQL is not allowed",
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
id: "no-device-overwrite",
|
|
25
|
+
pattern: /\bmkfs(?:\.\w+)?\b|\bdd\b[^\n;&|]*\bof=\/dev\//i,
|
|
26
|
+
reason: "Raw device overwrite is not allowed",
|
|
27
|
+
},
|
|
28
|
+
];
|
|
29
|
+
/** Canned destructive shell/SQL patterns on the `shell` tool's `command` argument. */
|
|
30
|
+
export const destructiveCommandsPack = {
|
|
31
|
+
id: "destructive-commands",
|
|
32
|
+
version: 1,
|
|
33
|
+
description: "Blocks destructive shell and SQL commands (recursive force delete, force push, drop table, device overwrite).",
|
|
34
|
+
build() {
|
|
35
|
+
return {
|
|
36
|
+
rules: DESTRUCTIVE_COMMANDS.map(({ id, pattern, reason }) => ({
|
|
37
|
+
id,
|
|
38
|
+
tool: "shell",
|
|
39
|
+
pattern,
|
|
40
|
+
argPath: "command",
|
|
41
|
+
reason,
|
|
42
|
+
})),
|
|
43
|
+
};
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
//# sourceMappingURL=destructive-commands.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Guardrail pack config/compile error (plan 092 Task 2). Config mistakes fail closed at compile time. */
|
|
2
|
+
export declare class GuardrailPackError extends Error {
|
|
3
|
+
readonly code = "ERR_PRISM_GUARDRAIL_PACK";
|
|
4
|
+
constructor(message: string, options?: {
|
|
5
|
+
readonly cause?: unknown;
|
|
6
|
+
});
|
|
7
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Guardrail pack config/compile error (plan 092 Task 2). Config mistakes fail closed at compile time. */
|
|
2
|
+
export class GuardrailPackError extends Error {
|
|
3
|
+
code = "ERR_PRISM_GUARDRAIL_PACK";
|
|
4
|
+
constructor(message, options) {
|
|
5
|
+
super(message, options);
|
|
6
|
+
this.name = "GuardrailPackError";
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Built-in guardrail pack registry (plan 092 Task 2). Definitions are pure data + pure factories. */
|
|
2
|
+
import { codingStandardPack } from "./coding-standard.js";
|
|
3
|
+
import { destructiveCommandsPack } from "./destructive-commands.js";
|
|
4
|
+
import { secretsHygienePack } from "./secrets-hygiene.js";
|
|
5
|
+
import { validationRespectPack } from "./validation-respect.js";
|
|
6
|
+
const DEFINITIONS = [
|
|
7
|
+
codingStandardPack,
|
|
8
|
+
destructiveCommandsPack,
|
|
9
|
+
validationRespectPack,
|
|
10
|
+
secretsHygienePack,
|
|
11
|
+
];
|
|
12
|
+
export const BUILT_IN_GUARDRAIL_PACKS = new Map(DEFINITIONS.map((definition) => [definition.id, definition]));
|
|
13
|
+
/** Built-in pack ids, in registry order. */
|
|
14
|
+
export const BUILT_IN_GUARDRAIL_PACK_IDS = DEFINITIONS.map((definition) => definition.id);
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Known credential shapes, all quantifier-bounded so a hostile argument string cannot blow up the regex.
|
|
3
|
+
* Prism redaction matches exact known values only (plan 092 Task 1), so these patterns ship with the pack.
|
|
4
|
+
*/
|
|
5
|
+
const SECRET_PATTERN = /(?:sk-[A-Za-z0-9]{16,}|gh[pousr]_[A-Za-z0-9]{20,}|AKIA[0-9A-Z]{16}|-----BEGIN [A-Z ]*PRIVATE KEY-----|eyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.|xox[baprs]-[A-Za-z0-9-]{10,})/;
|
|
6
|
+
/** Canned secret hygiene: any tool argument carrying credential-shaped material is denied. */
|
|
7
|
+
export const secretsHygienePack = {
|
|
8
|
+
id: "secrets-hygiene",
|
|
9
|
+
version: 1,
|
|
10
|
+
description: "Blocks tool calls whose arguments carry secret-shaped material (API keys, tokens, private keys).",
|
|
11
|
+
build() {
|
|
12
|
+
return {
|
|
13
|
+
rules: [
|
|
14
|
+
{
|
|
15
|
+
id: "no-secret-material-in-arguments",
|
|
16
|
+
pattern: SECRET_PATTERN,
|
|
17
|
+
reason: "Tool arguments contain secret-shaped material",
|
|
18
|
+
},
|
|
19
|
+
],
|
|
20
|
+
};
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=secrets-hygiene.js.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** Internal guardrail-pack definition types (plan 092 Task 2). Not SDK surface; hosts configure packs via `AgentSessionConfig.guardrailPacks`. */
|
|
2
|
+
import type { GuardrailRule, GuardrailRuleContext } from "../contracts-core/guardrail-packs.js";
|
|
3
|
+
import type { ToolResult } from "../contracts-protocol.js";
|
|
4
|
+
/** Plan 104 Task 2: pack-owned durable-state codec. The pack decides what a checkpoint carries. */
|
|
5
|
+
interface GuardrailPackStateCodec {
|
|
6
|
+
/** Serialize the live state for a checkpoint; `undefined` when nothing needs persisting. */
|
|
7
|
+
readonly snapshot: (state: Record<string, unknown>) => Readonly<Record<string, unknown>> | undefined;
|
|
8
|
+
/** Parse a persisted snapshot back into state fields; throw `GuardrailPackError` on a malformed value. */
|
|
9
|
+
readonly parse: (json: unknown) => Record<string, unknown>;
|
|
10
|
+
}
|
|
11
|
+
/** What a pack's `build` returns: restrictive rules plus an optional pure result observer. */
|
|
12
|
+
export interface GuardrailPackRules {
|
|
13
|
+
readonly rules: readonly GuardrailRule[];
|
|
14
|
+
/** Records tool results into pack-local state (never denies); a throw fails closed as a guardrail tripwire. */
|
|
15
|
+
readonly observe?: (state: Record<string, unknown>, result: ToolResult, context: GuardrailRuleContext) => void;
|
|
16
|
+
/** Optional codec making the pack's state survive a durable resume; a pack without one persists nothing. */
|
|
17
|
+
readonly state?: GuardrailPackStateCodec;
|
|
18
|
+
}
|
|
19
|
+
export interface GuardrailPackDefinition {
|
|
20
|
+
readonly id: string;
|
|
21
|
+
readonly version: number;
|
|
22
|
+
readonly description: string;
|
|
23
|
+
/** Pure factory: options in, rules out. No session access, no I/O. */
|
|
24
|
+
readonly build: (options: Readonly<Record<string, unknown>>) => GuardrailPackRules;
|
|
25
|
+
}
|
|
26
|
+
export {};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { GuardrailPackError } from "./errors.js";
|
|
2
|
+
const MUTATING_TOOLS = ["write", "edit", "delete", "move"];
|
|
3
|
+
/** Validation-style tool names. `shell` is opt-in (`validationTools`): a non-zero shell exit is a failure signal too. */
|
|
4
|
+
const DEFAULT_VALIDATION_TOOLS = ["test", "run_tests", "validate", "validation", "lint", "typecheck", "check"];
|
|
5
|
+
const MAX_VALIDATION_TOOLS = 16;
|
|
6
|
+
const MAX_VALIDATION_TOOL_CHARS = 128;
|
|
7
|
+
/** A tool result failed when it carries an error, or reported a non-zero `exitCode` (the shell tool's shape). */
|
|
8
|
+
function resultFailed(result) {
|
|
9
|
+
if (result.error !== undefined)
|
|
10
|
+
return true;
|
|
11
|
+
const value = result.value;
|
|
12
|
+
if (!value || typeof value !== "object" || !("exitCode" in value))
|
|
13
|
+
return false;
|
|
14
|
+
const exitCode = value.exitCode;
|
|
15
|
+
return typeof exitCode === "number" && exitCode !== 0;
|
|
16
|
+
}
|
|
17
|
+
function readValidationTools(value) {
|
|
18
|
+
if (value === undefined)
|
|
19
|
+
return DEFAULT_VALIDATION_TOOLS;
|
|
20
|
+
if (!Array.isArray(value) || value.length === 0 || value.length > MAX_VALIDATION_TOOLS) {
|
|
21
|
+
throw new GuardrailPackError(`validation-respect options.validationTools must be a non-empty string array (max ${MAX_VALIDATION_TOOLS})`);
|
|
22
|
+
}
|
|
23
|
+
return value.map((name) => {
|
|
24
|
+
if (typeof name !== "string" || !name.trim()) {
|
|
25
|
+
throw new GuardrailPackError("validation-respect options.validationTools entries must be non-empty strings");
|
|
26
|
+
}
|
|
27
|
+
return name;
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
/** Canned "respect failed validation": once a validation tool result fails, file mutations are denied until one passes. */
|
|
31
|
+
export const validationRespectPack = {
|
|
32
|
+
id: "validation-respect",
|
|
33
|
+
version: 1,
|
|
34
|
+
description: "Denies file mutations after a failed validation tool result until a later validation passes.",
|
|
35
|
+
build(options) {
|
|
36
|
+
const validationTools = readValidationTools(options.validationTools);
|
|
37
|
+
return {
|
|
38
|
+
observe(state, result, context) {
|
|
39
|
+
if (!validationTools.includes(context.toolName))
|
|
40
|
+
return;
|
|
41
|
+
state.validationFailed = resultFailed(result) ? context.toolName : undefined;
|
|
42
|
+
},
|
|
43
|
+
// Plan 104 Task 2: one tool name (or nothing) survives a resume, so a mutation the suspended
|
|
44
|
+
// run denied stays denied. The codec is the pack's own bound: 128 chars, never arguments.
|
|
45
|
+
state: {
|
|
46
|
+
snapshot: (state) => (typeof state.validationFailed === "string" ? { validationFailed: state.validationFailed } : undefined),
|
|
47
|
+
parse: (json) => {
|
|
48
|
+
const record = typeof json === "object" && json !== null ? json : {};
|
|
49
|
+
const failed = record.validationFailed;
|
|
50
|
+
if (failed === undefined)
|
|
51
|
+
return {};
|
|
52
|
+
if (typeof failed !== "string" || !failed.trim() || failed.length > MAX_VALIDATION_TOOL_CHARS) {
|
|
53
|
+
throw new GuardrailPackError(`validation-respect persisted state.validationFailed must be a non-empty string of at most ${MAX_VALIDATION_TOOL_CHARS} chars`);
|
|
54
|
+
}
|
|
55
|
+
return { validationFailed: failed };
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
rules: [
|
|
59
|
+
{
|
|
60
|
+
id: "no-mutation-after-failed-validation",
|
|
61
|
+
tool: MUTATING_TOOLS,
|
|
62
|
+
reason: "A previous validation result failed; fix it before mutating files",
|
|
63
|
+
deny: (_args, context) => context.state.validationFailed !== undefined,
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
};
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
//# sourceMappingURL=validation-respect.js.map
|
package/dist/guardrails.d.ts
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
|
-
import type { AgentEvent, GuardrailContext, GuardrailRecord, GuardrailStage, Guardrails, GuardrailValue } from "./contracts.js";
|
|
1
|
+
import type { AgentEvent, GuardrailContext, GuardrailPackRef, GuardrailRecord, GuardrailRule, GuardrailStage, Guardrails, GuardrailValue } from "./contracts.js";
|
|
2
|
+
export { GuardrailPackError } from "./guardrail-packs/errors.js";
|
|
2
3
|
import type { SecretRedactor } from "./redaction.js";
|
|
3
4
|
export declare const MAX_GUARDRAIL_CONCURRENCY = 16;
|
|
5
|
+
/** Guardrail pack compile bounds (plan 092 Task 2). All ceilings are config-shape limits, not runtime budgets. */
|
|
6
|
+
export declare const MAX_GUARDRAIL_PACKS = 8;
|
|
7
|
+
export declare const MAX_GUARDRAIL_PACK_RULES = 64;
|
|
8
|
+
/**
|
|
9
|
+
* Plan 104 T4/T6: the bounded, redacted refusal line for a terminal record that came from a compiled
|
|
10
|
+
* pack rule — `<prefix> by guardrail rule pack:<pack>/<rule>`, plus the pack's own reason when it set
|
|
11
|
+
* one — or `undefined` for any other guardrail, so the caller keeps its own neutral text. Only the
|
|
12
|
+
* compiler writes the `pack`/`rule` metadata, so a host-written guardrail named `pack:…` is never
|
|
13
|
+
* presented as a pack rule. Reasons are redacted where the record is built, pack names are
|
|
14
|
+
* compiler-bounded to 128 bytes (the identity always survives the cap), and a long reason is
|
|
15
|
+
* truncated, so the same derivation serves the tool refusal and decision-time revalidation.
|
|
16
|
+
*/
|
|
17
|
+
export declare function guardrailRefusalText(record: GuardrailRecord, prefix?: string): string | undefined;
|
|
4
18
|
export declare class GuardrailError extends Error {
|
|
5
19
|
readonly code: string;
|
|
6
20
|
readonly record: GuardrailRecord;
|
|
@@ -23,3 +37,49 @@ export interface GuardrailRunResult {
|
|
|
23
37
|
/** Evaluate one typed stage. Default is declaration-order sequential; bounded parallel mode still reports declaration order. */
|
|
24
38
|
export declare function runGuardrails<S extends GuardrailStage>(options: RunGuardrailsOptions<S>): Promise<GuardrailRunResult>;
|
|
25
39
|
export declare function assertGuardrailsAllowed(result: GuardrailRunResult): void;
|
|
40
|
+
/** One `guardrail:<stage>` identity row of a compiled pack, for run-bundle fingerprints. */
|
|
41
|
+
export interface GuardrailPackRow {
|
|
42
|
+
readonly name: string;
|
|
43
|
+
readonly stage: "tool_input" | "tool_output";
|
|
44
|
+
readonly revision: string | null;
|
|
45
|
+
}
|
|
46
|
+
/** Plan 104 Task 2: one replayable pack row of a durable checkpoint (`id`, resolved version, host options). */
|
|
47
|
+
interface GuardrailPackRefRow {
|
|
48
|
+
readonly id: string;
|
|
49
|
+
readonly version: number;
|
|
50
|
+
/** Host options the pack was compiled with, replayed verbatim on resume so enforcement is identical. */
|
|
51
|
+
readonly options?: Readonly<Record<string, unknown>>;
|
|
52
|
+
/**
|
|
53
|
+
* Plan 104 T3: the host's own rule list for an inline pack. Patterns are data and ride the
|
|
54
|
+
* checkpoint; a `deny` predicate or a `RegExp` pattern cannot round-trip and is refused at save.
|
|
55
|
+
*/
|
|
56
|
+
readonly rules?: readonly GuardrailRule[];
|
|
57
|
+
}
|
|
58
|
+
/** Plan 104 Task 2: a compile result that can round-trip through a durable checkpoint. */
|
|
59
|
+
interface CompiledGuardrailPacks {
|
|
60
|
+
readonly guardrails: Guardrails | undefined;
|
|
61
|
+
/** Rows a durable checkpoint replays; empty when no packs are configured. */
|
|
62
|
+
readonly packs: readonly GuardrailPackRefRow[];
|
|
63
|
+
/** Plan 104 T3: `ask` rules as the charge-time durable gate — a match records `interrupt`. */
|
|
64
|
+
readonly askGate?: Guardrails;
|
|
65
|
+
/** Plan 104 T3: the same rules as plain blocks, merged into a run that cannot suspend. */
|
|
66
|
+
readonly askBlocks?: Guardrails;
|
|
67
|
+
/** Pack-owned state snapshot (`{ <packId>: <pack state> }`); `undefined` when nothing needs persisting. */
|
|
68
|
+
readonly snapshotState: () => Record<string, Readonly<Record<string, unknown>>> | undefined;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Compiles `guardrailPacks` config onto the existing tool interception seams: one `tool_input`
|
|
72
|
+
* guardrail per rule (`name = pack:<pack>/<rule>`), plus one `tool_output` recorder for packs that
|
|
73
|
+
* observe results. Compiled once per session — patterns are compiled here, never per tool call.
|
|
74
|
+
* Throws `GuardrailPackError` on malformed config (fail closed); returns `undefined` when unset.
|
|
75
|
+
*/
|
|
76
|
+
export declare function compileGuardrailPacks(refs: readonly GuardrailPackRef[] | undefined, registry?: ReadonlyMap<string, import("./guardrail-packs/types.js").GuardrailPackDefinition>): Guardrails | undefined;
|
|
77
|
+
/**
|
|
78
|
+
* Plan 104 Task 2: the internal compile entry behind `compileGuardrailPacks`. Passing `initial`
|
|
79
|
+
* marks a durable restore — rows must then come from the installed registry, match its version, and
|
|
80
|
+
* parse through the pack's own state codec, so a mismatch fails closed instead of restoring a
|
|
81
|
+
* weaker policy. `snapshotState` is the checkpoint-side counterpart.
|
|
82
|
+
*/
|
|
83
|
+
export declare function compileGuardrailPacksWithState(refs: readonly GuardrailPackRef[] | undefined, registry?: ReadonlyMap<string, import("./guardrail-packs/types.js").GuardrailPackDefinition>, initial?: Readonly<Record<string, unknown>>): CompiledGuardrailPacks;
|
|
84
|
+
/** Stable identity rows for the same config `compileGuardrailPacks` accepts (no state, no guardrails built). */
|
|
85
|
+
export declare function describeGuardrailPacks(refs: readonly GuardrailPackRef[] | undefined, registry?: ReadonlyMap<string, import("./guardrail-packs/types.js").GuardrailPackDefinition>): readonly GuardrailPackRow[];
|