@cursor/july 0.1.105 → 0.1.108
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/README.md +10 -5
- package/dist/bin/agent-serve.js +31 -16
- package/dist/channels/bitbucket/types.d.ts +2 -4
- package/dist/channels/bitbucket/types.d.ts.map +1 -1
- package/dist/channels/deployments/types.d.ts +5 -8
- package/dist/channels/deployments/types.d.ts.map +1 -1
- package/dist/channels/github/github-channel.js +8 -5
- package/dist/channels/github/types.d.ts +7 -5
- package/dist/channels/github/types.d.ts.map +1 -1
- package/dist/channels/gitlab/types.d.ts +2 -5
- package/dist/channels/gitlab/types.d.ts.map +1 -1
- package/dist/channels/origin/origin-channel.d.ts.map +1 -1
- package/dist/channels/origin/origin-channel.js +27 -13
- package/dist/channels/origin/types.d.ts +7 -4
- package/dist/channels/origin/types.d.ts.map +1 -1
- package/dist/channels/slack/defaults.d.ts.map +1 -1
- package/dist/channels/slack/defaults.js +3 -0
- package/dist/channels/slack/dispatch.d.ts.map +1 -1
- package/dist/channels/slack/dispatch.js +1 -1
- package/dist/channels/slack/live-delivery.d.ts.map +1 -1
- package/dist/channels/slack/live-delivery.js +48 -11
- package/dist/channels/slack/types.d.ts +4 -3
- package/dist/channels/slack/types.d.ts.map +1 -1
- package/dist/channels.d.ts +45 -0
- package/dist/channels.d.ts.map +1 -1
- package/dist/channels.js +106 -7
- package/dist/connections.d.ts +2 -1
- package/dist/connections.d.ts.map +1 -1
- package/dist/connections.js +2 -1
- package/dist/docs/404.html +3 -3
- package/dist/docs/ab.html +6 -6
- package/dist/docs/assets/{app.BVwaffdK.js → app.BASKM3M4.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.BHZYsNVi.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.WuWTZ1x8.js → VPLocalSearchBox.BOKxlYGP.js} +2 -2
- package/dist/docs/assets/chunks/{theme.BYdI_6sF.js → theme.DbDZW-zb.js} +2 -2
- package/dist/docs/assets/{deployment.md.MFPKqsqI.js → deployment.md.JenwuCCB.js} +4 -4
- package/dist/docs/assets/{deployment.md.MFPKqsqI.lean.js → deployment.md.JenwuCCB.lean.js} +1 -1
- package/dist/docs/assets/{evals.md.CbMoebP1.js → evals.md.C1ekS3k2.js} +1 -1
- package/dist/docs/assets/guides_cloud-agents.md.BsloyHdY.js +9 -0
- package/dist/docs/assets/{guides_cloud-agents.md.DS8RIjwx.lean.js → guides_cloud-agents.md.BsloyHdY.lean.js} +1 -1
- package/dist/docs/assets/{guides_github.md.c0gdGJ-D.js → guides_github.md.BH33UEBJ.js} +1 -1
- package/dist/docs/assets/{guides_grokbot-agents.md.DVqdhBKb.js → guides_grokbot-agents.md.DyV-WArv.js} +1 -1
- package/dist/docs/assets/guides_improve.md.BGVk32bK.js +14 -0
- package/dist/docs/assets/guides_improve.md.BGVk32bK.lean.js +1 -0
- package/dist/docs/assets/{guides_opentelemetry.md.COh9jFVg.js → guides_opentelemetry.md.SCRMskno.js} +3 -3
- package/dist/docs/assets/{guides_opentelemetry.md.COh9jFVg.lean.js → guides_opentelemetry.md.SCRMskno.lean.js} +1 -1
- package/dist/docs/assets/{guides_slack.md.9oHPye9o.js → guides_slack.md.D4RVMM4G.js} +3 -3
- package/dist/docs/assets/{guides_slack.md.9oHPye9o.lean.js → guides_slack.md.D4RVMM4G.lean.js} +1 -1
- package/dist/docs/assets/index.md.BjH1w2ZW.js +5 -0
- package/dist/docs/assets/{reference_agent-config.md.CHNpiyp4.js → reference_agent-config.md.CvoL6pof.js} +1 -1
- package/dist/docs/assets/{reference_channels.md.DBGcaB7m.js → reference_channels.md.D-qTqwcq.js} +2 -2
- package/dist/docs/assets/{reference_channels.md.DBGcaB7m.lean.js → reference_channels.md.D-qTqwcq.lean.js} +1 -1
- package/dist/docs/assets/{reference_cli.md.C6Lo8SEd.js → reference_cli.md.Ca26u0Es.js} +6 -6
- package/dist/docs/assets/{reference_cli.md.C6Lo8SEd.lean.js → reference_cli.md.Ca26u0Es.lean.js} +1 -1
- package/dist/docs/assets/{reference_connections.md.Di6jJAXF.js → reference_connections.md.BojkC6c5.js} +1 -1
- package/dist/docs/assets/{reference_extensions.md.CGmMLblt.js → reference_extensions.md.CPWt00ds.js} +1 -1
- package/dist/docs/assets/{scaffolding-agents.md.em43xlY1.js → scaffolding-agents.md.Kctn3OVb.js} +1 -1
- package/dist/docs/assets/{skills_create-agent.md.BVoWPcan.js → skills_create-agent.md.Q3h6Je-e.js} +1 -1
- package/dist/docs/assets/{skills_debug.md.CDbPhHfg.js → skills_debug.md.CVjCXMFF.js} +1 -1
- package/dist/docs/assets/{skills_debug.md.CDbPhHfg.lean.js → skills_debug.md.CVjCXMFF.lean.js} +1 -1
- package/dist/docs/assets/{skills_evals.md.723kpUmA.js → skills_evals.md.BhovOvrl.js} +1 -1
- package/dist/docs/assets/skills_framework-map.md.D-tFZhFS.js +1 -0
- package/dist/docs/assets/{skills_framework-map.md.haibFyoB.lean.js → skills_framework-map.md.D-tFZhFS.lean.js} +1 -1
- package/dist/docs/assets/{skills_github.md.D0JahM8c.js → skills_github.md.hgFX_oKY.js} +1 -1
- package/dist/docs/assets/{skills_otel.md.CqhobH3B.js → skills_otel.md.B5Ddv1xH.js} +1 -1
- package/dist/docs/assets/{style.BRuM8477.css → style.DCD_zyg3.css} +1 -1
- package/dist/docs/assets/troubleshooting.md.CYEAO9bM.js +1 -0
- package/dist/docs/building-with-agents.html +6 -6
- package/dist/docs/concepts.html +5 -5
- package/dist/docs/deployment.html +9 -9
- package/dist/docs/deployment.md +7 -2
- package/dist/docs/evals.html +8 -8
- package/dist/docs/evals.md +3 -2
- package/dist/docs/guides/agent-to-agent.html +6 -6
- package/dist/docs/guides/cloud-agents.html +7 -7
- package/dist/docs/guides/cloud-agents.md +4 -3
- package/dist/docs/guides/convert-automation.html +6 -6
- package/dist/docs/guides/github.html +7 -7
- package/dist/docs/guides/github.md +2 -1
- package/dist/docs/guides/grokbot-agents.html +7 -7
- package/dist/docs/guides/grokbot-agents.md +2 -2
- package/dist/docs/guides/human-in-the-loop.html +6 -6
- package/dist/docs/guides/improve.html +40 -0
- package/dist/docs/guides/improve.md +91 -0
- package/dist/docs/guides/mcp-oauth.html +6 -6
- package/dist/docs/guides/opentelemetry.html +8 -8
- package/dist/docs/guides/opentelemetry.md +3 -4
- package/dist/docs/guides/slack.html +8 -8
- package/dist/docs/guides/slack.md +2 -1
- package/dist/docs/guides/webhooks.html +6 -6
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +6 -6
- package/dist/docs/index.html +8 -8
- package/dist/docs/index.md +4 -0
- package/dist/docs/llms-full.txt +180 -61
- package/dist/docs/llms.txt +1 -0
- package/dist/docs/quickstart.html +6 -6
- package/dist/docs/reference/agent-config.html +7 -7
- package/dist/docs/reference/agent-config.md +5 -2
- package/dist/docs/reference/artifacts.html +6 -6
- package/dist/docs/reference/channels.html +7 -7
- package/dist/docs/reference/channels.md +11 -19
- package/dist/docs/reference/cli.html +11 -11
- package/dist/docs/reference/cli.md +23 -13
- package/dist/docs/reference/connections.html +8 -8
- package/dist/docs/reference/connections.md +2 -1
- package/dist/docs/reference/extensions.html +7 -7
- package/dist/docs/reference/extensions.md +2 -0
- package/dist/docs/reference/hooks.html +6 -6
- package/dist/docs/reference/http-api.html +6 -6
- package/dist/docs/reference/instructions.html +6 -6
- package/dist/docs/reference/playground.html +5 -5
- package/dist/docs/reference/project-layout.html +6 -6
- package/dist/docs/reference/prompt.html +6 -6
- package/dist/docs/reference/result.html +6 -6
- package/dist/docs/reference/schedules.html +6 -6
- package/dist/docs/reference/sessions.html +5 -5
- package/dist/docs/reference/skills.html +6 -6
- package/dist/docs/reference/subagents.html +6 -6
- package/dist/docs/reference/tools.html +6 -6
- package/dist/docs/scaffolding-agents.html +6 -6
- package/dist/docs/scaffolding-agents.md +2 -1
- package/dist/docs/skills/ab.html +6 -6
- package/dist/docs/skills/create-agent.html +8 -8
- package/dist/docs/skills/create-agent.md +1 -1
- package/dist/docs/skills/debug.html +6 -6
- package/dist/docs/skills/debug.md +1 -1
- package/dist/docs/skills/evals.html +8 -8
- package/dist/docs/skills/evals.md +1 -1
- package/dist/docs/skills/framework-map.html +6 -6
- package/dist/docs/skills/framework-map.md +4 -2
- package/dist/docs/skills/github.html +8 -8
- package/dist/docs/skills/github.md +1 -1
- package/dist/docs/skills/hillclimb.html +6 -6
- package/dist/docs/skills/index.html +5 -5
- package/dist/docs/skills/mcp-auth.html +6 -6
- package/dist/docs/skills/otel.html +8 -8
- package/dist/docs/skills/otel.md +3 -3
- package/dist/docs/skills/setup-slack.html +6 -6
- package/dist/docs/storage.html +6 -6
- package/dist/docs/templates/agentic-owners.html +6 -6
- package/dist/docs/templates/agents-md.html +6 -6
- package/dist/docs/templates/code-wiki.html +6 -6
- package/dist/docs/templates/demo.html +6 -6
- package/dist/docs/templates/grokbot-agents.html +6 -6
- package/dist/docs/templates/pr-autofixer.html +6 -6
- package/dist/docs/templates/security-help.html +6 -6
- package/dist/docs/templates/security-reviewer.html +6 -6
- package/dist/docs/templates/triage.html +6 -6
- package/dist/docs/troubleshooting.html +6 -6
- package/dist/docs/troubleshooting.md +1 -1
- package/dist/extensions/improve/extension.d.ts +46 -0
- package/dist/extensions/improve/extension.d.ts.map +1 -0
- package/dist/extensions/improve/extension.js +41 -0
- package/dist/extensions/improve/skills/yourself.d.ts +4 -0
- package/dist/extensions/improve/skills/yourself.d.ts.map +1 -0
- package/dist/extensions/improve/skills/yourself.js +43 -0
- package/dist/index.d.ts +4 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -4
- package/dist/internal/builtin-tools/artifacts.d.ts.map +1 -1
- package/dist/internal/builtin-tools/artifacts.js +2 -3
- package/dist/internal/channel-route-dispatch.d.ts +13 -0
- package/dist/internal/channel-route-dispatch.d.ts.map +1 -0
- package/dist/internal/channel-route-dispatch.js +62 -0
- package/dist/internal/channel-state.d.ts +17 -0
- package/dist/internal/channel-state.d.ts.map +1 -0
- package/dist/internal/channel-state.js +78 -0
- package/dist/internal/cli-ax.d.ts +7 -0
- package/dist/internal/cli-ax.d.ts.map +1 -1
- package/dist/internal/cli-ax.js +99 -1
- package/dist/internal/cli-cursor.d.ts.map +1 -1
- package/dist/internal/cli-cursor.js +2 -0
- package/dist/internal/cli-deploy.d.ts.map +1 -1
- package/dist/internal/cli-deploy.js +61 -25
- package/dist/internal/cli-mcp-oauth.d.ts.map +1 -1
- package/dist/internal/cli-mcp-oauth.js +15 -0
- package/dist/internal/cli-mcp.d.ts.map +1 -1
- package/dist/internal/cli-mcp.js +12 -0
- package/dist/internal/cli-slack.d.ts.map +1 -1
- package/dist/internal/cli-slack.js +8 -2
- package/dist/internal/cursor/backend-client.d.ts +25 -0
- package/dist/internal/cursor/backend-client.d.ts.map +1 -1
- package/dist/internal/cursor/backend-client.js +57 -2
- package/dist/internal/cursor/credentials.d.ts +8 -2
- package/dist/internal/cursor/credentials.d.ts.map +1 -1
- package/dist/internal/cursor/credentials.js +27 -5
- package/dist/internal/deploy-client.d.ts +35 -0
- package/dist/internal/deploy-client.d.ts.map +1 -1
- package/dist/internal/deploy-client.js +46 -0
- package/dist/internal/deploy-manifest.d.ts +26 -0
- package/dist/internal/deploy-manifest.d.ts.map +1 -1
- package/dist/internal/deploy-manifest.js +99 -13
- package/dist/internal/describe-error.d.ts +1 -0
- package/dist/internal/describe-error.d.ts.map +1 -1
- package/dist/internal/describe-error.js +25 -0
- package/dist/internal/discovery/agent.d.ts.map +1 -1
- package/dist/internal/discovery/agent.js +1 -0
- package/dist/internal/discovery/info.d.ts.map +1 -1
- package/dist/internal/discovery/info.js +7 -3
- package/dist/internal/discovery/modules.d.ts +1 -1
- package/dist/internal/discovery/modules.d.ts.map +1 -1
- package/dist/internal/discovery/modules.js +1 -0
- package/dist/internal/discovery/project.d.ts.map +1 -1
- package/dist/internal/discovery/project.js +3 -0
- package/dist/internal/discovery/reminders.d.ts +7 -0
- package/dist/internal/discovery/reminders.d.ts.map +1 -0
- package/dist/internal/discovery/reminders.js +65 -0
- package/dist/internal/discovery/subagent.js +1 -0
- package/dist/internal/distribution.d.ts +5 -0
- package/dist/internal/distribution.d.ts.map +1 -1
- package/dist/internal/distribution.js +17 -0
- package/dist/internal/framework-storage-selection.d.ts +14 -3
- package/dist/internal/framework-storage-selection.d.ts.map +1 -1
- package/dist/internal/framework-storage-selection.js +36 -6
- package/dist/internal/guest-network.d.ts +4 -10
- package/dist/internal/guest-network.d.ts.map +1 -1
- package/dist/internal/guest-network.js +44 -26
- package/dist/internal/hosted-admission-adapter.d.ts +2 -0
- package/dist/internal/hosted-admission-adapter.d.ts.map +1 -1
- package/dist/internal/hosted-catch-protocol.d.ts +51 -0
- package/dist/internal/hosted-catch-protocol.d.ts.map +1 -0
- package/dist/internal/hosted-catch-protocol.js +103 -0
- package/dist/internal/hosted-catch.d.ts +40 -0
- package/dist/internal/hosted-catch.d.ts.map +1 -0
- package/dist/internal/hosted-catch.js +149 -0
- package/dist/internal/hosted-delivery-protocol.d.ts +89 -0
- package/dist/internal/hosted-delivery-protocol.d.ts.map +1 -1
- package/dist/internal/hosted-delivery-protocol.js +309 -0
- package/dist/internal/hosted-delivery.d.ts +20 -1
- package/dist/internal/hosted-delivery.d.ts.map +1 -1
- package/dist/internal/hosted-delivery.js +179 -36
- package/dist/internal/hosted-execution-diag.d.ts +4 -1
- package/dist/internal/hosted-execution-diag.d.ts.map +1 -1
- package/dist/internal/hosted-execution-diag.js +13 -4
- package/dist/internal/hosted-execution-flush.d.ts +3 -0
- package/dist/internal/hosted-execution-flush.d.ts.map +1 -1
- package/dist/internal/hosted-execution-flush.js +2 -4
- package/dist/internal/http-control-plane-session.d.ts +30 -0
- package/dist/internal/http-control-plane-session.d.ts.map +1 -0
- package/dist/internal/http-control-plane-session.js +83 -0
- package/dist/internal/legacy-command-guard.d.ts +22 -0
- package/dist/internal/legacy-command-guard.d.ts.map +1 -0
- package/dist/internal/legacy-command-guard.js +51 -0
- package/dist/internal/local-control-plane.d.ts +18 -2
- package/dist/internal/local-control-plane.d.ts.map +1 -1
- package/dist/internal/local-control-plane.js +199 -17
- package/dist/internal/platform-timers.d.ts +7 -0
- package/dist/internal/platform-timers.d.ts.map +1 -1
- package/dist/internal/platform-timers.js +139 -0
- package/dist/internal/reminder-control-plane-protocol.d.ts +189 -0
- package/dist/internal/reminder-control-plane-protocol.d.ts.map +1 -0
- package/dist/internal/reminder-control-plane-protocol.js +251 -0
- package/dist/internal/reminder-runner.d.ts +56 -6
- package/dist/internal/reminder-runner.d.ts.map +1 -1
- package/dist/internal/reminder-runner.js +372 -57
- package/dist/internal/reminder-schedule.d.ts +5 -2
- package/dist/internal/reminder-schedule.d.ts.map +1 -1
- package/dist/internal/reminder-schedule.js +8 -6
- package/dist/internal/reminder-store.d.ts +24 -7
- package/dist/internal/reminder-store.d.ts.map +1 -1
- package/dist/internal/reminder-store.js +6 -5
- package/dist/internal/request-error-status.d.ts +2 -0
- package/dist/internal/request-error-status.d.ts.map +1 -1
- package/dist/internal/request-error-status.js +22 -3
- package/dist/internal/resolve-prod-target.d.ts +2 -0
- package/dist/internal/resolve-prod-target.d.ts.map +1 -1
- package/dist/internal/resolve-prod-target.js +13 -0
- package/dist/internal/scm/pr-url.d.ts +40 -0
- package/dist/internal/scm/pr-url.d.ts.map +1 -1
- package/dist/internal/scm/pr-url.js +93 -14
- package/dist/internal/sdk-runner.d.ts.map +1 -1
- package/dist/internal/sdk-runner.js +4 -3
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +118 -77
- package/dist/internal/session-engine.d.ts +6 -6
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +100 -67
- package/dist/playground/assets/{index-BaQzjaNK.js → index-BMDqAeXu.js} +34 -34
- package/dist/playground/assets/index-LUgJoWdL.css +1 -0
- package/dist/playground/index.html +2 -2
- package/dist/reminders.d.ts +24 -5
- package/dist/reminders.d.ts.map +1 -1
- package/dist/reminders.js +28 -5
- package/dist/storage-backends/cursor-hosted.d.ts +6 -0
- package/dist/storage-backends/cursor-hosted.d.ts.map +1 -1
- package/dist/storage-backends/cursor-hosted.js +29 -1
- package/dist/types.d.ts +122 -25
- package/dist/types.d.ts.map +1 -1
- package/docs/README.md +4 -0
- package/docs/deployment.md +7 -2
- package/docs/evals.md +3 -2
- package/docs/guides/cloud-agents.md +4 -3
- package/docs/guides/github.md +2 -1
- package/docs/guides/grokbot-agents.md +2 -2
- package/docs/guides/improve.md +96 -0
- package/docs/guides/opentelemetry.md +3 -4
- package/docs/guides/slack.md +2 -1
- package/docs/reference/agent-config.md +5 -2
- package/docs/reference/channels.md +11 -19
- package/docs/reference/cli.md +23 -13
- package/docs/reference/connections.md +2 -1
- package/docs/reference/extensions.md +2 -0
- package/docs/scaffolding-agents.md +2 -1
- package/docs/troubleshooting.md +1 -1
- package/package.json +10 -3
- package/skills/create-agent/SKILL.md +1 -1
- package/skills/debug/SKILL.md +1 -1
- package/skills/evals/SKILL.md +1 -1
- package/skills/framework-map/SKILL.md +4 -2
- package/skills/github/SKILL.md +1 -1
- package/skills/otel/SKILL.md +3 -3
- package/src/bin/agent-serve.ts +28 -11
- package/src/channels/bitbucket/types.ts +2 -4
- package/src/channels/deployments/types.ts +5 -8
- package/src/channels/github/github-channel.ts +8 -8
- package/src/channels/github/types.ts +7 -4
- package/src/channels/gitlab/types.ts +2 -5
- package/src/channels/origin/origin-channel.ts +29 -13
- package/src/channels/origin/types.ts +7 -3
- package/src/channels/slack/defaults.ts +3 -0
- package/src/channels/slack/dispatch.ts +1 -0
- package/src/channels/slack/live-delivery.ts +53 -12
- package/src/channels/slack/types.ts +4 -3
- package/src/channels.ts +157 -10
- package/src/connections.ts +2 -1
- package/src/extensions/improve/extension.ts +70 -0
- package/src/extensions/improve/skills/yourself.ts +50 -0
- package/src/index.ts +6 -3
- package/src/internal/builtin-tools/artifacts.ts +2 -3
- package/src/internal/channel-route-dispatch.ts +66 -0
- package/src/internal/channel-state.ts +96 -0
- package/src/internal/cli-ax.ts +110 -1
- package/src/internal/cli-cursor.ts +4 -1
- package/src/internal/cli-deploy.ts +80 -22
- package/src/internal/cli-mcp-oauth.ts +18 -0
- package/src/internal/cli-mcp.ts +11 -0
- package/src/internal/cli-slack.ts +15 -2
- package/src/internal/cursor/backend-client.ts +90 -2
- package/src/internal/cursor/credentials.ts +35 -7
- package/src/internal/deploy-client.ts +70 -0
- package/src/internal/deploy-manifest.ts +131 -12
- package/src/internal/describe-error.ts +28 -0
- package/src/internal/discovery/agent.ts +1 -0
- package/src/internal/discovery/info.ts +6 -0
- package/src/internal/discovery/modules.ts +2 -4
- package/src/internal/discovery/project.ts +3 -0
- package/src/internal/discovery/reminders.ts +65 -0
- package/src/internal/discovery/subagent.ts +1 -0
- package/src/internal/distribution.ts +20 -0
- package/src/internal/framework-storage-selection.ts +43 -6
- package/src/internal/guest-network.ts +46 -29
- package/src/internal/hosted-admission-adapter.ts +2 -0
- package/src/internal/hosted-catch-protocol.ts +130 -0
- package/src/internal/hosted-catch.ts +192 -0
- package/src/internal/hosted-delivery-protocol.ts +483 -0
- package/src/internal/hosted-delivery.ts +303 -43
- package/src/internal/hosted-execution-diag.ts +21 -3
- package/src/internal/hosted-execution-flush.ts +6 -3
- package/src/internal/http-control-plane-session.ts +104 -0
- package/src/internal/legacy-command-guard.ts +59 -0
- package/src/internal/local-control-plane.ts +281 -22
- package/src/internal/platform-timers.ts +191 -0
- package/src/internal/reminder-control-plane-protocol.ts +512 -0
- package/src/internal/reminder-runner.ts +481 -57
- package/src/internal/reminder-schedule.ts +11 -6
- package/src/internal/reminder-store.ts +27 -7
- package/src/internal/request-error-status.ts +27 -3
- package/src/internal/resolve-prod-target.ts +15 -0
- package/src/internal/scm/pr-url.ts +167 -20
- package/src/internal/sdk-runner.ts +2 -1
- package/src/internal/server.ts +151 -88
- package/src/internal/session-engine.ts +146 -83
- package/src/reminders.ts +35 -4
- package/src/storage-backends/cursor-hosted.ts +40 -1
- package/src/types.ts +134 -26
- package/dist/docs/assets/chunks/@localSearchIndexroot.CJxMklAy.js +0 -1
- package/dist/docs/assets/guides_cloud-agents.md.DS8RIjwx.js +0 -9
- package/dist/docs/assets/index.md.BW_6tOgR.js +0 -5
- package/dist/docs/assets/skills_framework-map.md.haibFyoB.js +0 -1
- package/dist/docs/assets/troubleshooting.md.Cus_YZga.js +0 -1
- package/dist/playground/assets/index-CceqnLTX.css +0 -1
- /package/dist/docs/assets/{evals.md.CbMoebP1.lean.js → evals.md.C1ekS3k2.lean.js} +0 -0
- /package/dist/docs/assets/{guides_github.md.c0gdGJ-D.lean.js → guides_github.md.BH33UEBJ.lean.js} +0 -0
- /package/dist/docs/assets/{guides_grokbot-agents.md.DVqdhBKb.lean.js → guides_grokbot-agents.md.DyV-WArv.lean.js} +0 -0
- /package/dist/docs/assets/{index.md.BW_6tOgR.lean.js → index.md.BjH1w2ZW.lean.js} +0 -0
- /package/dist/docs/assets/{reference_agent-config.md.CHNpiyp4.lean.js → reference_agent-config.md.CvoL6pof.lean.js} +0 -0
- /package/dist/docs/assets/{reference_connections.md.Di6jJAXF.lean.js → reference_connections.md.BojkC6c5.lean.js} +0 -0
- /package/dist/docs/assets/{reference_extensions.md.CGmMLblt.lean.js → reference_extensions.md.CPWt00ds.lean.js} +0 -0
- /package/dist/docs/assets/{scaffolding-agents.md.em43xlY1.lean.js → scaffolding-agents.md.Kctn3OVb.lean.js} +0 -0
- /package/dist/docs/assets/{skills_create-agent.md.BVoWPcan.lean.js → skills_create-agent.md.Q3h6Je-e.lean.js} +0 -0
- /package/dist/docs/assets/{skills_evals.md.723kpUmA.lean.js → skills_evals.md.BhovOvrl.lean.js} +0 -0
- /package/dist/docs/assets/{skills_github.md.D0JahM8c.lean.js → skills_github.md.hgFX_oKY.lean.js} +0 -0
- /package/dist/docs/assets/{skills_otel.md.CqhobH3B.lean.js → skills_otel.md.B5Ddv1xH.lean.js} +0 -0
- /package/dist/docs/assets/{troubleshooting.md.Cus_YZga.lean.js → troubleshooting.md.CYEAO9bM.lean.js} +0 -0
|
@@ -1,20 +1,40 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Per-session reminder runner: durable wake subscriptions with
|
|
3
|
-
* prompt XOR run, every/cron/delay/at schedules, and
|
|
4
|
-
* function XOR prompt.
|
|
3
|
+
* prompt XOR named handler XOR run, every/cron/delay/at schedules, and
|
|
4
|
+
* until as function XOR prompt.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { randomBytes } from "node:crypto";
|
|
8
8
|
import type {
|
|
9
9
|
AuthContext,
|
|
10
|
+
DiscoveredReminder,
|
|
11
|
+
JsonObject,
|
|
12
|
+
JsonValue,
|
|
10
13
|
ReminderCreateInput,
|
|
14
|
+
ReminderDefinition,
|
|
11
15
|
ReminderFireContext,
|
|
12
16
|
ReminderFireResult,
|
|
13
17
|
ReminderInfo,
|
|
18
|
+
ReminderStatus,
|
|
14
19
|
ReminderUntilContext,
|
|
15
20
|
} from "../types.js";
|
|
21
|
+
import {
|
|
22
|
+
channelContinuationIdentity,
|
|
23
|
+
httpContinuationIdentity,
|
|
24
|
+
} from "./continuation-channel.js";
|
|
25
|
+
import { continuationSource } from "./continuation-identity.js";
|
|
26
|
+
import { NAME_PATTERN } from "./discovery/names.js";
|
|
16
27
|
import { parseDuration } from "./duration.js";
|
|
17
28
|
import type { PlatformTimers } from "./platform-timers.js";
|
|
29
|
+
import {
|
|
30
|
+
REMINDER_CP_PROTOCOL_VERSION,
|
|
31
|
+
type ReminderControlPlane,
|
|
32
|
+
type ReminderCreateIntent,
|
|
33
|
+
type ReminderExecutionOutcome,
|
|
34
|
+
type ReminderFireDescriptor,
|
|
35
|
+
scheduleSpecFromCreateInput,
|
|
36
|
+
toWireReschedule,
|
|
37
|
+
} from "./reminder-control-plane-protocol.js";
|
|
18
38
|
import {
|
|
19
39
|
defaultBusyPolicy,
|
|
20
40
|
MAX_TIMER_MS,
|
|
@@ -24,10 +44,18 @@ import {
|
|
|
24
44
|
} from "./reminder-schedule.js";
|
|
25
45
|
import type { ReminderBusyPolicy, ReminderRecord } from "./reminder-store.js";
|
|
26
46
|
import { APP_AUTH } from "./schedule-runner.js";
|
|
27
|
-
import {
|
|
47
|
+
import {
|
|
48
|
+
type EngineSendOptions,
|
|
49
|
+
HTTP_CHANNEL_ID,
|
|
50
|
+
SessionBusyError,
|
|
51
|
+
type SessionEngine,
|
|
52
|
+
} from "./session-engine.js";
|
|
28
53
|
|
|
29
54
|
export { ReminderValidationError } from "./reminder-schedule.js";
|
|
30
55
|
|
|
56
|
+
/** Max UTF-8 byte length of `JSON.stringify(args)` on named-handler create. */
|
|
57
|
+
export const REMINDER_ARGS_MAX_BYTES: number = 32 * 1024;
|
|
58
|
+
|
|
31
59
|
export class UnknownReminderError extends Error {
|
|
32
60
|
constructor(
|
|
33
61
|
reminderId: string,
|
|
@@ -43,10 +71,79 @@ interface LiveHandlers {
|
|
|
43
71
|
untilFn?: (ctx: ReminderUntilContext) => Promise<boolean>;
|
|
44
72
|
}
|
|
45
73
|
|
|
74
|
+
export interface ReminderRunnerOptions {
|
|
75
|
+
/** Discovered `agent/reminders/*` handlers, keyed by module stem. */
|
|
76
|
+
namedHandlers?: readonly DiscoveredReminder[];
|
|
77
|
+
/**
|
|
78
|
+
* Architecture v2: reject anonymous `run` and function `until` at create
|
|
79
|
+
* (named `handler` + prompt remain), whether local or hosted.
|
|
80
|
+
*/
|
|
81
|
+
rejectAnonymousHandlers?: boolean;
|
|
82
|
+
/**
|
|
83
|
+
* When set (local self-hosted architecture v2), create/cancel/rekey go
|
|
84
|
+
* through the control-plane protocol and fires are guest executions of
|
|
85
|
+
* immutable descriptors.
|
|
86
|
+
*/
|
|
87
|
+
controlPlane?: ReminderControlPlane;
|
|
88
|
+
/** Agent architecture; used with {@link controlPlane} for v2 protocol path. */
|
|
89
|
+
architecture?: "v1" | "v2";
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Server wiring for {@link ReminderRunnerOptions.rejectAnonymousHandlers}:
|
|
94
|
+
* architecture v2 always rejects anonymous run/until (local or hosted).
|
|
95
|
+
*/
|
|
96
|
+
export function rejectAnonymousReminderHandlers(options: {
|
|
97
|
+
noControlPlane?: boolean;
|
|
98
|
+
architecture?: string;
|
|
99
|
+
}): boolean {
|
|
100
|
+
return options.architecture === "v2";
|
|
101
|
+
}
|
|
102
|
+
|
|
46
103
|
function newReminderId(): string {
|
|
47
104
|
return `rem_${randomBytes(8).toString("hex")}`;
|
|
48
105
|
}
|
|
49
106
|
|
|
107
|
+
function isJsonObject(value: unknown): value is JsonObject {
|
|
108
|
+
return (
|
|
109
|
+
typeof value === "object" &&
|
|
110
|
+
value !== null &&
|
|
111
|
+
!Array.isArray(value) &&
|
|
112
|
+
Object.values(value as Record<string, unknown>).every(isJsonValue)
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function isJsonValue(value: unknown): value is JsonValue {
|
|
117
|
+
if (
|
|
118
|
+
value === null ||
|
|
119
|
+
typeof value === "string" ||
|
|
120
|
+
typeof value === "boolean"
|
|
121
|
+
) {
|
|
122
|
+
return true;
|
|
123
|
+
}
|
|
124
|
+
if (typeof value === "number") {
|
|
125
|
+
return Number.isFinite(value);
|
|
126
|
+
}
|
|
127
|
+
if (Array.isArray(value)) {
|
|
128
|
+
return value.every(isJsonValue);
|
|
129
|
+
}
|
|
130
|
+
return isJsonObject(value);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** Same stem rules as `agent/reminders/<name>.ts` discovery. */
|
|
134
|
+
function isValidReminderHandlerName(name: string): boolean {
|
|
135
|
+
return NAME_PATTERN.test(name) && !name.includes("__");
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function assertReminderArgsSize(args: JsonObject): void {
|
|
139
|
+
const bytes = Buffer.byteLength(JSON.stringify(args), "utf8");
|
|
140
|
+
if (bytes > REMINDER_ARGS_MAX_BYTES) {
|
|
141
|
+
throw new ReminderValidationError(
|
|
142
|
+
`reminders.create args exceed ${REMINDER_ARGS_MAX_BYTES} bytes (got ${bytes})`
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
50
147
|
function toInfo(record: ReminderRecord): ReminderInfo {
|
|
51
148
|
return {
|
|
52
149
|
id: record.id,
|
|
@@ -57,9 +154,11 @@ function toInfo(record: ReminderRecord): ReminderInfo {
|
|
|
57
154
|
scheduleKind: record.scheduleKind,
|
|
58
155
|
scheduleValue: record.scheduleValue,
|
|
59
156
|
prompt: record.prompt,
|
|
157
|
+
handler: record.handler,
|
|
158
|
+
args: record.args,
|
|
60
159
|
untilPrompt: record.untilPrompt,
|
|
61
160
|
busyPolicy: record.busyPolicy,
|
|
62
|
-
status: record.status,
|
|
161
|
+
status: record.status === "firing" ? "armed" : record.status,
|
|
63
162
|
disarmReason: record.disarmReason,
|
|
64
163
|
fireCount: record.fireCount,
|
|
65
164
|
nextFireAt: new Date(record.nextFireAtMs).toISOString(),
|
|
@@ -96,17 +195,36 @@ function buildFirePrompt(record: ReminderRecord): string {
|
|
|
96
195
|
export class ReminderRunner {
|
|
97
196
|
private readonly records = new Map<string, ReminderRecord>();
|
|
98
197
|
private readonly handlers = new Map<string, LiveHandlers>();
|
|
198
|
+
private readonly namedHandlers = new Map<string, ReminderDefinition>();
|
|
199
|
+
private readonly namedHandlerNames = new Map<ReminderDefinition, string>();
|
|
99
200
|
private readonly timers = new Map<string, NodeJS.Timeout>();
|
|
100
201
|
private readonly firing = new Set<string>();
|
|
101
202
|
/** Single-flight idle gates keyed by `channelId:continuationToken`. */
|
|
102
203
|
private readonly idleGates = new Map<string, Promise<void>>();
|
|
103
204
|
private started = false;
|
|
205
|
+
private readonly rejectAnonymousHandlers: boolean;
|
|
206
|
+
private readonly controlPlane: ReminderControlPlane | undefined;
|
|
207
|
+
private readonly architecture: "v1" | "v2" | undefined;
|
|
104
208
|
|
|
105
209
|
constructor(
|
|
106
210
|
private readonly engine: SessionEngine,
|
|
107
211
|
private readonly logger: (line: string) => void = () => {},
|
|
108
|
-
private readonly platformTimers?: PlatformTimers
|
|
109
|
-
|
|
212
|
+
private readonly platformTimers?: PlatformTimers,
|
|
213
|
+
options: ReminderRunnerOptions = {}
|
|
214
|
+
) {
|
|
215
|
+
this.rejectAnonymousHandlers = options.rejectAnonymousHandlers === true;
|
|
216
|
+
this.controlPlane = options.controlPlane;
|
|
217
|
+
this.architecture = options.architecture;
|
|
218
|
+
for (const reminder of options.namedHandlers ?? []) {
|
|
219
|
+
this.namedHandlers.set(reminder.name, reminder.definition);
|
|
220
|
+
this.namedHandlerNames.set(reminder.definition, reminder.name);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/** True when create/cancel/rekey/fire go through the CP protocol. */
|
|
225
|
+
private get usesControlPlaneProtocol(): boolean {
|
|
226
|
+
return this.controlPlane !== undefined && this.architecture === "v2";
|
|
227
|
+
}
|
|
110
228
|
|
|
111
229
|
/**
|
|
112
230
|
* Load reminder documents from the control plane into memory. Does not
|
|
@@ -136,6 +254,13 @@ export class ReminderRunner {
|
|
|
136
254
|
if (record.status !== "armed") {
|
|
137
255
|
continue;
|
|
138
256
|
}
|
|
257
|
+
if (record.handler !== undefined) {
|
|
258
|
+
if (this.namedHandlers.get(record.handler) === undefined) {
|
|
259
|
+
await this.disarm(record, "handler_missing");
|
|
260
|
+
disarmedOrphan += 1;
|
|
261
|
+
}
|
|
262
|
+
continue;
|
|
263
|
+
}
|
|
139
264
|
if (
|
|
140
265
|
(record.hasRunHandler === true || record.hasUntilFn === true) &&
|
|
141
266
|
this.handlers.get(record.id) === undefined
|
|
@@ -168,6 +293,16 @@ export class ReminderRunner {
|
|
|
168
293
|
let restored = 0;
|
|
169
294
|
let disarmedOrphan = 0;
|
|
170
295
|
for (const record of armed) {
|
|
296
|
+
if (record.handler !== undefined) {
|
|
297
|
+
if (this.namedHandlers.get(record.handler) === undefined) {
|
|
298
|
+
await this.disarm(record, "handler_missing");
|
|
299
|
+
disarmedOrphan += 1;
|
|
300
|
+
continue;
|
|
301
|
+
}
|
|
302
|
+
this.armTimer(record);
|
|
303
|
+
restored += 1;
|
|
304
|
+
continue;
|
|
305
|
+
}
|
|
171
306
|
if (
|
|
172
307
|
(record.hasRunHandler === true || record.hasUntilFn === true) &&
|
|
173
308
|
this.handlers.get(record.id) === undefined
|
|
@@ -249,9 +384,11 @@ export class ReminderRunner {
|
|
|
249
384
|
async create(input: ReminderCreateInput): Promise<ReminderInfo> {
|
|
250
385
|
const hasPrompt = input.prompt !== undefined;
|
|
251
386
|
const hasRun = input.run !== undefined;
|
|
252
|
-
|
|
387
|
+
const hasHandler = input.handler !== undefined;
|
|
388
|
+
const formCount = [hasPrompt, hasRun, hasHandler].filter(Boolean).length;
|
|
389
|
+
if (formCount !== 1) {
|
|
253
390
|
throw new ReminderValidationError(
|
|
254
|
-
"reminders.create requires exactly one of prompt or run"
|
|
391
|
+
"reminders.create requires exactly one of prompt, handler, or run"
|
|
255
392
|
);
|
|
256
393
|
}
|
|
257
394
|
if (input.continuationToken.trim() === "") {
|
|
@@ -264,46 +401,136 @@ export class ReminderRunner {
|
|
|
264
401
|
throw new ReminderValidationError("purpose is required");
|
|
265
402
|
}
|
|
266
403
|
|
|
267
|
-
const schedule = resolveSchedule(input);
|
|
268
|
-
const busyPolicy: ReminderBusyPolicy =
|
|
269
|
-
input.busyPolicy ?? defaultBusyPolicy(schedule.kind);
|
|
270
|
-
const now = new Date().toISOString();
|
|
271
|
-
const id = newReminderId();
|
|
272
|
-
|
|
273
404
|
const untilPrompt =
|
|
274
405
|
typeof input.until === "string" ? input.until : undefined;
|
|
275
406
|
const untilFn = typeof input.until === "function" ? input.until : undefined;
|
|
407
|
+
|
|
408
|
+
if (hasHandler && input.until !== undefined) {
|
|
409
|
+
throw new ReminderValidationError(
|
|
410
|
+
"reminders.create: until is not valid with handler; encode the stop condition in args and the handler body"
|
|
411
|
+
);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
if (this.rejectAnonymousHandlers) {
|
|
415
|
+
if (hasRun) {
|
|
416
|
+
throw new ReminderValidationError(
|
|
417
|
+
"reminders.create: anonymous run handlers are not durable on architecture v2; author agent/reminders/<name>.ts and pass handler + args"
|
|
418
|
+
);
|
|
419
|
+
}
|
|
420
|
+
if (untilFn !== undefined) {
|
|
421
|
+
throw new ReminderValidationError(
|
|
422
|
+
"reminders.create: function until is not durable on architecture v2; use a string until prompt"
|
|
423
|
+
);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
let handlerName: string | undefined;
|
|
428
|
+
let handlerArgs: JsonObject | undefined;
|
|
429
|
+
if (hasHandler) {
|
|
430
|
+
const handler = input.handler!;
|
|
431
|
+
const name =
|
|
432
|
+
typeof handler === "string"
|
|
433
|
+
? handler.trim()
|
|
434
|
+
: this.namedHandlerNames.get(handler);
|
|
435
|
+
if (name === undefined) {
|
|
436
|
+
throw new ReminderValidationError(
|
|
437
|
+
"Unknown reminder handler definition (expected a default export discovered under agent/reminders/)"
|
|
438
|
+
);
|
|
439
|
+
}
|
|
440
|
+
if (name === "") {
|
|
441
|
+
throw new ReminderValidationError("handler name is required");
|
|
442
|
+
}
|
|
443
|
+
if (!isValidReminderHandlerName(name)) {
|
|
444
|
+
throw new ReminderValidationError(
|
|
445
|
+
name.includes("__")
|
|
446
|
+
? `Invalid reminder handler name "${name}": may not contain "__"`
|
|
447
|
+
: `Invalid reminder handler name "${name}": must match ${NAME_PATTERN}`
|
|
448
|
+
);
|
|
449
|
+
}
|
|
450
|
+
if (this.namedHandlers.get(name) === undefined) {
|
|
451
|
+
throw new ReminderValidationError(
|
|
452
|
+
`Unknown reminder handler "${name}" (expected agent/reminders/${name}.ts)`
|
|
453
|
+
);
|
|
454
|
+
}
|
|
455
|
+
if (input.args !== undefined && !isJsonObject(input.args)) {
|
|
456
|
+
throw new ReminderValidationError(
|
|
457
|
+
"reminders.create args must be a JSON object"
|
|
458
|
+
);
|
|
459
|
+
}
|
|
460
|
+
handlerName = name;
|
|
461
|
+
handlerArgs = input.args ?? {};
|
|
462
|
+
assertReminderArgsSize(handlerArgs);
|
|
463
|
+
} else if (input.args !== undefined) {
|
|
464
|
+
throw new ReminderValidationError(
|
|
465
|
+
"reminders.create args is only valid with handler"
|
|
466
|
+
);
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
const schedule = resolveSchedule(input);
|
|
470
|
+
const busyPolicy: ReminderBusyPolicy =
|
|
471
|
+
input.busyPolicy ?? defaultBusyPolicy(schedule.kind);
|
|
276
472
|
const hasRunHandler = input.run !== undefined;
|
|
277
473
|
const hasUntilFn = untilFn !== undefined;
|
|
278
474
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
}
|
|
475
|
+
let record: ReminderRecord;
|
|
476
|
+
if (this.usesControlPlaneProtocol) {
|
|
477
|
+
const intent: ReminderCreateIntent = {
|
|
478
|
+
protocolVersion: REMINDER_CP_PROTOCOL_VERSION,
|
|
479
|
+
purpose: input.purpose,
|
|
480
|
+
channelId: input.channelId,
|
|
481
|
+
continuationToken: input.continuationToken,
|
|
482
|
+
target: input.target,
|
|
483
|
+
// CP recalculates nextFireAtMs / intervalMs from the raw schedule.
|
|
484
|
+
schedule: scheduleSpecFromCreateInput(input),
|
|
485
|
+
prompt: input.prompt,
|
|
486
|
+
handler: handlerName,
|
|
487
|
+
args: handlerArgs,
|
|
488
|
+
hasRunHandler,
|
|
489
|
+
hasUntilFn,
|
|
490
|
+
untilPrompt,
|
|
491
|
+
busyPolicy,
|
|
492
|
+
};
|
|
493
|
+
record = await this.controlPlane!.createReminder(intent);
|
|
494
|
+
this.records.set(record.id, record);
|
|
495
|
+
} else {
|
|
496
|
+
const now = new Date().toISOString();
|
|
497
|
+
const id = newReminderId();
|
|
498
|
+
record = {
|
|
499
|
+
version: 1,
|
|
500
|
+
id,
|
|
501
|
+
purpose: input.purpose,
|
|
502
|
+
channelId: input.channelId,
|
|
503
|
+
continuationToken: input.continuationToken,
|
|
504
|
+
target: input.target,
|
|
505
|
+
scheduleKind: schedule.kind,
|
|
506
|
+
scheduleValue: schedule.value,
|
|
507
|
+
intervalMs: schedule.intervalMs,
|
|
508
|
+
prompt: input.prompt,
|
|
509
|
+
handler: handlerName,
|
|
510
|
+
args: handlerArgs,
|
|
511
|
+
hasRunHandler,
|
|
512
|
+
hasUntilFn,
|
|
513
|
+
untilPrompt,
|
|
514
|
+
busyPolicy,
|
|
515
|
+
status: "armed",
|
|
516
|
+
fireCount: 0,
|
|
517
|
+
nextFireAtMs: schedule.nextFireAtMs,
|
|
518
|
+
generation: 0,
|
|
519
|
+
createdAt: now,
|
|
520
|
+
updatedAt: now,
|
|
521
|
+
};
|
|
522
|
+
await this.persist(record);
|
|
523
|
+
}
|
|
300
524
|
|
|
301
|
-
|
|
302
|
-
this.handlers.set(id, {
|
|
525
|
+
this.handlers.set(record.id, {
|
|
303
526
|
run: input.run,
|
|
304
527
|
untilFn,
|
|
305
528
|
});
|
|
306
|
-
if (
|
|
529
|
+
if (
|
|
530
|
+
this.started &&
|
|
531
|
+
this.platformTimers === undefined &&
|
|
532
|
+
!this.usesControlPlaneProtocol
|
|
533
|
+
) {
|
|
307
534
|
this.armTimer(record);
|
|
308
535
|
}
|
|
309
536
|
|
|
@@ -311,15 +538,18 @@ export class ReminderRunner {
|
|
|
311
538
|
}
|
|
312
539
|
|
|
313
540
|
async list(filter?: {
|
|
314
|
-
status?:
|
|
541
|
+
status?: ReminderStatus;
|
|
315
542
|
purpose?: string;
|
|
316
543
|
continuationToken?: string;
|
|
317
544
|
}): Promise<ReminderInfo[]> {
|
|
318
545
|
const all = await this.allRecords();
|
|
319
546
|
return all
|
|
320
547
|
.filter((r) => {
|
|
321
|
-
if (filter?.status !== undefined
|
|
322
|
-
|
|
548
|
+
if (filter?.status !== undefined) {
|
|
549
|
+
const publicStatus = r.status === "firing" ? "armed" : r.status;
|
|
550
|
+
if (publicStatus !== filter.status) {
|
|
551
|
+
return false;
|
|
552
|
+
}
|
|
323
553
|
}
|
|
324
554
|
if (filter?.purpose !== undefined && r.purpose !== filter.purpose) {
|
|
325
555
|
return false;
|
|
@@ -348,11 +578,22 @@ export class ReminderRunner {
|
|
|
348
578
|
id: string,
|
|
349
579
|
reason = "explicit_cancel"
|
|
350
580
|
): Promise<ReminderInfo | undefined> {
|
|
581
|
+
if (this.usesControlPlaneProtocol) {
|
|
582
|
+
const updated = await this.controlPlane!.cancelReminder(id, reason);
|
|
583
|
+
if (updated === undefined) {
|
|
584
|
+
this.records.delete(id);
|
|
585
|
+
this.handlers.delete(id);
|
|
586
|
+
return undefined;
|
|
587
|
+
}
|
|
588
|
+
this.records.set(id, updated);
|
|
589
|
+
this.handlers.delete(id);
|
|
590
|
+
return toInfo(updated);
|
|
591
|
+
}
|
|
351
592
|
const record = await this.getRecord(id);
|
|
352
593
|
if (record === undefined) {
|
|
353
594
|
return undefined;
|
|
354
595
|
}
|
|
355
|
-
if (record.status !== "armed") {
|
|
596
|
+
if (record.status !== "armed" && record.status !== "firing") {
|
|
356
597
|
return toInfo(record);
|
|
357
598
|
}
|
|
358
599
|
this.clearTimer(id);
|
|
@@ -360,6 +601,7 @@ export class ReminderRunner {
|
|
|
360
601
|
...record,
|
|
361
602
|
status: "cancelled",
|
|
362
603
|
disarmReason: reason,
|
|
604
|
+
generation: (record.generation ?? 0) + 1,
|
|
363
605
|
updatedAt: new Date().toISOString(),
|
|
364
606
|
};
|
|
365
607
|
await this.persist(updated);
|
|
@@ -394,7 +636,12 @@ export class ReminderRunner {
|
|
|
394
636
|
oldToken: string,
|
|
395
637
|
newToken: string
|
|
396
638
|
): Promise<number> {
|
|
397
|
-
|
|
639
|
+
if (this.usesControlPlaneProtocol) {
|
|
640
|
+
return this.controlPlane!.rekeyReminders(channelId, oldToken, newToken);
|
|
641
|
+
}
|
|
642
|
+
const armed = (await this.allRecords()).filter(
|
|
643
|
+
(r) => r.status === "armed" || r.status === "firing"
|
|
644
|
+
);
|
|
398
645
|
let n = 0;
|
|
399
646
|
for (const record of armed) {
|
|
400
647
|
if (
|
|
@@ -406,6 +653,7 @@ export class ReminderRunner {
|
|
|
406
653
|
await this.persist({
|
|
407
654
|
...record,
|
|
408
655
|
continuationToken: newToken,
|
|
656
|
+
generation: (record.generation ?? 0) + 1,
|
|
409
657
|
updatedAt: new Date().toISOString(),
|
|
410
658
|
});
|
|
411
659
|
n += 1;
|
|
@@ -441,6 +689,121 @@ export class ReminderRunner {
|
|
|
441
689
|
return { reminderId, ...result };
|
|
442
690
|
}
|
|
443
691
|
|
|
692
|
+
/**
|
|
693
|
+
* Architecture v2 / CP protocol guest entrypoint: execute an immutable fire
|
|
694
|
+
* descriptor and return an outcome. Does not mint ids or mutate
|
|
695
|
+
* authoritative status/fireCount — the control plane applies the outcome.
|
|
696
|
+
*/
|
|
697
|
+
async executeFire(
|
|
698
|
+
descriptor: ReminderFireDescriptor
|
|
699
|
+
): Promise<ReminderExecutionOutcome> {
|
|
700
|
+
const record = this.recordFromDescriptor(descriptor);
|
|
701
|
+
this.records.set(record.id, record);
|
|
702
|
+
|
|
703
|
+
const live = this.handlers.get(record.id) ?? {};
|
|
704
|
+
if (record.handler !== undefined) {
|
|
705
|
+
if (this.resolveNamedHandler(record.handler) === undefined) {
|
|
706
|
+
return { kind: "stop", reason: "handler_missing" };
|
|
707
|
+
}
|
|
708
|
+
} else if (
|
|
709
|
+
(record.hasRunHandler === true || record.hasUntilFn === true) &&
|
|
710
|
+
live.run === undefined &&
|
|
711
|
+
live.untilFn === undefined
|
|
712
|
+
) {
|
|
713
|
+
return { kind: "stop", reason: "handler_lost_on_restart" };
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
if (live.untilFn !== undefined) {
|
|
717
|
+
try {
|
|
718
|
+
const done = await live.untilFn(this.buildUntilContext(record));
|
|
719
|
+
if (done) {
|
|
720
|
+
return { kind: "stop", reason: "until_fn" };
|
|
721
|
+
}
|
|
722
|
+
} catch (error) {
|
|
723
|
+
this.logger(
|
|
724
|
+
`[agent-sdk] reminder "${record.id}" until() failed: ${
|
|
725
|
+
error instanceof Error ? error.message : String(error)
|
|
726
|
+
}`
|
|
727
|
+
);
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
if (await this.isSessionBusy(record.channelId, record.continuationToken)) {
|
|
732
|
+
if (record.busyPolicy === "skipIfBusy") {
|
|
733
|
+
this.logger(
|
|
734
|
+
`[agent-sdk] reminder "${record.id}" (${record.purpose}) skipped: session busy`
|
|
735
|
+
);
|
|
736
|
+
return { kind: "skipped" };
|
|
737
|
+
}
|
|
738
|
+
await this.whenSessionIdle(record.channelId, record.continuationToken);
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
let result: ReminderFireResult;
|
|
742
|
+
if (record.handler !== undefined) {
|
|
743
|
+
const named = this.resolveNamedHandler(record.handler);
|
|
744
|
+
if (named === undefined) {
|
|
745
|
+
return { kind: "stop", reason: "handler_missing" };
|
|
746
|
+
}
|
|
747
|
+
result = await named.run(this.buildFireContext(record));
|
|
748
|
+
} else if (live.run !== undefined) {
|
|
749
|
+
result = await live.run(this.buildFireContext(record));
|
|
750
|
+
} else if (record.prompt !== undefined) {
|
|
751
|
+
result = await this.deliverPrompt(record);
|
|
752
|
+
} else {
|
|
753
|
+
return { kind: "stop", reason: "missing_handler" };
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
if (result.action === "stop") {
|
|
757
|
+
return { kind: "stop", reason: "run_stop" };
|
|
758
|
+
}
|
|
759
|
+
if (result.action === "skip") {
|
|
760
|
+
return {
|
|
761
|
+
kind: "skipped",
|
|
762
|
+
reschedule:
|
|
763
|
+
result.reschedule !== undefined
|
|
764
|
+
? toWireReschedule(result.reschedule)
|
|
765
|
+
: undefined,
|
|
766
|
+
};
|
|
767
|
+
}
|
|
768
|
+
return {
|
|
769
|
+
kind: "delivered",
|
|
770
|
+
reschedule:
|
|
771
|
+
result.reschedule !== undefined
|
|
772
|
+
? toWireReschedule(result.reschedule)
|
|
773
|
+
: undefined,
|
|
774
|
+
};
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
private recordFromDescriptor(
|
|
778
|
+
descriptor: ReminderFireDescriptor
|
|
779
|
+
): ReminderRecord {
|
|
780
|
+
const now = new Date().toISOString();
|
|
781
|
+
return {
|
|
782
|
+
version: 1,
|
|
783
|
+
id: descriptor.id,
|
|
784
|
+
purpose: descriptor.purpose,
|
|
785
|
+
channelId: descriptor.channelId,
|
|
786
|
+
continuationToken: descriptor.continuationToken,
|
|
787
|
+
target: descriptor.target,
|
|
788
|
+
scheduleKind: descriptor.scheduleKind,
|
|
789
|
+
scheduleValue: descriptor.scheduleValue,
|
|
790
|
+
intervalMs: descriptor.intervalMs,
|
|
791
|
+
prompt: descriptor.prompt,
|
|
792
|
+
handler: descriptor.handler,
|
|
793
|
+
args: descriptor.args,
|
|
794
|
+
hasRunHandler: descriptor.hasRunHandler,
|
|
795
|
+
hasUntilFn: descriptor.hasUntilFn,
|
|
796
|
+
untilPrompt: descriptor.untilPrompt,
|
|
797
|
+
busyPolicy: descriptor.busyPolicy,
|
|
798
|
+
status: "firing",
|
|
799
|
+
fireCount: descriptor.fireCount,
|
|
800
|
+
nextFireAtMs: descriptor.nextFireAtMs,
|
|
801
|
+
generation: descriptor.generation,
|
|
802
|
+
createdAt: now,
|
|
803
|
+
updatedAt: now,
|
|
804
|
+
};
|
|
805
|
+
}
|
|
806
|
+
|
|
444
807
|
private armTimer(record: ReminderRecord): void {
|
|
445
808
|
this.clearTimer(record.id);
|
|
446
809
|
if (!this.started || record.status !== "armed") return;
|
|
@@ -493,6 +856,10 @@ export class ReminderRunner {
|
|
|
493
856
|
}
|
|
494
857
|
}
|
|
495
858
|
|
|
859
|
+
private resolveNamedHandler(name: string): ReminderDefinition | undefined {
|
|
860
|
+
return this.namedHandlers.get(name);
|
|
861
|
+
}
|
|
862
|
+
|
|
496
863
|
private async fire(
|
|
497
864
|
id: string,
|
|
498
865
|
opts: { force?: boolean } = {}
|
|
@@ -515,7 +882,12 @@ export class ReminderRunner {
|
|
|
515
882
|
}
|
|
516
883
|
|
|
517
884
|
const live = this.handlers.get(id) ?? {};
|
|
518
|
-
if (
|
|
885
|
+
if (record.handler !== undefined) {
|
|
886
|
+
if (this.resolveNamedHandler(record.handler) === undefined) {
|
|
887
|
+
await this.disarm(record, "handler_missing");
|
|
888
|
+
return { outcome: "noop", reason: "handler_missing" };
|
|
889
|
+
}
|
|
890
|
+
} else if (
|
|
519
891
|
(record.hasRunHandler === true || record.hasUntilFn === true) &&
|
|
520
892
|
live.run === undefined &&
|
|
521
893
|
live.untilFn === undefined
|
|
@@ -560,9 +932,15 @@ export class ReminderRunner {
|
|
|
560
932
|
}
|
|
561
933
|
|
|
562
934
|
let result: ReminderFireResult;
|
|
563
|
-
if (
|
|
564
|
-
const
|
|
565
|
-
|
|
935
|
+
if (record.handler !== undefined) {
|
|
936
|
+
const named = this.resolveNamedHandler(record.handler);
|
|
937
|
+
if (named === undefined) {
|
|
938
|
+
await this.disarm(record, "handler_missing");
|
|
939
|
+
return { outcome: "noop", reason: "handler_missing" };
|
|
940
|
+
}
|
|
941
|
+
result = await named.run(this.buildFireContext(record));
|
|
942
|
+
} else if (live.run !== undefined) {
|
|
943
|
+
result = await live.run(this.buildFireContext(record));
|
|
566
944
|
} else if (record.prompt !== undefined) {
|
|
567
945
|
result = await this.deliverPrompt(record);
|
|
568
946
|
} else {
|
|
@@ -595,7 +973,7 @@ export class ReminderRunner {
|
|
|
595
973
|
return { outcome: "fired", reason: "skipped" };
|
|
596
974
|
}
|
|
597
975
|
await this.afterFire(latest, "delivered", result.reschedule);
|
|
598
|
-
this.logger(`[agent-sdk] reminder "${id}" (${record.purpose})
|
|
976
|
+
this.logger(`[agent-sdk] reminder "${id}" (${record.purpose}) fired`);
|
|
599
977
|
return { outcome: "fired", reason: "delivered" };
|
|
600
978
|
} finally {
|
|
601
979
|
this.firing.delete(id);
|
|
@@ -662,22 +1040,66 @@ export class ReminderRunner {
|
|
|
662
1040
|
record.continuationToken
|
|
663
1041
|
);
|
|
664
1042
|
if (auth === undefined) {
|
|
665
|
-
|
|
1043
|
+
// Under CP protocol, return stop and let the CP apply/CAS; do not
|
|
1044
|
+
// mutate authoritative status from the guest mid-fire.
|
|
1045
|
+
if (!this.usesControlPlaneProtocol) {
|
|
1046
|
+
await this.disarm(record, "session_gone");
|
|
1047
|
+
}
|
|
666
1048
|
return { action: "stop" };
|
|
667
1049
|
}
|
|
668
1050
|
return this.sendFollowup(record, buildFirePrompt(record), auth);
|
|
669
1051
|
}
|
|
670
1052
|
|
|
1053
|
+
/**
|
|
1054
|
+
* Join the reminder's existing session. Control-plane (`/v2`) channels
|
|
1055
|
+
* refuse authored `continuationToken`; pass the stored key as
|
|
1056
|
+
* {@link EngineSendOptions.mailboxContinuation} so the engine reuses the
|
|
1057
|
+
* CP-selected identity without channel admission.
|
|
1058
|
+
*/
|
|
1059
|
+
private followupSendOptions(
|
|
1060
|
+
record: ReminderRecord,
|
|
1061
|
+
auth: AuthContext | null
|
|
1062
|
+
): EngineSendOptions {
|
|
1063
|
+
if (this.channelUsesControlPlaneContinuation(record.channelId)) {
|
|
1064
|
+
return {
|
|
1065
|
+
auth,
|
|
1066
|
+
mailboxContinuation: { key: record.continuationToken },
|
|
1067
|
+
};
|
|
1068
|
+
}
|
|
1069
|
+
return {
|
|
1070
|
+
auth,
|
|
1071
|
+
continuationToken: record.continuationToken,
|
|
1072
|
+
};
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
private channelUsesControlPlaneContinuation(channelId: string): boolean {
|
|
1076
|
+
const project = this.engine.project;
|
|
1077
|
+
// Test doubles may omit `project`; keep the legacy continuationToken path.
|
|
1078
|
+
if (project === undefined) {
|
|
1079
|
+
return false;
|
|
1080
|
+
}
|
|
1081
|
+
const identity =
|
|
1082
|
+
channelId === HTTP_CHANNEL_ID
|
|
1083
|
+
? httpContinuationIdentity(project.httpChannel)
|
|
1084
|
+
: channelContinuationIdentity(
|
|
1085
|
+
project.channels.find((channel) => channel.id === channelId)
|
|
1086
|
+
?.definition
|
|
1087
|
+
);
|
|
1088
|
+
return continuationSource(identity) === "control-plane";
|
|
1089
|
+
}
|
|
1090
|
+
|
|
671
1091
|
private async sendFollowup(
|
|
672
1092
|
record: ReminderRecord,
|
|
673
1093
|
message: string,
|
|
674
1094
|
auth: AuthContext | null
|
|
675
1095
|
): Promise<ReminderFireResult> {
|
|
1096
|
+
const sendOptions = this.followupSendOptions(record, auth);
|
|
676
1097
|
try {
|
|
677
|
-
const session = await this.engine.send(
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
1098
|
+
const session = await this.engine.send(
|
|
1099
|
+
record.channelId,
|
|
1100
|
+
message,
|
|
1101
|
+
sendOptions
|
|
1102
|
+
);
|
|
681
1103
|
this.engine.trackBackground(this.engine.waitForCompletion(session.id));
|
|
682
1104
|
return { action: "delivered" };
|
|
683
1105
|
} catch (error) {
|
|
@@ -687,10 +1109,11 @@ export class ReminderRunner {
|
|
|
687
1109
|
}
|
|
688
1110
|
await this.whenSessionIdle(record.channelId, record.continuationToken);
|
|
689
1111
|
try {
|
|
690
|
-
const session = await this.engine.send(
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
1112
|
+
const session = await this.engine.send(
|
|
1113
|
+
record.channelId,
|
|
1114
|
+
message,
|
|
1115
|
+
sendOptions
|
|
1116
|
+
);
|
|
694
1117
|
this.engine.trackBackground(
|
|
695
1118
|
this.engine.waitForCompletion(session.id)
|
|
696
1119
|
);
|
|
@@ -721,6 +1144,7 @@ export class ReminderRunner {
|
|
|
721
1144
|
continuationToken: record.continuationToken,
|
|
722
1145
|
...(record.target ?? {}),
|
|
723
1146
|
},
|
|
1147
|
+
args: record.args ?? {},
|
|
724
1148
|
host: this.engine.host,
|
|
725
1149
|
mcp: this.engine.host.mcp,
|
|
726
1150
|
appAuth: APP_AUTH,
|