@slopus/happy-agent-base 0.0.5 → 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.
Files changed (92) hide show
  1. package/README.md +62 -9
  2. package/dist/Agent.d.ts +27 -22
  3. package/dist/Agent.d.ts.map +1 -1
  4. package/dist/Agent.js +120 -110
  5. package/dist/Agent.js.map +1 -1
  6. package/dist/AgentBase.d.ts +27 -13
  7. package/dist/AgentBase.d.ts.map +1 -1
  8. package/dist/AgentBase.js +657 -151
  9. package/dist/AgentBase.js.map +1 -1
  10. package/dist/AgentBaseHooks.d.ts +58 -32
  11. package/dist/AgentBaseHooks.d.ts.map +1 -1
  12. package/dist/AgentBasePending.d.ts +6 -2
  13. package/dist/AgentBasePending.d.ts.map +1 -1
  14. package/dist/AgentBasePending.js +7 -0
  15. package/dist/AgentBasePending.js.map +1 -1
  16. package/dist/AgentConfig.d.ts +20 -13
  17. package/dist/AgentConfig.d.ts.map +1 -1
  18. package/dist/AgentConfig.js +32 -12
  19. package/dist/AgentConfig.js.map +1 -1
  20. package/dist/AgentContexts.d.ts +18 -1
  21. package/dist/AgentContexts.d.ts.map +1 -1
  22. package/dist/AgentContexts.js +24 -1
  23. package/dist/AgentContexts.js.map +1 -1
  24. package/dist/AgentDatabase.d.ts +35 -0
  25. package/dist/AgentDatabase.d.ts.map +1 -0
  26. package/dist/AgentDatabase.js +30 -0
  27. package/dist/AgentDatabase.js.map +1 -0
  28. package/dist/AgentKV.d.ts +19 -6
  29. package/dist/AgentKV.d.ts.map +1 -1
  30. package/dist/AgentKV.js +110 -43
  31. package/dist/AgentKV.js.map +1 -1
  32. package/dist/AgentMessageAcceptance.d.ts +14 -0
  33. package/dist/AgentMessageAcceptance.d.ts.map +1 -0
  34. package/dist/AgentMessageAcceptance.js +2 -0
  35. package/dist/AgentMessageAcceptance.js.map +1 -0
  36. package/dist/AgentMetadata.d.ts +37 -0
  37. package/dist/AgentMetadata.d.ts.map +1 -0
  38. package/dist/AgentMetadata.js +74 -0
  39. package/dist/AgentMetadata.js.map +1 -0
  40. package/dist/AgentModule.d.ts +209 -0
  41. package/dist/AgentModule.d.ts.map +1 -0
  42. package/dist/AgentModule.js +2 -0
  43. package/dist/AgentModule.js.map +1 -0
  44. package/dist/{AgentFeatureAction.d.ts → AgentModuleAction.d.ts} +7 -2
  45. package/dist/AgentModuleAction.d.ts.map +1 -0
  46. package/dist/AgentModuleAction.js +2 -0
  47. package/dist/AgentModuleAction.js.map +1 -0
  48. package/dist/AgentPermissionMode.d.ts +1 -1
  49. package/dist/AgentPermissionMode.js +1 -1
  50. package/dist/AgentPersistence.d.ts +20 -7
  51. package/dist/AgentPersistence.d.ts.map +1 -1
  52. package/dist/AgentPersistenceDrizzle.d.ts +31 -0
  53. package/dist/AgentPersistenceDrizzle.d.ts.map +1 -0
  54. package/dist/AgentPersistenceDrizzle.js +99 -0
  55. package/dist/AgentPersistenceDrizzle.js.map +1 -0
  56. package/dist/AgentRef.d.ts +17 -9
  57. package/dist/AgentRef.d.ts.map +1 -1
  58. package/dist/AgentRef.js +16 -9
  59. package/dist/AgentRef.js.map +1 -1
  60. package/dist/AgentStorage.d.ts +33 -13
  61. package/dist/AgentStorage.d.ts.map +1 -1
  62. package/dist/AgentStorage.js +174 -3
  63. package/dist/AgentStorage.js.map +1 -1
  64. package/dist/AgentSystem.d.ts +34 -12
  65. package/dist/AgentSystem.d.ts.map +1 -1
  66. package/dist/AgentSystemContext.d.ts +3 -3
  67. package/dist/AgentSystemContext.d.ts.map +1 -1
  68. package/dist/AgentSystemContext.js +4 -4
  69. package/dist/AgentSystemContext.js.map +1 -1
  70. package/dist/AgentSystemLocal.d.ts +30 -21
  71. package/dist/AgentSystemLocal.d.ts.map +1 -1
  72. package/dist/AgentSystemLocal.js +226 -59
  73. package/dist/AgentSystemLocal.js.map +1 -1
  74. package/dist/AgentSystemRef.d.ts +21 -10
  75. package/dist/AgentSystemRef.d.ts.map +1 -1
  76. package/dist/AgentSystemRef.js +41 -9
  77. package/dist/AgentSystemRef.js.map +1 -1
  78. package/dist/AgentTool.d.ts +16 -1
  79. package/dist/AgentTool.d.ts.map +1 -1
  80. package/dist/AgentTool.js.map +1 -1
  81. package/dist/index.d.ts +10 -7
  82. package/dist/index.d.ts.map +1 -1
  83. package/dist/index.js +9 -6
  84. package/dist/index.js.map +1 -1
  85. package/package.json +4 -3
  86. package/dist/AgentFeature.d.ts +0 -177
  87. package/dist/AgentFeature.d.ts.map +0 -1
  88. package/dist/AgentFeature.js +0 -2
  89. package/dist/AgentFeature.js.map +0 -1
  90. package/dist/AgentFeatureAction.d.ts.map +0 -1
  91. package/dist/AgentFeatureAction.js +0 -2
  92. package/dist/AgentFeatureAction.js.map +0 -1
