@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.
Files changed (90) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/agent-definitions.js +2 -3
  3. package/dist/agent-loops.js +12 -7
  4. package/dist/agent-run-lifecycle.d.ts +1 -2
  5. package/dist/agent-run-lifecycle.js +1 -1
  6. package/dist/agent-run-state.js +16 -3
  7. package/dist/agents.d.ts +1 -1
  8. package/dist/agents.js +121 -51
  9. package/dist/cache-helpers.js +18 -9
  10. package/dist/checkpoints.js +5 -9
  11. package/dist/cli-init.js +3 -7
  12. package/dist/cli-runner.d.ts +1 -1
  13. package/dist/cli-runner.js +74 -13
  14. package/dist/compaction.js +5 -4
  15. package/dist/config.js +7 -4
  16. package/dist/content.js +26 -24
  17. package/dist/context-budget.js +12 -8
  18. package/dist/contracts.d.ts +3 -3
  19. package/dist/contracts.js +4 -1
  20. package/dist/contribution-parsing.js +6 -2
  21. package/dist/conversations.js +2 -1
  22. package/dist/credentials.d.ts +1 -1
  23. package/dist/credentials.js +3 -1
  24. package/dist/event-multiplexer.js +1 -3
  25. package/dist/feedback.js +11 -9
  26. package/dist/guardrails.d.ts +1 -1
  27. package/dist/guardrails.js +17 -14
  28. package/dist/identity.js +10 -2
  29. package/dist/index.d.ts +82 -83
  30. package/dist/index.js +42 -42
  31. package/dist/input.d.ts +2 -2
  32. package/dist/input.js +40 -24
  33. package/dist/instruction-injection.d.ts +1 -1
  34. package/dist/node/agent-definitions.js +16 -8
  35. package/dist/node/contribution-discovery.d.ts +1 -2
  36. package/dist/node/contribution-discovery.js +3 -3
  37. package/dist/node/session-store-jsonl.js +10 -7
  38. package/dist/node/settings.d.ts +1 -1
  39. package/dist/node/settings.js +1 -1
  40. package/dist/node/system-project-prompts.js +2 -4
  41. package/dist/node/trust.js +1 -1
  42. package/dist/persistence-lifecycle.js +1 -3
  43. package/dist/provider-events.js +3 -1
  44. package/dist/provider-request-policy.js +3 -4
  45. package/dist/providers/media.d.ts +1 -1
  46. package/dist/providers/openai-compatible.js +3 -4
  47. package/dist/providers/openai-primitives.js +7 -7
  48. package/dist/redaction.d.ts +1 -0
  49. package/dist/redaction.js +5 -2
  50. package/dist/resources.d.ts +2 -2
  51. package/dist/resources.js +2 -2
  52. package/dist/rpc.js +42 -9
  53. package/dist/run-ledger.js +13 -4
  54. package/dist/run-limits.js +49 -10
  55. package/dist/secure-agent.js +1 -1
  56. package/dist/security.js +7 -2
  57. package/dist/session-stores.d.ts +1 -1
  58. package/dist/session-stores.js +13 -13
  59. package/dist/structured-output.js +2 -2
  60. package/dist/system-prompts.js +7 -2
  61. package/dist/testing/compaction-conformance.js +5 -1
  62. package/dist/testing/extension-conformance.js +15 -3
  63. package/dist/testing/feedback.d.ts +1 -3
  64. package/dist/testing/feedback.js +1 -1
  65. package/dist/testing/persistence-schema.js +206 -37
  66. package/dist/testing/provider-conformance.js +3 -3
  67. package/dist/testing/run-ledger-conformance.js +1 -1
  68. package/dist/testing/session-store-conformance.js +1 -1
  69. package/dist/testing/tool-conformance.js +30 -5
  70. package/dist/thinking.js +4 -1
  71. package/dist/tools.d.ts +2 -2
  72. package/dist/tools.js +24 -5
  73. package/docs/0.1.0-readiness.md +139 -0
  74. package/docs/index.md +3 -1
  75. package/docs/migration.md +29 -0
  76. package/docs/performance.md +33 -0
  77. package/docs/public-contracts.md +1 -1
  78. package/docs/release-and-install.md +106 -17
  79. package/package.json +14 -6
  80. package/docs/review-coverage-2026-07-14.md +0 -260
  81. package/docs/review-coverage-2026-07-15.md +0 -193
  82. package/docs/review-coverage-2026-07-17-provider-validation.md +0 -192
  83. package/docs/review-coverage-2026-07-19-phase-3.md +0 -174
  84. package/docs/review-coverage-2026-07-20-phase-4.md +0 -175
  85. package/docs/review-coverage-2026-07-21-phase-5.md +0 -172
  86. package/docs/review-coverage-2026-07-22-phase-6.md +0 -209
  87. package/docs/review-coverage-2026-07-22-phase-7.md +0 -173
  88. package/docs/review-coverage-2026-07-23-phase-8.md +0 -245
  89. package/docs/review-coverage-2026-07-25-phase-9.md +0 -256
  90. package/docs/review-coverage-2026-07-26-phase-10.md +0 -132
