@cursor/july 0.1.48 → 0.1.51

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 (151) hide show
  1. package/AGENTS.md +3 -3
  2. package/README.md +7 -14
  3. package/dist/bin/agent-serve.js +22 -8
  4. package/dist/channels/slack/init.d.ts +2 -3
  5. package/dist/channels/slack/init.d.ts.map +1 -1
  6. package/dist/channels/slack/init.js +8 -43
  7. package/dist/channels/slack/manifest.d.ts +3 -3
  8. package/dist/channels/slack/manifest.js +3 -3
  9. package/dist/channels/slack/setup.d.ts +2 -11
  10. package/dist/channels/slack/setup.d.ts.map +1 -1
  11. package/dist/channels/slack/setup.js +26 -94
  12. package/dist/channels/slack/types.d.ts +3 -4
  13. package/dist/channels/slack/types.d.ts.map +1 -1
  14. package/dist/docs/404.html +2 -2
  15. package/dist/docs/ab.html +5 -5
  16. package/dist/docs/assets/{ab.md.hdxsvX5M.js → ab.md.DYjwREAP.js} +2 -2
  17. package/dist/docs/assets/{ab.md.hdxsvX5M.lean.js → ab.md.DYjwREAP.lean.js} +1 -1
  18. package/dist/docs/assets/{app.BC1P20xI.js → app.C51TX1Bw.js} +1 -1
  19. package/dist/docs/assets/chunks/@localSearchIndexroot.D2DpXdZN.js +1 -0
  20. package/dist/docs/assets/chunks/{VPLocalSearchBox.C_900xn2.js → VPLocalSearchBox.BB9HCJPq.js} +1 -1
  21. package/dist/docs/assets/chunks/{theme.CT135Jhh.js → theme.Dp-0SZcu.js} +2 -2
  22. package/dist/docs/assets/{deployment.md.Cdp4rTE4.js → deployment.md.B8kW-h7P.js} +1 -1
  23. package/dist/docs/assets/{evals.md.qeoGgPw0.js → evals.md.CVe_O75-.js} +3 -3
  24. package/dist/docs/assets/{evals.md.qeoGgPw0.lean.js → evals.md.CVe_O75-.lean.js} +1 -1
  25. package/dist/docs/assets/{example-agents_benny.md.l7JTmm8X.js → example-agents_benny.md.B-LIDGja.js} +1 -1
  26. package/dist/docs/assets/{example-agents_oncall.md.ZE0n6ZFN.js → example-agents_oncall.md.CBmyuAKc.js} +2 -2
  27. package/dist/docs/assets/{guides_human-in-the-loop.md.BWvT7UqY.js → guides_human-in-the-loop.md.Cf8kIIqC.js} +2 -2
  28. package/dist/docs/assets/{guides_human-in-the-loop.md.BWvT7UqY.lean.js → guides_human-in-the-loop.md.Cf8kIIqC.lean.js} +1 -1
  29. package/dist/docs/assets/{guides_slack.md.zriQpU_9.js → guides_slack.md.D2nTRu9M.js} +7 -12
  30. package/dist/docs/assets/guides_slack.md.D2nTRu9M.lean.js +1 -0
  31. package/dist/docs/assets/{reference_cli.md.BDmjPPAm.js → reference_cli.md.CGKfz_Yj.js} +3 -7
  32. package/dist/docs/assets/{reference_cli.md.BDmjPPAm.lean.js → reference_cli.md.CGKfz_Yj.lean.js} +1 -1
  33. package/dist/docs/assets/{reference_http-api.md.DGrw_wOu.js → reference_http-api.md.DMbdFGVQ.js} +1 -1
  34. package/dist/docs/assets/{storage.md.CJYd5YmN.js → storage.md.D8NQ389l.js} +3 -3
  35. package/dist/docs/assets/storage.md.D8NQ389l.lean.js +1 -0
  36. package/dist/docs/assets/{troubleshooting.md.CkgwmVI0.js → troubleshooting.md.C6n3wCr6.js} +1 -1
  37. package/dist/docs/building-with-agents.html +3 -3
  38. package/dist/docs/concepts.html +3 -3
  39. package/dist/docs/deployment.html +5 -5
  40. package/dist/docs/evals.html +6 -6
  41. package/dist/docs/example-agents/approval-buddy.html +3 -3
  42. package/dist/docs/example-agents/benny.html +5 -5
  43. package/dist/docs/example-agents/bugbot.html +3 -3
  44. package/dist/docs/example-agents/codebase-wiki.html +3 -3
  45. package/dist/docs/example-agents/codeowners-review.html +3 -3
  46. package/dist/docs/example-agents/concierge.html +3 -3
  47. package/dist/docs/example-agents/fsd.html +3 -3
  48. package/dist/docs/example-agents/index.html +3 -3
  49. package/dist/docs/example-agents/knowledge-base.html +3 -3
  50. package/dist/docs/example-agents/oncall.html +6 -6
  51. package/dist/docs/example-agents/security-reviewer.html +3 -3
  52. package/dist/docs/example-agents/slack-agent.html +3 -3
  53. package/dist/docs/example-agents/weather-agent.html +3 -3
  54. package/dist/docs/guides/agent-to-agent.html +3 -3
  55. package/dist/docs/guides/cloud-runtime.html +3 -3
  56. package/dist/docs/guides/github.html +3 -3
  57. package/dist/docs/guides/human-in-the-loop.html +5 -5
  58. package/dist/docs/guides/mcp-oauth.html +3 -3
  59. package/dist/docs/guides/opentelemetry.html +3 -3
  60. package/dist/docs/guides/slack.html +11 -16
  61. package/dist/docs/guides/webhooks.html +3 -3
  62. package/dist/docs/hashmap.json +1 -1
  63. package/dist/docs/hillclimbing.html +3 -3
  64. package/dist/docs/index.html +3 -3
  65. package/dist/docs/quickstart.html +3 -3
  66. package/dist/docs/reference/agent-config.html +3 -3
  67. package/dist/docs/reference/artifacts.html +3 -3
  68. package/dist/docs/reference/channels.html +3 -3
  69. package/dist/docs/reference/cli.html +6 -10
  70. package/dist/docs/reference/connections.html +3 -3
  71. package/dist/docs/reference/hooks.html +3 -3
  72. package/dist/docs/reference/http-api.html +5 -5
  73. package/dist/docs/reference/instructions.html +3 -3
  74. package/dist/docs/reference/playground.html +3 -3
  75. package/dist/docs/reference/project-layout.html +3 -3
  76. package/dist/docs/reference/prompt.html +3 -3
  77. package/dist/docs/reference/schedules.html +3 -3
  78. package/dist/docs/reference/sessions.html +3 -3
  79. package/dist/docs/reference/skills.html +3 -3
  80. package/dist/docs/reference/subagents.html +3 -3
  81. package/dist/docs/reference/tools.html +3 -3
  82. package/dist/docs/scaffolding-agents.html +3 -3
  83. package/dist/docs/storage.html +5 -5
  84. package/dist/docs/templates/triage.html +3 -3
  85. package/dist/docs/troubleshooting.html +5 -5
  86. package/dist/internal/cli-ax.js +3 -3
  87. package/dist/internal/cli-cursor.d.ts +18 -0
  88. package/dist/internal/cli-cursor.d.ts.map +1 -1
  89. package/dist/internal/cli-cursor.js +25 -0
  90. package/dist/internal/cli-slack.d.ts +3 -4
  91. package/dist/internal/cli-slack.d.ts.map +1 -1
  92. package/dist/internal/cli-slack.js +126 -325
  93. package/dist/internal/convert-automation/convert-workflow.js +2 -2
  94. package/dist/internal/event-log.d.ts +17 -0
  95. package/dist/internal/event-log.d.ts.map +1 -1
  96. package/dist/internal/event-log.js +32 -2
  97. package/dist/internal/process-memory-telemetry.d.ts +90 -0
  98. package/dist/internal/process-memory-telemetry.d.ts.map +1 -0
  99. package/dist/internal/process-memory-telemetry.js +259 -0
  100. package/dist/internal/server.d.ts.map +1 -1
  101. package/dist/internal/server.js +9 -10
  102. package/dist/internal/session-engine.d.ts +4 -0
  103. package/dist/internal/session-engine.d.ts.map +1 -1
  104. package/dist/internal/session-engine.js +19 -5
  105. package/dist/internal/slack-provision-client.d.ts +41 -6
  106. package/dist/internal/slack-provision-client.d.ts.map +1 -1
  107. package/dist/internal/slack-provision-client.js +53 -7
  108. package/dist/playground/assets/{index-DEVTyeOu.js → index-BKMz70wx.js} +41 -41
  109. package/dist/playground/assets/index-BmMrulSc.css +1 -0
  110. package/dist/playground/index.html +2 -2
  111. package/dist/storage.d.ts +36 -10
  112. package/dist/storage.d.ts.map +1 -1
  113. package/dist/storage.js +82 -6
  114. package/docs/ab.md +4 -3
  115. package/docs/deployment.md +1 -1
  116. package/docs/evals.md +10 -7
  117. package/docs/example-agents/benny.md +2 -3
  118. package/docs/example-agents/oncall.md +4 -5
  119. package/docs/guides/human-in-the-loop.md +1 -1
  120. package/docs/guides/slack.md +51 -112
  121. package/docs/reference/cli.md +14 -37
  122. package/docs/reference/http-api.md +4 -3
  123. package/docs/storage.md +38 -22
  124. package/docs/troubleshooting.md +2 -2
  125. package/package.json +1 -1
  126. package/skills/create-agent/SKILL.md +4 -5
  127. package/skills/setup-slack/SKILL.md +74 -132
  128. package/src/bin/agent-serve.ts +26 -9
  129. package/src/channels/slack/init.ts +10 -71
  130. package/src/channels/slack/manifest.ts +3 -3
  131. package/src/channels/slack/setup.ts +25 -103
  132. package/src/channels/slack/types.ts +3 -4
  133. package/src/internal/cli-ax.ts +3 -3
  134. package/src/internal/cli-cursor.ts +34 -0
  135. package/src/internal/cli-slack.ts +136 -394
  136. package/src/internal/convert-automation/convert-workflow.ts +2 -2
  137. package/src/internal/event-log.ts +45 -7
  138. package/src/internal/process-memory-telemetry.ts +373 -0
  139. package/src/internal/server.ts +13 -0
  140. package/src/internal/session-engine.ts +20 -1
  141. package/src/internal/slack-provision-client.ts +90 -9
  142. package/src/storage.ts +130 -11
  143. package/dist/docs/assets/chunks/@localSearchIndexroot.DV5SAHnQ.js +0 -1
  144. package/dist/docs/assets/guides_slack.md.zriQpU_9.lean.js +0 -1
  145. package/dist/docs/assets/storage.md.CJYd5YmN.lean.js +0 -1
  146. package/dist/playground/assets/index-CiCmH6R-.css +0 -1
  147. /package/dist/docs/assets/{deployment.md.Cdp4rTE4.lean.js → deployment.md.B8kW-h7P.lean.js} +0 -0
  148. /package/dist/docs/assets/{example-agents_benny.md.l7JTmm8X.lean.js → example-agents_benny.md.B-LIDGja.lean.js} +0 -0
  149. /package/dist/docs/assets/{example-agents_oncall.md.ZE0n6ZFN.lean.js → example-agents_oncall.md.CBmyuAKc.lean.js} +0 -0
  150. /package/dist/docs/assets/{reference_http-api.md.DGrw_wOu.lean.js → reference_http-api.md.DMbdFGVQ.lean.js} +0 -0
  151. /package/dist/docs/assets/{troubleshooting.md.CkgwmVI0.lean.js → troubleshooting.md.C6n3wCr6.lean.js} +0 -0