@@ -1,16 +1,21 @@
1
1
  import type { SessionUserMessage } from "@slopus/happy-providers";
2
+ import type { AgentMessageMetadata } from "./AgentMetadata.js";
2
3
  /**
3
4
  * What a lifecycle hook can ask the agent to do next: queue a steering or sent message through
4
5
  * the ordinary durable queues, or trigger a compaction. An action drives the loop exactly like
5
6
  * an external call to `steer`, `send`, or `compact` would.
6
7
  */
7
- export type AgentFeatureAction = {
8
+ export type AgentModuleAction = {
8
9
  readonly type: "steer";
10
+ readonly id?: string;
9
11
  readonly message: SessionUserMessage;
12
+ readonly metadata?: AgentMessageMetadata;
10
13
  } | {
11
14
  readonly type: "send";
15
+ readonly id?: string;
12
16
  readonly message: SessionUserMessage;
17
+ readonly metadata?: AgentMessageMetadata;
13
18
  } | {
14
19
  readonly type: "compact";
15
20
  };
16
- //# sourceMappingURL=AgentFeatureAction.d.ts.map
21
+ //# sourceMappingURL=AgentModuleAction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AgentModuleAction.d.ts","sourceRoot":"","sources":["../sources/AgentModuleAction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAElE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE/D;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GACvB;IACI,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,oBAAoB,CAAC;CAC5C,GACD;IACI,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,oBAAoB,CAAC;CAC5C,GACD;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=AgentModuleAction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AgentModuleAction.js","sourceRoot":"","sources":["../sources/AgentModuleAction.ts"],"names":[],"mappings":""}
@@ -5,7 +5,7 @@ import { type Static } from "@sinclair/typebox";
5
5
  * The mode is part of what an agent is running on, exactly like its model: it is carried on every
6
6
  * context the agent derives, it is durable, and a message may change it. What the runtime does not
7
7
  * do is enforce it — the loop has no idea what any particular tool touches. Enforcement belongs to
8
- * the features and tools that know, and they read the mode in force from the context they are
8
+ * the modules and tools that know, and they read the mode in force from the context they are
9
9
  * given.
10
10
  */
11
11
  export declare const agentPermissionModeSchema: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"read_only">, import("@sinclair/typebox").TLiteral<"workspace_write">, import("@sinclair/typebox").TLiteral<"auto">, import("@sinclair/typebox").TLiteral<"full_access">]>;
@@ -6,7 +6,7 @@ import { Value } from "@sinclair/typebox/value";
6
6
  * The mode is part of what an agent is running on, exactly like its model: it is carried on every
7
7
  * context the agent derives, it is durable, and a message may change it. What the runtime does not
8
8
  * do is enforce it — the loop has no idea what any particular tool touches. Enforcement belongs to
9
- * the features and tools that know, and they read the mode in force from the context they are
9
+ * the modules and tools that know, and they read the mode in force from the context they are
10
10
  * given.
11
11
  */
