@cursor/july 0.1.48 → 0.1.49

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 (99) hide show
  1. package/dist/docs/404.html +2 -2
  2. package/dist/docs/ab.html +5 -5
  3. package/dist/docs/assets/{ab.md.hdxsvX5M.js → ab.md.DYjwREAP.js} +2 -2
  4. package/dist/docs/assets/{ab.md.hdxsvX5M.lean.js → ab.md.DYjwREAP.lean.js} +1 -1
  5. package/dist/docs/assets/{app.BC1P20xI.js → app.BpWAgjaR.js} +1 -1
  6. package/dist/docs/assets/chunks/@localSearchIndexroot.D00d772K.js +1 -0
  7. package/dist/docs/assets/chunks/{VPLocalSearchBox.C_900xn2.js → VPLocalSearchBox.CnAktZtG.js} +1 -1
  8. package/dist/docs/assets/chunks/{theme.CT135Jhh.js → theme.B5IvUxOB.js} +2 -2
  9. package/dist/docs/assets/{evals.md.qeoGgPw0.js → evals.md.CVe_O75-.js} +3 -3
  10. package/dist/docs/assets/{evals.md.qeoGgPw0.lean.js → evals.md.CVe_O75-.lean.js} +1 -1
  11. package/dist/docs/assets/{reference_http-api.md.DGrw_wOu.js → reference_http-api.md.DMbdFGVQ.js} +1 -1
  12. package/dist/docs/assets/{storage.md.CJYd5YmN.js → storage.md.D8NQ389l.js} +3 -3
  13. package/dist/docs/assets/storage.md.D8NQ389l.lean.js +1 -0
  14. package/dist/docs/building-with-agents.html +3 -3
  15. package/dist/docs/concepts.html +3 -3
  16. package/dist/docs/deployment.html +3 -3
  17. package/dist/docs/evals.html +6 -6
  18. package/dist/docs/example-agents/approval-buddy.html +3 -3
  19. package/dist/docs/example-agents/benny.html +3 -3
  20. package/dist/docs/example-agents/bugbot.html +3 -3
  21. package/dist/docs/example-agents/codebase-wiki.html +3 -3
  22. package/dist/docs/example-agents/codeowners-review.html +3 -3
  23. package/dist/docs/example-agents/concierge.html +3 -3
  24. package/dist/docs/example-agents/fsd.html +3 -3
  25. package/dist/docs/example-agents/index.html +3 -3
  26. package/dist/docs/example-agents/knowledge-base.html +3 -3
  27. package/dist/docs/example-agents/oncall.html +3 -3
  28. package/dist/docs/example-agents/security-reviewer.html +3 -3
  29. package/dist/docs/example-agents/slack-agent.html +3 -3
  30. package/dist/docs/example-agents/weather-agent.html +3 -3
  31. package/dist/docs/guides/agent-to-agent.html +3 -3
  32. package/dist/docs/guides/cloud-runtime.html +3 -3
  33. package/dist/docs/guides/github.html +3 -3
  34. package/dist/docs/guides/human-in-the-loop.html +3 -3
  35. package/dist/docs/guides/mcp-oauth.html +3 -3
  36. package/dist/docs/guides/opentelemetry.html +3 -3
  37. package/dist/docs/guides/slack.html +3 -3
  38. package/dist/docs/guides/webhooks.html +3 -3
  39. package/dist/docs/hashmap.json +1 -1
  40. package/dist/docs/hillclimbing.html +3 -3
  41. package/dist/docs/index.html +3 -3
  42. package/dist/docs/quickstart.html +3 -3
  43. package/dist/docs/reference/agent-config.html +3 -3
  44. package/dist/docs/reference/artifacts.html +3 -3
  45. package/dist/docs/reference/channels.html +3 -3
  46. package/dist/docs/reference/cli.html +3 -3
  47. package/dist/docs/reference/connections.html +3 -3
  48. package/dist/docs/reference/hooks.html +3 -3
  49. package/dist/docs/reference/http-api.html +5 -5
  50. package/dist/docs/reference/instructions.html +3 -3
  51. package/dist/docs/reference/playground.html +3 -3
  52. package/dist/docs/reference/project-layout.html +3 -3
  53. package/dist/docs/reference/prompt.html +3 -3
  54. package/dist/docs/reference/schedules.html +3 -3
  55. package/dist/docs/reference/sessions.html +3 -3
  56. package/dist/docs/reference/skills.html +3 -3
  57. package/dist/docs/reference/subagents.html +3 -3
  58. package/dist/docs/reference/tools.html +3 -3
  59. package/dist/docs/scaffolding-agents.html +3 -3
  60. package/dist/docs/storage.html +5 -5
  61. package/dist/docs/templates/triage.html +3 -3
  62. package/dist/docs/troubleshooting.html +3 -3
  63. package/dist/internal/cli-slack.js +0 -3
  64. package/dist/internal/event-log.d.ts +17 -0
  65. package/dist/internal/event-log.d.ts.map +1 -1
  66. package/dist/internal/event-log.js +32 -2
  67. package/dist/internal/process-memory-telemetry.d.ts +90 -0
  68. package/dist/internal/process-memory-telemetry.d.ts.map +1 -0
  69. package/dist/internal/process-memory-telemetry.js +259 -0
  70. package/dist/internal/server.d.ts.map +1 -1
  71. package/dist/internal/server.js +9 -10
  72. package/dist/internal/session-engine.d.ts +4 -0
  73. package/dist/internal/session-engine.d.ts.map +1 -1
  74. package/dist/internal/session-engine.js +19 -5
  75. package/dist/internal/slack-provision-client.d.ts +4 -4
  76. package/dist/internal/slack-provision-client.js +7 -7
  77. package/dist/playground/assets/index-Dox74yWJ.css +1 -0
  78. package/dist/playground/assets/{index-DEVTyeOu.js → index-Dq_HqyU-.js} +41 -41
  79. package/dist/playground/index.html +2 -2
  80. package/dist/storage.d.ts +36 -10
  81. package/dist/storage.d.ts.map +1 -1
  82. package/dist/storage.js +82 -6
  83. package/docs/ab.md +4 -3
  84. package/docs/evals.md +10 -7
  85. package/docs/reference/http-api.md +4 -3
  86. package/docs/storage.md +38 -22
  87. package/package.json +1 -1
  88. package/skills/setup-slack/SKILL.md +1 -1
  89. package/src/internal/cli-slack.ts +0 -5
  90. package/src/internal/event-log.ts +45 -7
  91. package/src/internal/process-memory-telemetry.ts +373 -0
  92. package/src/internal/server.ts +13 -0
  93. package/src/internal/session-engine.ts +20 -1
  94. package/src/internal/slack-provision-client.ts +7 -7
  95. package/src/storage.ts +130 -11
  96. package/dist/docs/assets/chunks/@localSearchIndexroot.DV5SAHnQ.js +0 -1
  97. package/dist/docs/assets/storage.md.CJYd5YmN.lean.js +0 -1
  98. package/dist/playground/assets/index-CiCmH6R-.css +0 -1
  99. /package/dist/docs/assets/{reference_http-api.md.DGrw_wOu.lean.js → reference_http-api.md.DMbdFGVQ.lean.js} +0 -0
