@cursor/july 0.1.95 → 0.1.97
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 +3 -4
- package/README.md +3 -2
- package/dist/bin/agent-serve.js +14 -3
- package/dist/channels/deployments/types.d.ts +1 -1
- package/dist/channels/deployments/types.d.ts.map +1 -1
- package/dist/channels/deployments/types.js +1 -0
- package/dist/channels/origin/api.d.ts +72 -15
- package/dist/channels/origin/api.d.ts.map +1 -1
- package/dist/channels/origin/api.js +185 -28
- package/dist/channels/origin/binding.d.ts +13 -2
- package/dist/channels/origin/binding.d.ts.map +1 -1
- package/dist/channels/origin/binding.js +41 -25
- package/dist/channels/origin/checks.d.ts +6 -6
- package/dist/channels/origin/checks.js +6 -6
- package/dist/channels/origin/cursor-account.d.ts +5 -3
- package/dist/channels/origin/cursor-account.d.ts.map +1 -1
- package/dist/channels/origin/cursor-account.js +5 -3
- 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.map +1 -1
- package/dist/channels/origin/origin-channel.js +3 -0
- 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/api.d.ts +9 -0
- package/dist/channels/slack/api.d.ts.map +1 -1
- package/dist/channels/slack/api.js +36 -5
- 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 +110 -81
- package/dist/channels/slack/dispatch.d.ts +7 -1
- package/dist/channels/slack/dispatch.d.ts.map +1 -1
- package/dist/channels/slack/dispatch.js +47 -23
- package/dist/channels/slack/inbound.d.ts +8 -0
- package/dist/channels/slack/inbound.d.ts.map +1 -1
- package/dist/channels/slack/inbound.js +32 -0
- 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 +26 -29
- package/dist/channels/slack/live-delivery.d.ts.map +1 -1
- package/dist/channels/slack/live-delivery.js +172 -73
- package/dist/channels/slack/manifest.d.ts +1 -1
- package/dist/channels/slack/manifest.d.ts.map +1 -1
- package/dist/channels/slack/manifest.js +6 -2
- package/dist/channels/slack/nudge-carrier.d.ts +2 -0
- package/dist/channels/slack/nudge-carrier.d.ts.map +1 -1
- package/dist/channels/slack/nudge-carrier.js +48 -1
- 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 +3 -2
- package/dist/channels/slack/tool-approval-events.d.ts.map +1 -1
- package/dist/channels/slack/tool-approval-events.js +91 -1
- package/dist/docs/404.html +2 -2
- package/dist/docs/ab.html +4 -4
- package/dist/docs/assets/{app.BBj0klBO.js → app.B3rWNYE1.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.BU9nHdnQ.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.CUEXpL78.js → VPLocalSearchBox.C1lhqJJR.js} +1 -1
- package/dist/docs/assets/chunks/{theme.DabmQnia.js → theme.B40_SXuv.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/{index.md.BoHaMdeZ.lean.js → index.md.CVeRUOeZ.lean.js} +1 -1
- 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.BsMOxDvh.js → reference_cli.md.RyZf5OTE.js} +10 -6
- package/dist/docs/assets/{reference_cli.md.BsMOxDvh.lean.js → reference_cli.md.RyZf5OTE.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.5zOAbV86.js} +1 -1
- package/dist/docs/assets/reference_sessions.md.NxFP_CAC.js +1 -0
- package/dist/docs/assets/{reference_tools.md.BHeXn2id.js → reference_tools.md.B84gw9Ii.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/templates_code-wiki.md.CDYZIBFN.js +2 -0
- package/dist/docs/assets/templates_code-wiki.md.CDYZIBFN.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/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 +7 -3
- package/dist/docs/llms-full.txt +398 -653
- 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 +14 -10
- package/dist/docs/reference/cli.md +39 -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 +6 -6
- package/dist/docs/reference/http-api.md +2 -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 +6 -6
- package/dist/docs/reference/tools.md +9 -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 +28 -0
- package/dist/docs/templates/code-wiki.md +91 -0
- package/dist/docs/templates/demo.html +5 -5
- 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 +26 -4
- package/dist/files-backends/cursor-hosted.d.ts.map +1 -1
- package/dist/files-backends/cursor-hosted.js +32 -4
- package/dist/internal/advertise-tools.d.ts +2 -0
- package/dist/internal/advertise-tools.d.ts.map +1 -1
- package/dist/internal/advertise-tools.js +30 -10
- 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/bounded.d.ts +7 -0
- package/dist/internal/bounded.d.ts.map +1 -0
- package/dist/internal/bounded.js +32 -0
- package/dist/internal/chat-client.js +10 -0
- package/dist/internal/cli-deploy.d.ts +5 -0
- package/dist/internal/cli-deploy.d.ts.map +1 -1
- package/dist/internal/cli-deploy.js +57 -18
- 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/conversation-mirror.d.ts +11 -8
- package/dist/internal/conversation-mirror.d.ts.map +1 -1
- package/dist/internal/conversation-mirror.js +116 -55
- 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/backend-client.d.ts.map +1 -1
- package/dist/internal/cursor/backend-client.js +22 -48
- package/dist/internal/cursor/session-token.d.ts +45 -0
- package/dist/internal/cursor/session-token.d.ts.map +1 -0
- package/dist/internal/cursor/session-token.js +99 -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 +2 -0
- 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 +61 -0
- package/dist/internal/framework-file-storage.d.ts.map +1 -0
- package/dist/internal/framework-file-storage.js +210 -0
- package/dist/internal/framework-storage-selection.d.ts +11 -5
- package/dist/internal/framework-storage-selection.d.ts.map +1 -1
- package/dist/internal/framework-storage-selection.js +38 -11
- package/dist/internal/hosted-delivery-protocol.d.ts +7 -0
- package/dist/internal/hosted-delivery-protocol.d.ts.map +1 -1
- package/dist/internal/hosted-delivery-protocol.js +7 -0
- package/dist/internal/hosted-delivery.d.ts +13 -0
- package/dist/internal/hosted-delivery.d.ts.map +1 -1
- package/dist/internal/hosted-delivery.js +64 -19
- package/dist/internal/hosted-execution-diag.d.ts +48 -0
- package/dist/internal/hosted-execution-diag.d.ts.map +1 -0
- package/dist/internal/hosted-execution-diag.js +150 -0
- package/dist/internal/http-channel.d.ts.map +1 -1
- package/dist/internal/http-channel.js +81 -1
- package/dist/internal/init-project.d.ts.map +1 -1
- package/dist/internal/init-project.js +4 -0
- package/dist/internal/install-cursor-skills.d.ts.map +1 -1
- package/dist/internal/install-cursor-skills.js +1 -3
- 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/managed-delivery.d.ts +80 -0
- package/dist/internal/managed-delivery.d.ts.map +1 -0
- package/dist/internal/managed-delivery.js +86 -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/otel/collector.d.ts.map +1 -1
- package/dist/internal/otel/collector.js +22 -9
- package/dist/internal/runtime-dispatch-runner.d.ts +5 -1
- package/dist/internal/runtime-dispatch-runner.d.ts.map +1 -1
- package/dist/internal/runtime-dispatch-runner.js +7 -0
- package/dist/internal/sdk-runner.d.ts +11 -0
- package/dist/internal/sdk-runner.d.ts.map +1 -1
- package/dist/internal/sdk-runner.js +39 -8
- package/dist/internal/server.d.ts +3 -0
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +49 -21
- package/dist/internal/session-engine.d.ts +101 -3
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +577 -46
- 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/steering.d.ts +15 -0
- package/dist/internal/steering.d.ts.map +1 -0
- package/dist/internal/steering.js +18 -0
- package/dist/internal/storage-coordinator.d.ts +7 -0
- package/dist/internal/storage-coordinator.d.ts.map +1 -1
- package/dist/internal/storage-coordinator.js +28 -5
- 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 +9 -1
- package/dist/internal/tool-policy.d.ts.map +1 -1
- package/dist/internal/tool-policy.js +13 -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-CZA1uEWA.js → index-DrkI6y5O.js} +51 -51
- package/dist/playground/assets/index-DzNGwm7q.css +1 -0
- package/dist/playground/index.html +2 -2
- package/dist/storage-backends/cursor-hosted.d.ts +9 -6
- package/dist/storage-backends/cursor-hosted.d.ts.map +1 -1
- package/dist/storage-backends/cursor-hosted.js +16 -3
- package/dist/storage.d.ts +8 -0
- package/dist/storage.d.ts.map +1 -1
- package/dist/types.d.ts +65 -8
- package/dist/types.d.ts.map +1 -1
- package/docs/README.md +7 -3
- package/docs/deployment.md +5 -4
- 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 +39 -16
- package/docs/reference/connections.md +6 -3
- package/docs/reference/http-api.md +2 -1
- package/docs/reference/sessions.md +4 -2
- package/docs/reference/tools.md +9 -2
- package/docs/templates/agents-md.md +110 -0
- package/docs/templates/code-wiki.md +96 -0
- package/docs/troubleshooting.md +2 -2
- package/package.json +2 -2
- package/skills/ab/SKILL.md +13 -97
- package/skills/create-agent/SKILL.md +124 -223
- package/skills/debug/SKILL.md +34 -68
- package/skills/evals/SKILL.md +55 -180
- package/skills/framework-map/SKILL.md +83 -145
- package/skills/github/SKILL.md +53 -111
- package/skills/hillclimb/SKILL.md +40 -163
- package/skills/mcp-auth/SKILL.md +51 -107
- package/skills/otel/SKILL.md +22 -68
- package/skills/setup-slack/SKILL.md +91 -212
- package/src/bin/agent-serve.ts +13 -1
- package/src/channels/deployments/types.ts +1 -0
- package/src/channels/origin/api.ts +264 -33
- package/src/channels/origin/binding.ts +57 -28
- package/src/channels/origin/checks.ts +6 -6
- package/src/channels/origin/cursor-account.ts +5 -3
- package/src/channels/origin/index.ts +1 -0
- package/src/channels/origin/origin-channel.ts +4 -0
- package/src/channels/origin/reactions.ts +82 -0
- package/src/channels/origin/types.ts +11 -0
- package/src/channels/slack/api.ts +41 -5
- package/src/channels/slack/approvals.ts +105 -0
- package/src/channels/slack/cli-project.ts +267 -0
- package/src/channels/slack/defaults.ts +122 -93
- package/src/channels/slack/dispatch.ts +56 -22
- package/src/channels/slack/inbound.ts +43 -0
- package/src/channels/slack/init.ts +10 -5
- package/src/channels/slack/interactive.ts +35 -9
- package/src/channels/slack/live-delivery.ts +235 -114
- package/src/channels/slack/manifest.ts +6 -2
- package/src/channels/slack/nudge-carrier.ts +48 -1
- package/src/channels/slack/setup.ts +10 -6
- package/src/channels/slack/slack-channel.ts +3 -0
- package/src/channels/slack/tool-approval-events.ts +93 -0
- package/src/evals/run-facts.ts +32 -0
- package/src/files-backends/cursor-hosted.ts +40 -7
- package/src/internal/advertise-tools.ts +49 -12
- package/src/internal/approval-gate.ts +20 -29
- package/src/internal/bounded.ts +28 -0
- package/src/internal/chat-client.ts +19 -0
- package/src/internal/cli-deploy.ts +91 -9
- 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/conversation-mirror.ts +145 -69
- package/src/internal/cursor/account-mcp.ts +21 -0
- package/src/internal/cursor/backend-client.ts +34 -58
- package/src/internal/cursor/session-token.ts +115 -0
- package/src/internal/cursor-agent-template.ts +2 -0
- package/src/internal/deploy-client.ts +43 -0
- package/src/internal/env-file.ts +84 -0
- package/src/internal/framework-file-storage.ts +228 -0
- package/src/internal/framework-storage-selection.ts +51 -11
- package/src/internal/hosted-delivery-protocol.ts +7 -0
- package/src/internal/hosted-delivery.ts +107 -24
- package/src/internal/hosted-execution-diag.ts +207 -0
- package/src/internal/http-channel.ts +99 -0
- package/src/internal/init-project.ts +4 -0
- package/src/internal/install-cursor-skills.ts +1 -4
- package/src/internal/logs-client.ts +5 -0
- package/src/internal/managed-delivery.ts +125 -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/otel/collector.ts +30 -0
- package/src/internal/runtime-dispatch-runner.ts +10 -0
- package/src/internal/sdk-runner.ts +56 -8
- package/src/internal/server.ts +61 -9
- package/src/internal/session-engine.ts +723 -60
- package/src/internal/sessions-client.ts +17 -8
- package/src/internal/steering.ts +17 -0
- package/src/internal/storage-coordinator.ts +38 -8
- package/src/internal/storage-roles.ts +7 -0
- package/src/internal/stream-progress.ts +19 -0
- package/src/internal/tool-policy.ts +18 -0
- package/src/internal/trajectory.ts +10 -0
- package/src/internal/turn-outbox.ts +85 -0
- package/src/storage-backends/cursor-hosted.ts +22 -8
- package/src/storage.ts +12 -0
- package/src/types.ts +70 -9
- 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/templates/code-wiki/README.md +34 -0
- package/templates/code-wiki/agent/agent.ts +8 -0
- package/templates/code-wiki/agent/channels/github.ts +144 -0
- package/templates/code-wiki/agent/instructions.md +39 -0
- package/templates/code-wiki/agent/lib/repos.ts +5 -0
- package/templates/code-wiki/agent/lib/wiki.ts +22 -0
- package/templates/code-wiki/agent/tools/apply_wiki.ts +219 -0
- package/templates/code-wiki/evals/evals.config.ts +5 -0
- package/templates/code-wiki/evals/wiki.eval.ts +132 -0
- package/templates/code-wiki/init.json +25 -0
- package/templates/code-wiki/package.json +18 -0
- package/templates/code-wiki/tsconfig.json +12 -0
- package/dist/docs/assets/chunks/@localSearchIndexroot.oqPawjiD.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.BoHaMdeZ.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/internal/deployment-scm-event-stream.d.ts +0 -116
- package/dist/internal/deployment-scm-event-stream.d.ts.map +0 -1
- package/dist/internal/deployment-scm-event-stream.js +0 -474
- package/dist/playground/assets/index-CF7hUDnQ.css +0 -1
- package/docs/design/agsh.md +0 -406
- package/src/internal/deployment-scm-event-stream.ts +0 -593
- /package/dist/docs/assets/{deployment.md.D9msOFOW.lean.js → deployment.md.MFPKqsqI.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.5zOAbV86.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/{reference_tools.md.BHeXn2id.lean.js → reference_tools.md.B84gw9Ii.lean.js} +0 -0
- /package/dist/docs/assets/{troubleshooting.md.Ctv3T8C2.lean.js → troubleshooting.md.DCiPBhYs.lean.js} +0 -0
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import type { HostGitHubClient } from "@cursor/july";
|
|
4
|
+
import { defineTool } from "@cursor/july/tools";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
import { agentsPath, parseRepo, updateBranch } from "../lib/paths.js";
|
|
7
|
+
|
|
8
|
+
const file = z.object({
|
|
9
|
+
path: z.string().min(1).max(240),
|
|
10
|
+
content: z.string().min(1).max(64_000),
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
type File = z.infer<typeof file>;
|
|
14
|
+
type Octokit = Awaited<ReturnType<HostGitHubClient["getOctokit"]>>;
|
|
15
|
+
|
|
16
|
+
type Write = {
|
|
17
|
+
octokit: Octokit;
|
|
18
|
+
owner: string;
|
|
19
|
+
repo: string;
|
|
20
|
+
window: string;
|
|
21
|
+
reason: string;
|
|
22
|
+
files: File[];
|
|
23
|
+
base: string;
|
|
24
|
+
branch: string;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export default defineTool({
|
|
28
|
+
description:
|
|
29
|
+
"Skip or open an AGENTS.md follow-up PR for this weekly review. Call once.",
|
|
30
|
+
needsApproval: (input) => input.verdict === "update",
|
|
31
|
+
effect: (input) => (input.verdict === "update" ? "write" : "read"),
|
|
32
|
+
inputSchema: z.discriminatedUnion("verdict", [
|
|
33
|
+
z.object({
|
|
34
|
+
verdict: z.literal("skip"),
|
|
35
|
+
reason: z.string().min(1).max(280),
|
|
36
|
+
}),
|
|
37
|
+
z.object({
|
|
38
|
+
verdict: z.literal("update"),
|
|
39
|
+
reason: z.string().min(1).max(280),
|
|
40
|
+
files: z.array(file).min(1).max(8),
|
|
41
|
+
}),
|
|
42
|
+
]),
|
|
43
|
+
async execute(input, ctx) {
|
|
44
|
+
if (ctx.session.purpose === "eval") {
|
|
45
|
+
return { posted: false, reason: "eval", verdict: input.verdict };
|
|
46
|
+
}
|
|
47
|
+
if (input.verdict === "skip") {
|
|
48
|
+
return { posted: false, reason: input.reason, verdict: "skip" };
|
|
49
|
+
}
|
|
50
|
+
const dir = ctx.workspaceDir;
|
|
51
|
+
const repo = parseRepo(await readTrimmed(dir, "week/repo.txt"));
|
|
52
|
+
const base = await readTrimmed(dir, "week/base.ref");
|
|
53
|
+
const window = await readTrimmed(dir, "week/window.txt");
|
|
54
|
+
const branch = updateBranch(base);
|
|
55
|
+
if (repo === undefined || branch === undefined || window === "") {
|
|
56
|
+
throw new Error("missing week/repo.txt, week/base.ref, or week/window.txt");
|
|
57
|
+
}
|
|
58
|
+
const files = input.files.map((item) => {
|
|
59
|
+
const path = agentsPath(item.path);
|
|
60
|
+
if (path === undefined) {
|
|
61
|
+
throw new Error(`invalid AGENTS.md path: ${item.path}`);
|
|
62
|
+
}
|
|
63
|
+
return { path, content: item.content };
|
|
64
|
+
});
|
|
65
|
+
return openAgentsPr({
|
|
66
|
+
octokit: await ctx.host.github.getOctokit(),
|
|
67
|
+
owner: repo.owner,
|
|
68
|
+
repo: repo.repo,
|
|
69
|
+
window,
|
|
70
|
+
reason: input.reason,
|
|
71
|
+
files,
|
|
72
|
+
base,
|
|
73
|
+
branch,
|
|
74
|
+
});
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
async function openAgentsPr(input: Write) {
|
|
79
|
+
const repo = { owner: input.owner, repo: input.repo };
|
|
80
|
+
const existing = await input.octokit.rest.pulls.list({
|
|
81
|
+
...repo,
|
|
82
|
+
state: "open",
|
|
83
|
+
head: `${input.owner}:${input.branch}`,
|
|
84
|
+
base: input.base,
|
|
85
|
+
per_page: 1,
|
|
86
|
+
});
|
|
87
|
+
const open = existing.data[0];
|
|
88
|
+
if (open !== undefined && citesWindow(open.body, input.window)) {
|
|
89
|
+
return {
|
|
90
|
+
posted: false,
|
|
91
|
+
reason: "exists",
|
|
92
|
+
verdict: "update",
|
|
93
|
+
window: input.window,
|
|
94
|
+
url: open.html_url,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
const branchSha = await refSha(input.octokit, repo, input.branch);
|
|
98
|
+
const parent = branchSha ?? (await refSha(input.octokit, repo, input.base));
|
|
99
|
+
if (parent === undefined) {
|
|
100
|
+
throw new Error(`missing base ref: ${input.base}`);
|
|
101
|
+
}
|
|
102
|
+
const { data: commit } = await input.octokit.rest.git.getCommit({
|
|
103
|
+
...repo,
|
|
104
|
+
commit_sha: parent,
|
|
105
|
+
});
|
|
106
|
+
const blobs = await Promise.all(
|
|
107
|
+
input.files.map(async (item) => {
|
|
108
|
+
const { data } = await input.octokit.rest.git.createBlob({
|
|
109
|
+
...repo,
|
|
110
|
+
content: Buffer.from(item.content).toString("base64"),
|
|
111
|
+
encoding: "base64",
|
|
112
|
+
});
|
|
113
|
+
return {
|
|
114
|
+
path: item.path,
|
|
115
|
+
mode: "100644" as const,
|
|
116
|
+
type: "blob" as const,
|
|
117
|
+
sha: data.sha,
|
|
118
|
+
};
|
|
119
|
+
})
|
|
120
|
+
);
|
|
121
|
+
const { data: tree } = await input.octokit.rest.git.createTree({
|
|
122
|
+
...repo,
|
|
123
|
+
base_tree: commit.tree.sha,
|
|
124
|
+
tree: blobs,
|
|
125
|
+
});
|
|
126
|
+
const { data: next } = await input.octokit.rest.git.createCommit({
|
|
127
|
+
...repo,
|
|
128
|
+
message: `agents.md: ${input.reason}`,
|
|
129
|
+
tree: tree.sha,
|
|
130
|
+
parents: [parent],
|
|
131
|
+
});
|
|
132
|
+
if (branchSha === undefined) {
|
|
133
|
+
await input.octokit.rest.git.createRef({
|
|
134
|
+
...repo,
|
|
135
|
+
ref: `refs/heads/${input.branch}`,
|
|
136
|
+
sha: next.sha,
|
|
137
|
+
});
|
|
138
|
+
} else {
|
|
139
|
+
await input.octokit.rest.git.updateRef({
|
|
140
|
+
...repo,
|
|
141
|
+
ref: `heads/${input.branch}`,
|
|
142
|
+
sha: next.sha,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
if (open !== undefined) {
|
|
146
|
+
await input.octokit.rest.pulls.update({
|
|
147
|
+
...repo,
|
|
148
|
+
pull_number: open.number,
|
|
149
|
+
body: appendWindow(open.body ?? "", input.reason, input.window),
|
|
150
|
+
});
|
|
151
|
+
return {
|
|
152
|
+
posted: true,
|
|
153
|
+
verdict: "update",
|
|
154
|
+
window: input.window,
|
|
155
|
+
url: open.html_url,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
const { data: pull } = await input.octokit.rest.pulls.create({
|
|
159
|
+
...repo,
|
|
160
|
+
title: `agents.md: update for ${input.window}`,
|
|
161
|
+
head: input.branch,
|
|
162
|
+
base: input.base,
|
|
163
|
+
draft: true,
|
|
164
|
+
body: pullBody(input.reason, input.window),
|
|
165
|
+
});
|
|
166
|
+
return {
|
|
167
|
+
posted: true,
|
|
168
|
+
verdict: "update",
|
|
169
|
+
window: input.window,
|
|
170
|
+
url: pull.html_url,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
async function readTrimmed(dir: string, rel: string): Promise<string> {
|
|
175
|
+
return (await readFile(join(dir, rel), "utf8")).trim();
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
async function refSha(
|
|
179
|
+
octokit: Octokit,
|
|
180
|
+
repo: { owner: string; repo: string },
|
|
181
|
+
name: string
|
|
182
|
+
): Promise<string | undefined> {
|
|
183
|
+
try {
|
|
184
|
+
const { data } = await octokit.rest.git.getRef({
|
|
185
|
+
...repo,
|
|
186
|
+
ref: `heads/${name}`,
|
|
187
|
+
});
|
|
188
|
+
return data.object.sha;
|
|
189
|
+
} catch (error) {
|
|
190
|
+
if (isNotFound(error)) {
|
|
191
|
+
return undefined;
|
|
192
|
+
}
|
|
193
|
+
throw error;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function pullBody(reason: string, window: string): string {
|
|
198
|
+
return `${reason}
|
|
199
|
+
|
|
200
|
+
Window: ${window}
|
|
201
|
+
|
|
202
|
+
This pull request rewrites AGENTS.md. Those files are always-applied agent instructions. Review the bodies, then mark the draft ready and merge.`;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function citesWindow(body: string | null | undefined, window: string): boolean {
|
|
206
|
+
return new RegExp(
|
|
207
|
+
`(?:^|\\n)Window: ${escapeRegExp(window)}(?:\\s|$)`
|
|
208
|
+
).test(body ?? "");
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function appendWindow(body: string, reason: string, window: string): string {
|
|
212
|
+
return `${body.trim()}\n\n${reason}\nWindow: ${window}`;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function escapeRegExp(value: string): string {
|
|
216
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function isNotFound(error: unknown): boolean {
|
|
220
|
+
return (
|
|
221
|
+
typeof error === "object" &&
|
|
222
|
+
error !== null &&
|
|
223
|
+
"status" in error &&
|
|
224
|
+
error.status === 404
|
|
225
|
+
);
|
|
226
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { defineEval } from "@cursor/july/evals";
|
|
2
|
+
|
|
3
|
+
const WINDOW = "2026-08-26/2026-09-02";
|
|
4
|
+
|
|
5
|
+
function weekly(): string {
|
|
6
|
+
return [
|
|
7
|
+
`Weekly AGENTS.md review for acme/api (${WINDOW}).`,
|
|
8
|
+
"Read week/ and week/tree/. Call apply_agents once.",
|
|
9
|
+
].join("\n");
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const AGENTS = [
|
|
13
|
+
"# API",
|
|
14
|
+
"",
|
|
15
|
+
"Usage events are protobuf messages in `proto/billing.proto`.",
|
|
16
|
+
"Do not add ad-hoc billing columns on the request path.",
|
|
17
|
+
"",
|
|
18
|
+
].join("\n");
|
|
19
|
+
|
|
20
|
+
const CHORE = [
|
|
21
|
+
"# Merged pull requests",
|
|
22
|
+
"",
|
|
23
|
+
"## #12 Fix sidebar opener lint failure",
|
|
24
|
+
"url: https://github.com/acme/api/pull/12",
|
|
25
|
+
"author: @sam",
|
|
26
|
+
"merged: 2026-08-28T16:00:00Z",
|
|
27
|
+
"files: src/sidebar.ts",
|
|
28
|
+
"",
|
|
29
|
+
"Quote style only.",
|
|
30
|
+
"",
|
|
31
|
+
].join("\n");
|
|
32
|
+
|
|
33
|
+
const RULE = [
|
|
34
|
+
"# Merged pull requests",
|
|
35
|
+
"",
|
|
36
|
+
"## #18 Route every billing write through UsageEvent",
|
|
37
|
+
"url: https://github.com/acme/api/pull/18",
|
|
38
|
+
"author: @sam",
|
|
39
|
+
"merged: 2026-08-29T18:00:00Z",
|
|
40
|
+
"files: proto/billing.proto, src/billing.ts",
|
|
41
|
+
"",
|
|
42
|
+
"Adds usage_unit and workspace_id to UsageEvent.",
|
|
43
|
+
"",
|
|
44
|
+
"### comments",
|
|
45
|
+
"- @lee: always put new billing fields on UsageEvent. no request-path columns.",
|
|
46
|
+
"",
|
|
47
|
+
].join("\n");
|
|
48
|
+
|
|
49
|
+
const SLACK = [
|
|
50
|
+
"## #eng-api",
|
|
51
|
+
"- <@U1>: lunch at 12",
|
|
52
|
+
"- <@U2>: yes, every new billing field goes on UsageEvent from now on",
|
|
53
|
+
"",
|
|
54
|
+
].join("\n");
|
|
55
|
+
|
|
56
|
+
export default defineEval({
|
|
57
|
+
tags: ["smoke"],
|
|
58
|
+
cases: [
|
|
59
|
+
{
|
|
60
|
+
id: "skip-chore",
|
|
61
|
+
description: "A lint-only week does not open an AGENTS.md PR.",
|
|
62
|
+
async test(t) {
|
|
63
|
+
await t.send(weekly(), {
|
|
64
|
+
workspaceFiles: {
|
|
65
|
+
"week/window.txt": `${WINDOW}\n`,
|
|
66
|
+
"week/repo.txt": "acme/api\n",
|
|
67
|
+
"week/base.ref": "main\n",
|
|
68
|
+
"week/files.txt": "AGENTS.md\n",
|
|
69
|
+
"week/prs.md": CHORE,
|
|
70
|
+
"week/slack.md": "## #eng-api\n- <@U1>: lunch at 12\n",
|
|
71
|
+
"week/tree/AGENTS.md.txt": AGENTS,
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
t.succeeded();
|
|
75
|
+
t.calledTool("apply_agents", { input: { verdict: "skip" } });
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
id: "update-rule",
|
|
80
|
+
description: "A repeated billing rule parks the AGENTS.md write.",
|
|
81
|
+
async test(t) {
|
|
82
|
+
await t.send(weekly(), {
|
|
83
|
+
workspaceFiles: {
|
|
84
|
+
"week/window.txt": `${WINDOW}\n`,
|
|
85
|
+
"week/repo.txt": "acme/api\n",
|
|
86
|
+
"week/base.ref": "main\n",
|
|
87
|
+
"week/files.txt": "AGENTS.md\n",
|
|
88
|
+
"week/prs.md": RULE,
|
|
89
|
+
"week/slack.md": SLACK,
|
|
90
|
+
"week/tree/AGENTS.md.txt": "# API\n\nKeep handlers thin.\n",
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
t.parked();
|
|
94
|
+
t.calledTool("apply_agents", { input: { verdict: "update" } });
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
id: "skip-known",
|
|
99
|
+
description: "A rule already in AGENTS.md stays quiet.",
|
|
100
|
+
async test(t) {
|
|
101
|
+
await t.send(weekly(), {
|
|
102
|
+
workspaceFiles: {
|
|
103
|
+
"week/window.txt": `${WINDOW}\n`,
|
|
104
|
+
"week/repo.txt": "acme/api\n",
|
|
105
|
+
"week/base.ref": "main\n",
|
|
106
|
+
"week/files.txt": "AGENTS.md\n",
|
|
107
|
+
"week/prs.md": RULE,
|
|
108
|
+
"week/slack.md": SLACK,
|
|
109
|
+
"week/tree/AGENTS.md.txt": AGENTS,
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
t.succeeded();
|
|
113
|
+
t.calledTool("apply_agents", { input: { verdict: "skip" } });
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
id: "skip-empty",
|
|
118
|
+
description: "An empty week does not open an AGENTS.md PR.",
|
|
119
|
+
async test(t) {
|
|
120
|
+
await t.send(weekly(), {
|
|
121
|
+
workspaceFiles: {
|
|
122
|
+
"week/window.txt": `${WINDOW}\n`,
|
|
123
|
+
"week/repo.txt": "acme/api\n",
|
|
124
|
+
"week/base.ref": "main\n",
|
|
125
|
+
"week/files.txt": "\n",
|
|
126
|
+
"week/prs.md": "No merged pull requests this week.\n",
|
|
127
|
+
"week/slack.md": "No Slack channels configured.\n",
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
t.succeeded();
|
|
131
|
+
t.calledTool("apply_agents", { input: { verdict: "skip" } });
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
],
|
|
135
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"questions": [
|
|
3
|
+
{
|
|
4
|
+
"id": "repos",
|
|
5
|
+
"prompt": "Which GitHub repo should this agent maintain AGENTS.md for?",
|
|
6
|
+
"hint": "One owner/repo. Init once per app.",
|
|
7
|
+
"placeholder": "acme/api",
|
|
8
|
+
"parse": "owner-repo-list"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"id": "slack",
|
|
12
|
+
"prompt": "Which Slack channels should this agent read?",
|
|
13
|
+
"hint": "Comma-separated #names or channel ids. Invite the bot, including to private channels. Use none to skip Slack.",
|
|
14
|
+
"placeholder": "#eng-api, #api-private",
|
|
15
|
+
"default": "none"
|
|
16
|
+
}
|
|
17
|
+
],
|
|
18
|
+
"replace": [
|
|
19
|
+
{
|
|
20
|
+
"file": "agent/lib/config.ts",
|
|
21
|
+
"find": "[\"owner/repo\"]",
|
|
22
|
+
"answer": "repos",
|
|
23
|
+
"as": "json-array"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"file": "agent/lib/config.ts",
|
|
27
|
+
"find": "[\"#eng\"]",
|
|
28
|
+
"answer": "slack",
|
|
29
|
+
"as": "json-array"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"file": "README.md",
|
|
33
|
+
"find": "owner/repo",
|
|
34
|
+
"answer": "repos",
|
|
35
|
+
"as": "first"
|
|
36
|
+
}
|
|
37
|
+
]
|
|
38
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "agents-md",
|
|
3
|
+
"private": true,
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Keeps AGENTS.md current from last week's merged PRs and Slack.",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"check": "tsc --noEmit",
|
|
8
|
+
"dev": "agent-sdk dev"
|
|
9
|
+
},
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"@cursor/july": "latest",
|
|
12
|
+
"zod": "^3.25.0"
|
|
13
|
+
},
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@types/node": "^22.14.0",
|
|
16
|
+
"typescript": "^5.8.0"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Code wiki
|
|
2
|
+
|
|
3
|
+
Keeps `wiki/` pages current after a pull request merges. Opens a
|
|
4
|
+
follow-up PR against that merge's base when a durable fact changed.
|
|
5
|
+
Skips chores. Same-base updates stack on `wiki/<base>`.
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx @cursor/july init ./code-wiki --template code-wiki
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
`init` asks which repos to watch. Skip the prompt with
|
|
12
|
+
`--var repos=owner/repo`.
|
|
13
|
+
|
|
14
|
+
## Run
|
|
15
|
+
|
|
16
|
+
Connect GitHub in Cursor for those repos. Then sign the host in:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
agent-sdk login
|
|
20
|
+
agent-sdk dev
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Events and API calls use your Cursor GitHub connection. Replay a merged PR:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
agent-sdk github replay https://github.com/owner/repo/pull/1 --dir . --action closed
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Files
|
|
30
|
+
|
|
31
|
+
- `agent/lib/repos.ts`: watched repos
|
|
32
|
+
- `agent/lib/wiki.ts`: wiki path rules
|
|
33
|
+
- `agent/instructions.md`: what counts as a wiki update
|
|
34
|
+
- `evals/wiki.eval.ts`: skip and update smoke cases
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import type { HostGitHubClient } from "@cursor/july";
|
|
2
|
+
import {
|
|
3
|
+
defaultGitHubAuth,
|
|
4
|
+
githubChannel,
|
|
5
|
+
} from "@cursor/july/channels/github";
|
|
6
|
+
import { REPOS, watches } from "../lib/repos.js";
|
|
7
|
+
import { WIKI_DIR, isWikiPath } from "../lib/wiki.js";
|
|
8
|
+
|
|
9
|
+
const MAX_DIFF_CHARS = 150_000;
|
|
10
|
+
const MAX_WIKI_PAGES = 40;
|
|
11
|
+
const LIST_FILES_CAP = 3000;
|
|
12
|
+
|
|
13
|
+
type Octokit = Awaited<ReturnType<HostGitHubClient["getOctokit"]>>;
|
|
14
|
+
|
|
15
|
+
export default githubChannel({
|
|
16
|
+
cursorAccount: { repos: REPOS, permissions: "contents-write" },
|
|
17
|
+
deliverReplies: false,
|
|
18
|
+
onComment: () => null,
|
|
19
|
+
onPullRequest: async (ctx, pr) => {
|
|
20
|
+
if (!watches(ctx.repository.fullName)) {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
if (pr.action !== "closed" || !pr.merged) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
if (pr.headRef.startsWith(`${WIKI_DIR}/`)) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
const octokit = await ctx.github.getOctokit();
|
|
30
|
+
const pull = {
|
|
31
|
+
owner: ctx.repository.owner,
|
|
32
|
+
repo: ctx.repository.name,
|
|
33
|
+
pull_number: pr.number,
|
|
34
|
+
};
|
|
35
|
+
const listed = await octokit.paginate(octokit.rest.pulls.listFiles, {
|
|
36
|
+
...pull,
|
|
37
|
+
per_page: 100,
|
|
38
|
+
});
|
|
39
|
+
const files = listed.map((file) => file.filename);
|
|
40
|
+
if (
|
|
41
|
+
files.length > 0 &&
|
|
42
|
+
files.length < LIST_FILES_CAP &&
|
|
43
|
+
files.every(isWikiPath)
|
|
44
|
+
) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
auth: defaultGitHubAuth(ctx),
|
|
49
|
+
context: [
|
|
50
|
+
"This pull request merged. Read pr/files.txt, pr/diff.patch, and wiki/.",
|
|
51
|
+
],
|
|
52
|
+
async workspaceFiles() {
|
|
53
|
+
const [diff, wiki] = await Promise.all([
|
|
54
|
+
octokit.rest.pulls.get({ ...pull, mediaType: { format: "diff" } }),
|
|
55
|
+
loadWiki(octokit, pull.owner, pull.repo, pr.baseRef),
|
|
56
|
+
]);
|
|
57
|
+
const text = String(diff.data);
|
|
58
|
+
return {
|
|
59
|
+
"pr/base.ref": `${pr.baseRef}\n`,
|
|
60
|
+
"pr/files.txt": `${files.join("\n")}\n`,
|
|
61
|
+
"pr/diff.patch":
|
|
62
|
+
text.length > MAX_DIFF_CHARS
|
|
63
|
+
? `${text.slice(0, MAX_DIFF_CHARS)}\n…[truncated]\n`
|
|
64
|
+
: text,
|
|
65
|
+
...wiki,
|
|
66
|
+
};
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
async function loadWiki(
|
|
73
|
+
octokit: Octokit,
|
|
74
|
+
owner: string,
|
|
75
|
+
repo: string,
|
|
76
|
+
ref: string
|
|
77
|
+
): Promise<Record<string, string>> {
|
|
78
|
+
const listed = await readContents(octokit, {
|
|
79
|
+
owner,
|
|
80
|
+
repo,
|
|
81
|
+
path: WIKI_DIR,
|
|
82
|
+
ref,
|
|
83
|
+
});
|
|
84
|
+
if (!Array.isArray(listed)) {
|
|
85
|
+
return { "wiki/pages.txt": "" };
|
|
86
|
+
}
|
|
87
|
+
const markdown = listed.filter(
|
|
88
|
+
(item) => item.type === "file" && item.name.endsWith(".md")
|
|
89
|
+
);
|
|
90
|
+
const truncated = markdown.length > MAX_WIKI_PAGES;
|
|
91
|
+
const files = markdown.slice(0, MAX_WIKI_PAGES);
|
|
92
|
+
const pages: Record<string, string> = {};
|
|
93
|
+
await Promise.all(
|
|
94
|
+
files.map(async (file) => {
|
|
95
|
+
const body = await readContents(octokit, {
|
|
96
|
+
owner,
|
|
97
|
+
repo,
|
|
98
|
+
path: `${WIKI_DIR}/${file.name}`,
|
|
99
|
+
ref,
|
|
100
|
+
});
|
|
101
|
+
if (
|
|
102
|
+
body === undefined ||
|
|
103
|
+
Array.isArray(body) ||
|
|
104
|
+
body.encoding !== "base64" ||
|
|
105
|
+
typeof body.content !== "string"
|
|
106
|
+
) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
pages[`${WIKI_DIR}/${file.name}`] = Buffer.from(
|
|
110
|
+
body.content,
|
|
111
|
+
"base64"
|
|
112
|
+
).toString("utf8");
|
|
113
|
+
})
|
|
114
|
+
);
|
|
115
|
+
const names = Object.keys(pages).sort();
|
|
116
|
+
pages["wiki/pages.txt"] = truncated
|
|
117
|
+
? `${names.join("\n")}\n…[truncated]\n`
|
|
118
|
+
: `${names.join("\n")}\n`;
|
|
119
|
+
return pages;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async function readContents(
|
|
123
|
+
octokit: Octokit,
|
|
124
|
+
args: { owner: string; repo: string; path: string; ref: string }
|
|
125
|
+
) {
|
|
126
|
+
try {
|
|
127
|
+
const { data } = await octokit.rest.repos.getContent(args);
|
|
128
|
+
return data;
|
|
129
|
+
} catch (error) {
|
|
130
|
+
if (isNotFound(error)) {
|
|
131
|
+
return undefined;
|
|
132
|
+
}
|
|
133
|
+
throw error;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function isNotFound(error: unknown): boolean {
|
|
138
|
+
return (
|
|
139
|
+
typeof error === "object" &&
|
|
140
|
+
error !== null &&
|
|
141
|
+
"status" in error &&
|
|
142
|
+
error.status === 404
|
|
143
|
+
);
|
|
144
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Code wiki
|
|
2
|
+
|
|
3
|
+
You keep the in-repo wiki current after a pull request merges.
|
|
4
|
+
|
|
5
|
+
## Read
|
|
6
|
+
|
|
7
|
+
The workspace has `pr/files.txt`, `pr/diff.patch`, and `wiki/`.
|
|
8
|
+
`wiki/pages.txt` lists existing pages. Missing pages mean the wiki is
|
|
9
|
+
empty. Read the file list and the pages that own the change. Use the
|
|
10
|
+
diff only to test a fact.
|
|
11
|
+
|
|
12
|
+
## Decide
|
|
13
|
+
|
|
14
|
+
Update only when the merge changes a durable fact someone would look
|
|
15
|
+
up later: how a system works, a public or operator contract, a default
|
|
16
|
+
or ownership change, a removed feature.
|
|
17
|
+
|
|
18
|
+
An empty wiki is not a license to document the whole repo. Create a
|
|
19
|
+
page only for a durable contract in this merge.
|
|
20
|
+
|
|
21
|
+
Skip lint, format, lockfiles, dependency pins, tests-only, cherry-picks,
|
|
22
|
+
backports, telemetry-only changes, one-off bug fixes that leave the
|
|
23
|
+
described behavior the same, knobs the wiki never mentioned, and facts
|
|
24
|
+
the matching page already states.
|
|
25
|
+
|
|
26
|
+
Do not write a changelog or a PR list.
|
|
27
|
+
|
|
28
|
+
## Write
|
|
29
|
+
|
|
30
|
+
Call `apply_wiki` once.
|
|
31
|
+
|
|
32
|
+
- Skip: `{ verdict: "skip", reason }` with one line.
|
|
33
|
+
- Update: `{ verdict: "update", reason, pages }` with full page bodies.
|
|
34
|
+
|
|
35
|
+
Pages stay under `wiki/`, flat, `*.md`. Keep `_index.md` in sync when
|
|
36
|
+
you add a page. Each catalog line names the page and the paths it owns.
|
|
37
|
+
Short declarative sentences. Edit only the stale or missing facts.
|
|
38
|
+
|
|
39
|
+
Reply with `skip` or `update` and the reason.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export const WIKI_DIR = "wiki";
|
|
2
|
+
|
|
3
|
+
const PAGE = /^[A-Za-z0-9._-]+\.md$/;
|
|
4
|
+
|
|
5
|
+
export function isWikiPath(path: string): boolean {
|
|
6
|
+
return path === WIKI_DIR || path.startsWith(`${WIKI_DIR}/`);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function wikiPagePath(raw: string): string | undefined {
|
|
10
|
+
const path = raw.replace(/^\/+/, "");
|
|
11
|
+
if (path.includes("..") || path.includes("\\")) {
|
|
12
|
+
return undefined;
|
|
13
|
+
}
|
|
14
|
+
if (!path.startsWith(`${WIKI_DIR}/`) || !path.endsWith(".md")) {
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
const name = path.slice(WIKI_DIR.length + 1);
|
|
18
|
+
if (!PAGE.test(name)) {
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
return `${WIKI_DIR}/${name}`;
|
|
22
|
+
}
|