package/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.0.16] - 2026-07-26
4
+
5
+ ### Added
6
+ - Phase 11 simplification/readiness: new public export `resolveRedactor` from `@arnilo/prism` (single survivor of four private copies across evals/memory/rag/workflows) and a new internal `@arnilo/prism-session-store-codecs` package (shared SQLite/Postgres row codecs, not enrolled in any profile family), bringing the exact graph to **44 publishable manifests**.
7
+ - Offline pre-publish release gates: `npm run release:gate` (API-surface `.d.ts` diff vs `scripts/compat-baseline/`, tarball deny-list, exact version ranges), wired into `npm run sdk:ready`.
8
+ - Performance budgets in `scripts/budgets.json`, enforced by `scripts/budget-gate.test.mjs` (in `npm test`) and `scripts/benchmark-0.0.16.mjs`.
9
+
10
+ ### Changed
11
+ - Dropped historical `docs/review-coverage-*.md` from the root tarball (11 files, ~283 KB): packed size 659,478 → ≈575,680 bytes, 281 → 270 files.
12
+ - All six profiles (`prism-all`, `prism-base`, `prism-code`, `prism-compaction`, `prism-providers`, `prism-sdk`) retained on adoption evidence; zero retirements. No runtime behavior changes.
13
+
3
14
  ## [0.0.15] - 2026-07-26
4
15
 
5
16
  ### Added
@@ -1,5 +1,5 @@
1
1
  import { createAgent } from "./agents.js";
2
- import { resolveActiveSkills, createSkillRegistry } from "./skills.js";
2
+ import { createSkillRegistry, resolveActiveSkills } from "./skills.js";
3
3
  import { createToolRegistry } from "./tools.js";
4
4
  /** Resolve an {@link AgentDefinition} into a runnable {@link Agent}.
5
5
  *
@@ -96,8 +96,7 @@ function hasList(value) {
96
96
  return typeof value === "object" && value !== null && "list" in value && typeof value.list === "function";
97
97
  }
98
98
  function resolveSkills(names, tools, context) {
99
- const registry = context.skillsRegistry ??
100
- (context.registries?.skills ? createSkillRegistry(context.registries.skills.list()) : undefined);
99
+ const registry = context.skillsRegistry ?? (context.registries?.skills ? createSkillRegistry(context.registries.skills.list()) : undefined);
101
100
  if (!names && !context.activateAllCapabilities)
102
101
  return undefined;
103
102
  if (!registry) {
@@ -1,5 +1,5 @@
1
- import { inputMessages } from "./input.js";
2
1
  import { createId } from "./ids.js";
2
+ import { inputMessages } from "./input.js";
3
3
  import { artifactStructuredOutputRequest, withoutStructuredOutput } from "./structured-output.js";
4
4
  function throwIfAborted(signal) {
5
5
  if (signal.aborted)
@@ -8,7 +8,10 @@ function throwIfAborted(signal) {
8
8
  function toolResultMessage(result) {
9
9
  return {
10
10
  role: "tool",
11
- content: [{ type: "tool_result", toolCallId: result.toolCallId, name: result.name, result: result.value, error: result.error }, ...(result.content ?? [])],
11
+ content: [
12
+ { type: "tool_result", toolCallId: result.toolCallId, name: result.name, result: result.value, error: result.error },
13
+ ...(result.content ?? []),
14
+ ],
12
15
  metadata: result.metadata,
13
16
  };
14
17
  }
@@ -121,7 +124,11 @@ export function generateValidateReviseLoop(opts) {
121
124
  continue;
122
125
  }
123
126
  if (toolRounds >= ctx.maxToolRounds) {
124
- const result = { ok: false, errors: [{ message: "maximum tool rounds exceeded" }], metadata: { reason: "tool_round_limit" } };
127
+ const result = {
128
+ ok: false,
129
+ errors: [{ message: "maximum tool rounds exceeded" }],
130
+ metadata: { reason: "tool_round_limit" },
131
+ };
125
132
  ctx.emit({ type: "artifact_failed", sessionId: ctx.sessionId, runId: ctx.runId, turn, attempt: attempts + 1, result });
126
133
  return usage;
127
134
  }
@@ -166,7 +173,7 @@ export function generateValidateReviseLoop(opts) {
166
173
  : undefined;
167
174
  const attempt = ++attempts;
168
175
  ctx.emit({ type: "artifact_validation_started", sessionId: ctx.sessionId, runId: ctx.runId, turn, attempt });
169
- const result = parseFailure ?? await opts.validator(parsed.value, artifactCtx);
176
+ const result = parseFailure ?? (await opts.validator(parsed.value, artifactCtx));
170
177
  ctx.emit({ type: "artifact_validation_finished", sessionId: ctx.sessionId, runId: ctx.runId, turn, attempt, result });
171
178
  if (result.ok) {
172
179
  ctx.emit({ type: "artifact_finished", sessionId: ctx.sessionId, runId: ctx.runId, turn, attempt, result });
@@ -213,9 +220,7 @@ export async function dispatchToolCallsInOrder(calls, ctx) {
213
220
  if (calls.length === 0)
214
221
  return;
215
222
  ctx.chargeToolRound?.(calls);
216
- const concurrency = calls.some((call) => ctx.isToolCallExclusive?.(call))
217
- ? 1
218
- : Math.max(1, Math.min(ctx.toolConcurrency, calls.length));
223
+ const concurrency = calls.some((call) => ctx.isToolCallExclusive?.(call)) ? 1 : Math.max(1, Math.min(ctx.toolConcurrency, calls.length));
219
224
  if (concurrency === 1) {
220
225
  for (const call of calls) {
221
226
  const result = await ctx.dispatchToolCall(call);
@@ -1,5 +1,4 @@
1
- import type { Agent, AgentEvent, AgentRunRef, AgentRunResult, AgentRunResume, AgentRunStatusResult, OwnershipScope, SubscribeOptions } from "./contracts.js";
2
- import type { CheckpointStore } from "./contracts.js";
1
+ import type { Agent, AgentEvent, AgentRunRef, AgentRunResult, AgentRunResume, AgentRunStatusResult, CheckpointStore, OwnershipScope, SubscribeOptions } from "./contracts.js";
3
2
  export interface AgentRunLifecycleAgent {
4
3
  readonly agent: Agent;
5
4
  /** Current host-authored revision; it must match the stored revision. */