@@ -8,8 +8,8 @@
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-DEVTyeOu.js"></script>
12
- <link rel="stylesheet" crossorigin href="./assets/index-CiCmH6R-.css">
11
+ <script type="module" crossorigin src="./assets/index-Dq_HqyU-.js"></script>
12
+ <link rel="stylesheet" crossorigin href="./assets/index-Dox74yWJ.css">
13
13
  </head>
14
14
  <body>
15
15
  <div id="root"></div>
package/dist/storage.d.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";
@@ -178,13 +181,20 @@ export interface StorageConfig {
178
181
  /** Timing knobs; see {@link StoragePolicy}. */
179
182
  policy?: StoragePolicy;
180
183
  /**
181
- * Dedicated eval-runs table. Omit it and playground eval history stays
182
- * in process memory (lost on restart).
184
+ * Dedicated eval-runs table a backend-native optimization, not a
185
+ * requirement. When omitted, `defineStorage` derives the table over the
186
+ * KV core (one key per run under `agentkit/v1/{agent}/eval-runs/`),
187
+ * which needs core `put`, `delete`, and `list`; only when the core
188
+ * lacks `delete` or `list` does playground eval history stay in process
189
+ * memory (lost on restart).
183
190
  */
184
191
  evals?: StorageEvalsTable;
185
192
  /**
186
- * Dedicated A/B table. Omit it and metric samples are not exported
187
- * (session event logs remain the assignment/fold source of truth).
193
+ * Dedicated A/B table a backend-native optimization, not a
194
+ * requirement. When omitted, `defineStorage` derives it over the KV
195
+ * core: `putSample` and `putSnapshot` need only core `put` (always
196
+ * present), `getSnapshot` additionally needs core `get`. Session event
197
+ * logs remain the assignment/fold source of truth either way.
188
198
  */
189
199
  abs?: StorageABTable;
190
200
  /**
@@ -217,7 +227,8 @@ export interface StorageConfig {
217
227
  /**
218
228
  * All entries under a key prefix, in ascending key order. Optional —
219
229
  * required for the **startup bulk restore** (sessions + event streams)
220
- * and playground eval history.
230
+ * and, together with `delete`, for the derived eval-runs table
231
+ * (playground eval history).
221
232
  */
222
233
  list?(prefix: string, ctx: StorageContext): StorageEntry[] | Promise<StorageEntry[]>;
223
234
  }