@@ -6,11 +6,11 @@
6
6
  *
7
7
  * Auth is the user API key sent directly as the bearer (the routes are
8
8
  * `wrapUserApiRoute` on the backend); there is no token exchange here.
9
- * The endpoints are gated on the `agent_serve_slack_provisioning` Statsig
10
- * gate and 404 when it is off — the error mapping says so instead of
11
- * "not found". Expected provisioning failures carry a stable JSON `code`
9
+ * The endpoints ride `requireAgentServeAccess` and 404 `{ error: "Not found" }`
10
+ * when Agent Serve is off — same mapping as other agent-sdk deploy 404s.
11
+ * Expected provisioning failures carry a stable JSON `code`
12
12
  * (`not_connected`, `insufficient_scopes`, `manager_reauth_required`,
13
- * `app_conflict`, `app_cap_reached`, `ratelimited`, `invalid_app_id`, …)
13
+ * `app_conflict`, `ratelimited`, `invalid_app_id`, …)
14
14
  * which flows through on {@link SlackProvisionApiError.code} so the CLI
15
15
  * can branch.
16
16
  */
@@ -55,8 +55,8 @@ export type SlackAppIconInput =
55
55
  * Outcome of `POST /apps`. Credentials are returned exactly once and never
56
56
  * persisted server-side — the caller owns storing them. `appToken` can be
