@arnilo/prism 0.0.6 → 0.0.7

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.
@@ -2,7 +2,7 @@ import type { AgentInput } from "./input.js";
2
2
  import type { ContributionRegistries } from "./contributions.js";
3
3
  import type { Middleware, MiddlewareHookName, MiddlewareRegistry } from "./middleware.js";
4
4
  import type { SecretRedactor } from "./redaction.js";
5
- import type { PermissionPolicy } from "./security.js";
5
+ import type { PermissionPolicy, TrustPolicy } from "./security.js";
6
6
  import type { ManifestContributionDeclaration } from "./manifests.js";
7
7
  import type { ToolValidator } from "./tools.js";
8
8
  import type { AudioContent, DocumentContent, FileContent } from "./content.js";
@@ -106,6 +106,83 @@ export interface Usage {
106
106
  readonly cost?: number;
107
107
  readonly currency?: string;
108
108
  }
109
+ export interface RunLimits {
110
+ readonly maxTurns?: number;
111
+ readonly maxProviderAttempts?: number;
112
+ readonly maxToolRounds?: number;
113
+ readonly maxToolCalls?: number;
114
+ readonly maxWallTimeMs?: number;
115
+ readonly maxRequestBytes?: number;
116
+ readonly maxResponseBytes?: number;
117
+ readonly maxInputTokens?: number;
118
+ readonly maxOutputTokens?: number;
119
+ readonly maxTotalTokens?: number;
120
+ readonly maxCost?: {
121
+ readonly amount: number;
122
+ readonly currency: string;
123
+ };
124
+ }
125
+ export type RunLimitName = keyof Required<RunLimits>;
126
+ export interface RunLimitCounters {
127
+ readonly turns: number;
128
+ readonly providerAttempts: number;
129
+ readonly toolRounds: number;
130
+ readonly toolCalls: number;
131
+ readonly wallTimeMs: number;
132
+ readonly requestBytes: number;
133
+ readonly responseBytes: number;
134
+ readonly inputTokens: number;
135
+ readonly outputTokens: number;
136
+ readonly totalTokens: number;
137
+ readonly cost: number;
138
+ }
139
+ export interface RunLimitBreach {
140
+ readonly limit: RunLimitName;
141
+ readonly maximum: number;
142
+ readonly observed: number;
143
+ readonly currency?: string;
144
+ }
145
+ export type GuardrailStage = "input" | "output" | "tool_input" | "tool_output";
146
+ export type GuardrailAction = "allow" | "block" | "tripwire" | "interrupt";
147
+ export type GuardrailValue<S extends GuardrailStage> = S extends "input" ? readonly Message[] : S extends "output" ? ProviderTurnResult : S extends "tool_input" ? ToolCallContent : ToolResult;
148
+ export interface GuardrailContext<S extends GuardrailStage> {
149
+ readonly stage: S;
150
+ readonly value: GuardrailValue<S>;
151
+ readonly sessionId: string;
152
+ readonly runId: string;
153
+ readonly toolCallId?: string;
154
+ readonly toolName?: string;
155
+ readonly metadata: Readonly<Record<string, unknown>>;
156
+ readonly signal: AbortSignal;
157
+ }
158
+ export interface GuardrailDecision {
159
+ readonly action: GuardrailAction;
160
+ readonly reason?: string;
161
+ /** Public data only; Prism JSON-normalizes, bounds, and redacts it before emission. */
162
+ readonly metadata?: Readonly<Record<string, unknown>>;
163
+ }
164
+ export interface Guardrail<S extends GuardrailStage = GuardrailStage> {
165
+ readonly name: string;
166
+ readonly stage: S;
167
+ /** Host-authored stable identity for durable definitions; unused by ordinary runs. */
168
+ readonly revision?: string;
169
+ evaluate(context: GuardrailContext<S>): GuardrailDecision | Promise<GuardrailDecision>;
170
+ }
171
+ export interface GuardrailRecord {
172
+ readonly guardrail: string;
173
+ readonly stage: GuardrailStage;
174
+ readonly action: GuardrailAction;
175
+ readonly reason?: string;
176
+ readonly metadata?: Readonly<Record<string, unknown>>;
177
+ }
178
+ export interface Guardrails {
179
+ readonly input?: readonly Guardrail<"input">[];
180
+ readonly output?: readonly Guardrail<"output">[];
181
+ readonly toolInput?: readonly Guardrail<"tool_input">[];
182
+ readonly toolOutput?: readonly Guardrail<"tool_output">[];
183
+ /** Defaults to sequential; at most 16 stage evaluations run at once. */
184
+ readonly maxConcurrency?: number;
185
+ }
109
186
  export type CacheRetention = "none" | "short" | "long";
