@cursor/july 0.1.96 → 0.1.99
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 +1 -1
- package/README.md +3 -2
- package/dist/bin/agent-serve.js +13 -3
- package/dist/channels/github/github-channel.d.ts.map +1 -1
- package/dist/channels/github/github-channel.js +16 -0
- package/dist/channels/origin/api.d.ts +15 -4
- package/dist/channels/origin/api.d.ts.map +1 -1
- package/dist/channels/origin/api.js +19 -3
- package/dist/channels/origin/binding.d.ts +11 -0
- package/dist/channels/origin/binding.d.ts.map +1 -1
- package/dist/channels/origin/binding.js +41 -25
- package/dist/channels/origin/index.d.ts +1 -0
- package/dist/channels/origin/index.d.ts.map +1 -1
- package/dist/channels/origin/index.js +1 -0
- package/dist/channels/origin/origin-channel.d.ts +2 -0
- package/dist/channels/origin/origin-channel.d.ts.map +1 -1
- package/dist/channels/origin/origin-channel.js +40 -4
- package/dist/channels/origin/reactions.d.ts +56 -0
- package/dist/channels/origin/reactions.d.ts.map +1 -0
- package/dist/channels/origin/reactions.js +67 -0
- package/dist/channels/origin/types.d.ts +11 -0
- package/dist/channels/origin/types.d.ts.map +1 -1
- package/dist/channels/slack/approvals.d.ts +16 -0
- package/dist/channels/slack/approvals.d.ts.map +1 -1
- package/dist/channels/slack/approvals.js +86 -0
- package/dist/channels/slack/cli-project.d.ts +19 -0
- package/dist/channels/slack/cli-project.d.ts.map +1 -0
- package/dist/channels/slack/cli-project.js +234 -0
- package/dist/channels/slack/defaults.d.ts.map +1 -1
- package/dist/channels/slack/defaults.js +142 -63
- package/dist/channels/slack/dispatch.d.ts.map +1 -1
- package/dist/channels/slack/dispatch.js +1 -1
- package/dist/channels/slack/init.d.ts +3 -2
- package/dist/channels/slack/init.d.ts.map +1 -1
- package/dist/channels/slack/init.js +5 -5
- package/dist/channels/slack/interactive.d.ts +2 -1
- package/dist/channels/slack/interactive.d.ts.map +1 -1
- package/dist/channels/slack/interactive.js +15 -4
- package/dist/channels/slack/live-delivery.d.ts +1 -1
- package/dist/channels/slack/live-delivery.d.ts.map +1 -1
- package/dist/channels/slack/live-delivery.js +4 -2
- package/dist/channels/slack/manifest.d.ts +1 -1
- package/dist/channels/slack/manifest.js +1 -1
- package/dist/channels/slack/progress-delivery.d.ts +28 -0
- package/dist/channels/slack/progress-delivery.d.ts.map +1 -0
- package/dist/channels/slack/progress-delivery.js +115 -0
- package/dist/channels/slack/setup.d.ts +1 -1
- package/dist/channels/slack/setup.d.ts.map +1 -1
- package/dist/channels/slack/setup.js +10 -6
- package/dist/channels/slack/slack-channel.d.ts.map +1 -1
- package/dist/channels/slack/slack-channel.js +1 -0
- package/dist/channels/slack/tool-approval-events.d.ts.map +1 -1
- package/dist/channels/slack/tool-approval-events.js +91 -1
- package/dist/channels/slack/types.d.ts +9 -1
- package/dist/channels/slack/types.d.ts.map +1 -1
- package/dist/docs/404.html +2 -2
- package/dist/docs/ab.html +4 -4
- package/dist/docs/assets/{app.jXleCmOc.js → app.BplEAZ3S.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.DpuI4i7Z.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.8LhyglIT.js → VPLocalSearchBox.CHXyv4wP.js} +1 -1
- package/dist/docs/assets/chunks/{theme.9ged-pr2.js → theme.BTcsZmjQ.js} +2 -2
- package/dist/docs/assets/{deployment.md.D9msOFOW.js → deployment.md.MFPKqsqI.js} +2 -2
- package/dist/docs/assets/{guides_mcp-oauth.md.DPYmBCbV.js → guides_mcp-oauth.md.CN-6YmTJ.js} +4 -4
- package/dist/docs/assets/{guides_mcp-oauth.md.DPYmBCbV.lean.js → guides_mcp-oauth.md.CN-6YmTJ.lean.js} +1 -1
- package/dist/docs/assets/guides_slack.md.VDXQV3ja.js +22 -0
- package/dist/docs/assets/guides_slack.md.VDXQV3ja.lean.js +1 -0
- package/dist/docs/assets/index.md.CVeRUOeZ.js +5 -0
- package/dist/docs/assets/{reference_agent-config.md.Cp_x38Nl.js → reference_agent-config.md.BHeYMgme.js} +1 -1
- package/dist/docs/assets/{reference_cli.md.CCnG-nJx.js → reference_cli.md.DfoeyvL0.js} +9 -6
- package/dist/docs/assets/{reference_cli.md.CCnG-nJx.lean.js → reference_cli.md.DfoeyvL0.lean.js} +1 -1
- package/dist/docs/assets/{reference_connections.md.BH8Oc0D0.js → reference_connections.md.DxldvyIB.js} +4 -3
- package/dist/docs/assets/{reference_http-api.md.D89k1mdm.js → reference_http-api.md.BEJx9XVj.js} +2 -2
- package/dist/docs/assets/reference_sessions.md.NxFP_CAC.js +1 -0
- package/dist/docs/assets/{reference_tools.md.BHeXn2id.js → reference_tools.md.CvAHsdSp.js} +10 -2
- package/dist/docs/assets/{reference_tools.md.BHeXn2id.lean.js → reference_tools.md.CvAHsdSp.lean.js} +1 -1
- package/dist/docs/assets/templates_agents-md.md.CXSMZljE.js +2 -0
- package/dist/docs/assets/templates_agents-md.md.CXSMZljE.lean.js +1 -0
- package/dist/docs/assets/troubleshooting.md.DCiPBhYs.js +1 -0
- package/dist/docs/building-with-agents.html +4 -4
- package/dist/docs/concepts.html +4 -4
- package/dist/docs/deployment.html +7 -7
- package/dist/docs/deployment.md +5 -4
- package/dist/docs/design/runtime-abstraction.md +1757 -0
- package/dist/docs/evals.html +4 -4
- package/dist/docs/guides/agent-to-agent.html +4 -4
- package/dist/docs/guides/cloud-runtime.html +4 -4
- package/dist/docs/guides/convert-automation.html +4 -4
- package/dist/docs/guides/github.html +4 -4
- package/dist/docs/guides/human-in-the-loop.html +4 -4
- package/dist/docs/guides/mcp-oauth.html +8 -8
- package/dist/docs/guides/mcp-oauth.md +26 -8
- package/dist/docs/guides/opentelemetry.html +4 -4
- package/dist/docs/guides/slack.html +17 -33
- package/dist/docs/guides/slack.md +92 -201
- package/dist/docs/guides/webhooks.html +4 -4
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +4 -4
- package/dist/docs/index.html +6 -6
- package/dist/docs/index.md +5 -3
- package/dist/docs/llms-full.txt +2065 -637
- package/dist/docs/llms.txt +3 -2
- package/dist/docs/quickstart.html +4 -4
- package/dist/docs/reference/agent-config.html +6 -6
- package/dist/docs/reference/agent-config.md +2 -2
- package/dist/docs/reference/artifacts.html +4 -4
- package/dist/docs/reference/channels.html +4 -4
- package/dist/docs/reference/cli.html +13 -10
- package/dist/docs/reference/cli.md +32 -16
- package/dist/docs/reference/connections.html +9 -8
- package/dist/docs/reference/connections.md +6 -3
- package/dist/docs/reference/hooks.html +4 -4
- package/dist/docs/reference/http-api.html +7 -7
- package/dist/docs/reference/http-api.md +3 -1
- package/dist/docs/reference/instructions.html +4 -4
- package/dist/docs/reference/playground.html +4 -4
- package/dist/docs/reference/project-layout.html +4 -4
- package/dist/docs/reference/prompt.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 +4 -2
- package/dist/docs/reference/skills.html +4 -4
- package/dist/docs/reference/subagents.html +4 -4
- package/dist/docs/reference/tools.html +15 -7
- package/dist/docs/reference/tools.md +34 -2
- package/dist/docs/scaffolding-agents.html +4 -4
- package/dist/docs/storage.html +4 -4
- package/dist/docs/templates/agentic-owners.html +4 -4
- package/dist/docs/templates/agents-md.html +28 -0
- package/dist/docs/templates/agents-md.md +105 -0
- package/dist/docs/templates/code-wiki.html +5 -5
- package/dist/docs/templates/demo.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 +5 -5
- package/dist/docs/templates/triage.html +4 -4
- package/dist/docs/troubleshooting.html +5 -5
- package/dist/docs/troubleshooting.md +2 -2
- package/dist/evals/run-facts.d.ts.map +1 -1
- package/dist/evals/run-facts.js +27 -0
- package/dist/files-backends/cursor-hosted.d.ts +3 -2
- package/dist/files-backends/cursor-hosted.d.ts.map +1 -1
- package/dist/files-backends/cursor-hosted.js +3 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/internal/advertise-tools.d.ts.map +1 -1
- package/dist/internal/advertise-tools.js +15 -9
- package/dist/internal/approval-gate.d.ts +12 -13
- package/dist/internal/approval-gate.d.ts.map +1 -1
- package/dist/internal/approval-gate.js +16 -21
- package/dist/internal/as-of.d.ts +19 -0
- package/dist/internal/as-of.d.ts.map +1 -0
- package/dist/internal/as-of.js +82 -0
- package/dist/internal/chat-client.js +10 -0
- package/dist/internal/cli-deploy.d.ts +6 -0
- package/dist/internal/cli-deploy.d.ts.map +1 -1
- package/dist/internal/cli-deploy.js +149 -21
- package/dist/internal/cli-mcp-oauth.js +8 -18
- package/dist/internal/cli-slack-manual.d.ts +24 -2
- package/dist/internal/cli-slack-manual.d.ts.map +1 -1
- package/dist/internal/cli-slack-manual.js +251 -20
- package/dist/internal/cli-slack.d.ts +9 -2
- package/dist/internal/cli-slack.d.ts.map +1 -1
- package/dist/internal/cli-slack.js +29 -82
- package/dist/internal/cursor/account-mcp.d.ts +1 -0
- package/dist/internal/cursor/account-mcp.d.ts.map +1 -1
- package/dist/internal/cursor/account-mcp.js +17 -0
- package/dist/internal/cursor-agent-template.d.ts +1 -1
- package/dist/internal/cursor-agent-template.d.ts.map +1 -1
- package/dist/internal/cursor-agent-template.js +1 -0
- package/dist/internal/cursor-event-relay.d.ts.map +1 -1
- package/dist/internal/cursor-event-relay.js +5 -6
- package/dist/internal/deploy-client.d.ts +17 -0
- package/dist/internal/deploy-client.d.ts.map +1 -1
- package/dist/internal/deploy-client.js +31 -10
- package/dist/internal/env-file.d.ts +19 -0
- package/dist/internal/env-file.d.ts.map +1 -0
- package/dist/internal/env-file.js +90 -0
- package/dist/internal/framework-file-storage.d.ts +11 -17
- package/dist/internal/framework-file-storage.d.ts.map +1 -1
- package/dist/internal/framework-file-storage.js +17 -40
- package/dist/internal/framework-storage-selection.d.ts +13 -11
- package/dist/internal/framework-storage-selection.d.ts.map +1 -1
- package/dist/internal/framework-storage-selection.js +37 -26
- package/dist/internal/hosted-admission-adapter.d.ts +28 -0
- package/dist/internal/hosted-admission-adapter.d.ts.map +1 -0
- package/dist/internal/hosted-admission-adapter.js +7 -0
- package/dist/internal/hosted-delivery-protocol.d.ts +13 -1
- package/dist/internal/hosted-delivery-protocol.d.ts.map +1 -1
- package/dist/internal/hosted-delivery-protocol.js +8 -1
- package/dist/internal/hosted-delivery.d.ts +21 -1
- package/dist/internal/hosted-delivery.d.ts.map +1 -1
- package/dist/internal/hosted-delivery.js +101 -34
- package/dist/internal/hosted-execution-diag.d.ts +59 -0
- package/dist/internal/hosted-execution-diag.d.ts.map +1 -0
- package/dist/internal/hosted-execution-diag.js +187 -0
- package/dist/internal/http-channel.d.ts.map +1 -1
- package/dist/internal/http-channel.js +85 -2
- package/dist/internal/init-project.d.ts.map +1 -1
- package/dist/internal/init-project.js +2 -0
- package/dist/internal/logs-client.d.ts +5 -0
- package/dist/internal/logs-client.d.ts.map +1 -1
- package/dist/internal/logs-client.js +5 -0
- package/dist/internal/mcp-endpoint.js +2 -3
- package/dist/internal/mcp-host.d.ts +10 -0
- package/dist/internal/mcp-host.d.ts.map +1 -1
- package/dist/internal/mcp-host.js +57 -8
- package/dist/internal/mcp-oauth-on-demand.d.ts +68 -0
- package/dist/internal/mcp-oauth-on-demand.d.ts.map +1 -0
- package/dist/internal/mcp-oauth-on-demand.js +287 -0
- package/dist/internal/mcp-oauth-persist.d.ts +42 -0
- package/dist/internal/mcp-oauth-persist.d.ts.map +1 -0
- package/dist/internal/mcp-oauth-persist.js +92 -0
- package/dist/internal/mcp-oauth.d.ts +1 -0
- package/dist/internal/mcp-oauth.d.ts.map +1 -1
- package/dist/internal/mcp-oauth.js +10 -2
- package/dist/internal/null-kv-storage.d.ts +48 -0
- package/dist/internal/null-kv-storage.d.ts.map +1 -0
- package/dist/internal/null-kv-storage.js +58 -0
- package/dist/internal/otel/collector.d.ts.map +1 -1
- package/dist/internal/otel/collector.js +22 -9
- package/dist/internal/server.d.ts +6 -0
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +123 -33
- package/dist/internal/session-engine.d.ts +88 -3
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +538 -46
- package/dist/internal/session-run-log.d.ts +120 -0
- package/dist/internal/session-run-log.d.ts.map +1 -0
- package/dist/internal/session-run-log.js +359 -0
- package/dist/internal/sessions-client.d.ts +9 -7
- package/dist/internal/sessions-client.d.ts.map +1 -1
- package/dist/internal/sessions-client.js +3 -1
- package/dist/internal/storage-coordinator.d.ts +13 -0
- package/dist/internal/storage-coordinator.d.ts.map +1 -1
- package/dist/internal/storage-coordinator.js +37 -6
- package/dist/internal/storage-roles.d.ts +5 -0
- package/dist/internal/storage-roles.d.ts.map +1 -1
- package/dist/internal/stream-progress.d.ts.map +1 -1
- package/dist/internal/stream-progress.js +10 -0
- package/dist/internal/tool-policy.d.ts +29 -9
- package/dist/internal/tool-policy.d.ts.map +1 -1
- package/dist/internal/tool-policy.js +24 -0
- package/dist/internal/trajectory.d.ts.map +1 -1
- package/dist/internal/trajectory.js +10 -0
- package/dist/internal/turn-outbox.d.ts +24 -0
- package/dist/internal/turn-outbox.d.ts.map +1 -0
- package/dist/internal/turn-outbox.js +80 -0
- package/dist/playground/assets/index-D7rGZNjy.css +1 -0
- package/dist/playground/assets/index-jzNbJENa.js +69 -0
- package/dist/playground/index.html +2 -2
- package/dist/storage-backends/cursor-hosted.d.ts +1 -1
- package/dist/storage-backends/cursor-hosted.d.ts.map +1 -1
- package/dist/storage-backends/cursor-hosted.js +12 -0
- package/dist/storage-protocol.d.ts +8 -0
- package/dist/storage-protocol.d.ts.map +1 -1
- package/dist/storage-protocol.js +8 -0
- package/dist/storage.d.ts +8 -0
- package/dist/storage.d.ts.map +1 -1
- package/dist/tools.d.ts +12 -2
- package/dist/tools.d.ts.map +1 -1
- package/dist/types.d.ts +88 -7
- package/dist/types.d.ts.map +1 -1
- package/docs/README.md +5 -3
- package/docs/deployment.md +5 -4
- package/docs/design/runtime-abstraction.md +1757 -0
- package/docs/guides/mcp-oauth.md +26 -8
- package/docs/guides/slack.md +93 -202
- package/docs/reference/agent-config.md +2 -2
- package/docs/reference/cli.md +32 -16
- package/docs/reference/connections.md +6 -3
- package/docs/reference/http-api.md +3 -1
- package/docs/reference/sessions.md +4 -2
- package/docs/reference/tools.md +34 -2
- package/docs/templates/agents-md.md +110 -0
- package/docs/troubleshooting.md +2 -2
- package/package.json +1 -1
- package/skills/create-agent/SKILL.md +2 -1
- package/skills/mcp-auth/SKILL.md +6 -3
- package/skills/setup-slack/SKILL.md +23 -13
- package/src/bin/agent-serve.ts +12 -1
- package/src/channels/github/github-channel.ts +17 -0
- package/src/channels/origin/api.ts +24 -5
- package/src/channels/origin/binding.ts +55 -26
- package/src/channels/origin/index.ts +1 -0
- package/src/channels/origin/origin-channel.ts +78 -10
- package/src/channels/origin/reactions.ts +82 -0
- package/src/channels/origin/types.ts +11 -0
- package/src/channels/slack/approvals.ts +105 -0
- package/src/channels/slack/cli-project.ts +267 -0
- package/src/channels/slack/defaults.ts +165 -74
- package/src/channels/slack/dispatch.ts +2 -0
- package/src/channels/slack/init.ts +10 -5
- package/src/channels/slack/interactive.ts +35 -9
- package/src/channels/slack/live-delivery.ts +5 -3
- package/src/channels/slack/manifest.ts +1 -1
- package/src/channels/slack/progress-delivery.ts +133 -0
- package/src/channels/slack/setup.ts +10 -6
- package/src/channels/slack/slack-channel.ts +1 -0
- package/src/channels/slack/tool-approval-events.ts +93 -0
- package/src/channels/slack/types.ts +9 -1
- package/src/evals/run-facts.ts +32 -0
- package/src/files-backends/cursor-hosted.ts +3 -2
- package/src/index.ts +4 -0
- package/src/internal/advertise-tools.ts +31 -10
- package/src/internal/approval-gate.ts +20 -29
- package/src/internal/as-of.ts +107 -0
- package/src/internal/chat-client.ts +19 -0
- package/src/internal/cli-deploy.ts +203 -13
- package/src/internal/cli-mcp-oauth.ts +7 -21
- package/src/internal/cli-slack-manual.ts +350 -18
- package/src/internal/cli-slack.ts +40 -84
- package/src/internal/cursor/account-mcp.ts +21 -0
- package/src/internal/cursor-agent-template.ts +1 -0
- package/src/internal/cursor-event-relay.ts +5 -6
- package/src/internal/deploy-client.ts +43 -0
- package/src/internal/env-file.ts +84 -0
- package/src/internal/framework-file-storage.ts +18 -46
- package/src/internal/framework-storage-selection.ts +41 -25
- package/src/internal/hosted-admission-adapter.ts +42 -0
- package/src/internal/hosted-delivery-protocol.ts +14 -2
- package/src/internal/hosted-delivery.ts +169 -44
- package/src/internal/hosted-execution-diag.ts +252 -0
- package/src/internal/http-channel.ts +107 -0
- package/src/internal/init-project.ts +2 -0
- package/src/internal/logs-client.ts +5 -0
- package/src/internal/mcp-endpoint.ts +13 -4
- package/src/internal/mcp-host.ts +77 -11
- package/src/internal/mcp-oauth-on-demand.ts +352 -0
- package/src/internal/mcp-oauth-persist.ts +127 -0
- package/src/internal/mcp-oauth.ts +17 -1
- package/src/internal/null-kv-storage.ts +74 -0
- package/src/internal/otel/collector.ts +30 -0
- package/src/internal/server.ts +159 -11
- package/src/internal/session-engine.ts +691 -57
- package/src/internal/session-run-log.ts +584 -0
- package/src/internal/sessions-client.ts +17 -8
- package/src/internal/storage-coordinator.ts +49 -9
- package/src/internal/storage-roles.ts +7 -0
- package/src/internal/stream-progress.ts +19 -0
- package/src/internal/tool-policy.ts +49 -9
- package/src/internal/trajectory.ts +10 -0
- package/src/internal/turn-outbox.ts +85 -0
- package/src/storage-backends/cursor-hosted.ts +13 -1
- package/src/storage-protocol.ts +10 -0
- package/src/storage.ts +12 -0
- package/src/tools.ts +12 -2
- package/src/types.ts +93 -8
- package/templates/agents-md/README.md +39 -0
- package/templates/agents-md/agent/agent.ts +8 -0
- package/templates/agents-md/agent/channels/github.ts +10 -0
- package/templates/agents-md/agent/channels/queue.ts +28 -0
- package/templates/agents-md/agent/channels/slack.ts +9 -0
- package/templates/agents-md/agent/instructions.md +39 -0
- package/templates/agents-md/agent/lib/collect.ts +439 -0
- package/templates/agents-md/agent/lib/config.ts +8 -0
- package/templates/agents-md/agent/lib/paths.ts +51 -0
- package/templates/agents-md/agent/schedules/weekly.ts +17 -0
- package/templates/agents-md/agent/tools/apply_agents.ts +226 -0
- package/templates/agents-md/evals/agents.eval.ts +135 -0
- package/templates/agents-md/evals/evals.config.ts +5 -0
- package/templates/agents-md/init.json +38 -0
- package/templates/agents-md/package.json +18 -0
- package/templates/agents-md/tsconfig.json +12 -0
- package/dist/docs/assets/chunks/@localSearchIndexroot.DFoGuETX.js +0 -1
- package/dist/docs/assets/guides_slack.md.C32HsdKk.js +0 -38
- package/dist/docs/assets/guides_slack.md.C32HsdKk.lean.js +0 -1
- package/dist/docs/assets/index.md.CI93Ltlb.js +0 -5
- package/dist/docs/assets/reference_sessions.md.D0mIh4KK.js +0 -1
- package/dist/docs/assets/troubleshooting.md.Ctv3T8C2.js +0 -1
- package/dist/docs/design/agsh.md +0 -406
- package/dist/playground/assets/index-B1DDvBeC.css +0 -1
- package/dist/playground/assets/index-Cx9CclK_.js +0 -88
- package/docs/design/agsh.md +0 -406
- /package/dist/docs/assets/{deployment.md.D9msOFOW.lean.js → deployment.md.MFPKqsqI.lean.js} +0 -0
- /package/dist/docs/assets/{index.md.CI93Ltlb.lean.js → index.md.CVeRUOeZ.lean.js} +0 -0
- /package/dist/docs/assets/{reference_agent-config.md.Cp_x38Nl.lean.js → reference_agent-config.md.BHeYMgme.lean.js} +0 -0
- /package/dist/docs/assets/{reference_connections.md.BH8Oc0D0.lean.js → reference_connections.md.DxldvyIB.lean.js} +0 -0
- /package/dist/docs/assets/{reference_http-api.md.D89k1mdm.lean.js → reference_http-api.md.BEJx9XVj.lean.js} +0 -0
- /package/dist/docs/assets/{reference_sessions.md.D0mIh4KK.lean.js → reference_sessions.md.NxFP_CAC.lean.js} +0 -0
- /package/dist/docs/assets/{troubleshooting.md.Ctv3T8C2.lean.js → troubleshooting.md.DCiPBhYs.lean.js} +0 -0
|
@@ -0,0 +1,584 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Durable hosted-execution run log on the framework file store. **v2 only.**
|
|
3
|
+
*
|
|
4
|
+
* One JSON document per factory session (`ses_…`), with per-execution
|
|
5
|
+
* entries inside. The later customer UI is session-scoped ("why did this
|
|
6
|
+
* session fail?") so a single GET is the read path; continuations are FIFO
|
|
7
|
+
* so last-write-wins merge is safe. Guest-local `hosted-execution.json` and
|
|
8
|
+
* factorydb `last_error` are lossy: the on-disk diag dies with the pod, and
|
|
9
|
+
* the session row only keeps the first 1024 characters of a generic HTTP
|
|
10
|
+
* 500.
|
|
11
|
+
*
|
|
12
|
+
* Process death: persist `running` at turn start so SIGKILL / OOM still
|
|
13
|
+
* leaves a durable leftover. `uncaughtException` / SIGTERM flush the same
|
|
14
|
+
* session key with `processDeath: true` and the real throw. Soft-fail on
|
|
15
|
+
* persist so a store outage never changes the hosted-execution HTTP reply.
|
|
16
|
+
*
|
|
17
|
+
* Keys: {@link storageKeys.sessionRun}.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import type { FileSink } from "../files.js";
|
|
21
|
+
import {
|
|
22
|
+
cursorFrameworkStoreSourceId,
|
|
23
|
+
cursorHostedFiles,
|
|
24
|
+
} from "../files-backends/cursor-hosted.js";
|
|
25
|
+
import { storageKeys } from "../storage-protocol.js";
|
|
26
|
+
import type { AgentProject } from "../types.js";
|
|
27
|
+
import { resolveApiKeySync } from "./cursor/credentials.js";
|
|
28
|
+
import { AGENT_SERVE_GENERATION_ENV_VAR } from "./cursor-relay-core.js";
|
|
29
|
+
import { describeError } from "./describe-error.js";
|
|
30
|
+
import type { HostedExecutionDiagAbortReason } from "./hosted-execution-diag.js";
|
|
31
|
+
import type { LogRingEntry } from "./log-ring.js";
|
|
32
|
+
|
|
33
|
+
export const SESSION_RUN_LOG_VERSION = 1;
|
|
34
|
+
/** Last N log-ring lines kept on each execution. */
|
|
35
|
+
export const SESSION_RUN_LOG_MAX_ENTRIES = 200;
|
|
36
|
+
/** Per-line cap so a runaway logger cannot blow the document. */
|
|
37
|
+
export const SESSION_RUN_LOG_MAX_LINE_CHARS = 4096;
|
|
38
|
+
/** Continuations are FIFO; keep a bounded history for the session UI. */
|
|
39
|
+
export const SESSION_RUN_LOG_MAX_EXECUTIONS = 20;
|
|
40
|
+
const MAX_ERROR_MESSAGE_CHARS = 4096;
|
|
41
|
+
const MAX_ERROR_STACK_CHARS = 16_384;
|
|
42
|
+
const MAX_DOCUMENT_CHARS = 512 * 1024;
|
|
43
|
+
/** Crash-handler flush must not block `process.exit`. */
|
|
44
|
+
export const SESSION_RUN_FATAL_FLUSH_TIMEOUT_MS = 2_000;
|
|
45
|
+
|
|
46
|
+
export type SessionRunAbortReason =
|
|
47
|
+
| HostedExecutionDiagAbortReason
|
|
48
|
+
| "process_exit"
|
|
49
|
+
| "uncaught_exception"
|
|
50
|
+
| "unhandled_rejection";
|
|
51
|
+
|
|
52
|
+
export type SessionRunLogError = {
|
|
53
|
+
name: string;
|
|
54
|
+
message: string;
|
|
55
|
+
stack?: string;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export type SessionRunExecution = {
|
|
59
|
+
executionId: string;
|
|
60
|
+
writtenAt: string;
|
|
61
|
+
sessionId: string;
|
|
62
|
+
turnStatus: string;
|
|
63
|
+
durationMs: number;
|
|
64
|
+
abortReason?: SessionRunAbortReason;
|
|
65
|
+
message?: string;
|
|
66
|
+
error?: SessionRunLogError;
|
|
67
|
+
/** True when this entry was flushed from a process-death handler. */
|
|
68
|
+
processDeath?: boolean;
|
|
69
|
+
logs: LogRingEntry[];
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Latest non-success execution, including leftover `running` after the
|
|
74
|
+
* process died without a terminal persist (SIGKILL / OOM). Undefined when
|
|
75
|
+
* the latest execution `turnStatus` is `finished`.
|
|
76
|
+
*/
|
|
77
|
+
export type SessionRunLastFailure = {
|
|
78
|
+
executionId: string;
|
|
79
|
+
writtenAt: string;
|
|
80
|
+
turnStatus: string;
|
|
81
|
+
abortReason?: SessionRunAbortReason;
|
|
82
|
+
message?: string;
|
|
83
|
+
error?: SessionRunLogError;
|
|
84
|
+
processDeath?: boolean;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
/** One document per factory session. The customer UI reads this object. */
|
|
88
|
+
export type SessionRunLogDocument = {
|
|
89
|
+
v: typeof SESSION_RUN_LOG_VERSION;
|
|
90
|
+
sessionPublicId: string;
|
|
91
|
+
updatedAt: string;
|
|
92
|
+
lastFailure?: SessionRunLastFailure;
|
|
93
|
+
executions: SessionRunExecution[];
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
/** Persist input: one execution upserted into the session document. */
|
|
97
|
+
export type SessionRunExecutionWrite = SessionRunExecution & {
|
|
98
|
+
sessionPublicId: string;
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
export interface SessionRunLogStore {
|
|
102
|
+
persist(write: SessionRunExecutionWrite): Promise<void>;
|
|
103
|
+
read(sessionPublicId: string): Promise<SessionRunLogDocument | undefined>;
|
|
104
|
+
/**
|
|
105
|
+
* Upgrade the in-flight `running` claim to a terminal process-death
|
|
106
|
+
* entry. No-op when no execution is active (already terminal, or never
|
|
107
|
+
* started). Soft-fail.
|
|
108
|
+
*/
|
|
109
|
+
flushProcessDeath(
|
|
110
|
+
reason: Extract<
|
|
111
|
+
SessionRunAbortReason,
|
|
112
|
+
"process_exit" | "uncaught_exception" | "unhandled_rejection"
|
|
113
|
+
>,
|
|
114
|
+
error?: unknown
|
|
115
|
+
): Promise<void>;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
type ActiveExecution = {
|
|
119
|
+
sessionPublicId: string;
|
|
120
|
+
executionId: string;
|
|
121
|
+
sessionId: string;
|
|
122
|
+
startedAt: number;
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
let fatalFlush: ((error: unknown) => Promise<void>) | undefined;
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Install the crash-handler flush used by `bin/agent-serve` on
|
|
129
|
+
* `uncaughtException`. One process, one active hosted serve.
|
|
130
|
+
*/
|
|
131
|
+
export function registerSessionRunFatalFlush(
|
|
132
|
+
flush: (error: unknown) => Promise<void>
|
|
133
|
+
): void {
|
|
134
|
+
fatalFlush = flush;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export function unregisterSessionRunFatalFlush(): void {
|
|
138
|
+
fatalFlush = undefined;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Await the registered crash flush, bounded so a hung store cannot prevent
|
|
143
|
+
* `process.exit`. Soft-fail.
|
|
144
|
+
*/
|
|
145
|
+
export async function flushSessionRunFatal(error: unknown): Promise<void> {
|
|
146
|
+
if (fatalFlush === undefined) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
await Promise.race([
|
|
150
|
+
fatalFlush(error).catch(() => undefined),
|
|
151
|
+
new Promise<void>((resolve) => {
|
|
152
|
+
setTimeout(resolve, SESSION_RUN_FATAL_FLUSH_TIMEOUT_MS);
|
|
153
|
+
}),
|
|
154
|
+
]);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function boundedText(value: string, max: number): string {
|
|
158
|
+
return value.length > max ? `${value.slice(0, max)}…` : value;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function boundedOptionalText(
|
|
162
|
+
value: string | undefined,
|
|
163
|
+
max: number
|
|
164
|
+
): string | undefined {
|
|
165
|
+
if (value === undefined || value.length === 0) {
|
|
166
|
+
return undefined;
|
|
167
|
+
}
|
|
168
|
+
return boundedText(value, max);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export function serializeSessionRunError(error: unknown): SessionRunLogError {
|
|
172
|
+
if (error instanceof Error) {
|
|
173
|
+
const stack = boundedOptionalText(error.stack, MAX_ERROR_STACK_CHARS);
|
|
174
|
+
return {
|
|
175
|
+
name: boundedText(error.name.length > 0 ? error.name : "Error", 128),
|
|
176
|
+
message: boundedText(error.message, MAX_ERROR_MESSAGE_CHARS),
|
|
177
|
+
...(stack === undefined ? {} : { stack }),
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
return {
|
|
181
|
+
name: "Error",
|
|
182
|
+
message: boundedText(String(error), MAX_ERROR_MESSAGE_CHARS),
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export function snapshotSessionRunLogs(
|
|
187
|
+
entries: readonly LogRingEntry[]
|
|
188
|
+
): LogRingEntry[] {
|
|
189
|
+
const tail = entries.slice(-SESSION_RUN_LOG_MAX_ENTRIES);
|
|
190
|
+
return tail.map((entry) => ({
|
|
191
|
+
index: entry.index,
|
|
192
|
+
at: entry.at,
|
|
193
|
+
line: boundedText(entry.line, SESSION_RUN_LOG_MAX_LINE_CHARS),
|
|
194
|
+
}));
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
198
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function decodeSinkBody(body: Uint8Array | { body: Uint8Array }): Uint8Array {
|
|
202
|
+
return body instanceof Uint8Array ? body : body.body;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function parseError(value: unknown): SessionRunLogError | undefined {
|
|
206
|
+
if (!isRecord(value)) {
|
|
207
|
+
return undefined;
|
|
208
|
+
}
|
|
209
|
+
const name = typeof value.name === "string" ? value.name : "";
|
|
210
|
+
const message = typeof value.message === "string" ? value.message : "";
|
|
211
|
+
const stack = typeof value.stack === "string" ? value.stack : undefined;
|
|
212
|
+
return {
|
|
213
|
+
name,
|
|
214
|
+
message,
|
|
215
|
+
...(stack === undefined ? {} : { stack }),
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function parseLogs(value: unknown): LogRingEntry[] {
|
|
220
|
+
if (!Array.isArray(value)) {
|
|
221
|
+
return [];
|
|
222
|
+
}
|
|
223
|
+
const logs: LogRingEntry[] = [];
|
|
224
|
+
for (const entry of value) {
|
|
225
|
+
if (!isRecord(entry)) {
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
if (
|
|
229
|
+
typeof entry.index !== "number" ||
|
|
230
|
+
typeof entry.at !== "string" ||
|
|
231
|
+
typeof entry.line !== "string"
|
|
232
|
+
) {
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
logs.push({ index: entry.index, at: entry.at, line: entry.line });
|
|
236
|
+
}
|
|
237
|
+
return logs;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function parseExecution(value: unknown): SessionRunExecution | undefined {
|
|
241
|
+
if (!isRecord(value)) {
|
|
242
|
+
return undefined;
|
|
243
|
+
}
|
|
244
|
+
const executionId =
|
|
245
|
+
typeof value.executionId === "string" ? value.executionId : undefined;
|
|
246
|
+
const writtenAt =
|
|
247
|
+
typeof value.writtenAt === "string" ? value.writtenAt : undefined;
|
|
248
|
+
const sessionId =
|
|
249
|
+
typeof value.sessionId === "string" ? value.sessionId : undefined;
|
|
250
|
+
const turnStatus =
|
|
251
|
+
typeof value.turnStatus === "string" ? value.turnStatus : undefined;
|
|
252
|
+
const durationMs =
|
|
253
|
+
typeof value.durationMs === "number" && Number.isFinite(value.durationMs)
|
|
254
|
+
? value.durationMs
|
|
255
|
+
: undefined;
|
|
256
|
+
if (
|
|
257
|
+
executionId === undefined ||
|
|
258
|
+
executionId.length === 0 ||
|
|
259
|
+
writtenAt === undefined ||
|
|
260
|
+
sessionId === undefined ||
|
|
261
|
+
turnStatus === undefined ||
|
|
262
|
+
turnStatus.length === 0 ||
|
|
263
|
+
durationMs === undefined ||
|
|
264
|
+
durationMs < 0
|
|
265
|
+
) {
|
|
266
|
+
return undefined;
|
|
267
|
+
}
|
|
268
|
+
const abortReason =
|
|
269
|
+
typeof value.abortReason === "string" ? value.abortReason : undefined;
|
|
270
|
+
const message = typeof value.message === "string" ? value.message : undefined;
|
|
271
|
+
const error = parseError(value.error);
|
|
272
|
+
return {
|
|
273
|
+
executionId,
|
|
274
|
+
writtenAt,
|
|
275
|
+
sessionId,
|
|
276
|
+
turnStatus,
|
|
277
|
+
durationMs,
|
|
278
|
+
...(abortReason === undefined
|
|
279
|
+
? {}
|
|
280
|
+
: { abortReason: abortReason as SessionRunAbortReason }),
|
|
281
|
+
...(message === undefined ? {} : { message }),
|
|
282
|
+
...(error === undefined ? {} : { error }),
|
|
283
|
+
...(value.processDeath === true ? { processDeath: true } : {}),
|
|
284
|
+
logs: parseLogs(value.logs),
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
export function lastFailureFromExecutions(
|
|
289
|
+
executions: readonly SessionRunExecution[]
|
|
290
|
+
): SessionRunLastFailure | undefined {
|
|
291
|
+
const latest = executions.at(-1);
|
|
292
|
+
if (latest === undefined || latest.turnStatus === "finished") {
|
|
293
|
+
return undefined;
|
|
294
|
+
}
|
|
295
|
+
return {
|
|
296
|
+
executionId: latest.executionId,
|
|
297
|
+
writtenAt: latest.writtenAt,
|
|
298
|
+
turnStatus: latest.turnStatus,
|
|
299
|
+
...(latest.abortReason === undefined
|
|
300
|
+
? {}
|
|
301
|
+
: { abortReason: latest.abortReason }),
|
|
302
|
+
...(latest.message === undefined ? {} : { message: latest.message }),
|
|
303
|
+
...(latest.error === undefined ? {} : { error: latest.error }),
|
|
304
|
+
...(latest.processDeath === true ? { processDeath: true } : {}),
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
function boundExecution(write: SessionRunExecution): SessionRunExecution {
|
|
309
|
+
const error =
|
|
310
|
+
write.error === undefined
|
|
311
|
+
? undefined
|
|
312
|
+
: {
|
|
313
|
+
name: boundedText(write.error.name, 128),
|
|
314
|
+
message: boundedText(write.error.message, MAX_ERROR_MESSAGE_CHARS),
|
|
315
|
+
...(write.error.stack === undefined
|
|
316
|
+
? {}
|
|
317
|
+
: {
|
|
318
|
+
stack: boundedText(write.error.stack, MAX_ERROR_STACK_CHARS),
|
|
319
|
+
}),
|
|
320
|
+
};
|
|
321
|
+
return {
|
|
322
|
+
executionId: write.executionId,
|
|
323
|
+
writtenAt: write.writtenAt,
|
|
324
|
+
sessionId: write.sessionId,
|
|
325
|
+
turnStatus: write.turnStatus,
|
|
326
|
+
durationMs: write.durationMs,
|
|
327
|
+
...(write.abortReason === undefined
|
|
328
|
+
? {}
|
|
329
|
+
: { abortReason: write.abortReason }),
|
|
330
|
+
...(boundedOptionalText(write.message, MAX_ERROR_MESSAGE_CHARS) ===
|
|
331
|
+
undefined
|
|
332
|
+
? {}
|
|
333
|
+
: {
|
|
334
|
+
message: boundedOptionalText(write.message, MAX_ERROR_MESSAGE_CHARS),
|
|
335
|
+
}),
|
|
336
|
+
...(error === undefined ? {} : { error }),
|
|
337
|
+
...(write.processDeath === true ? { processDeath: true } : {}),
|
|
338
|
+
logs: snapshotSessionRunLogs(write.logs),
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
function upsertExecution(
|
|
343
|
+
existing: readonly SessionRunExecution[],
|
|
344
|
+
next: SessionRunExecution
|
|
345
|
+
): SessionRunExecution[] {
|
|
346
|
+
const executions = existing.filter(
|
|
347
|
+
(entry) => entry.executionId !== next.executionId
|
|
348
|
+
);
|
|
349
|
+
executions.push(next);
|
|
350
|
+
executions.sort((a, b) => a.writtenAt.localeCompare(b.writtenAt));
|
|
351
|
+
return executions.slice(-SESSION_RUN_LOG_MAX_EXECUTIONS);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
function shrinkSessionDocument(
|
|
355
|
+
document: SessionRunLogDocument
|
|
356
|
+
): SessionRunLogDocument {
|
|
357
|
+
let executions = document.executions;
|
|
358
|
+
let next: SessionRunLogDocument = {
|
|
359
|
+
...document,
|
|
360
|
+
executions,
|
|
361
|
+
lastFailure: lastFailureFromExecutions(executions),
|
|
362
|
+
};
|
|
363
|
+
let serialized = JSON.stringify(next);
|
|
364
|
+
while (serialized.length > MAX_DOCUMENT_CHARS) {
|
|
365
|
+
const oldestWithLogs = executions.findIndex(
|
|
366
|
+
(entry) => entry.logs.length > 0
|
|
367
|
+
);
|
|
368
|
+
if (oldestWithLogs >= 0) {
|
|
369
|
+
const entry = executions[oldestWithLogs]!;
|
|
370
|
+
executions = executions.map((item, index) =>
|
|
371
|
+
index === oldestWithLogs
|
|
372
|
+
? {
|
|
373
|
+
...entry,
|
|
374
|
+
logs: entry.logs.slice(Math.ceil(entry.logs.length / 2)),
|
|
375
|
+
}
|
|
376
|
+
: item
|
|
377
|
+
);
|
|
378
|
+
} else if (executions.length > 1) {
|
|
379
|
+
executions = executions.slice(1);
|
|
380
|
+
} else {
|
|
381
|
+
break;
|
|
382
|
+
}
|
|
383
|
+
next = {
|
|
384
|
+
...document,
|
|
385
|
+
executions,
|
|
386
|
+
lastFailure: lastFailureFromExecutions(executions),
|
|
387
|
+
};
|
|
388
|
+
serialized = JSON.stringify(next);
|
|
389
|
+
}
|
|
390
|
+
return next;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
export function parseSessionRunLogDocument(
|
|
394
|
+
value: unknown
|
|
395
|
+
): SessionRunLogDocument | undefined {
|
|
396
|
+
if (!isRecord(value) || value.v !== SESSION_RUN_LOG_VERSION) {
|
|
397
|
+
return undefined;
|
|
398
|
+
}
|
|
399
|
+
const sessionPublicId =
|
|
400
|
+
typeof value.sessionPublicId === "string"
|
|
401
|
+
? value.sessionPublicId
|
|
402
|
+
: undefined;
|
|
403
|
+
const updatedAt =
|
|
404
|
+
typeof value.updatedAt === "string" ? value.updatedAt : undefined;
|
|
405
|
+
if (
|
|
406
|
+
sessionPublicId === undefined ||
|
|
407
|
+
sessionPublicId.length === 0 ||
|
|
408
|
+
updatedAt === undefined ||
|
|
409
|
+
!Array.isArray(value.executions)
|
|
410
|
+
) {
|
|
411
|
+
return undefined;
|
|
412
|
+
}
|
|
413
|
+
const executions: SessionRunExecution[] = [];
|
|
414
|
+
for (const entry of value.executions) {
|
|
415
|
+
const parsed = parseExecution(entry);
|
|
416
|
+
if (parsed !== undefined) {
|
|
417
|
+
executions.push(parsed);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
executions.sort((a, b) => a.writtenAt.localeCompare(b.writtenAt));
|
|
421
|
+
const lastFailure = lastFailureFromExecutions(executions);
|
|
422
|
+
return {
|
|
423
|
+
v: SESSION_RUN_LOG_VERSION,
|
|
424
|
+
sessionPublicId,
|
|
425
|
+
updatedAt,
|
|
426
|
+
...(lastFailure === undefined ? {} : { lastFailure }),
|
|
427
|
+
executions,
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
export function createSessionRunLogStore(input: {
|
|
432
|
+
sink: FileSink;
|
|
433
|
+
agentName: string;
|
|
434
|
+
logger?: (line: string) => void;
|
|
435
|
+
snapshotLogs?: () => readonly LogRingEntry[];
|
|
436
|
+
}): SessionRunLogStore {
|
|
437
|
+
const { sink, agentName } = input;
|
|
438
|
+
const logger = input.logger ?? (() => {});
|
|
439
|
+
let active: ActiveExecution | undefined;
|
|
440
|
+
|
|
441
|
+
const readDocument = async (
|
|
442
|
+
sessionPublicId: string
|
|
443
|
+
): Promise<SessionRunLogDocument | undefined> => {
|
|
444
|
+
const key = storageKeys.sessionRun(agentName, sessionPublicId);
|
|
445
|
+
const body = await sink.get(key);
|
|
446
|
+
if (body === undefined) {
|
|
447
|
+
return undefined;
|
|
448
|
+
}
|
|
449
|
+
try {
|
|
450
|
+
return parseSessionRunLogDocument(
|
|
451
|
+
JSON.parse(new TextDecoder().decode(decodeSinkBody(body)))
|
|
452
|
+
);
|
|
453
|
+
} catch (error) {
|
|
454
|
+
logger(
|
|
455
|
+
`[agent-sdk] session-run log: skip unreadable ${key} (${describeError(error)})`
|
|
456
|
+
);
|
|
457
|
+
return undefined;
|
|
458
|
+
}
|
|
459
|
+
};
|
|
460
|
+
|
|
461
|
+
const persistWrite = async (
|
|
462
|
+
write: SessionRunExecutionWrite
|
|
463
|
+
): Promise<void> => {
|
|
464
|
+
const fitted = boundExecution(write);
|
|
465
|
+
let existing: SessionRunLogDocument | undefined;
|
|
466
|
+
try {
|
|
467
|
+
existing = await readDocument(write.sessionPublicId);
|
|
468
|
+
} catch (error) {
|
|
469
|
+
logger(
|
|
470
|
+
`[agent-sdk] session-run log: persist failed for ${fitted.executionId} (${describeError(error)})`
|
|
471
|
+
);
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
474
|
+
const executions = upsertExecution(existing?.executions ?? [], fitted);
|
|
475
|
+
const document = shrinkSessionDocument({
|
|
476
|
+
v: SESSION_RUN_LOG_VERSION,
|
|
477
|
+
sessionPublicId: write.sessionPublicId,
|
|
478
|
+
updatedAt: fitted.writtenAt,
|
|
479
|
+
executions,
|
|
480
|
+
});
|
|
481
|
+
const key = storageKeys.sessionRun(agentName, document.sessionPublicId);
|
|
482
|
+
try {
|
|
483
|
+
await sink.put(key, new TextEncoder().encode(JSON.stringify(document)));
|
|
484
|
+
} catch (error) {
|
|
485
|
+
logger(
|
|
486
|
+
`[agent-sdk] session-run log: persist failed for ${fitted.executionId} (${describeError(error)})`
|
|
487
|
+
);
|
|
488
|
+
return;
|
|
489
|
+
}
|
|
490
|
+
if (fitted.turnStatus === "running") {
|
|
491
|
+
active = {
|
|
492
|
+
sessionPublicId: write.sessionPublicId,
|
|
493
|
+
executionId: fitted.executionId,
|
|
494
|
+
sessionId: fitted.sessionId,
|
|
495
|
+
startedAt: Date.now(),
|
|
496
|
+
};
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
499
|
+
if (active?.executionId === fitted.executionId) {
|
|
500
|
+
active = undefined;
|
|
501
|
+
}
|
|
502
|
+
};
|
|
503
|
+
|
|
504
|
+
return {
|
|
505
|
+
persist: persistWrite,
|
|
506
|
+
|
|
507
|
+
async read(sessionPublicId) {
|
|
508
|
+
try {
|
|
509
|
+
return await readDocument(sessionPublicId);
|
|
510
|
+
} catch (error) {
|
|
511
|
+
logger(
|
|
512
|
+
`[agent-sdk] session-run log: read failed for ${sessionPublicId} (${describeError(error)})`
|
|
513
|
+
);
|
|
514
|
+
return undefined;
|
|
515
|
+
}
|
|
516
|
+
},
|
|
517
|
+
|
|
518
|
+
async flushProcessDeath(reason, error) {
|
|
519
|
+
if (active === undefined) {
|
|
520
|
+
return;
|
|
521
|
+
}
|
|
522
|
+
const current = active;
|
|
523
|
+
const serialized =
|
|
524
|
+
error === undefined ? undefined : serializeSessionRunError(error);
|
|
525
|
+
const message =
|
|
526
|
+
error instanceof Error
|
|
527
|
+
? error.message
|
|
528
|
+
: error !== undefined
|
|
529
|
+
? String(error)
|
|
530
|
+
: "process died during hosted execution";
|
|
531
|
+
await persistWrite({
|
|
532
|
+
sessionPublicId: current.sessionPublicId,
|
|
533
|
+
executionId: current.executionId,
|
|
534
|
+
writtenAt: new Date().toISOString(),
|
|
535
|
+
sessionId: current.sessionId,
|
|
536
|
+
turnStatus: "error",
|
|
537
|
+
durationMs: Math.max(0, Date.now() - current.startedAt),
|
|
538
|
+
abortReason: reason,
|
|
539
|
+
processDeath: true,
|
|
540
|
+
message,
|
|
541
|
+
...(serialized === undefined ? {} : { error: serialized }),
|
|
542
|
+
logs: snapshotSessionRunLogs(input.snapshotLogs?.() ?? []),
|
|
543
|
+
});
|
|
544
|
+
},
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
/**
|
|
549
|
+
* Same selection as the conversation mirror: architecture-v2 hosted
|
|
550
|
+
* engines with a provisioned framework file store. Self-hosted and v1
|
|
551
|
+
* stay on local disk / today's behavior. This is the only path that
|
|
552
|
+
* installs the session-run log — v1 never writes these documents.
|
|
553
|
+
*/
|
|
554
|
+
export function selectSessionRunLogStore(input: {
|
|
555
|
+
project: AgentProject;
|
|
556
|
+
logger?: (line: string) => void;
|
|
557
|
+
env?: Record<string, string | undefined>;
|
|
558
|
+
snapshotLogs?: () => readonly LogRingEntry[];
|
|
559
|
+
}): SessionRunLogStore | undefined {
|
|
560
|
+
if (input.project.agent.architecture !== "v2") {
|
|
561
|
+
return undefined;
|
|
562
|
+
}
|
|
563
|
+
const env = input.env ?? process.env;
|
|
564
|
+
const frameworkStoreId = cursorFrameworkStoreSourceId(
|
|
565
|
+
env as NodeJS.ProcessEnv
|
|
566
|
+
);
|
|
567
|
+
if (
|
|
568
|
+
env[AGENT_SERVE_GENERATION_ENV_VAR] === undefined ||
|
|
569
|
+
frameworkStoreId === undefined
|
|
570
|
+
) {
|
|
571
|
+
return undefined;
|
|
572
|
+
}
|
|
573
|
+
return createSessionRunLogStore({
|
|
574
|
+
sink: cursorHostedFiles({
|
|
575
|
+
storeSourceId: frameworkStoreId,
|
|
576
|
+
resolveApiKey: () => resolveApiKeySync()?.apiKey,
|
|
577
|
+
}),
|
|
578
|
+
agentName: input.project.name,
|
|
579
|
+
logger: input.logger,
|
|
580
|
+
...(input.snapshotLogs === undefined
|
|
581
|
+
? {}
|
|
582
|
+
: { snapshotLogs: input.snapshotLogs }),
|
|
583
|
+
});
|
|
584
|
+
}
|
|
@@ -18,24 +18,32 @@ export interface ListedSessions {
|
|
|
18
18
|
source?: SessionListSource;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
export
|
|
21
|
+
export interface ListSessionsArgs {
|
|
22
22
|
baseUrl: string;
|
|
23
23
|
auth?: RequestAuth;
|
|
24
24
|
fetchImpl?: typeof fetch;
|
|
25
|
-
|
|
25
|
+
/**
|
|
26
|
+
* Ask for only the newest visible session (`?latest=1`). The server
|
|
27
|
+
* answers from memory where it can instead of scanning durable storage.
|
|
28
|
+
*/
|
|
29
|
+
latest?: boolean;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export async function listSessions(
|
|
33
|
+
args: ListSessionsArgs
|
|
34
|
+
): Promise<SessionSummary[]> {
|
|
26
35
|
return (await listSessionsWithSource(args)).sessions;
|
|
27
36
|
}
|
|
28
37
|
|
|
29
|
-
export async function listSessionsWithSource(
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
fetchImpl?: typeof fetch;
|
|
33
|
-
}): Promise<ListedSessions> {
|
|
38
|
+
export async function listSessionsWithSource(
|
|
39
|
+
args: ListSessionsArgs
|
|
40
|
+
): Promise<ListedSessions> {
|
|
34
41
|
const baseUrl = args.baseUrl.replace(/\/$/, "");
|
|
35
42
|
const fetchImpl = args.fetchImpl ?? fetch;
|
|
43
|
+
const query = args.latest === true ? "?latest=1" : "";
|
|
36
44
|
let resp: Response;
|
|
37
45
|
try {
|
|
38
|
-
resp = await fetchImpl(`${baseUrl}/v1/sessions`, {
|
|
46
|
+
resp = await fetchImpl(`${baseUrl}/v1/sessions${query}`, {
|
|
39
47
|
headers: mergeRequestHeaders(args.auth),
|
|
40
48
|
});
|
|
41
49
|
} catch (error) {
|
|
@@ -168,6 +176,7 @@ function parseSessionSummary(value: unknown): SessionSummary | undefined {
|
|
|
168
176
|
queued: typeof row.queued === "boolean" ? row.queued : undefined,
|
|
169
177
|
createdAt: typeof row.createdAt === "string" ? row.createdAt : "",
|
|
170
178
|
updatedAt: typeof row.updatedAt === "string" ? row.updatedAt : "",
|
|
179
|
+
dryRun: row.dryRun === true ? true : undefined,
|
|
171
180
|
continuationToken,
|
|
172
181
|
externalUrl:
|
|
173
182
|
typeof row.externalUrl === "string" ? row.externalUrl : undefined,
|