57
57
  * absent when Slack's install response omitted the app-level token.
58
- * `oauthAuthorizeUrl` is only minted on a fresh app create, so an update
59
- * that lands in admin approval omits it.
58
+ * `oauthAuthorizeUrl` is Slack's request-approval / reminder page. Fresh
59
+ * creates mint it; updates return it when Slack (or a persisted row) has one.
60
60
  */
61
61
  export type SlackAppProvisionResult =
62
62
  | {
@@ -176,6 +176,66 @@ const setIconResponseSchema = z
176
176
  })
177
177
  .passthrough();
178
178
 
179
+ const mintWizardResponseSchema = z
180
+ .object({
181
+ wizardId: z.string().min(1),
182
+ url: z.string().min(1),
183
+ })
184
+ .passthrough();
185
+
186
+ const wizardPollResponseSchema = z
187
+ .object({
188
+ wizardId: z.string(),
189
+ teamId: z.number(),
190
+ slug: z.string(),
191
+ env: z.string(),
192
+ status: z.string(),
193
+ appId: z.string().optional(),
194
+ oauthAuthorizeUrl: z.string().optional(),
195
+ error: z.string().optional(),
196
+ localEnv: z
197
+ .object({
198
+ botToken: z.string().min(1),
199
+ appToken: z.string().optional(),
200
+ })
201
+ .optional(),
202
+ localEnvClaimed: z.boolean().optional(),
203
+ })
204
+ .passthrough();
205
+
206
+ export interface SlackWizardMintResult {
207
+ wizardId: string;
208
+ url: string;
209
+ }
210
+
211
+ export interface SlackWizardPollResult {
212
+ wizardId: string;
213
+ teamId: number;
214
+ slug: string;
215
+ env: string;
216
+ status: string;
217
+ appId?: string;
218
+ oauthAuthorizeUrl?: string;
219
+ error?: string;
220
+ localEnv?: { botToken: string; appToken?: string };
221
+ localEnvClaimed?: boolean;
222
+ }
223
+
224
+ export interface SlackWizardMintInput {
225
+ teamId: number;
226
+ slug: string;
227
+ env: SlackAppEnv;
228
+ envPrefix?: string;
229
+ name?: string;
230
+ gitRepoUrl?: string;
231
+ gitRef?: string;
232
+ agentPath?: string;
233
+ channelPosts?: boolean;
234
+ slackTeamId?: string;
235
+ iconUrl?: string;
236
+ force?: boolean;
237
+ }
238
+
179
239
  // ============================================================================