12
12
  export const agentPermissionModeSchema = Type.Union([
@@ -1,5 +1,7 @@
1
1
  import type { SessionAssistantBlock, SessionMessage, SessionSystemMessage, SessionToolResultMessage, SessionUserMessage } from "@slopus/happy-providers";
2
2
  import type { Context } from "@steve.kite/stdlib";
3
+ import type { AgentDatabase } from "./AgentDatabase.js";
4
+ import type { AgentMessageMetadata } from "./AgentMetadata.js";
3
5
  /**
4
6
  * One record of the main context store. Only content that is part of the model context lives
5
7
  * here: user messages enter when a turn consumes them, assistant output is appended one finished
@@ -11,7 +13,9 @@ import type { Context } from "@steve.kite/stdlib";
11
13
  */
12
14
  export type AgentRecord = {
13
15
  readonly type: "user";
16
+ readonly id: string;
14
17
  readonly message: SessionUserMessage;
18
+ readonly metadata?: AgentMessageMetadata;
15
19
  } | {
16
20
  readonly type: "block";
17
21
  readonly block: SessionAssistantBlock;
@@ -29,17 +33,21 @@ export type AgentRecord = {
29
33
  * Storage for one agent: an append-only main context store plus a sorted key-value store held
30
34
  * alongside it. A sent message is first written under a `pending.` key ordered by append time;
31
35
  * it reaches the main store only when a turn consumes it into the context, and its pending key
32
- * is deleted at that moment. Exactly one owner connects to a store, and the agent serializes its
33
- * own record and bookkeeping writes through one lock, so history order always matches storage
34
- * order. Key-value operations a feature's or a tool's run as they come, so each one has to be
35
- * atomic on its own, but no implementation ever has to defend against a second owner.
36
+ * is deleted at that moment. A `message.` uniqueness key makes retrying a cuid2 message ID an
37
+ * ignored database conflict; history replacement removes keys for the records it deletes.
38
+ * Exactly one owner connects to a store, and the agent serializes its own record and bookkeeping
39
+ * writes through one lock, so history order always matches storage order. Key-value operations
40
+ * a module's or a tool's — run as they come, so each one has to be atomic on its own, but no
41
+ * implementation ever has to defend against a second owner.
36
42
  */
37
43
  export interface AgentPersistence {
44
+ /** The root Drizzle facade for this store. */
45
+ readonly database: AgentDatabase;
38
46
  /**
39
47
  * Run work atomically. The implementation opens a transaction and passes work a derived
40
- * context that its own operations recognize; how the transaction rides on that context is
41
- * entirely the implementation's business. Work resolving commits every operation; a thrown
42
- * error rolls them all back.
48
+ * context that its own operations recognize and that carries stdlib's universal
49
+ * `afterCommit` scope. Work resolving commits every operation and then drains that scope; a
50
+ * thrown error rolls everything back without draining it.
43
51
  */
44
52
  transaction<Result>(ctx: Context, work: (ctx: Context) => Promise<Result>): Promise<Result>;
45
53
  /** Every record in the main context store, in append order. */
@@ -59,6 +67,11 @@ export interface AgentPersistence {
59
67
  }[]>;
60
68
  /** Store the value under `key`, replacing whatever was there before. */
61
69
  writeValue(ctx: Context, key: string, value: unknown): Promise<void>;
70
+ /**
71
+ * Store the value only when `key` is absent. Returns false for the database uniqueness
72
+ * conflict without changing the existing value.
73
+ */
74
+ writeValueIfAbsent(ctx: Context, key: string, value: unknown): Promise<boolean>;
62
75
  /** Remove the entry stored under `key`, if any. */
63
76
  deleteValue(ctx: Context, key: string): Promise<void>;
64
77
  }
@@ -1 +1 @@
1
- {"version":3,"file":"AgentPersistence.d.ts","sourceRoot":"","sources":["../sources/AgentPersistence.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACR,qBAAqB,EACrB,cAAc,EACd,oBAAoB,EACpB,wBAAwB,EACxB,kBAAkB,EACrB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAElD;;;;;;;;GAQG;AACH,MAAM,MAAM,WAAW,GACjB;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAA;CAAE,GAC/D;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,qBAAqB,CAAA;CAAE,GACjE;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,wBAAwB,CAAA;CAAE,GACrE;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,oBAAoB,CAAA;CAAE,GACnE;IACI,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,SAAS,cAAc,EAAE,CAAC;CAChD,CAAC;AAER;;;;;;;;GAQG;AACH,MAAM,WAAW,gBAAgB;IAC7B;;;;;OAKG;IACH,WAAW,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5F,+DAA+D;IAC/D,IAAI,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,SAAS,WAAW,EAAE,CAAC,CAAC;IACpD,gEAAgE;IAChE,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD;;;;OAIG;IACH,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,0EAA0E;IAC1E,UAAU,CACN,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,MAAM,GACf,OAAO,CAAC,SAAS;QAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC,CAAC;IACzE,wEAAwE;IACxE,UAAU,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrE,mDAAmD;IACnD,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACzD"}
1
+ {"version":3,"file":"AgentPersistence.d.ts","sourceRoot":"","sources":["../sources/AgentPersistence.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACR,qBAAqB,EACrB,cAAc,EACd,oBAAoB,EACpB,wBAAwB,EACxB,kBAAkB,EACrB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE/D;;;;;;;;GAQG;AACH,MAAM,MAAM,WAAW,GACjB;IACI,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,oBAAoB,CAAC;CAC5C,GACD;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,qBAAqB,CAAA;CAAE,GACjE;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,wBAAwB,CAAA;CAAE,GACrE;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,oBAAoB,CAAA;CAAE,GACnE;IACI,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,SAAS,cAAc,EAAE,CAAC;CAChD,CAAC;AAER;;;;;;;;;;GAUG;AACH,MAAM,WAAW,gBAAgB;IAC7B,8CAA8C;IAC9C,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;IACjC;;;;;OAKG;IACH,WAAW,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5F,+DAA+D;IAC/D,IAAI,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,SAAS,WAAW,EAAE,CAAC,CAAC;IACpD,gEAAgE;IAChE,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD;;;;OAIG;IACH,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,0EAA0E;IAC1E,UAAU,CACN,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,MAAM,GACf,OAAO,CAAC,SAAS;QAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC,CAAC;IACzE,wEAAwE;IACxE,UAAU,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrE;;;OAGG;IACH,kBAAkB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAChF,mDAAmD;IACnD,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACzD"}
@@ -0,0 +1,31 @@
1
+ import type { Context } from "@steve.kite/stdlib";
2
+ import { type AgentDatabase, type AgentStorageTransaction } from "./AgentDatabase.js";
3
+ import type { AgentPersistence, AgentRecord } from "./AgentPersistence.js";
4
+ /** The database and transaction integration shared by every scope in one AgentStorage. */
5
+ export interface AgentPersistenceDrizzleOptions<Database extends AgentDatabase = AgentDatabase> {
6
+ readonly database: Database;
7
+ readonly owner: object;
8
+ readonly transaction: AgentStorageTransaction<Database>;
9
+ }
10
+ /**
11
+ * Drizzle-backed records and key-value entries for either the collection root or one agent.
12
+ * Tables are shared by every instance; `ownerId` is empty for collection state and the cuid2
13
+ * agent identity for a conversation.
14
+ */
15
+ export declare class AgentPersistenceDrizzle<Database extends AgentDatabase = AgentDatabase> implements AgentPersistence {
16
+ #private;
17
+ constructor(options: AgentPersistenceDrizzleOptions<Database>, ownerId: string);
18
+ get database(): AgentDatabase;
19
+ transaction<Result>(ctx: Context, work: (ctx: Context) => Promise<Result>): Promise<Result>;
20
+ load(ctx: Context): Promise<readonly AgentRecord[]>;
21
+ append(ctx: Context, record: AgentRecord): Promise<void>;
22
+ clearRecords(ctx: Context): Promise<void>;
23
+ readValues(ctx: Context, prefix: string): Promise<readonly {
24
+ readonly key: string;
25
+ readonly value: unknown;
26
+ }[]>;
27
+ writeValue(ctx: Context, key: string, value: unknown): Promise<void>;
28
+ writeValueIfAbsent(ctx: Context, key: string, value: unknown): Promise<boolean>;
29
+ deleteValue(ctx: Context, key: string): Promise<void>;
30
+ }
31
+ //# sourceMappingURL=AgentPersistenceDrizzle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AgentPersistenceDrizzle.d.ts","sourceRoot":"","sources":["../sources/AgentPersistenceDrizzle.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,EAGH,KAAK,aAAa,EAElB,KAAK,uBAAuB,EAC/B,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAE3E,0FAA0F;AAC1F,MAAM,WAAW,8BAA8B,CAAC,QAAQ,SAAS,aAAa,GAAG,aAAa;IAC1F,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,EAAE,uBAAuB,CAAC,QAAQ,CAAC,CAAC;CAC3D;AAED;;;;GAIG;AACH,qBAAa,uBAAuB,CAChC,QAAQ,SAAS,aAAa,GAAG,aAAa,CAChD,YAAW,gBAAgB;;IAIzB,YAAY,OAAO,EAAE,8BAA8B,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,MAAM,EAG7E;IAED,IAAI,QAAQ,IAAI,aAAa,CAE5B;IAEK,WAAW,CAAC,MAAM,EACpB,GAAG,EAAE,OAAO,EACZ,IAAI,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,MAAM,CAAC,GACxC,OAAO,CAAC,MAAM,CAAC,CAEjB;IAEK,IAAI,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,SAAS,WAAW,EAAE,CAAC,CAWxD;IAEK,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAU7D;IAEK,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAO9C;IAEK,UAAU,CACZ,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,MAAM,GACf,OAAO,CAAC,SAAS;QAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC,CAYvE;IAEK,UAAU,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAYzE;IAEK,kBAAkB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAapF;IAEK,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ1D;CAoBJ"}
@@ -0,0 +1,99 @@
1
+ import { sql } from "drizzle-orm";
2
+ import { agentDatabaseRows, agentDatabaseRun, } from "./AgentDatabase.js";
3
+ import { agentStorageTransaction } from "./AgentContexts.js";
4
+ /**
5
+ * Drizzle-backed records and key-value entries for either the collection root or one agent.
6
+ * Tables are shared by every instance; `ownerId` is empty for collection state and the cuid2
7
+ * agent identity for a conversation.
8
+ */
9
+ export class AgentPersistenceDrizzle {
10
+ #options;
11
+ #ownerId;
12
+ constructor(options, ownerId) {
13
+ this.#options = options;
14
+ this.#ownerId = ownerId;
15
+ }
16
+ get database() {
17
+ return this.#options.database;
18
+ }
19
+ async transaction(ctx, work) {
20
+ return await this.#options.transaction(ctx, async (txCtx) => await work(txCtx));
21
+ }
22
+ async load(ctx) {
23
+ return await this.#operation(ctx, async (database) => {
24
+ const rows = await agentDatabaseRows(database, sql `SELECT record_json
25
+ FROM happy_agent_records
26
+ WHERE owner_id = ${this.#ownerId}
27
+ ORDER BY position`);
28
+ return rows.map(({ record_json }) => JSON.parse(record_json));
29
+ });
30
+ }
31
+ async append(ctx, record) {
32
+ await this.#operation(ctx, async (database) => {
33
+ await agentDatabaseRun(database, sql `INSERT INTO happy_agent_records (owner_id, position, record_json)
34
+ SELECT ${this.#ownerId}, COALESCE(MAX(position), -1) + 1, ${JSON.stringify(record)}
35
+ FROM happy_agent_records
36
+ WHERE owner_id = ${this.#ownerId}`);
37
+ });
38
+ }
39
+ async clearRecords(ctx) {
40
+ await this.#operation(ctx, async (database) => {
41
+ await agentDatabaseRun(database, sql `DELETE FROM happy_agent_records WHERE owner_id = ${this.#ownerId}`);
42
+ });
43
+ }
44
+ async readValues(ctx, prefix) {
45
+ return await this.#operation(ctx, async (database) => {
46
+ const rows = await agentDatabaseRows(database, sql `SELECT key, value_json
47
+ FROM happy_agent_values
48
+ WHERE owner_id = ${this.#ownerId}
49
+ AND substr(key, 1, length(${prefix})) = ${prefix}
50
+ ORDER BY key`);
51
+ return rows.map(({ key, value_json }) => ({ key, value: JSON.parse(value_json) }));
52
+ });
53
+ }
54
+ async writeValue(ctx, key, value) {
55
+ const encoded = JSON.stringify(value);
56
+ if (encoded === undefined)
57
+ throw new Error("Agent storage cannot persist undefined.");
58
+ await this.#operation(ctx, async (database) => {
59
+ await agentDatabaseRun(database, sql `INSERT INTO happy_agent_values (owner_id, key, value_json)
60
+ VALUES (${this.#ownerId}, ${key}, ${encoded})
61
+ ON CONFLICT (owner_id, key)
62
+ DO UPDATE SET value_json = EXCLUDED.value_json`);
63
+ });
64
+ }
65
+ async writeValueIfAbsent(ctx, key, value) {
66
+ const encoded = JSON.stringify(value);
67
+ if (encoded === undefined)
68
+ throw new Error("Agent storage cannot persist undefined.");
69
+ return await this.#operation(ctx, async (database) => {
70
+ const rows = await agentDatabaseRows(database, sql `INSERT INTO happy_agent_values (owner_id, key, value_json)
71
+ VALUES (${this.#ownerId}, ${key}, ${encoded})
72
+ ON CONFLICT (owner_id, key) DO NOTHING
73
+ RETURNING key`);
74
+ return rows.length > 0;
75
+ });
76
+ }
77
+ async deleteValue(ctx, key) {
78
+ await this.#operation(ctx, async (database) => {
79
+ await agentDatabaseRun(database, sql `DELETE FROM happy_agent_values
80
+ WHERE owner_id = ${this.#ownerId} AND key = ${key}`);
81
+ });
82
+ }
83
+ async #operation(ctx, work) {
84
+ const transaction = agentStorageTransaction(ctx);
85
+ if (transaction !== undefined) {
86
+ if (transaction.lifetime.aborted) {
87
+ throw new Error("The agent storage transaction carried by this context has ended.");
88
+ }
89
+ if (transaction.owner !== this.#options.owner) {
90
+ throw new Error("A transaction context cannot be used with another agent storage.");
91
+ }
92
+ return await work(transaction.database);
93
+ }
94
+ return await this.#options.transaction(ctx, async (_txCtx, database) => {
95
+ return await work(database);
96
+ });
97
+ }
98
+ }
99
+ //# sourceMappingURL=AgentPersistenceDrizzle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AgentPersistenceDrizzle.js","sourceRoot":"","sources":["../sources/AgentPersistenceDrizzle.ts"],"names":[],"mappings":"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"}
@@ -2,15 +2,19 @@ import type { SessionUserMessage } from "@slopus/happy-providers";
2
2
  import type { Context } from "@steve.kite/stdlib";
