@cursor/july 0.1.107 → 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 +13 -11
- package/dist/bin/agent-serve.js +30 -8
- 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/github/github-channel.js +8 -5
- package/dist/channels/github/types.d.ts +5 -1
- package/dist/channels/github/types.d.ts.map +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/origin/origin-channel.d.ts.map +1 -1
- package/dist/channels/origin/origin-channel.js +27 -13
- package/dist/channels/origin/types.d.ts +5 -1
- package/dist/channels/origin/types.d.ts.map +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/channels.d.ts +45 -0
- package/dist/channels.d.ts.map +1 -1
- package/dist/channels.js +106 -7
- package/dist/connections.d.ts +2 -1
- package/dist/connections.d.ts.map +1 -1
- package/dist/connections.js +2 -1
- package/dist/docs/404.html +2 -2
- package/dist/docs/assets/{app.CtuckIiL.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.Bkkhnu8K.js → VPLocalSearchBox.CVQERt56.js} +1 -1
- package/dist/docs/assets/chunks/{theme.DhpIe0Pa.js → theme.Dnsd3XOn.js} +2 -2
- package/dist/docs/assets/concepts.md.B4o63Gul.js +1 -0
- package/dist/docs/assets/{deployment.md.MFPKqsqI.js → deployment.md.JenwuCCB.js} +4 -4
- package/dist/docs/assets/{deployment.md.MFPKqsqI.lean.js → deployment.md.JenwuCCB.lean.js} +1 -1
- 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_cloud-agents.md.BsloyHdY.js +9 -0
- package/dist/docs/assets/{guides_cloud-agents.md.DS8RIjwx.lean.js → guides_cloud-agents.md.BsloyHdY.lean.js} +1 -1
- package/dist/docs/assets/{guides_github.md.c0gdGJ-D.js → guides_github.md.TZaTZlfz.js} +13 -3
- package/dist/docs/assets/{guides_github.md.c0gdGJ-D.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_grokbot-agents.md.DVqdhBKb.js → guides_grokbot-agents.md.DyV-WArv.js} +1 -1
- package/dist/docs/assets/guides_improve.md.BGVk32bK.js +14 -0
- package/dist/docs/assets/guides_improve.md.BGVk32bK.lean.js +1 -0
- package/dist/docs/assets/{guides_slack.md.9oHPye9o.js → guides_slack.md.D4RVMM4G.js} +3 -3
- package/dist/docs/assets/{guides_slack.md.9oHPye9o.lean.js → guides_slack.md.D4RVMM4G.lean.js} +1 -1
- 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.BW_6tOgR.lean.js → index.md.DD9Q2XuJ.lean.js} +1 -1
- package/dist/docs/assets/{reference_agent-config.md.CHNpiyp4.js → reference_agent-config.md.CvoL6pof.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.Dm67hd2D.js → reference_cli.md.Deg7849l.js} +7 -7
- package/dist/docs/assets/{reference_cli.md.Dm67hd2D.lean.js → reference_cli.md.Deg7849l.lean.js} +1 -1
- package/dist/docs/assets/{reference_connections.md.Di6jJAXF.js → reference_connections.md.BojkC6c5.js} +1 -1
- package/dist/docs/assets/{reference_extensions.md.CGmMLblt.js → reference_extensions.md.ZAVUyuEX.js} +3 -3
- 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/{scaffolding-agents.md.em43xlY1.js → scaffolding-agents.md.Kctn3OVb.js} +1 -1
- package/dist/docs/assets/{skills_create-agent.md.BVoWPcan.js → skills_create-agent.md.Q3h6Je-e.js} +1 -1
- package/dist/docs/assets/{skills_debug.md.CDbPhHfg.js → skills_debug.md.CVjCXMFF.js} +1 -1
- package/dist/docs/assets/{skills_debug.md.CDbPhHfg.lean.js → skills_debug.md.CVjCXMFF.lean.js} +1 -1
- 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.DFxYPErF.js +25 -0
- package/dist/docs/assets/skills_evals.md.DFxYPErF.lean.js +1 -0
- package/dist/docs/assets/skills_framework-map.md.BxLSOhSY.js +1 -0
- package/dist/docs/assets/{skills_framework-map.md.haibFyoB.lean.js → skills_framework-map.md.BxLSOhSY.lean.js} +1 -1
- package/dist/docs/assets/{skills_github.md.D0JahM8c.js → skills_github.md.hgFX_oKY.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/assets/troubleshooting.md.CYEAO9bM.js +1 -0
- 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 +7 -7
- package/dist/docs/deployment.md +7 -2
- package/dist/docs/evals.html +161 -35
- package/dist/docs/evals.md +612 -296
- 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 +6 -6
- package/dist/docs/guides/cloud-agents.md +4 -3
- package/dist/docs/guides/convert-automation.html +4 -4
- package/dist/docs/guides/github.html +17 -7
- package/dist/docs/guides/github.md +33 -1
- package/dist/docs/guides/gitlab.html +40 -0
- package/dist/docs/guides/gitlab.md +92 -0
- package/dist/docs/guides/grokbot-agents.html +6 -6
- package/dist/docs/guides/grokbot-agents.md +2 -2
- package/dist/docs/guides/human-in-the-loop.html +4 -4
- package/dist/docs/guides/improve.html +40 -0
- package/dist/docs/guides/improve.md +91 -0
- package/dist/docs/guides/mcp-oauth.html +4 -4
- package/dist/docs/guides/opentelemetry.html +5 -5
- package/dist/docs/guides/slack.html +7 -7
- package/dist/docs/guides/slack.md +2 -1
- 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 +14 -6
- package/dist/docs/llms-full.txt +1274 -814
- package/dist/docs/llms.txt +7 -5
- package/dist/docs/quickstart.html +4 -4
- package/dist/docs/reference/agent-config.html +6 -6
- package/dist/docs/reference/agent-config.md +5 -2
- 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 +11 -11
- package/dist/docs/reference/cli.md +24 -15
- package/dist/docs/reference/connections.html +6 -6
- package/dist/docs/reference/connections.md +2 -1
- package/dist/docs/reference/extensions.html +8 -8
- package/dist/docs/reference/extensions.md +2 -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 +5 -5
- package/dist/docs/scaffolding-agents.md +2 -1
- package/dist/docs/skills/create-agent.html +6 -6
- package/dist/docs/skills/create-agent.md +1 -1
- package/dist/docs/skills/debug.html +5 -5
- package/dist/docs/skills/debug.md +1 -1
- 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 +5 -4
- package/dist/docs/skills/github.html +6 -6
- package/dist/docs/skills/github.md +1 -1
- 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 +5 -5
- package/dist/docs/troubleshooting.md +1 -1
- package/dist/extensions/improve/extension.d.ts +46 -0
- package/dist/extensions/improve/extension.d.ts.map +1 -0
- package/dist/extensions/improve/extension.js +41 -0
- package/dist/extensions/improve/skills/yourself.d.ts +4 -0
- package/dist/extensions/improve/skills/yourself.d.ts.map +1 -0
- package/dist/extensions/improve/skills/yourself.js +43 -0
- 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/builtin-tools/artifacts.d.ts.map +1 -1
- package/dist/internal/builtin-tools/artifacts.js +2 -3
- package/dist/internal/channel-route-dispatch.d.ts +13 -0
- package/dist/internal/channel-route-dispatch.d.ts.map +1 -0
- package/dist/internal/channel-route-dispatch.js +62 -0
- package/dist/internal/channel-state.d.ts +17 -0
- package/dist/internal/channel-state.d.ts.map +1 -0
- package/dist/internal/channel-state.js +78 -0
- package/dist/internal/cli-ax.d.ts +8 -2
- package/dist/internal/cli-ax.d.ts.map +1 -1
- package/dist/internal/cli-ax.js +100 -3
- package/dist/internal/cli-cursor.d.ts.map +1 -1
- package/dist/internal/cli-cursor.js +2 -0
- package/dist/internal/cli-deploy.d.ts.map +1 -1
- package/dist/internal/cli-deploy.js +38 -14
- package/dist/internal/cli-mcp-oauth.d.ts.map +1 -1
- package/dist/internal/cli-mcp-oauth.js +15 -0
- package/dist/internal/cli-mcp.d.ts.map +1 -1
- package/dist/internal/cli-mcp.js +12 -0
- package/dist/internal/cli-slack.d.ts.map +1 -1
- package/dist/internal/cli-slack.js +8 -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/cursor/credentials.d.ts +8 -2
- package/dist/internal/cursor/credentials.d.ts.map +1 -1
- package/dist/internal/cursor/credentials.js +27 -5
- package/dist/internal/deploy-client.d.ts +27 -0
- package/dist/internal/deploy-client.d.ts.map +1 -1
- package/dist/internal/deploy-client.js +32 -0
- package/dist/internal/deploy-manifest.d.ts +23 -0
- package/dist/internal/deploy-manifest.d.ts.map +1 -1
- package/dist/internal/deploy-manifest.js +84 -1
- package/dist/internal/describe-error.d.ts +1 -0
- package/dist/internal/describe-error.d.ts.map +1 -1
- package/dist/internal/describe-error.js +25 -0
- 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/guest-network.d.ts +4 -10
- package/dist/internal/guest-network.d.ts.map +1 -1
- package/dist/internal/guest-network.js +42 -26
- package/dist/internal/hosted-admission-adapter.d.ts +2 -0
- package/dist/internal/hosted-admission-adapter.d.ts.map +1 -1
- package/dist/internal/hosted-catch-protocol.d.ts +51 -0
- package/dist/internal/hosted-catch-protocol.d.ts.map +1 -0
- package/dist/internal/hosted-catch-protocol.js +103 -0
- package/dist/internal/hosted-catch.d.ts +40 -0
- package/dist/internal/hosted-catch.d.ts.map +1 -0
- package/dist/internal/hosted-catch.js +149 -0
- package/dist/internal/hosted-delivery-protocol.d.ts +41 -0
- package/dist/internal/hosted-delivery-protocol.d.ts.map +1 -1
- package/dist/internal/hosted-delivery-protocol.js +249 -0
- package/dist/internal/hosted-delivery.d.ts +10 -1
- package/dist/internal/hosted-delivery.d.ts.map +1 -1
- package/dist/internal/hosted-delivery.js +100 -22
- package/dist/internal/hosted-execution-diag.d.ts +4 -1
- package/dist/internal/hosted-execution-diag.d.ts.map +1 -1
- package/dist/internal/hosted-execution-diag.js +13 -4
- package/dist/internal/hosted-execution-flush.d.ts +3 -0
- package/dist/internal/hosted-execution-flush.d.ts.map +1 -1
- package/dist/internal/hosted-execution-flush.js +2 -4
- package/dist/internal/http-control-plane-session.d.ts +30 -0
- package/dist/internal/http-control-plane-session.d.ts.map +1 -0
- package/dist/internal/http-control-plane-session.js +83 -0
- 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/legacy-command-guard.d.ts +22 -0
- package/dist/internal/legacy-command-guard.d.ts.map +1 -0
- package/dist/internal/legacy-command-guard.js +51 -0
- package/dist/internal/platform-timers.d.ts +7 -0
- package/dist/internal/platform-timers.d.ts.map +1 -1
- package/dist/internal/platform-timers.js +139 -0
- package/dist/internal/reminder-control-plane-protocol.d.ts +2 -0
- package/dist/internal/reminder-control-plane-protocol.d.ts.map +1 -1
- package/dist/internal/reminder-control-plane-protocol.js +9 -2
- package/dist/internal/reminder-runner.d.ts +8 -0
- package/dist/internal/reminder-runner.d.ts.map +1 -1
- package/dist/internal/reminder-runner.js +36 -9
- package/dist/internal/resolve-prod-target.d.ts +2 -0
- package/dist/internal/resolve-prod-target.d.ts.map +1 -1
- package/dist/internal/resolve-prod-target.js +13 -0
- package/dist/internal/run-client.d.ts +1 -1
- package/dist/internal/sdk-runner.d.ts.map +1 -1
- package/dist/internal/sdk-runner.js +5 -4
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +57 -70
- package/dist/internal/session-engine.d.ts +7 -41
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +110 -227
- 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 +7 -2
- package/dist/storage-backends/cursor-hosted.d.ts.map +1 -1
- package/dist/storage-backends/cursor-hosted.js +29 -31
- 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 +53 -62
- package/dist/types.d.ts.map +1 -1
- package/docs/README.md +14 -6
- package/docs/building-with-agents.md +3 -2
- package/docs/concepts.md +2 -4
- package/docs/deployment.md +7 -2
- package/docs/evals.md +613 -297
- package/docs/guides/bitbucket.md +89 -0
- package/docs/guides/cloud-agents.md +4 -3
- package/docs/guides/github.md +33 -1
- package/docs/guides/gitlab.md +97 -0
- package/docs/guides/grokbot-agents.md +2 -2
- package/docs/guides/improve.md +96 -0
- package/docs/guides/slack.md +2 -1
- package/docs/guides/webhooks.md +4 -2
- package/docs/hillclimbing.md +2 -2
- package/docs/reference/agent-config.md +5 -2
- package/docs/reference/channels.md +16 -3
- package/docs/reference/cli.md +24 -15
- package/docs/reference/connections.md +2 -1
- package/docs/reference/extensions.md +2 -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/scaffolding-agents.md +2 -1
- package/docs/skills/index.md +2 -2
- package/docs/storage.md +15 -24
- package/docs/troubleshooting.md +1 -1
- package/package.json +8 -7
- package/skills/create-agent/SKILL.md +1 -1
- package/skills/debug/SKILL.md +1 -1
- package/skills/deploy/SKILL.md +169 -0
- package/skills/evals/SKILL.md +45 -8
- package/skills/framework-map/SKILL.md +5 -4
- package/skills/github/SKILL.md +1 -1
- package/src/bin/agent-serve.ts +27 -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/github/github-channel.ts +8 -8
- package/src/channels/github/types.ts +5 -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/origin/origin-channel.ts +29 -13
- package/src/channels/origin/types.ts +5 -0
- package/src/channels/slack/dispatch.ts +30 -0
- package/src/channels/slack/slack-channel.ts +69 -7
- package/src/channels.ts +157 -10
- package/src/connections.ts +2 -1
- package/src/extensions/improve/extension.ts +70 -0
- package/src/extensions/improve/skills/yourself.ts +50 -0
- 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/builtin-tools/artifacts.ts +2 -3
- package/src/internal/channel-route-dispatch.ts +66 -0
- package/src/internal/channel-state.ts +96 -0
- package/src/internal/cli-ax.ts +111 -3
- package/src/internal/cli-cursor.ts +4 -1
- package/src/internal/cli-deploy.ts +50 -10
- package/src/internal/cli-mcp-oauth.ts +18 -0
- package/src/internal/cli-mcp.ts +11 -0
- package/src/internal/cli-slack.ts +15 -2
- package/src/internal/continuation-channel.ts +2 -1
- package/src/internal/continuation-identity.ts +10 -2
- package/src/internal/cursor/credentials.ts +35 -7
- package/src/internal/deploy-client.ts +54 -0
- package/src/internal/deploy-manifest.ts +115 -1
- package/src/internal/describe-error.ts +28 -0
- 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/guest-network.ts +43 -29
- package/src/internal/hosted-admission-adapter.ts +2 -0
- package/src/internal/hosted-catch-protocol.ts +130 -0
- package/src/internal/hosted-catch.ts +192 -0
- package/src/internal/hosted-delivery-protocol.ts +387 -0
- package/src/internal/hosted-delivery.ts +155 -22
- package/src/internal/hosted-execution-diag.ts +21 -3
- package/src/internal/hosted-execution-flush.ts +6 -3
- package/src/internal/http-control-plane-session.ts +104 -0
- package/src/internal/init-scaffold.ts +1 -2
- package/src/internal/install-cursor-skills.ts +38 -5
- package/src/internal/legacy-command-guard.ts +59 -0
- package/src/internal/platform-timers.ts +191 -0
- package/src/internal/reminder-control-plane-protocol.ts +15 -2
- package/src/internal/reminder-runner.ts +60 -9
- package/src/internal/resolve-prod-target.ts +15 -0
- package/src/internal/run-client.ts +1 -1
- package/src/internal/sdk-runner.ts +3 -2
- package/src/internal/server.ts +89 -95
- package/src/internal/session-engine.ts +155 -285
- 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 +40 -38
- 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 +58 -62
- 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.DXXZxiMv.js +0 -1
- package/dist/docs/assets/concepts.md.DgEcZOfT.js +0 -1
- package/dist/docs/assets/evals.md.CbMoebP1.js +0 -85
- package/dist/docs/assets/evals.md.CbMoebP1.lean.js +0 -1
- package/dist/docs/assets/guides_cloud-agents.md.DS8RIjwx.js +0 -9
- package/dist/docs/assets/index.md.BW_6tOgR.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.723kpUmA.js +0 -25
- package/dist/docs/assets/skills_evals.md.723kpUmA.lean.js +0 -1
- package/dist/docs/assets/skills_framework-map.md.haibFyoB.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/assets/troubleshooting.md.Cus_YZga.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-Bq2HpEQB.js +0 -67
- package/dist/playground/assets/index-CZKKNlmb.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_grokbot-agents.md.DVqdhBKb.lean.js → guides_grokbot-agents.md.DyV-WArv.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_agent-config.md.CHNpiyp4.lean.js → reference_agent-config.md.CvoL6pof.lean.js} +0 -0
- /package/dist/docs/assets/{reference_connections.md.Di6jJAXF.lean.js → reference_connections.md.BojkC6c5.lean.js} +0 -0
- /package/dist/docs/assets/{reference_extensions.md.CGmMLblt.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/{scaffolding-agents.md.em43xlY1.lean.js → scaffolding-agents.md.Kctn3OVb.lean.js} +0 -0
- /package/dist/docs/assets/{skills_create-agent.md.BVoWPcan.lean.js → skills_create-agent.md.Q3h6Je-e.lean.js} +0 -0
- /package/dist/docs/assets/{skills_github.md.D0JahM8c.lean.js → skills_github.md.hgFX_oKY.lean.js} +0 -0
- /package/dist/docs/assets/{troubleshooting.md.Cus_YZga.lean.js → troubleshooting.md.CYEAO9bM.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,
|
|
@@ -114,6 +105,10 @@ import {
|
|
|
114
105
|
sessionClock,
|
|
115
106
|
} from "./as-of.js";
|
|
116
107
|
import { SessionAuthError, samePrincipal } from "./auth.js";
|
|
108
|
+
import {
|
|
109
|
+
mergeChannelStateMutation,
|
|
110
|
+
mergeChannelStateSkipNull,
|
|
111
|
+
} from "./channel-state.js";
|
|
117
112
|
import { mergeCloudOptions, resolveSessionRuntime } from "./cloud-merge.js";
|
|
118
113
|
import {
|
|
119
114
|
applyCloudUsageToEvents,
|
|
@@ -132,7 +127,7 @@ import {
|
|
|
132
127
|
resolveV2Key,
|
|
133
128
|
V2EngineError,
|
|
134
129
|
} from "./continuation-identity.js";
|
|
135
|
-
import { describeError } from "./describe-error.js";
|
|
130
|
+
import { describeError, describeErrorCode } from "./describe-error.js";
|
|
136
131
|
import { isDevMode } from "./dev-mode.js";
|
|
137
132
|
import { type EventLogMemoryStats, EventLogStore } from "./event-log.js";
|
|
138
133
|
import { TurnEventMapper } from "./event-mapper.js";
|
|
@@ -160,6 +155,7 @@ import {
|
|
|
160
155
|
HostedAdmissionLocalSendError,
|
|
161
156
|
isDuringHostedAdmission,
|
|
162
157
|
} from "./hosted-admission-context.js";
|
|
158
|
+
import { hostedSessionResumeKey } from "./hosted-catch-protocol.js";
|
|
163
159
|
import {
|
|
164
160
|
formatContinuationToken,
|
|
165
161
|
newContinuationKey,
|
|
@@ -217,11 +213,17 @@ import {
|
|
|
217
213
|
} from "./workspace-sync.js";
|
|
218
214
|
|
|
219
215
|
export const HTTP_CHANNEL_ID = "http";
|
|
216
|
+
export { mergeChannelStateSkipNull } from "./channel-state.js";
|
|
220
217
|
export { SCHEDULE_CHANNEL_PREFIX } from "./prompt-context.js";
|
|
221
218
|
|
|
222
219
|
/** Authored surfaces mirrored onto the Agent Store before a first cloud prompt. */
|
|
223
220
|
type CloudSyncSurface = "skills" | "workspace";
|
|
224
221
|
|
|
222
|
+
interface EventDispatchContext {
|
|
223
|
+
channelState: JsonValue;
|
|
224
|
+
session: SessionInfo;
|
|
225
|
+
}
|
|
226
|
+
|
|
225
227
|
/** The Agent Store cloud turns read authored files from, and where the VM mounts it. */
|
|
226
228
|
interface CloudStoreTarget {
|
|
227
229
|
sink: FileSink;
|
|
@@ -444,8 +446,8 @@ export class SessionEngine {
|
|
|
444
446
|
/**
|
|
445
447
|
* Runtime for `agent/storage.ts` (`defineStorage`), when
|
|
446
448
|
* authored. All durable state changes funnel through it (session
|
|
447
|
-
* records, event chunks
|
|
448
|
-
*
|
|
449
|
+
* records, event chunks); the eval run store attaches via
|
|
450
|
+
* {@link StorageCoordinator.evalRuns} at serve start.
|
|
449
451
|
*/
|
|
450
452
|
readonly storage: StorageCoordinator | undefined;
|
|
451
453
|
/** In-flight lazy restores, deduped per channel + continuation key. */
|
|
@@ -453,8 +455,6 @@ export class SessionEngine {
|
|
|
453
455
|
string,
|
|
454
456
|
Promise<SessionRecord | undefined>
|
|
455
457
|
>();
|
|
456
|
-
/** Once-per-process cache for the A/B snapshot backfill (see abSnapshot). */
|
|
457
|
-
private restoredAbSnapshot: Promise<ABSnapshot | undefined> | undefined;
|
|
458
458
|
/** In-flight authored files → Agent Store syncs (see syncToCloudStore). */
|
|
459
459
|
private readonly cloudSyncs = new Map<CloudSyncSurface, Promise<boolean>>();
|
|
460
460
|
|
|
@@ -517,7 +517,6 @@ export class SessionEngine {
|
|
|
517
517
|
private probeCursorAccount:
|
|
518
518
|
| ((connection: string) => Promise<string | undefined>)
|
|
519
519
|
| undefined;
|
|
520
|
-
private readonly abCollector: ABCollector;
|
|
521
520
|
private readonly otel: OtelCollector | undefined;
|
|
522
521
|
private readonly otelHost: HostOtelSessionApi;
|
|
523
522
|
private readonly stopMemoryTelemetry: (() => void) | undefined;
|
|
@@ -628,13 +627,6 @@ export class SessionEngine {
|
|
|
628
627
|
config: options.project.artifacts,
|
|
629
628
|
sink: managedV2Files?.(),
|
|
630
629
|
});
|
|
631
|
-
this.abCollector = new ABCollector(
|
|
632
|
-
options.project.abs,
|
|
633
|
-
this.logger,
|
|
634
|
-
async (sessionId) => (await this.logs.get(sessionId)).snapshot(0),
|
|
635
|
-
// Samples flow to the defineStorage `abs` table (no-op without one).
|
|
636
|
-
{ persistSample: (sample) => this.storage?.abSample(sample) }
|
|
637
|
-
);
|
|
638
630
|
// Peer and Cursor-account transports are symbolic until the serve host
|
|
639
631
|
// resolves them; the host-side MCP registry starts with the concrete
|
|
640
632
|
// connections and gains the rest via setResolvedConnections.
|
|
@@ -1019,6 +1011,18 @@ export class SessionEngine {
|
|
|
1019
1011
|
sendOptions.continuationToken
|
|
1020
1012
|
);
|
|
1021
1013
|
}
|
|
1014
|
+
if (
|
|
1015
|
+
existing === undefined &&
|
|
1016
|
+
sendOptions.hostedSessionId !== undefined &&
|
|
1017
|
+
sendOptions.mailboxContinuation?.key ===
|
|
1018
|
+
hostedSessionResumeKey(sendOptions.hostedSessionId)
|
|
1019
|
+
) {
|
|
1020
|
+
// Explicit control-plane resume of an existing session: the CP named
|
|
1021
|
+
// the session by its own id and stamped the matching resume key. The
|
|
1022
|
+
// session keeps its original continuation key (a PR lane must stay
|
|
1023
|
+
// addressable by its webhooks); this is a follow-up turn by id.
|
|
1024
|
+
existing = await this.getOrRestoreSession(sendOptions.hostedSessionId);
|
|
1025
|
+
}
|
|
1022
1026
|
|
|
1023
1027
|
if (existing !== undefined) {
|
|
1024
1028
|
if (
|
|
@@ -1115,7 +1119,7 @@ export class SessionEngine {
|
|
|
1115
1119
|
const purpose = sendOptions.purpose === "eval" ? "eval" : "live";
|
|
1116
1120
|
const frozenAsOf = normalizeAsOf(sendOptions.asOf);
|
|
1117
1121
|
assertTimeArgs(this.project.agent.tools, frozenAsOf);
|
|
1118
|
-
|
|
1122
|
+
const record: SessionRecord = {
|
|
1119
1123
|
sessionId: sendOptions.hostedSessionId ?? newSessionId(),
|
|
1120
1124
|
channelId,
|
|
1121
1125
|
mode: sendOptions.mode ?? "chat",
|
|
@@ -1144,7 +1148,6 @@ export class SessionEngine {
|
|
|
1144
1148
|
dryRun: record.dryRun === true ? true : undefined,
|
|
1145
1149
|
},
|
|
1146
1150
|
});
|
|
1147
|
-
record = await this.enrollABs(record);
|
|
1148
1151
|
const since = (await this.logs.get(record.sessionId)).count;
|
|
1149
1152
|
await this.startTurn(record.sessionId, message, {
|
|
1150
1153
|
admission: sendOptions.admission ?? "preempt",
|
|
@@ -1218,97 +1221,6 @@ export class SessionEngine {
|
|
|
1218
1221
|
return existing !== undefined;
|
|
1219
1222
|
}
|
|
1220
1223
|
|
|
1221
|
-
/**
|
|
1222
|
-
* Sticky A/B enrollment at session creation — before the first turn, so
|
|
1223
|
-
* variants are in the durable stream (and on {@link SessionRecord.abs})
|
|
1224
|
-
* ahead of model/instructions work. Failures persist as `variant: null`
|
|
1225
|
-
* (sticky skip). Eval harness sessions (`purpose: "eval"`) are never
|
|
1226
|
-
* enrolled.
|
|
1227
|
-
*/
|
|
1228
|
-
private async enrollABs(record: SessionRecord): Promise<SessionRecord> {
|
|
1229
|
-
if (!this.abCollector.enabled || record.purpose === "eval") {
|
|
1230
|
-
return record;
|
|
1231
|
-
}
|
|
1232
|
-
const sessionInfo = this.sessionInfo(record);
|
|
1233
|
-
const abs: Record<string, string | null> = {};
|
|
1234
|
-
for (const experiment of this.project.abs) {
|
|
1235
|
-
const def = experiment.definition as ABDefinition;
|
|
1236
|
-
const variantKeys = Object.keys(def.variants);
|
|
1237
|
-
let variant: string | null = null;
|
|
1238
|
-
try {
|
|
1239
|
-
variant = await resolveABSplit(def.split, {
|
|
1240
|
-
agent: { name: this.project.name },
|
|
1241
|
-
channel: { id: record.channelId },
|
|
1242
|
-
session: sessionInfo,
|
|
1243
|
-
experiment: experiment.name,
|
|
1244
|
-
variants: variantKeys,
|
|
1245
|
-
});
|
|
1246
|
-
if (variant !== null && !(variant in def.variants)) {
|
|
1247
|
-
throw new Error(
|
|
1248
|
-
`split resolved to ${JSON.stringify(variant)}; expected one of ${variantKeys.join(", ")} or null to skip`
|
|
1249
|
-
);
|
|
1250
|
-
}
|
|
1251
|
-
} catch (error) {
|
|
1252
|
-
this.logger(
|
|
1253
|
-
`[agent-sdk] ab "${experiment.name}" enrollment failed (sticky skip): ${describeError(error)}`
|
|
1254
|
-
);
|
|
1255
|
-
variant = null;
|
|
1256
|
-
}
|
|
1257
|
-
abs[experiment.name] = variant;
|
|
1258
|
-
await this.appendEvent(record.sessionId, {
|
|
1259
|
-
type: "ab.assigned",
|
|
1260
|
-
data: { experiment: experiment.name, variant },
|
|
1261
|
-
});
|
|
1262
|
-
}
|
|
1263
|
-
return this.updateRecord(record.sessionId, (current) => ({
|
|
1264
|
-
...current,
|
|
1265
|
-
abs,
|
|
1266
|
-
}));
|
|
1267
|
-
}
|
|
1268
|
-
|
|
1269
|
-
/**
|
|
1270
|
-
* Ensure {@link SessionRecord.abs} is populated (hydrate from the durable
|
|
1271
|
-
* `ab.assigned` stream when missing — e.g. older sessions after upgrade).
|
|
1272
|
-
*/
|
|
1273
|
-
private async ensureAbs(record: SessionRecord): Promise<SessionRecord> {
|
|
1274
|
-
if (record.abs !== undefined || record.purpose === "eval") {
|
|
1275
|
-
return record;
|
|
1276
|
-
}
|
|
1277
|
-
if (!this.abCollector.enabled) {
|
|
1278
|
-
return record;
|
|
1279
|
-
}
|
|
1280
|
-
const events = await this.listEvents(record.sessionId, 0);
|
|
1281
|
-
const folded = foldABStream(events);
|
|
1282
|
-
if (folded.arms.size === 0) {
|
|
1283
|
-
return record;
|
|
1284
|
-
}
|
|
1285
|
-
const abs = Object.fromEntries(folded.arms);
|
|
1286
|
-
return this.updateRecord(record.sessionId, (current) => ({
|
|
1287
|
-
...current,
|
|
1288
|
-
abs,
|
|
1289
|
-
}));
|
|
1290
|
-
}
|
|
1291
|
-
|
|
1292
|
-
/**
|
|
1293
|
-
* Agent config for this session: base project agent plus any per-variant
|
|
1294
|
-
* `instructions` overlays from enrolled A/B arms.
|
|
1295
|
-
*/
|
|
1296
|
-
private agentForSession(record: SessionRecord): ResolvedAgent {
|
|
1297
|
-
const base = this.project.agent;
|
|
1298
|
-
const instructions = mergeABInstructions(
|
|
1299
|
-
base.instructions,
|
|
1300
|
-
record.abs,
|
|
1301
|
-
this.project.abs.map((experiment) => ({
|
|
1302
|
-
name: experiment.name,
|
|
1303
|
-
definition: experiment.definition as ABDefinition,
|
|
1304
|
-
}))
|
|
1305
|
-
);
|
|
1306
|
-
if (instructions === base.instructions) {
|
|
1307
|
-
return base;
|
|
1308
|
-
}
|
|
1309
|
-
return { ...base, instructions };
|
|
1310
|
-
}
|
|
1311
|
-
|
|
1312
1224
|
/** Look up a session as a channel-scoped handle. */
|
|
1313
1225
|
async getChannelSession(
|
|
1314
1226
|
channelId: string,
|
|
@@ -1633,12 +1545,10 @@ export class SessionEngine {
|
|
|
1633
1545
|
|
|
1634
1546
|
let lifecycleInstalled = false;
|
|
1635
1547
|
try {
|
|
1636
|
-
|
|
1548
|
+
const record = await this.updateRecord(sessionId, (current) => ({
|
|
1637
1549
|
...current,
|
|
1638
1550
|
turnCount: current.turnCount + 1,
|
|
1639
1551
|
}));
|
|
1640
|
-
// Arms must be on the record before tools/instructions see SessionInfo.
|
|
1641
|
-
record = await this.ensureAbs(record);
|
|
1642
1552
|
const turnId = `turn_${record.turnCount}`;
|
|
1643
1553
|
const isFirstTurn = record.turnCount === 1;
|
|
1644
1554
|
|
|
@@ -1668,10 +1578,16 @@ export class SessionEngine {
|
|
|
1668
1578
|
isFirstTurn,
|
|
1669
1579
|
abort.signal
|
|
1670
1580
|
);
|
|
1581
|
+
if (outcome.status === "cancelled") {
|
|
1582
|
+
outcome.cancellationReason = abort.signal.aborted
|
|
1583
|
+
? "signal"
|
|
1584
|
+
: "runner";
|
|
1585
|
+
}
|
|
1671
1586
|
} catch (error) {
|
|
1672
1587
|
outcome = {
|
|
1673
1588
|
status: "error",
|
|
1674
1589
|
errorMessage: describeError(error),
|
|
1590
|
+
errorCode: describeErrorCode(error),
|
|
1675
1591
|
};
|
|
1676
1592
|
} finally {
|
|
1677
1593
|
clearInterval(poll);
|
|
@@ -2192,6 +2108,11 @@ export class SessionEngine {
|
|
|
2192
2108
|
const sessionId = record.sessionId;
|
|
2193
2109
|
const workspaceDir = this.scaffoldDir(record);
|
|
2194
2110
|
const harnessCwd = this.harnessCwd(record);
|
|
2111
|
+
const turnChannelState = structuredClone(record.channelState ?? null);
|
|
2112
|
+
const eventContext: EventDispatchContext = {
|
|
2113
|
+
channelState: structuredClone(turnChannelState),
|
|
2114
|
+
session: this.sessionInfo(record),
|
|
2115
|
+
};
|
|
2195
2116
|
// Hold the open log so tool events append synchronously. Fire-and-forget
|
|
2196
2117
|
// `appendEvent` races parallel tool completions and delays the live stream
|
|
2197
2118
|
// until the next await tick — often after *all* parallel tools finish.
|
|
@@ -2199,7 +2120,7 @@ export class SessionEngine {
|
|
|
2199
2120
|
const emit = (payload: SessionEventPayload): void => {
|
|
2200
2121
|
try {
|
|
2201
2122
|
const event = log.append({ ...payload, turnId });
|
|
2202
|
-
this.queueDispatch(sessionId, event);
|
|
2123
|
+
this.queueDispatch(sessionId, event, eventContext);
|
|
2203
2124
|
} catch (error) {
|
|
2204
2125
|
this.logger(
|
|
2205
2126
|
`[agent-sdk] failed to record event for ${sessionId}: ${describeError(error)}`
|
|
@@ -2235,12 +2156,10 @@ export class SessionEngine {
|
|
|
2235
2156
|
emit({ type: "turn.started", data: {} });
|
|
2236
2157
|
try {
|
|
2237
2158
|
// Scaffold agent files into the session workspace even when the harness
|
|
2238
|
-
// cwd is overridden (e.g. a PR worktree).
|
|
2239
|
-
// overlays are applied via agentForSession.
|
|
2240
|
-
const agent = this.agentForSession(record);
|
|
2159
|
+
// cwd is overridden (e.g. a PR worktree).
|
|
2241
2160
|
if (!this.hasRootOverride()) {
|
|
2242
2161
|
await materializeWorkspace({
|
|
2243
|
-
agent,
|
|
2162
|
+
agent: this.project.agent,
|
|
2244
2163
|
workspaceDir,
|
|
2245
2164
|
seed: isFirstTurn,
|
|
2246
2165
|
stateRoot: this.stateRoot,
|
|
@@ -2262,7 +2181,7 @@ export class SessionEngine {
|
|
|
2262
2181
|
const pendingFiles = record.pendingWorkspaceFiles;
|
|
2263
2182
|
const pendingImages = record.pendingImages;
|
|
2264
2183
|
const runtime = resolveSessionRuntime({
|
|
2265
|
-
agentRuntime: agent.runtime,
|
|
2184
|
+
agentRuntime: this.project.agent.runtime,
|
|
2266
2185
|
cloudOverride: record.cloudOverride,
|
|
2267
2186
|
});
|
|
2268
2187
|
const hasPendingFiles =
|
|
@@ -2305,12 +2224,12 @@ export class SessionEngine {
|
|
|
2305
2224
|
(await isNestedInGitRepo(harnessCwd)));
|
|
2306
2225
|
const request = await this.buildTurnRequest(
|
|
2307
2226
|
record,
|
|
2308
|
-
agent,
|
|
2309
2227
|
turnId,
|
|
2310
2228
|
message,
|
|
2311
2229
|
isFirstTurn,
|
|
2312
2230
|
instructionsInvisibleToHarness,
|
|
2313
2231
|
emit,
|
|
2232
|
+
eventContext,
|
|
2314
2233
|
async (update) => {
|
|
2315
2234
|
const turn = this.turnRoots.get(sessionId);
|
|
2316
2235
|
if (turn !== undefined) {
|
|
@@ -2352,7 +2271,11 @@ export class SessionEngine {
|
|
|
2352
2271
|
} catch (error) {
|
|
2353
2272
|
this.approvals.cancelSession(sessionId, "deny");
|
|
2354
2273
|
this.auths.cancelSession(sessionId, "deny");
|
|
2355
|
-
outcome = {
|
|
2274
|
+
outcome = {
|
|
2275
|
+
status: "error",
|
|
2276
|
+
errorMessage: describeError(error),
|
|
2277
|
+
errorCode: describeErrorCode(error),
|
|
2278
|
+
};
|
|
2356
2279
|
} finally {
|
|
2357
2280
|
permit.release();
|
|
2358
2281
|
this.dropTurnFileSystem(sessionId);
|
|
@@ -2371,6 +2294,7 @@ export class SessionEngine {
|
|
|
2371
2294
|
if (mapper.title !== undefined) {
|
|
2372
2295
|
const title = mapper.title;
|
|
2373
2296
|
await this.updateRecord(sessionId, (current) => ({ ...current, title }));
|
|
2297
|
+
eventContext.session = { ...eventContext.session, title };
|
|
2374
2298
|
}
|
|
2375
2299
|
|
|
2376
2300
|
const finalResult = outcome.result ?? mapper.finalText;
|
|
@@ -2395,7 +2319,8 @@ export class SessionEngine {
|
|
|
2395
2319
|
text: finalResult,
|
|
2396
2320
|
dryRun: record.dryRun === true,
|
|
2397
2321
|
ctx: {
|
|
2398
|
-
session:
|
|
2322
|
+
session: eventContext.session,
|
|
2323
|
+
channelState: turnChannelState,
|
|
2399
2324
|
host: this.hostForSession(sessionId),
|
|
2400
2325
|
artifacts: this.artifactsApi({ sessionId, turnId }),
|
|
2401
2326
|
stateRoot: this.stateRoot,
|
|
@@ -2414,29 +2339,38 @@ export class SessionEngine {
|
|
|
2414
2339
|
}
|
|
2415
2340
|
|
|
2416
2341
|
if (outcome.status === "finished") {
|
|
2417
|
-
await this.appendEvent(
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2342
|
+
await this.appendEvent(
|
|
2343
|
+
sessionId,
|
|
2344
|
+
{
|
|
2345
|
+
type: "turn.completed",
|
|
2346
|
+
turnId,
|
|
2347
|
+
data: {
|
|
2348
|
+
result: finalResult,
|
|
2349
|
+
usage: finalUsage,
|
|
2350
|
+
cost: finalCost,
|
|
2351
|
+
},
|
|
2424
2352
|
},
|
|
2425
|
-
|
|
2353
|
+
eventContext
|
|
2354
|
+
);
|
|
2426
2355
|
} else {
|
|
2427
2356
|
const interrupted = signal.aborted && outcome.status === "cancelled";
|
|
2428
|
-
await this.appendEvent(
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
:
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2357
|
+
await this.appendEvent(
|
|
2358
|
+
sessionId,
|
|
2359
|
+
{
|
|
2360
|
+
type: "turn.failed",
|
|
2361
|
+
turnId,
|
|
2362
|
+
data: {
|
|
2363
|
+
status: outcome.status,
|
|
2364
|
+
message: interrupted
|
|
2365
|
+
? "turn interrupted"
|
|
2366
|
+
: (outcome.errorMessage ??
|
|
2367
|
+
(outcome.status === "cancelled"
|
|
2368
|
+
? "turn cancelled"
|
|
2369
|
+
: "turn failed")),
|
|
2370
|
+
},
|
|
2438
2371
|
},
|
|
2439
|
-
|
|
2372
|
+
eventContext
|
|
2373
|
+
);
|
|
2440
2374
|
}
|
|
2441
2375
|
|
|
2442
2376
|
const current = await this.sessions.get(sessionId);
|
|
@@ -2450,15 +2384,20 @@ export class SessionEngine {
|
|
|
2450
2384
|
type: "session.failed",
|
|
2451
2385
|
turnId,
|
|
2452
2386
|
data: { message: outcome.errorMessage ?? "task failed" },
|
|
2453
|
-
}
|
|
2387
|
+
},
|
|
2388
|
+
eventContext
|
|
2454
2389
|
);
|
|
2455
2390
|
await this.wipeCloudSessionWorkspace(sessionId);
|
|
2456
2391
|
} else {
|
|
2457
|
-
await this.appendEvent(
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2392
|
+
await this.appendEvent(
|
|
2393
|
+
sessionId,
|
|
2394
|
+
{
|
|
2395
|
+
type: "session.waiting",
|
|
2396
|
+
turnId,
|
|
2397
|
+
data: {},
|
|
2398
|
+
},
|
|
2399
|
+
eventContext
|
|
2400
|
+
);
|
|
2462
2401
|
}
|
|
2463
2402
|
|
|
2464
2403
|
return {
|
|
@@ -2658,16 +2597,17 @@ export class SessionEngine {
|
|
|
2658
2597
|
|
|
2659
2598
|
private async buildTurnRequest(
|
|
2660
2599
|
record: SessionRecord,
|
|
2661
|
-
agent: ResolvedAgent,
|
|
2662
2600
|
turnId: string,
|
|
2663
2601
|
prompt: string,
|
|
2664
2602
|
isFirstTurn: boolean,
|
|
2665
2603
|
instructionsInvisibleToHarness: boolean,
|
|
2666
2604
|
emit: (payload: SessionEventPayload) => void,
|
|
2605
|
+
eventContext: EventDispatchContext,
|
|
2667
2606
|
onUpdate: RunnerTurnRequest["onUpdate"],
|
|
2668
2607
|
signal: AbortSignal,
|
|
2669
2608
|
images?: Array<{ data: string; mimeType: string }>
|
|
2670
2609
|
): Promise<RunnerTurnRequest> {
|
|
2610
|
+
const agent = this.project.agent;
|
|
2671
2611
|
// Per-session cloud attach (channel/tool handoff) forces cloud runtime
|
|
2672
2612
|
// even when the agent defaults to local for chat server tools.
|
|
2673
2613
|
const runtime = resolveSessionRuntime({
|
|
@@ -2875,9 +2815,7 @@ export class SessionEngine {
|
|
|
2875
2815
|
? {}
|
|
2876
2816
|
: { sdkAgentId: record.sdkAgentId }),
|
|
2877
2817
|
workspaceDir: this.harnessCwd(record),
|
|
2878
|
-
sandbox: authoredRoot
|
|
2879
|
-
? false
|
|
2880
|
-
: this.project.agent.local?.sandbox === true,
|
|
2818
|
+
sandbox: authoredRoot ? false : agent.local?.sandbox === true,
|
|
2881
2819
|
...(runtime === "local" && harnessTools !== undefined
|
|
2882
2820
|
? {
|
|
2883
2821
|
...(harnessTools.tools === undefined
|
|
@@ -2910,13 +2848,7 @@ export class SessionEngine {
|
|
|
2910
2848
|
: {}),
|
|
2911
2849
|
customTools:
|
|
2912
2850
|
runtime === "local"
|
|
2913
|
-
? await this.buildCustomTools(
|
|
2914
|
-
record,
|
|
2915
|
-
agent,
|
|
2916
|
-
turnId,
|
|
2917
|
-
emit,
|
|
2918
|
-
synthesized
|
|
2919
|
-
)
|
|
2851
|
+
? await this.buildCustomTools(record, turnId, emit, synthesized)
|
|
2920
2852
|
: {},
|
|
2921
2853
|
mcpServers: this.buildMcpServers(
|
|
2922
2854
|
runtime,
|
|
@@ -2944,16 +2876,21 @@ export class SessionEngine {
|
|
|
2944
2876
|
sdkAgentId,
|
|
2945
2877
|
}));
|
|
2946
2878
|
record.sdkAgentId = sdkAgentId;
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2879
|
+
eventContext.session = { ...eventContext.session, sdkAgentId };
|
|
2880
|
+
await this.appendEvent(
|
|
2881
|
+
record.sessionId,
|
|
2882
|
+
{
|
|
2883
|
+
type: "agent.bound",
|
|
2884
|
+
turnId,
|
|
2885
|
+
data: {
|
|
2886
|
+
sdkAgentId,
|
|
2887
|
+
...(sdkAgentId.startsWith("bc-")
|
|
2888
|
+
? { url: `https://cursor.com/agents/${sdkAgentId}` }
|
|
2889
|
+
: {}),
|
|
2890
|
+
},
|
|
2955
2891
|
},
|
|
2956
|
-
|
|
2892
|
+
eventContext
|
|
2893
|
+
);
|
|
2957
2894
|
},
|
|
2958
2895
|
};
|
|
2959
2896
|
}
|
|
@@ -3208,11 +3145,11 @@ export class SessionEngine {
|
|
|
3208
3145
|
|
|
3209
3146
|
private async buildCustomTools(
|
|
3210
3147
|
record: SessionRecord,
|
|
3211
|
-
agent: ResolvedAgent,
|
|
3212
3148
|
turnId: string,
|
|
3213
3149
|
emit: (payload: SessionEventPayload) => void,
|
|
3214
3150
|
extraTools: DiscoveredTool[] = []
|
|
3215
3151
|
): Promise<Record<string, SDKCustomTool>> {
|
|
3152
|
+
const agent = this.project.agent;
|
|
3216
3153
|
const tools: Record<string, SDKCustomTool> = {};
|
|
3217
3154
|
const register = (tool: ResolvedAgent["tools"][number]): void => {
|
|
3218
3155
|
tools[tool.name] = {
|
|
@@ -4606,21 +4543,26 @@ export class SessionEngine {
|
|
|
4606
4543
|
|
|
4607
4544
|
private async appendEvent(
|
|
4608
4545
|
sessionId: string,
|
|
4609
|
-
payload: SessionEventPayload & { turnId?: string }
|
|
4546
|
+
payload: SessionEventPayload & { turnId?: string },
|
|
4547
|
+
context?: EventDispatchContext
|
|
4610
4548
|
): Promise<SessionEvent> {
|
|
4611
4549
|
const log = await this.logs.get(sessionId);
|
|
4612
4550
|
const event = log.append(payload);
|
|
4613
|
-
this.queueDispatch(sessionId, event);
|
|
4551
|
+
this.queueDispatch(sessionId, event, context);
|
|
4614
4552
|
return event;
|
|
4615
4553
|
}
|
|
4616
4554
|
|
|
4617
|
-
private queueDispatch(
|
|
4555
|
+
private queueDispatch(
|
|
4556
|
+
sessionId: string,
|
|
4557
|
+
event: SessionEvent,
|
|
4558
|
+
context?: EventDispatchContext
|
|
4559
|
+
): void {
|
|
4618
4560
|
// Single funnel for both append paths (appendEvent + the held-log emit),
|
|
4619
4561
|
// so the storage sink sees every durable event exactly once.
|
|
4620
4562
|
this.storage?.event(event);
|
|
4621
4563
|
const chain = this.dispatchChains.get(sessionId) ?? Promise.resolve();
|
|
4622
4564
|
const next = chain
|
|
4623
|
-
.then(() => this.dispatchEvent(sessionId, event))
|
|
4565
|
+
.then(() => this.dispatchEvent(sessionId, event, context))
|
|
4624
4566
|
.catch((error) => {
|
|
4625
4567
|
this.logger(
|
|
4626
4568
|
`[agent-sdk] event dispatch failed for ${sessionId}: ${describeError(error)}`
|
|
@@ -4637,16 +4579,27 @@ export class SessionEngine {
|
|
|
4637
4579
|
|
|
4638
4580
|
private async dispatchEvent(
|
|
4639
4581
|
sessionId: string,
|
|
4640
|
-
event: SessionEvent
|
|
4582
|
+
event: SessionEvent,
|
|
4583
|
+
context?: EventDispatchContext
|
|
4641
4584
|
): Promise<void> {
|
|
4642
4585
|
const record = await this.sessions.get(sessionId);
|
|
4643
4586
|
if (record === undefined) {
|
|
4644
4587
|
return;
|
|
4645
4588
|
}
|
|
4589
|
+
const channelState =
|
|
4590
|
+
context === undefined
|
|
4591
|
+
? (record.channelState ?? null)
|
|
4592
|
+
: context.channelState;
|
|
4593
|
+
const channelStateBefore =
|
|
4594
|
+
context === undefined ? undefined : structuredClone(channelState);
|
|
4646
4595
|
|
|
4647
4596
|
const sessionCtx: SessionContext = {
|
|
4648
|
-
session: this.sessionInfo(record),
|
|
4597
|
+
session: context?.session ?? this.sessionInfo(record),
|
|
4649
4598
|
host: this.hostForSession(record.sessionId),
|
|
4599
|
+
artifacts: this.artifactsApi({
|
|
4600
|
+
sessionId: record.sessionId,
|
|
4601
|
+
turnId: event.turnId,
|
|
4602
|
+
}),
|
|
4650
4603
|
};
|
|
4651
4604
|
const channelEvents = this.channelEventHandlersFor(record.channelId);
|
|
4652
4605
|
if (channelEvents !== undefined) {
|
|
@@ -4658,7 +4611,7 @@ export class SessionEngine {
|
|
|
4658
4611
|
];
|
|
4659
4612
|
const channelCtx = {
|
|
4660
4613
|
channelId: record.channelId,
|
|
4661
|
-
state:
|
|
4614
|
+
state: channelState,
|
|
4662
4615
|
continuationToken: record.continuationKey,
|
|
4663
4616
|
setContinuationToken: (token: string | null) =>
|
|
4664
4617
|
this.setContinuationToken(sessionId, token),
|
|
@@ -4675,8 +4628,21 @@ export class SessionEngine {
|
|
|
4675
4628
|
);
|
|
4676
4629
|
}
|
|
4677
4630
|
}
|
|
4678
|
-
|
|
4679
|
-
|
|
4631
|
+
if (context === undefined || channelStateBefore === undefined) {
|
|
4632
|
+
// Handlers mutate live channel state in place; save the current record.
|
|
4633
|
+
await this.updateRecord(sessionId, (current) => ({ ...current }));
|
|
4634
|
+
} else {
|
|
4635
|
+
const updatedState = channelCtx.state as JsonValue;
|
|
4636
|
+
context.channelState = updatedState;
|
|
4637
|
+
await this.updateRecord(sessionId, (current) => ({
|
|
4638
|
+
...current,
|
|
4639
|
+
channelState: mergeChannelStateMutation({
|
|
4640
|
+
current: current.channelState,
|
|
4641
|
+
before: channelStateBefore,
|
|
4642
|
+
after: updatedState,
|
|
4643
|
+
}),
|
|
4644
|
+
}));
|
|
4645
|
+
}
|
|
4680
4646
|
}
|
|
4681
4647
|
|
|
4682
4648
|
for (const hook of this.project.hooks) {
|
|
@@ -4697,10 +4663,6 @@ export class SessionEngine {
|
|
|
4697
4663
|
continuationToken: record.continuationKey,
|
|
4698
4664
|
},
|
|
4699
4665
|
stateRoot: this.stateRoot,
|
|
4700
|
-
artifacts: this.artifactsApi({
|
|
4701
|
-
sessionId: record.sessionId,
|
|
4702
|
-
turnId: event.turnId,
|
|
4703
|
-
}),
|
|
4704
4666
|
});
|
|
4705
4667
|
} catch (error) {
|
|
4706
4668
|
this.logger(
|
|
@@ -4710,14 +4672,6 @@ export class SessionEngine {
|
|
|
4710
4672
|
}
|
|
4711
4673
|
}
|
|
4712
4674
|
|
|
4713
|
-
if (this.abCollector.enabled) {
|
|
4714
|
-
await this.abCollector.onEvent(
|
|
4715
|
-
event,
|
|
4716
|
-
sessionCtx.session,
|
|
4717
|
-
this.project.name
|
|
4718
|
-
);
|
|
4719
|
-
}
|
|
4720
|
-
|
|
4721
4675
|
this.otel?.onEvent(event, sessionCtx.session);
|
|
4722
4676
|
}
|
|
4723
4677
|
|
|
@@ -4776,6 +4730,10 @@ export class SessionEngine {
|
|
|
4776
4730
|
await active;
|
|
4777
4731
|
continue;
|
|
4778
4732
|
}
|
|
4733
|
+
const dispatch = this.dispatchChains.get(sessionId);
|
|
4734
|
+
if (dispatch !== undefined) {
|
|
4735
|
+
await dispatch.catch(() => {});
|
|
4736
|
+
}
|
|
4779
4737
|
return this.lastOutcomes.get(sessionId) ?? { status: "finished" };
|
|
4780
4738
|
}
|
|
4781
4739
|
}
|
|
@@ -5033,61 +4991,6 @@ export class SessionEngine {
|
|
|
5033
4991
|
});
|
|
5034
4992
|
}
|
|
5035
4993
|
|
|
5036
|
-
/**
|
|
5037
|
-
* Fold durable session streams into per-session A/B assignments and
|
|
5038
|
-
* aggregate arm metrics (`GET /v1/abs`). Collector-independent: always
|
|
5039
|
-
* reads `events.ndjson`.
|
|
5040
|
-
*/
|
|
5041
|
-
async abSnapshot(
|
|
5042
|
-
caller: AuthContext | null,
|
|
5043
|
-
options?: { includeAll?: boolean }
|
|
5044
|
-
): Promise<ABSnapshot> {
|
|
5045
|
-
const sessions = await this.listSessions(caller, options);
|
|
5046
|
-
const abConfig = this.project.abConfig;
|
|
5047
|
-
const maxPlaygroundSessions = resolveABMaxPlaygroundSessions(
|
|
5048
|
-
abConfig?.maxPlaygroundSessions
|
|
5049
|
-
);
|
|
5050
|
-
const foldedSessions = sessions.slice(0, maxPlaygroundSessions);
|
|
5051
|
-
// Backfill for a replacement host with nothing local to fold (e.g.
|
|
5052
|
-
// lazy-only restore before any session resumed): serve the persisted
|
|
5053
|
-
// aggregate instead of an empty surface. Gated on the host having no
|
|
5054
|
-
// sessions AT ALL — the persisted snapshot spans every principal, so a
|
|
5055
|
-
// caller who merely owns no sessions must not see it. Loaded once per
|
|
5056
|
-
// process (playground polls this route ~every 4s); skip the persist
|
|
5057
|
-
// side effect below — re-saving a restored snapshot would echo stale
|
|
5058
|
-
// data back into the store.
|
|
5059
|
-
if (
|
|
5060
|
-
foldedSessions.length === 0 &&
|
|
5061
|
-
this.storage !== undefined &&
|
|
5062
|
-
(await this.sessions.list()).length === 0
|
|
5063
|
-
) {
|
|
5064
|
-
this.restoredAbSnapshot ??= this.storage.getLatestAbSnapshot();
|
|
5065
|
-
const restoredSnapshot = await this.restoredAbSnapshot;
|
|
5066
|
-
if (restoredSnapshot !== undefined) {
|
|
5067
|
-
return restoredSnapshot;
|
|
5068
|
-
}
|
|
5069
|
-
}
|
|
5070
|
-
const abTable = this.project.storage?.abs;
|
|
5071
|
-
const snapshot = await buildABSnapshot({
|
|
5072
|
-
experiments: this.project.abs,
|
|
5073
|
-
agentName: this.project.name,
|
|
5074
|
-
sessions: foldedSessions,
|
|
5075
|
-
loadRecord: (sessionId) => this.sessions.get(sessionId),
|
|
5076
|
-
loadEvents: (sessionId) => this.listEvents(sessionId, 0),
|
|
5077
|
-
sessionInfo: (record) => this.sessionInfo(record),
|
|
5078
|
-
logger: this.logger,
|
|
5079
|
-
config: {
|
|
5080
|
-
maxPlaygroundSessions,
|
|
5081
|
-
durableSamples: abTable !== undefined,
|
|
5082
|
-
durableSnapshots: abTable?.putSnapshot !== undefined,
|
|
5083
|
-
},
|
|
5084
|
-
});
|
|
5085
|
-
// Side effect on the read path: playground polls GET /v1/abs ~every 4s;
|
|
5086
|
-
// the coordinator throttles the actual table write.
|
|
5087
|
-
this.storage?.abSnapshot(snapshot);
|
|
5088
|
-
return snapshot;
|
|
5089
|
-
}
|
|
5090
|
-
|
|
5091
4994
|
async eventStream(
|
|
5092
4995
|
sessionId: string,
|
|
5093
4996
|
startIndex = 0
|
|
@@ -5347,7 +5250,6 @@ export class SessionEngine {
|
|
|
5347
5250
|
asOf: record.asOf,
|
|
5348
5251
|
auth: record.auth,
|
|
5349
5252
|
continuationKey: record.continuationKey,
|
|
5350
|
-
...(record.abs === undefined ? {} : { abs: record.abs }),
|
|
5351
5253
|
...(record.title === undefined ? {} : { title: record.title }),
|
|
5352
5254
|
...(record.sdkAgentId === undefined
|
|
5353
5255
|
? {}
|
|
@@ -5449,9 +5351,9 @@ export class SessionEngine {
|
|
|
5449
5351
|
* serve start, before channels accept traffic: any persisted session
|
|
5450
5352
|
* missing from the local `--state-root` is materialized there — events
|
|
5451
5353
|
* as `events.ndjson`, record as `session.json` — after which every
|
|
5452
|
-
* existing read path (continuation lookup, event replay/streams
|
|
5453
|
-
*
|
|
5454
|
-
*
|
|
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.
|
|
5455
5357
|
*
|
|
5456
5358
|
* Failures are logged and skipped; a broken store (including rows that
|
|
5457
5359
|
* violate the SessionRecord shape) never blocks serve start.
|
|
@@ -5770,38 +5672,6 @@ function mergePendingWorkspaceFiles(
|
|
|
5770
5672
|
return { ...current, ...incoming };
|
|
5771
5673
|
}
|
|
5772
5674
|
|
|
5773
|
-
/**
|
|
5774
|
-
* Shallow-merge a wake patch into durable channel state. Null / undefined
|
|
5775
|
-
* patch values leave the existing key alone so sticky fields survive.
|
|
5776
|
-
*/
|
|
5777
|
-
export function mergeChannelStateSkipNull(
|
|
5778
|
-
current: JsonValue | undefined,
|
|
5779
|
-
patch: JsonValue | undefined
|
|
5780
|
-
): JsonValue | undefined {
|
|
5781
|
-
if (patch === undefined) {
|
|
5782
|
-
return current;
|
|
5783
|
-
}
|
|
5784
|
-
if (
|
|
5785
|
-
typeof patch !== "object" ||
|
|
5786
|
-
patch === null ||
|
|
5787
|
-
Array.isArray(patch) ||
|
|
5788
|
-
typeof current !== "object" ||
|
|
5789
|
-
current === null ||
|
|
5790
|
-
Array.isArray(current)
|
|
5791
|
-
) {
|
|
5792
|
-
return structuredClone(patch);
|
|
5793
|
-
}
|
|
5794
|
-
const merged: Record<string, JsonValue> = {
|
|
5795
|
-
...(current as Record<string, JsonValue>),
|
|
5796
|
-
};
|
|
5797
|
-
for (const [key, value] of Object.entries(patch)) {
|
|
5798
|
-
if (value !== null && value !== undefined) {
|
|
5799
|
-
merged[key] = value as JsonValue;
|
|
5800
|
-
}
|
|
5801
|
-
}
|
|
5802
|
-
return merged;
|
|
5803
|
-
}
|
|
5804
|
-
|
|
5805
5675
|
function eventsNdjson(events: SessionEvent[]): string | undefined {
|
|
5806
5676
|
if (events.length === 0) {
|
|
5807
5677
|
return undefined;
|