180
240
  // Client
181
241
  // ============================================================================
@@ -224,6 +284,27 @@ export class AgentServeSlackClient {
224
284
  return connectResponseSchema.parse(raw).url;
225
285
  }
226
286
 
287
+ async mintWizard(
288
+ input: SlackWizardMintInput
289
+ ): Promise<SlackWizardMintResult> {
290
+ const raw = await this.request({
291
+ method: "POST",
292
+ path: "/internal/agent-serve/slack/wizard",
293
+ body: input,
294
+ context: { verb: "start Slack setup" },
295
+ });
296
+ return mintWizardResponseSchema.parse(raw);
297
+ }
298
+
299
+ async pollWizard(wizardId: string): Promise<SlackWizardPollResult> {
300
+ const raw = await this.request({
301
+ method: "GET",
302
+ path: `/internal/agent-serve/slack/wizard/${encodeURIComponent(wizardId)}`,
303
+ context: { verb: "poll Slack setup" },
304
+ });
305
+ return wizardPollResponseSchema.parse(raw);
306
+ }
307
+
227
308
  /**
228
309
  * Provision (create or update) and install one managed Slack app for
229
310
  * (slackTeamId, slug, env). Expected failures throw
@@ -398,8 +479,8 @@ function mapErrorResponse(
398
479
  { status: 404 }
399
480
  );
400
481
  }
401
- // The gate-off body is exactly {error: "Not found"}; anything else
402
- // (e.g. "App not found" on delete) is a real not-found to surface.
482
+ // `{ error: "Not found" }` is Agent Serve off (`requireAgentServeAccess`),
483
+ // not a Slack-only enrollment bar.
403
484
  if (serverError !== undefined && serverError !== "Not found") {
404
485
  return new SlackProvisionApiError(serverError, {
405
486
  status: 404,
@@ -407,7 +488,7 @@ function mapErrorResponse(
407
488
  });
408
489
  }
409
490
  return new SlackProvisionApiError(
410
- `Not found — Cursor's "Add to Slack" provisioning (the agent_serve_slack_provisioning feature gate) is not enabled for this account yet.`,
491
+ `Not found — the agent_serve_mvp feature gate may not be enabled for your team.`,
411
492
  { status: 404 }
412
493
  );
413
494
  }
package/src/storage.ts CHANGED
@@ -9,9 +9,12 @@
9
9
  * The sink is a plain key-value store — put/get/delete/list, no schema —
10
10
  * plus a conditional-write group ({@link StorageConfig.cas}, the substrate
11
11
  * for framework coordination; optional for plain storage, required by
12
- * coordination features) and two optional dedicated tables
13
- * ({@link StorageConfig.evals} and {@link StorageConfig.abs}) for
14
- * eval-run and A/B history:
12
+ * coordination features). Implementing that small KV core is enough for
13
+ * FULL functionality: eval-run and A/B history are derived over the core
14
+ * when the optional dedicated tables ({@link StorageConfig.evals} and
15
+ * {@link StorageConfig.abs}) are not authored — those groups exist as
16
+ * backend-native optimizations (a real table, an analytics pipeline),
17
+ * not as required-or-lose-history hooks:
15
18
  *
16
19
  * ```ts
17
20
  * import { defineStorage } from "@anysphere/agent-serve/storage";
@@ -207,13 +210,20 @@ export interface StorageConfig {
207
210
  /** Timing knobs; see {@link StoragePolicy}. */
