@cursor/july 0.1.6 → 0.1.8

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 (179) hide show
  1. package/dist/bin/agent-serve.js +73 -19
  2. package/dist/channels/slack/channel-watch.d.ts +6 -1
  3. package/dist/channels/slack/channel-watch.d.ts.map +1 -1
  4. package/dist/channels/slack/channel-watch.js +22 -1
  5. package/dist/channels/slack/cursor-account.d.ts +4 -0
  6. package/dist/channels/slack/cursor-account.d.ts.map +1 -1
  7. package/dist/channels/slack/cursor-account.js +12 -2
  8. package/dist/channels/slack/defaults.d.ts +10 -5
  9. package/dist/channels/slack/defaults.d.ts.map +1 -1
  10. package/dist/channels/slack/defaults.js +39 -17
  11. package/dist/channels/slack/dispatch.d.ts +18 -0
  12. package/dist/channels/slack/dispatch.d.ts.map +1 -1
  13. package/dist/channels/slack/dispatch.js +141 -38
  14. package/dist/channels/slack/inbound.d.ts +13 -3
  15. package/dist/channels/slack/inbound.d.ts.map +1 -1
  16. package/dist/channels/slack/inbound.js +17 -9
  17. package/dist/channels/slack/index.d.ts +4 -0
  18. package/dist/channels/slack/index.d.ts.map +1 -1
  19. package/dist/channels/slack/index.js +4 -0
  20. package/dist/channels/slack/live-delivery.d.ts.map +1 -1
  21. package/dist/channels/slack/live-delivery.js +1 -0
  22. package/dist/channels/slack/manifest.d.ts.map +1 -1
  23. package/dist/channels/slack/manifest.js +3 -0
  24. package/dist/channels/slack/nudge-carrier.d.ts +19 -0
  25. package/dist/channels/slack/nudge-carrier.d.ts.map +1 -0
  26. package/dist/channels/slack/nudge-carrier.js +166 -0
  27. package/dist/channels/slack/nudge-store.d.ts +61 -0
  28. package/dist/channels/slack/nudge-store.d.ts.map +1 -0
  29. package/dist/channels/slack/nudge-store.js +266 -0
  30. package/dist/channels/slack/slack-channel.d.ts.map +1 -1
  31. package/dist/channels/slack/slack-channel.js +74 -25
  32. package/dist/channels/slack/stop.d.ts +14 -0
  33. package/dist/channels/slack/stop.d.ts.map +1 -0
  34. package/dist/channels/slack/stop.js +22 -0
  35. package/dist/channels/slack/thread-context.d.ts +81 -0
  36. package/dist/channels/slack/thread-context.d.ts.map +1 -0
  37. package/dist/channels/slack/thread-context.js +470 -0
  38. package/dist/channels/slack/types.d.ts +27 -0
  39. package/dist/channels/slack/types.d.ts.map +1 -1
  40. package/dist/docs/404.html +2 -2
  41. package/dist/docs/ab.html +4 -4
  42. package/dist/docs/assets/{app.DMboGKUD.js → app.BP8mAVMW.js} +1 -1
  43. package/dist/docs/assets/chunks/@localSearchIndexroot.DevOabKJ.js +1 -0
  44. package/dist/docs/assets/chunks/{VPLocalSearchBox.DkEqEnJU.js → VPLocalSearchBox.1FXIZbz8.js} +1 -1
  45. package/dist/docs/assets/chunks/{theme.ASugdMNm.js → theme.Dm1R02v9.js} +2 -2
  46. package/dist/docs/assets/example-agents_index.md.CwtWu5ix.js +2 -0
  47. package/dist/docs/assets/{example-agents_index.md.CRqJlnIf.lean.js → example-agents_index.md.CwtWu5ix.lean.js} +1 -1
  48. package/dist/docs/assets/example-agents_oncall.md.BG_sUMly.js +10 -0
  49. package/dist/docs/assets/example-agents_oncall.md.BG_sUMly.lean.js +1 -0
  50. package/dist/docs/assets/{guides_slack.md.CCwqHvSV.js → guides_slack.md.FWale6Ip.js} +4 -3
  51. package/dist/docs/assets/{guides_slack.md.CCwqHvSV.lean.js → guides_slack.md.FWale6Ip.lean.js} +1 -1
  52. package/dist/docs/assets/{reference_sessions.md.DdjWabnN.js → reference_sessions.md.DLd6mvbv.js} +2 -2
  53. package/dist/docs/assets/{reference_sessions.md.DdjWabnN.lean.js → reference_sessions.md.DLd6mvbv.lean.js} +1 -1
  54. package/dist/docs/assets/{storage.md.CVnInNiN.js → storage.md.Cu3MwM2a.js} +3 -2
  55. package/dist/docs/assets/{storage.md.CVnInNiN.lean.js → storage.md.Cu3MwM2a.lean.js} +1 -1
  56. package/dist/docs/building-with-agents.html +4 -4
  57. package/dist/docs/concepts.html +4 -4
  58. package/dist/docs/deployment.html +4 -4
  59. package/dist/docs/evals.html +4 -4
  60. package/dist/docs/example-agents/approval-buddy.html +4 -4
  61. package/dist/docs/example-agents/benny.html +5 -5
  62. package/dist/docs/example-agents/bugbot.html +5 -5
  63. package/dist/docs/example-agents/codebase-wiki.html +4 -4
  64. package/dist/docs/example-agents/codeowners-review.html +4 -4
  65. package/dist/docs/example-agents/concierge.html +4 -4
  66. package/dist/docs/example-agents/fsd.html +4 -4
  67. package/dist/docs/example-agents/index.html +6 -6
  68. package/dist/docs/example-agents/knowledge-base.html +4 -4
  69. package/dist/docs/example-agents/oncall.html +34 -0
  70. package/dist/docs/example-agents/security-reviewer.html +4 -4
  71. package/dist/docs/example-agents/slack-agent.html +4 -4
  72. package/dist/docs/example-agents/weather-agent.html +4 -4
  73. package/dist/docs/guides/agent-to-agent.html +4 -4
  74. package/dist/docs/guides/cloud-runtime.html +4 -4
  75. package/dist/docs/guides/github.html +4 -4
  76. package/dist/docs/guides/human-in-the-loop.html +4 -4
  77. package/dist/docs/guides/slack.html +7 -6
  78. package/dist/docs/guides/webhooks.html +4 -4
  79. package/dist/docs/hashmap.json +1 -1
  80. package/dist/docs/hillclimbing.html +4 -4
  81. package/dist/docs/index.html +4 -4
  82. package/dist/docs/quickstart.html +4 -4
  83. package/dist/docs/reference/agent-config.html +4 -4
  84. package/dist/docs/reference/channels.html +4 -4
  85. package/dist/docs/reference/cli.html +4 -4
  86. package/dist/docs/reference/connections.html +4 -4
  87. package/dist/docs/reference/hooks.html +4 -4
  88. package/dist/docs/reference/http-api.html +4 -4
  89. package/dist/docs/reference/instructions.html +4 -4
  90. package/dist/docs/reference/playground.html +4 -4
  91. package/dist/docs/reference/project-layout.html +4 -4
  92. package/dist/docs/reference/schedules.html +4 -4
  93. package/dist/docs/reference/sessions.html +5 -5
  94. package/dist/docs/reference/skills.html +4 -4
  95. package/dist/docs/reference/subagents.html +4 -4
  96. package/dist/docs/reference/tools.html +4 -4
  97. package/dist/docs/scaffolding-agents.html +4 -4
  98. package/dist/docs/storage.html +7 -6
  99. package/dist/docs/troubleshooting.html +4 -4
  100. package/dist/evals.d.ts +2 -2
  101. package/dist/internal/cli-ax.d.ts +23 -10
  102. package/dist/internal/cli-ax.d.ts.map +1 -1
  103. package/dist/internal/cli-ax.js +358 -55
  104. package/dist/internal/cli-mcp.d.ts +64 -0
  105. package/dist/internal/cli-mcp.d.ts.map +1 -0
  106. package/dist/internal/cli-mcp.js +570 -0
  107. package/dist/internal/distribution.d.ts.map +1 -1
  108. package/dist/internal/distribution.js +2 -0
  109. package/dist/internal/eval-run-store.d.ts +2 -0
  110. package/dist/internal/eval-run-store.d.ts.map +1 -1
  111. package/dist/internal/eval-run-store.js +4 -4
  112. package/dist/internal/evals-client.d.ts +96 -0
  113. package/dist/internal/evals-client.d.ts.map +1 -0
  114. package/dist/internal/evals-client.js +262 -0
  115. package/dist/internal/host-kv.d.ts +17 -0
  116. package/dist/internal/host-kv.d.ts.map +1 -0
  117. package/dist/internal/host-kv.js +77 -0
  118. package/dist/internal/init-project.js +3 -3
  119. package/dist/internal/server.d.ts.map +1 -1
  120. package/dist/internal/server.js +19 -2
  121. package/dist/internal/session-engine.d.ts +42 -7
  122. package/dist/internal/session-engine.d.ts.map +1 -1
  123. package/dist/internal/session-engine.js +247 -51
  124. package/dist/internal/storage-coordinator.d.ts +18 -1
  125. package/dist/internal/storage-coordinator.d.ts.map +1 -1
  126. package/dist/internal/storage-coordinator.js +43 -0
  127. package/dist/playground/assets/index-Bpr4Th4M.js +319 -0
  128. package/dist/playground/index.html +1 -1
  129. package/dist/storage-backends/file-kv.d.ts +42 -0
  130. package/dist/storage-backends/file-kv.d.ts.map +1 -0
  131. package/dist/storage-backends/file-kv.js +190 -0
  132. package/dist/storage-backends/postgres-kv.d.ts +77 -0
  133. package/dist/storage-backends/postgres-kv.d.ts.map +1 -0
  134. package/dist/storage-backends/postgres-kv.js +180 -0
  135. package/dist/storage.d.ts +10 -1
  136. package/dist/storage.d.ts.map +1 -1
  137. package/dist/storage.js +10 -1
  138. package/dist/types.d.ts +79 -0
  139. package/dist/types.d.ts.map +1 -1
  140. package/docs/example-agents/index.md +14 -9
  141. package/docs/example-agents/oncall.md +216 -0
  142. package/docs/guides/slack.md +11 -2
  143. package/docs/reference/sessions.md +13 -4
  144. package/docs/storage.md +27 -0
  145. package/package.json +15 -1
  146. package/skills/framework-map/SKILL.md +6 -4
  147. package/src/bin/agent-serve.ts +79 -18
  148. package/src/channels/slack/channel-watch.ts +28 -1
  149. package/src/channels/slack/cursor-account.ts +20 -0
  150. package/src/channels/slack/defaults.ts +51 -20
  151. package/src/channels/slack/dispatch.ts +215 -40
  152. package/src/channels/slack/inbound.ts +30 -10
  153. package/src/channels/slack/index.ts +4 -0
  154. package/src/channels/slack/live-delivery.ts +1 -0
  155. package/src/channels/slack/manifest.ts +3 -0
  156. package/src/channels/slack/nudge-carrier.ts +182 -0
  157. package/src/channels/slack/nudge-store.ts +308 -0
  158. package/src/channels/slack/slack-channel.ts +106 -31
  159. package/src/channels/slack/stop.ts +25 -0
  160. package/src/channels/slack/thread-context.ts +572 -0
  161. package/src/channels/slack/types.ts +27 -0
  162. package/src/evals.ts +2 -2
  163. package/src/internal/cli-ax.ts +466 -75
  164. package/src/internal/cli-mcp.ts +708 -0
  165. package/src/internal/distribution.ts +2 -0
  166. package/src/internal/eval-run-store.ts +5 -0
  167. package/src/internal/evals-client.ts +431 -0
  168. package/src/internal/host-kv.ts +85 -0
  169. package/src/internal/init-project.ts +3 -3
  170. package/src/internal/server.ts +43 -0
  171. package/src/internal/session-engine.ts +351 -50
  172. package/src/internal/storage-coordinator.ts +41 -0
  173. package/src/storage-backends/file-kv.ts +221 -0
  174. package/src/storage-backends/postgres-kv.ts +248 -0
  175. package/src/storage.ts +11 -1
  176. package/src/types.ts +83 -0
  177. package/dist/docs/assets/chunks/@localSearchIndexroot.O6eP7QZr.js +0 -1
  178. package/dist/docs/assets/example-agents_index.md.CRqJlnIf.js +0 -2
  179. package/dist/playground/assets/index-mux9aj5P.js +0 -319