@@ -1,6 +1,6 @@
1
- import { AgentRunStateError } from "./contracts.js";
2
1
  import { loadAgentRunState, publicState } from "./agent-run-state.js";
3
2
  import { resumeAgentRun, resumeAgentRunStream } from "./agents.js";
3
+ import { AgentRunStateError } from "./contracts.js";
4
4
  function assertAgentId(actual, expected) {
5
5
  if (expected !== undefined && actual !== expected)
6
6
  throw new AgentRunStateError("Agent run capability mismatch");
@@ -21,7 +21,9 @@ export function agentFingerprint(agent, revision) {
21
21
  model: config.model,
22
22
  tools: tools.map((tool) => ({ name: tool.name, parameters: tool.parameters, exclusive: tool.exclusive })),
23
23
  guardrails: guardrails.map((guardrail) => ({ name: guardrail.name, stage: guardrail.stage, revision: guardrail.revision })),
24
- loop: typeof config.loop === "object" && config.loop && "strategy" in config.loop ? config.loop.strategy : config.loop?.name ?? "single-shot",
24
+ loop: typeof config.loop === "object" && config.loop && "strategy" in config.loop
25
+ ? config.loop.strategy
26
+ : (config.loop?.name ?? "single-shot"),
25
27
  });
26
28
  return createHash("sha256").update(value).digest("hex");
27
29
  }