208
211
  policy?: StoragePolicy;
209
212
  /**
210
- * Dedicated eval-runs table. Omit it and playground eval history stays
211
- * in process memory (lost on restart).
213
+ * Dedicated eval-runs table a backend-native optimization, not a
214
+ * requirement. When omitted, `defineStorage` derives the table over the
215
+ * KV core (one key per run under `agentkit/v1/{agent}/eval-runs/`),
216
+ * which needs core `put`, `delete`, and `list`; only when the core
217
+ * lacks `delete` or `list` does playground eval history stay in process
218
+ * memory (lost on restart).
212
219
  */
213
220
  evals?: StorageEvalsTable;
214
221
  /**
215
- * Dedicated A/B table. Omit it and metric samples are not exported
216
- * (session event logs remain the assignment/fold source of truth).
222
+ * Dedicated A/B table a backend-native optimization, not a
223
+ * requirement. When omitted, `defineStorage` derives it over the KV
224
+ * core: `putSample` and `putSnapshot` need only core `put` (always
225
+ * present), `getSnapshot` additionally needs core `get`. Session event
226
+ * logs remain the assignment/fold source of truth either way.
217
227
  */
218
228
  abs?: StorageABTable;
219
229
  /**
@@ -249,7 +259,8 @@ export interface StorageConfig {
249
259
  /**
250
260
  * All entries under a key prefix, in ascending key order. Optional —
251
261
  * required for the **startup bulk restore** (sessions + event streams)
252
- * and playground eval history.
262
+ * and, together with `delete`, for the derived eval-runs table
263
+ * (playground eval history).
253
264
  */