@@ -252,9 +263,14 @@ export declare const STORAGE_KEY_ROOT: "agentkit/v1";
252
263
  * | `agentkit/v1/{agent}/session-events/{sessionId}/{index}` | `SessionEvent[]` chunk (index = first event's index, zero-padded) |
253
264
  * | `agentkit/v1/{agent}/continuation/{channelId}/{token}` | `{ sessionId }` |
254
265
  * | `agentkit/v1/{agent}/kv/{key}` | Author JSON via {@link HostContext.kv} |
266
+ * | `agentkit/v1/{agent}/eval-runs/{runId}` | `EvalRunSnapshot` (derived `evals` table) |
267
+ * | `agentkit/v1/{agent}/ab-samples/{experiment}/{sessionId}/{at}` | `ABMetricSample` (derived `abs` table, append-only) |
268
+ * | `agentkit/v1/{agent}/ab-snapshot` | `ABSnapshot` (derived `abs` table, LWW) |
255
269
  *
256
- * Eval-run and A/B history do not flow through this KV scheme — they have
257
- * dedicated tables ({@link StorageConfig.evals} / {@link StorageConfig.abs}).
270
+ * The `eval-runs` / `ab-samples` / `ab-snapshot` families are minted only
271
+ * by the tables `defineStorage` derives over the KV core; a backend that
272
+ * authors dedicated {@link StorageConfig.evals} / {@link StorageConfig.abs}
273
+ * groups never sees them.
258
274
  */
259
275
  export declare const storageKeys: {
260
276
  readonly session: (agent: string, sessionId: string) => string;
@@ -268,6 +284,16 @@ export declare const storageKeys: {
268
284
  */
269
285
  readonly kv: (agent: string, key: string) => string;
270
286
  readonly kvPrefix: (agent: string) => string;
287
+ /** One playground eval-run snapshot (derived `evals` table). */
288
+ readonly evalRun: (agent: string, runId: string) => string;
289
+ readonly evalRunsPrefix: (agent: string) => string;
290
+ /**
291
+ * One A/B metric sample (derived `abs` table); the segments mirror the
292
+ * dedicated table's row identity (experiment + sessionId + at).
293
+ */
294
+ readonly abSample: (agent: string, experiment: string, sessionId: string, at: string) => string;
295
+ /** Latest aggregate A/B snapshot (derived `abs` table, LWW). */
296
+ readonly abSnapshot: (agent: string) => string;
271
297
  };
272
298
  /**
273
299
  * 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":"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"}
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"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"}
package/dist/storage.js 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";
@@ -48,6 +51,15 @@
48
51
  * event log under `--state-root` remains the live source of truth; this
49
52
  * interface is the durable mirror.
50
53
  */
54
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
55
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
56
+ return new (P || (P = Promise))(function (resolve, reject) {
57
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
58
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
59
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
60
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
61
+ });
62
+ };
51
63
  import { createHash } from "node:crypto";
52
64
  import { brandDefinition } from "./internal/brand.js";
53
65
  /**
@@ -101,7 +113,56 @@ export function defineStorage(config) {
101
113
  }
102
114
  // Validate eagerly so a bad policy fails at discovery, not first flush.
103
115
  resolveStoragePolicy(config.policy);
104
- return brandDefinition("storage", config);
116
+ // A backend that implements only the KV core gets full functionality:
117
+ // the dedicated tables are backend-native optimizations, derived over
118
+ // the core when absent. Authored groups always win.
119
+ const derivedEvals = config.evals === undefined ? deriveEvalsTable(config) : undefined;
120
+ const derivedAbs = config.abs === undefined ? deriveAbsTable(config) : undefined;
121
+ return brandDefinition("storage", Object.assign(Object.assign(Object.assign({}, config), (derivedEvals === undefined ? {} : { evals: derivedEvals })), (derivedAbs === undefined ? {} : { abs: derivedAbs })));
122
+ }
123
+ /**
124
+ * Eval-runs table over the KV core: one key per run under
125
+ * {@link storageKeys.evalRun}, hydrate via prefix `list`, prune via
126
+ * `delete`. Requires core `put` + `delete` + `list`; without `delete` or
127
+ * `list` there is no derivation (pruning or hydration would silently not
128
+ * work) and eval history stays in process memory.
129
+ */
130
+ function deriveEvalsTable(config) {
131
+ if (config.delete === undefined || config.list === undefined) {
132
+ return undefined;
133
+ }
134
+ return {
135
+ put: (run, ctx) => config.put(storageKeys.evalRun(ctx.agentName, run.runId), run, ctx),
136
+ delete: (runId, ctx) => { var _a; return (_a = config.delete) === null || _a === void 0 ? void 0 : _a.call(config, storageKeys.evalRun(ctx.agentName, runId), ctx); },
137
+ list: (ctx) => __awaiter(this, void 0, void 0, function* () {
138
+ var _a;
139
+ var _b;
140
+ const entries = (_b = (yield (_a = config.list) === null || _a === void 0 ? void 0 : _a.call(config, storageKeys.evalRunsPrefix(ctx.agentName), ctx))) !== null && _b !== void 0 ? _b : [];
141
+ return entries.map((entry) => entry.value);
142
+ }),
143
+ };
144
+ }
145
+ /**
146
+ * A/B table over the KV core. Each sample lands as its own key (identity
147
+ * = experiment + sessionId + at, matching the dedicated table's row
148
+ * uniqueness): appending to one array value would need read-modify-write
149
+ * — lost updates under concurrent writers without CAS, and unbounded
150
+ * value growth — while a key per sample keeps `putSample` a blind put
151
+ * with real append-only semantics. The aggregate snapshot lives at one
152
+ * fixed key via plain `put` (last-write-wins is correct for "latest").
153
+ * Requires only core `put`; `getSnapshot` is included when core `get`
154
+ * exists.
155
+ */
156
+ function deriveAbsTable(config) {
157
+ const get = config.get;
158
+ return Object.assign({ putSample: (sample, ctx) => config.put(storageKeys.abSample(ctx.agentName, sample.experiment, sample.sessionId, sample.at), sample, ctx), putSnapshot: (snapshot, ctx) => config.put(storageKeys.abSnapshot(ctx.agentName), snapshot, ctx) }, (get === undefined
159
+ ? {}
160
+ : {
161
+ getSnapshot: (ctx) => __awaiter(this, void 0, void 0, function* () {
162
+ const value = yield get(storageKeys.abSnapshot(ctx.agentName), ctx);
163
+ return (value !== null && value !== void 0 ? value : undefined);
164
+ }),
165
+ }));
105
166
  }
106
167
  // ============================================================================
107
168
  // Key scheme
@@ -129,9 +190,14 @@ export const STORAGE_KEY_ROOT = "agentkit/v1";
129
190
  * | `agentkit/v1/{agent}/session-events/{sessionId}/{index}` | `SessionEvent[]` chunk (index = first event's index, zero-padded) |
130
191
  * | `agentkit/v1/{agent}/continuation/{channelId}/{token}` | `{ sessionId }` |
131
192
  * | `agentkit/v1/{agent}/kv/{key}` | Author JSON via {@link HostContext.kv} |
193
+ * | `agentkit/v1/{agent}/eval-runs/{runId}` | `EvalRunSnapshot` (derived `evals` table) |
194
+ * | `agentkit/v1/{agent}/ab-samples/{experiment}/{sessionId}/{at}` | `ABMetricSample` (derived `abs` table, append-only) |
195
+ * | `agentkit/v1/{agent}/ab-snapshot` | `ABSnapshot` (derived `abs` table, LWW) |
132
196
  *
133
- * Eval-run and A/B history do not flow through this KV scheme — they have
134
- * dedicated tables ({@link StorageConfig.evals} / {@link StorageConfig.abs}).
197
+ * The `eval-runs` / `ab-samples` / `ab-snapshot` families are minted only
198
+ * by the tables `defineStorage` derives over the KV core; a backend that
199
+ * authors dedicated {@link StorageConfig.evals} / {@link StorageConfig.abs}
200
+ * groups never sees them.
135
201
  */
136
202
  export const storageKeys = {
137
203
  session: (agent, sessionId) => `${STORAGE_KEY_ROOT}/${agent}/session/${sessionId}`,
@@ -145,6 +211,16 @@ export const storageKeys = {
145
211
  */
146
212
  kv: (agent, key) => `${STORAGE_KEY_ROOT}/${agent}/kv/${keySegment(key)}`,
147
213
  kvPrefix: (agent) => `${STORAGE_KEY_ROOT}/${agent}/kv/`,
214
+ /** One playground eval-run snapshot (derived `evals` table). */
215
+ evalRun: (agent, runId) => `${STORAGE_KEY_ROOT}/${agent}/eval-runs/${keySegment(runId)}`,
216
+ evalRunsPrefix: (agent) => `${STORAGE_KEY_ROOT}/${agent}/eval-runs/`,
217
+ /**
218
+ * One A/B metric sample (derived `abs` table); the segments mirror the
219
+ * dedicated table's row identity (experiment + sessionId + at).
220
+ */
221
+ abSample: (agent, experiment, sessionId, at) => `${STORAGE_KEY_ROOT}/${agent}/ab-samples/${keySegment(experiment)}/${keySegment(sessionId)}/${keySegment(at)}`,
222
+ /** Latest aggregate A/B snapshot (derived `abs` table, LWW). */
223
+ abSnapshot: (agent) => `${STORAGE_KEY_ROOT}/${agent}/ab-snapshot`,
148
224
  };
149
225
  /**
150
226
  * Max bytes a caller-controlled key segment may occupy after URI-encoding.
package/docs/ab.md CHANGED
@@ -255,9 +255,10 @@ too. This include-all behavior can still apply to `GET /v1/abs` in dev
255
255
  when bearer or custom auth keeps `GET /v1/sessions` owner-scoped.
256
256
 
257
257
  Session `events.ndjson` is the source of truth for assignment + fold.
258
- `GET /v1/abs` recomputes aggregates from those logs. For durable
259
- sample and snapshot export, declare an `abs` table in
260
- `agent/storage.ts` same idea as the eval-runs table. See
258
+ `GET /v1/abs` recomputes aggregates from those logs. Any
259
+ `agent/storage.ts` exports samples and snapshots durably: an authored
260
+ `abs` table when the backend has a native shape for it, or the table
261
+ derived over the KV core otherwise. See
261
262
  [Storage](./storage.md#eval-and-a-b-tables).
262
263
 
263
264
  ## Configure the playground fold window
package/docs/evals.md CHANGED
@@ -147,10 +147,12 @@ JUnit XML file for CI, `Artifacts` writes per-case files, and
147
147
  the XML for a custom destination). A file or case can add its own
148
148
  `reporters` on top of the config list.
149
149
 
150
- Playground batches live in process memory and disappear when `serve`
151
- exits. Navigating away and back still works while the process is up.
152
- To keep batches across restarts, declare an `evals` table in
153
- `agent/storage.ts`; see [Storage](./storage.md#eval-and-a-b-tables).
150
+ Playground batches survive restarts whenever `agent/storage.ts` exists
151
+ with an `evals` table or a KV core providing `delete` and `list` (the
152
+ table is derived over the core); see
153
+ [Storage](./storage.md#eval-and-a-b-tables). Without storage they live
154
+ in process memory and disappear when `serve` exits — navigating away
155
+ and back still works while the process is up.
154
156
 
155
157
  ## Drive and assert with `t`
156
158
 
@@ -360,9 +362,10 @@ agent-sdk serve --dir . --dev
360
362
 
361
363
  Playground runs target the live server instead of an ephemeral one.
362
364
  Their sessions appear in the session list. One eval batch can run at a
363
- time. By default those batches are **in-memory only** (capped by
364
- `maxPlaygroundRuns`); declare an `evals` table in `agent/storage.ts` if
365
- you need them after a serve restart see
365
+ time. Batches persist across restarts whenever `agent/storage.ts`
366
+ provides an `evals` table or a KV core with `delete` and `list` (the
367
+ table is derived over the core); without storage they are **in-memory
368
+ only** (capped by `maxPlaygroundRuns`) — see
366
369
  [Storage](./storage.md#eval-and-a-b-tables).
367
370
 
368
371
  The UI uses the playground eval routes (available without `--dev`):
@@ -208,9 +208,10 @@ Eval runs are asynchronous. Poll the run route for case progress and
208
208
  the final `completed` or `failed` status. Batch errors appear on the
209
209
  snapshot returned by the poll. Entries within `filterIds` and `tags`
210
210
  use OR semantics. When both fields are present, a case must match one
211
- entry from each field. Without a storage `evals` table in
212
- `agent/storage.ts` (see [Storage](../storage.md)), listed runs are
213
- process-memory only (capped by `maxPlaygroundRuns`).
211
+ entry from each field. Listed runs persist across restarts whenever
212
+ `agent/storage.ts` provides an `evals` table or a KV core with `delete`
213
+ and `list` (the table is derived — see [Storage](../storage.md));
214
+ otherwise they are process-memory only (capped by `maxPlaygroundRuns`).
214
215
 
215
216
  ## Dev-mode routes
216
217
 
package/docs/storage.md CHANGED
@@ -52,17 +52,22 @@ export default defineStorage({
52
52
 
53
53
  ## Which fields to provide
54
54
 
55
+ Implement the small KV core — `put`/`get`/`delete`/`list` plus the `cas`
56
+ group — and you get **full functionality**: eval-run and A/B history are
57
+ derived over the core automatically. The dedicated `evals` / `abs` groups
58
+ are backend-native optimizations, not required-or-lose-history hooks.
59
+
55
60
  | Field | Required | Role |
56
61
  | --- | --- | --- |
57
62
  | `put` | Yes | Write or update a value |
58
63
  | `cas` | For coordination | Conditional writes; see [Conditional writes](#conditional-writes-the-cas-group) |
59
- | `get` | For restore | Look up one key |
60
- | `list` | For restore | Return entries under a prefix, in key order |
61
- | `delete` | For cleanup | Remove a key |
64
+ | `get` | For restore | Look up one key (also: derived A/B snapshot backfill) |
65
+ | `list` | For restore | Return entries under a prefix, in key order (also: derived eval-runs hydrate) |
66
+ | `delete` | For cleanup | Remove a key (also: derived eval-runs pruning) |
62
67
  | `name` | No | Label surfaced on `GET /v1/info` diagnostics |
63
68
  | `policy` | No | Timing knobs; see [Policy](#policy) |
64
- | `evals` | No | Dedicated eval-runs table; see [Eval and A/B tables](#eval-and-a-b-tables) |
65
- | `abs` | No | Dedicated A/B metrics table; see [Eval and A/B tables](#eval-and-a-b-tables) |
69
+ | `evals` | No | Backend-native eval-runs table; derived over the core when omitted — see [Eval and A/B tables](#eval-and-a-b-tables) |
70
+ | `abs` | No | Backend-native A/B metrics table; derived over the core when omitted — see [Eval and A/B tables](#eval-and-a-b-tables) |
66
71
 
67
72
  A throwing `put` is logged and dropped. It never fails a turn. When
68
73
  resolving a missing continuation token, a throwing `get` fails the
@@ -71,23 +76,34 @@ follow-up so a store outage does not open a new session. Return
71
76
 
72
77
  ## Eval and A/B tables
73
78
 
74
- Two dedicated tables carry structured rows instead of opaque KV values.
75
- Both are optional and independent of `put` / `get` / `list`.
76
-
77
- `evals` keeps playground eval batches across restarts. Provide `put`,
78
- `delete`, and `list` over run snapshots keyed by `runId`. The Agent SDK
79
- upserts a snapshot as a batch starts, progresses, and finishes, prunes
80
- runs past the playground history window, and lists everything back at
81
- serve start. Without this table, eval history lives in process memory
82
- and a restart clears it. See [Evals](./evals.md#configure-eval-runs).
83
-
84
- `abs` exports live A/B metrics. Provide `putSample` to append one
85
- cumulative metric sample per enrolled experiment on each completed or
86
- failed turn. Optional `putSnapshot` and `getSnapshot` store and serve
87
- back the latest aggregate snapshot, so a replacement host with no local
88
- sessions can still serve the A/Bs surface. Without this table, samples
89
- only go where each experiment's `onSample` sends them; session event
90
- logs remain the assignment source of truth. See
79
+ Two dedicated table groups carry structured rows instead of opaque KV
80
+ values. Both are **optional optimizations**: when a group is not
81
+ authored, `defineStorage` derives it over the KV core, so a backend that
82
+ implements only the core loses nothing. Author a group only when the
83
+ backend has a better native shape (a real database table, an analytics
84
+ pipeline) the built-in `fileKv` and `cursorHostedStorage` both do.
85
+
86
+ `evals` keeps playground eval batches across restarts (`put`, `delete`,
87
+ `list` over run snapshots keyed by `runId`). The Agent SDK upserts a
88
+ snapshot as a batch starts, progresses, and finishes, prunes runs past
89
+ the playground history window, and lists everything back at serve start.
90
+ **Derived form**: one key per run under
91
+ `agentkit/v1/{agent}/eval-runs/{runId}` needs core `put` + `delete` +
92
+ `list`. Only a core missing `delete` or `list` leaves eval history in
93
+ process memory (cleared on restart). See
94
+ [Evals](./evals.md#configure-eval-runs).
95
+
96
+ `abs` exports live A/B metrics: `putSample` appends one cumulative
97
+ metric sample per enrolled experiment on each completed or failed turn;
98
+ optional `putSnapshot` / `getSnapshot` store and serve back the latest
99
+ aggregate so a replacement host with no local sessions can still serve
100
+ the A/Bs surface. **Derived form**: each sample lands as its own key
101
+ (`agentkit/v1/{agent}/ab-samples/{experiment}/{sessionId}/{at}` — a
102
+ blind append-only put, never a read-modify-write of one growing array)
103
+ and the snapshot lives at the fixed `agentkit/v1/{agent}/ab-snapshot`
104
+ key (last-write-wins is correct for "latest aggregate"). `putSample` and
105
+ `putSnapshot` need only core `put`; `getSnapshot` needs core `get`.
106
+ Session event logs remain the assignment source of truth either way. See
91
107
  [Live A/B metrics](./ab.md).
92
108
 
93
109
  ## Policy
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cursor/july",
3
- "version": "0.1.48",
3
+ "version": "0.1.49",
4
4
  "description": "(early alpha) Filesystem-first framework for defining Cursor agents as markdown and TypeScript and serving them over channels with the Cursor SDK.",
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "repository": {
@@ -270,7 +270,7 @@ a mention), opt in explicitly:
270
270
  export default slackChannel({
271
271
  engagement: {
272
272
  channelPosts: {
273
- allow: ["#issues-glass"], // explicit allowlist; no wildcard exists
273
+ allow: ["#issues-cursor-desktop"], // explicit allowlist; no wildcard exists
274
274
  posts: "top-level", // default — thread replies never dispatch
275
275
  debounceMs: 15_000, // optional: edits settle, deletes cancel
276
276
  },
@@ -1126,11 +1126,6 @@ function renderCreateProvisionError(
1126
1126
  `${error.message}\nA concurrent \`${CLI} slack create\` for this agent won the race; re-run create to pick up that app.\n`
1127
1127
  );
1128
1128
  return 1;
1129
- case "app_cap_reached":
1130
- err(
1131
- `${error.message}\nDelete unused apps with \`${CLI} slack destroy\`, then re-run create.\n`
1132
- );
1133
- return 1;
1134
1129
  case "ratelimited":
1135
1130
  err(`${error.message}\nRe-run \`${CLI} slack create\` after the wait.\n`);
1136
1131
  return 1;
@@ -59,6 +59,17 @@ export class SessionEventLog {
59
59
  return this.events.length;
60
60
  }
61
61
 
62
+ /**
63
+ * In-process residency vs recorded length. Today those are the same
64
+ * (`events` is the cache). A later change can drop the cache and keep
65
+ * `eventsTotal` as the durable count while `eventsRetained` shrinks to
66
+ * the unflushed tail.
67
+ */
68
+ memoryStats(): { eventsRetained: number; eventsTotal: number } {
69
+ const n = this.events.length;
70
+ return { eventsRetained: n, eventsTotal: n };
71
+ }
72
+
62
73
  /**
63
74
  * Assign the next index, record the event, and fan out to live
64
75
  * subscribers. Ordering is synchronous; file persistence is chained in
@@ -154,9 +165,16 @@ export class SessionEventLog {
154
165
  }
155
166
  }
156
167
 
168
+ export type EventLogMemoryStats = {
169
+ residentSessions: number;
170
+ eventsRetained: number;
171
+ eventsTotal: number;
172
+ };
173
+
157
174
  /** Lazily opens one {@link SessionEventLog} per session. */
158
175
  export class EventLogStore {
159
176
  private readonly logs = new Map<string, Promise<SessionEventLog>>();
177
+ private readonly opened = new Map<string, SessionEventLog>();
160
178
 
161
179
  constructor(
162
180
  private readonly eventFilePathFor: (sessionId: string) => string,
@@ -170,18 +188,38 @@ export class EventLogStore {
170
188
  let log = this.logs.get(sessionId);
171
189
  if (log === undefined) {
172
190
  const filePath = this.eventFilePathFor(sessionId);
173
- log = mkdir(dirname(filePath), { recursive: true }).then(() =>
174
- SessionEventLog.open({
175
- sessionId,
176
- filePath,
177
- onPersistError: (error) => this.onPersistError(sessionId, error),
178
- })
179
- );
191
+ log = mkdir(dirname(filePath), { recursive: true })
192
+ .then(() =>
193
+ SessionEventLog.open({
194
+ sessionId,
195
+ filePath,
196
+ onPersistError: (error) => this.onPersistError(sessionId, error),
197
+ })
198
+ )
199
+ .then((opened) => {
200
+ this.opened.set(sessionId, opened);
201
+ return opened;
202
+ });
180
203
  this.logs.set(sessionId, log);
181
204
  }
182
205
  return log;
183
206
  }
184
207
 
208
+ memoryStats(): EventLogMemoryStats {
209
+ let eventsRetained = 0;
210
+ let eventsTotal = 0;
211
+ for (const log of this.opened.values()) {
212
+ const stats = log.memoryStats();
213
+ eventsRetained += stats.eventsRetained;
214
+ eventsTotal += stats.eventsTotal;
215
+ }
216
+ return {
217
+ residentSessions: this.logs.size,
218
+ eventsRetained,
219
+ eventsTotal,
220
+ };
221
+ }
222
+
185
223
  async flushAll(): Promise<void> {
186
224
  await Promise.all(
187
225
  [...this.logs.values()].map((logPromise) =>