@@ -8,7 +8,7 @@
8
8
  />
9
9
  <meta name="viewport" content="width=device-width, initial-scale=1" />
10
10
  <title>agent-serve playground</title>
11
- <script type="module" crossorigin src="./assets/index-mux9aj5P.js"></script>
11
+ <script type="module" crossorigin src="./assets/index-Bpr4Th4M.js"></script>
12
12
  <link rel="stylesheet" crossorigin href="./assets/index-7GJIUFQj.css">
13
13
  </head>
14
14
  <body>
@@ -0,0 +1,42 @@
1
+ /**
2
+ * File-backed `defineStorage` helper: a file-per-key KV store plus
3
+ * file-backed `evals` / `abs` tables.
4
+ *
5
+ * Implements the whole `defineStorage` surface with zero external
6
+ * dependencies: the four KV methods against a flat directory of JSON files
7
+ * (one file per key, filename = URI-encoded key), eval runs as
8
+ * `eval-runs/<agent>/<runId>.json`, and A/B metrics as
9
+ * `ab/<agent>/samples.ndjson` (append-only) plus `ab/<agent>/snapshot.json`
10
+ * (latest aggregate). KV keys carry the agent name inside the framework
11
+ * key scheme, but the evals/abs tables have no such scheme — the agent
12
+ * subdirectory keeps agents sharing one storage `dir` from mixing or
13
+ * overwriting each other's history. Swap this for a real backend
14
+ * (Postgres, S3, …) in production; the contracts are identical.
15
+ *
16
+ * Layout notes:
17
+ * - KV filenames encode the full key (`encodeURIComponent(key) + ".json"`),
18
+ * so `list(prefix)` is a readdir + decode + filter, returned in key
19
+ * order as the contract requires.
20
+ * - `put` writes via tmp + rename: the framework serializes writes, but a
21
+ * restore-path `get`/`list` can run concurrently and must never see a
22
+ * torn file.
23
+ * - `get` distinguishes a definitive miss (ENOENT → `undefined`) from a
24
+ * real failure (anything else throws) — on the lazy-restore path a
25
+ * throw correctly fails the follow-up instead of forking the session.
26
+ */
27
+ import type { StorageABTable, StorageConfig, StorageEvalsTable } from "../storage.js";
28
+ export interface FileKvOptions {
29
+ /**
30
+ * Directory holding the storage files, relative to the agent project root
31
+ * (default `".agent-serve/kv"`). Absolute paths are used as-is.
32
+ */
33
+ dir?: string;
34
+ }
35
+ type FileKvMethods = Required<Pick<StorageConfig, "put" | "get" | "delete" | "list">> & {
36
+ evals: StorageEvalsTable;
37
+ abs: StorageABTable;
38
+ };
39
+ /** File-backed `defineStorage` methods, ready to spread into `defineStorage({...})`. */
40
+ export declare function fileKv(options?: FileKvOptions): FileKvMethods;
41
+ export {};
42
+ //# sourceMappingURL=file-kv.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-kv.d.ts","sourceRoot":"","sources":["../../src/storage-backends/file-kv.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAeH,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EAGb,iBAAiB,EAClB,MAAM,eAAe,CAAC;AAGvB,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,KAAK,aAAa,GAAG,QAAQ,CAC3B,IAAI,CAAC,aAAa,EAAE,KAAK,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC,CACvD,GAAG;IACF,KAAK,EAAE,iBAAiB,CAAC;IACzB,GAAG,EAAE,cAAc,CAAC;CACrB,CAAC;AAEF,wFAAwF;AACxF,wBAAgB,MAAM,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,aAAa,CA+I7D"}
@@ -0,0 +1,190 @@
1
+ /**
2
+ * File-backed `defineStorage` helper: a file-per-key KV store plus
3
+ * file-backed `evals` / `abs` tables.
4
+ *
5
+ * Implements the whole `defineStorage` surface with zero external
6
+ * dependencies: the four KV methods against a flat directory of JSON files
7
+ * (one file per key, filename = URI-encoded key), eval runs as
8
+ * `eval-runs/<agent>/<runId>.json`, and A/B metrics as
9
+ * `ab/<agent>/samples.ndjson` (append-only) plus `ab/<agent>/snapshot.json`
10
+ * (latest aggregate). KV keys carry the agent name inside the framework
11
+ * key scheme, but the evals/abs tables have no such scheme — the agent
12
+ * subdirectory keeps agents sharing one storage `dir` from mixing or
13
+ * overwriting each other's history. Swap this for a real backend
14
+ * (Postgres, S3, …) in production; the contracts are identical.
15
+ *
16
+ * Layout notes:
17
+ * - KV filenames encode the full key (`encodeURIComponent(key) + ".json"`),
18
+ * so `list(prefix)` is a readdir + decode + filter, returned in key
19
+ * order as the contract requires.
20
+ * - `put` writes via tmp + rename: the framework serializes writes, but a
21
+ * restore-path `get`/`list` can run concurrently and must never see a
22
+ * torn file.
23
+ * - `get` distinguishes a definitive miss (ENOENT → `undefined`) from a
24
+ * real failure (anything else throws) — on the lazy-restore path a
25
+ * throw correctly fails the follow-up instead of forking the session.
26
+ */
27
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
28
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
29
+ return new (P || (P = Promise))(function (resolve, reject) {
30
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
31
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
32
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
33
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
34
+ });
35
+ };
36
+ import { randomUUID } from "node:crypto";
37
+ import { appendFile, mkdir, readdir, readFile, rename, rm, writeFile, } from "node:fs/promises";
38
+ import { join } from "node:path";
39
+ /** File-backed `defineStorage` methods, ready to spread into `defineStorage({...})`. */
40
+ export function fileKv(options) {
41
+ const resolveDir = (ctx) => { var _a; return join(ctx.projectRoot, (_a = options === null || options === void 0 ? void 0 : options.dir) !== null && _a !== void 0 ? _a : ".agent-serve/kv"); };
42
+ // The evals/abs tables are scoped per agent (KV keys already carry the
43
+ // agent name via the framework key scheme).
44
+ const evalRunsDir = (ctx) => join(resolveDir(ctx), "eval-runs", encodeURIComponent(ctx.agentName));
45
+ const abDir = (ctx) => join(resolveDir(ctx), "ab", encodeURIComponent(ctx.agentName));
46
+ const filePath = (ctx, key) => join(resolveDir(ctx), `${encodeURIComponent(key)}.json`);
47
+ const readKey = (ctx, key) => __awaiter(this, void 0, void 0, function* () {
48
+ try {
49
+ return JSON.parse(yield readFile(filePath(ctx, key), "utf8"));
50
+ }
51
+ catch (error) {
52
+ if (error.code === "ENOENT") {
53
+ return undefined; // definitive miss — key was never written
54
+ }
55
+ throw error; // real failure: let lazy restore fail the follow-up
56
+ }
57
+ });
58
+ return {
59
+ put(key, value, ctx) {
60
+ return __awaiter(this, void 0, void 0, function* () {
61
+ yield writeJsonAtomic({
62
+ dir: resolveDir(ctx),
63
+ fileName: `${encodeURIComponent(key)}.json`,
64
+ value,
65
+ });
66
+ });
67
+ },
68
+ get(key, ctx) {
69
+ return readKey(ctx, key);
70
+ },
71
+ delete(key, ctx) {
72
+ return __awaiter(this, void 0, void 0, function* () {
73
+ yield rm(filePath(ctx, key), { force: true });
74
+ });
75
+ },
76
+ list(prefix, ctx) {
77
+ return __awaiter(this, void 0, void 0, function* () {
78
+ let names;
79
+ try {
80
+ names = yield readdir(resolveDir(ctx));
81
+ }
82
+ catch (error) {
83
+ if (error.code === "ENOENT") {
84
+ return []; // nothing stored yet
85
+ }
86
+ throw error;
87
+ }
88
+ const keys = names
89
+ .filter((name) => name.endsWith(".json"))
90
+ .map((name) => decodeURIComponent(name.slice(0, -".json".length)))
91
+ .filter((key) => key.startsWith(prefix))
92
+ .sort();
93
+ const entries = [];
94
+ for (const key of keys) {
95
+ const value = yield readKey(ctx, key);
96
+ if (value !== undefined) {
97
+ entries.push({ key, value });
98
+ }
99
+ }
100
+ return entries;
101
+ });
102
+ },
103
+ // Playground eval batches: one JSON file per run under eval-runs/<agent>/.
104
+ evals: {
105
+ put(run, ctx) {
106
+ return __awaiter(this, void 0, void 0, function* () {
107
+ yield writeJsonAtomic({
108
+ dir: evalRunsDir(ctx),
109
+ fileName: `${encodeURIComponent(run.runId)}.json`,
110
+ value: run,
111
+ });
112
+ });
113
+ },
114
+ delete(runId, ctx) {
115
+ return __awaiter(this, void 0, void 0, function* () {
116
+ yield rm(join(evalRunsDir(ctx), `${encodeURIComponent(runId)}.json`), {
117
+ force: true,
118
+ });
119
+ });
120
+ },
121
+ list(ctx) {
122
+ return __awaiter(this, void 0, void 0, function* () {
123
+ const dir = evalRunsDir(ctx);
124
+ let names;
125
+ try {
126
+ names = yield readdir(dir);
127
+ }
128
+ catch (error) {
129
+ if (error.code === "ENOENT") {
130
+ return [];
131
+ }
132
+ throw error;
133
+ }
134
+ const runs = [];
135
+ for (const name of names.filter((n) => n.endsWith(".json")).sort()) {
136
+ // One unreadable/corrupt file must not wipe the whole history:
137
+ // hydrate treats a throwing list() as "nothing saved".
138
+ try {
139
+ runs.push(JSON.parse(yield readFile(join(dir, name), "utf8")));
140
+ }
141
+ catch (_a) { }
142
+ }
143
+ return runs;
144
+ });
145
+ },
146
+ },
147
+ // A/B metrics: append-only sample log + latest aggregate snapshot,
148
+ // both under ab/<agent>/.
149
+ abs: {
150
+ putSample(sample, ctx) {
151
+ return __awaiter(this, void 0, void 0, function* () {
152
+ const dir = abDir(ctx);
153
+ yield mkdir(dir, { recursive: true });
154
+ yield appendFile(join(dir, "samples.ndjson"), `${JSON.stringify(sample)}\n`, "utf8");
155
+ });
156
+ },
157
+ putSnapshot(snapshot, ctx) {
158
+ return __awaiter(this, void 0, void 0, function* () {
159
+ yield writeJsonAtomic({
160
+ dir: abDir(ctx),
161
+ fileName: "snapshot.json",
162
+ value: snapshot,
163
+ });
164
+ });
165
+ },
166
+ getSnapshot(ctx) {
167
+ return __awaiter(this, void 0, void 0, function* () {
168
+ try {
169
+ return JSON.parse(yield readFile(join(abDir(ctx), "snapshot.json"), "utf8"));
170
+ }
171
+ catch (error) {
172
+ if (error.code === "ENOENT") {
173
+ return undefined;
174
+ }
175
+ throw error;
176
+ }
177
+ });
178
+ },
179
+ },
180
+ };
181
+ }
182
+ /** tmp + rename write so concurrent readers never see a torn file. */
183
+ function writeJsonAtomic(args) {
184
+ return __awaiter(this, void 0, void 0, function* () {
185
+ yield mkdir(args.dir, { recursive: true });
186
+ const tmp = join(args.dir, `.tmp-${randomUUID()}`);
187
+ yield writeFile(tmp, JSON.stringify(args.value), "utf8");
188
+ yield rename(tmp, join(args.dir, args.fileName));
189
+ });
190
+ }
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Postgres `defineStorage` helper on the agent-serve tables
3
+ * (backend/packages/prisma-bugbot):
4
+ *
5
+ * agent_serve_kv(deployment_id, key, value JSONB, updated_at)
6
+ * PRIMARY KEY (deployment_id, key)
7
+ * agent_serve_eval_runs(deployment_id, agent, run_id, run JSONB, updated_at)
8
+ * PRIMARY KEY (deployment_id, agent, run_id)
9
+ * agent_serve_ab(deployment_id, agent, kind, ref, value JSONB, updated_at)
10
+ * PRIMARY KEY (deployment_id, agent, kind, ref)
11
+ *
12
+ * `postgresStorage` implements the whole `defineStorage` surface as plain
13
+ * SQL: the four KV methods against the last-write-wins `agent_serve_kv`
14
+ * table (sessions, event chunks, continuations, reminders), the `evals`
15
+ * table against `agent_serve_eval_runs` (one row per playground eval
16
+ * batch), and the `abs` table against `agent_serve_ab` (`kind = 'sample'`
17
+ * rows per metric sample plus one `kind = 'snapshot'` row holding the
18
+ * latest aggregate).
19
+ *
20
+ * - KV `put` upserts on the primary key (LWW matches the framework contract).
21
+ * - KV `list` is a prefix range scan on the PK btree (`key >= p AND key < p||…`
22
+ * spelled as LIKE with escaped wildcards, ordered by key).
23
+ * - `get` returning no row is a definitive miss (`undefined`); a connection
24
+ * error throws, so lazy restore fails the follow-up instead of forking
25
+ * the session.
26
+ *
27
+ * Connection comes from `BUGBOTDB_URL` — the repo-wide convention for the
28
+ * bugbot Postgres database, whose Prisma package owns these tables' schema
29
+ * and migrations; locally it falls back to the dev bugbot DB. Non-local
30
+ * URLs enable TLS (`ssl.rejectUnauthorized`) because PlanetScale requires
31
+ * SSL even when the vault URL omits `sslmode`.
32
+ * `deploymentId` scopes rows per deployment (`AGENT_SERVE_DEPLOYMENT_ID`);
33
+ * the local default keeps dev runs of different checkouts from colliding
34
+ * only by agent name.
35
+ *
36
+ * Callers must pass `Pool` from their own `import { Pool } from "pg"`.
37
+ * This module must not import `pg` itself: Node resolves modules from
38
+ * *this* file's directory tree, so a `pg` dep declared only on the
39
+ * consuming agent package would never be found after a hosted install.
40
+ */
41
+ import type { StorageABTable, StorageConfig, StorageEvalsTable } from "../storage.js";
42
+ /** Minimal `pg.Pool` surface used here (avoids importing `pg` from this path). */
43
+ export interface PostgresQueryable {
44
+ query<T extends Record<string, unknown> = Record<string, unknown>>(text: string, values?: readonly unknown[]): Promise<{
45
+ rows: T[];
46
+ }>;
47
+ }
48
+ /** `pg.Pool` constructor supplied by the consuming example package. */
49
+ export type PostgresPoolConstructor = new (config?: {
50
+ connectionString?: string;
51
+ max?: number;
52
+ ssl?: boolean | {
53
+ rejectUnauthorized?: boolean;
54
+ };
55
+ }) => PostgresQueryable;
56
+ export interface PostgresStorageOptions {
57
+ /**
58
+ * Pass `Pool` from `import { Pool } from "pg"` in the example that declares
59
+ * the `pg` dependency (hosted installs put it in that package's
60
+ * `node_modules` only).
61
+ */
62
+ Pool: PostgresPoolConstructor;
63
+ /** Postgres connection string (default: env, then local bugbot dev DB). */
64
+ databaseUrl?: string;
65
+ /** Value for the tables' deployment_id column (default: env or "local-dev"). */
66
+ deploymentId?: string;
67
+ }
68
+ type PostgresStorageMethods = Required<Pick<StorageConfig, "put" | "get" | "delete" | "list">> & {
69
+ evals: StorageEvalsTable;
70
+ abs: StorageABTable;
71
+ };
72
+ /** True for local bugbot/dev URLs that do not speak TLS. */
73
+ export declare function isLocalPostgresUrl(connectionString: string): boolean;
74
+ /** Postgres-backed `defineStorage` methods, ready to spread into `defineStorage({...})`. */
75
+ export declare function postgresStorage(options: PostgresStorageOptions): PostgresStorageMethods;
76
+ export {};
77
+ //# sourceMappingURL=postgres-kv.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgres-kv.d.ts","sourceRoot":"","sources":["../../src/storage-backends/postgres-kv.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAIH,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EAEb,iBAAiB,EAClB,MAAM,eAAe,CAAC;AAGvB,kFAAkF;AAClF,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/D,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,SAAS,OAAO,EAAE,GAC1B,OAAO,CAAC;QAAE,IAAI,EAAE,CAAC,EAAE,CAAA;KAAE,CAAC,CAAC;CAC3B;AAED,uEAAuE;AACvE,MAAM,MAAM,uBAAuB,GAAG,KAAK,MAAM,CAAC,EAAE;IAClD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,OAAO,GAAG;QAAE,kBAAkB,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CAClD,KAAK,iBAAiB,CAAC;AAExB,MAAM,WAAW,sBAAsB;IACrC;;;;OAIG;IACH,IAAI,EAAE,uBAAuB,CAAC;IAC9B,2EAA2E;IAC3E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gFAAgF;IAChF,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,KAAK,sBAAsB,GAAG,QAAQ,CACpC,IAAI,CAAC,aAAa,EAAE,KAAK,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC,CACvD,GAAG;IACF,KAAK,EAAE,iBAAiB,CAAC;IACzB,GAAG,EAAE,cAAc,CAAC;CACrB,CAAC;AAEF,4DAA4D;AAC5D,wBAAgB,kBAAkB,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAYpE;AAED,4FAA4F;AAC5F,wBAAgB,eAAe,CAC7B,OAAO,EAAE,sBAAsB,GAC9B,sBAAsB,CA4HxB"}
@@ -0,0 +1,180 @@
1
+ /**
2
+ * Postgres `defineStorage` helper on the agent-serve tables
3
+ * (backend/packages/prisma-bugbot):
4
+ *
5
+ * agent_serve_kv(deployment_id, key, value JSONB, updated_at)
6
+ * PRIMARY KEY (deployment_id, key)
7
+ * agent_serve_eval_runs(deployment_id, agent, run_id, run JSONB, updated_at)
8
+ * PRIMARY KEY (deployment_id, agent, run_id)
9
+ * agent_serve_ab(deployment_id, agent, kind, ref, value JSONB, updated_at)
10
+ * PRIMARY KEY (deployment_id, agent, kind, ref)
11
+ *
12
+ * `postgresStorage` implements the whole `defineStorage` surface as plain
13
+ * SQL: the four KV methods against the last-write-wins `agent_serve_kv`
14
+ * table (sessions, event chunks, continuations, reminders), the `evals`
15
+ * table against `agent_serve_eval_runs` (one row per playground eval
16
+ * batch), and the `abs` table against `agent_serve_ab` (`kind = 'sample'`
17
+ * rows per metric sample plus one `kind = 'snapshot'` row holding the
18
+ * latest aggregate).
19
+ *
20
+ * - KV `put` upserts on the primary key (LWW matches the framework contract).
21
+ * - KV `list` is a prefix range scan on the PK btree (`key >= p AND key < p||…`
22
+ * spelled as LIKE with escaped wildcards, ordered by key).
23
+ * - `get` returning no row is a definitive miss (`undefined`); a connection
24
+ * error throws, so lazy restore fails the follow-up instead of forking
25
+ * the session.
26
+ *
27
+ * Connection comes from `BUGBOTDB_URL` — the repo-wide convention for the
28
+ * bugbot Postgres database, whose Prisma package owns these tables' schema
29
+ * and migrations; locally it falls back to the dev bugbot DB. Non-local
30
+ * URLs enable TLS (`ssl.rejectUnauthorized`) because PlanetScale requires
31
+ * SSL even when the vault URL omits `sslmode`.
32
+ * `deploymentId` scopes rows per deployment (`AGENT_SERVE_DEPLOYMENT_ID`);
33
+ * the local default keeps dev runs of different checkouts from colliding
34
+ * only by agent name.
35
+ *
36
+ * Callers must pass `Pool` from their own `import { Pool } from "pg"`.
37
+ * This module must not import `pg` itself: Node resolves modules from
38
+ * *this* file's directory tree, so a `pg` dep declared only on the
39
+ * consuming agent package would never be found after a hosted install.
40
+ */
41
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
42
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
43
+ return new (P || (P = Promise))(function (resolve, reject) {
44
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
45
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
46
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
47
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
48
+ });
49
+ };
50
+ /** True for local bugbot/dev URLs that do not speak TLS. */
51
+ export function isLocalPostgresUrl(connectionString) {
52
+ try {
53
+ const host = new URL(connectionString).hostname.toLowerCase();
54
+ return (host === "localhost" ||
55
+ host === "127.0.0.1" ||
56
+ host === "::1" ||
57
+ host === "[::1]");
58
+ }
59
+ catch (_a) {
60
+ return /@(localhost|127\.0\.0\.1|\[::1\])([:/]|$)/i.test(connectionString);
61
+ }
62
+ }
63
+ /** Postgres-backed `defineStorage` methods, ready to spread into `defineStorage({...})`. */
64
+ export function postgresStorage(options) {
65
+ var _a, _b, _c, _d;
66
+ const connectionString = (_b = (_a = options.databaseUrl) !== null && _a !== void 0 ? _a : process.env.BUGBOTDB_URL) !== null && _b !== void 0 ? _b : "postgresql://prisma:prisma@localhost:5432/bugbot";
67
+ // Prod Bugbot is PlanetScale Postgres: TLS is required and the vault
68
+ // `BUGBOTDB_URL` often omits `sslmode`. Without an explicit `ssl` option,
69
+ // `pg` opens plaintext and PlanetScale rejects with "SSL connection is
70
+ // required" — sessions stay in-memory. Skip TLS only for local hosts.
71
+ const pool = new options.Pool(Object.assign({ connectionString,
72
+ // Small fixed pool per agent, mirroring the backend's connection_limit
73
+ // clamp on BUGBOTDB_URL consumers (backend/server/src/prisma.ts).
74
+ max: 3 }, (isLocalPostgresUrl(connectionString)
75
+ ? {}
76
+ : { ssl: { rejectUnauthorized: true } })));
77
+ const deploymentId = (_d = (_c = options.deploymentId) !== null && _c !== void 0 ? _c : process.env.AGENT_SERVE_DEPLOYMENT_ID) !== null && _d !== void 0 ? _d : "local-dev";
78
+ return {
79
+ put(key, value) {
80
+ return __awaiter(this, void 0, void 0, function* () {
81
+ yield pool.query(`INSERT INTO agent_serve_kv (deployment_id, key, value, updated_at)
82
+ VALUES ($1, $2, $3::jsonb, now())
83
+ ON CONFLICT ON CONSTRAINT pk_agent_serve_kv
84
+ DO UPDATE SET value = EXCLUDED.value, updated_at = now()`, [deploymentId, key, JSON.stringify(value)]);
85
+ });
86
+ },
87
+ get(key) {
88
+ return __awaiter(this, void 0, void 0, function* () {
89
+ var _a;
90
+ const result = yield pool.query(`SELECT value FROM agent_serve_kv
91
+ WHERE deployment_id = $1 AND key = $2`, [deploymentId, key]);
92
+ return (_a = result.rows[0]) === null || _a === void 0 ? void 0 : _a.value; // no row ⇒ definitive miss
93
+ });
94
+ },
95
+ delete(key) {
96
+ return __awaiter(this, void 0, void 0, function* () {
97
+ yield pool.query(`DELETE FROM agent_serve_kv WHERE deployment_id = $1 AND key = $2`, [deploymentId, key]);
98
+ });
99
+ },
100
+ list(prefix) {
101
+ return __awaiter(this, void 0, void 0, function* () {
102
+ // Escape LIKE wildcards in the prefix so keys containing % or _
103
+ // (URI-encoded segments cannot, but be safe) match literally.
104
+ const escaped = prefix.replace(/([\\%_])/g, "\\$1");
105
+ const result = yield pool.query(`SELECT key, value FROM agent_serve_kv
106
+ WHERE deployment_id = $1 AND key LIKE $2 ESCAPE '\\'
107
+ ORDER BY key ASC`, [deploymentId, `${escaped}%`]);
108
+ return result.rows;
109
+ });
110
+ },
111
+ // Playground eval batches → agent_serve_eval_runs (one row per run).
112
+ evals: {
113
+ put(run, ctx) {
114
+ return __awaiter(this, void 0, void 0, function* () {
115
+ yield pool.query(`INSERT INTO agent_serve_eval_runs (deployment_id, agent, run_id, run, updated_at)
116
+ VALUES ($1, $2, $3, $4::jsonb, now())
117
+ ON CONFLICT ON CONSTRAINT pk_agent_serve_eval_runs
118
+ DO UPDATE SET run = EXCLUDED.run, updated_at = now()`, [deploymentId, ctx.agentName, run.runId, JSON.stringify(run)]);
119
+ });
120
+ },
121
+ delete(runId, ctx) {
122
+ return __awaiter(this, void 0, void 0, function* () {
123
+ yield pool.query(`DELETE FROM agent_serve_eval_runs
124
+ WHERE deployment_id = $1 AND agent = $2 AND run_id = $3`, [deploymentId, ctx.agentName, runId]);
125
+ });
126
+ },
127
+ list(ctx) {
128
+ return __awaiter(this, void 0, void 0, function* () {
129
+ const result = yield pool.query(`SELECT run FROM agent_serve_eval_runs
130
+ WHERE deployment_id = $1 AND agent = $2`, [deploymentId, ctx.agentName]);
131
+ return result.rows.map((row) => row.run);
132
+ });
133
+ },
134
+ },
135
+ // A/B metrics → agent_serve_ab: sample rows plus one snapshot row.
136
+ abs: {
137
+ putSample(sample, ctx) {
138
+ return __awaiter(this, void 0, void 0, function* () {
139
+ yield upsertAbRow(pool, {
140
+ deploymentId,
141
+ agent: ctx.agentName,
142
+ kind: "sample",
143
+ // One boundary event emits a sample per enrolled experiment with
144
+ // the same sessionId/at — the experiment must be in the row key
145
+ // or those samples overwrite each other.
146
+ ref: `${sample.experiment}/${sample.sessionId}/${sample.at}`,
147
+ value: sample,
148
+ });
149
+ });
150
+ },
151
+ putSnapshot(snapshot, ctx) {
152
+ return __awaiter(this, void 0, void 0, function* () {
153
+ yield upsertAbRow(pool, {
154
+ deploymentId,
155
+ agent: ctx.agentName,
156
+ kind: "snapshot",
157
+ ref: "",
158
+ value: snapshot,
159
+ });
160
+ });
161
+ },
162
+ getSnapshot(ctx) {
163
+ return __awaiter(this, void 0, void 0, function* () {
164
+ var _a;
165
+ const result = yield pool.query(`SELECT value FROM agent_serve_ab
166
+ WHERE deployment_id = $1 AND agent = $2 AND kind = 'snapshot' AND ref = ''`, [deploymentId, ctx.agentName]);
167
+ return (_a = result.rows[0]) === null || _a === void 0 ? void 0 : _a.value;
168
+ });
169
+ },
170
+ },
171
+ };
172
+ }
173
+ function upsertAbRow(pool, row) {
174
+ return __awaiter(this, void 0, void 0, function* () {
175
+ yield pool.query(`INSERT INTO agent_serve_ab (deployment_id, agent, kind, ref, value, updated_at)
176
+ VALUES ($1, $2, $3, $4, $5::jsonb, now())
177
+ ON CONFLICT ON CONSTRAINT pk_agent_serve_ab
178
+ DO UPDATE SET value = EXCLUDED.value, updated_at = now()`, [row.deploymentId, row.agent, row.kind, row.ref, JSON.stringify(row.value)]);
179
+ });
180
+ }
package/dist/storage.d.ts CHANGED
@@ -33,7 +33,9 @@
33
33
  *