@@ -43,7 +45,10 @@ export async function loadAgentRunState(checkpoints, ref, ownership) {
43
45
  const record = await checkpoints.loadCheckpoint({ namespace: AGENT_RUN_STATE_NAMESPACE, key: ref.runId, ...ownership });
44
46
  if (!record)
45
47
  throw new AgentRunStateError(`No durable agent run ${ref.runId}`);
46
- if (ref.sessionId && record.value && typeof record.value === "object" && record.value.sessionId !== ref.sessionId) {
48
+ if (ref.sessionId &&
49
+ record.value &&
50
+ typeof record.value === "object" &&
51
+ record.value.sessionId !== ref.sessionId) {
47
52
  throw new AgentRunStateError("Agent run session mismatch");
48
53
  }
49
54
  return { record, state: parseAgentRunState(record.value, record.version) };
@@ -95,7 +100,15 @@ export function parseAgentRunState(value, version) {
95
100
  const state = value;
96
101
  if (state.schemaVersion !== AGENT_RUN_STATE_SCHEMA_VERSION)
97
102
  throw new AgentRunStateError(`Unsupported agent run state schemaVersion ${String(state.schemaVersion)}`);
98
- if (!state.agentId || !state.definitionRevision || !state.fingerprint || !state.runId || !state.sessionId || !state.model || !state.status || !state.counters || !state.deadlineAt) {
103
+ if (!state.agentId ||
104
+ !state.definitionRevision ||
105
+ !state.fingerprint ||
106
+ !state.runId ||
107
+ !state.sessionId ||
108
+ !state.model ||
109
+ !state.status ||
110
+ !state.counters ||
111
+ !state.deadlineAt) {
99
112
  throw new AgentRunStateError("Malformed agent run state");
100
113
  }
101
114
  return boundState({ ...state, version }, DEFAULT_MAX_AGENT_RUN_STATE_BYTES);
package/dist/agents.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Agent, AgentConfig, AgentEvent, AgentRunResult, AgentRunResume, AgentRunResumeOptions, AgentRunResumeStreamOptions, AgentRunRef, AgentSession, AgentSessionConfig } from "./contracts.js";
1
+ import type { Agent, AgentConfig, AgentEvent, AgentRunRef, AgentRunResult, AgentRunResume, AgentRunResumeOptions, AgentRunResumeStreamOptions, AgentSession, AgentSessionConfig } from "./contracts.js";
2
2
  export declare function createAgent(config: AgentConfig): Agent;
3
3
  export declare function createAgentSession(config: AgentSessionConfig & {
4
4
  readonly agent: Agent;
package/dist/agents.js CHANGED
@@ -1,23 +1,23 @@
1
- import { AgentRunError, AgentRunStateError, DEFAULT_MAX_PENDING_STEER_BYTES, DEFAULT_MAX_PENDING_STEERS, } from "./contracts.js";
2
1
  import { resolveLoop, resolveToolConcurrency } from "./agent-loops.js";
3
- import { createId } from "./ids.js";
4
- import { assertGuardrailsAllowed, GuardrailError, runGuardrails } from "./guardrails.js";
5
- import { createProviderTurnMetadata, readProviderHttpStatus } from "./observability.js";
2
+ import { agentFingerprint, initialAgentRunState, loadAgentRunState, publicState, saveAgentRunState, validateRunStateOptions, } from "./agent-run-state.js";
6
3
  import { createDefaultCompactionStrategy, isCompactionEntryData } from "./compaction.js";
4
+ import { AgentRunError, AgentRunStateError, DEFAULT_MAX_PENDING_STEER_BYTES, DEFAULT_MAX_PENDING_STEERS } from "./contracts.js";
5
+ import { assertGuardrailsAllowed, GuardrailError, runGuardrails } from "./guardrails.js";
6
+ import { identityTelemetryAttributes, ownershipFromIdentity, resolveRunIdentity } from "./identity.js";
7
+ import { createId } from "./ids.js";
7
8
  import { assembleProviderInput } from "./input.js";
9
+ import { createProviderTurnMetadata, readProviderHttpStatus } from "./observability.js";
8
10
  import { providerToolCallDeltaContent, reconstructToolCallDeltas } from "./provider-events.js";
9
11
  import { createProviderRequestPolicyChain, normalizeProviderRequestPolicyResult } from "./provider-request-policy.js";
10
- import { assertStructuredOutputRequestSupported, resolveRunProviderOptions } from "./structured-output.js";
11
- import { errorToErrorInfo, redactAgentEvent, redactProviderRequest, redactRunLedgerRecord, redactSecrets, redactSessionEntry } from "./redaction.js";
12
- import { composeSystemPrompt, mergeSystemPromptConfig } from "./system-prompts.js";
12
+ import { errorToErrorInfo, redactAgentEvent, redactProviderRequest, redactRunLedgerRecord, redactSecrets, redactSessionEntry, } from "./redaction.js";
13
13
  import { createDefaultRetryPolicy, waitForRetry } from "./retry.js";
14
- import { createMemorySessionStore, createSessionEntry, getSessionBranchEntries, rebuildSessionContext } from "./session-stores.js";
15
14
  import { isFlushableRunLedger } from "./run-ledger.js";
16
- import { createToolRegistry, dispatchToolCall } from "./tools.js";
17
15
  import { RunLimitError, RunLimitTracker, resolveRunLimits } from "./run-limits.js";
18
- import { agentFingerprint, initialAgentRunState, loadAgentRunState, publicState, saveAgentRunState, validateRunStateOptions } from "./agent-run-state.js";
16
+ import { createMemorySessionStore, createSessionEntry, getSessionBranchEntries, rebuildSessionContext, } from "./session-stores.js";
19
17
  import { resolveActiveSkills } from "./skills.js";
20
- import { identityTelemetryAttributes, ownershipFromIdentity, resolveRunIdentity, } from "./identity.js";
18
+ import { assertStructuredOutputRequestSupported, resolveRunProviderOptions } from "./structured-output.js";
19
+ import { composeSystemPrompt, mergeSystemPromptConfig } from "./system-prompts.js";
20
+ import { createToolRegistry, dispatchToolCall } from "./tools.js";
21
21
  export function createAgent(config) {
22
22
  return {
23
23
  config,
@@ -39,7 +39,9 @@ export async function* resumeAgentRunStream(agent, ref, resume, options) {
39
39
  const prepared = await prepareAgentRunResume(agent, ref, resume, options, options.signal);
40
40
  const subscription = prepared.session.subscribe(options);
41
41
  let settled = false;
42
- const runPromise = executePreparedAgentRunResume(prepared, options.signal).finally(() => { settled = true; });
42
+ const runPromise = executePreparedAgentRunResume(prepared, options.signal).finally(() => {
43
+ settled = true;
44
+ });
43
45
  try {
44
46
  for await (const event of subscription) {
45
47
  if ("runId" in event && event.runId !== ref.runId)
@@ -58,7 +60,9 @@ export async function* resumeAgentRunStream(agent, ref, resume, options) {
58
60
  async function prepareAgentRunResume(agent, ref, resume, options, signal) {
59
61
  throwIfAbortedSignal(signal);
60
62
  const { record, state } = await loadAgentRunState(options.checkpoints, ref, options.ownership);
61
- if (state.definitionRevision !== options.definitionRevision || state.agentId !== (agent.config.id ?? agent.config.name) || state.fingerprint !== agentFingerprint(agent, options.definitionRevision)) {
63
+ if (state.definitionRevision !== options.definitionRevision ||
64
+ state.agentId !== (agent.config.id ?? agent.config.name) ||
65
+ state.fingerprint !== agentFingerprint(agent, options.definitionRevision)) {
62
66
  throw new AgentRunStateError("Agent definition revision or fingerprint mismatch on resume");
63
67
  }
64
68
  if (record.version !== resume.expectedVersion || state.status !== "suspended") {
@@ -211,7 +215,11 @@ class RuntimeAgentSession {
211
215
  }
212
216
  }
213
217
  async resumeDurable(state, runState, ownership, signal) {
214
- return this.runInternal(state.input ?? [], { runState, ownership, signal }, state.runId, { options: runState, state, version: state.version });
218
+ return this.runInternal(state.input ?? [], { runState, ownership, signal }, state.runId, {
219
+ options: runState,
220
+ state,
221
+ version: state.version,
222
+ });
215
223
  }
216
224
  async recordDurableDenial(runId, interruption, version, ownership) {
217
225
  this.activeLedger = this.agent.config.runLedger;
@@ -229,7 +237,11 @@ class RuntimeAgentSession {
229
237
  }
230
238
  }
231
239
  async runInternal(input, options, runId, resumed) {
232
- if (this.agent.config.secure && (options.redactor !== undefined || options.ownership !== undefined || options.validate !== undefined || options.runState !== undefined)) {
240
+ if (this.agent.config.secure &&
241
+ (options.redactor !== undefined ||
242
+ options.ownership !== undefined ||
243
+ options.validate !== undefined ||
244
+ options.runState !== undefined)) {
233
245
  throw new AgentRunStateError("Secure agent defaults cannot be replaced per run");
234
246
  }
235
247
  const requestedLimits = options.maxToolRounds === undefined
@@ -316,7 +328,14 @@ class RuntimeAgentSession {
316
328
  const { registry, tools } = activeTools(this.agent.config.tools);
317
329
  const activeSkills = this.resolveRunSkills(options, tools);
318
330
  if (options.model && JSON.stringify(options.model) !== JSON.stringify(this.agent.config.model)) {
319
- await this.appendEntry(createSessionEntry({ sessionId: this.id, parentId: this.currentLeafId, runId, kind: "model_change", previousModel: this.agent.config.model, model: options.model }));
331
+ await this.appendEntry(createSessionEntry({
332
+ sessionId: this.id,
333
+ parentId: this.currentLeafId,
334
+ runId,
335
+ kind: "model_change",
336
+ previousModel: this.agent.config.model,
337
+ model: options.model,
338
+ }));
320
339
  }
321
340
  const inputMessages = inputToMessages(input).map((message) => this.redact(message));
322
341
  const inputGuardrails = await runGuardrails({
@@ -340,7 +359,9 @@ class RuntimeAgentSession {
340
359
  await this.appendMessage(message, runId);
341
360
  await this.autoCompact(runId, options, controller.signal, inputMessages);
342
361
  const maxToolRounds = resolvedLimits.maxToolRounds;
343
- const systemInstructions = composeSystemPrompt(mergeSystemPromptConfig(this.agent.config.systemPrompt, options.systemPrompt), { base: this.agent.config.instructions });
362
+ const systemInstructions = composeSystemPrompt(mergeSystemPromptConfig(this.agent.config.systemPrompt, options.systemPrompt), {
363
+ base: this.agent.config.instructions,
364
+ });
344
365
  const contextProviders = [
345
366
  ...(this.agent.config.context ?? []),
346
367
  // ponytail: skill context after host context; no per-skill token budget yet.
@@ -429,7 +450,7 @@ class RuntimeAgentSession {
429
450
  limits.charge("maxTurns");
430
451
  assembledTurn = false;
431
452
  const policyResult = await this.applyProviderRequestPolicies(request, runId, options, metadata, controller.signal);
432
- const middlewareRequest = await this.agent.config.middleware?.run("provider_request", policyResult.request) ?? policyResult.request;
453
+ const middlewareRequest = (await this.agent.config.middleware?.run("provider_request", policyResult.request)) ?? policyResult.request;
433
454
  try {
434
455
  return await this.generateWithRetry(this.redactProviderRequest(middlewareRequest), runId, options, controller.signal, policyResult.secrets, this.activeLoopTurn, recordProviderUsage);
435
456
  }
@@ -468,12 +489,22 @@ class RuntimeAgentSession {
468
489
  return;
469
490
  const pending = durable.state?.pending;
470
491
  if (pending?.call.id === mediatedCall.id && pending.status === "ready") {
471
- await this.persistDurable({ ...durable.state, status: "running", pending: { ...pending, status: "dispatched" }, interruption: undefined });
492
+ await this.persistDurable({
493
+ ...durable.state,
494
+ status: "running",
495
+ pending: { ...pending, status: "dispatched" },
496
+ interruption: undefined,
497
+ });
472
498
  return;
473
499
  }
474
500
  if (!durable.options.interruptBeforeTool)
475
501
  return;
476
- const interruption = { kind: "tool_approval", reason: "Tool side effect requires approval", toolCallId: mediatedCall.id, toolName: mediatedCall.name };
502
+ const interruption = {
503
+ kind: "tool_approval",
504
+ reason: "Tool side effect requires approval",
505
+ toolCallId: mediatedCall.id,
506
+ toolName: mediatedCall.name,
507
+ };
477
508
  throw new AgentRunSuspended(await this.suspendDurable({
478
509
  runId,
479
510
  model,
@@ -508,13 +539,19 @@ class RuntimeAgentSession {
508
539
  const result = await ctx.dispatchToolCall(resumed.state.pending.call);
509
540
  await ctx.appendMessage({
510
541
  role: "tool",
511
- content: [{ type: "tool_result", toolCallId: result.toolCallId, name: result.name, result: result.value, error: result.error }, ...(result.content ?? [])],
542
+ content: [
543
+ { type: "tool_result", toolCallId: result.toolCallId, name: result.name, result: result.value, error: result.error },
544
+ ...(result.content ?? []),
545
+ ],
512
546
  metadata: result.metadata,
513
547
  });
514
548
  }
515
549
  const loopUsage = await loop.run(ctx);
516
550
  if (loop.name === "generate-validate-revise" && !artifactFinished) {
517
- throw Object.assign(new Error(artifactFailedInfo?.message ?? "artifact loop ended without a validated artifact"), { name: "ArtifactFailed", code: artifactFailedInfo?.code ?? "artifact_failed" });
551
+ throw Object.assign(new Error(artifactFailedInfo?.message ?? "artifact loop ended without a validated artifact"), {
552
+ name: "ArtifactFailed",
553
+ code: artifactFailedInfo?.code ?? "artifact_failed",
554
+ });
518
555
  }
519
556
  usage = runUsage.value() ?? loopUsage;
520
557
  if (usage && this.activeLedger) {
@@ -661,21 +698,22 @@ class RuntimeAgentSession {
661
698
  const durable = this.activeDurable;
662
699
  if (!durable)
663
700
  throw new AgentRunStateError("Durable interruption is not configured");
664
- const state = durable.state ?? initialAgentRunState({
665
- agent: this.agent,
666
- options: durable.options,
667
- runId: input.runId,
668
- sessionId: this.id,
669
- leafId: this.currentLeafId,
670
- model: input.model,
671
- counters: input.limits.snapshot(),
672
- deadlineAt: input.limits.deadlineAt,
673
- status: "suspended",
674
- interruption: input.interruption,
675
- messages: input.messages,
676
- pending: input.pending,
677
- interruptBeforeTool: durable.options.interruptBeforeTool,
678
- });
701
+ const state = durable.state ??
702
+ initialAgentRunState({
703
+ agent: this.agent,
704
+ options: durable.options,
705
+ runId: input.runId,
706
+ sessionId: this.id,
707
+ leafId: this.currentLeafId,
708
+ model: input.model,
709
+ counters: input.limits.snapshot(),
710
+ deadlineAt: input.limits.deadlineAt,
711
+ status: "suspended",
712
+ interruption: input.interruption,
713
+ messages: input.messages,
714
+ pending: input.pending,
715
+ interruptBeforeTool: durable.options.interruptBeforeTool,
716
+ });
679
717
  return this.persistDurable({
680
718
  ...state,
681
719
  leafId: this.currentLeafId,
@@ -723,7 +761,13 @@ class RuntimeAgentSession {
723
761
  await this.rebuildHistory();
724
762
  }
725
763
  fork(options = {}) {
726
- return createAgentSession({ agent: this.agent, id: this.id, store: this.store, leafId: options.leafId ?? this.currentLeafId, metadata: this.metadata });
764
+ return createAgentSession({
765
+ agent: this.agent,
766
+ id: this.id,
767
+ store: this.store,
768
+ leafId: options.leafId ?? this.currentLeafId,
769
+ metadata: this.metadata,
770
+ });
727
771
  }
728
772
  async clone(options = {}) {
729
773
  const id = options.id ?? randomId("session");
@@ -739,7 +783,13 @@ class RuntimeAgentSession {
739
783
  const { id: _oldId, parentId: _oldParentId, sessionId: _oldSessionId, ...rest } = entry;
740
784
  await this.store.append({ ...rest, id: nextId, parentId: entry.parentId ? remap.get(entry.parentId) : undefined, sessionId: id });
741
785
  }
742
- return createAgentSession({ agent: this.agent, id, store: this.store, leafId: branch.length ? remap.get(branch[branch.length - 1].id) : undefined, metadata: this.metadata });
786
+ return createAgentSession({
787
+ agent: this.agent,
788
+ id,
789
+ store: this.store,
790
+ leafId: branch.length ? remap.get(branch[branch.length - 1].id) : undefined,
791
+ metadata: this.metadata,
792
+ });
743
793
  }
744
794
  branchReader() {
745
795
  // ponytail: prefer the store's readBranchPath (one ancestor-chain query) when present so a
@@ -753,9 +803,7 @@ class RuntimeAgentSession {
753
803
  // the resolver entirely; otherwise `RunOptions.providerSource` overrides
754
804
  // `AgentConfig.providerSource` for this run. A miss on every source fails
755
805
  // closed with `Unknown provider: ${model.provider}` before any provider turn.
756
- const provider = this.agent.config.provider ??
757
- options.providerSource?.(model) ??
758
- this.agent.config.providerSource?.(model);
806
+ const provider = this.agent.config.provider ?? options.providerSource?.(model) ?? this.agent.config.providerSource?.(model);
759
807
  if (!provider)
760
808
  throw new Error(`Unknown provider: ${model.provider}`);
761
809
  this.activeProvider = provider;
@@ -828,7 +876,10 @@ class RuntimeAgentSession {
828
876
  throw errorFromInfo(info);
829
877
  const context = { sessionId: this.id, runId, attempt, error: info, metadata: retry?.metadata, signal };
830
878
  let decision = await policy.decide(context);
831
- const payload = await this.agent.config.middleware?.run("retry", { context, decision }) ?? { context, decision };
879
+ const payload = (await this.agent.config.middleware?.run("retry", { context, decision })) ?? {
880
+ context,
881
+ decision,
882
+ };
832
883
  decision = payload.decision;
833
884
  if (!decision.retry)
834
885
  throw errorFromInfo(info);
@@ -1029,16 +1080,35 @@ class RuntimeAgentSession {
1029
1080
  throwIfAbortedSignal(signal);
1030
1081
  const entries = await this.entries();
1031
1082
  const secrets = options.secrets ?? [];
1032
- const strategy = options.strategy ?? createDefaultCompactionStrategy({ keepRecentEntries: options.keepRecentEntries, maxSummaryChars: options.maxSummaryChars, secrets });
1033
- const context = { sessionId: this.id, entries, keepRecentEntries: options.keepRecentEntries, trigger, secrets, metadata: options.metadata, signal };
1083
+ const strategy = options.strategy ??
1084
+ createDefaultCompactionStrategy({ keepRecentEntries: options.keepRecentEntries, maxSummaryChars: options.maxSummaryChars, secrets });
1085
+ const context = {
1086
+ sessionId: this.id,
1087
+ entries,
1088
+ keepRecentEntries: options.keepRecentEntries,
1089
+ trigger,
1090
+ secrets,
1091
+ metadata: options.metadata,
1092
+ signal,
1093
+ };
1034
1094
  this.emit({ type: "compaction_started", sessionId: this.id, runId });
1035
1095
  let result = await strategy.compact(context);
1036
1096
  result = { ...result, summary: redactSecrets(result.summary, secrets) };
1037
- const payload = await this.agent.config.middleware?.run("compaction", { context, result }) ?? { context, result };
1097
+ const payload = (await this.agent.config.middleware?.run("compaction", { context, result })) ?? {
1098
+ context,
1099
+ result,
1100
+ };
1038
1101
  result = { ...payload.result, summary: redactSecrets(payload.result.summary, secrets) };
1039
1102
  const source = result.entries?.find((entry) => entry.kind === "compaction");
1040
1103
  const data = isCompactionEntryData(source?.data) ? source.data : undefined;
1041
- const entry = createSessionEntry({ sessionId: this.id, parentId: this.currentLeafId, runId, kind: "compaction", summary: result.summary, data });
1104
+ const entry = createSessionEntry({
1105
+ sessionId: this.id,
1106
+ parentId: this.currentLeafId,
1107
+ runId,
1108
+ kind: "compaction",
1109
+ summary: result.summary,
1110
+ data,
1111
+ });
1042
1112
  await this.appendEntry(entry);
1043
1113
  const finalResult = { ...result, entries: [entry] };
1044
1114
  this.emit({ type: "compaction_finished", sessionId: this.id, runId, summary: finalResult.summary });
@@ -1181,8 +1251,8 @@ class SteerSoftInterrupt extends Error {
1181
1251
  }
1182
1252
  }
1183
1253
  function isSteerSoftInterrupt(error) {
1184
- return error instanceof SteerSoftInterrupt
1185
- || (typeof error === "object" && error !== null && error.code === STEER_SOFT_INTERRUPT_CODE);
1254
+ return (error instanceof SteerSoftInterrupt ||
1255
+ (typeof error === "object" && error !== null && error.code === STEER_SOFT_INTERRUPT_CODE));
1186
1256
  }
1187
1257
  function finalAssistantMessage(history) {
1188
1258
  for (let index = history.length - 1; index >= 0; index -= 1) {
@@ -1295,8 +1365,8 @@ function createUsageAccumulator() {
1295
1365
  if (value !== undefined)
1296
1366
  sums.set(key, (sums.get(key) ?? 0) + value);
1297
1367
  }
1298
- const total = usage.totalTokens
1299
- ?? (usage.inputTokens !== undefined || usage.outputTokens !== undefined
1368
+ const total = usage.totalTokens ??
1369
+ (usage.inputTokens !== undefined || usage.outputTokens !== undefined
1300
1370
  ? (usage.inputTokens ?? 0) + (usage.outputTokens ?? 0)
1301
1371
  : undefined);
1302
1372
  if (total !== undefined)
@@ -1,5 +1,8 @@
1
1
  export function sanitizeCacheKey(value, maxLength) {
2
- const key = value?.replace(/[^A-Za-z0-9_.:-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, Math.max(0, maxLength));
2
+ const key = value
3
+ ?.replace(/[^A-Za-z0-9_.:-]+/g, "-")
4
+ .replace(/^-+|-+$/g, "")
5
+ .slice(0, Math.max(0, maxLength));
3
6
  return key || undefined;
4
7
  }
5
8
  export function mapCacheRetention(retention, model) {
@@ -37,7 +40,7 @@ export function cacheSavings(usage, model) {
37
40
  const cacheRead = model.cost?.cacheRead;
38
41
  if (read === undefined || input === undefined || cacheRead === undefined)
39
42
  return undefined;
40
- return read * Math.max(0, input - cacheRead) / costUnitDivisor(model.cost?.unit);
43
+ return (read * Math.max(0, input - cacheRead)) / costUnitDivisor(model.cost?.unit);
41
44
  }
42
45
  export function cacheUsageReport(usage, model) {
43
46
  if (!usage)
@@ -48,17 +51,23 @@ export function cacheUsageReport(usage, model) {
48
51
  cacheWriteTokens: usage.cacheWriteTokens ?? 0,
49
52
  hitRate: cacheHitRate(usage),
50
53
  estimatedSavings,
51
- currency: estimatedSavings === undefined ? usage.currency : model?.cost?.currency ?? usage.currency,
54
+ currency: estimatedSavings === undefined ? usage.currency : (model?.cost?.currency ?? usage.currency),
52
55
  };
53
56
  }
54
57
  function resolveBreakpoint(messages, breakpoint) {
55
58
  switch (breakpoint.location) {
56
- case "system_prompt": return messages.findIndex((message) => message.role === "system");
57
- case "tools": return messages.findIndex((message) => message.role === "tool" || message.content.some((block) => block.type === "tool_call" || block.type === "tool_result"));
58
- case "stable_context": return messages.findIndex((message) => message.role !== "system");
59
- case "last_stable_message": return messages.length > 1 ? messages.length - 2 : messages.length - 1;
60
- case "last_user_message": return findLastIndex(messages, (message) => message.role === "user");
61
- case "message_id": return messages.findIndex((message) => message.id === breakpoint.messageId);
59
+ case "system_prompt":
60
+ return messages.findIndex((message) => message.role === "system");
61
+ case "tools":
62
+ return messages.findIndex((message) => message.role === "tool" || message.content.some((block) => block.type === "tool_call" || block.type === "tool_result"));
63
+ case "stable_context":
64
+ return messages.findIndex((message) => message.role !== "system");
65
+ case "last_stable_message":
66
+ return messages.length > 1 ? messages.length - 2 : messages.length - 1;
67
+ case "last_user_message":
68
+ return findLastIndex(messages, (message) => message.role === "user");
69
+ case "message_id":
70
+ return messages.findIndex((message) => message.id === breakpoint.messageId);
62
71
  }
63
72
  }
64
73
  function findLastIndex(items, predicate) {
@@ -61,9 +61,7 @@ export function createMemoryCheckpointStore(options = {}) {
61
61
  throwIfAborted(query.signal);
62
62
  const offset = decodeCursor(query.cursor);
63
63
  const limit = Math.min(Math.max(1, query.limit ?? 100), maxPageSize);
64
- const categories = query.category === undefined
65
- ? undefined
66
- : new Set(Array.isArray(query.category) ? query.category : [query.category]);
64
+ const categories = query.category === undefined ? undefined : new Set(Array.isArray(query.category) ? query.category : [query.category]);
67
65
  const items = [...records.values()]
68
66
  .filter((record) => query.namespace === undefined || record.namespace === query.namespace)
69
67
  .filter((record) => query.keyPrefix === undefined || record.key.startsWith(query.keyPrefix))
@@ -104,14 +102,12 @@ function ownership(input) {
104
102
  };
105
103
  }
106
104
  function ownershipMatches(expected, actual) {
107
- return expected.tenantId === actual.tenantId
108
- && expected.accountId === actual.accountId
109
- && expected.userId === actual.userId;
105
+ return expected.tenantId === actual.tenantId && expected.accountId === actual.accountId && expected.userId === actual.userId;
110
106
  }
111
107
  function ownershipFilterMatches(expected, actual) {
112
- return (expected.tenantId === undefined || expected.tenantId === actual.tenantId)
113
- && (expected.accountId === undefined || expected.accountId === actual.accountId)
114
- && (expected.userId === undefined || expected.userId === actual.userId);
108
+ return ((expected.tenantId === undefined || expected.tenantId === actual.tenantId) &&
109
+ (expected.accountId === undefined || expected.accountId === actual.accountId) &&
110
+ (expected.userId === undefined || expected.userId === actual.userId));
115
111
  }
116
112
  function assertOwnership(expected, actual) {
117
113
  if (!ownershipMatches(expected, actual)) {
package/dist/cli-init.js CHANGED
@@ -1,5 +1,5 @@
1
- import { access, mkdir, readdir, readFile, writeFile } from "node:fs/promises";
2
1
  import { constants as fsConstants, readFileSync } from "node:fs";
2
+ import { access, mkdir, readdir, readFile, writeFile } from "node:fs/promises";
3
3
  import { dirname, isAbsolute, join, normalize, relative, resolve, sep } from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
5
  export class InitUsageError extends Error {
@@ -305,12 +305,8 @@ function buildTokens(input) {
305
305
  ? `2. Copy \`.env.example\` to \`.env\` and set \`${input.provider.envKey}\`.\n3. Run \`npm start\` for a live provider call.`
306
306
  : `2. Run \`npm start\` (mock provider; no network or credentials).`;
307
307
  const optionalDocs = [
308
- ...(input.withWorkflows
309
- ? ["- `src/workflows-example.ts` — tiny DAG example using `@arnilo/prism-workflows`."]
310
- : []),
311
- ...(input.withEvals
312
- ? ["- `src/evals-example.ts` — deterministic scorer example using `@arnilo/prism-evals`."]
313
- : []),
308
+ ...(input.withWorkflows ? ["- `src/workflows-example.ts` — tiny DAG example using `@arnilo/prism-workflows`."] : []),
309
+ ...(input.withEvals ? ["- `src/evals-example.ts` — deterministic scorer example using `@arnilo/prism-evals`."] : []),
314
310
  ].join("\n");
315
311
  return {
316
312
  __PROJECT_NAME__: input.projectName,
@@ -46,7 +46,7 @@ export interface CliOptions {
46
46
  readonly agentsMdFile?: string;
47
47
  readonly systemMdFile?: string;
48
48
  /** Runtime-populated: AGENTS.md/SYSTEM.md layers loaded from disk (print/json modes only;
49
- * RPC is host-owned). Threaded into `AgentConfig.systemPrompt` by `defaultCreateSession`. */
49
+ * RPC is host-owned). Threaded into `AgentConfig.systemPrompt` by `defaultCreateSession`. */
50
50
  readonly systemPromptLayers: readonly SystemPromptContribution[];
51
51
  }
52
52
  export interface CliRuntime {