254
265
  list?(
255
266
  prefix: string,
@@ -326,7 +337,91 @@ export function defineStorage(config: StorageConfig): StorageDefinition {
326
337
  }
327
338
  // Validate eagerly so a bad policy fails at discovery, not first flush.
328
339
  resolveStoragePolicy(config.policy);
329
- return brandDefinition("storage", config);
340
+ // A backend that implements only the KV core gets full functionality:
341
+ // the dedicated tables are backend-native optimizations, derived over
342
+ // the core when absent. Authored groups always win.
343
+ const derivedEvals =
344
+ config.evals === undefined ? deriveEvalsTable(config) : undefined;
345
+ const derivedAbs =
346
+ config.abs === undefined ? deriveAbsTable(config) : undefined;
347
+ return brandDefinition("storage", {
348
+ ...config,
349
+ ...(derivedEvals === undefined ? {} : { evals: derivedEvals }),
350
+ ...(derivedAbs === undefined ? {} : { abs: derivedAbs }),
351
+ });
352
+ }
353
+
354
+ /**
355
+ * Eval-runs table over the KV core: one key per run under
356
+ * {@link storageKeys.evalRun}, hydrate via prefix `list`, prune via
357
+ * `delete`. Requires core `put` + `delete` + `list`; without `delete` or
358
+ * `list` there is no derivation (pruning or hydration would silently not
359
+ * work) and eval history stays in process memory.
360
+ */
361
+ function deriveEvalsTable(
362
+ config: StorageConfig
363
+ ): StorageEvalsTable | undefined {
364
+ if (config.delete === undefined || config.list === undefined) {
365
+ return undefined;
366
+ }
367
+ return {
368
+ put: (run, ctx) =>
369
+ config.put(
370
+ storageKeys.evalRun(ctx.agentName, run.runId),
371
+ run as unknown as JsonValue,
372
+ ctx
373
+ ),
374
+ delete: (runId, ctx) =>
375
+ config.delete?.(storageKeys.evalRun(ctx.agentName, runId), ctx),
376
+ list: async (ctx) => {
377
+ const entries =
378
+ (await config.list?.(storageKeys.evalRunsPrefix(ctx.agentName), ctx)) ??
379
+ [];
380
+ return entries.map((entry) => entry.value as unknown as EvalRunSnapshot);
381
+ },
382
+ };
383
+ }
384
+
385
+ /**
386
+ * A/B table over the KV core. Each sample lands as its own key (identity
387
+ * = experiment + sessionId + at, matching the dedicated table's row
388
+ * uniqueness): appending to one array value would need read-modify-write
389
+ * — lost updates under concurrent writers without CAS, and unbounded
390
+ * value growth — while a key per sample keeps `putSample` a blind put
391
+ * with real append-only semantics. The aggregate snapshot lives at one
392
+ * fixed key via plain `put` (last-write-wins is correct for "latest").
393
+ * Requires only core `put`; `getSnapshot` is included when core `get`
394
+ * exists.
395
+ */
396
+ function deriveAbsTable(config: StorageConfig): StorageABTable {
397
+ const get = config.get;
398
+ return {
399
+ putSample: (sample, ctx) =>
400
+ config.put(
401
+ storageKeys.abSample(
402
+ ctx.agentName,
403
+ sample.experiment,
404
+ sample.sessionId,
405
+ sample.at
406
+ ),
407
+ sample as unknown as JsonValue,
408
+ ctx
409
+ ),
410
+ putSnapshot: (snapshot, ctx) =>
411
+ config.put(
412
+ storageKeys.abSnapshot(ctx.agentName),
413
+ snapshot as unknown as JsonValue,
414
+ ctx
415
+ ),
416
+ ...(get === undefined
417
+ ? {}
418
+ : {
419
+ getSnapshot: async (ctx: StorageContext) => {
420
+ const value = await get(storageKeys.abSnapshot(ctx.agentName), ctx);
421
+ return (value ?? undefined) as ABSnapshot | undefined;
422
+ },
423
+ }),
424
+ };
330
425
  }
