@rowan-agent/agent 0.9.3 → 0.9.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -778,6 +778,8 @@ type MessageBase = Readonly<{
778
778
  id: MessageId;
779
779
  agentId: AgentId;
780
780
  runId: RunId;
781
+ /** Monotonic active revision. Omitted on legacy/initial messages and read as 0. */
782
+ messageRevision?: number;
781
783
  metadata?: Metadata;
782
784
  sequenceWithinRun: number;
783
785
  createdAt: string;
@@ -888,6 +890,14 @@ type MessageCommitted = DurableEventBase & Readonly<{
888
890
  kind: "message_committed";
889
891
  message: Message;
890
892
  }>;
893
+ type MessageRevised = DurableEventBase & Readonly<{
894
+ kind: "message_revised";
895
+ message: UserMessage;
896
+ previousRevision: number;
897
+ invalidatedRunIds: readonly RunId[];
898
+ targetRunId: RunId;
899
+ cutoffSequenceWithinRun: number;
900
+ }>;
891
901
  type RunStateChanged = DurableEventBase & (Readonly<{
892
902
  kind: "run_state_changed";
893
903
  from: null;
@@ -986,7 +996,7 @@ type ToolStateChanged = DurableEventBase & (Readonly<{
986
996
  state: "indeterminate";
987
997
  }>;
988
998
  }>);
989
- type DurableRunEvent = MessageCommitted | RunStateChanged | ToolStateChanged;
999
+ type DurableRunEvent = MessageCommitted | MessageRevised | RunStateChanged | ToolStateChanged;
990
1000
  type MessageDelta = Readonly<{
991
1001
  kind: "message_delta";
992
1002
  durability: "transient";
@@ -1265,6 +1275,7 @@ type UserInput = string | Readonly<{
1265
1275
  content: UserContent;
1266
1276
  metadata?: Metadata;
1267
1277
  }>;
1278
+ type HistorySeed = readonly Message[];
1268
1279
  type ToolInvocationContext = Readonly<{
1269
1280
  agentId: AgentId;
1270
1281
  runId: RunId;
@@ -1402,6 +1413,11 @@ type RunRecord = Readonly<{
1402
1413
  revision: number;
1403
1414
  state: RunState;
1404
1415
  input: UserInput;
1416
+ initialMessageId?: MessageId;
1417
+ invalidatedBy?: Readonly<{
1418
+ messageId: MessageId;
1419
+ messageRevision: number;
1420
+ }>;
1405
1421
  metadata?: Metadata;
1406
1422
  pinnedConfigToken?: ConfigToken;
1407
1423
  checkpoint?: ExecutionCheckpoint;
@@ -1413,6 +1429,22 @@ type RunRecord = Readonly<{
1413
1429
  createdAt: string;
1414
1430
  updatedAt: string;
1415
1431
  }>;
1432
+ type MessageRevisionResult = Readonly<{
1433
+ message: UserMessage & Readonly<{
1434
+ messageRevision: number;
1435
+ }>;
1436
+ replacementRun: RunRecord;
1437
+ invalidatedRunIds: readonly RunId[];
1438
+ affectedToolCallIds: readonly ToolCallId[];
1439
+ effectDigest?: string;
1440
+ }>;
1441
+ type RetentionResult = Readonly<{
1442
+ deletedRunIds: readonly RunId[];
1443
+ deletedToolCallIds: readonly ToolCallId[];
1444
+ deletedEventCount: number;
1445
+ retentionFloor: EventCursor;
1446
+ skipped?: "active_consumers" | "no_eligible_events";
1447
+ }>;
1416
1448
  type AgentSummary = Readonly<{
1417
1449
  id: AgentId;
1418
1450
  metadata?: Metadata;
@@ -1520,6 +1552,7 @@ interface OwnedStore {
1520
1552
  idempotencyKey: string;
1521
1553
  metadata?: Metadata;
1522
1554
  configIdentity?: string;
1555
+ historySeed?: HistorySeed;
1523
1556
  }): Promise<AgentRecord>;
1524
1557
  activateAgent(agentId: AgentId, configToken?: ConfigToken, configIdentity?: string): Promise<AgentRecord>;
1525
1558
  updateAgentConfigToken(input: {
@@ -1529,6 +1562,18 @@ interface OwnedStore {
1529
1562
  idempotencyKey: string;
1530
1563
  }): Promise<AgentRecord>;
1531
1564
  deleteAgent(input: AgentDeletionRequest): Promise<void>;
1565
+ reviseMessage(input: {
1566
+ agentId: AgentId;
1567
+ messageId: MessageId;
1568
+ expectedMessageRevision: number;
1569
+ content: UserContent;
1570
+ operationId: string;
1571
+ effectDigestConfirmation?: string;
1572
+ }): Promise<MessageRevisionResult>;
1573
+ compact(input?: {
1574
+ now?: string;
1575
+ retentionMs?: number;
1576
+ }): Promise<RetentionResult>;
1532
1577
  createRun(input: {
1533
1578
  agentId: AgentId;
1534
1579
  input: UserInput;
@@ -1610,6 +1655,7 @@ interface OwnedStore {
1610
1655
  output?: AssistantMessage;
1611
1656
  }): Promise<RunRecord>;
1612
1657
  snapshotRun(runId: RunId): Promise<RunSnapshot>;
1658
+ history(agentId: AgentId): Promise<readonly Message[]>;
1613
1659
  listAgents(): Promise<readonly AgentRecord[]>;
1614
1660
  listRuns(input?: {
1615
1661
  agentId?: AgentId;
@@ -1674,16 +1720,29 @@ interface AgentRuntime$1 {
1674
1720
  createAgent(config: AgentConfigRequest, options?: {
1675
1721
  idempotencyKey?: string;
1676
1722
  metadata?: Metadata;
1723
+ historySeed?: HistorySeed;
1677
1724
  }): Promise<AgentId>;
1678
1725
  updateAgentConfig(agentId: AgentId, config: AgentConfigRequest, options: {
1679
1726
  idempotencyKey: string;
1680
1727
  }): Promise<void>;
1681
1728
  deleteAgent(input: AgentDeletionRequest): Promise<void>;
1729
+ revise(agentId: AgentId, input: {
1730
+ messageId: MessageId;
1731
+ expectedMessageRevision: number;
1732
+ content: UserContent;
1733
+ operationId: string;
1734
+ effectDigestConfirmation?: string;
1735
+ }): Promise<MessageRevisionResult>;
1736
+ compact(input?: {
1737
+ now?: string;
1738
+ retentionMs?: number;
1739
+ }): Promise<RetentionResult>;
1682
1740
  start(agentId: AgentId, input: UserInput, options: {
1683
1741
  idempotencyKey: string;
1684
1742
  metadata?: Metadata;
1685
1743
  }): Promise<AgentRun>;
1686
1744
  run(runId: RunId): AgentRun;
1745
+ history(agentId: AgentId): Promise<readonly Message[]>;
1687
1746
  listAgents(input?: {
1688
1747
  after?: AgentListCursor;
1689
1748
  limit?: number;
@@ -1740,11 +1799,29 @@ declare class AgentRuntime implements AgentRuntime$1 {
1740
1799
  createAgent(config: AgentConfigRequest, options?: {
1741
1800
  idempotencyKey?: string;
1742
1801
  metadata?: Metadata;
1802
+ historySeed?: HistorySeed;
1743
1803
  }): Promise<AgentId>;
1744
1804
  updateAgentConfig(agentId: AgentId, config: AgentConfigRequest, options: {
1745
1805
  idempotencyKey: string;
1746
1806
  }): Promise<void>;
1747
1807
  deleteAgent(input: AgentDeletionRequest): Promise<void>;
1808
+ revise(agentId: AgentId, input: {
1809
+ messageId: MessageId;
1810
+ expectedMessageRevision: number;
1811
+ content: UserContent;
1812
+ operationId: string;
1813
+ effectDigestConfirmation?: string;
1814
+ }): Promise<MessageRevisionResult>;
1815
+ compact(input?: {
1816
+ now?: string;
1817
+ retentionMs?: number;
1818
+ }): Promise<Readonly<{
1819
+ deletedRunIds: readonly RunId[];
1820
+ deletedToolCallIds: readonly ToolCallId[];
1821
+ deletedEventCount: number;
1822
+ retentionFloor: EventCursor;
1823
+ skipped?: "active_consumers" | "no_eligible_events";
1824
+ }>>;
1748
1825
  start(agentId: AgentId, input: UserInput, options: {
1749
1826
  idempotencyKey: string;
1750
1827
  metadata?: Metadata;
@@ -1769,6 +1846,7 @@ declare class AgentRuntime implements AgentRuntime$1 {
1769
1846
  }): Promise<DurableConsumer>;
1770
1847
  close(): Promise<void>;
1771
1848
  snapshot(runId: RunId): Promise<RunSnapshot>;
1849
+ history(agentId: AgentId): Promise<readonly Message[]>;
1772
1850
  respond(runId: RunId, input: {
1773
1851
  requestId: InputRequestId;
1774
1852
  input: UserInput;
@@ -1807,7 +1885,9 @@ type InMemoryStoreState = Readonly<{
1807
1885
  events: readonly DurableRunEvent[];
1808
1886
  idempotency: readonly (readonly [string, IdempotencyReceipt])[];
1809
1887
  operationReceipts: readonly (readonly [string, IdempotencyReceipt])[];
1888
+ historySeeds?: readonly (readonly [AgentId, readonly Message[]])[];
1810
1889
  consumerCheckpoints: readonly (readonly [string, EventCursor])[];
1890
+ retentionFloor?: number;
1811
1891
  nextAgentSequence: readonly (readonly [AgentId, number])[];
1812
1892
  nextReadySequence: readonly (readonly [AgentId, number])[];
1813
1893
  eventSequence: number;
@@ -1821,12 +1901,14 @@ declare class InMemoryStore implements DurableStore {
1821
1901
  private readonly events;
1822
1902
  private readonly idempotency;
1823
1903
  private readonly operationReceipts;
1904
+ private readonly historySeeds;
1824
1905
  private readonly consumerCheckpoints;
1825
1906
  private readonly nextAgentSequence;
1826
1907
  private readonly nextReadySequence;
1827
1908
  private owner?;
1828
1909
  private ownerEpoch;
1829
1910
  private eventSequence;
1911
+ private retentionFloor;
1830
1912
  constructor(options?: {
1831
1913
  incarnation?: string;
1832
1914
  });
@@ -1845,6 +1927,7 @@ declare class InMemoryStore implements DurableStore {
1845
1927
  idempotencyKey: string;
1846
1928
  metadata?: Metadata;
1847
1929
  configIdentity?: string;
1930
+ historySeed?: HistorySeed;
1848
1931
  }): AgentRecord;
1849
1932
  activateAgent(lease: OwnerLease, agentId: AgentId, configToken?: ConfigToken, configIdentity?: string): AgentRecord;
1850
1933
  updateAgentConfigToken(lease: OwnerLease, input: {
@@ -1854,6 +1937,14 @@ declare class InMemoryStore implements DurableStore {
1854
1937
  idempotencyKey: string;
1855
1938
  }): AgentRecord;
1856
1939
  deleteAgent(lease: OwnerLease, input: AgentDeletionRequest): void;
1940
+ reviseMessage(lease: OwnerLease, input: {
1941
+ agentId: AgentId;
1942
+ messageId: MessageId;
1943
+ expectedMessageRevision: number;
1944
+ content: UserContent;
1945
+ operationId: string;
1946
+ effectDigestConfirmation?: string;
1947
+ }): MessageRevisionResult;
1857
1948
  createRun(lease: OwnerLease, input: {
1858
1949
  agentId: AgentId;
1859
1950
  input: UserInput;
@@ -1955,6 +2046,10 @@ declare class InMemoryStore implements DurableStore {
1955
2046
  consumerId: string;
1956
2047
  cursor: EventCursor;
1957
2048
  }): void;
2049
+ compact(lease: OwnerLease, input?: {
2050
+ now?: string;
2051
+ retentionMs?: number;
2052
+ }): RetentionResult;
1958
2053
  private replay;
1959
2054
  private writeReceipt;
1960
2055
  private replayOperation;
@@ -1971,7 +2066,8 @@ declare class InMemoryStore implements DurableStore {
1971
2066
  private nextReady;
1972
2067
  private nextMessageSequence;
1973
2068
  private messagesForRun;
1974
- private history;
2069
+ history(lease: OwnerLease, agentId: AgentId): readonly Message[];
2070
+ private activeHistory;
1975
2071
  private appendMessage;
1976
2072
  private appendTransition;
1977
2073
  private appendToolTransition;
@@ -1994,6 +2090,7 @@ declare class SqliteStore implements DurableStore {
1994
2090
  idempotencyKey: string;
1995
2091
  metadata?: Metadata;
1996
2092
  configIdentity?: string;
2093
+ historySeed?: HistorySeed;
1997
2094
  }): Promise<AgentRecord>;
1998
2095
  activateAgent(lease: OwnerLease, agentId: AgentId, configToken?: ConfigToken, configIdentity?: string): Promise<AgentRecord>;
1999
2096
  updateAgentConfigToken(lease: OwnerLease, input: {
@@ -2003,6 +2100,14 @@ declare class SqliteStore implements DurableStore {
2003
2100
  idempotencyKey: string;
2004
2101
  }): Promise<AgentRecord>;
2005
2102
  deleteAgent(lease: OwnerLease, input: AgentDeletionRequest): Promise<void>;
2103
+ reviseMessage(lease: OwnerLease, input: {
2104
+ agentId: AgentId;
2105
+ messageId: MessageId;
2106
+ expectedMessageRevision: number;
2107
+ content: UserContent;
2108
+ operationId: string;
2109
+ effectDigestConfirmation?: string;
2110
+ }): Promise<MessageRevisionResult>;
2006
2111
  createRun(lease: OwnerLease, input: {
2007
2112
  agentId: AgentId;
2008
2113
  input: UserInput;
@@ -2091,6 +2196,7 @@ declare class SqliteStore implements DurableStore {
2091
2196
  output?: AssistantMessage;
2092
2197
  }): Promise<RunRecord>;
2093
2198
  snapshotRun(lease: OwnerLease, runId: RunId): Promise<RunSnapshot>;
2199
+ history(lease: OwnerLease, agentId: AgentId): Promise<readonly Message[]>;
2094
2200
  listAgents(lease: OwnerLease): Promise<readonly AgentRecord[]>;
2095
2201
  listRuns(lease: OwnerLease, input?: {
2096
2202
  agentId?: AgentId;
@@ -2104,6 +2210,10 @@ declare class SqliteStore implements DurableStore {
2104
2210
  consumerId: string;
2105
2211
  cursor: EventCursor;
2106
2212
  }): Promise<void>;
2213
+ compact(lease: OwnerLease, input?: {
2214
+ now?: string;
2215
+ retentionMs?: number;
2216
+ }): Promise<RetentionResult>;
2107
2217
  renewOwner(lease: OwnerLease, leaseMs: number): Promise<OwnerLease>;
2108
2218
  sealAndReleaseOwner(lease: OwnerLease): Promise<void>;
2109
2219
  private invoke;
@@ -2142,7 +2252,7 @@ declare class InMemoryConfigProvider implements ConfigProvider {
2142
2252
  }
2143
2253
  declare function brandConfigToken(raw: unknown): ConfigToken;
2144
2254
 
2145
- type RuntimeErrorCode = "invalid_argument" | "runtime_closed" | "runtime_already_owned" | "runtime_ownership_lost" | "agent_not_found" | "run_not_found" | "run_state_conflict" | "input_request_conflict" | "idempotency_conflict" | "configuration_unavailable" | "checkpoint_incompatible" | "consumer_already_active" | "invalid_cursor" | "store_unavailable" | "unsupported_store_version";
2255
+ type RuntimeErrorCode = "invalid_argument" | "runtime_closed" | "runtime_already_owned" | "runtime_ownership_lost" | "agent_not_found" | "run_not_found" | "run_state_conflict" | "message_revision_conflict" | "tool_effect_confirmation_required" | "input_request_conflict" | "idempotency_conflict" | "configuration_unavailable" | "checkpoint_incompatible" | "consumer_already_active" | "invalid_cursor" | "store_unavailable" | "unsupported_store_version";
2146
2256
  type RuntimeErrorDetails = {
2147
2257
  invalid_argument: Readonly<{
2148
2258
  argument: string;
@@ -2170,6 +2280,18 @@ type RuntimeErrorDetails = {
2170
2280
  expected: readonly RunState[];
2171
2281
  actual: RunState;
2172
2282
  }>;
2283
+ message_revision_conflict: Readonly<{
2284
+ agentId: AgentId;
2285
+ messageId: MessageId;
2286
+ expected: number;
2287
+ actual: number;
2288
+ }>;
2289
+ tool_effect_confirmation_required: Readonly<{
2290
+ agentId: AgentId;
2291
+ messageId: MessageId;
2292
+ effectDigest: string;
2293
+ toolCallIds: readonly ToolCallId[];
2294
+ }>;
2173
2295
  input_request_conflict: Readonly<{
2174
2296
  runId: RunId;
2175
2297
  requestId: InputRequestId;
@@ -2201,7 +2323,7 @@ type RuntimeErrorDetails = {
2201
2323
  }>;
2202
2324
  invalid_cursor: Readonly<{
2203
2325
  cursorType: "agent_list" | "run_list" | "event";
2204
- reason: "malformed" | "wrong_store" | "wrong_collection" | "filter_mismatch" | "beyond_waterline";
2326
+ reason: "malformed" | "wrong_store" | "wrong_collection" | "filter_mismatch" | "beyond_waterline" | "expired";
2205
2327
  }>;
2206
2328
  store_unavailable: Readonly<{
2207
2329
  operation: string;
@@ -2277,4 +2399,4 @@ declare function parseFrontmatter<T = Record<string, unknown>>(raw: string): Fro
2277
2399
 
2278
2400
  declare function createCoreTools(input?: CoreToolContext): Tool[];
2279
2401
 
2280
- export { type AfterToolCall, type AgentConfig, type AgentConfigRequest, type AgentConfiguration, type AgentDefinition, type AgentId, type AgentListCursor, type AgentRecord, type AgentResources, type AgentRun, AgentRuntime, type AgentRuntimeOptions, type AgentSummary, type AnyRuntimeError, type AssistantContent, type AssistantMessage, type BeforeToolCall, type ConfigProvider, type ConfigPutResult, type ConfigResolution, type ConfigToken, type ConfigurationSnapshot, type ContextCandidate, type CoreToolContext, type DefinitionLayer, type DurableConsumer, type DurableRunEvent, type DurableStore, type DurableToolResult, type EventCursor, type EventId, type ExecutionCheckpoint, type ExecutionId, type ExecutionToken, type ExtensionAPI, type ExtensionActivationError, type ExtensionActivationResult, type ExtensionContribution, type ExtensionDisposer, type ExtensionFactory, type ExtensionFactoryResult, ExtensionLifetimeError, type ExtensionLifetimeErrorCode, type ExtensionLoadInput, type FrontmatterResult, type HookEvent, type HookEventType, type HookHandler, InMemoryConfigProvider, InMemoryStore, type InputRequest, type InputRequestId, type InputRequiredCommit, type JsonObject, type JsonPrimitive, type JsonValue, type LoadExtensionsResult, type LoadInput, type LoadResult, type LoadedExtension, type Message, type MessageBase, type MessageCommitted, type MessageContent, type MessageDelta, type MessageId, type Metadata, type OpaqueId, type Outcome, type OwnerLease, type OwnerToken, type Page, type Phase, type PhaseContext, type PhaseContribution, type PhaseExecutionIdentity, type PhaseInvocation, type PhaseOutput, type PhaseRegistry, type PhaseRegistrySelection, type PhaseState, type ResolvedResourceView, type ResourceDiagnostic, type ResourceKind, type ResourceRef, ResourceRegistry, ResourceRegistryError, type ResourceRegistryErrorCode, type ResourceSourceId, type ResourceView, type RunBoundary, type RunClaim, type RunEvent, type RunFailure, type RunId, type RunListCursor, type RunRecord, type RunSnapshot, type RunState, type RunStateChanged, type RunSummary, RuntimeBootstrapRegistry, RuntimeError, type RuntimeErrorCode, type RuntimeErrorDetails, RuntimeExtensionLifetime, type Skill, SqliteStore, type TextContent, type ThinkingContent, type Tool, type ToolCallId, type ToolCallSnapshot, type ToolCallState, type ToolContribution, type ToolDefinition, type ToolExecutionResult, type ToolInvocationContext, type ToolMessage, type ToolMessageContent, type ToolProgress, type ToolResultContent, type ToolStateChanged, type ToolUseContent, type UserContent, type UserInput, type UserMessage, brandConfigToken, createCoreTools, isRuntimeError, loadExtensionsFromPath as loadExtensions, loadPhase, loadPhases, loadSkill, loadSkills, materializeConfigurationSnapshot, parseAgentDefinition, parseFrontmatter, resolveConfigurationSnapshot };
2402
+ export { type AfterToolCall, type AgentConfig, type AgentConfigRequest, type AgentConfiguration, type AgentDefinition, type AgentId, type AgentListCursor, type AgentRecord, type AgentResources, type AgentRun, AgentRuntime, type AgentRuntimeOptions, type AgentSummary, type AnyRuntimeError, type AssistantContent, type AssistantMessage, type BeforeToolCall, type ConfigProvider, type ConfigPutResult, type ConfigResolution, type ConfigToken, type ConfigurationSnapshot, type ContextCandidate, type CoreToolContext, type DefinitionLayer, type DurableConsumer, type DurableRunEvent, type DurableStore, type DurableToolResult, type EventCursor, type EventId, type ExecutionCheckpoint, type ExecutionId, type ExecutionToken, type ExtensionAPI, type ExtensionActivationError, type ExtensionActivationResult, type ExtensionContribution, type ExtensionDisposer, type ExtensionFactory, type ExtensionFactoryResult, ExtensionLifetimeError, type ExtensionLifetimeErrorCode, type ExtensionLoadInput, type FrontmatterResult, type HistorySeed, type HookEvent, type HookEventType, type HookHandler, InMemoryConfigProvider, InMemoryStore, type InputRequest, type InputRequestId, type InputRequiredCommit, type JsonObject, type JsonPrimitive, type JsonValue, type LoadExtensionsResult, type LoadInput, type LoadResult, type LoadedExtension, type Message, type MessageBase, type MessageCommitted, type MessageContent, type MessageDelta, type MessageId, type MessageRevised, type MessageRevisionResult, type Metadata, type OpaqueId, type Outcome, type OwnerLease, type OwnerToken, type Page, type Phase, type PhaseContext, type PhaseContribution, type PhaseExecutionIdentity, type PhaseInvocation, type PhaseOutput, type PhaseRegistry, type PhaseRegistrySelection, type PhaseState, type ResolvedResourceView, type ResourceDiagnostic, type ResourceKind, type ResourceRef, ResourceRegistry, ResourceRegistryError, type ResourceRegistryErrorCode, type ResourceSourceId, type ResourceView, type RetentionResult, type RunBoundary, type RunClaim, type RunEvent, type RunFailure, type RunId, type RunListCursor, type RunRecord, type RunSnapshot, type RunState, type RunStateChanged, type RunSummary, RuntimeBootstrapRegistry, RuntimeError, type RuntimeErrorCode, type RuntimeErrorDetails, RuntimeExtensionLifetime, type Skill, SqliteStore, type TextContent, type ThinkingContent, type Tool, type ToolCallId, type ToolCallSnapshot, type ToolCallState, type ToolContribution, type ToolDefinition, type ToolExecutionResult, type ToolInvocationContext, type ToolMessage, type ToolMessageContent, type ToolProgress, type ToolResultContent, type ToolStateChanged, type ToolUseContent, type UserContent, type UserInput, type UserMessage, brandConfigToken, createCoreTools, isRuntimeError, loadExtensionsFromPath as loadExtensions, loadPhase, loadPhases, loadSkill, loadSkills, materializeConfigurationSnapshot, parseAgentDefinition, parseFrontmatter, resolveConfigurationSnapshot };
package/dist/index.js CHANGED
@@ -2895,7 +2895,7 @@ function normalizeUserInput(input) {
2895
2895
  return normalized;
2896
2896
  }
2897
2897
  function isAssistantMessage(value) {
2898
- return isRecord3(value) && hasOnlyKeys(value, ["id", "agentId", "runId", "role", "content", "metadata", "sequenceWithinRun", "createdAt", "interrupted"]) && typeof value.id === "string" && typeof value.agentId === "string" && typeof value.runId === "string" && value.role === "assistant" && Number.isInteger(value.sequenceWithinRun) && value.sequenceWithinRun >= 0 && typeof value.createdAt === "string" && isAssistantContent(value.content) && (value.metadata === void 0 || isMetadata(value.metadata)) && (value.interrupted === void 0 || typeof value.interrupted === "boolean");
2898
+ return isRecord3(value) && hasOnlyKeys(value, ["id", "agentId", "runId", "messageRevision", "role", "content", "metadata", "sequenceWithinRun", "createdAt", "interrupted"]) && typeof value.id === "string" && typeof value.agentId === "string" && typeof value.runId === "string" && value.role === "assistant" && (value.messageRevision === void 0 || Number.isInteger(value.messageRevision) && value.messageRevision >= 0) && Number.isInteger(value.sequenceWithinRun) && value.sequenceWithinRun >= 0 && typeof value.createdAt === "string" && isAssistantContent(value.content) && (value.metadata === void 0 || isMetadata(value.metadata)) && (value.interrupted === void 0 || typeof value.interrupted === "boolean");
2899
2899
  }
2900
2900
  function isToolResult(value) {
2901
2901
  if (!isRecord3(value) || !isJsonValue(value.content) || typeof value.ok !== "boolean") return false;
@@ -3193,6 +3193,7 @@ var ConfigCommandService = class {
3193
3193
  const reserved = await this.store.reserveAgent({
3194
3194
  idempotencyKey: input.idempotencyKey,
3195
3195
  ...input.metadata === void 0 ? {} : { metadata: input.metadata },
3196
+ ...input.historySeed === void 0 ? {} : { historySeed: input.historySeed },
3196
3197
  configIdentity: input.config.identity
3197
3198
  });
3198
3199
  if (reserved.activatedAt && reserved.currentConfigToken) return reserved.id;
@@ -5179,6 +5180,7 @@ var AgentRuntime = class _AgentRuntime {
5179
5180
  return this.commands.createAgent({
5180
5181
  config,
5181
5182
  ...options.metadata === void 0 ? {} : { metadata: options.metadata },
5183
+ ...options.historySeed === void 0 ? {} : { historySeed: options.historySeed },
5182
5184
  idempotencyKey: options.idempotencyKey ?? crypto.randomUUID()
5183
5185
  });
5184
5186
  }
@@ -5196,6 +5198,23 @@ var AgentRuntime = class _AgentRuntime {
5196
5198
  }
5197
5199
  await this.owned.deleteAgent(input);
5198
5200
  }
5201
+ async revise(agentId, input) {
5202
+ this.assertOpen();
5203
+ const result = await this.owned.reviseMessage({ agentId, ...input });
5204
+ for (const runId of result.invalidatedRunIds) {
5205
+ const execution = this.executions.get(runId);
5206
+ if (execution) {
5207
+ execution.controller.abort();
5208
+ this.transientEvents.clear(runId, execution.executionId);
5209
+ }
5210
+ }
5211
+ void this.pump();
5212
+ return result;
5213
+ }
5214
+ async compact(input = {}) {
5215
+ this.assertOpen();
5216
+ return this.owned.compact(input);
5217
+ }
5199
5218
  async start(agentId, input, options) {
5200
5219
  this.assertOpen();
5201
5220
  const agent = await this.requireAgent(agentId);
@@ -5249,6 +5268,10 @@ var AgentRuntime = class _AgentRuntime {
5249
5268
  this.assertOpen();
5250
5269
  return this.owned.snapshotRun(runId);
5251
5270
  }
5271
+ async history(agentId) {
5272
+ this.assertOpen();
5273
+ return this.owned.history(agentId);
5274
+ }
5252
5275
  async respond(runId, input) {
5253
5276
  this.assertOpen();
5254
5277
  const snapshot = await this.owned.snapshotRun(runId);
@@ -5793,6 +5816,7 @@ function deferred2() {
5793
5816
  }
5794
5817
 
5795
5818
  // src/runtime/durable-store.ts
5819
+ import { createHash } from "crypto";
5796
5820
  var InMemoryStore = class _InMemoryStore {
5797
5821
  incarnation;
5798
5822
  agents = /* @__PURE__ */ new Map();
@@ -5802,12 +5826,14 @@ var InMemoryStore = class _InMemoryStore {
5802
5826
  events = [];
5803
5827
  idempotency = /* @__PURE__ */ new Map();
5804
5828
  operationReceipts = /* @__PURE__ */ new Map();
5829
+ historySeeds = /* @__PURE__ */ new Map();
5805
5830
  consumerCheckpoints = /* @__PURE__ */ new Map();
5806
5831
  nextAgentSequence = /* @__PURE__ */ new Map();
5807
5832
  nextReadySequence = /* @__PURE__ */ new Map();
5808
5833
  owner;
5809
5834
  ownerEpoch = 0;
5810
5835
  eventSequence = 0;
5836
+ retentionFloor = 1;
5811
5837
  constructor(options = {}) {
5812
5838
  this.incarnation = options.incarnation ?? createId("store");
5813
5839
  }
@@ -5820,10 +5846,12 @@ var InMemoryStore = class _InMemoryStore {
5820
5846
  store.events.push(...clone(state.events));
5821
5847
  for (const [key, receipt] of state.idempotency) store.idempotency.set(key, clone(receipt));
5822
5848
  for (const [key, receipt] of state.operationReceipts) store.operationReceipts.set(key, clone(receipt));
5849
+ for (const [agentId, messages] of state.historySeeds ?? []) store.historySeeds.set(agentId, clone(messages));
5823
5850
  for (const [consumerId, cursor] of state.consumerCheckpoints ?? []) store.consumerCheckpoints.set(consumerId, cursor);
5824
5851
  for (const [agentId, sequence] of state.nextAgentSequence) store.nextAgentSequence.set(agentId, sequence);
5825
5852
  for (const [agentId, sequence] of state.nextReadySequence) store.nextReadySequence.set(agentId, sequence);
5826
5853
  store.eventSequence = state.eventSequence;
5854
+ store.retentionFloor = Math.max(1, state.retentionFloor ?? 1);
5827
5855
  store.ownerEpoch = Math.max(
5828
5856
  0,
5829
5857
  ...state.runs.map((run) => run.execution?.ownerEpoch ?? 0)
@@ -5840,7 +5868,9 @@ var InMemoryStore = class _InMemoryStore {
5840
5868
  events: this.events,
5841
5869
  idempotency: [...this.idempotency.entries()],
5842
5870
  operationReceipts: [...this.operationReceipts.entries()],
5871
+ historySeeds: [...this.historySeeds.entries()],
5843
5872
  consumerCheckpoints: [...this.consumerCheckpoints.entries()],
5873
+ retentionFloor: this.retentionFloor,
5844
5874
  nextAgentSequence: [...this.nextAgentSequence.entries()],
5845
5875
  nextReadySequence: [...this.nextReadySequence.entries()],
5846
5876
  eventSequence: this.eventSequence
@@ -5916,7 +5946,8 @@ var InMemoryStore = class _InMemoryStore {
5916
5946
  const scope = createIdempotencyScope("create_agent", input.idempotencyKey);
5917
5947
  const payload = canonicalJson({
5918
5948
  ...input.metadata === void 0 ? {} : { metadata: input.metadata },
5919
- ...input.configIdentity === void 0 ? {} : { configIdentity: input.configIdentity }
5949
+ ...input.configIdentity === void 0 ? {} : { configIdentity: input.configIdentity },
5950
+ ...input.historySeed === void 0 ? {} : { historySeed: input.historySeed }
5920
5951
  });
5921
5952
  const replay = this.replay(scope, payload);
5922
5953
  if (replay) return clone(replay);
@@ -5928,6 +5959,7 @@ var InMemoryStore = class _InMemoryStore {
5928
5959
  updatedAt: timestamp
5929
5960
  };
5930
5961
  this.agents.set(agent.id, agent);
5962
+ if (input.historySeed && input.historySeed.length > 0) this.historySeeds.set(agent.id, materializeHistorySeed(agent.id, input.historySeed));
5931
5963
  this.nextAgentSequence.set(agent.id, 0);
5932
5964
  this.nextReadySequence.set(agent.id, 0);
5933
5965
  this.writeReceipt(scope, payload, agent);
@@ -5975,6 +6007,7 @@ var InMemoryStore = class _InMemoryStore {
5975
6007
  this.agents.delete(agent.id);
5976
6008
  this.nextAgentSequence.delete(agent.id);
5977
6009
  this.nextReadySequence.delete(agent.id);
6010
+ this.historySeeds.delete(agent.id);
5978
6011
  for (const run of runs) this.runs.delete(run.id);
5979
6012
  for (const [messageId, message] of this.messages) {
5980
6013
  if (runIds.has(message.runId)) this.messages.delete(messageId);
@@ -5992,6 +6025,140 @@ var InMemoryStore = class _InMemoryStore {
5992
6025
  if (key.includes(String(agent.id)) || [...runIds].some((runId) => key.includes(String(runId)))) this.operationReceipts.delete(key);
5993
6026
  }
5994
6027
  }
6028
+ reviseMessage(lease, input) {
6029
+ this.assertOwner(lease);
6030
+ if (!Number.isInteger(input.expectedMessageRevision) || input.expectedMessageRevision < 0) {
6031
+ throw new TypeError("expectedMessageRevision must be a non-negative integer");
6032
+ }
6033
+ if (typeof input.operationId !== "string" || input.operationId.length === 0) throw new TypeError("operationId must be non-empty");
6034
+ const normalized = normalizeUserInput({ content: input.content });
6035
+ const operationKey = `revise_message:${input.agentId}:${input.operationId}`;
6036
+ const operationPayload = canonicalJson([
6037
+ input.messageId,
6038
+ input.expectedMessageRevision,
6039
+ normalized,
6040
+ input.effectDigestConfirmation ?? null
6041
+ ]);
6042
+ const replay = this.replayOperation(operationKey, operationPayload);
6043
+ if (replay) return clone(replay);
6044
+ const agent = this.requireAgent(input.agentId);
6045
+ const seed = this.historySeeds.get(agent.id) ?? [];
6046
+ const original = this.messages.get(input.messageId) ?? seed.find(({ id }) => id === input.messageId);
6047
+ if (!original || original.agentId !== agent.id || original.role !== "user") {
6048
+ throw new RuntimeError("message_revision_conflict", {
6049
+ agentId: agent.id,
6050
+ messageId: input.messageId,
6051
+ expected: input.expectedMessageRevision,
6052
+ actual: -1
6053
+ });
6054
+ }
6055
+ const actualRevision = original.messageRevision ?? 0;
6056
+ if (actualRevision !== input.expectedMessageRevision) {
6057
+ throw new RuntimeError("message_revision_conflict", {
6058
+ agentId: agent.id,
6059
+ messageId: input.messageId,
6060
+ expected: input.expectedMessageRevision,
6061
+ actual: actualRevision
6062
+ });
6063
+ }
6064
+ const targetRun = this.runs.get(original.runId);
6065
+ const isSeedMessage = !targetRun && seed.some(({ id }) => id === original.id);
6066
+ if (!targetRun && !isSeedMessage) {
6067
+ throw new RuntimeError("message_revision_conflict", {
6068
+ agentId: agent.id,
6069
+ messageId: input.messageId,
6070
+ expected: input.expectedMessageRevision,
6071
+ actual: actualRevision
6072
+ });
6073
+ }
6074
+ const targetAgentSequence = targetRun?.agentSequence ?? -1;
6075
+ const affectedRuns = [...this.runs.values()].filter((run) => run.agentId === agent.id && run.agentSequence >= targetAgentSequence).sort((left, right) => left.agentSequence - right.agentSequence);
6076
+ const affectedRunIds = affectedRuns.map((run) => run.id);
6077
+ const affectedRunSet = new Set(affectedRunIds);
6078
+ const affectedTools = [...this.toolCalls.values()].filter((toolCall) => affectedRunSet.has(toolCall.runId)).sort((left, right) => String(left.id).localeCompare(String(right.id)));
6079
+ const effectDigest = affectedTools.length > 0 ? digestToolEffects(affectedTools) : void 0;
6080
+ if (effectDigest && input.effectDigestConfirmation !== effectDigest) {
6081
+ throw new RuntimeError("tool_effect_confirmation_required", {
6082
+ agentId: agent.id,
6083
+ messageId: input.messageId,
6084
+ effectDigest,
6085
+ toolCallIds: affectedTools.map((toolCall) => toolCall.id)
6086
+ });
6087
+ }
6088
+ const timestamp = createTimestamp();
6089
+ const replacementRun = {
6090
+ id: createId("run"),
6091
+ agentId: agent.id,
6092
+ agentSequence: this.nextSequence(agent.id),
6093
+ readySequence: this.nextReady(agent.id),
6094
+ revision: 0,
6095
+ state: "queued",
6096
+ input: targetInput(normalized, original.metadata),
6097
+ initialMessageId: original.id,
6098
+ ...(targetRun?.pinnedConfigToken ?? this.agents.get(agent.id)?.currentConfigToken) === void 0 ? {} : { pinnedConfigToken: targetRun?.pinnedConfigToken ?? this.agents.get(agent.id)?.currentConfigToken },
6099
+ createdAt: timestamp,
6100
+ updatedAt: timestamp
6101
+ };
6102
+ for (const run of affectedRuns) {
6103
+ const previousState = run.state;
6104
+ run.invalidatedBy = { messageId: original.id, messageRevision: actualRevision + 1 };
6105
+ if (run.state === "running" || run.state === "queued" || run.state === "input_required") {
6106
+ if (run.state === "running") {
6107
+ const openToolCalls = [...this.toolCalls.values()].filter((toolCall) => toolCall.runId === run.id && toolCall.executionId === run.execution?.executionId && (toolCall.state === "pending" || toolCall.state === "running"));
6108
+ for (const toolCall of openToolCalls) this.interruptToolCall(run, toolCall, "Run superseded by Message revision.");
6109
+ } else {
6110
+ delete run.openInputRequest;
6111
+ delete run.checkpoint;
6112
+ }
6113
+ delete run.execution;
6114
+ run.state = "cancelled";
6115
+ run.cancellationReason = "Run superseded by Message revision.";
6116
+ run.revision += 1;
6117
+ run.updatedAt = timestamp;
6118
+ this.appendTransition(run, previousState, "cancelled", void 0, void 0, void 0, void 0, run.cancellationReason);
6119
+ } else {
6120
+ run.revision += 1;
6121
+ run.updatedAt = timestamp;
6122
+ }
6123
+ }
6124
+ for (const [messageId, message] of this.messages) {
6125
+ if (!affectedRunSet.has(message.runId)) continue;
6126
+ if (message.runId !== original.runId || message.sequenceWithinRun > original.sequenceWithinRun) this.messages.delete(messageId);
6127
+ }
6128
+ if (isSeedMessage) {
6129
+ const targetIndex = seed.findIndex(({ id }) => id === original.id);
6130
+ if (targetIndex >= 0) this.historySeeds.set(agent.id, seed.slice(0, targetIndex));
6131
+ }
6132
+ const revisedMessage = {
6133
+ ...clone(original),
6134
+ runId: replacementRun.id,
6135
+ content: userInputContent(normalized),
6136
+ messageRevision: actualRevision + 1,
6137
+ sequenceWithinRun: 0,
6138
+ createdAt: timestamp
6139
+ };
6140
+ this.messages.set(revisedMessage.id, revisedMessage);
6141
+ this.runs.set(replacementRun.id, replacementRun);
6142
+ this.appendTransition(replacementRun, null, "queued");
6143
+ this.events.push({
6144
+ ...this.baseEvent(replacementRun),
6145
+ kind: "message_revised",
6146
+ message: revisedMessage,
6147
+ previousRevision: actualRevision,
6148
+ invalidatedRunIds: affectedRunIds,
6149
+ targetRunId: original.runId,
6150
+ cutoffSequenceWithinRun: original.sequenceWithinRun
6151
+ });
6152
+ const result = {
6153
+ message: clone(revisedMessage),
6154
+ replacementRun: clone(replacementRun),
6155
+ invalidatedRunIds: affectedRunIds,
6156
+ affectedToolCallIds: affectedTools.map((toolCall) => toolCall.id),
6157
+ ...effectDigest === void 0 ? {} : { effectDigest }
6158
+ };
6159
+ this.writeOperationReceipt(operationKey, operationPayload, result);
6160
+ return clone(result);
6161
+ }
5995
6162
  createRun(lease, input) {
5996
6163
  this.assertOwner(lease);
5997
6164
  this.requireAgent(input.agentId);
@@ -6039,7 +6206,7 @@ var InMemoryStore = class _InMemoryStore {
6039
6206
  }
6040
6207
  if (!run.pinnedConfigToken && input.configToken) run.pinnedConfigToken = input.configToken;
6041
6208
  let message;
6042
- if (!run.checkpoint) {
6209
+ if (!run.checkpoint && !run.initialMessageId) {
6043
6210
  const userInput = normalizeUserInput(run.input);
6044
6211
  message = {
6045
6212
  id: input.messageId ?? createId("msg"),
@@ -6064,7 +6231,7 @@ var InMemoryStore = class _InMemoryStore {
6064
6231
  run.updatedAt = createTimestamp();
6065
6232
  if (message) this.appendMessage(run, message);
6066
6233
  this.appendTransition(run, "queued", "running");
6067
- const result = { run: clone(run), execution: clone(execution), history: this.history(run.agentId, run.agentSequence) };
6234
+ const result = { run: clone(run), execution: clone(execution), history: this.activeHistory(run.agentId, run.agentSequence) };
6068
6235
  this.writeOperationReceipt(operationKey, operationPayload, result);
6069
6236
  return result;
6070
6237
  }
@@ -6459,7 +6626,10 @@ var InMemoryStore = class _InMemoryStore {
6459
6626
  }
6460
6627
  listEvents(lease, input = {}) {
6461
6628
  this.assertOwner(lease);
6462
- const after = input.after ? this.parseCursor(input.after) : 0;
6629
+ const after = input.after ? this.parseCursor(input.after) : this.retentionFloor - 1;
6630
+ if (input.after && after < this.retentionFloor - 1) {
6631
+ throw new RuntimeError("invalid_cursor", { cursorType: "event", reason: "expired" });
6632
+ }
6463
6633
  if (after > this.eventSequence) {
6464
6634
  throw new RuntimeError("invalid_cursor", { cursorType: "event", reason: "beyond_waterline" });
6465
6635
  }
@@ -6476,11 +6646,72 @@ var InMemoryStore = class _InMemoryStore {
6476
6646
  advanceConsumerCheckpoint(lease, input) {
6477
6647
  this.assertOwner(lease);
6478
6648
  const next = this.parseCursor(input.cursor);
6649
+ if (next < this.retentionFloor - 1) {
6650
+ throw new RuntimeError("invalid_cursor", { cursorType: "event", reason: "expired" });
6651
+ }
6479
6652
  if (next > this.eventSequence) throw new RuntimeError("invalid_cursor", { cursorType: "event", reason: "beyond_waterline" });
6480
6653
  const previous = this.consumerCheckpoints.get(input.consumerId);
6481
6654
  if (previous !== void 0 && next <= this.parseCursor(previous)) return;
6482
6655
  this.consumerCheckpoints.set(input.consumerId, input.cursor);
6483
6656
  }
6657
+ compact(lease, input = {}) {
6658
+ this.assertOwner(lease);
6659
+ const retentionMs = input.retentionMs ?? 7 * 24 * 60 * 60 * 1e3;
6660
+ if (!Number.isFinite(retentionMs) || retentionMs < 0) {
6661
+ throw new TypeError("retentionMs must be a non-negative finite number");
6662
+ }
6663
+ const now = input.now === void 0 ? Date.now() : Date.parse(input.now);
6664
+ if (!Number.isFinite(now)) throw new TypeError("now must be an ISO timestamp");
6665
+ const cutoff = now - retentionMs;
6666
+ const checkpointSequences = [...this.consumerCheckpoints.values()].map((cursor) => this.parseCursor(cursor));
6667
+ const consumerFloor = checkpointSequences.length > 0 ? Math.min(...checkpointSequences) : this.eventSequence;
6668
+ const blockedRunIds = /* @__PURE__ */ new Set();
6669
+ for (const run of this.runs.values()) {
6670
+ if (run.state === "running") blockedRunIds.add(run.id);
6671
+ }
6672
+ for (const tool of this.toolCalls.values()) {
6673
+ if (tool.state === "pending" || tool.state === "running" || tool.state === "indeterminate") {
6674
+ blockedRunIds.add(tool.runId);
6675
+ }
6676
+ }
6677
+ let deleteThrough = this.retentionFloor - 1;
6678
+ for (const event of this.events) {
6679
+ const sequence = this.parseCursor(event.cursor);
6680
+ if (sequence < this.retentionFloor) continue;
6681
+ if (sequence > consumerFloor) break;
6682
+ if (Date.parse(event.createdAt) > cutoff || blockedRunIds.has(event.runId)) break;
6683
+ const eventRun = this.runs.get(event.runId);
6684
+ if (!eventRun || eventRun.invalidatedBy === void 0 || !["completed", "failed", "cancelled"].includes(eventRun.state) || Date.parse(eventRun.updatedAt) > cutoff) break;
6685
+ deleteThrough = sequence;
6686
+ }
6687
+ const deletedEvents = deleteThrough >= this.retentionFloor ? this.events.filter((event) => this.parseCursor(event.cursor) <= deleteThrough) : [];
6688
+ if (deleteThrough >= this.retentionFloor) {
6689
+ this.events.splice(0, this.events.length, ...this.events.filter((event) => this.parseCursor(event.cursor) > deleteThrough));
6690
+ this.retentionFloor = deleteThrough + 1;
6691
+ for (const [consumerId, cursor] of this.consumerCheckpoints) {
6692
+ if (this.parseCursor(cursor) < this.retentionFloor - 1) {
6693
+ this.consumerCheckpoints.delete(consumerId);
6694
+ }
6695
+ }
6696
+ }
6697
+ const activeMessageRunIds = new Set([...this.messages.values()].map((message) => message.runId));
6698
+ const deletableRuns = [...this.runs.values()].filter((run) => run.invalidatedBy !== void 0 && ["completed", "failed", "cancelled"].includes(run.state) && Date.parse(run.updatedAt) <= cutoff && !activeMessageRunIds.has(run.id) && !blockedRunIds.has(run.id) && this.events.filter((event) => event.runId === run.id).every((event) => this.parseCursor(event.cursor) <= consumerFloor && Date.parse(event.createdAt) <= cutoff));
6699
+ const deletedRunIds = deletableRuns.map((run) => run.id);
6700
+ const deletedRunSet = new Set(deletedRunIds);
6701
+ const deletedTools = [...this.toolCalls.values()].filter((tool) => deletedRunSet.has(tool.runId));
6702
+ for (const runId of deletedRunIds) this.runs.delete(runId);
6703
+ for (const [messageId, message] of this.messages) {
6704
+ if (deletedRunSet.has(message.runId)) this.messages.delete(messageId);
6705
+ }
6706
+ for (const tool of deletedTools) this.toolCalls.delete(tool.id);
6707
+ return {
6708
+ deletedRunIds,
6709
+ deletedToolCallIds: deletedTools.map((tool) => tool.id),
6710
+ deletedEventCount: deletedEvents.length,
6711
+ retentionFloor: `${this.incarnation}:${this.retentionFloor}`,
6712
+ ...deletedRunIds.length === 0 && deletedEvents.length === 0 ? { skipped: "no_eligible_events" } : {}
6713
+ };
6714
+ }
6484
6715
  replay(scope, payload) {
6485
6716
  const key = encodeIdempotencyScope(this.incarnation, scope);
6486
6717
  const receipt = this.idempotency.get(key);
@@ -6578,8 +6809,16 @@ var InMemoryStore = class _InMemoryStore {
6578
6809
  messagesForRun(runId) {
6579
6810
  return [...this.messages.values()].filter((message) => message.runId === runId).sort((a, b) => a.sequenceWithinRun - b.sequenceWithinRun);
6580
6811
  }
6581
- history(agentId, beforeSequence) {
6582
- return clone([...this.runs.values()].filter((run) => run.agentId === agentId && run.agentSequence <= beforeSequence).sort((a, b) => a.agentSequence - b.agentSequence).flatMap((run) => this.messagesForRun(run.id)));
6812
+ history(lease, agentId) {
6813
+ this.assertOwner(lease);
6814
+ this.requireAgent(agentId);
6815
+ return this.activeHistory(agentId, Number.MAX_SAFE_INTEGER);
6816
+ }
6817
+ activeHistory(agentId, beforeSequence) {
6818
+ return clone([
6819
+ ...this.historySeeds.get(agentId) ?? [],
6820
+ ...[...this.runs.values()].filter((run) => run.agentId === agentId && run.agentSequence <= beforeSequence).sort((a, b) => a.agentSequence - b.agentSequence).flatMap((run) => this.messagesForRun(run.id))
6821
+ ].map((message) => ({ ...message, messageRevision: message.messageRevision ?? 0 })));
6583
6822
  }
6584
6823
  appendMessage(run, message) {
6585
6824
  this.events.push(this.baseEvent(run, {
@@ -6650,6 +6889,12 @@ var MemoryOwnedStore = class {
6650
6889
  async deleteAgent(input) {
6651
6890
  this.store.deleteAgent(this.lease, input);
6652
6891
  }
6892
+ async reviseMessage(input) {
6893
+ return this.store.reviseMessage(this.lease, input);
6894
+ }
6895
+ async compact(input) {
6896
+ return this.store.compact(this.lease, input);
6897
+ }
6653
6898
  async createRun(input) {
6654
6899
  return this.store.createRun(this.lease, input);
6655
6900
  }
@@ -6686,6 +6931,9 @@ var MemoryOwnedStore = class {
6686
6931
  async snapshotRun(runId) {
6687
6932
  return this.store.snapshotRun(this.lease, runId);
6688
6933
  }
6934
+ async history(agentId) {
6935
+ return this.store.history(this.lease, agentId);
6936
+ }
6689
6937
  async listAgents() {
6690
6938
  return this.store.listAgents(this.lease);
6691
6939
  }
@@ -6733,6 +6981,41 @@ function userInputContent(input) {
6733
6981
  function userInputMetadata(input) {
6734
6982
  return typeof input === "string" ? void 0 : input.metadata;
6735
6983
  }
6984
+ function targetInput(input, metadata) {
6985
+ const content = typeof input === "string" ? input : input.content;
6986
+ return metadata === void 0 ? { content } : { content, metadata: clone(metadata) };
6987
+ }
6988
+ function materializeHistorySeed(agentId, source) {
6989
+ const seedRunId = createId("seed");
6990
+ const toolIds = /* @__PURE__ */ new Map();
6991
+ return source.map((message, sequenceWithinRun) => {
6992
+ const content = remapSeedContent(message.content, toolIds);
6993
+ return {
6994
+ ...clone(message),
6995
+ id: createId("msg"),
6996
+ agentId,
6997
+ runId: seedRunId,
6998
+ content,
6999
+ messageRevision: message.messageRevision ?? 0,
7000
+ sequenceWithinRun,
7001
+ createdAt: createTimestamp()
7002
+ };
7003
+ });
7004
+ }
7005
+ function remapSeedContent(content, toolIds) {
7006
+ if (typeof content === "string") return content;
7007
+ return content.map((part) => {
7008
+ if (part.type === "tool_use" || part.type === "tool_result") {
7009
+ const toolCallId = toolIds.get(part.toolCallId) ?? createId("tool");
7010
+ toolIds.set(part.toolCallId, toolCallId);
7011
+ return part.type === "tool_result" ? { ...part, toolCallId, result: clone(part.result) } : { ...part, toolCallId };
7012
+ }
7013
+ return clone(part);
7014
+ });
7015
+ }
7016
+ function digestToolEffects(toolCalls) {
7017
+ return createHash("sha256").update(canonicalJson(toolCalls)).digest("hex");
7018
+ }
6736
7019
  function assertToolValue(value, argument) {
6737
7020
  assertUtf8ByteLimit(canonicalJson(value), TOOL_VALUE_JSON_BYTES, argument);
6738
7021
  }
@@ -6740,8 +7023,9 @@ function assertToolValue(value, argument) {
6740
7023
  // src/runtime/sqlite-durable-store.ts
6741
7024
  import { Database } from "bun:sqlite";
6742
7025
  var SCHEMA_ID = "rowan.agent.runtime";
6743
- var SCHEMA_VERSION = "1";
7026
+ var SCHEMA_VERSION = "2";
6744
7027
  var SCHEMA_VALUE = `${SCHEMA_ID}:${SCHEMA_VERSION}`;
7028
+ var RETENTION_FLOOR_KEY = "retention_floor";
6745
7029
  var STATE_ROW = 1;
6746
7030
  var CURRENT_TABLES = /* @__PURE__ */ new Set([
6747
7031
  "runtime_meta",
@@ -6909,6 +7193,9 @@ var SqliteStore = class {
6909
7193
  async deleteAgent(lease, input) {
6910
7194
  return this.invoke(lease, (store, current) => store.deleteAgent(current, input));
6911
7195
  }
7196
+ async reviseMessage(lease, input) {
7197
+ return this.invoke(lease, (store, current) => store.reviseMessage(current, input));
7198
+ }
6912
7199
  async createRun(lease, input) {
6913
7200
  return this.invoke(lease, (store, current) => store.createRun(current, input));
6914
7201
  }
@@ -6945,6 +7232,9 @@ var SqliteStore = class {
6945
7232
  async snapshotRun(lease, runId) {
6946
7233
  return this.invoke(lease, (store, current) => store.snapshotRun(current, runId), false);
6947
7234
  }
7235
+ async history(lease, agentId) {
7236
+ return this.invoke(lease, (store, current) => store.history(current, agentId), false);
7237
+ }
6948
7238
  async listAgents(lease) {
6949
7239
  return this.invoke(lease, (store, current) => store.listAgents(current), false);
6950
7240
  }
@@ -6955,15 +7245,19 @@ var SqliteStore = class {
6955
7245
  this.assertOpen();
6956
7246
  return this.readTransaction(() => {
6957
7247
  this.requireMatchingOwner(lease, true);
6958
- const after = input.after ? parseEventCursor(lease, input.after) : 0;
7248
+ const retentionRow = this.database.query(
7249
+ "SELECT value FROM runtime_meta WHERE key = ?"
7250
+ ).get(RETENTION_FLOOR_KEY);
7251
+ const retentionFloor = Math.max(1, Number(retentionRow?.value ?? "1"));
7252
+ const after = input.after ? parseEventCursor(lease, input.after) : retentionFloor - 1;
7253
+ if (input.after && after < retentionFloor - 1) {
7254
+ throw new RuntimeError("invalid_cursor", { cursorType: "event", reason: "expired" });
7255
+ }
6959
7256
  if (input.after) {
6960
7257
  const latest = this.database.query(
6961
- "SELECT payload_json FROM run_events ORDER BY sequence DESC LIMIT 1"
7258
+ "SELECT max(sequence) AS sequence FROM run_events"
6962
7259
  ).get();
6963
- const waterline = latest ? parseEventCursor(
6964
- lease,
6965
- JSON.parse(latest.payload_json).cursor
6966
- ) : 0;
7260
+ const waterline = latest.sequence ?? 0;
6967
7261
  if (after > waterline) {
6968
7262
  throw new RuntimeError("invalid_cursor", { cursorType: "event", reason: "beyond_waterline" });
6969
7263
  }
@@ -6981,6 +7275,15 @@ var SqliteStore = class {
6981
7275
  async advanceConsumerCheckpoint(lease, input) {
6982
7276
  return this.invoke(lease, (store, current) => store.advanceConsumerCheckpoint(current, input));
6983
7277
  }
7278
+ async compact(lease, input = {}) {
7279
+ this.assertOpen();
7280
+ const result = this.invoke(lease, (store, current) => store.compact(current, input));
7281
+ if (result.deletedEventCount > 0 || result.deletedRunIds.length > 0) {
7282
+ this.database.run("PRAGMA wal_checkpoint(PASSIVE)");
7283
+ this.database.run("PRAGMA incremental_vacuum");
7284
+ }
7285
+ return result;
7286
+ }
6984
7287
  async renewOwner(lease, leaseMs) {
6985
7288
  this.assertOpen();
6986
7289
  assertOwnerInput(lease.ownerId, leaseMs);
@@ -7033,6 +7336,7 @@ var SqliteStore = class {
7033
7336
  if (sql) this.database.run(sql);
7034
7337
  }
7035
7338
  this.database.run("INSERT INTO runtime_meta (key, value) VALUES (?, ?)", ["schema_version", SCHEMA_VALUE]);
7339
+ this.database.run("INSERT INTO runtime_meta (key, value) VALUES (?, ?)", [RETENTION_FLOOR_KEY, "1"]);
7036
7340
  const state = new InMemoryStore();
7037
7341
  this.database.run("INSERT INTO runtime_owner (singleton, epoch) VALUES (?, ?)", [STATE_ROW, 0]);
7038
7342
  this.database.run("INSERT INTO runtime_state (singleton, state_json) VALUES (?, ?)", [STATE_ROW, JSON.stringify(state.exportState())]);
@@ -7081,6 +7385,10 @@ var SqliteStore = class {
7081
7385
  }
7082
7386
  persistState(state) {
7083
7387
  this.writeState(state);
7388
+ this.database.run(
7389
+ "INSERT INTO runtime_meta (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value",
7390
+ [RETENTION_FLOOR_KEY, String(Math.max(1, state.retentionFloor ?? 1))]
7391
+ );
7084
7392
  for (const table of ["consumer_checkpoints", "idempotency", "run_events", "messages", "input_requests", "tool_calls", "runs", "agents"]) {
7085
7393
  this.database.run(`DELETE FROM ${table}`);
7086
7394
  }
@@ -7199,6 +7507,12 @@ var SqliteOwnedStore = class {
7199
7507
  deleteAgent(input) {
7200
7508
  return this.store.deleteAgent(this.lease, input);
7201
7509
  }
7510
+ reviseMessage(input) {
7511
+ return this.store.reviseMessage(this.lease, input);
7512
+ }
7513
+ compact(input) {
7514
+ return this.store.compact(this.lease, input);
7515
+ }
7202
7516
  createRun(input) {
7203
7517
  return this.store.createRun(this.lease, input);
7204
7518
  }
@@ -7235,6 +7549,9 @@ var SqliteOwnedStore = class {
7235
7549
  snapshotRun(runId) {
7236
7550
  return this.store.snapshotRun(this.lease, runId);
7237
7551
  }
7552
+ history(agentId) {
7553
+ return this.store.history(this.lease, agentId);
7554
+ }
7238
7555
  listAgents() {
7239
7556
  return this.store.listAgents(this.lease);
7240
7557
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rowan-agent/agent",
3
- "version": "0.9.3",
3
+ "version": "0.9.4",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",