@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
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
resolveStoragePolicy,
|
|
31
31
|
type StorageContext,
|
|
32
32
|
type StorageDefinition,
|
|
33
|
+
type StorageEntry,
|
|
33
34
|
storageKeys,
|
|
34
35
|
} from "../storage.js";
|
|
35
36
|
import { isCursorHostedStorage } from "../storage-backends/cursor-hosted.js";
|
|
@@ -37,6 +38,7 @@ import type { JsonValue, SessionEvent, SessionRecord } from "../types.js";
|
|
|
37
38
|
import type { ABSnapshot } from "./ab-snapshot.js";
|
|
38
39
|
import { describeError } from "./describe-error.js";
|
|
39
40
|
import type { EvalRunStorage } from "./eval-run-store.js";
|
|
41
|
+
import { isAuthorKvUnsupported } from "./null-kv-storage.js";
|
|
40
42
|
import type {
|
|
41
43
|
AuthorKvStore,
|
|
42
44
|
EvalAbStore,
|
|
@@ -97,6 +99,18 @@ interface SessionBuffer {
|
|
|
97
99
|
debounceTimer?: ReturnType<typeof setTimeout>;
|
|
98
100
|
}
|
|
99
101
|
|
|
102
|
+
/** Session records out of raw sink entries; rows without a usable id are dropped. */
|
|
103
|
+
function sessionRecordsOf(entries: readonly StorageEntry[]): SessionRecord[] {
|
|
104
|
+
return entries
|
|
105
|
+
.map((entry) => entry.value as unknown as SessionRecord)
|
|
106
|
+
.filter(
|
|
107
|
+
(record) =>
|
|
108
|
+
record != null &&
|
|
109
|
+
typeof record.sessionId === "string" &&
|
|
110
|
+
record.sessionId !== ""
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
100
114
|
export class StorageCoordinator
|
|
101
115
|
implements FrameworkSessionStore, AuthorKvStore, EvalAbStore
|
|
102
116
|
{
|
|
@@ -315,14 +329,31 @@ export class StorageCoordinator
|
|
|
315
329
|
if (!Array.isArray(entries)) {
|
|
316
330
|
throw new Error("storage list returned a non-array");
|
|
317
331
|
}
|
|
318
|
-
return entries
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
332
|
+
return sessionRecordsOf(entries);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Newest-written session records from the sink (`GET /v1/sessions?latest=1`
|
|
337
|
+
* on a host whose local store has nothing for the caller). Same error
|
|
338
|
+
* posture as {@link listSessionsFromSink}; `undefined` when the sink
|
|
339
|
+
* cannot order by write time, so the caller falls back to the full list.
|
|
340
|
+
*/
|
|
341
|
+
async listNewestSessionsFromSink(
|
|
342
|
+
limit: number
|
|
343
|
+
): Promise<SessionRecord[] | undefined> {
|
|
344
|
+
const listNewest = this.definition.listNewest;
|
|
345
|
+
if (listNewest === undefined) {
|
|
346
|
+
return undefined;
|
|
347
|
+
}
|
|
348
|
+
const entries = await listNewest(
|
|
349
|
+
storageKeys.sessionPrefix(this.agentName),
|
|
350
|
+
limit,
|
|
351
|
+
this.context("restore")
|
|
352
|
+
);
|
|
353
|
+
if (!Array.isArray(entries)) {
|
|
354
|
+
throw new Error("storage listNewest returned a non-array");
|
|
355
|
+
}
|
|
356
|
+
return sessionRecordsOf(entries);
|
|
326
357
|
}
|
|
327
358
|
|
|
328
359
|
/**
|
|
@@ -438,9 +469,18 @@ export class StorageCoordinator
|
|
|
438
469
|
/**
|
|
439
470
|
* Whether the sink can serve awaited author reads/writes (`get` is
|
|
440
471
|
* required — `put` is always present on {@link StorageConfig}).
|
|
472
|
+
*
|
|
473
|
+
* A sink may keep `get` for framework session state while refusing author
|
|
474
|
+
* KV: hosted v2 reads sessions from the framework file store but has no
|
|
475
|
+
* working KV backend, and author handlers that cannot read their own
|
|
476
|
+
* writes back are better served by the local-disk fallback than by a sink
|
|
477
|
+
* that accepts every write and forgets it.
|
|
441
478
|
*/
|
|
442
479
|
get supportsAuthorKv(): boolean {
|
|
443
|
-
return
|
|
480
|
+
return (
|
|
481
|
+
this.definition.get !== undefined &&
|
|
482
|
+
!isAuthorKvUnsupported(this.definition)
|
|
483
|
+
);
|
|
444
484
|
}
|
|
445
485
|
|
|
446
486
|
/**
|
|
@@ -54,6 +54,13 @@ export interface FrameworkSessionStore {
|
|
|
54
54
|
|
|
55
55
|
listSessions(): Promise<SessionRecord[]>;
|
|
56
56
|
listSessionsFromSink(): Promise<SessionRecord[]>;
|
|
57
|
+
/**
|
|
58
|
+
* The `limit` most recently written session records from the sink,
|
|
59
|
+
* newest first; `undefined` when the sink has no `listNewest`.
|
|
60
|
+
*/
|
|
61
|
+
listNewestSessionsFromSink(
|
|
62
|
+
limit: number
|
|
63
|
+
): Promise<SessionRecord[] | undefined>;
|
|
57
64
|
listSessionEvents(sessionId: string): Promise<SessionEvent[]>;
|
|
58
65
|
getSessionById(sessionId: string): Promise<SessionRecord | undefined>;
|
|
59
66
|
getSessionByContinuation(
|
|
@@ -154,6 +154,25 @@ export function createStreamProgress(options?: {
|
|
|
154
154
|
);
|
|
155
155
|
break;
|
|
156
156
|
}
|
|
157
|
+
case "action.auth_requested": {
|
|
158
|
+
closeAssistant();
|
|
159
|
+
write(
|
|
160
|
+
` ${c.yellow("⏸")} ${c.bold(event.data.connection)} ${c.dim(
|
|
161
|
+
"awaiting MCP authorization"
|
|
162
|
+
)}\n`
|
|
163
|
+
);
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
166
|
+
case "action.auth_resolved": {
|
|
167
|
+
const mark =
|
|
168
|
+
event.data.decision === "approve" ? c.green("✓") : c.red("✗");
|
|
169
|
+
write(
|
|
170
|
+
` ${mark} ${c.bold(event.data.connection)} ${c.dim(
|
|
171
|
+
event.data.decision === "approve" ? "connected" : "denied"
|
|
172
|
+
)}\n`
|
|
173
|
+
);
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
157
176
|
case "action.result": {
|
|
158
177
|
if (
|
|
159
178
|
event.data.toolName === "task" &&
|
|
@@ -10,11 +10,13 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import type {
|
|
13
|
+
DiscoveredTool,
|
|
13
14
|
McpToolAnnotations,
|
|
14
15
|
ToolEffect,
|
|
15
16
|
ToolEffectDeclaration,
|
|
16
17
|
ToolExecuteResult,
|
|
17
18
|
} from "../types.js";
|
|
19
|
+
import { timeArgViolation } from "./as-of.js";
|
|
18
20
|
|
|
19
21
|
/** What the host does with one tool call. */
|
|
20
22
|
export type ToolDecision =
|
|
@@ -23,12 +25,17 @@ export type ToolDecision =
|
|
|
23
25
|
/** Do not run it; return this to the model instead. */
|
|
24
26
|
| { kind: "answer"; result: ToolExecuteResult }
|
|
25
27
|
/**
|
|
26
|
-
* Do not run it; fail the call with this message. Only
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
28
|
+
* Do not run it; fail the call with this message. Only produced in a dry
|
|
29
|
+
* run, for an MCP tool nothing classifies: stubbing it would let the run
|
|
30
|
+
* reach a confident conclusion from no data, and running it could leak a
|
|
31
|
+
* real write — refusing is the one failure that is loud.
|
|
30
32
|
*/
|
|
31
|
-
| { kind: "refuse"; message: string }
|
|
33
|
+
| { kind: "refuse"; message: string }
|
|
34
|
+
/**
|
|
35
|
+
* Do not run it; the `asOf` session was asked to read without absolute
|
|
36
|
+
* bounds, which would read the present.
|
|
37
|
+
*/
|
|
38
|
+
| { kind: "unbounded"; message: string };
|
|
32
39
|
|
|
33
40
|
/** What a policy decision needs to know about the call. */
|
|
34
41
|
export interface ToolCallFacts {
|
|
@@ -47,12 +54,16 @@ export interface ToolCallFacts {
|
|
|
47
54
|
/** What a stubbed write should answer with, if the tool supplied one. */
|
|
48
55
|
dryRunResult?: ToolExecuteResult | ((input: never) => ToolExecuteResult);
|
|
49
56
|
/**
|
|
50
|
-
* Validated input, as the tool body would receive it.
|
|
51
|
-
*
|
|
52
|
-
* with
|
|
53
|
-
* can omit it.
|
|
57
|
+
* Validated input, as the tool body would receive it. Read by a per-call
|
|
58
|
+
* `effect` predicate, a `dryRunResult` function, and the {@link timeArgs}
|
|
59
|
+
* bound check, so a caller with none of those — a bridged MCP tool, which
|
|
60
|
+
* carries no declaration at all — can omit it.
|
|
54
61
|
*/
|
|
55
62
|
input?: unknown;
|
|
63
|
+
/** The session's frozen instant, when it has one. */
|
|
64
|
+
asOf?: string;
|
|
65
|
+
/** The tool's declared time-bound argument names, if it made them. */
|
|
66
|
+
timeArgs?: readonly string[];
|
|
56
67
|
}
|
|
57
68
|
|
|
58
69
|
/**
|
|
@@ -111,6 +122,23 @@ export function classifyAnnotationsEffect(
|
|
|
111
122
|
return undefined;
|
|
112
123
|
}
|
|
113
124
|
|
|
125
|
+
/**
|
|
126
|
+
* The effect of one direct call on a discovered tool, the same way
|
|
127
|
+
* {@link decideToolCall} reads it: the authored declaration when there is
|
|
128
|
+
* one (possibly per input), else the MCP server's own annotations for an
|
|
129
|
+
* advertised passthrough. `undefined` is an advertised tool nothing
|
|
130
|
+
* classifies; callers gating on "read" treat it as a write.
|
|
131
|
+
*/
|
|
132
|
+
export function directCallEffect(
|
|
133
|
+
tool: Pick<DiscoveredTool, "advertised" | "annotations" | "definition">,
|
|
134
|
+
input: unknown
|
|
135
|
+
): ToolEffect | undefined {
|
|
136
|
+
if (tool.definition.effect === undefined && tool.advertised === true) {
|
|
137
|
+
return classifyAnnotationsEffect(tool.annotations);
|
|
138
|
+
}
|
|
139
|
+
return resolveEffect(tool.definition.effect, input);
|
|
140
|
+
}
|
|
141
|
+
|
|
114
142
|
/**
|
|
115
143
|
* What a dry run answers when nothing classifies an MCP tool. Deliberately
|
|
116
144
|
* reads as a strict API rather than disclosing the session's posture (see
|
|
@@ -129,6 +157,18 @@ function unclassifiedRefusal(toolName: string): string {
|
|
|
129
157
|
|
|
130
158
|
/** Decide what to do with one tool call. Pure; no I/O, no session state. */
|
|
131
159
|
export function decideToolCall(facts: ToolCallFacts): ToolDecision {
|
|
160
|
+
// Before the dry-run split: a frozen session bounds its reads whether or
|
|
161
|
+
// not its writes are stubbed.
|
|
162
|
+
if (
|
|
163
|
+
facts.asOf !== undefined &&
|
|
164
|
+
facts.timeArgs !== undefined &&
|
|
165
|
+
facts.timeArgs.length > 0
|
|
166
|
+
) {
|
|
167
|
+
const violation = timeArgViolation(facts.input, facts.timeArgs, facts.asOf);
|
|
168
|
+
if (violation !== undefined) {
|
|
169
|
+
return { kind: "unbounded", message: violation };
|
|
170
|
+
}
|
|
171
|
+
}
|
|
132
172
|
if (!facts.dryRun) {
|
|
133
173
|
return { kind: "run" };
|
|
134
174
|
}
|
|
@@ -170,6 +170,16 @@ export function buildTrajectory(events: SessionEvent[]): Trajectory {
|
|
|
170
170
|
}
|
|
171
171
|
break;
|
|
172
172
|
}
|
|
173
|
+
case "action.auth_requested": {
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
case "action.auth_resolved": {
|
|
177
|
+
const pending = pendingCalls.get(event.data.callId);
|
|
178
|
+
if (pending !== undefined) {
|
|
179
|
+
pending.approvalDecision = event.data.decision;
|
|
180
|
+
}
|
|
181
|
+
break;
|
|
182
|
+
}
|
|
173
183
|
case "action.result": {
|
|
174
184
|
const pending = pendingCalls.get(event.data.callId);
|
|
175
185
|
if (pending !== undefined) {
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hand-off of a message to the server that holds the session's turn lease.
|
|
3
|
+
*
|
|
4
|
+
* Blue/green replicas share a state root but not a process, and only the
|
|
5
|
+
* lease holder can admit a message to its running turn. A server that
|
|
6
|
+
* receives a message for a turn it does not own drops it here, under
|
|
7
|
+
* `<stateRoot>/outbox/<sessionId>`; the holder takes everything out while its
|
|
8
|
+
* turn runs and once more after releasing the lease. Local messages never
|
|
9
|
+
* touch this.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { randomUUID } from "node:crypto";
|
|
13
|
+
import {
|
|
14
|
+
mkdir,
|
|
15
|
+
readdir,
|
|
16
|
+
readFile,
|
|
17
|
+
rename,
|
|
18
|
+
rm,
|
|
19
|
+
unlink,
|
|
20
|
+
writeFile,
|
|
21
|
+
} from "node:fs/promises";
|
|
22
|
+
import { join } from "node:path";
|
|
23
|
+
|
|
24
|
+
export interface OutboxItem<T> {
|
|
25
|
+
message: string;
|
|
26
|
+
options: T;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function safeKey(sessionId: string): string {
|
|
30
|
+
const sanitized = sessionId
|
|
31
|
+
.trim()
|
|
32
|
+
.replace(/[^a-zA-Z0-9._-]+/g, "_")
|
|
33
|
+
.replace(/^\.+/, "")
|
|
34
|
+
.replace(/\.+/g, "_")
|
|
35
|
+
.slice(0, 180);
|
|
36
|
+
return sanitized === "" ? "_empty" : sanitized;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export class TurnOutbox<T> {
|
|
40
|
+
private readonly rootDir: string;
|
|
41
|
+
|
|
42
|
+
constructor(rootDir: string) {
|
|
43
|
+
this.rootDir = rootDir;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
private dir(sessionId: string): string {
|
|
47
|
+
return join(this.rootDir, safeKey(sessionId));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async post(sessionId: string, item: OutboxItem<T>): Promise<void> {
|
|
51
|
+
const dir = this.dir(sessionId);
|
|
52
|
+
await mkdir(dir, { recursive: true });
|
|
53
|
+
// Timestamp first so a listing sorts in arrival order.
|
|
54
|
+
const path = join(dir, `${Date.now()}-${randomUUID()}.json`);
|
|
55
|
+
await writeFile(`${path}.tmp`, `${JSON.stringify(item)}\n`, "utf8");
|
|
56
|
+
await rename(`${path}.tmp`, path);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** Remove and return everything posted, in arrival order. */
|
|
60
|
+
async takeAll(sessionId: string): Promise<OutboxItem<T>[]> {
|
|
61
|
+
const dir = this.dir(sessionId);
|
|
62
|
+
let names: string[];
|
|
63
|
+
try {
|
|
64
|
+
names = await readdir(dir);
|
|
65
|
+
} catch {
|
|
66
|
+
return [];
|
|
67
|
+
}
|
|
68
|
+
const items: OutboxItem<T>[] = [];
|
|
69
|
+
for (const name of names.filter((n) => n.endsWith(".json")).sort()) {
|
|
70
|
+
const path = join(dir, name);
|
|
71
|
+
try {
|
|
72
|
+
const raw = await readFile(path, "utf8");
|
|
73
|
+
await unlink(path);
|
|
74
|
+
items.push(JSON.parse(raw) as OutboxItem<T>);
|
|
75
|
+
} catch {
|
|
76
|
+
// Taken by the holder between readdir and here.
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return items;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async clear(sessionId: string): Promise<void> {
|
|
83
|
+
await rm(this.dir(sessionId), { recursive: true, force: true });
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -108,7 +108,7 @@ export function isCursorHostedStorage(value: unknown): boolean {
|
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
type CursorHostedStorageMethods = Required<
|
|
111
|
-
Pick<StorageConfig, "put" | "get" | "delete" | "list">
|
|
111
|
+
Pick<StorageConfig, "put" | "get" | "delete" | "list" | "listNewest">
|
|
112
112
|
> & {
|
|
113
113
|
readonly [CURSOR_HOSTED_STORAGE]: true;
|
|
114
114
|
cas: StorageCasTable;
|
|
@@ -284,6 +284,18 @@ export function cursorHostedStorage(
|
|
|
284
284
|
}>(options, "/internal/agent-serve/storage/kv/list", { prefix });
|
|
285
285
|
return result.entries;
|
|
286
286
|
},
|
|
287
|
+
async listNewest(prefix, limit): Promise<StorageEntry[]> {
|
|
288
|
+
// Same route; the server orders the prefix range by row write time
|
|
289
|
+
// and caps the rows instead of returning the whole range.
|
|
290
|
+
const result = await storageRpc<{
|
|
291
|
+
entries: Array<{ key: string; value: JsonValue }>;
|
|
292
|
+
}>(options, "/internal/agent-serve/storage/kv/list", {
|
|
293
|
+
prefix,
|
|
294
|
+
limit,
|
|
295
|
+
newestFirst: true,
|
|
296
|
+
});
|
|
297
|
+
return result.entries;
|
|
298
|
+
},
|
|
287
299
|
// Conditional writes over the same proxy (server routes: see the CAS
|
|
288
300
|
// wire-protocol block above). The proxy scopes rows from the service
|
|
289
301
|
// account, so ctx is not part of the wire contract.
|
package/src/storage-protocol.ts
CHANGED
|
@@ -38,6 +38,7 @@ const DURABLE_SESSION_RECORD_KEY_RE =
|
|
|
38
38
|
* | --- | --- |
|
|
39
39
|
* | `agentkit/v1/{agent}/session/{sessionId}` | `SessionRecord` |
|
|
40
40
|
* | `agentkit/v1/{agent}/session-events/{sessionId}/{index}` | `SessionEvent[]` chunk (index = first event's index, zero-padded) |
|
|
41
|
+
* | `agentkit/v1/{agent}/session-runs/{sessionPublicId}` | One session-level hosted-execution log (executions[] + lastFailure) |
|
|
41
42
|
* | `agentkit/v1/{agent}/continuation/{channelId}/{token}` | `{ sessionId }` |
|
|
42
43
|
* | `agentkit/v1/{agent}/kv/{key}` | Author JSON via `HostContext.kv` |
|
|
43
44
|
*
|
|
@@ -59,6 +60,15 @@ export const storageKeys = {
|
|
|
59
60
|
`${STORAGE_KEY_ROOT}/${agent}/session-events/${sessionId}/${String(firstIndex).padStart(8, "0")}`,
|
|
60
61
|
sessionEventsPrefix: (agent: string, sessionId: string): string =>
|
|
61
62
|
`${STORAGE_KEY_ROOT}/${agent}/session-events/${sessionId}/`,
|
|
63
|
+
/**
|
|
64
|
+
* One session-level hosted-execution log (v2 only). `sessionPublicId` is
|
|
65
|
+
* the factory `ses_…` so a throw that never minted a July session still
|
|
66
|
+
* lands under a stable key. Per-execution rows live inside the document.
|
|
67
|
+
*/
|
|
68
|
+
sessionRun: (agent: string, sessionPublicId: string): string =>
|
|
69
|
+
`${STORAGE_KEY_ROOT}/${agent}/session-runs/${keySegment(sessionPublicId)}`,
|
|
70
|
+
sessionRunsPrefix: (agent: string): string =>
|
|
71
|
+
`${STORAGE_KEY_ROOT}/${agent}/session-runs/`,
|
|
62
72
|
continuation: (
|
|
63
73
|
agent: string,
|
|
64
74
|
channelId: string,
|
package/src/storage.ts
CHANGED
|
@@ -275,6 +275,18 @@ export interface StorageConfig {
|
|
|
275
275
|
prefix: string,
|
|
276
276
|
ctx: StorageContext
|
|
277
277
|
): StorageEntry[] | Promise<StorageEntry[]>;
|
|
278
|
+
/**
|
|
279
|
+
* The `limit` most recently **written** entries under a prefix, newest
|
|
280
|
+
* first. Optional — a backend-native shortcut for `GET /v1/sessions?latest=1`
|
|
281
|
+
* on a replacement host, where the alternative is listing every session
|
|
282
|
+
* row. Without it the engine falls back to `list`. Write order is an
|
|
283
|
+
* approximation of the records' own `updatedAt`; callers tolerate that.
|
|
284
|
+
*/
|
|
285
|
+
listNewest?(
|
|
286
|
+
prefix: string,
|
|
287
|
+
limit: number,
|
|
288
|
+
ctx: StorageContext
|
|
289
|
+
): StorageEntry[] | Promise<StorageEntry[]>;
|
|
278
290
|
}
|
|
279
291
|
|
|
280
292
|
export type StorageDefinition = StorageConfig & {
|
package/src/tools.ts
CHANGED
|
@@ -99,6 +99,15 @@ type ServerToolConfig<TSchema> = {
|
|
|
99
99
|
* write, so a dry-run session answers it instead of running it.
|
|
100
100
|
*/
|
|
101
101
|
effect?: ToolEffectDeclaration<ToolInput<TSchema>>;
|
|
102
|
+
/**
|
|
103
|
+
* Input properties carrying time bounds. In an `asOf` session each named
|
|
104
|
+
* argument must be an absolute ISO-8601 instant with a timezone, no later
|
|
105
|
+
* than the frozen instant; a call that omits one, or supplies a relative
|
|
106
|
+
* or later value, is refused so the model retries with absolute bounds.
|
|
107
|
+
* Names must exist in {@link inputSchema} or the frozen session refuses to
|
|
108
|
+
* start. Ignored without `asOf`.
|
|
109
|
+
*/
|
|
110
|
+
timeArgs?: readonly string[];
|
|
102
111
|
/** What a `"write"` tool returns in a dry-run session. */
|
|
103
112
|
dryRunResult?:
|
|
104
113
|
| ToolExecuteResult
|
|
@@ -126,10 +135,11 @@ type AgentToolConfig<TSchema> = {
|
|
|
126
135
|
needsApproval?: never;
|
|
127
136
|
/**
|
|
128
137
|
* Agent tools run inside the harness, not through the host's tool path, so
|
|
129
|
-
* a dry run cannot answer them
|
|
130
|
-
*
|
|
138
|
+
* a dry run cannot answer them and an `asOf` session cannot bound them.
|
|
139
|
+
* Classify the work as a server tool if it needs either.
|
|
131
140
|
*/
|
|
132
141
|
effect?: never;
|
|
142
|
+
timeArgs?: never;
|
|
133
143
|
dryRunResult?: never;
|
|
134
144
|
};
|
|
135
145
|
|
package/src/types.ts
CHANGED
|
@@ -316,7 +316,8 @@ export interface AgentConcurrencyOptions {
|
|
|
316
316
|
* {@link MAX_RUNNING_TURNS_LIMIT}. Omit for unlimited.
|
|
317
317
|
*
|
|
318
318
|
* A queued turn still counts as `running` for busy semantics
|
|
319
|
-
* (follow-ups preempt it; direct tool calls get
|
|
319
|
+
* (follow-ups preempt it; direct write-effect tool calls get
|
|
320
|
+
* `SessionBusyError`),
|
|
320
321
|
* and a follow-up that preempts a queued turn re-queues at the back.
|
|
321
322
|
*/
|
|
322
323
|
maxRunningTurns?: number;
|
|
@@ -879,6 +880,8 @@ export interface ToolContext {
|
|
|
879
880
|
* `subagent.completed`). Omitted for scratch `callTool` with no session.
|
|
880
881
|
*/
|
|
881
882
|
emit?: (payload: SessionEventPayload) => void;
|
|
883
|
+
/** The session's frozen `asOf`, or the wall clock. Use instead of `Date.now()`. */
|
|
884
|
+
now(): Date;
|
|
882
885
|
}
|
|
883
886
|
|
|
884
887
|
/**
|
|
@@ -991,6 +994,17 @@ export interface ToolConfig<TInput> {
|
|
|
991
994
|
* write, so a dry run stubs it — see {@link ToolEffect}.
|
|
992
995
|
*/
|
|
993
996
|
effect?: ToolEffectDeclaration<TInput>;
|
|
997
|
+
/**
|
|
998
|
+
* Input properties that carry time bounds. In a session created with
|
|
999
|
+
* {@link SendMessageOptions.asOf}, every named argument must be an
|
|
1000
|
+
* absolute ISO-8601 instant with a timezone, no later than the session's
|
|
1001
|
+
* frozen instant — a call that omits one, or supplies a relative or later
|
|
1002
|
+
* value, is refused so the model retries with absolute bounds. Names must
|
|
1003
|
+
* exist in {@link inputSchema}; a session with `asOf` refuses to start
|
|
1004
|
+
* otherwise, because a misspelled name would silently check nothing.
|
|
1005
|
+
* Ignored in sessions without `asOf`.
|
|
1006
|
+
*/
|
|
1007
|
+
timeArgs?: readonly string[];
|
|
994
1008
|
/**
|
|
995
1009
|
* What a write tool returns in a dry-run session instead of executing.
|
|
996
1010
|
*
|
|
@@ -1024,6 +1038,7 @@ export interface ToolDefinition extends BrandedDefinition<"tool"> {
|
|
|
1024
1038
|
readonly outputSchema?: z.ZodTypeAny | JsonSchemaObject;
|
|
1025
1039
|
readonly needsApproval?: ToolNeedsApproval<never>;
|
|
1026
1040
|
readonly effect?: ToolEffectDeclaration<never>;
|
|
1041
|
+
readonly timeArgs?: readonly string[];
|
|
1027
1042
|
readonly dryRunResult?:
|
|
1028
1043
|
| ToolExecuteResult
|
|
1029
1044
|
| ((input: never) => ToolExecuteResult);
|
|
@@ -1151,7 +1166,9 @@ export function cursorAccountServersHasMixedWildcard(
|
|
|
1151
1166
|
*/
|
|
1152
1167
|
export function isHostOauthConnectionTransport(
|
|
1153
1168
|
transport: ConnectionTransport
|
|
1154
|
-
):
|
|
1169
|
+
): transport is Extract<ConnectionTransport, { url: string }> & {
|
|
1170
|
+
oauth: true;
|
|
1171
|
+
} {
|
|
1155
1172
|
return "url" in transport && transport.oauth === true;
|
|
1156
1173
|
}
|
|
1157
1174
|
|
|
@@ -1380,8 +1397,18 @@ export interface PendingApproval {
|
|
|
1380
1397
|
requestedAt: string;
|
|
1381
1398
|
}
|
|
1382
1399
|
|
|
1400
|
+
/** Durable record of a tool call waiting on MCP authorization. */
|
|
1401
|
+
export interface PendingAuth {
|
|
1402
|
+
callId: string;
|
|
1403
|
+
turnId: string;
|
|
1404
|
+
toolName: string;
|
|
1405
|
+
connection: string;
|
|
1406
|
+
authUrl: string;
|
|
1407
|
+
requestedAt: string;
|
|
1408
|
+
}
|
|
1409
|
+
|
|
1383
1410
|
export type SessionEventPayload =
|
|
1384
|
-
| { type: "session.started"; data: { channelId: string } }
|
|
1411
|
+
| { type: "session.started"; data: { channelId: string; dryRun?: boolean } }
|
|
1385
1412
|
| {
|
|
1386
1413
|
/**
|
|
1387
1414
|
* Sticky A/B enrollment for one experiment (`defineAB` under `agent/ab`).
|
|
@@ -1457,6 +1484,31 @@ export type SessionEventPayload =
|
|
|
1457
1484
|
parentCallId?: string;
|
|
1458
1485
|
};
|
|
1459
1486
|
}
|
|
1487
|
+
| {
|
|
1488
|
+
/**
|
|
1489
|
+
* A host MCP call/list needs OAuth. The turn stays running until
|
|
1490
|
+
* the human completes the `authUrl` and the runtime retries.
|
|
1491
|
+
*/
|
|
1492
|
+
type: "action.auth_requested";
|
|
1493
|
+
data: {
|
|
1494
|
+
callId: string;
|
|
1495
|
+
toolName: string;
|
|
1496
|
+
connection: string;
|
|
1497
|
+
authUrl: string;
|
|
1498
|
+
parentCallId?: string;
|
|
1499
|
+
};
|
|
1500
|
+
}
|
|
1501
|
+
| {
|
|
1502
|
+
type: "action.auth_resolved";
|
|
1503
|
+
data: {
|
|
1504
|
+
callId: string;
|
|
1505
|
+
toolName: string;
|
|
1506
|
+
connection: string;
|
|
1507
|
+
decision: ApprovalDecision;
|
|
1508
|
+
by?: string;
|
|
1509
|
+
parentCallId?: string;
|
|
1510
|
+
};
|
|
1511
|
+
}
|
|
1460
1512
|
| {
|
|
1461
1513
|
type: "action.result";
|
|
1462
1514
|
data: {
|
|
@@ -1586,6 +1638,8 @@ export interface SessionInfo {
|
|
|
1586
1638
|
purpose?: SessionPurpose;
|
|
1587
1639
|
/** True when write-classified tool calls are answered by the host. */
|
|
1588
1640
|
dryRun?: boolean;
|
|
1641
|
+
/** Frozen instant this session reads at; absent means the wall clock. */
|
|
1642
|
+
asOf?: string;
|
|
1589
1643
|
auth: AuthContext | null;
|
|
1590
1644
|
title?: string;
|
|
1591
1645
|
/**
|
|
@@ -1620,6 +1674,8 @@ export interface SessionRecord {
|
|
|
1620
1674
|
purpose?: SessionPurpose;
|
|
1621
1675
|
/** Frozen at create from {@link SendMessageOptions.dryRun}. */
|
|
1622
1676
|
dryRun?: boolean;
|
|
1677
|
+
/** Frozen at create from {@link SendMessageOptions.asOf}. */
|
|
1678
|
+
asOf?: string;
|
|
1623
1679
|
/**
|
|
1624
1680
|
* Denormalized sticky A/B arms (mirrors durable `ab.assigned` events) so
|
|
1625
1681
|
* the agent loop / tools can read arms without re-folding the log. Source
|
|
@@ -1672,6 +1728,11 @@ export interface SessionRecord {
|
|
|
1672
1728
|
* SDK tool callback cannot be resumed after process restart).
|
|
1673
1729
|
*/
|
|
1674
1730
|
pendingApprovals?: PendingApproval[];
|
|
1731
|
+
/**
|
|
1732
|
+
* Server-tool MCP calls parked for host or Cursor-account OAuth.
|
|
1733
|
+
* Cleared when resolved or when the host restarts without a live waiter.
|
|
1734
|
+
*/
|
|
1735
|
+
pendingAuths?: PendingAuth[];
|
|
1675
1736
|
turnCount: number;
|
|
1676
1737
|
createdAt: string;
|
|
1677
1738
|
updatedAt: string;
|
|
@@ -1708,6 +1769,8 @@ export interface SessionSummary {
|
|
|
1708
1769
|
queued?: boolean;
|
|
1709
1770
|
createdAt: string;
|
|
1710
1771
|
updatedAt: string;
|
|
1772
|
+
/** True when write-classified tool calls are answered by the host. */
|
|
1773
|
+
dryRun?: boolean;
|
|
1711
1774
|
/** Active wire token for HTTP follow-ups, or null when not addressable. */
|
|
1712
1775
|
continuationToken: string | null;
|
|
1713
1776
|
/**
|
|
@@ -1808,6 +1871,13 @@ export interface SendMessageOptions {
|
|
|
1808
1871
|
* model chose stay on the session log as the record of the intended action.
|
|
1809
1872
|
*/
|
|
1810
1873
|
dryRun?: boolean;
|
|
1874
|
+
/**
|
|
1875
|
+
* ISO-8601 instant with a timezone, frozen at create: the prompt states
|
|
1876
|
+
* it, {@link ToolContext.now} returns it, and tools that declare
|
|
1877
|
+
* {@link ToolConfig.timeArgs} refuse calls not bounded at or before it. A
|
|
1878
|
+
* tool that declares nothing still reads the present.
|
|
1879
|
+
*/
|
|
1880
|
+
asOf?: string;
|
|
1811
1881
|
/**
|
|
1812
1882
|
* Absolute directory used as the local harness `cwd` for this session.
|
|
1813
1883
|
* On create, sets the session workspace. On resume (continuation hit),
|
|
@@ -1928,11 +1998,14 @@ export interface ToolCallOutcome {
|
|
|
1928
1998
|
/** Present when the call ran inside an existing session. */
|
|
1929
1999
|
sessionId?: string;
|
|
1930
2000
|
/**
|
|
1931
|
-
* Present (true) when a session-bound call could not materialize
|
|
1932
|
-
* session
|
|
1933
|
-
* session identity still applied (read-effect calls only get here),
|
|
1934
|
-
* `ctx.workspaceDir` was not the session workspace — callers
|
|
1935
|
-
* results as session state should surface this.
|
|
2001
|
+
* Present (true) when a session-bound call could not materialize a
|
|
2002
|
+
* session-owned harness cwd and ran in a scratch workspace instead.
|
|
2003
|
+
* The session identity still applied (read-effect calls only get here),
|
|
2004
|
+
* but `ctx.workspaceDir` was not the session workspace — callers
|
|
2005
|
+
* rendering results as session state should surface this.
|
|
2006
|
+
*
|
|
2007
|
+
* A shared `local.workspaceDir` the host cannot create (a phantom path
|
|
2008
|
+
* like `/repo`) is kept as-is and does not set this flag.
|
|
1936
2009
|
*/
|
|
1937
2010
|
scratchWorkspace?: true;
|
|
1938
2011
|
}
|
|
@@ -2187,6 +2260,18 @@ export interface ChannelStartArgs {
|
|
|
2187
2260
|
auth: AuthContext | null,
|
|
2188
2261
|
options?: { asSessionOwner?: boolean }
|
|
2189
2262
|
): Promise<PendingApproval>;
|
|
2263
|
+
/**
|
|
2264
|
+
* Mark a parked MCP auth as connected or cancelled. Channel packs
|
|
2265
|
+
* (Slack "Connected") use this; the public OAuth callback also
|
|
2266
|
+
* resolves after `finishAuth`.
|
|
2267
|
+
*/
|
|
2268
|
+
resolveAuth(
|
|
2269
|
+
sessionId: string,
|
|
2270
|
+
callId: string,
|
|
2271
|
+
decision: ApprovalDecision,
|
|
2272
|
+
auth: AuthContext | null,
|
|
2273
|
+
options?: { asSessionOwner?: boolean }
|
|
2274
|
+
): Promise<PendingAuth>;
|
|
2190
2275
|
/**
|
|
2191
2276
|
* Server log sink (same as {@link ServeOptions.logger}). Channel packs
|
|
2192
2277
|
* should prefer this over `console.*` so CLI/eval hosts can redirect.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Living AGENTS.md
|
|
2
|
+
|
|
3
|
+
Keeps `AGENTS.md` current from last week's merged pull requests and the
|
|
4
|
+
listed Slack channels. Parks an update until a person approves it, then
|
|
5
|
+
opens a draft follow-up PR. Chores stay quiet. Same-base updates stack
|
|
6
|
+
on `agents-md/<base>`.
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
npx @cursor/july init ./agents-md --template agents-md
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
`init` asks which repo to watch and which Slack channels to read. Skip
|
|
13
|
+
the prompt with `--var repos=owner/repo --var slack=#eng-api`.
|
|
14
|
+
|
|
15
|
+
## Run
|
|
16
|
+
|
|
17
|
+
Connect GitHub in Cursor for that repo. Create the Slack app and invite
|
|
18
|
+
the bot to each listed channel, including private ones. Then sign the
|
|
19
|
+
host in:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
agent-sdk login
|
|
23
|
+
agent-sdk slack create --dir .
|
|
24
|
+
agent-sdk dev
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Schedules do not fire under `dev`. Dispatch the weekly job:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
curl -X POST http://127.0.0.1:3000/v1/dev/schedules/weekly
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Or run `/queue/run` in the playground.
|
|
34
|
+
|
|
35
|
+
## Files
|
|
36
|
+
|
|
37
|
+
- `agent/lib/config.ts`: repo and Slack channels
|
|
38
|
+
- `agent/instructions.md`: what counts as an AGENTS.md update
|
|
39
|
+
- `evals/agents.eval.ts`: skip and update smoke cases
|