331
426
 
332
427
  // ============================================================================
@@ -357,9 +452,14 @@ export const STORAGE_KEY_ROOT = "agentkit/v1" as const;
357
452
  * | `agentkit/v1/{agent}/session-events/{sessionId}/{index}` | `SessionEvent[]` chunk (index = first event's index, zero-padded) |
358
453
  * | `agentkit/v1/{agent}/continuation/{channelId}/{token}` | `{ sessionId }` |
359
454
  * | `agentkit/v1/{agent}/kv/{key}` | Author JSON via {@link HostContext.kv} |
455
+ * | `agentkit/v1/{agent}/eval-runs/{runId}` | `EvalRunSnapshot` (derived `evals` table) |
456
+ * | `agentkit/v1/{agent}/ab-samples/{experiment}/{sessionId}/{at}` | `ABMetricSample` (derived `abs` table, append-only) |
457
+ * | `agentkit/v1/{agent}/ab-snapshot` | `ABSnapshot` (derived `abs` table, LWW) |
360
458
  *
361
- * Eval-run and A/B history do not flow through this KV scheme — they have
362
- * dedicated tables ({@link StorageConfig.evals} / {@link StorageConfig.abs}).
459
+ * The `eval-runs` / `ab-samples` / `ab-snapshot` families are minted only
460
+ * by the tables `defineStorage` derives over the KV core; a backend that
461
+ * authors dedicated {@link StorageConfig.evals} / {@link StorageConfig.abs}
462
+ * groups never sees them.
363
463
  */
364
464
  export const storageKeys = {
365
465
  session: (agent: string, sessionId: string): string =>
@@ -387,6 +487,25 @@ export const storageKeys = {
387
487
  kv: (agent: string, key: string): string =>
388
488
  `${STORAGE_KEY_ROOT}/${agent}/kv/${keySegment(key)}`,
389
489
  kvPrefix: (agent: string): string => `${STORAGE_KEY_ROOT}/${agent}/kv/`,
490
+ /** One playground eval-run snapshot (derived `evals` table). */
491
+ evalRun: (agent: string, runId: string): string =>
492
+ `${STORAGE_KEY_ROOT}/${agent}/eval-runs/${keySegment(runId)}`,
493
+ evalRunsPrefix: (agent: string): string =>
494
+ `${STORAGE_KEY_ROOT}/${agent}/eval-runs/`,
495
+ /**
496
+ * One A/B metric sample (derived `abs` table); the segments mirror the
497
+ * dedicated table's row identity (experiment + sessionId + at).
498
+ */
499
+ abSample: (
500
+ agent: string,
501
+ experiment: string,
502
+ sessionId: string,
503
+ at: string
504
+ ): string =>
505
+ `${STORAGE_KEY_ROOT}/${agent}/ab-samples/${keySegment(experiment)}/${keySegment(sessionId)}/${keySegment(at)}`,
506
+ /** Latest aggregate A/B snapshot (derived `abs` table, LWW). */
507
+ abSnapshot: (agent: string): string =>
508
+ `${STORAGE_KEY_ROOT}/${agent}/ab-snapshot`,
390
509
  } as const;
391
510
 
392
511
  /**