3
3
  import type { Agent } from "./Agent.js";
4
4
  import type { AgentBaseMessageOptions } from "./AgentBase.js";
5
+ import type { AgentDatabase } from "./AgentDatabase.js";
6
+ import type { AgentMetadata } from "./AgentMetadata.js";
7
+ import type { AgentMessageAcceptance } from "./AgentMessageAcceptance.js";
8
+ import type { AnyAgentTool } from "./AgentTool.js";
5
9
  /**
6
10
  * Whether this caller may be told that `agentId` durably accepted a message. Acceptance is a
7
11
  * queue write under that agent's own persistence lock, so waiting for it is safe from anywhere
8
- * except inside that agent's loop, which is holding the lock the write needs. The proof is the
9
- * caller's context naming a different agent; a context naming none proves nothing.
12
+ * except inside that agent's loop, which is holding the lock the write needs. A caller naming no
13
+ * agent is an external host and may wait; only the target agent itself cannot.
10
14
  */
11
15
  export declare function acceptanceIsWaitable(ctx: Context, target: string): boolean;
12
16
  /**
13
- * A reference to an agent for code that runs inside one — a feature hook, or a tool the run loop
17
+ * A reference to an agent for code that runs inside one — a module hook, or a tool the run loop
14
18
  * is waiting on. No operation here waits for a run loop: `compact` and `abort` are requests that
15
19
  * resolve once they have been made, and there is no `close`, `waitForIdle` or `start`, each of
16
20
  * which is whole-agent lifetime owned by whoever created the agent and nothing *but* the wait
@@ -21,18 +25,22 @@ export declare function acceptanceIsWaitable(ctx: Context, target: string): bool
21
25
  * agent's conversation and reject when the write fails, so a caller routing work elsewhere knows
22
26
  * whether it arrived. Addressed to the agent the caller is running inside — whose loop would have
23
27
  * to perform that write — the message is queued and not waited for. The context decides, since it
24
- * names the agent the caller is in; a context that names none proves nothing and waits for
25
- * nothing.
28
+ * names the agent the caller is in; a context that names none is an external host and receives
29
+ * the durable acceptance result.
26
30
  */