34
34
  * Because keys are opaque strings to the sink, new kinds of durable state
35
35
  * (channel cursors, thread affinity, …) are new key prefixes — existing
36
- * sinks store them with no code changes.
36
+ * sinks store them with no code changes. Authors can also store their own
37
+ * JSON under `agentkit/v1/{agent}/kv/…` via {@link HostContext.kv}; the
38
+ * framework still mints the full key from the author-supplied segment.
37
39
  *
38
40
  * Delivery semantics: writes are **serialized** (one sink call in flight
39
41
  * per agent, in order), **bounded** (a sink that falls behind sheds writes
@@ -205,6 +207,7 @@ export declare const STORAGE_KEY_ROOT: "agentkit/v1";
205
207
  * | `agentkit/v1/{agent}/session-events/{sessionId}/{index}` | `SessionEvent[]` chunk (index = first event's index, zero-padded) |
206
208
  * | `agentkit/v1/{agent}/continuation/{channelId}/{token}` | `{ sessionId }` |
207
209
  * | `agentkit/v1/{agent}/reminder/{reminderId}` | `ReminderRecord` |
210
+ * | `agentkit/v1/{agent}/kv/{key}` | Author JSON via {@link HostContext.kv} |
208
211
  *
209
212
  * Eval-run and A/B history do not flow through this KV scheme — they have
210
213
  * dedicated tables ({@link StorageConfig.evals} / {@link StorageConfig.abs}).
@@ -217,6 +220,12 @@ export declare const storageKeys: {
217
220
  readonly continuation: (agent: string, channelId: string, continuationKey: string) => string;
218
221
  readonly reminder: (agent: string, reminderId: string) => string;
219
222
  readonly reminderPrefix: (agent: string) => string;
223
+ /**
224
+ * Author-facing opaque JSON (see {@link HostContext.kv}). `key` is
225
+ * URI-encoded / digested like other caller-controlled segments.
226
+ */
227
+ readonly kv: (agent: string, key: string) => string;
228
+ readonly kvPrefix: (agent: string) => string;
220
229
  };
221
230
  /**
222
231
  * Max bytes a caller-controlled key segment may occupy after URI-encoding.
@@ -1 +1 @@
1
- {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAE5D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAM5C,wEAAwE;AACxE,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,SAAS,CAAC;CAClB;AAED,yCAAyC;AACzC,MAAM,WAAW,cAAc;IAC7B,uEAAuE;IACvE,SAAS,EAAE,MAAM,CAAC;IAClB,sEAAsE;IACtE,WAAW,EAAE,MAAM,CAAC;IACpB;;;;;OAKG;IACH,MAAM,EAAE,QAAQ,GAAG,UAAU,GAAG,SAAS,CAAC;CAC3C;AAED,MAAM,WAAW,aAAa;IAC5B;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;;;;OASG;IACH,OAAO,CAAC,EAAE,oBAAoB,GAAG,KAAK,CAAC;CACxC;AAED,mFAAmF;AACnF,MAAM,WAAW,oBAAoB;IACnC,wFAAwF;IACxF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,mEAAmE;IACnE,GAAG,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrE,gEAAgE;IAChE,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,cAAc,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE,+EAA+E;IAC/E,IAAI,CAAC,GAAG,EAAE,cAAc,GAAG,eAAe,EAAE,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;CAC3E;AAED;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B,gEAAgE;IAChE,SAAS,CAAC,MAAM,EAAE,cAAc,EAAE,GAAG,EAAE,cAAc,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7E,4EAA4E;IAC5E,WAAW,CAAC,CAAC,QAAQ,EAAE,UAAU,EAAE,GAAG,EAAE,cAAc,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9E,6EAA6E;IAC7E,WAAW,CAAC,CACV,GAAG,EAAE,cAAc,GAClB,UAAU,GAAG,SAAS,GAAG,IAAI,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,GAAG,IAAI,CAAC,CAAC;CAC3E;AAED,MAAM,WAAW,aAAa;IAC5B,6DAA6D;IAC7D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB;;;OAGG;IACH,KAAK,CAAC,EAAE,iBAAiB,CAAC;IAC1B;;;OAGG;IACH,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB;;;;;;OAMG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,cAAc,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9E,kEAAkE;IAClE,MAAM,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,cAAc,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChE;;;;;;;OAOG;IACH,GAAG,CAAC,CACF,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,cAAc,GAClB,SAAS,GAAG,SAAS,GAAG,IAAI,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,GAAG,IAAI,CAAC,CAAC;IACxE;;;;OAIG;IACH,IAAI,CAAC,CACH,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,cAAc,GAClB,YAAY,EAAE,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;CAC7C;AAED,MAAM,MAAM,iBAAiB,GAAG,aAAa,GAAG;IAC9C,QAAQ,CAAC,YAAY,EAAE,SAAS,CAAC;CAClC,CAAC;AAEF;;;GAGG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,iBAAiB,CAuCtE;AAMD;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAG,aAAsB,CAAC;AAEvD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,WAAW;aACtB,OAAO,UAAU,MAAM,aAAa,MAAM,KAAG,MAAM;aAEnD,aAAa,UAAU,MAAM,KAAG,MAAM;aAEtC,aAAa,UACJ,MAAM,aACF,MAAM,cACL,MAAM,KACjB,MAAM;aAET,mBAAmB,UAAU,MAAM,aAAa,MAAM,KAAG,MAAM;aAE/D,YAAY,UACH,MAAM,aACF,MAAM,mBACA,MAAM,KACtB,MAAM;aAET,QAAQ,UAAU,MAAM,cAAc,MAAM,KAAG,MAAM;aAErD,cAAc,UAAU,MAAM,KAAG,MAAM;CAE/B,CAAC;AAEX;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,MAAM,CAAC;AAoBzC,eAAO,MAAM,oCAAoC,OAAQ,CAAC;AAC1D,eAAO,MAAM,kCAAkC,EAAE,MAA8B,CAAC;AAChF,eAAO,MAAM,uCAAuC,aAAgB,CAAC;AAErE,mDAAmD;AACnD,MAAM,WAAW,qBAAqB;IACpC,sEAAsE;IACtE,MAAM,EAAE,SAAS,GAAG;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C,OAAO,EACH,KAAK,GACL;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC;CACtE;AAED,wEAAwE;AACxE,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,aAAa,GAAG,SAAS,GAChC,qBAAqB,CA8BvB"}
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"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"}
package/dist/storage.js CHANGED
@@ -33,7 +33,9 @@
33
33
  *
34
34
  * Because keys are opaque strings to the sink, new kinds of durable state
35
35
  * (channel cursors, thread affinity, …) are new key prefixes — existing
36
- * sinks store them with no code changes.
36
+ * sinks store them with no code changes. Authors can also store their own
37
+ * JSON under `agentkit/v1/{agent}/kv/…` via {@link HostContext.kv}; the
38
+ * framework still mints the full key from the author-supplied segment.
37
39
  *
38
40
  * Delivery semantics: writes are **serialized** (one sink call in flight
39
41
  * per agent, in order), **bounded** (a sink that falls behind sheds writes
@@ -106,6 +108,7 @@ export const STORAGE_KEY_ROOT = "agentkit/v1";
106
108
  * | `agentkit/v1/{agent}/session-events/{sessionId}/{index}` | `SessionEvent[]` chunk (index = first event's index, zero-padded) |
107
109
  * | `agentkit/v1/{agent}/continuation/{channelId}/{token}` | `{ sessionId }` |
108
110
  * | `agentkit/v1/{agent}/reminder/{reminderId}` | `ReminderRecord` |
111
+ * | `agentkit/v1/{agent}/kv/{key}` | Author JSON via {@link HostContext.kv} |
109
112
  *
110
113
  * Eval-run and A/B history do not flow through this KV scheme — they have
111
114
  * dedicated tables ({@link StorageConfig.evals} / {@link StorageConfig.abs}).
@@ -118,6 +121,12 @@ export const storageKeys = {
118
121
  continuation: (agent, channelId, continuationKey) => `${STORAGE_KEY_ROOT}/${agent}/continuation/${keySegment(channelId)}/${keySegment(continuationKey)}`,
119
122
  reminder: (agent, reminderId) => `${STORAGE_KEY_ROOT}/${agent}/reminder/${reminderId}`,
120
123
  reminderPrefix: (agent) => `${STORAGE_KEY_ROOT}/${agent}/reminder/`,
124
+ /**
125
+ * Author-facing opaque JSON (see {@link HostContext.kv}). `key` is
126
+ * URI-encoded / digested like other caller-controlled segments.
127
+ */
128
+ kv: (agent, key) => `${STORAGE_KEY_ROOT}/${agent}/kv/${keySegment(key)}`,
129
+ kvPrefix: (agent) => `${STORAGE_KEY_ROOT}/${agent}/kv/`,
121
130
  };
122
131
  /**
123
132
  * Max bytes a caller-controlled key segment may occupy after URI-encoding.