110
187
  export type PromptCacheKind = "implicit" | "openai_key" | "cache_control" | "provider_specific" | "none";
111
188
  export interface ModelCacheCapabilities {
@@ -195,7 +272,10 @@ export interface RunOptions {
195
272
  readonly signal?: AbortSignal;
196
273
  readonly model?: ModelConfig;
197
274
  readonly providerSource?: ProviderResolver;
275
+ /** @deprecated Use `limits.maxToolRounds`. */
198
276
  readonly maxToolRounds?: number;
277
+ /** Run-scoped ceilings. When an agent config also sets limits, these can only narrow it. */
278
+ readonly limits?: RunLimits;
199
279
  readonly providerOptions?: ProviderRequestOptions;
200
280
  readonly providerRequestPolicies?: ProviderRequestPolicy | readonly ProviderRequestPolicy[];
201
281
  readonly systemPrompt?: SystemPromptConfig;
@@ -212,6 +292,10 @@ export interface RunOptions {
212
292
  readonly instructionInjectors?: readonly InstructionInjector[];
213
293
  readonly inputLayout?: InputAssemblyLayout;
214
294
  readonly loop?: AgentLoopStrategy | AgentLoopOptions;
295
+ /** Appended to agent-level guardrails for this run. */
296
+ readonly guardrails?: Guardrails;
297
+ /** Opt-in durable interruption/checkpointing. */
298
+ readonly runState?: AgentRunStateOptions;
215
299
  }
216
300
  export interface AgentDefinition {
217
301
  readonly name: string;
@@ -258,6 +342,8 @@ export interface AgentConfig {
258
342
  readonly resourceLoader?: ResourceLoader;
259
343
  readonly store?: SessionStore;
260
344
  readonly permission?: PermissionPolicy;
345
+ /** Optional trust check for tool and resource targets. */
346
+ readonly trust?: TrustPolicy;
261
347
  readonly providerOptions?: ProviderRequestOptions;
262
348
  readonly providerRequestPolicies?: ProviderRequestPolicy | readonly ProviderRequestPolicy[];
263
349
  readonly systemPrompt?: SystemPromptConfig;
@@ -267,11 +353,31 @@ export interface AgentConfig {
267
353
  readonly idempotencyKey?: string;
268
354
  readonly compaction?: false | CompactionOptions;
269
355
  readonly retry?: false | RetryOptions;
356
+ /** Agent-wide ceilings; per-run limits may only narrow these values. */
357
+ readonly limits?: RunLimits;
270
358
  readonly metadata?: Readonly<Record<string, unknown>>;
271
359
  readonly validator?: ToolValidator;
272
360
  readonly instructionInjectors?: readonly InstructionInjector[];
273
361
  readonly inputLayout?: InputAssemblyLayout;
274
362
  readonly loop?: AgentLoopStrategy | AgentLoopOptions;
363
+ readonly guardrails?: Guardrails;
364
+ /** Opt-in durable interruption/checkpointing default for this agent. */
365
+ readonly runState?: AgentRunStateOptions;
366
+ /** Internal marker set by createSecureAgent(); makes security defaults immutable per run. */
367
+ readonly secure?: true;
368
+ }
369
+ /** Opt-in fail-closed composition over the normal explicit AgentConfig API. */
370
+ export interface SecureAgentOptions extends Omit<AgentConfig, "tools" | "validator" | "redactor" | "permission" | "trust" | "ownership" | "limits" | "runState" | "secure"> {
371
+ readonly id: string;
372
+ readonly tools: readonly ToolDefinition[];
373
+ readonly toolArgumentValidator: import("./tools.js").ToolArgumentValidator;
374
+ readonly redactor: SecretRedactor;
375
+ readonly permission: PermissionPolicy;
376
+ readonly trust: TrustPolicy;
377
+ readonly ownership: OwnershipScope;
378
+ readonly limits: RunLimits;
379
+ readonly definitionRevision: string;
380
+ readonly runState: Omit<AgentRunStateOptions, "definitionRevision" | "interruptBeforeTool">;
275
381
  }
276
382
  export interface Agent {
277
383
  readonly config: AgentConfig;
@@ -298,7 +404,61 @@ export interface SubscribeOptions {
298
404
  /** What to do when `maxQueuedEvents` is reached. Defaults to `close`. */
299
405
  readonly overflow?: SubscriberOverflowPolicy;
300
406
  }
301
- export type AgentRunStatus = "succeeded" | "failed" | "aborted";
407
+ export type AgentRunStatus = "succeeded" | "failed" | "aborted" | "suspended" | "denied";
408
+ export type AgentRunInterruptionKind = "input_guardrail" | "tool_approval";
409
+ /** Redacted safe-boundary descriptor; never contains tool arguments. */
410
+ export interface AgentRunInterruption {
411
+ readonly kind: AgentRunInterruptionKind;
412
+ readonly reason: string;
413
+ readonly toolCallId?: string;
414
+ readonly toolName?: string;
415
+ }
416
+ export interface AgentRunStateOptions {
417
+ readonly checkpoints: CheckpointStore;
418
+ /** Host-authored immutable revision required for durable runs. */
419
+ readonly definitionRevision: string;
420
+ /** Suspend every tool call before its side effect. */
421
+ readonly interruptBeforeTool?: boolean;
422
+ readonly maxStateBytes?: number;
423
+ readonly fencingToken?: number;
424
+ }
425
+ /** Versioned, redacted checkpoint payload. Treat as opaque except status/version/interruption. */
426
+ export interface AgentRunState {
427
+ readonly schemaVersion: 1;
428
+ readonly agentId: string;
429
+ readonly definitionRevision: string;
430
+ readonly fingerprint: string;
431
+ readonly runId: string;
432
+ readonly sessionId: string;
433
+ readonly leafId?: string;
434
+ readonly model: ModelConfig;
435
+ readonly status: AgentRunStatus | "running";
436
+ readonly interruption?: AgentRunInterruption;
437
+ readonly version?: number;
438
+ }
439
+ export interface AgentRunResume {
440
+ readonly decision: "approve" | "deny";
441
+ readonly expectedVersion: number;
442
+ }
443
+ export interface AgentRunResumeOptions {
444
+ readonly checkpoints: CheckpointStore;
445
+ /** Current host-authored revision; must exactly match the checkpoint. */
446
+ readonly definitionRevision: string;
447
+ readonly ownership?: OwnershipScope;
448
+ readonly fencingToken?: number;
449
+ }
450
+ export interface AgentRunRef {
451
+ readonly runId: string;
452
+ readonly sessionId?: string;
453
+ }
454
+ export interface AgentRunStatusResult {
455
+ readonly state: AgentRunState;
456
+ readonly version: number;
457
+ }
458
+ export declare class AgentRunStateError extends Error {
459
+ readonly code = "ERR_PRISM_AGENT_RUN_STATE";
460
+ constructor(message: string);
461
+ }
302
462
  /** Terminal result of `session.run()` / `session.prompt()`. Failed and aborted runs throw {@link AgentRunError} with this shape attached. */
303
463
  export interface AgentRunResult {
304
464
  readonly sessionId: string;
@@ -314,10 +474,16 @@ export interface AgentRunResult {
314
474
  readonly message?: Message;
315
475
  /** Aggregate usage across provider turns (`run_total` scope). */
316
476
  readonly usage?: Usage;
477
+ /** Present when the run hit a configured resource ceiling. */
478
+ readonly limit?: RunLimitBreach;
317
479
  /** Present when `status` is `"failed"` or when a failed attempt still produced partial output. */
318
480
  readonly error?: ErrorInfo;
319
481
  /** String form of the abort reason when `status` is `"aborted"`. */
320
482
  readonly abortReason?: string;
483
+ /** Present for durable suspended/terminal runs. Payload is redacted and bounded. */
484
+ readonly runState?: AgentRunState;
485
+ /** Present only while awaiting an operator decision. */
486
+ readonly interruption?: AgentRunInterruption;
321
487
  }
322
488
  export declare class AgentRunError extends Error {
323
489
  readonly result: AgentRunResult;
@@ -365,6 +531,23 @@ export type AgentEvent = {
365
531
  readonly sessionId: string;
366
532
  readonly runId: string;
367
533
  readonly usage?: Usage;
534
+ } | {
535
+ readonly type: "agent_suspended";
536
+ readonly sessionId: string;
537
+ readonly runId: string;
538
+ readonly interruption: AgentRunInterruption;
539
+ readonly version: number;
540
+ } | {
541
+ readonly type: "agent_resumed";
542
+ readonly sessionId: string;
543
+ readonly runId: string;
544
+ readonly version: number;
545
+ } | {
546
+ readonly type: "agent_denied";
547
+ readonly sessionId: string;
548
+ readonly runId: string;
549
+ readonly interruption: AgentRunInterruption;
550
+ readonly version: number;
368
551
  } | {
369
552
  readonly type: "turn_started";
370
553
  readonly sessionId: string;
@@ -439,6 +622,18 @@ export type AgentEvent = {
439
622
  readonly reason: string;
440
623
  readonly error: ErrorInfo;
441
624
  readonly metadata: ToolExecutionMetadata;
625
+ } | {
626
+ readonly type: "guardrail_decision";
627
+ readonly sessionId: string;
628
+ readonly runId: string;
629
+ readonly toolCallId?: string;
630
+ readonly toolName?: string;
631
+ readonly record: GuardrailRecord;
632
+ } | {
633
+ readonly type: "run_limit_exceeded";
634
+ readonly sessionId: string;
635
+ readonly runId: string;
636
+ readonly breach: RunLimitBreach;
442
637
  } | {
443
638
  readonly type: "queue_updated";
444
639
  readonly sessionId: string;
@@ -617,6 +812,8 @@ export interface InputBuildContext {
617
812
  readonly runId?: string;
618
813
  readonly metadata?: Readonly<Record<string, unknown>>;
619
814
  readonly signal?: AbortSignal;
815
+ readonly permission?: PermissionPolicy;
816
+ readonly trust?: TrustPolicy;
620
817
  }
621
818
  export interface PromptBuilder {
622
819
  readonly name: string;
@@ -1006,7 +1203,7 @@ export interface BranchRecord {
1006
1203
  readonly createdAt: string;
1007
1204
  readonly metadata?: Readonly<Record<string, unknown>>;
1008
1205
  }
1009
- export type RunStatus = "queued" | "running" | "succeeded" | "failed" | "aborted";
1206
+ export type RunStatus = "queued" | "running" | "suspended" | "denied" | "succeeded" | "failed" | "aborted";
1010
1207
  /** Stored run record. */
1011
1208
  export interface RunRecord extends OwnershipScope {
1012
1209
  readonly id: string;
@@ -1377,6 +1574,7 @@ export interface ResourceLoadContext {
1377
1574
  readonly signal?: AbortSignal;
1378
1575
  readonly metadata?: Readonly<Record<string, unknown>>;
1379
1576
  readonly permission?: PermissionPolicy;
1577
+ readonly trust?: TrustPolicy;
1380
1578
  }
1381
1579
  export interface SettingsProvider {
1382
1580
  get<T = unknown>(key: string): Promise<T | undefined> | T | undefined;
@@ -1420,6 +1618,8 @@ export interface LoopContext {
1420
1618
  /** Maximum independent tool calls dispatched concurrently per provider turn. Default `1`. */
1421
1619
  readonly toolConcurrency: number;
1422
1620
  assemble(nextInput: AgentInput, toolResults?: readonly ToolResult[], turn?: number): Promise<ProviderRequest>;
1621
+ /** Charges a complete tool round before any call in it can start. */
1622
+ chargeToolRound?(calls: readonly ToolCallContent[]): void;
1423
1623
  generate(request: ProviderRequest): Promise<ProviderTurnResult>;
1424
1624
  dispatchToolCall(call: ToolCallContent): Promise<ToolResult>;
1425
1625
  isToolCallExclusive?(call: ToolCallContent): boolean;
package/dist/contracts.js CHANGED
@@ -1,3 +1,7 @@
1
+ export class AgentRunStateError extends Error {
2
+ code = "ERR_PRISM_AGENT_RUN_STATE";
3
+ constructor(message) { super(message); this.name = "AgentRunStateError"; }
4
+ }
1
5
  export class AgentRunError extends Error {
2
6
  result;
3
7
  constructor(result, options) {
@@ -0,0 +1,25 @@
1
+ import type { AgentEvent, GuardrailContext, GuardrailRecord, Guardrails, GuardrailStage, GuardrailValue } from "./contracts.js";
2
+ import type { SecretRedactor } from "./redaction.js";
3
+ export declare const MAX_GUARDRAIL_CONCURRENCY = 16;
4
+ export declare class GuardrailError extends Error {
5
+ readonly code: string;
6
+ readonly record: GuardrailRecord;
7
+ constructor(record: GuardrailRecord);
8
+ }
9
+ export interface RunGuardrailsOptions<S extends GuardrailStage> {
10
+ readonly stage: S;
11
+ readonly guardrails?: Guardrails;
12
+ readonly value: GuardrailValue<S>;
13
+ readonly context: Omit<GuardrailContext<S>, "stage" | "value" | "signal"> & {
14
+ readonly signal?: AbortSignal;
15
+ };
16
+ readonly redactor?: SecretRedactor;
17
+ readonly emit?: (event: AgentEvent) => void | Promise<void>;
18
+ }
19
+ export interface GuardrailRunResult {
20
+ readonly records: readonly GuardrailRecord[];
21
+ readonly terminal?: GuardrailRecord;
22
+ }
23
+ /** Evaluate one typed stage. Default is declaration-order sequential; bounded parallel mode still reports declaration order. */
24
+ export declare function runGuardrails<S extends GuardrailStage>(options: RunGuardrailsOptions<S>): Promise<GuardrailRunResult>;
25
+ export declare function assertGuardrailsAllowed(result: GuardrailRunResult): void;
@@ -0,0 +1,133 @@
1
+ export const MAX_GUARDRAIL_CONCURRENCY = 16;
2
+ const MAX_REASON_BYTES = 4 * 1024;
3
+ const MAX_METADATA_BYTES = 16 * 1024;
4
+ export class GuardrailError extends Error {
5
+ code;
6
+ record;
7
+ constructor(record) {
8
+ super(record.action === "interrupt" ? "Guardrail interruption is unavailable" : "Guardrail blocked run");
9
+ this.name = "GuardrailError";
10
+ this.code = record.action === "interrupt"
11
+ ? "ERR_PRISM_GUARDRAIL_INTERRUPT_UNAVAILABLE"
12
+ : "ERR_PRISM_GUARDRAIL_BLOCKED";
13
+ this.record = record;
14
+ }
15
+ }
16
+ /** Evaluate one typed stage. Default is declaration-order sequential; bounded parallel mode still reports declaration order. */
17
+ export async function runGuardrails(options) {
18
+ const guards = stageGuards(options.guardrails, options.stage);
19
+ if (guards.length === 0)
20
+ return { records: [] };
21
+ const maxConcurrency = resolveConcurrency(options.guardrails?.maxConcurrency);
22
+ const controller = new AbortController();
23
+ const signal = options.context.signal
24
+ ? AbortSignal.any([options.context.signal, controller.signal])
25
+ : controller.signal;
26
+ const records = new Array(guards.length);
27
+ let next = 0;
28
+ let stopped = false;
29
+ const worker = async () => {
30
+ for (;;) {
31
+ if (stopped)
32
+ return;
33
+ const index = next++;
34
+ if (index >= guards.length)
35
+ return;
36
+ const record = await evaluate(guards[index], options, signal);
37
+ // A sibling may have reached a terminal decision while this callback was settling.
38
+ if (stopped)
39
+ return;
40
+ records[index] = record;
41
+ if (record.action !== "allow") {
42
+ stopped = true;
43
+ controller.abort(new GuardrailError(record));
44
+ }
45
+ }
46
+ };
47
+ await Promise.all(Array.from({ length: Math.min(maxConcurrency, guards.length) }, worker));
48
+ const normalized = records.filter((record) => record !== undefined);
49
+ for (const record of normalized) {
50
+ await options.emit?.({
51
+ type: "guardrail_decision",
52
+ sessionId: options.context.sessionId,
53
+ runId: options.context.runId,
54
+ toolCallId: options.context.toolCallId,
55
+ toolName: options.context.toolName,
56
+ record,
57
+ });
58
+ }
59
+ return { records: normalized, terminal: normalized.find((record) => record.action !== "allow") };
60
+ }
61
+ export function assertGuardrailsAllowed(result) {
62
+ if (result.terminal)
63
+ throw new GuardrailError(result.terminal);
64
+ }
65
+ function stageGuards(guardrails, stage) {
66
+ if (!guardrails)
67
+ return [];
68
+ switch (stage) {
69
+ case "input": return (guardrails.input ?? []);
70
+ case "output": return (guardrails.output ?? []);
71
+ case "tool_input": return (guardrails.toolInput ?? []);
72
+ case "tool_output": return (guardrails.toolOutput ?? []);
73
+ }
74
+ }
75
+ async function evaluate(guardrail, options, signal) {
76
+ if (!guardrail || typeof guardrail.name !== "string" || !guardrail.name || guardrail.name.length > 128 || guardrail.stage !== options.stage || typeof guardrail.evaluate !== "function") {
77
+ return record(guardrail?.name ?? "invalid", options.stage, "tripwire", "guardrail_invalid", undefined, options.redactor);
78
+ }
79
+ try {
80
+ const decision = await guardrail.evaluate({ ...options.context, stage: options.stage, value: options.value, signal });
81
+ if (!decision || !isAction(decision.action)) {
82
+ return record(guardrail.name, options.stage, "tripwire", "guardrail_invalid_decision", undefined, options.redactor);
83
+ }
84
+ return record(guardrail.name, options.stage, decision.action, decision.reason, decision.metadata, options.redactor);
85
+ }
86
+ catch {
87
+ return record(guardrail.name, options.stage, "tripwire", "guardrail_failed", undefined, options.redactor);
88
+ }
89
+ }
90
+ function resolveConcurrency(value) {
91
+ if (value === undefined)
92
+ return 1;
93
+ if (!Number.isSafeInteger(value) || value < 1 || value > MAX_GUARDRAIL_CONCURRENCY) {
94
+ throw new Error(`Guardrail maxConcurrency must be a safe integer from 1 to ${MAX_GUARDRAIL_CONCURRENCY}`);
95
+ }
96
+ return value;
97
+ }
98
+ function isAction(value) {
99
+ return value === "allow" || value === "block" || value === "tripwire" || value === "interrupt";
100
+ }
101
+ function record(guardrail, stage, action, reason, metadata, redactor) {
102
+ return {
103
+ guardrail: boundText(guardrail, 128) || "invalid",
104
+ stage,
105
+ action,
106
+ reason: typeof reason === "string" ? boundText(redactor?.redact(reason) ?? reason, MAX_REASON_BYTES) : undefined,
107
+ metadata: boundedMetadata(metadata, redactor),
108
+ };
109
+ }
110
+ function boundedMetadata(value, redactor) {
111
+ if (!value || typeof value !== "object" || Array.isArray(value))
112
+ return undefined;
113
+ try {
114
+ const json = JSON.stringify(redactor?.redact(value) ?? value);
115
+ if (!json || byteLength(json) > MAX_METADATA_BYTES)
116
+ return { truncated: true };
117
+ const parsed = JSON.parse(json);
118
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed)
119
+ ? parsed
120
+ : undefined;
121
+ }
122
+ catch {
123
+ return { invalid: true };
124
+ }
125
+ }
126
+ function boundText(value, limit) {
127
+ const bytes = new TextEncoder().encode(value);
128
+ return bytes.length <= limit ? value : new TextDecoder().decode(bytes.subarray(0, limit));
129
+ }
130
+ function byteLength(value) {
131
+ return new TextEncoder().encode(value).length;
132
+ }
133
+ //# sourceMappingURL=guardrails.js.map
package/dist/index.d.ts CHANGED
@@ -1,9 +1,15 @@
1
1
  export type * from "./contracts.js";
2
- export { isSessionEntryKind, SESSION_APPEND_CONFLICT_CODE, SESSION_ENTRY_KINDS, SESSION_ENTRY_SCHEMA_VERSION, SessionAppendConflictError, isSessionAppendConflict, AgentRunError } from "./contracts.js";
3
- export { createAgent, createAgentSession } from "./agents.js";
2
+ export type { RunLimitCounters, RunLimitName, SecureAgentOptions } from "./contracts.js";
3
+ export { isSessionEntryKind, SESSION_APPEND_CONFLICT_CODE, SESSION_ENTRY_KINDS, SESSION_ENTRY_SCHEMA_VERSION, SessionAppendConflictError, isSessionAppendConflict, AgentRunError, AgentRunStateError } from "./contracts.js";
4
+ export { createAgent, createAgentSession, resumeAgentRun } from "./agents.js";
5
+ export { createSecureAgent } from "./secure-agent.js";
4
6
  export { createMemoryRunFeedbackStore, prepareRunFeedback, requireRunFeedbackOwnership, runFeedbackPageLimit, RunFeedbackError, } from "./feedback.js";
5
7
  export type { MemoryRunFeedbackStoreOptions, PrepareRunFeedbackOptions, RunFeedbackLimits, RunFeedbackRun, RunFeedbackRunResolver, } from "./feedback.js";
6
8
  export { CHECKPOINT_CONFLICT_CODE, CheckpointConflictError, createMemoryCheckpointStore } from "./checkpoints.js";
9
+ export { AGENT_RUN_STATE_NAMESPACE, AGENT_RUN_STATE_SCHEMA_VERSION, DEFAULT_MAX_AGENT_RUN_STATE_BYTES, HARD_MAX_AGENT_RUN_STATE_BYTES, agentFingerprint, loadAgentRunState } from "./agent-run-state.js";
10
+ export type { StoredAgentRunState } from "./agent-run-state.js";
11
+ export { createAgentRunLifecycle } from "./agent-run-lifecycle.js";
12
+ export type { AgentRunLifecycle, AgentRunLifecycleAgent, AgentRunLifecycleOptions, AgentRunLifecycleRequest } from "./agent-run-lifecycle.js";
7
13
  export type { MemoryCheckpointStoreOptions } from "./checkpoints.js";
8
14
  export { LEASE_CONFLICT_CODE, LeaseConflictError, createMemoryLeaseStore } from "./leases.js";
9
15
  export { createEventMultiplexer } from "./event-multiplexer.js";
@@ -67,9 +73,13 @@ export type { ResolveActiveSkillsOptions, SkillRegistryOptions } from "./skills.
67
73
  export { resolveInstructionInjectors, runInstructionInjectors } from "./instruction-injection.js";
68
74
  export type { ResolveInstructionInjectorsOptions } from "./instruction-injection.js";
69
75
  export { createToolRegistry, dispatchToolCall, filterTools, createToolParameterValidator } from "./tools.js";
76
+ export { assertGuardrailsAllowed, GuardrailError, MAX_GUARDRAIL_CONCURRENCY, runGuardrails } from "./guardrails.js";
77
+ export { createRunLimitTracker, DEFAULT_RUN_LIMITS, HARD_MAX_RUN_COST, HARD_RUN_LIMITS, RunLimitError, RunLimitTracker, resolveRunLimits } from "./run-limits.js";
78
+ export type { GuardrailRunResult, RunGuardrailsOptions, } from "./guardrails.js";
79
+ export type { RunLimitTrackerOptions, } from "./run-limits.js";
70
80
  export type { DispatchToolCallOptions, ToolArgumentValidationError, ToolArgumentValidationResult, ToolArgumentValidator, ToolFilter, ToolFilterInput, ToolParameterValidatorOptions, ToolRegistryOptions, ToolValidator, } from "./tools.js";
71
81
  export type { DuplicateRegistrationOptions, DuplicateRegistrationPolicy } from "./registry-options.js";
72
82
  export { dispatchToolCallsInOrder, generateValidateReviseLoop, isAgentLoopOptions, resolveLoop, resolveToolConcurrency, singleShotLoop } from "./agent-loops.js";
73
83
  export declare const name = "prism";
74
- export declare const version = "0.0.6";
84
+ export declare const version = "0.0.7";
75
85
  export declare const description = "Agent harness for AI providers, agents, sessions, and tools.";
package/dist/index.js CHANGED
@@ -1,7 +1,10 @@
1
- export { isSessionEntryKind, SESSION_APPEND_CONFLICT_CODE, SESSION_ENTRY_KINDS, SESSION_ENTRY_SCHEMA_VERSION, SessionAppendConflictError, isSessionAppendConflict, AgentRunError } from "./contracts.js";
2
- export { createAgent, createAgentSession } from "./agents.js";
1
+ export { isSessionEntryKind, SESSION_APPEND_CONFLICT_CODE, SESSION_ENTRY_KINDS, SESSION_ENTRY_SCHEMA_VERSION, SessionAppendConflictError, isSessionAppendConflict, AgentRunError, AgentRunStateError } from "./contracts.js";
2
+ export { createAgent, createAgentSession, resumeAgentRun } from "./agents.js";
3
+ export { createSecureAgent } from "./secure-agent.js";
3
4
  export { createMemoryRunFeedbackStore, prepareRunFeedback, requireRunFeedbackOwnership, runFeedbackPageLimit, RunFeedbackError, } from "./feedback.js";
4
5
  export { CHECKPOINT_CONFLICT_CODE, CheckpointConflictError, createMemoryCheckpointStore } from "./checkpoints.js";
6
+ export { AGENT_RUN_STATE_NAMESPACE, AGENT_RUN_STATE_SCHEMA_VERSION, DEFAULT_MAX_AGENT_RUN_STATE_BYTES, HARD_MAX_AGENT_RUN_STATE_BYTES, agentFingerprint, loadAgentRunState } from "./agent-run-state.js";
7
+ export { createAgentRunLifecycle } from "./agent-run-lifecycle.js";
5
8
  export { LEASE_CONFLICT_CODE, LeaseConflictError, createMemoryLeaseStore } from "./leases.js";
6
9
  export { createEventMultiplexer } from "./event-multiplexer.js";
7
10
  export { applyCacheControl, cacheHitRate, cacheSavings, cacheUsageReport, mapCacheRetention, sanitizeCacheKey } from "./cache-helpers.js";
@@ -37,8 +40,10 @@ export { applyExecutionDecision, assertExecutionAllowed, checkExecution, Executi
37
40
  export { createSkillRegistry, resolveActiveSkills } from "./skills.js";
38
41
  export { resolveInstructionInjectors, runInstructionInjectors } from "./instruction-injection.js";
39
42
  export { createToolRegistry, dispatchToolCall, filterTools, createToolParameterValidator } from "./tools.js";
43
+ export { assertGuardrailsAllowed, GuardrailError, MAX_GUARDRAIL_CONCURRENCY, runGuardrails } from "./guardrails.js";
44
+ export { createRunLimitTracker, DEFAULT_RUN_LIMITS, HARD_MAX_RUN_COST, HARD_RUN_LIMITS, RunLimitError, RunLimitTracker, resolveRunLimits } from "./run-limits.js";
40
45
  export { dispatchToolCallsInOrder, generateValidateReviseLoop, isAgentLoopOptions, resolveLoop, resolveToolConcurrency, singleShotLoop } from "./agent-loops.js";
41
46
  export const name = "prism";
42
- export const version = "0.0.6";
47
+ export const version = "0.0.7";
43
48
  export const description = "Agent harness for AI providers, agents, sessions, and tools.";
44
49
  //# sourceMappingURL=index.js.map
package/dist/input.js CHANGED
@@ -189,6 +189,8 @@ async function resourceMessage(uri, context, attachment) {
189
189
  const text = await loadTextResource(context.resourceLoader, uri, {
190
190
  signal: context.signal,
191
191
  metadata: context.metadata,
192
+ permission: context.permission,
193
+ trust: context.trust,
192
194
  });
193
195
  const label = attachment?.name ?? uri;
194
196
  return textMessage("user", `Resource ${label}:\n${text}`, attachmentMetadata({ ...attachment, uri }));
package/dist/resources.js CHANGED
@@ -1,8 +1,9 @@
1
1
  import { parsePrismManifest } from "./manifests.js";
2
2
  import { assertJsonObject } from "./config.js";
3
3
  import { DEFAULT_MAX_MEDIA_ITEM_BYTES, loadBoundedBinaryResource, } from "./content.js";
4
- import { assertPermission } from "./security.js";
4
+ import { assertPermission, assertTrusted } from "./security.js";
5
5
  export async function loadTextResource(loader, uri, context) {
6
+ await assertTrusted(context?.trust, { kind: "resource", target: uri, capability: "load", metadata: context?.metadata });
6
7
  await assertPermission(context?.permission, { kind: "resource", action: "load", target: uri, metadata: context?.metadata });
7
8
  const resource = await loader.load(uri, context);
8
9
  if (resource.text !== undefined)
@@ -0,0 +1,34 @@
1
+ import type { RunLimitBreach, RunLimitCounters, RunLimitName, RunLimits, Usage } from "./contracts.js";
2
+ export declare const DEFAULT_RUN_LIMITS: Required<Omit<RunLimits, "maxCost">>;
3
+ export declare const HARD_MAX_RUN_COST = 10000;
4
+ export declare const HARD_RUN_LIMITS: Required<Omit<RunLimits, "maxCost">>;
5
+ export declare class RunLimitError extends Error {
6
+ readonly breach: RunLimitBreach;
7
+ readonly code = "ERR_PRISM_RUN_LIMIT";
8
+ constructor(breach: RunLimitBreach);
9
+ }
10
+ export interface RunLimitTrackerOptions {
11
+ readonly onExceeded?: (breach: RunLimitBreach) => void;
12
+ /** Durable resumption restores cumulative counters and original wall deadline. */
13
+ readonly snapshot?: RunLimitCounters;
14
+ readonly deadlineAt?: string;
15
+ }
16
+ /** Validate one host-authored layer. Defaults are applied only after inheritance is resolved. */
17
+ export declare function resolveRunLimits(agent?: RunLimits, run?: RunLimits): Readonly<Required<Omit<RunLimits, "maxCost">> & Pick<RunLimits, "maxCost">>;
18
+ export declare class RunLimitTracker {
19
+ private readonly options;
20
+ readonly limits: Readonly<Required<Omit<RunLimits, "maxCost">> & Pick<RunLimits, "maxCost">>;
21
+ private readonly startedAt;
22
+ readonly deadlineAt: string;
23
+ private readonly counters;
24
+ private timer?;
25
+ private exceeded?;
26
+ constructor(limits: Readonly<Required<Omit<RunLimits, "maxCost">> & Pick<RunLimits, "maxCost">>, options?: RunLimitTrackerOptions);
27
+ get breach(): RunLimitBreach | undefined;
28
+ snapshot(): RunLimitCounters;
29
+ dispose(): void;
30
+ charge(limit: Exclude<RunLimitName, "maxCost">, delta?: number): void;
31
+ recordUsage(usage: Usage | undefined): void;
32
+ private exceed;
33
+ }
34
+ export declare function createRunLimitTracker(limits: RunLimits | undefined, options?: RunLimitTrackerOptions): RunLimitTracker;