27
- export declare class AgentRef {
31
+ export declare class AgentRef<Database extends AgentDatabase = AgentDatabase> {
28
32
  #private;
29
- constructor(agent: Agent);
33
+ /** The durable parent captured when this reference was resolved, or `null` for a root. */
34
+ readonly parent: string | null;
35
+ constructor(agent: Agent<AnyAgentTool, Database>, parent?: string | null);
30
36
  /** The wrapped agent's ID. */
31
37
  get id(): string;
32
38
  /** Queue a message that injects as soon as the current response and its tool batch finish. */
33
- steer(ctx: Context, message: SessionUserMessage, options?: AgentBaseMessageOptions): Promise<void>;
39
+ steer(ctx: Context, message: SessionUserMessage, options?: AgentBaseMessageOptions): Promise<AgentMessageAcceptance>;
34
40
  /** Queue a message that injects when the agent would otherwise stop. */
35
- send(ctx: Context, message: SessionUserMessage, options?: AgentBaseMessageOptions): Promise<void>;
41
+ send(ctx: Context, message: SessionUserMessage, options?: AgentBaseMessageOptions): Promise<AgentMessageAcceptance>;
42
+ /** Shallow-merge fields into this agent's immutable metadata. */
43
+ updateMetadata(ctx: Context, update: AgentMetadata): Promise<void>;
36
44
  /** Ask the agent to compact, which it does between turns. */
37
45
  compact(ctx: Context): Promise<void>;
38
46
  /** Cancel the agent's active turn. */
@@ -1 +1 @@
1
- {"version":3,"file":"AgentRef.d.ts","sourceRoot":"","sources":["../sources/AgentRef.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAG9D;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAG1E;AAED;;;;;;;;;;;;;;GAcG;AACH,qBAAa,QAAQ;;IAIjB,YAAY,KAAK,EAAE,KAAK,EAEvB;IAED,8BAA8B;IAC9B,IAAI,EAAE,IAAI,MAAM,CAEf;IAED,8FAA8F;IACxF,KAAK,CACP,GAAG,EAAE,OAAO,EACZ,OAAO,EAAE,kBAAkB,EAC3B,OAAO,CAAC,EAAE,uBAAuB,GAClC,OAAO,CAAC,IAAI,CAAC,CAKf;IAED,wEAAwE;IAClE,IAAI,CACN,GAAG,EAAE,OAAO,EACZ,OAAO,EAAE,kBAAkB,EAC3B,OAAO,CAAC,EAAE,uBAAuB,GAClC,OAAO,CAAC,IAAI,CAAC,CAKf;IAED,6DAA6D;IACvD,OAAO,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAEzC;IAED,sCAAsC;IAChC,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAEvC;CACJ"}
1
+ {"version":3,"file":"AgentRef.d.ts","sourceRoot":"","sources":["../sources/AgentRef.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAE9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAC1E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAG1E;AAED;;;;;;;;;;;;;;GAcG;AACH,qBAAa,QAAQ,CAAC,QAAQ,SAAS,aAAa,GAAG,aAAa;;IAGhE,0FAA0F;IAC1F,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAE/B,YAAY,KAAK,EAAE,KAAK,CAAC,YAAY,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAE,MAAM,GAAG,IAAW,EAG7E;IAED,8BAA8B;IAC9B,IAAI,EAAE,IAAI,MAAM,CAEf;IAED,8FAA8F;IACxF,KAAK,CACP,GAAG,EAAE,OAAO,EACZ,OAAO,EAAE,kBAAkB,EAC3B,OAAO,CAAC,EAAE,uBAAuB,GAClC,OAAO,CAAC,sBAAsB,CAAC,CAKjC;IAED,wEAAwE;IAClE,IAAI,CACN,GAAG,EAAE,OAAO,EACZ,OAAO,EAAE,kBAAkB,EAC3B,OAAO,CAAC,EAAE,uBAAuB,GAClC,OAAO,CAAC,sBAAsB,CAAC,CAKjC;IAED,iEAAiE;IAC3D,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAEvE;IAED,6DAA6D;IACvD,OAAO,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAEzC;IAED,sCAAsC;IAChC,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAEvC;CACJ"}
package/dist/AgentRef.js CHANGED
@@ -2,15 +2,15 @@ import { agentId } from "./AgentContexts.js";
2
2
  /**
3
3
  * Whether this caller may be told that `agentId` durably accepted a message. Acceptance is a
4
4
  * queue write under that agent's own persistence lock, so waiting for it is safe from anywhere
5
- * except inside that agent's loop, which is holding the lock the write needs. The proof is the
6
- * caller's context naming a different agent; a context naming none proves nothing.
5
+ * except inside that agent's loop, which is holding the lock the write needs. A caller naming no
6
+ * agent is an external host and may wait; only the target agent itself cannot.
7
7
  */
8
8
  export function acceptanceIsWaitable(ctx, target) {
9
9
  const caller = agentId(ctx);
10
- return caller !== undefined && caller !== target;
10
+ return caller !== target;
11
11
  }
12
12
  /**
13
- * A reference to an agent for code that runs inside one — a feature hook, or a tool the run loop
13
+ * A reference to an agent for code that runs inside one — a module hook, or a tool the run loop
14
14
  * is waiting on. No operation here waits for a run loop: `compact` and `abort` are requests that
15
15
  * resolve once they have been made, and there is no `close`, `waitForIdle` or `start`, each of
16
16
  * which is whole-agent lifetime owned by whoever created the agent and nothing *but* the wait
@@ -21,14 +21,17 @@ export function acceptanceIsWaitable(ctx, target) {
21
21
  * agent's conversation and reject when the write fails, so a caller routing work elsewhere knows
22
22
  * whether it arrived. Addressed to the agent the caller is running inside — whose loop would have
23
23
  * to perform that write — the message is queued and not waited for. The context decides, since it
24
- * names the agent the caller is in; a context that names none proves nothing and waits for
25
- * nothing.
24
+ * names the agent the caller is in; a context that names none is an external host and receives
25
+ * the durable acceptance result.
26
26
  */
27
27
  export class AgentRef {
28
28
  /** The agent this reference wraps. */
29
29
  #agent;
30
- constructor(agent) {
30
+ /** The durable parent captured when this reference was resolved, or `null` for a root. */
31
+ parent;
32
+ constructor(agent, parent = null) {
31
33
  this.#agent = agent;
34
+ this.parent = parent;
32
35
  }
33
36
  /** The wrapped agent's ID. */
34
37
  get id() {
@@ -36,18 +39,22 @@ export class AgentRef {
36
39
  }
37
40
  /** Queue a message that injects as soon as the current response and its tool batch finish. */
38
41
  async steer(ctx, message, options) {
39
- await this.#agent.steer(ctx, message, {
42
+ return await this.#agent.steer(ctx, message, {
40
43
  ...options,
41
44
  await: acceptanceIsWaitable(ctx, this.#agent.id),
42
45
  });
43
46
  }
44
47
  /** Queue a message that injects when the agent would otherwise stop. */
45
48
  async send(ctx, message, options) {
46
- await this.#agent.send(ctx, message, {
49
+ return await this.#agent.send(ctx, message, {
47
50
  ...options,
48
51
  await: acceptanceIsWaitable(ctx, this.#agent.id),
49
52
  });
50
53
  }
54
+ /** Shallow-merge fields into this agent's immutable metadata. */
55
+ async updateMetadata(ctx, update) {
56
+ await this.#agent.updateMetadata(ctx, update);
57
+ }
51
58
  /** Ask the agent to compact, which it does between turns. */
52
59
  async compact(ctx) {
53
60
  await this.#agent.compact(ctx, { await: false });
@@ -1 +1 @@
1
- {"version":3,"file":"AgentRef.js","sourceRoot":"","sources":["../sources/AgentRef.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAE7C;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAAY,EAAE,MAAc;IAC7D,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAC5B,OAAO,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,MAAM,CAAC;AACrD,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,OAAO,QAAQ;IACjB,sCAAsC;IAC7B,MAAM,CAAQ;IAEvB,YAAY,KAAY;QACpB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;IACxB,CAAC;IAED,8BAA8B;IAC9B,IAAI,EAAE;QACF,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;IAC1B,CAAC;IAED,8FAA8F;IAC9F,KAAK,CAAC,KAAK,CACP,GAAY,EACZ,OAA2B,EAC3B,OAAiC;QAEjC,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE;YAClC,GAAG,OAAO;YACV,KAAK,EAAE,oBAAoB,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;SACnD,CAAC,CAAC;IACP,CAAC;IAED,wEAAwE;IACxE,KAAK,CAAC,IAAI,CACN,GAAY,EACZ,OAA2B,EAC3B,OAAiC;QAEjC,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE;YACjC,GAAG,OAAO;YACV,KAAK,EAAE,oBAAoB,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;SACnD,CAAC,CAAC;IACP,CAAC;IAED,6DAA6D;IAC7D,KAAK,CAAC,OAAO,CAAC,GAAY;QACtB,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,sCAAsC;IACtC,KAAK,CAAC,KAAK,CAAC,GAAY;QACpB,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IACnD,CAAC;CACJ"}
1
+ {"version":3,"file":"AgentRef.js","sourceRoot":"","sources":["../sources/AgentRef.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAM7C;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAAY,EAAE,MAAc;IAC7D,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAC5B,OAAO,MAAM,KAAK,MAAM,CAAC;AAC7B,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,OAAO,QAAQ;IACjB,sCAAsC;IAC7B,MAAM,CAAgC;IAC/C,0FAA0F;IACjF,MAAM,CAAgB;IAE/B,YAAY,KAAoC,EAAE,MAAM,GAAkB,IAAI;QAC1E,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACzB,CAAC;IAED,8BAA8B;IAC9B,IAAI,EAAE;QACF,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;IAC1B,CAAC;IAED,8FAA8F;IAC9F,KAAK,CAAC,KAAK,CACP,GAAY,EACZ,OAA2B,EAC3B,OAAiC;QAEjC,OAAO,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE;YACzC,GAAG,OAAO;YACV,KAAK,EAAE,oBAAoB,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;SACnD,CAAC,CAAC;IACP,CAAC;IAED,wEAAwE;IACxE,KAAK,CAAC,IAAI,CACN,GAAY,EACZ,OAA2B,EAC3B,OAAiC;QAEjC,OAAO,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE;YACxC,GAAG,OAAO;YACV,KAAK,EAAE,oBAAoB,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;SACnD,CAAC,CAAC;IACP,CAAC;IAED,iEAAiE;IACjE,KAAK,CAAC,cAAc,CAAC,GAAY,EAAE,MAAqB;QACpD,MAAM,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAClD,CAAC;IAED,6DAA6D;IAC7D,KAAK,CAAC,OAAO,CAAC,GAAY;QACtB,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,sCAAsC;IACtC,KAAK,CAAC,KAAK,CAAC,GAAY;QACpB,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IACnD,CAAC;CACJ"}
@@ -1,32 +1,43 @@
1
- import type { Context } from "@steve.kite/stdlib";
2
- import type { AgentKV } from "./AgentKV.js";
1
+ import { type Context } from "@steve.kite/stdlib";
2
+ import { type AgentDatabase, type AgentDatabaseFacade, type AgentStorageTransaction } from "./AgentDatabase.js";
3
+ import type { AgentModule } from "./AgentModule.js";
4
+ import { AgentKV } from "./AgentKV.js";
3
5
  import type { AgentPersistence } from "./AgentPersistence.js";
6
+ import type { AnyAgentTool } from "./AgentTool.js";
4
7
  /**
5
- * The exclusive ownership of one durable agent store. The storage adapter must back this with
6
- * the database's hard process-level lock rather than an in-memory convention.
8
+ * The exclusive ownership of one durable agent store. A host sharing its database between
9
+ * processes should back this with the same hard process-level lock as the database itself.
7
10
  */
8
11
  export interface AgentStorageLock {
9
12
  /** Release the hard lock after the owning AgentSystem has stopped every agent. */
10
13
  release(ctx: Context): Promise<void>;
11
14
  }
12
- /** What an `AgentStorage` is built from. */
13
- export interface AgentStorageOptions {
15
+ interface AgentStorageCommonOptions {
14
16
  /**
15
17
  * Acquire exclusive ownership of the whole store. This must fail while any other process or
16
18
  * AgentSystem owns the same durable store.
17
19
  */
18
20
  readonly acquireLock: (ctx: Context) => Promise<AgentStorageLock>;
19
- /** Shared key-value storage used for state spanning all agents. */
20
- readonly kv: AgentKV;
21
- /** Produce the isolated persistence used by one agent. */
22
- readonly persistence: (agentId: string) => AgentPersistence;
23
21
  }
24
- /** Storage roots shared by an `AgentSystemLocal` collection. */
25
- export declare class AgentStorage {
22
+ /** Drizzle-owned storage with optional host transaction integration. */
23
+ export type AgentStorageOptions<Database extends AgentDatabase = AgentDatabase> = AgentStorageCommonOptions & {
24
+ /** The engine-specific Drizzle facade; the same object is passed through to modules. */
25
+ readonly database: Database;
26
+ /**
27
+ * Host transaction integration. It must pass the active Drizzle transaction facade and a
28
+ * context carrying the host transaction's stdlib `afterCommit` scope to `work`. Omission
29
+ * uses the Drizzle facade's own transaction method and installs that scope automatically.
30
+ */
31
+ readonly transaction?: AgentStorageTransaction<Database>;
32
+ };
33
+ /** Storage roots and Drizzle persistence shared by an `AgentSystemLocal` collection. */
34
+ export declare class AgentStorage<Database extends AgentDatabase = AgentDatabase> {
26
35
  #private;
36
+ /** The root Drizzle facade. */
37
+ readonly database: Database;
27
38
  /** Shared key-value storage used for state spanning all agents. */
28
39
  readonly kv: AgentKV;
29
- constructor(options: AgentStorageOptions);
40
+ constructor(options: AgentStorageOptions<Database>);
30
41
  /**
31
42
  * Acquire exclusive ownership until the returned lock is released. The adapter's lock
32
43
  * enforces this across processes; the local guard also rejects accidental reuse of this
@@ -35,5 +46,14 @@ export declare class AgentStorage {
35
46
  acquireLock(ctx: Context): Promise<AgentStorageLock>;
36
47
  /** The isolated persistence for the given agent. */
37
48
  persistence(agentId: string): AgentPersistence;
49
+ /** Run work in this storage's default or host-supplied transaction integration. */
50
+ transaction<Result>(ctx: Context, work: (ctx: Context, database: AgentDatabaseFacade<Database>) => Promise<Result>): Promise<Result>;
51
+ /**
52
+ * Install the base schema and every module's ordered keyed migrations. Each migration and
53
+ * its success marker commit atomically. Applied keys must remain an exact prefix, so inserting
54
+ * or reordering historical migrations fails instead of silently changing their meaning.
55
+ */
56
+ migrate(ctx: Context, modules: readonly AgentModule<AnyAgentTool, Database>[]): Promise<void>;
38
57
  }
58
+ export {};
39
59
  //# sourceMappingURL=AgentStorage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AgentStorage.d.ts","sourceRoot":"","sources":["../sources/AgentStorage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAE9D;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC7B,kFAAkF;IAClF,OAAO,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACxC;AAED,4CAA4C;AAC5C,MAAM,WAAW,mBAAmB;IAChC;;;OAGG;IACH,QAAQ,CAAC,WAAW,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAClE,mEAAmE;IACnE,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,0DAA0D;IAC1D,QAAQ,CAAC,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,gBAAgB,CAAC;CAC/D;AAED,gEAAgE;AAChE,qBAAa,YAAY;;IACrB,mEAAmE;IACnE,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IAQrB,YAAY,OAAO,EAAE,mBAAmB,EAIvC;IAED;;;;OAIG;IACG,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAmBzD;IAED,oDAAoD;IACpD,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,CAE7C;CACJ"}
1
+ {"version":3,"file":"AgentStorage.d.ts","sourceRoot":"","sources":["../sources/AgentStorage.ts"],"names":[],"mappings":"AAEA,OAAO,EAA8B,KAAK,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAE9E,OAAO,EAIH,KAAK,aAAa,EAClB,KAAK,mBAAmB,EAExB,KAAK,uBAAuB,EAC/B,MAAM,oBAAoB,CAAC;AAM5B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAMnD;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC7B,kFAAkF;IAClF,OAAO,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACxC;AAED,UAAU,yBAAyB;IAC/B;;;OAGG;IACH,QAAQ,CAAC,WAAW,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAC;CACrE;AAED,wEAAwE;AACxE,MAAM,MAAM,mBAAmB,CAAC,QAAQ,SAAS,aAAa,GAAG,aAAa,IAC1E,yBAAyB,GAAG;IACxB,wFAAwF;IACxF,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,uBAAuB,CAAC,QAAQ,CAAC,CAAC;CAC5D,CAAC;AAIN,wFAAwF;AACxF,qBAAa,YAAY,CAAC,QAAQ,SAAS,aAAa,GAAG,aAAa;;IACpE,+BAA+B;IAC/B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,mEAAmE;IACnE,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IAUrB,YAAY,OAAO,EAAE,mBAAmB,CAAC,QAAQ,CAAC,EAcjD;IAED;;;;OAIG;IACG,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAmBzD;IAED,oDAAoD;IACpD,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,CAE7C;IAED,mFAAmF;IAC7E,WAAW,CAAC,MAAM,EACpB,GAAG,EAAE,OAAO,EACZ,IAAI,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,mBAAmB,CAAC,QAAQ,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,GACjF,OAAO,CAAC,MAAM,CAAC,CAEjB;IAED;;;;OAIG;IACG,OAAO,CACT,GAAG,EAAE,OAAO,EACZ,OAAO,EAAE,SAAS,WAAW,CAAC,YAAY,EAAE,QAAQ,CAAC,EAAE,GACxD,OAAO,CAAC,IAAI,CAAC,CA6Cf;CA8CJ"}