@cursor/july 0.1.108 → 0.1.109
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 +2 -6
- package/README.md +3 -6
- package/dist/channels/bitbucket/api.d.ts +41 -0
- package/dist/channels/bitbucket/api.d.ts.map +1 -1
- package/dist/channels/bitbucket/api.js +260 -0
- package/dist/channels/bitbucket/binding.d.ts +4 -0
- package/dist/channels/bitbucket/binding.d.ts.map +1 -1
- package/dist/channels/bitbucket/binding.js +16 -0
- package/dist/channels/bitbucket/index.d.ts +1 -1
- package/dist/channels/bitbucket/index.d.ts.map +1 -1
- package/dist/channels/bitbucket/index.js +1 -1
- package/dist/channels/gitlab/api.d.ts +27 -0
- package/dist/channels/gitlab/api.d.ts.map +1 -1
- package/dist/channels/gitlab/api.js +88 -0
- package/dist/channels/gitlab/binding.d.ts +5 -0
- package/dist/channels/gitlab/binding.d.ts.map +1 -1
- package/dist/channels/gitlab/binding.js +10 -0
- package/dist/channels/gitlab/index.d.ts +1 -1
- package/dist/channels/gitlab/index.d.ts.map +1 -1
- package/dist/channels/gitlab/index.js +1 -1
- package/dist/channels/slack/dispatch.d.ts +10 -0
- package/dist/channels/slack/dispatch.d.ts.map +1 -1
- package/dist/channels/slack/dispatch.js +20 -3
- package/dist/channels/slack/slack-channel.d.ts +12 -5
- package/dist/channels/slack/slack-channel.d.ts.map +1 -1
- package/dist/channels/slack/slack-channel.js +59 -8
- package/dist/docs/404.html +2 -2
- package/dist/docs/assets/{app.BASKM3M4.js → app.Cr-wVbnB.js} +1 -1
- package/dist/docs/assets/{building-with-agents.md.CUSWxlP_.js → building-with-agents.md.D0KbSkJn.js} +2 -2
- package/dist/docs/assets/{building-with-agents.md.CUSWxlP_.lean.js → building-with-agents.md.D0KbSkJn.lean.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.CFVQ4S17.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.BOKxlYGP.js → VPLocalSearchBox.CVQERt56.js} +1 -1
- package/dist/docs/assets/chunks/{theme.DbDZW-zb.js → theme.Dnsd3XOn.js} +2 -2
- package/dist/docs/assets/concepts.md.B4o63Gul.js +1 -0
- package/dist/docs/assets/evals.md.C7JLjoEP.js +211 -0
- package/dist/docs/assets/evals.md.C7JLjoEP.lean.js +1 -0
- package/dist/docs/assets/guides_bitbucket.md.DZPzmUjU.js +10 -0
- package/dist/docs/assets/guides_bitbucket.md.DZPzmUjU.lean.js +1 -0
- package/dist/docs/assets/{guides_github.md.BH33UEBJ.js → guides_github.md.TZaTZlfz.js} +13 -3
- package/dist/docs/assets/{guides_github.md.BH33UEBJ.lean.js → guides_github.md.TZaTZlfz.lean.js} +1 -1
- package/dist/docs/assets/guides_gitlab.md.BmqwQfdG.js +14 -0
- package/dist/docs/assets/guides_gitlab.md.BmqwQfdG.lean.js +1 -0
- package/dist/docs/assets/{guides_webhooks.md.DKdA43Qm.js → guides_webhooks.md.CJK484ex.js} +2 -2
- package/dist/docs/assets/{hillclimbing.md.CpTGTCle.js → hillclimbing.md.BOiVo1tf.js} +1 -1
- package/dist/docs/assets/index.md.DD9Q2XuJ.js +5 -0
- package/dist/docs/assets/{index.md.BjH1w2ZW.lean.js → index.md.DD9Q2XuJ.lean.js} +1 -1
- package/dist/docs/assets/{reference_channels.md.D-qTqwcq.js → reference_channels.md.CAo-iK4j.js} +2 -2
- package/dist/docs/assets/{reference_channels.md.D-qTqwcq.lean.js → reference_channels.md.CAo-iK4j.lean.js} +1 -1
- package/dist/docs/assets/{reference_cli.md.Ca26u0Es.js → reference_cli.md.Deg7849l.js} +1 -1
- package/dist/docs/assets/{reference_extensions.md.CPWt00ds.js → reference_extensions.md.ZAVUyuEX.js} +2 -2
- package/dist/docs/assets/{reference_hooks.md.Ddt5DdgJ.js → reference_hooks.md.BlM_bOg6.js} +3 -3
- package/dist/docs/assets/{reference_hooks.md.Ddt5DdgJ.lean.js → reference_hooks.md.BlM_bOg6.lean.js} +1 -1
- package/dist/docs/assets/{reference_http-api.md.oySXBO8o.js → reference_http-api.md.BwaCo-VO.js} +1 -1
- package/dist/docs/assets/{reference_playground.md.4myJPxrf.js → reference_playground.md.DLnoaczX.js} +1 -1
- package/dist/docs/assets/{reference_playground.md.4myJPxrf.lean.js → reference_playground.md.DLnoaczX.lean.js} +1 -1
- package/dist/docs/assets/{reference_project-layout.md.DuBu9a96.js → reference_project-layout.md.BEU8MtQV.js} +3 -3
- package/dist/docs/assets/{reference_project-layout.md.DuBu9a96.lean.js → reference_project-layout.md.BEU8MtQV.lean.js} +1 -1
- package/dist/docs/assets/reference_sessions.md.CyXV1MUw.js +1 -0
- package/dist/docs/assets/skills_deploy.md.CWqi_ZxW.js +35 -0
- package/dist/docs/assets/skills_deploy.md.CWqi_ZxW.lean.js +1 -0
- package/dist/docs/assets/{skills_evals.md.BhovOvrl.js → skills_evals.md.DFxYPErF.js} +3 -3
- package/dist/docs/assets/skills_evals.md.DFxYPErF.lean.js +1 -0
- package/dist/docs/assets/{skills_framework-map.md.D-tFZhFS.js → skills_framework-map.md.BxLSOhSY.js} +1 -1
- package/dist/docs/assets/skills_index.md.DL7EHaQ-.js +1 -0
- package/dist/docs/assets/skills_index.md.DL7EHaQ-.lean.js +1 -0
- package/dist/docs/assets/{storage.md.BOHeqk2M.js → storage.md.BUrhJ-Zz.js} +4 -4
- package/dist/docs/assets/{storage.md.BOHeqk2M.lean.js → storage.md.BUrhJ-Zz.lean.js} +1 -1
- package/dist/docs/building-with-agents.html +5 -5
- package/dist/docs/building-with-agents.md +3 -2
- package/dist/docs/concepts.html +5 -5
- package/dist/docs/concepts.md +2 -4
- package/dist/docs/deployment.html +4 -4
- package/dist/docs/evals.html +161 -35
- package/dist/docs/evals.md +612 -297
- package/dist/docs/guides/agent-to-agent.html +4 -4
- package/dist/docs/guides/bitbucket.html +36 -0
- package/dist/docs/guides/bitbucket.md +84 -0
- package/dist/docs/guides/cloud-agents.html +4 -4
- package/dist/docs/guides/convert-automation.html +4 -4
- package/dist/docs/guides/github.html +17 -7
- package/dist/docs/guides/github.md +31 -0
- package/dist/docs/guides/gitlab.html +40 -0
- package/dist/docs/guides/gitlab.md +92 -0
- package/dist/docs/guides/grokbot-agents.html +4 -4
- package/dist/docs/guides/human-in-the-loop.html +4 -4
- package/dist/docs/guides/improve.html +4 -4
- package/dist/docs/guides/mcp-oauth.html +4 -4
- package/dist/docs/guides/opentelemetry.html +4 -4
- package/dist/docs/guides/slack.html +5 -5
- package/dist/docs/guides/webhooks.html +6 -6
- package/dist/docs/guides/webhooks.md +4 -2
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +6 -6
- package/dist/docs/hillclimbing.md +2 -2
- package/dist/docs/index.html +6 -6
- package/dist/docs/index.md +10 -6
- package/dist/docs/llms-full.txt +1113 -778
- package/dist/docs/llms.txt +6 -5
- package/dist/docs/quickstart.html +4 -4
- package/dist/docs/reference/agent-config.html +4 -4
- package/dist/docs/reference/artifacts.html +4 -4
- package/dist/docs/reference/channels.html +6 -6
- package/dist/docs/reference/channels.md +16 -3
- package/dist/docs/reference/cli.html +6 -6
- package/dist/docs/reference/cli.md +6 -4
- package/dist/docs/reference/connections.html +4 -4
- package/dist/docs/reference/extensions.html +7 -7
- package/dist/docs/reference/extensions.md +0 -3
- package/dist/docs/reference/hooks.html +7 -7
- package/dist/docs/reference/hooks.md +9 -12
- package/dist/docs/reference/http-api.html +6 -6
- package/dist/docs/reference/http-api.md +2 -3
- package/dist/docs/reference/instructions.html +4 -4
- package/dist/docs/reference/playground.html +5 -5
- package/dist/docs/reference/playground.md +0 -4
- package/dist/docs/reference/project-layout.html +7 -7
- package/dist/docs/reference/project-layout.md +1 -8
- package/dist/docs/reference/prompt.html +4 -4
- package/dist/docs/reference/result.html +4 -4
- package/dist/docs/reference/schedules.html +4 -4
- package/dist/docs/reference/sessions.html +5 -5
- package/dist/docs/reference/sessions.md +1 -2
- package/dist/docs/reference/skills.html +4 -4
- package/dist/docs/reference/subagents.html +4 -4
- package/dist/docs/reference/tools.html +4 -4
- package/dist/docs/scaffolding-agents.html +4 -4
- package/dist/docs/skills/create-agent.html +4 -4
- package/dist/docs/skills/debug.html +4 -4
- package/dist/docs/skills/deploy.html +61 -0
- package/dist/docs/skills/deploy.md +161 -0
- package/dist/docs/skills/evals.html +8 -8
- package/dist/docs/skills/evals.md +44 -6
- package/dist/docs/skills/framework-map.html +5 -5
- package/dist/docs/skills/framework-map.md +1 -2
- package/dist/docs/skills/github.html +4 -4
- package/dist/docs/skills/hillclimb.html +4 -4
- package/dist/docs/skills/index.html +6 -6
- package/dist/docs/skills/index.md +1 -1
- package/dist/docs/skills/mcp-auth.html +4 -4
- package/dist/docs/skills/otel.html +4 -4
- package/dist/docs/skills/setup-slack.html +4 -4
- package/dist/docs/storage.html +8 -8
- package/dist/docs/storage.md +15 -24
- package/dist/docs/templates/agentic-owners.html +4 -4
- package/dist/docs/templates/agents-md.html +4 -4
- package/dist/docs/templates/code-wiki.html +4 -4
- package/dist/docs/templates/demo.html +4 -4
- package/dist/docs/templates/grokbot-agents.html +4 -4
- package/dist/docs/templates/pr-autofixer.html +4 -4
- package/dist/docs/templates/security-help.html +4 -4
- package/dist/docs/templates/security-reviewer.html +4 -4
- package/dist/docs/templates/triage.html +4 -4
- package/dist/docs/troubleshooting.html +4 -4
- package/dist/extensions.d.ts +2 -3
- package/dist/extensions.d.ts.map +1 -1
- package/dist/extensions.js +2 -5
- package/dist/index.d.ts +2 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -2
- package/dist/internal/authored-alias-hooks.d.ts +5 -0
- package/dist/internal/authored-alias-hooks.d.ts.map +1 -1
- package/dist/internal/authored-alias-hooks.js +17 -0
- package/dist/internal/authored-loaders.d.ts +4 -0
- package/dist/internal/authored-loaders.d.ts.map +1 -1
- package/dist/internal/authored-loaders.js +21 -2
- package/dist/internal/cli-ax.d.ts +1 -2
- package/dist/internal/cli-ax.d.ts.map +1 -1
- package/dist/internal/cli-ax.js +1 -2
- package/dist/internal/continuation-channel.d.ts.map +1 -1
- package/dist/internal/continuation-channel.js +2 -2
- package/dist/internal/continuation-identity.js +8 -3
- package/dist/internal/discovery/agent.d.ts +1 -1
- package/dist/internal/discovery/agent.d.ts.map +1 -1
- package/dist/internal/discovery/agent.js +0 -5
- package/dist/internal/discovery/extension-overlay.d.ts +1 -2
- package/dist/internal/discovery/extension-overlay.d.ts.map +1 -1
- package/dist/internal/discovery/extension-overlay.js +0 -14
- package/dist/internal/discovery/extensions.d.ts +1 -2
- package/dist/internal/discovery/extensions.d.ts.map +1 -1
- package/dist/internal/discovery/extensions.js +4 -22
- package/dist/internal/discovery/info.d.ts.map +1 -1
- package/dist/internal/discovery/info.js +42 -24
- package/dist/internal/discovery/modules.js +0 -1
- package/dist/internal/discovery/project.d.ts.map +1 -1
- package/dist/internal/discovery/project.js +0 -16
- package/dist/internal/eval-runner.js +0 -1
- package/dist/internal/framework-file-storage.d.ts +4 -5
- package/dist/internal/framework-file-storage.d.ts.map +1 -1
- package/dist/internal/framework-file-storage.js +4 -5
- package/dist/internal/framework-storage-selection.d.ts +2 -2
- package/dist/internal/framework-storage-selection.js +2 -2
- package/dist/internal/init-scaffold.d.ts.map +1 -1
- package/dist/internal/init-scaffold.js +1 -2
- package/dist/internal/install-cursor-skills.d.ts +5 -2
- package/dist/internal/install-cursor-skills.d.ts.map +1 -1
- package/dist/internal/install-cursor-skills.js +25 -5
- package/dist/internal/run-client.d.ts +1 -1
- package/dist/internal/sdk-runner.js +1 -1
- package/dist/internal/server.js +0 -14
- package/dist/internal/session-engine.d.ts +5 -35
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +17 -162
- package/dist/internal/storage-coordinator.d.ts +5 -19
- package/dist/internal/storage-coordinator.d.ts.map +1 -1
- package/dist/internal/storage-coordinator.js +3 -62
- package/dist/internal/storage-roles.d.ts +4 -9
- package/dist/internal/storage-roles.d.ts.map +1 -1
- package/dist/internal/storage-roles.js +2 -2
- package/dist/playground/assets/index-Bhxzrcf6.css +1 -0
- package/dist/playground/assets/index-CqLX5uF3.js +67 -0
- package/dist/playground/index.html +2 -2
- package/dist/storage-backends/cursor-hosted-v2.d.ts +4 -5
- package/dist/storage-backends/cursor-hosted-v2.d.ts.map +1 -1
- package/dist/storage-backends/cursor-hosted-v2.js +4 -5
- package/dist/storage-backends/cursor-hosted.d.ts +1 -2
- package/dist/storage-backends/cursor-hosted.d.ts.map +1 -1
- package/dist/storage-backends/cursor-hosted.js +0 -30
- package/dist/storage-backends/file-kv.d.ts +9 -12
- package/dist/storage-backends/file-kv.d.ts.map +1 -1
- package/dist/storage-backends/file-kv.js +11 -47
- package/dist/storage-protocol.d.ts +3 -11
- package/dist/storage-protocol.d.ts.map +1 -1
- package/dist/storage-protocol.js +3 -11
- package/dist/storage.d.ts +8 -36
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +8 -44
- package/dist/types.d.ts +20 -57
- package/dist/types.d.ts.map +1 -1
- package/docs/README.md +10 -6
- package/docs/building-with-agents.md +3 -2
- package/docs/concepts.md +2 -4
- package/docs/evals.md +613 -298
- package/docs/guides/bitbucket.md +89 -0
- package/docs/guides/github.md +31 -0
- package/docs/guides/gitlab.md +97 -0
- package/docs/guides/webhooks.md +4 -2
- package/docs/hillclimbing.md +2 -2
- package/docs/reference/channels.md +16 -3
- package/docs/reference/cli.md +6 -4
- package/docs/reference/extensions.md +0 -3
- package/docs/reference/hooks.md +9 -12
- package/docs/reference/http-api.md +2 -3
- package/docs/reference/playground.md +0 -4
- package/docs/reference/project-layout.md +1 -8
- package/docs/reference/sessions.md +1 -2
- package/docs/skills/index.md +2 -2
- package/docs/storage.md +15 -24
- package/package.json +1 -7
- package/skills/deploy/SKILL.md +169 -0
- package/skills/evals/SKILL.md +45 -8
- package/skills/framework-map/SKILL.md +1 -2
- package/src/channels/bitbucket/api.ts +341 -0
- package/src/channels/bitbucket/binding.ts +25 -0
- package/src/channels/bitbucket/index.ts +2 -0
- package/src/channels/gitlab/api.ts +123 -0
- package/src/channels/gitlab/binding.ts +12 -0
- package/src/channels/gitlab/index.ts +1 -0
- package/src/channels/slack/dispatch.ts +30 -0
- package/src/channels/slack/slack-channel.ts +69 -7
- package/src/extensions.ts +2 -6
- package/src/index.ts +0 -3
- package/src/internal/authored-alias-hooks.ts +32 -0
- package/src/internal/authored-loaders.ts +26 -2
- package/src/internal/cli-ax.ts +1 -2
- package/src/internal/continuation-channel.ts +2 -1
- package/src/internal/continuation-identity.ts +10 -2
- package/src/internal/discovery/agent.ts +1 -7
- package/src/internal/discovery/extension-overlay.ts +0 -18
- package/src/internal/discovery/extensions.ts +2 -26
- package/src/internal/discovery/info.ts +3 -13
- package/src/internal/discovery/modules.ts +0 -1
- package/src/internal/discovery/project.ts +0 -16
- package/src/internal/eval-runner.ts +0 -1
- package/src/internal/framework-file-storage.ts +4 -5
- package/src/internal/framework-storage-selection.ts +2 -2
- package/src/internal/init-scaffold.ts +1 -2
- package/src/internal/install-cursor-skills.ts +38 -5
- package/src/internal/run-client.ts +1 -1
- package/src/internal/sdk-runner.ts +1 -1
- package/src/internal/server.ts +0 -16
- package/src/internal/session-engine.ts +14 -202
- package/src/internal/storage-coordinator.ts +5 -76
- package/src/internal/storage-roles.ts +4 -9
- package/src/storage-backends/cursor-hosted-v2.ts +4 -7
- package/src/storage-backends/cursor-hosted.ts +0 -37
- package/src/storage-backends/file-kv.ts +10 -51
- package/src/storage-protocol.ts +3 -17
- package/src/storage.ts +10 -101
- package/src/types.ts +19 -56
- package/templates/demo/README.md +10 -6
- package/templates/demo/agent/channels/github.ts +2 -0
- package/templates/demo/agent/channels/queue.ts +6 -2
- package/templates/demo/agent/lib/repos.ts +5 -0
- package/templates/demo/init.json +25 -0
- package/dist/ab.d.ts +0 -209
- package/dist/ab.d.ts.map +0 -1
- package/dist/ab.js +0 -246
- package/dist/docs/ab.html +0 -80
- package/dist/docs/ab.md +0 -332
- package/dist/docs/assets/ab.md.mlVgqvSk.js +0 -54
- package/dist/docs/assets/ab.md.mlVgqvSk.lean.js +0 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.BHZYsNVi.js +0 -1
- package/dist/docs/assets/concepts.md.DgEcZOfT.js +0 -1
- package/dist/docs/assets/evals.md.C1ekS3k2.js +0 -85
- package/dist/docs/assets/evals.md.C1ekS3k2.lean.js +0 -1
- package/dist/docs/assets/index.md.BjH1w2ZW.js +0 -5
- package/dist/docs/assets/reference_sessions.md.CueyOHSL.js +0 -1
- package/dist/docs/assets/skills_ab.md.CsFNatVx.js +0 -26
- package/dist/docs/assets/skills_ab.md.CsFNatVx.lean.js +0 -1
- package/dist/docs/assets/skills_evals.md.BhovOvrl.lean.js +0 -1
- package/dist/docs/assets/skills_index.md.DKwIxzGg.js +0 -1
- package/dist/docs/assets/skills_index.md.DKwIxzGg.lean.js +0 -1
- package/dist/docs/skills/ab.html +0 -52
- package/dist/docs/skills/ab.md +0 -50
- package/dist/internal/ab-collector.d.ts +0 -44
- package/dist/internal/ab-collector.d.ts.map +0 -1
- package/dist/internal/ab-collector.js +0 -142
- package/dist/internal/ab-fold.d.ts +0 -36
- package/dist/internal/ab-fold.d.ts.map +0 -1
- package/dist/internal/ab-fold.js +0 -175
- package/dist/internal/ab-snapshot.d.ts +0 -68
- package/dist/internal/ab-snapshot.d.ts.map +0 -1
- package/dist/internal/ab-snapshot.js +0 -208
- package/dist/internal/discovery/ab.d.ts +0 -9
- package/dist/internal/discovery/ab.d.ts.map +0 -1
- package/dist/internal/discovery/ab.js +0 -113
- package/dist/playground/assets/index-BMDqAeXu.js +0 -67
- package/dist/playground/assets/index-LUgJoWdL.css +0 -1
- package/docs/ab.md +0 -337
- package/skills/ab/SKILL.md +0 -58
- package/src/ab.ts +0 -430
- package/src/internal/ab-collector.ts +0 -200
- package/src/internal/ab-fold.ts +0 -232
- package/src/internal/ab-snapshot.ts +0 -331
- package/src/internal/discovery/ab.ts +0 -131
- /package/dist/docs/assets/{concepts.md.DgEcZOfT.lean.js → concepts.md.B4o63Gul.lean.js} +0 -0
- /package/dist/docs/assets/{guides_webhooks.md.DKdA43Qm.lean.js → guides_webhooks.md.CJK484ex.lean.js} +0 -0
- /package/dist/docs/assets/{hillclimbing.md.CpTGTCle.lean.js → hillclimbing.md.BOiVo1tf.lean.js} +0 -0
- /package/dist/docs/assets/{reference_cli.md.Ca26u0Es.lean.js → reference_cli.md.Deg7849l.lean.js} +0 -0
- /package/dist/docs/assets/{reference_extensions.md.CPWt00ds.lean.js → reference_extensions.md.ZAVUyuEX.lean.js} +0 -0
- /package/dist/docs/assets/{reference_http-api.md.oySXBO8o.lean.js → reference_http-api.md.BwaCo-VO.lean.js} +0 -0
- /package/dist/docs/assets/{reference_sessions.md.CueyOHSL.lean.js → reference_sessions.md.CyXV1MUw.lean.js} +0 -0
- /package/dist/docs/assets/{skills_framework-map.md.D-tFZhFS.lean.js → skills_framework-map.md.BxLSOhSY.lean.js} +0 -0
|
@@ -12,12 +12,6 @@ import { mkdir, rm, writeFile } from "node:fs/promises";
|
|
|
12
12
|
import { dirname, join } from "node:path";
|
|
13
13
|
import type { SDKCustomTool, SDKCustomToolResult } from "@cursor/sdk";
|
|
14
14
|
import type { Meter } from "@opentelemetry/api";
|
|
15
|
-
import {
|
|
16
|
-
type ABDefinition,
|
|
17
|
-
mergeABInstructions,
|
|
18
|
-
resolveABMaxPlaygroundSessions,
|
|
19
|
-
resolveABSplit,
|
|
20
|
-
} from "../ab.js";
|
|
21
15
|
import { SLACK_CHANNEL_ID } from "../channels/slack/constants.js";
|
|
22
16
|
import { materializeSlackNudgeCarrier } from "../channels/slack/nudge-carrier.js";
|
|
23
17
|
import {
|
|
@@ -98,9 +92,6 @@ import {
|
|
|
98
92
|
type ToolNeedsApproval,
|
|
99
93
|
type TurnOutcome,
|
|
100
94
|
} from "../types.js";
|
|
101
|
-
import { ABCollector } from "./ab-collector.js";
|
|
102
|
-
import { foldABStream } from "./ab-fold.js";
|
|
103
|
-
import { type ABSnapshot, buildABSnapshot } from "./ab-snapshot.js";
|
|
104
95
|
import {
|
|
105
96
|
type AdvertiseHostMcp,
|
|
106
97
|
resolveAdvertisedTools,
|
|
@@ -455,8 +446,8 @@ export class SessionEngine {
|
|
|
455
446
|
/**
|
|
456
447
|
* Runtime for `agent/storage.ts` (`defineStorage`), when
|
|
457
448
|
* authored. All durable state changes funnel through it (session
|
|
458
|
-
* records, event chunks
|
|
459
|
-
*
|
|
449
|
+
* records, event chunks); the eval run store attaches via
|
|
450
|
+
* {@link StorageCoordinator.evalRuns} at serve start.
|
|
460
451
|
*/
|
|
461
452
|
readonly storage: StorageCoordinator | undefined;
|
|
462
453
|
/** In-flight lazy restores, deduped per channel + continuation key. */
|
|
@@ -464,8 +455,6 @@ export class SessionEngine {
|
|
|
464
455
|
string,
|
|
465
456
|
Promise<SessionRecord | undefined>
|
|
466
457
|
>();
|
|
467
|
-
/** Once-per-process cache for the A/B snapshot backfill (see abSnapshot). */
|
|
468
|
-
private restoredAbSnapshot: Promise<ABSnapshot | undefined> | undefined;
|
|
469
458
|
/** In-flight authored files → Agent Store syncs (see syncToCloudStore). */
|
|
470
459
|
private readonly cloudSyncs = new Map<CloudSyncSurface, Promise<boolean>>();
|
|
471
460
|
|
|
@@ -528,7 +517,6 @@ export class SessionEngine {
|
|
|
528
517
|
private probeCursorAccount:
|
|
529
518
|
| ((connection: string) => Promise<string | undefined>)
|
|
530
519
|
| undefined;
|
|
531
|
-
private readonly abCollector: ABCollector;
|
|
532
520
|
private readonly otel: OtelCollector | undefined;
|
|
533
521
|
private readonly otelHost: HostOtelSessionApi;
|
|
534
522
|
private readonly stopMemoryTelemetry: (() => void) | undefined;
|
|
@@ -639,13 +627,6 @@ export class SessionEngine {
|
|
|
639
627
|
config: options.project.artifacts,
|
|
640
628
|
sink: managedV2Files?.(),
|
|
641
629
|
});
|
|
642
|
-
this.abCollector = new ABCollector(
|
|
643
|
-
options.project.abs,
|
|
644
|
-
this.logger,
|
|
645
|
-
async (sessionId) => (await this.logs.get(sessionId)).snapshot(0),
|
|
646
|
-
// Samples flow to the defineStorage `abs` table (no-op without one).
|
|
647
|
-
{ persistSample: (sample) => this.storage?.abSample(sample) }
|
|
648
|
-
);
|
|
649
630
|
// Peer and Cursor-account transports are symbolic until the serve host
|
|
650
631
|
// resolves them; the host-side MCP registry starts with the concrete
|
|
651
632
|
// connections and gains the rest via setResolvedConnections.
|
|
@@ -1138,7 +1119,7 @@ export class SessionEngine {
|
|
|
1138
1119
|
const purpose = sendOptions.purpose === "eval" ? "eval" : "live";
|
|
1139
1120
|
const frozenAsOf = normalizeAsOf(sendOptions.asOf);
|
|
1140
1121
|
assertTimeArgs(this.project.agent.tools, frozenAsOf);
|
|
1141
|
-
|
|
1122
|
+
const record: SessionRecord = {
|
|
1142
1123
|
sessionId: sendOptions.hostedSessionId ?? newSessionId(),
|
|
1143
1124
|
channelId,
|
|
1144
1125
|
mode: sendOptions.mode ?? "chat",
|
|
@@ -1167,7 +1148,6 @@ export class SessionEngine {
|
|
|
1167
1148
|
dryRun: record.dryRun === true ? true : undefined,
|
|
1168
1149
|
},
|
|
1169
1150
|
});
|
|
1170
|
-
record = await this.enrollABs(record);
|
|
1171
1151
|
const since = (await this.logs.get(record.sessionId)).count;
|
|
1172
1152
|
await this.startTurn(record.sessionId, message, {
|
|
1173
1153
|
admission: sendOptions.admission ?? "preempt",
|
|
@@ -1241,97 +1221,6 @@ export class SessionEngine {
|
|
|
1241
1221
|
return existing !== undefined;
|
|
1242
1222
|
}
|
|
1243
1223
|
|
|
1244
|
-
/**
|
|
1245
|
-
* Sticky A/B enrollment at session creation — before the first turn, so
|
|
1246
|
-
* variants are in the durable stream (and on {@link SessionRecord.abs})
|
|
1247
|
-
* ahead of model/instructions work. Failures persist as `variant: null`
|
|
1248
|
-
* (sticky skip). Eval harness sessions (`purpose: "eval"`) are never
|
|
1249
|
-
* enrolled.
|
|
1250
|
-
*/
|
|
1251
|
-
private async enrollABs(record: SessionRecord): Promise<SessionRecord> {
|
|
1252
|
-
if (!this.abCollector.enabled || record.purpose === "eval") {
|
|
1253
|
-
return record;
|
|
1254
|
-
}
|
|
1255
|
-
const sessionInfo = this.sessionInfo(record);
|
|
1256
|
-
const abs: Record<string, string | null> = {};
|
|
1257
|
-
for (const experiment of this.project.abs) {
|
|
1258
|
-
const def = experiment.definition as ABDefinition;
|
|
1259
|
-
const variantKeys = Object.keys(def.variants);
|
|
1260
|
-
let variant: string | null = null;
|
|
1261
|
-
try {
|
|
1262
|
-
variant = await resolveABSplit(def.split, {
|
|
1263
|
-
agent: { name: this.project.name },
|
|
1264
|
-
channel: { id: record.channelId },
|
|
1265
|
-
session: sessionInfo,
|
|
1266
|
-
experiment: experiment.name,
|
|
1267
|
-
variants: variantKeys,
|
|
1268
|
-
});
|
|
1269
|
-
if (variant !== null && !(variant in def.variants)) {
|
|
1270
|
-
throw new Error(
|
|
1271
|
-
`split resolved to ${JSON.stringify(variant)}; expected one of ${variantKeys.join(", ")} or null to skip`
|
|
1272
|
-
);
|
|
1273
|
-
}
|
|
1274
|
-
} catch (error) {
|
|
1275
|
-
this.logger(
|
|
1276
|
-
`[agent-sdk] ab "${experiment.name}" enrollment failed (sticky skip): ${describeError(error)}`
|
|
1277
|
-
);
|
|
1278
|
-
variant = null;
|
|
1279
|
-
}
|
|
1280
|
-
abs[experiment.name] = variant;
|
|
1281
|
-
await this.appendEvent(record.sessionId, {
|
|
1282
|
-
type: "ab.assigned",
|
|
1283
|
-
data: { experiment: experiment.name, variant },
|
|
1284
|
-
});
|
|
1285
|
-
}
|
|
1286
|
-
return this.updateRecord(record.sessionId, (current) => ({
|
|
1287
|
-
...current,
|
|
1288
|
-
abs,
|
|
1289
|
-
}));
|
|
1290
|
-
}
|
|
1291
|
-
|
|
1292
|
-
/**
|
|
1293
|
-
* Ensure {@link SessionRecord.abs} is populated (hydrate from the durable
|
|
1294
|
-
* `ab.assigned` stream when missing — e.g. older sessions after upgrade).
|
|
1295
|
-
*/
|
|
1296
|
-
private async ensureAbs(record: SessionRecord): Promise<SessionRecord> {
|
|
1297
|
-
if (record.abs !== undefined || record.purpose === "eval") {
|
|
1298
|
-
return record;
|
|
1299
|
-
}
|
|
1300
|
-
if (!this.abCollector.enabled) {
|
|
1301
|
-
return record;
|
|
1302
|
-
}
|
|
1303
|
-
const events = await this.listEvents(record.sessionId, 0);
|
|
1304
|
-
const folded = foldABStream(events);
|
|
1305
|
-
if (folded.arms.size === 0) {
|
|
1306
|
-
return record;
|
|
1307
|
-
}
|
|
1308
|
-
const abs = Object.fromEntries(folded.arms);
|
|
1309
|
-
return this.updateRecord(record.sessionId, (current) => ({
|
|
1310
|
-
...current,
|
|
1311
|
-
abs,
|
|
1312
|
-
}));
|
|
1313
|
-
}
|
|
1314
|
-
|
|
1315
|
-
/**
|
|
1316
|
-
* Agent config for this session: base project agent plus any per-variant
|
|
1317
|
-
* `instructions` overlays from enrolled A/B arms.
|
|
1318
|
-
*/
|
|
1319
|
-
private agentForSession(record: SessionRecord): ResolvedAgent {
|
|
1320
|
-
const base = this.project.agent;
|
|
1321
|
-
const instructions = mergeABInstructions(
|
|
1322
|
-
base.instructions,
|
|
1323
|
-
record.abs,
|
|
1324
|
-
this.project.abs.map((experiment) => ({
|
|
1325
|
-
name: experiment.name,
|
|
1326
|
-
definition: experiment.definition as ABDefinition,
|
|
1327
|
-
}))
|
|
1328
|
-
);
|
|
1329
|
-
if (instructions === base.instructions) {
|
|
1330
|
-
return base;
|
|
1331
|
-
}
|
|
1332
|
-
return { ...base, instructions };
|
|
1333
|
-
}
|
|
1334
|
-
|
|
1335
1224
|
/** Look up a session as a channel-scoped handle. */
|
|
1336
1225
|
async getChannelSession(
|
|
1337
1226
|
channelId: string,
|
|
@@ -1656,12 +1545,10 @@ export class SessionEngine {
|
|
|
1656
1545
|
|
|
1657
1546
|
let lifecycleInstalled = false;
|
|
1658
1547
|
try {
|
|
1659
|
-
|
|
1548
|
+
const record = await this.updateRecord(sessionId, (current) => ({
|
|
1660
1549
|
...current,
|
|
1661
1550
|
turnCount: current.turnCount + 1,
|
|
1662
1551
|
}));
|
|
1663
|
-
// Arms must be on the record before tools/instructions see SessionInfo.
|
|
1664
|
-
record = await this.ensureAbs(record);
|
|
1665
1552
|
const turnId = `turn_${record.turnCount}`;
|
|
1666
1553
|
const isFirstTurn = record.turnCount === 1;
|
|
1667
1554
|
|
|
@@ -2269,12 +2156,10 @@ export class SessionEngine {
|
|
|
2269
2156
|
emit({ type: "turn.started", data: {} });
|
|
2270
2157
|
try {
|
|
2271
2158
|
// Scaffold agent files into the session workspace even when the harness
|
|
2272
|
-
// cwd is overridden (e.g. a PR worktree).
|
|
2273
|
-
// overlays are applied via agentForSession.
|
|
2274
|
-
const agent = this.agentForSession(record);
|
|
2159
|
+
// cwd is overridden (e.g. a PR worktree).
|
|
2275
2160
|
if (!this.hasRootOverride()) {
|
|
2276
2161
|
await materializeWorkspace({
|
|
2277
|
-
agent,
|
|
2162
|
+
agent: this.project.agent,
|
|
2278
2163
|
workspaceDir,
|
|
2279
2164
|
seed: isFirstTurn,
|
|
2280
2165
|
stateRoot: this.stateRoot,
|
|
@@ -2296,7 +2181,7 @@ export class SessionEngine {
|
|
|
2296
2181
|
const pendingFiles = record.pendingWorkspaceFiles;
|
|
2297
2182
|
const pendingImages = record.pendingImages;
|
|
2298
2183
|
const runtime = resolveSessionRuntime({
|
|
2299
|
-
agentRuntime: agent.runtime,
|
|
2184
|
+
agentRuntime: this.project.agent.runtime,
|
|
2300
2185
|
cloudOverride: record.cloudOverride,
|
|
2301
2186
|
});
|
|
2302
2187
|
const hasPendingFiles =
|
|
@@ -2339,7 +2224,6 @@ export class SessionEngine {
|
|
|
2339
2224
|
(await isNestedInGitRepo(harnessCwd)));
|
|
2340
2225
|
const request = await this.buildTurnRequest(
|
|
2341
2226
|
record,
|
|
2342
|
-
agent,
|
|
2343
2227
|
turnId,
|
|
2344
2228
|
message,
|
|
2345
2229
|
isFirstTurn,
|
|
@@ -2713,7 +2597,6 @@ export class SessionEngine {
|
|
|
2713
2597
|
|
|
2714
2598
|
private async buildTurnRequest(
|
|
2715
2599
|
record: SessionRecord,
|
|
2716
|
-
agent: ResolvedAgent,
|
|
2717
2600
|
turnId: string,
|
|
2718
2601
|
prompt: string,
|
|
2719
2602
|
isFirstTurn: boolean,
|
|
@@ -2724,6 +2607,7 @@ export class SessionEngine {
|
|
|
2724
2607
|
signal: AbortSignal,
|
|
2725
2608
|
images?: Array<{ data: string; mimeType: string }>
|
|
2726
2609
|
): Promise<RunnerTurnRequest> {
|
|
2610
|
+
const agent = this.project.agent;
|
|
2727
2611
|
// Per-session cloud attach (channel/tool handoff) forces cloud runtime
|
|
2728
2612
|
// even when the agent defaults to local for chat server tools.
|
|
2729
2613
|
const runtime = resolveSessionRuntime({
|
|
@@ -2931,9 +2815,7 @@ export class SessionEngine {
|
|
|
2931
2815
|
? {}
|
|
2932
2816
|
: { sdkAgentId: record.sdkAgentId }),
|
|
2933
2817
|
workspaceDir: this.harnessCwd(record),
|
|
2934
|
-
sandbox: authoredRoot
|
|
2935
|
-
? false
|
|
2936
|
-
: this.project.agent.local?.sandbox === true,
|
|
2818
|
+
sandbox: authoredRoot ? false : agent.local?.sandbox === true,
|
|
2937
2819
|
...(runtime === "local" && harnessTools !== undefined
|
|
2938
2820
|
? {
|
|
2939
2821
|
...(harnessTools.tools === undefined
|
|
@@ -2966,13 +2848,7 @@ export class SessionEngine {
|
|
|
2966
2848
|
: {}),
|
|
2967
2849
|
customTools:
|
|
2968
2850
|
runtime === "local"
|
|
2969
|
-
? await this.buildCustomTools(
|
|
2970
|
-
record,
|
|
2971
|
-
agent,
|
|
2972
|
-
turnId,
|
|
2973
|
-
emit,
|
|
2974
|
-
synthesized
|
|
2975
|
-
)
|
|
2851
|
+
? await this.buildCustomTools(record, turnId, emit, synthesized)
|
|
2976
2852
|
: {},
|
|
2977
2853
|
mcpServers: this.buildMcpServers(
|
|
2978
2854
|
runtime,
|
|
@@ -3269,11 +3145,11 @@ export class SessionEngine {
|
|
|
3269
3145
|
|
|
3270
3146
|
private async buildCustomTools(
|
|
3271
3147
|
record: SessionRecord,
|
|
3272
|
-
agent: ResolvedAgent,
|
|
3273
3148
|
turnId: string,
|
|
3274
3149
|
emit: (payload: SessionEventPayload) => void,
|
|
3275
3150
|
extraTools: DiscoveredTool[] = []
|
|
3276
3151
|
): Promise<Record<string, SDKCustomTool>> {
|
|
3152
|
+
const agent = this.project.agent;
|
|
3277
3153
|
const tools: Record<string, SDKCustomTool> = {};
|
|
3278
3154
|
const register = (tool: ResolvedAgent["tools"][number]): void => {
|
|
3279
3155
|
tools[tool.name] = {
|
|
@@ -4796,14 +4672,6 @@ export class SessionEngine {
|
|
|
4796
4672
|
}
|
|
4797
4673
|
}
|
|
4798
4674
|
|
|
4799
|
-
if (this.abCollector.enabled) {
|
|
4800
|
-
await this.abCollector.onEvent(
|
|
4801
|
-
event,
|
|
4802
|
-
sessionCtx.session,
|
|
4803
|
-
this.project.name
|
|
4804
|
-
);
|
|
4805
|
-
}
|
|
4806
|
-
|
|
4807
4675
|
this.otel?.onEvent(event, sessionCtx.session);
|
|
4808
4676
|
}
|
|
4809
4677
|
|
|
@@ -5123,61 +4991,6 @@ export class SessionEngine {
|
|
|
5123
4991
|
});
|
|
5124
4992
|
}
|
|
5125
4993
|
|
|
5126
|
-
/**
|
|
5127
|
-
* Fold durable session streams into per-session A/B assignments and
|
|
5128
|
-
* aggregate arm metrics (`GET /v1/abs`). Collector-independent: always
|
|
5129
|
-
* reads `events.ndjson`.
|
|
5130
|
-
*/
|
|
5131
|
-
async abSnapshot(
|
|
5132
|
-
caller: AuthContext | null,
|
|
5133
|
-
options?: { includeAll?: boolean }
|
|
5134
|
-
): Promise<ABSnapshot> {
|
|
5135
|
-
const sessions = await this.listSessions(caller, options);
|
|
5136
|
-
const abConfig = this.project.abConfig;
|
|
5137
|
-
const maxPlaygroundSessions = resolveABMaxPlaygroundSessions(
|
|
5138
|
-
abConfig?.maxPlaygroundSessions
|
|
5139
|
-
);
|
|
5140
|
-
const foldedSessions = sessions.slice(0, maxPlaygroundSessions);
|
|
5141
|
-
// Backfill for a replacement host with nothing local to fold (e.g.
|
|
5142
|
-
// lazy-only restore before any session resumed): serve the persisted
|
|
5143
|
-
// aggregate instead of an empty surface. Gated on the host having no
|
|
5144
|
-
// sessions AT ALL — the persisted snapshot spans every principal, so a
|
|
5145
|
-
// caller who merely owns no sessions must not see it. Loaded once per
|
|
5146
|
-
// process (playground polls this route ~every 4s); skip the persist
|
|
5147
|
-
// side effect below — re-saving a restored snapshot would echo stale
|
|
5148
|
-
// data back into the store.
|
|
5149
|
-
if (
|
|
5150
|
-
foldedSessions.length === 0 &&
|
|
5151
|
-
this.storage !== undefined &&
|
|
5152
|
-
(await this.sessions.list()).length === 0
|
|
5153
|
-
) {
|
|
5154
|
-
this.restoredAbSnapshot ??= this.storage.getLatestAbSnapshot();
|
|
5155
|
-
const restoredSnapshot = await this.restoredAbSnapshot;
|
|
5156
|
-
if (restoredSnapshot !== undefined) {
|
|
5157
|
-
return restoredSnapshot;
|
|
5158
|
-
}
|
|
5159
|
-
}
|
|
5160
|
-
const abTable = this.project.storage?.abs;
|
|
5161
|
-
const snapshot = await buildABSnapshot({
|
|
5162
|
-
experiments: this.project.abs,
|
|
5163
|
-
agentName: this.project.name,
|
|
5164
|
-
sessions: foldedSessions,
|
|
5165
|
-
loadRecord: (sessionId) => this.sessions.get(sessionId),
|
|
5166
|
-
loadEvents: (sessionId) => this.listEvents(sessionId, 0),
|
|
5167
|
-
sessionInfo: (record) => this.sessionInfo(record),
|
|
5168
|
-
logger: this.logger,
|
|
5169
|
-
config: {
|
|
5170
|
-
maxPlaygroundSessions,
|
|
5171
|
-
durableSamples: abTable !== undefined,
|
|
5172
|
-
durableSnapshots: abTable?.putSnapshot !== undefined,
|
|
5173
|
-
},
|
|
5174
|
-
});
|
|
5175
|
-
// Side effect on the read path: playground polls GET /v1/abs ~every 4s;
|
|
5176
|
-
// the coordinator throttles the actual table write.
|
|
5177
|
-
this.storage?.abSnapshot(snapshot);
|
|
5178
|
-
return snapshot;
|
|
5179
|
-
}
|
|
5180
|
-
|
|
5181
4994
|
async eventStream(
|
|
5182
4995
|
sessionId: string,
|
|
5183
4996
|
startIndex = 0
|
|
@@ -5437,7 +5250,6 @@ export class SessionEngine {
|
|
|
5437
5250
|
asOf: record.asOf,
|
|
5438
5251
|
auth: record.auth,
|
|
5439
5252
|
continuationKey: record.continuationKey,
|
|
5440
|
-
...(record.abs === undefined ? {} : { abs: record.abs }),
|
|
5441
5253
|
...(record.title === undefined ? {} : { title: record.title }),
|
|
5442
5254
|
...(record.sdkAgentId === undefined
|
|
5443
5255
|
? {}
|
|
@@ -5539,9 +5351,9 @@ export class SessionEngine {
|
|
|
5539
5351
|
* serve start, before channels accept traffic: any persisted session
|
|
5540
5352
|
* missing from the local `--state-root` is materialized there — events
|
|
5541
5353
|
* as `events.ndjson`, record as `session.json` — after which every
|
|
5542
|
-
* existing read path (continuation lookup, event replay/streams
|
|
5543
|
-
*
|
|
5544
|
-
*
|
|
5354
|
+
* existing read path (continuation lookup, event replay/streams) works
|
|
5355
|
+
* unchanged. Local state always wins over the sink, so restarts on the
|
|
5356
|
+
* same host are no-ops.
|
|
5545
5357
|
*
|
|
5546
5358
|
* Failures are logged and skipped; a broken store (including rows that
|
|
5547
5359
|
* violate the SessionRecord shape) never blocks serve start.
|
|
@@ -11,19 +11,17 @@
|
|
|
11
11
|
* must never stall or fail a turn.
|
|
12
12
|
*
|
|
13
13
|
* Scaling shape: sessions reduce to keyed puts on the KV sink; eval runs
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* bounded, serialized queue.
|
|
14
|
+
* go to their dedicated `evals` table. Reminder documents live on the
|
|
15
|
+
* control plane. Everything shares one bounded, serialized queue.
|
|
17
16
|
*
|
|
18
17
|
* It does three unrelated jobs, declared separately as
|
|
19
18
|
* {@link FrameworkSessionStore}, {@link AuthorKvStore}, and
|
|
20
|
-
* {@link
|
|
19
|
+
* {@link EvalStore} — see `storage-roles.ts` for why they differ and where
|
|
21
20
|
* each is headed. The queue stays shared: it is one bounded, serialized chain
|
|
22
21
|
* per agent, and splitting it would change backpressure behavior, which this
|
|
23
22
|
* seam deliberately does not touch.
|
|
24
23
|
*/
|
|
25
24
|
|
|
26
|
-
import type { ABMetricSample } from "../ab.js";
|
|
27
25
|
import type { EvalRunSnapshot } from "../evals.js";
|
|
28
26
|
import {
|
|
29
27
|
type ResolvedStoragePolicy,
|
|
@@ -36,12 +34,11 @@ import {
|
|
|
36
34
|
} from "../storage.js";
|
|
37
35
|
import { isCursorHostedStorage } from "../storage-backends/cursor-hosted.js";
|
|
38
36
|
import type { JsonValue, SessionEvent, SessionRecord } from "../types.js";
|
|
39
|
-
import type { ABSnapshot } from "./ab-snapshot.js";
|
|
40
37
|
import { describeError } from "./describe-error.js";
|
|
41
38
|
import type { EvalRunStorage } from "./eval-run-store.js";
|
|
42
39
|
import type {
|
|
43
40
|
AuthorKvStore,
|
|
44
|
-
|
|
41
|
+
EvalStore,
|
|
45
42
|
FrameworkSessionStore,
|
|
46
43
|
} from "./storage-roles.js";
|
|
47
44
|
|
|
@@ -71,13 +68,6 @@ const CLOSE_DRAIN_TIMEOUT_MS = 10_000;
|
|
|
71
68
|
/** Debounced event batching flushes early past this many buffered events. */
|
|
72
69
|
const DEBOUNCE_MAX_BATCH = 200;
|
|
73
70
|
|
|
74
|
-
/**
|
|
75
|
-
* Aggregate A/B snapshots are refreshed at most this often — the
|
|
76
|
-
* playground polls `GET /v1/abs` every few seconds, and the snapshot is a
|
|
77
|
-
* convenience backfill, not a source of truth.
|
|
78
|
-
*/
|
|
79
|
-
const AB_SNAPSHOT_MIN_INTERVAL_MS = 60_000;
|
|
80
|
-
|
|
81
71
|
/** One queued sink call (KV put/delete or a dedicated-table write). */
|
|
82
72
|
interface StorageOp {
|
|
83
73
|
/** Human-readable op label for failure logs, e.g. `put({root}/...)`. */
|
|
@@ -114,7 +104,7 @@ function sessionRecordsOf(entries: readonly StorageEntry[]): SessionRecord[] {
|
|
|
114
104
|
}
|
|
115
105
|
|
|
116
106
|
export class StorageCoordinator
|
|
117
|
-
implements FrameworkSessionStore, AuthorKvStore,
|
|
107
|
+
implements FrameworkSessionStore, AuthorKvStore, EvalStore
|
|
118
108
|
{
|
|
119
109
|
readonly policy: ResolvedStoragePolicy;
|
|
120
110
|
|
|
@@ -136,7 +126,6 @@ export class StorageCoordinator
|
|
|
136
126
|
private pending = 0;
|
|
137
127
|
/** Ops dropped because the queue was full. */
|
|
138
128
|
private dropped = 0;
|
|
139
|
-
private lastAbSnapshotAt = 0;
|
|
140
129
|
private closed = false;
|
|
141
130
|
|
|
142
131
|
constructor(options: StorageCoordinatorOptions) {
|
|
@@ -559,66 +548,6 @@ export class StorageCoordinator
|
|
|
559
548
|
};
|
|
560
549
|
}
|
|
561
550
|
|
|
562
|
-
// ==========================================================================
|
|
563
|
-
// A/Bs (dedicated `abs` table)
|
|
564
|
-
// ==========================================================================
|
|
565
|
-
|
|
566
|
-
/** Append one metric sample to the `abs` table (no-op without it). */
|
|
567
|
-
abSample(sample: ABMetricSample): void {
|
|
568
|
-
const table = this.definition.abs;
|
|
569
|
-
if (this.closed || table === undefined) {
|
|
570
|
-
return;
|
|
571
|
-
}
|
|
572
|
-
this.enqueue(
|
|
573
|
-
[
|
|
574
|
-
{
|
|
575
|
-
label: `abs.putSample(${sample.sessionId})`,
|
|
576
|
-
run: (ctx) => table.putSample(sample, ctx),
|
|
577
|
-
},
|
|
578
|
-
],
|
|
579
|
-
"policy"
|
|
580
|
-
);
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
/**
|
|
584
|
-
* Refresh the persisted aggregate A/B snapshot, throttled to once per
|
|
585
|
-
* {@link AB_SNAPSHOT_MIN_INTERVAL_MS} (the playground recomputes the
|
|
586
|
-
* fold on every `GET /v1/abs` poll). No-op without `abs.putSnapshot`.
|
|
587
|
-
*/
|
|
588
|
-
abSnapshot(snapshot: ABSnapshot): void {
|
|
589
|
-
const putSnapshot = this.definition.abs?.putSnapshot;
|
|
590
|
-
const now = Date.now();
|
|
591
|
-
if (
|
|
592
|
-
this.closed ||
|
|
593
|
-
putSnapshot === undefined ||
|
|
594
|
-
now - this.lastAbSnapshotAt < AB_SNAPSHOT_MIN_INTERVAL_MS
|
|
595
|
-
) {
|
|
596
|
-
return;
|
|
597
|
-
}
|
|
598
|
-
this.lastAbSnapshotAt = now;
|
|
599
|
-
this.enqueue(
|
|
600
|
-
[{ label: "abs.putSnapshot", run: (ctx) => putSnapshot(snapshot, ctx) }],
|
|
601
|
-
"policy"
|
|
602
|
-
);
|
|
603
|
-
}
|
|
604
|
-
|
|
605
|
-
/** Latest persisted aggregate A/B snapshot; errors read as absent. */
|
|
606
|
-
async getLatestAbSnapshot(): Promise<ABSnapshot | undefined> {
|
|
607
|
-
const getSnapshot = this.definition.abs?.getSnapshot;
|
|
608
|
-
if (getSnapshot === undefined) {
|
|
609
|
-
return undefined;
|
|
610
|
-
}
|
|
611
|
-
try {
|
|
612
|
-
const value = await getSnapshot(this.context("restore"));
|
|
613
|
-
return value ?? undefined;
|
|
614
|
-
} catch (error) {
|
|
615
|
-
this.logger(
|
|
616
|
-
`[agent-sdk] storage abs.getSnapshot() failed: ${describeError(error)}`
|
|
617
|
-
);
|
|
618
|
-
return undefined;
|
|
619
|
-
}
|
|
620
|
-
}
|
|
621
|
-
|
|
622
551
|
// ==========================================================================
|
|
623
552
|
// Delivery
|
|
624
553
|
// ==========================================================================
|
|
@@ -14,18 +14,16 @@
|
|
|
14
14
|
* - {@link AuthorKvStore} is author state: whatever `ctx.host.kv` was handed.
|
|
15
15
|
* It converges onto the author file plane, which is a different destination
|
|
16
16
|
* from the one above.
|
|
17
|
-
* - {@link
|
|
18
|
-
*
|
|
17
|
+
* - {@link EvalStore} is playground eval bookkeeping with its own dedicated
|
|
18
|
+
* table, and follows neither.
|
|
19
19
|
*
|
|
20
20
|
* Consumers should depend on the narrowest role they use. That is what keeps a
|
|
21
21
|
* later change to framework persistence from silently reaching author KV, and
|
|
22
22
|
* it is why these are interfaces rather than a comment on one class.
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
|
-
import type { ABMetricSample } from "../ab.js";
|
|
26
25
|
import type { StorageContext } from "../storage.js";
|
|
27
26
|
import type { JsonValue, SessionEvent, SessionRecord } from "../types.js";
|
|
28
|
-
import type { ABSnapshot } from "./ab-snapshot.js";
|
|
29
27
|
import type { EvalRunStorage } from "./eval-run-store.js";
|
|
30
28
|
|
|
31
29
|
/**
|
|
@@ -84,10 +82,7 @@ export interface AuthorKvStore {
|
|
|
84
82
|
kvDelete(authorKey: string): Promise<void>;
|
|
85
83
|
}
|
|
86
84
|
|
|
87
|
-
/** Playground eval batches
|
|
88
|
-
export interface
|
|
85
|
+
/** Playground eval batches, on their own table. */
|
|
86
|
+
export interface EvalStore {
|
|
89
87
|
evalRuns(): EvalRunStorage | undefined;
|
|
90
|
-
abSample(sample: ABMetricSample): void;
|
|
91
|
-
abSnapshot(snapshot: ABSnapshot): void;
|
|
92
|
-
getLatestAbSnapshot(): Promise<ABSnapshot | undefined>;
|
|
93
88
|
}
|
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
* pagination. `list` / `listKeys` below drain every page, so the v1
|
|
26
26
|
* truncated-scan failure mode does not exist here.
|
|
27
27
|
*
|
|
28
|
-
* Eval runs
|
|
29
|
-
*
|
|
30
|
-
*
|
|
28
|
+
* Eval runs still ride the v1 storage proxy's dedicated table (`evals`
|
|
29
|
+
* below); moving them to factorydb is a separate follow-up from the KV
|
|
30
|
+
* cutover.
|
|
31
31
|
*
|
|
32
32
|
* This backend is platform-selected for architecture v2
|
|
33
33
|
* (framework-storage-selection.ts) — authors never import it; `agent/storage.ts`
|
|
@@ -35,7 +35,6 @@
|
|
|
35
35
|
*/
|
|
36
36
|
|
|
37
37
|
import type {
|
|
38
|
-
StorageABTable,
|
|
39
38
|
StorageCasTable,
|
|
40
39
|
StorageConfig,
|
|
41
40
|
StorageEntry,
|
|
@@ -85,7 +84,6 @@ type CursorHostedStorageV2Methods = Required<
|
|
|
85
84
|
readonly [CURSOR_HOSTED_STORAGE]: true;
|
|
86
85
|
cas: StorageCasTable;
|
|
87
86
|
evals: StorageEvalsTable;
|
|
88
|
-
abs: StorageABTable;
|
|
89
87
|
};
|
|
90
88
|
|
|
91
89
|
function toCasResult(response: KvV2PutResponse): KvCasResult {
|
|
@@ -149,7 +147,7 @@ async function listAllPages(
|
|
|
149
147
|
export function cursorHostedStorageV2(
|
|
150
148
|
options: CursorHostedStorageOptions = {}
|
|
151
149
|
): CursorHostedStorageV2Methods {
|
|
152
|
-
// Eval runs
|
|
150
|
+
// Eval runs stay on the v1 proxy's dedicated table.
|
|
153
151
|
const v1 = cursorHostedStorage(options);
|
|
154
152
|
return {
|
|
155
153
|
[CURSOR_HOSTED_STORAGE]: true,
|
|
@@ -214,6 +212,5 @@ export function cursorHostedStorageV2(
|
|
|
214
212
|
},
|
|
215
213
|
},
|
|
216
214
|
evals: v1.evals,
|
|
217
|
-
abs: v1.abs,
|
|
218
215
|
};
|
|
219
216
|
}
|
|
@@ -22,11 +22,9 @@
|
|
|
22
22
|
* ```
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
|
-
import type { ABSnapshot } from "../ab.js";
|
|
26
25
|
import type { EvalRunSnapshot } from "../evals.js";
|
|
27
26
|
import { injectActiveTraceContext } from "../otel.js";
|
|
28
27
|
import type {
|
|
29
|
-
StorageABTable,
|
|
30
28
|
StorageCasTable,
|
|
31
29
|
StorageConfig,
|
|
32
30
|
StorageEntry,
|
|
@@ -114,7 +112,6 @@ type CursorHostedStorageMethods = Required<
|
|
|
114
112
|
readonly [CURSOR_HOSTED_STORAGE]: true;
|
|
115
113
|
cas: StorageCasTable;
|
|
116
114
|
evals: StorageEvalsTable;
|
|
117
|
-
abs: StorageABTable;
|
|
118
115
|
};
|
|
119
116
|
|
|
120
117
|
// ============================================================================
|
|
@@ -417,39 +414,5 @@ export function cursorHostedStorage(
|
|
|
417
414
|
return result.runs;
|
|
418
415
|
},
|
|
419
416
|
},
|
|
420
|
-
abs: {
|
|
421
|
-
async putSample(sample, ctx): Promise<void> {
|
|
422
|
-
await storageRpc(
|
|
423
|
-
options,
|
|
424
|
-
"/internal/agent-serve/storage/abs/put-sample",
|
|
425
|
-
{
|
|
426
|
-
agentName: ctx.agentName,
|
|
427
|
-
sample,
|
|
428
|
-
}
|
|
429
|
-
);
|
|
430
|
-
},
|
|
431
|
-
async putSnapshot(snapshot, ctx): Promise<void> {
|
|
432
|
-
await storageRpc(
|
|
433
|
-
options,
|
|
434
|
-
"/internal/agent-serve/storage/abs/put-snapshot",
|
|
435
|
-
{
|
|
436
|
-
agentName: ctx.agentName,
|
|
437
|
-
snapshot,
|
|
438
|
-
}
|
|
439
|
-
);
|
|
440
|
-
},
|
|
441
|
-
async getSnapshot(ctx): Promise<ABSnapshot | undefined> {
|
|
442
|
-
const result = await storageRpc<{
|
|
443
|
-
found: boolean;
|
|
444
|
-
snapshot: ABSnapshot | null;
|
|
445
|
-
}>(options, "/internal/agent-serve/storage/abs/get-snapshot", {
|
|
446
|
-
agentName: ctx.agentName,
|
|
447
|
-
});
|
|
448
|
-
if (!result.found) {
|
|
449
|
-
return undefined;
|
|
450
|
-
}
|
|
451
|
-
return result.snapshot ?? undefined;
|
|
452
|
-
},
|
|
453
|
-
},
|
|
454
417
|
};
|
|
455
418
|
}
|