@cursor/july 0.1.40 → 0.1.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +13 -6
- package/dist/bin/agent-serve.js +28 -9
- package/dist/channels/slack/attachments.d.ts +82 -0
- package/dist/channels/slack/attachments.d.ts.map +1 -0
- package/dist/channels/slack/attachments.js +520 -0
- package/dist/channels/slack/cursor-account.d.ts +7 -1
- package/dist/channels/slack/cursor-account.d.ts.map +1 -1
- package/dist/channels/slack/cursor-account.js +2 -2
- package/dist/channels/slack/dispatch.d.ts +4 -3
- package/dist/channels/slack/dispatch.d.ts.map +1 -1
- package/dist/channels/slack/dispatch.js +84 -21
- package/dist/channels/slack/inbound.d.ts +6 -0
- package/dist/channels/slack/inbound.d.ts.map +1 -1
- package/dist/channels/slack/inbound.js +48 -2
- package/dist/channels/slack/index.d.ts +1 -0
- package/dist/channels/slack/index.d.ts.map +1 -1
- package/dist/channels/slack/index.js +1 -0
- package/dist/channels/slack/manifest.d.ts.map +1 -1
- package/dist/channels/slack/manifest.js +1 -0
- package/dist/channels/slack/slack-channel.d.ts.map +1 -1
- package/dist/channels/slack/slack-channel.js +7 -4
- package/dist/channels/slack/types.d.ts +49 -1
- package/dist/channels/slack/types.d.ts.map +1 -1
- package/dist/docs/404.html +2 -2
- package/dist/docs/ab.html +6 -6
- package/dist/docs/assets/{ab.md.6cLOW7--.js → ab.md.hdxsvX5M.js} +2 -2
- package/dist/docs/assets/{app.DpGLSiym.js → app.C4-Gwi7g.js} +1 -1
- package/dist/docs/assets/{building-with-agents.md.txrcGU2B.js → building-with-agents.md.PeZaZA1P.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.BlU3A8EB.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.B11XEMST.js → VPLocalSearchBox.DDoLm843.js} +1 -1
- package/dist/docs/assets/chunks/{theme.iTidHsAx.js → theme.SbjGIiM0.js} +2 -2
- package/dist/docs/assets/{deployment.md.CuK5SNjN.js → deployment.md.BHVjVqRa.js} +4 -4
- package/dist/docs/assets/{deployment.md.CuK5SNjN.lean.js → deployment.md.BHVjVqRa.lean.js} +1 -1
- package/dist/docs/assets/{evals.md.BQXI3rXy.js → evals.md.qeoGgPw0.js} +3 -3
- package/dist/docs/assets/example-agents_index.md.xmJ87d_3.js +2 -0
- package/dist/docs/assets/{guides_webhooks.md.BERuBSJW.js → guides_webhooks.md.DB-r_er9.js} +47 -4
- package/dist/docs/assets/{guides_webhooks.md.BERuBSJW.lean.js → guides_webhooks.md.DB-r_er9.lean.js} +1 -1
- package/dist/docs/assets/index.md.BKpbkCa6.js +24 -0
- package/dist/docs/assets/{index.md.CmhptOmN.lean.js → index.md.BKpbkCa6.lean.js} +1 -1
- package/dist/docs/assets/{quickstart.md.C_b6ESpD.js → quickstart.md.rIbfahJM.js} +4 -4
- package/dist/docs/assets/{reference_cli.md.Byvrg8eu.js → reference_cli.md.DqEqQpGn.js} +5 -5
- package/dist/docs/assets/{reference_cli.md.Byvrg8eu.lean.js → reference_cli.md.DqEqQpGn.lean.js} +1 -1
- package/dist/docs/assets/reference_hooks.md.B40QAG6m.js +14 -0
- package/dist/docs/assets/{reference_hooks.md.BGDw4VLm.lean.js → reference_hooks.md.B40QAG6m.lean.js} +1 -1
- package/dist/docs/assets/{storage.md.mQDtIULc.js → storage.md.DcGSnIxX.js} +10 -4
- package/dist/docs/assets/{storage.md.mQDtIULc.lean.js → storage.md.DcGSnIxX.lean.js} +1 -1
- package/dist/docs/assets/troubleshooting.md.CkgwmVI0.js +1 -0
- package/dist/docs/assets/{troubleshooting.md.B5RVX_tL.lean.js → troubleshooting.md.CkgwmVI0.lean.js} +1 -1
- package/dist/docs/building-with-agents.html +5 -5
- package/dist/docs/concepts.html +3 -3
- package/dist/docs/deployment.html +6 -6
- package/dist/docs/evals.html +7 -7
- package/dist/docs/example-agents/approval-buddy.html +3 -3
- package/dist/docs/example-agents/benny.html +3 -3
- package/dist/docs/example-agents/bugbot.html +3 -3
- package/dist/docs/example-agents/codebase-wiki.html +3 -3
- package/dist/docs/example-agents/codeowners-review.html +3 -3
- package/dist/docs/example-agents/concierge.html +3 -3
- package/dist/docs/example-agents/fsd.html +3 -3
- package/dist/docs/example-agents/index.html +5 -5
- package/dist/docs/example-agents/knowledge-base.html +3 -3
- package/dist/docs/example-agents/oncall.html +3 -3
- package/dist/docs/example-agents/security-reviewer.html +3 -3
- package/dist/docs/example-agents/slack-agent.html +3 -3
- package/dist/docs/example-agents/weather-agent.html +3 -3
- package/dist/docs/guides/agent-to-agent.html +3 -3
- package/dist/docs/guides/cloud-runtime.html +3 -3
- package/dist/docs/guides/github.html +3 -3
- package/dist/docs/guides/human-in-the-loop.html +3 -3
- package/dist/docs/guides/mcp-oauth.html +3 -3
- package/dist/docs/guides/slack.html +3 -3
- package/dist/docs/guides/webhooks.html +49 -6
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +3 -3
- package/dist/docs/index.html +7 -7
- package/dist/docs/quickstart.html +8 -8
- package/dist/docs/reference/agent-config.html +3 -3
- package/dist/docs/reference/artifacts.html +3 -3
- package/dist/docs/reference/channels.html +3 -3
- package/dist/docs/reference/cli.html +8 -8
- package/dist/docs/reference/connections.html +3 -3
- package/dist/docs/reference/hooks.html +9 -7
- package/dist/docs/reference/http-api.html +3 -3
- package/dist/docs/reference/instructions.html +3 -3
- package/dist/docs/reference/playground.html +3 -3
- package/dist/docs/reference/project-layout.html +3 -3
- package/dist/docs/reference/prompt.html +3 -3
- package/dist/docs/reference/schedules.html +3 -3
- package/dist/docs/reference/sessions.html +3 -3
- package/dist/docs/reference/skills.html +3 -3
- package/dist/docs/reference/subagents.html +3 -3
- package/dist/docs/reference/tools.html +3 -3
- package/dist/docs/scaffolding-agents.html +3 -3
- package/dist/docs/storage.html +14 -8
- package/dist/docs/troubleshooting.html +5 -5
- package/dist/hooks.d.ts +3 -1
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +3 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/internal/cli-ax.d.ts.map +1 -1
- package/dist/internal/cli-ax.js +22 -2
- package/dist/internal/cli-deploy.d.ts +6 -0
- package/dist/internal/cli-deploy.d.ts.map +1 -1
- package/dist/internal/cli-deploy.js +14 -4
- package/dist/internal/cli-mcp.js +4 -4
- package/dist/internal/deploy-client.js +1 -1
- package/dist/internal/discovery.d.ts.map +1 -1
- package/dist/internal/discovery.js +35 -7
- package/dist/internal/distribution.d.ts.map +1 -1
- package/dist/internal/distribution.js +3 -1
- package/dist/internal/durable-session-store.d.ts +48 -0
- package/dist/internal/durable-session-store.d.ts.map +1 -0
- package/dist/internal/durable-session-store.js +86 -0
- package/dist/internal/hosting.d.ts +1 -1
- package/dist/internal/hosting.js +2 -2
- package/dist/internal/init-project.d.ts +34 -0
- package/dist/internal/init-project.d.ts.map +1 -1
- package/dist/internal/init-project.js +121 -2
- package/dist/internal/ledger-serving.d.ts +101 -0
- package/dist/internal/ledger-serving.d.ts.map +1 -0
- package/dist/internal/ledger-serving.js +174 -0
- package/dist/internal/listen-port.d.ts +22 -0
- package/dist/internal/listen-port.d.ts.map +1 -0
- package/dist/internal/listen-port.js +77 -0
- package/dist/internal/playground/static.d.ts +21 -4
- package/dist/internal/playground/static.d.ts.map +1 -1
- package/dist/internal/playground/static.js +82 -18
- package/dist/internal/sdk-runner.d.ts.map +1 -1
- package/dist/internal/sdk-runner.js +10 -1
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +61 -47
- package/dist/internal/session-engine.d.ts +57 -1
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +118 -28
- package/dist/internal/slack-provision-client.js +1 -1
- package/dist/internal/workspace.d.ts +6 -2
- package/dist/internal/workspace.d.ts.map +1 -1
- package/dist/internal/workspace.js +10 -2
- package/dist/kv/memory-kv.d.ts +23 -0
- package/dist/kv/memory-kv.d.ts.map +1 -0
- package/dist/kv/memory-kv.js +103 -0
- package/dist/kv.d.ts +22 -0
- package/dist/kv.d.ts.map +1 -0
- package/dist/kv.js +20 -0
- package/dist/ledger/session-ledger.d.ts +204 -0
- package/dist/ledger/session-ledger.d.ts.map +1 -0
- package/dist/ledger/session-ledger.js +382 -0
- package/dist/ledger.d.ts +11 -0
- package/dist/ledger.d.ts.map +1 -0
- package/dist/ledger.js +9 -0
- package/dist/playground/assets/index-B3HBneZZ.js +85 -0
- package/dist/playground/assets/index-Bqk9nplh.css +1 -0
- package/dist/playground/index.html +2 -2
- package/dist/storage-backends/cursor-hosted.d.ts +25 -3
- package/dist/storage-backends/cursor-hosted.d.ts.map +1 -1
- package/dist/storage-backends/cursor-hosted.js +50 -2
- package/dist/storage-backends/file-kv.d.ts +5 -2
- package/dist/storage-backends/file-kv.d.ts.map +1 -1
- package/dist/storage-backends/file-kv.js +107 -7
- package/dist/storage.d.ts +60 -5
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +28 -4
- package/dist/types.d.ts +132 -6
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +14 -0
- package/docs/README.md +10 -7
- package/docs/ab.md +2 -2
- package/docs/building-with-agents.md +1 -1
- package/docs/deployment.md +34 -11
- package/docs/evals.md +3 -3
- package/docs/example-agents/index.md +1 -1
- package/docs/guides/webhooks.md +87 -0
- package/docs/quickstart.md +7 -8
- package/docs/reference/cli.md +15 -6
- package/docs/reference/hooks.md +12 -3
- package/docs/storage.md +67 -7
- package/docs/troubleshooting.md +10 -2
- package/package.json +20 -7
- package/skills/create-agent/SKILL.md +1 -1
- package/skills/debug/SKILL.md +4 -0
- package/src/bin/agent-serve.ts +27 -11
- package/src/channels/slack/attachments.ts +635 -0
- package/src/channels/slack/cursor-account.ts +8 -0
- package/src/channels/slack/dispatch.ts +121 -6
- package/src/channels/slack/inbound.ts +60 -0
- package/src/channels/slack/index.ts +1 -0
- package/src/channels/slack/manifest.ts +1 -0
- package/src/channels/slack/slack-channel.ts +7 -0
- package/src/channels/slack/types.ts +47 -1
- package/src/hooks.ts +3 -1
- package/src/index.ts +9 -0
- package/src/internal/cli-ax.ts +25 -1
- package/src/internal/cli-deploy.ts +22 -4
- package/src/internal/cli-mcp.ts +4 -4
- package/src/internal/deploy-client.ts +1 -1
- package/src/internal/discovery.ts +42 -5
- package/src/internal/distribution.ts +3 -1
- package/src/internal/durable-session-store.ts +95 -0
- package/src/internal/hosting.ts +2 -2
- package/src/internal/init-project.ts +151 -2
- package/src/internal/ledger-serving.ts +240 -0
- package/src/internal/listen-port.ts +85 -0
- package/src/internal/playground/static.ts +111 -20
- package/src/internal/sdk-runner.ts +11 -1
- package/src/internal/server.ts +68 -61
- package/src/internal/session-engine.ts +193 -16
- package/src/internal/slack-provision-client.ts +1 -1
- package/src/internal/workspace.ts +14 -3
- package/src/kv/memory-kv.ts +99 -0
- package/src/kv.ts +27 -0
- package/src/ledger/session-ledger.ts +535 -0
- package/src/ledger.ts +29 -0
- package/src/storage-backends/cursor-hosted.ts +108 -3
- package/src/storage-backends/file-kv.ts +128 -12
- package/src/storage.ts +90 -6
- package/src/types.ts +139 -7
- package/dist/channels/slack/post-update-delivery.d.ts +0 -85
- package/dist/channels/slack/post-update-delivery.d.ts.map +0 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.D82_RVtF.js +0 -1
- package/dist/docs/assets/example-agents_index.md.DgGBwckv.js +0 -2
- package/dist/docs/assets/index.md.CmhptOmN.js +0 -24
- package/dist/docs/assets/reference_hooks.md.BGDw4VLm.js +0 -12
- package/dist/docs/assets/troubleshooting.md.B5RVX_tL.js +0 -1
- package/dist/internal/json-dir-store.d.ts +0 -32
- package/dist/internal/json-dir-store.d.ts.map +0 -1
- package/dist/internal/persistence-coordinator.d.ts +0 -127
- package/dist/internal/persistence-coordinator.d.ts.map +0 -1
- package/dist/multi-tenant.d.ts +0 -80
- package/dist/multi-tenant.d.ts.map +0 -1
- package/dist/multi-tenant.js +0 -69
- package/dist/persistence.d.ts +0 -184
- package/dist/persistence.d.ts.map +0 -1
- package/dist/playground/assets/index-BRhBbnd4.css +0 -1
- package/dist/playground/assets/index-Bc1oFgFG.js +0 -85
- package/dist/storage-backends/postgres-kv.d.ts +0 -82
- package/dist/storage-backends/postgres-kv.d.ts.map +0 -1
- package/dist/storage-backends/postgres-kv.js +0 -185
- package/src/storage-backends/postgres-kv.ts +0 -253
- /package/dist/docs/assets/{ab.md.6cLOW7--.lean.js → ab.md.hdxsvX5M.lean.js} +0 -0
- /package/dist/docs/assets/{building-with-agents.md.txrcGU2B.lean.js → building-with-agents.md.PeZaZA1P.lean.js} +0 -0
- /package/dist/docs/assets/{evals.md.BQXI3rXy.lean.js → evals.md.qeoGgPw0.lean.js} +0 -0
- /package/dist/docs/assets/{example-agents_index.md.DgGBwckv.lean.js → example-agents_index.md.xmJ87d_3.lean.js} +0 -0
- /package/dist/docs/assets/{quickstart.md.C_b6ESpD.lean.js → quickstart.md.rIbfahJM.lean.js} +0 -0
|
@@ -1,82 +0,0 @@
|
|
|
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
|
-
* For Cursor-managed hosting prefer `cursorHostedStorage` from
|
|
13
|
-
* `@cursor/july/storage/cursor-hosted` — same tables via a control-plane
|
|
14
|
-
* HTTP proxy (no pod-visible DSN). Use this helper when you supply
|
|
15
|
-
* `BUGBOTDB_URL` / `AGENT_SERVE_DEPLOYMENT_ID` yourself (self-host).
|
|
16
|
-
*
|
|
17
|
-
* `postgresStorage` implements the whole `defineStorage` surface as plain
|
|
18
|
-
* SQL: the four KV methods against the last-write-wins `agent_serve_kv`
|
|
19
|
-
* table (sessions, event chunks, continuations, reminders), the `evals`
|
|
20
|
-
* table against `agent_serve_eval_runs` (one row per playground eval
|
|
21
|
-
* batch), and the `abs` table against `agent_serve_ab` (`kind = 'sample'`
|
|
22
|
-
* rows per metric sample plus one `kind = 'snapshot'` row holding the
|
|
23
|
-
* latest aggregate).
|
|
24
|
-
*
|
|
25
|
-
* - KV `put` upserts on the primary key (LWW matches the framework contract).
|
|
26
|
-
* - KV `list` is a prefix range scan on the PK btree (`key >= p AND key < p||…`
|
|
27
|
-
* spelled as LIKE with escaped wildcards, ordered by key).
|
|
28
|
-
* - `get` returning no row is a definitive miss (`undefined`); a connection
|
|
29
|
-
* error throws, so lazy restore fails the follow-up instead of forking
|
|
30
|
-
* the session.
|
|
31
|
-
*
|
|
32
|
-
* Connection comes from `BUGBOTDB_URL` — the repo-wide convention for the
|
|
33
|
-
* bugbot Postgres database, whose Prisma package owns these tables' schema
|
|
34
|
-
* and migrations; locally it falls back to the dev bugbot DB. Non-local
|
|
35
|
-
* URLs enable TLS (`ssl.rejectUnauthorized`) because PlanetScale requires
|
|
36
|
-
* SSL even when the vault URL omits `sslmode`.
|
|
37
|
-
* `deploymentId` scopes rows per deployment (`AGENT_SERVE_DEPLOYMENT_ID`);
|
|
38
|
-
* the local default keeps dev runs of different checkouts from colliding
|
|
39
|
-
* only by agent name.
|
|
40
|
-
*
|
|
41
|
-
* Callers must pass `Pool` from their own `import { Pool } from "pg"`.
|
|
42
|
-
* This module must not import `pg` itself: Node resolves modules from
|
|
43
|
-
* *this* file's directory tree, so a `pg` dep declared only on the
|
|
44
|
-
* consuming agent package would never be found after a hosted install.
|
|
45
|
-
*/
|
|
46
|
-
import type { StorageABTable, StorageConfig, StorageEvalsTable } from "../storage.js";
|
|
47
|
-
/** Minimal `pg.Pool` surface used here (avoids importing `pg` from this path). */
|
|
48
|
-
export interface PostgresQueryable {
|
|
49
|
-
query<T extends Record<string, unknown> = Record<string, unknown>>(text: string, values?: readonly unknown[]): Promise<{
|
|
50
|
-
rows: T[];
|
|
51
|
-
}>;
|
|
52
|
-
}
|
|
53
|
-
/** `pg.Pool` constructor supplied by the consuming example package. */
|
|
54
|
-
export type PostgresPoolConstructor = new (config?: {
|
|
55
|
-
connectionString?: string;
|
|
56
|
-
max?: number;
|
|
57
|
-
ssl?: boolean | {
|
|
58
|
-
rejectUnauthorized?: boolean;
|
|
59
|
-
};
|
|
60
|
-
}) => PostgresQueryable;
|
|
61
|
-
export interface PostgresStorageOptions {
|
|
62
|
-
/**
|
|
63
|
-
* Pass `Pool` from `import { Pool } from "pg"` in the example that declares
|
|
64
|
-
* the `pg` dependency (hosted installs put it in that package's
|
|
65
|
-
* `node_modules` only).
|
|
66
|
-
*/
|
|
67
|
-
Pool: PostgresPoolConstructor;
|
|
68
|
-
/** Postgres connection string (default: env, then local bugbot dev DB). */
|
|
69
|
-
databaseUrl?: string;
|
|
70
|
-
/** Value for the tables' deployment_id column (default: env or "local-dev"). */
|
|
71
|
-
deploymentId?: string;
|
|
72
|
-
}
|
|
73
|
-
type PostgresStorageMethods = Required<Pick<StorageConfig, "put" | "get" | "delete" | "list">> & {
|
|
74
|
-
evals: StorageEvalsTable;
|
|
75
|
-
abs: StorageABTable;
|
|
76
|
-
};
|
|
77
|
-
/** True for local bugbot/dev URLs that do not speak TLS. */
|
|
78
|
-
export declare function isLocalPostgresUrl(connectionString: string): boolean;
|
|
79
|
-
/** Postgres-backed `defineStorage` methods, ready to spread into `defineStorage({...})`. */
|
|
80
|
-
export declare function postgresStorage(options: PostgresStorageOptions): PostgresStorageMethods;
|
|
81
|
-
export {};
|
|
82
|
-
//# sourceMappingURL=postgres-kv.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"postgres-kv.d.ts","sourceRoot":"","sources":["../../src/storage-backends/postgres-kv.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;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"}
|
|
@@ -1,185 +0,0 @@
|
|
|
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
|
-
* For Cursor-managed hosting prefer `cursorHostedStorage` from
|
|
13
|
-
* `@cursor/july/storage/cursor-hosted` — same tables via a control-plane
|
|
14
|
-
* HTTP proxy (no pod-visible DSN). Use this helper when you supply
|
|
15
|
-
* `BUGBOTDB_URL` / `AGENT_SERVE_DEPLOYMENT_ID` yourself (self-host).
|
|
16
|
-
*
|
|
17
|
-
* `postgresStorage` implements the whole `defineStorage` surface as plain
|
|
18
|
-
* SQL: the four KV methods against the last-write-wins `agent_serve_kv`
|
|
19
|
-
* table (sessions, event chunks, continuations, reminders), the `evals`
|
|
20
|
-
* table against `agent_serve_eval_runs` (one row per playground eval
|
|
21
|
-
* batch), and the `abs` table against `agent_serve_ab` (`kind = 'sample'`
|
|
22
|
-
* rows per metric sample plus one `kind = 'snapshot'` row holding the
|
|
23
|
-
* latest aggregate).
|
|
24
|
-
*
|
|
25
|
-
* - KV `put` upserts on the primary key (LWW matches the framework contract).
|
|
26
|
-
* - KV `list` is a prefix range scan on the PK btree (`key >= p AND key < p||…`
|
|
27
|
-
* spelled as LIKE with escaped wildcards, ordered by key).
|
|
28
|
-
* - `get` returning no row is a definitive miss (`undefined`); a connection
|
|
29
|
-
* error throws, so lazy restore fails the follow-up instead of forking
|
|
30
|
-
* the session.
|
|
31
|
-
*
|
|
32
|
-
* Connection comes from `BUGBOTDB_URL` — the repo-wide convention for the
|
|
33
|
-
* bugbot Postgres database, whose Prisma package owns these tables' schema
|
|
34
|
-
* and migrations; locally it falls back to the dev bugbot DB. Non-local
|
|
35
|
-
* URLs enable TLS (`ssl.rejectUnauthorized`) because PlanetScale requires
|
|
36
|
-
* SSL even when the vault URL omits `sslmode`.
|
|
37
|
-
* `deploymentId` scopes rows per deployment (`AGENT_SERVE_DEPLOYMENT_ID`);
|
|
38
|
-
* the local default keeps dev runs of different checkouts from colliding
|
|
39
|
-
* only by agent name.
|
|
40
|
-
*
|
|
41
|
-
* Callers must pass `Pool` from their own `import { Pool } from "pg"`.
|
|
42
|
-
* This module must not import `pg` itself: Node resolves modules from
|
|
43
|
-
* *this* file's directory tree, so a `pg` dep declared only on the
|
|
44
|
-
* consuming agent package would never be found after a hosted install.
|
|
45
|
-
*/
|
|
46
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
47
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
48
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
49
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
50
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
51
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
52
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
53
|
-
});
|
|
54
|
-
};
|
|
55
|
-
/** True for local bugbot/dev URLs that do not speak TLS. */
|
|
56
|
-
export function isLocalPostgresUrl(connectionString) {
|
|
57
|
-
try {
|
|
58
|
-
const host = new URL(connectionString).hostname.toLowerCase();
|
|
59
|
-
return (host === "localhost" ||
|
|
60
|
-
host === "127.0.0.1" ||
|
|
61
|
-
host === "::1" ||
|
|
62
|
-
host === "[::1]");
|
|
63
|
-
}
|
|
64
|
-
catch (_a) {
|
|
65
|
-
return /@(localhost|127\.0\.0\.1|\[::1\])([:/]|$)/i.test(connectionString);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
/** Postgres-backed `defineStorage` methods, ready to spread into `defineStorage({...})`. */
|
|
69
|
-
export function postgresStorage(options) {
|
|
70
|
-
var _a, _b, _c, _d;
|
|
71
|
-
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";
|
|
72
|
-
// Prod Bugbot is PlanetScale Postgres: TLS is required and the vault
|
|
73
|
-
// `BUGBOTDB_URL` often omits `sslmode`. Without an explicit `ssl` option,
|
|
74
|
-
// `pg` opens plaintext and PlanetScale rejects with "SSL connection is
|
|
75
|
-
// required" — sessions stay in-memory. Skip TLS only for local hosts.
|
|
76
|
-
const pool = new options.Pool(Object.assign({ connectionString,
|
|
77
|
-
// Small fixed pool per agent, mirroring the backend's connection_limit
|
|
78
|
-
// clamp on BUGBOTDB_URL consumers (backend/server/src/prisma.ts).
|
|
79
|
-
max: 3 }, (isLocalPostgresUrl(connectionString)
|
|
80
|
-
? {}
|
|
81
|
-
: { ssl: { rejectUnauthorized: true } })));
|
|
82
|
-
const deploymentId = (_d = (_c = options.deploymentId) !== null && _c !== void 0 ? _c : process.env.AGENT_SERVE_DEPLOYMENT_ID) !== null && _d !== void 0 ? _d : "local-dev";
|
|
83
|
-
return {
|
|
84
|
-
put(key, value) {
|
|
85
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
86
|
-
yield pool.query(`INSERT INTO agent_serve_kv (deployment_id, key, value, updated_at)
|
|
87
|
-
VALUES ($1, $2, $3::jsonb, now())
|
|
88
|
-
ON CONFLICT ON CONSTRAINT pk_agent_serve_kv
|
|
89
|
-
DO UPDATE SET value = EXCLUDED.value, updated_at = now()`, [deploymentId, key, JSON.stringify(value)]);
|
|
90
|
-
});
|
|
91
|
-
},
|
|
92
|
-
get(key) {
|
|
93
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
94
|
-
var _a;
|
|
95
|
-
const result = yield pool.query(`SELECT value FROM agent_serve_kv
|
|
96
|
-
WHERE deployment_id = $1 AND key = $2`, [deploymentId, key]);
|
|
97
|
-
return (_a = result.rows[0]) === null || _a === void 0 ? void 0 : _a.value; // no row ⇒ definitive miss
|
|
98
|
-
});
|
|
99
|
-
},
|
|
100
|
-
delete(key) {
|
|
101
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
102
|
-
yield pool.query(`DELETE FROM agent_serve_kv WHERE deployment_id = $1 AND key = $2`, [deploymentId, key]);
|
|
103
|
-
});
|
|
104
|
-
},
|
|
105
|
-
list(prefix) {
|
|
106
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
107
|
-
// Escape LIKE wildcards in the prefix so keys containing % or _
|
|
108
|
-
// (URI-encoded segments cannot, but be safe) match literally.
|
|
109
|
-
const escaped = prefix.replace(/([\\%_])/g, "\\$1");
|
|
110
|
-
const result = yield pool.query(`SELECT key, value FROM agent_serve_kv
|
|
111
|
-
WHERE deployment_id = $1 AND key LIKE $2 ESCAPE '\\'
|
|
112
|
-
ORDER BY key ASC`, [deploymentId, `${escaped}%`]);
|
|
113
|
-
return result.rows;
|
|
114
|
-
});
|
|
115
|
-
},
|
|
116
|
-
// Playground eval batches → agent_serve_eval_runs (one row per run).
|
|
117
|
-
evals: {
|
|
118
|
-
put(run, ctx) {
|
|
119
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
120
|
-
yield pool.query(`INSERT INTO agent_serve_eval_runs (deployment_id, agent, run_id, run, updated_at)
|
|
121
|
-
VALUES ($1, $2, $3, $4::jsonb, now())
|
|
122
|
-
ON CONFLICT ON CONSTRAINT pk_agent_serve_eval_runs
|
|
123
|
-
DO UPDATE SET run = EXCLUDED.run, updated_at = now()`, [deploymentId, ctx.agentName, run.runId, JSON.stringify(run)]);
|
|
124
|
-
});
|
|
125
|
-
},
|
|
126
|
-
delete(runId, ctx) {
|
|
127
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
128
|
-
yield pool.query(`DELETE FROM agent_serve_eval_runs
|
|
129
|
-
WHERE deployment_id = $1 AND agent = $2 AND run_id = $3`, [deploymentId, ctx.agentName, runId]);
|
|
130
|
-
});
|
|
131
|
-
},
|
|
132
|
-
list(ctx) {
|
|
133
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
134
|
-
const result = yield pool.query(`SELECT run FROM agent_serve_eval_runs
|
|
135
|
-
WHERE deployment_id = $1 AND agent = $2`, [deploymentId, ctx.agentName]);
|
|
136
|
-
return result.rows.map((row) => row.run);
|
|
137
|
-
});
|
|
138
|
-
},
|
|
139
|
-
},
|
|
140
|
-
// A/B metrics → agent_serve_ab: sample rows plus one snapshot row.
|
|
141
|
-
abs: {
|
|
142
|
-
putSample(sample, ctx) {
|
|
143
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
144
|
-
yield upsertAbRow(pool, {
|
|
145
|
-
deploymentId,
|
|
146
|
-
agent: ctx.agentName,
|
|
147
|
-
kind: "sample",
|
|
148
|
-
// One boundary event emits a sample per enrolled experiment with
|
|
149
|
-
// the same sessionId/at — the experiment must be in the row key
|
|
150
|
-
// or those samples overwrite each other.
|
|
151
|
-
ref: `${sample.experiment}/${sample.sessionId}/${sample.at}`,
|
|
152
|
-
value: sample,
|
|
153
|
-
});
|
|
154
|
-
});
|
|
155
|
-
},
|
|
156
|
-
putSnapshot(snapshot, ctx) {
|
|
157
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
158
|
-
yield upsertAbRow(pool, {
|
|
159
|
-
deploymentId,
|
|
160
|
-
agent: ctx.agentName,
|
|
161
|
-
kind: "snapshot",
|
|
162
|
-
ref: "",
|
|
163
|
-
value: snapshot,
|
|
164
|
-
});
|
|
165
|
-
});
|
|
166
|
-
},
|
|
167
|
-
getSnapshot(ctx) {
|
|
168
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
169
|
-
var _a;
|
|
170
|
-
const result = yield pool.query(`SELECT value FROM agent_serve_ab
|
|
171
|
-
WHERE deployment_id = $1 AND agent = $2 AND kind = 'snapshot' AND ref = ''`, [deploymentId, ctx.agentName]);
|
|
172
|
-
return (_a = result.rows[0]) === null || _a === void 0 ? void 0 : _a.value;
|
|
173
|
-
});
|
|
174
|
-
},
|
|
175
|
-
},
|
|
176
|
-
};
|
|
177
|
-
}
|
|
178
|
-
function upsertAbRow(pool, row) {
|
|
179
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
180
|
-
yield pool.query(`INSERT INTO agent_serve_ab (deployment_id, agent, kind, ref, value, updated_at)
|
|
181
|
-
VALUES ($1, $2, $3, $4, $5::jsonb, now())
|
|
182
|
-
ON CONFLICT ON CONSTRAINT pk_agent_serve_ab
|
|
183
|
-
DO UPDATE SET value = EXCLUDED.value, updated_at = now()`, [row.deploymentId, row.agent, row.kind, row.ref, JSON.stringify(row.value)]);
|
|
184
|
-
});
|
|
185
|
-
}
|
|
@@ -1,253 +0,0 @@
|
|
|
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
|
-
* For Cursor-managed hosting prefer `cursorHostedStorage` from
|
|
13
|
-
* `@cursor/july/storage/cursor-hosted` — same tables via a control-plane
|
|
14
|
-
* HTTP proxy (no pod-visible DSN). Use this helper when you supply
|
|
15
|
-
* `BUGBOTDB_URL` / `AGENT_SERVE_DEPLOYMENT_ID` yourself (self-host).
|
|
16
|
-
*
|
|
17
|
-
* `postgresStorage` implements the whole `defineStorage` surface as plain
|
|
18
|
-
* SQL: the four KV methods against the last-write-wins `agent_serve_kv`
|
|
19
|
-
* table (sessions, event chunks, continuations, reminders), the `evals`
|
|
20
|
-
* table against `agent_serve_eval_runs` (one row per playground eval
|
|
21
|
-
* batch), and the `abs` table against `agent_serve_ab` (`kind = 'sample'`
|
|
22
|
-
* rows per metric sample plus one `kind = 'snapshot'` row holding the
|
|
23
|
-
* latest aggregate).
|
|
24
|
-
*
|
|
25
|
-
* - KV `put` upserts on the primary key (LWW matches the framework contract).
|
|
26
|
-
* - KV `list` is a prefix range scan on the PK btree (`key >= p AND key < p||…`
|
|
27
|
-
* spelled as LIKE with escaped wildcards, ordered by key).
|
|
28
|
-
* - `get` returning no row is a definitive miss (`undefined`); a connection
|
|
29
|
-
* error throws, so lazy restore fails the follow-up instead of forking
|
|
30
|
-
* the session.
|
|
31
|
-
*
|
|
32
|
-
* Connection comes from `BUGBOTDB_URL` — the repo-wide convention for the
|
|
33
|
-
* bugbot Postgres database, whose Prisma package owns these tables' schema
|
|
34
|
-
* and migrations; locally it falls back to the dev bugbot DB. Non-local
|
|
35
|
-
* URLs enable TLS (`ssl.rejectUnauthorized`) because PlanetScale requires
|
|
36
|
-
* SSL even when the vault URL omits `sslmode`.
|
|
37
|
-
* `deploymentId` scopes rows per deployment (`AGENT_SERVE_DEPLOYMENT_ID`);
|
|
38
|
-
* the local default keeps dev runs of different checkouts from colliding
|
|
39
|
-
* only by agent name.
|
|
40
|
-
*
|
|
41
|
-
* Callers must pass `Pool` from their own `import { Pool } from "pg"`.
|
|
42
|
-
* This module must not import `pg` itself: Node resolves modules from
|
|
43
|
-
* *this* file's directory tree, so a `pg` dep declared only on the
|
|
44
|
-
* consuming agent package would never be found after a hosted install.
|
|
45
|
-
*/
|
|
46
|
-
|
|
47
|
-
import type { ABSnapshot } from "../ab.js";
|
|
48
|
-
import type { EvalRunSnapshot } from "../evals.js";
|
|
49
|
-
import type {
|
|
50
|
-
StorageABTable,
|
|
51
|
-
StorageConfig,
|
|
52
|
-
StorageEntry,
|
|
53
|
-
StorageEvalsTable,
|
|
54
|
-
} from "../storage.js";
|
|
55
|
-
import type { JsonValue } from "../types.js";
|
|
56
|
-
|
|
57
|
-
/** Minimal `pg.Pool` surface used here (avoids importing `pg` from this path). */
|
|
58
|
-
export interface PostgresQueryable {
|
|
59
|
-
query<T extends Record<string, unknown> = Record<string, unknown>>(
|
|
60
|
-
text: string,
|
|
61
|
-
values?: readonly unknown[]
|
|
62
|
-
): Promise<{ rows: T[] }>;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/** `pg.Pool` constructor supplied by the consuming example package. */
|
|
66
|
-
export type PostgresPoolConstructor = new (config?: {
|
|
67
|
-
connectionString?: string;
|
|
68
|
-
max?: number;
|
|
69
|
-
ssl?: boolean | { rejectUnauthorized?: boolean };
|
|
70
|
-
}) => PostgresQueryable;
|
|
71
|
-
|
|
72
|
-
export interface PostgresStorageOptions {
|
|
73
|
-
/**
|
|
74
|
-
* Pass `Pool` from `import { Pool } from "pg"` in the example that declares
|
|
75
|
-
* the `pg` dependency (hosted installs put it in that package's
|
|
76
|
-
* `node_modules` only).
|
|
77
|
-
*/
|
|
78
|
-
Pool: PostgresPoolConstructor;
|
|
79
|
-
/** Postgres connection string (default: env, then local bugbot dev DB). */
|
|
80
|
-
databaseUrl?: string;
|
|
81
|
-
/** Value for the tables' deployment_id column (default: env or "local-dev"). */
|
|
82
|
-
deploymentId?: string;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
type PostgresStorageMethods = Required<
|
|
86
|
-
Pick<StorageConfig, "put" | "get" | "delete" | "list">
|
|
87
|
-
> & {
|
|
88
|
-
evals: StorageEvalsTable;
|
|
89
|
-
abs: StorageABTable;
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
/** True for local bugbot/dev URLs that do not speak TLS. */
|
|
93
|
-
export function isLocalPostgresUrl(connectionString: string): boolean {
|
|
94
|
-
try {
|
|
95
|
-
const host = new URL(connectionString).hostname.toLowerCase();
|
|
96
|
-
return (
|
|
97
|
-
host === "localhost" ||
|
|
98
|
-
host === "127.0.0.1" ||
|
|
99
|
-
host === "::1" ||
|
|
100
|
-
host === "[::1]"
|
|
101
|
-
);
|
|
102
|
-
} catch {
|
|
103
|
-
return /@(localhost|127\.0\.0\.1|\[::1\])([:/]|$)/i.test(connectionString);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/** Postgres-backed `defineStorage` methods, ready to spread into `defineStorage({...})`. */
|
|
108
|
-
export function postgresStorage(
|
|
109
|
-
options: PostgresStorageOptions
|
|
110
|
-
): PostgresStorageMethods {
|
|
111
|
-
const connectionString =
|
|
112
|
-
options.databaseUrl ??
|
|
113
|
-
process.env.BUGBOTDB_URL ??
|
|
114
|
-
"postgresql://prisma:prisma@localhost:5432/bugbot";
|
|
115
|
-
// Prod Bugbot is PlanetScale Postgres: TLS is required and the vault
|
|
116
|
-
// `BUGBOTDB_URL` often omits `sslmode`. Without an explicit `ssl` option,
|
|
117
|
-
// `pg` opens plaintext and PlanetScale rejects with "SSL connection is
|
|
118
|
-
// required" — sessions stay in-memory. Skip TLS only for local hosts.
|
|
119
|
-
const pool = new options.Pool({
|
|
120
|
-
connectionString,
|
|
121
|
-
// Small fixed pool per agent, mirroring the backend's connection_limit
|
|
122
|
-
// clamp on BUGBOTDB_URL consumers (backend/server/src/prisma.ts).
|
|
123
|
-
max: 3,
|
|
124
|
-
...(isLocalPostgresUrl(connectionString)
|
|
125
|
-
? {}
|
|
126
|
-
: { ssl: { rejectUnauthorized: true } }),
|
|
127
|
-
});
|
|
128
|
-
const deploymentId =
|
|
129
|
-
options.deploymentId ??
|
|
130
|
-
process.env.AGENT_SERVE_DEPLOYMENT_ID ??
|
|
131
|
-
"local-dev";
|
|
132
|
-
|
|
133
|
-
return {
|
|
134
|
-
async put(key, value): Promise<void> {
|
|
135
|
-
await pool.query(
|
|
136
|
-
`INSERT INTO agent_serve_kv (deployment_id, key, value, updated_at)
|
|
137
|
-
VALUES ($1, $2, $3::jsonb, now())
|
|
138
|
-
ON CONFLICT ON CONSTRAINT pk_agent_serve_kv
|
|
139
|
-
DO UPDATE SET value = EXCLUDED.value, updated_at = now()`,
|
|
140
|
-
[deploymentId, key, JSON.stringify(value)]
|
|
141
|
-
);
|
|
142
|
-
},
|
|
143
|
-
|
|
144
|
-
async get(key): Promise<JsonValue | undefined> {
|
|
145
|
-
const result = await pool.query<{ value: JsonValue }>(
|
|
146
|
-
`SELECT value FROM agent_serve_kv
|
|
147
|
-
WHERE deployment_id = $1 AND key = $2`,
|
|
148
|
-
[deploymentId, key]
|
|
149
|
-
);
|
|
150
|
-
return result.rows[0]?.value; // no row ⇒ definitive miss
|
|
151
|
-
},
|
|
152
|
-
|
|
153
|
-
async delete(key): Promise<void> {
|
|
154
|
-
await pool.query(
|
|
155
|
-
`DELETE FROM agent_serve_kv WHERE deployment_id = $1 AND key = $2`,
|
|
156
|
-
[deploymentId, key]
|
|
157
|
-
);
|
|
158
|
-
},
|
|
159
|
-
|
|
160
|
-
async list(prefix): Promise<StorageEntry[]> {
|
|
161
|
-
// Escape LIKE wildcards in the prefix so keys containing % or _
|
|
162
|
-
// (URI-encoded segments cannot, but be safe) match literally.
|
|
163
|
-
const escaped = prefix.replace(/([\\%_])/g, "\\$1");
|
|
164
|
-
const result = await pool.query<{ key: string; value: JsonValue }>(
|
|
165
|
-
`SELECT key, value FROM agent_serve_kv
|
|
166
|
-
WHERE deployment_id = $1 AND key LIKE $2 ESCAPE '\\'
|
|
167
|
-
ORDER BY key ASC`,
|
|
168
|
-
[deploymentId, `${escaped}%`]
|
|
169
|
-
);
|
|
170
|
-
return result.rows;
|
|
171
|
-
},
|
|
172
|
-
|
|
173
|
-
// Playground eval batches → agent_serve_eval_runs (one row per run).
|
|
174
|
-
evals: {
|
|
175
|
-
async put(run, ctx): Promise<void> {
|
|
176
|
-
await pool.query(
|
|
177
|
-
`INSERT INTO agent_serve_eval_runs (deployment_id, agent, run_id, run, updated_at)
|
|
178
|
-
VALUES ($1, $2, $3, $4::jsonb, now())
|
|
179
|
-
ON CONFLICT ON CONSTRAINT pk_agent_serve_eval_runs
|
|
180
|
-
DO UPDATE SET run = EXCLUDED.run, updated_at = now()`,
|
|
181
|
-
[deploymentId, ctx.agentName, run.runId, JSON.stringify(run)]
|
|
182
|
-
);
|
|
183
|
-
},
|
|
184
|
-
async delete(runId, ctx): Promise<void> {
|
|
185
|
-
await pool.query(
|
|
186
|
-
`DELETE FROM agent_serve_eval_runs
|
|
187
|
-
WHERE deployment_id = $1 AND agent = $2 AND run_id = $3`,
|
|
188
|
-
[deploymentId, ctx.agentName, runId]
|
|
189
|
-
);
|
|
190
|
-
},
|
|
191
|
-
async list(ctx): Promise<EvalRunSnapshot[]> {
|
|
192
|
-
const result = await pool.query<{ run: EvalRunSnapshot }>(
|
|
193
|
-
`SELECT run FROM agent_serve_eval_runs
|
|
194
|
-
WHERE deployment_id = $1 AND agent = $2`,
|
|
195
|
-
[deploymentId, ctx.agentName]
|
|
196
|
-
);
|
|
197
|
-
return result.rows.map((row) => row.run);
|
|
198
|
-
},
|
|
199
|
-
},
|
|
200
|
-
|
|
201
|
-
// A/B metrics → agent_serve_ab: sample rows plus one snapshot row.
|
|
202
|
-
abs: {
|
|
203
|
-
async putSample(sample, ctx): Promise<void> {
|
|
204
|
-
await upsertAbRow(pool, {
|
|
205
|
-
deploymentId,
|
|
206
|
-
agent: ctx.agentName,
|
|
207
|
-
kind: "sample",
|
|
208
|
-
// One boundary event emits a sample per enrolled experiment with
|
|
209
|
-
// the same sessionId/at — the experiment must be in the row key
|
|
210
|
-
// or those samples overwrite each other.
|
|
211
|
-
ref: `${sample.experiment}/${sample.sessionId}/${sample.at}`,
|
|
212
|
-
value: sample,
|
|
213
|
-
});
|
|
214
|
-
},
|
|
215
|
-
async putSnapshot(snapshot, ctx): Promise<void> {
|
|
216
|
-
await upsertAbRow(pool, {
|
|
217
|
-
deploymentId,
|
|
218
|
-
agent: ctx.agentName,
|
|
219
|
-
kind: "snapshot",
|
|
220
|
-
ref: "",
|
|
221
|
-
value: snapshot,
|
|
222
|
-
});
|
|
223
|
-
},
|
|
224
|
-
async getSnapshot(ctx): Promise<ABSnapshot | undefined> {
|
|
225
|
-
const result = await pool.query<{ value: JsonValue }>(
|
|
226
|
-
`SELECT value FROM agent_serve_ab
|
|
227
|
-
WHERE deployment_id = $1 AND agent = $2 AND kind = 'snapshot' AND ref = ''`,
|
|
228
|
-
[deploymentId, ctx.agentName]
|
|
229
|
-
);
|
|
230
|
-
return result.rows[0]?.value as unknown as ABSnapshot | undefined;
|
|
231
|
-
},
|
|
232
|
-
},
|
|
233
|
-
};
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
async function upsertAbRow(
|
|
237
|
-
pool: PostgresQueryable,
|
|
238
|
-
row: {
|
|
239
|
-
deploymentId: string;
|
|
240
|
-
agent: string;
|
|
241
|
-
kind: "sample" | "snapshot";
|
|
242
|
-
ref: string;
|
|
243
|
-
value: unknown;
|
|
244
|
-
}
|
|
245
|
-
): Promise<void> {
|
|
246
|
-
await pool.query(
|
|
247
|
-
`INSERT INTO agent_serve_ab (deployment_id, agent, kind, ref, value, updated_at)
|
|
248
|
-
VALUES ($1, $2, $3, $4, $5::jsonb, now())
|
|
249
|
-
ON CONFLICT ON CONSTRAINT pk_agent_serve_ab
|
|
250
|
-
DO UPDATE SET value = EXCLUDED.value, updated_at = now()`,
|
|
251
|
-
[row.deploymentId, row.agent, row.kind, row.ref, JSON.stringify(row.value)]
|
|
252
|
-
);
|
|
253
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|