@cursor/july 0.1.96 → 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/README.md +3 -2
- package/dist/bin/agent-serve.js +14 -3
- package/dist/channels/origin/api.d.ts +15 -4
- package/dist/channels/origin/api.d.ts.map +1 -1
- package/dist/channels/origin/api.js +19 -3
- package/dist/channels/origin/binding.d.ts +11 -0
- package/dist/channels/origin/binding.d.ts.map +1 -1
- package/dist/channels/origin/binding.js +41 -25
- package/dist/channels/origin/index.d.ts +1 -0
- package/dist/channels/origin/index.d.ts.map +1 -1
- package/dist/channels/origin/index.js +1 -0
- package/dist/channels/origin/origin-channel.d.ts.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/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 +97 -39
- 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/manifest.d.ts +1 -1
- package/dist/channels/slack/manifest.js +1 -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 +1 -0
- package/dist/channels/slack/tool-approval-events.d.ts.map +1 -1
- package/dist/channels/slack/tool-approval-events.js +91 -1
- package/dist/docs/404.html +2 -2
- package/dist/docs/ab.html +4 -4
- package/dist/docs/assets/{app.jXleCmOc.js → app.B3rWNYE1.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.BU9nHdnQ.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.8LhyglIT.js → VPLocalSearchBox.C1lhqJJR.js} +1 -1
- package/dist/docs/assets/chunks/{theme.9ged-pr2.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/{reference_agent-config.md.Cp_x38Nl.js → reference_agent-config.md.BHeYMgme.js} +1 -1
- package/dist/docs/assets/{reference_cli.md.CCnG-nJx.js → reference_cli.md.RyZf5OTE.js} +9 -6
- package/dist/docs/assets/{reference_cli.md.CCnG-nJx.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/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 +5 -3
- package/dist/docs/llms-full.txt +299 -653
- package/dist/docs/llms.txt +2 -2
- package/dist/docs/quickstart.html +4 -4
- package/dist/docs/reference/agent-config.html +6 -6
- package/dist/docs/reference/agent-config.md +2 -2
- package/dist/docs/reference/artifacts.html +4 -4
- package/dist/docs/reference/channels.html +4 -4
- package/dist/docs/reference/cli.html +13 -10
- package/dist/docs/reference/cli.md +38 -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 +5 -5
- package/dist/docs/templates/demo.html +4 -4
- package/dist/docs/templates/pr-autofixer.html +4 -4
- package/dist/docs/templates/security-help.html +4 -4
- package/dist/docs/templates/security-reviewer.html +5 -5
- package/dist/docs/templates/triage.html +4 -4
- package/dist/docs/troubleshooting.html +5 -5
- package/dist/docs/troubleshooting.md +2 -2
- package/dist/evals/run-facts.d.ts.map +1 -1
- package/dist/evals/run-facts.js +27 -0
- package/dist/internal/advertise-tools.d.ts.map +1 -1
- package/dist/internal/advertise-tools.js +15 -9
- package/dist/internal/approval-gate.d.ts +12 -13
- package/dist/internal/approval-gate.d.ts.map +1 -1
- package/dist/internal/approval-gate.js +16 -21
- package/dist/internal/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 +50 -17
- package/dist/internal/cli-mcp-oauth.js +8 -18
- package/dist/internal/cli-slack-manual.d.ts +24 -2
- package/dist/internal/cli-slack-manual.d.ts.map +1 -1
- package/dist/internal/cli-slack-manual.js +251 -20
- package/dist/internal/cli-slack.d.ts +9 -2
- package/dist/internal/cli-slack.d.ts.map +1 -1
- package/dist/internal/cli-slack.js +29 -82
- package/dist/internal/cursor/account-mcp.d.ts +1 -0
- package/dist/internal/cursor/account-mcp.d.ts.map +1 -1
- package/dist/internal/cursor/account-mcp.js +17 -0
- package/dist/internal/cursor-agent-template.d.ts +1 -1
- package/dist/internal/cursor-agent-template.d.ts.map +1 -1
- package/dist/internal/cursor-agent-template.js +1 -0
- package/dist/internal/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 +1 -1
- package/dist/internal/framework-file-storage.d.ts.map +1 -1
- package/dist/internal/framework-file-storage.js +6 -0
- 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 +6 -0
- package/dist/internal/hosted-delivery.d.ts.map +1 -1
- package/dist/internal/hosted-delivery.js +63 -22
- 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 +2 -0
- package/dist/internal/logs-client.d.ts +5 -0
- package/dist/internal/logs-client.d.ts.map +1 -1
- package/dist/internal/logs-client.js +5 -0
- package/dist/internal/mcp-endpoint.js +2 -3
- package/dist/internal/mcp-host.d.ts +10 -0
- package/dist/internal/mcp-host.d.ts.map +1 -1
- package/dist/internal/mcp-host.js +57 -8
- package/dist/internal/mcp-oauth-on-demand.d.ts +68 -0
- package/dist/internal/mcp-oauth-on-demand.d.ts.map +1 -0
- package/dist/internal/mcp-oauth-on-demand.js +287 -0
- package/dist/internal/mcp-oauth-persist.d.ts +42 -0
- package/dist/internal/mcp-oauth-persist.d.ts.map +1 -0
- package/dist/internal/mcp-oauth-persist.js +92 -0
- package/dist/internal/mcp-oauth.d.ts +1 -0
- package/dist/internal/mcp-oauth.d.ts.map +1 -1
- package/dist/internal/mcp-oauth.js +10 -2
- package/dist/internal/otel/collector.d.ts.map +1 -1
- package/dist/internal/otel/collector.js +22 -9
- package/dist/internal/server.d.ts +3 -0
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +49 -22
- package/dist/internal/session-engine.d.ts +88 -3
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +515 -43
- package/dist/internal/sessions-client.d.ts +9 -7
- package/dist/internal/sessions-client.d.ts.map +1 -1
- package/dist/internal/sessions-client.js +3 -1
- package/dist/internal/storage-coordinator.d.ts +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-Cx9CclK_.js → index-DrkI6y5O.js} +45 -45
- package/dist/playground/assets/index-DzNGwm7q.css +1 -0
- package/dist/playground/index.html +2 -2
- package/dist/storage-backends/cursor-hosted.d.ts +1 -1
- package/dist/storage-backends/cursor-hosted.d.ts.map +1 -1
- package/dist/storage-backends/cursor-hosted.js +12 -0
- package/dist/storage.d.ts +8 -0
- package/dist/storage.d.ts.map +1 -1
- package/dist/types.d.ts +63 -7
- package/dist/types.d.ts.map +1 -1
- package/docs/README.md +5 -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 +38 -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/troubleshooting.md +2 -2
- package/package.json +1 -1
- package/skills/create-agent/SKILL.md +2 -1
- package/skills/mcp-auth/SKILL.md +6 -3
- package/skills/setup-slack/SKILL.md +23 -13
- package/src/bin/agent-serve.ts +13 -1
- package/src/channels/origin/api.ts +24 -5
- package/src/channels/origin/binding.ts +55 -26
- package/src/channels/origin/index.ts +1 -0
- package/src/channels/origin/origin-channel.ts +4 -0
- package/src/channels/origin/reactions.ts +82 -0
- package/src/channels/origin/types.ts +11 -0
- package/src/channels/slack/approvals.ts +105 -0
- package/src/channels/slack/cli-project.ts +267 -0
- package/src/channels/slack/defaults.ts +109 -46
- package/src/channels/slack/init.ts +10 -5
- package/src/channels/slack/interactive.ts +35 -9
- package/src/channels/slack/manifest.ts +1 -1
- package/src/channels/slack/setup.ts +10 -6
- package/src/channels/slack/slack-channel.ts +1 -0
- package/src/channels/slack/tool-approval-events.ts +93 -0
- package/src/evals/run-facts.ts +32 -0
- package/src/internal/advertise-tools.ts +31 -10
- package/src/internal/approval-gate.ts +20 -29
- package/src/internal/chat-client.ts +19 -0
- package/src/internal/cli-deploy.ts +79 -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/cursor/account-mcp.ts +21 -0
- package/src/internal/cursor-agent-template.ts +1 -0
- package/src/internal/deploy-client.ts +43 -0
- package/src/internal/env-file.ts +84 -0
- package/src/internal/framework-file-storage.ts +7 -1
- package/src/internal/hosted-delivery-protocol.ts +7 -0
- package/src/internal/hosted-delivery.ts +100 -27
- package/src/internal/hosted-execution-diag.ts +207 -0
- package/src/internal/http-channel.ts +99 -0
- package/src/internal/init-project.ts +2 -0
- package/src/internal/logs-client.ts +5 -0
- package/src/internal/mcp-endpoint.ts +13 -4
- package/src/internal/mcp-host.ts +77 -11
- package/src/internal/mcp-oauth-on-demand.ts +352 -0
- package/src/internal/mcp-oauth-persist.ts +127 -0
- package/src/internal/mcp-oauth.ts +17 -1
- package/src/internal/otel/collector.ts +30 -0
- package/src/internal/server.ts +59 -9
- package/src/internal/session-engine.ts +659 -56
- package/src/internal/sessions-client.ts +17 -8
- 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 +13 -1
- package/src/storage.ts +12 -0
- package/src/types.ts +68 -8
- package/templates/agents-md/README.md +39 -0
- package/templates/agents-md/agent/agent.ts +8 -0
- package/templates/agents-md/agent/channels/github.ts +10 -0
- package/templates/agents-md/agent/channels/queue.ts +28 -0
- package/templates/agents-md/agent/channels/slack.ts +9 -0
- package/templates/agents-md/agent/instructions.md +39 -0
- package/templates/agents-md/agent/lib/collect.ts +439 -0
- package/templates/agents-md/agent/lib/config.ts +8 -0
- package/templates/agents-md/agent/lib/paths.ts +51 -0
- package/templates/agents-md/agent/schedules/weekly.ts +17 -0
- package/templates/agents-md/agent/tools/apply_agents.ts +226 -0
- package/templates/agents-md/evals/agents.eval.ts +135 -0
- package/templates/agents-md/evals/evals.config.ts +5 -0
- package/templates/agents-md/init.json +38 -0
- package/templates/agents-md/package.json +18 -0
- package/templates/agents-md/tsconfig.json +12 -0
- package/dist/docs/assets/chunks/@localSearchIndexroot.DFoGuETX.js +0 -1
- package/dist/docs/assets/guides_slack.md.C32HsdKk.js +0 -38
- package/dist/docs/assets/guides_slack.md.C32HsdKk.lean.js +0 -1
- package/dist/docs/assets/index.md.CI93Ltlb.js +0 -5
- package/dist/docs/assets/reference_sessions.md.D0mIh4KK.js +0 -1
- package/dist/docs/assets/troubleshooting.md.Ctv3T8C2.js +0 -1
- package/dist/docs/design/agsh.md +0 -406
- package/dist/playground/assets/index-B1DDvBeC.css +0 -1
- package/docs/design/agsh.md +0 -406
- /package/dist/docs/assets/{deployment.md.D9msOFOW.lean.js → deployment.md.MFPKqsqI.lean.js} +0 -0
- /package/dist/docs/assets/{index.md.CI93Ltlb.lean.js → index.md.CVeRUOeZ.lean.js} +0 -0
- /package/dist/docs/assets/{reference_agent-config.md.Cp_x38Nl.lean.js → reference_agent-config.md.BHeYMgme.lean.js} +0 -0
- /package/dist/docs/assets/{reference_connections.md.BH8Oc0D0.lean.js → reference_connections.md.DxldvyIB.lean.js} +0 -0
- /package/dist/docs/assets/{reference_http-api.md.D89k1mdm.lean.js → reference_http-api.md.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,110 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Keep AGENTS.md current from last week's work"
|
|
3
|
+
description: "Scaffold the agent, pick a repo and Slack channels, dispatch the weekly job, and deploy."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Keep AGENTS.md current from last week's work
|
|
7
|
+
|
|
8
|
+
This agent runs every Monday at 09:00 UTC. It reads last week's merged
|
|
9
|
+
pull requests and the Slack channels you list. When a durable rule
|
|
10
|
+
showed up, `apply_agents` parks the write until a person approves it,
|
|
11
|
+
then opens a draft follow-up pull request against the default branch.
|
|
12
|
+
Chores and rules the file already states stay quiet.
|
|
13
|
+
|
|
14
|
+
This template is one model turn: read the week, then call
|
|
15
|
+
`apply_agents`.
|
|
16
|
+
|
|
17
|
+
Init once per app. Pass a different repo and channel list each time.
|
|
18
|
+
|
|
19
|
+
## Scaffold
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npx @cursor/july init ./agents-md --template agents-md
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
`init` asks which GitHub repo to watch and which Slack channels to
|
|
26
|
+
read. Pass `--var repos=acme/api --var slack=#eng-api,#api-private`
|
|
27
|
+
to skip the prompt. Use `--var slack=none` when Slack is out of
|
|
28
|
+
scope.
|
|
29
|
+
|
|
30
|
+
The answers land in `agent/lib/config.ts`. Edit that file when the
|
|
31
|
+
set changes.
|
|
32
|
+
|
|
33
|
+
## Connect GitHub and Slack
|
|
34
|
+
|
|
35
|
+
Connect GitHub in Cursor for that repository (Settings or
|
|
36
|
+
[cursor.com/dashboard](https://cursor.com/dashboard)). Sign the host
|
|
37
|
+
in:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
cd agents-md
|
|
41
|
+
agent-sdk login
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
`cursorAccount` mints a short-lived, repo-scoped credential with
|
|
45
|
+
`contents-write` so the agent can open the follow-up PR. See the
|
|
46
|
+
[GitHub guide](../guides/github.md).
|
|
47
|
+
|
|
48
|
+
Create the Slack app and invite the bot to each listed channel,
|
|
49
|
+
including private ones:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
agent-sdk slack create --dir .
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
See the [Slack guide](../guides/slack.md).
|
|
56
|
+
|
|
57
|
+
## First weekly run
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
agent-sdk dev
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Schedules never fire under `dev`. Dispatch the same path production
|
|
64
|
+
uses:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
curl -X POST http://127.0.0.1:3000/v1/dev/schedules/weekly
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
The playground can run `/queue/run` too.
|
|
71
|
+
|
|
72
|
+
The host writes `week/prs.md`, `week/slack.md`, `week/window.txt`,
|
|
73
|
+
and `week/tree/**.txt` snapshots of the current `AGENTS.md` files,
|
|
74
|
+
then starts a model turn. The
|
|
75
|
+
model calls `apply_agents` once. A skip finishes. An update parks in
|
|
76
|
+
the playground until someone approves; then a draft PR opens against
|
|
77
|
+
the repository default branch. Later updates to the same base stack
|
|
78
|
+
on `agents-md/<base>`. Pull requests from those branches are ignored
|
|
79
|
+
so the follow-up cannot feed the next week.
|
|
80
|
+
|
|
81
|
+
Chat replies stay in the playground. `apply_agents` records a skip,
|
|
82
|
+
or parks the write. Approve there or with
|
|
83
|
+
`POST /v1/session/:id/approvals/:callId`.
|
|
84
|
+
|
|
85
|
+
## What to edit
|
|
86
|
+
|
|
87
|
+
- `agent/lib/config.ts`: repo and Slack channels
|
|
88
|
+
- `agent/instructions.md`: what counts as an update
|
|
89
|
+
- `evals/agents.eval.ts`: smoke cases
|
|
90
|
+
|
|
91
|
+
## Evals
|
|
92
|
+
|
|
93
|
+
Four smoke cases: a lint-only week, a billing rule that parks the
|
|
94
|
+
write, the same rule already in `AGENTS.md`, and an empty week.
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
agent-sdk eval
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Eval sessions skip the GitHub write.
|
|
101
|
+
|
|
102
|
+
## Deploy
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
agent-sdk deploy
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Run it from the agent's git checkout. The command infers repository,
|
|
109
|
+
ref, path, and slug. Production fires the Monday cron. The deployment
|
|
110
|
+
uses the team's Cursor GitHub connection for the watched repo.
|
package/docs/troubleshooting.md
CHANGED
|
@@ -42,7 +42,7 @@ not on `PATH`, use `npx @cursor/july`.
|
|
|
42
42
|
| What you see | What to do |
|
|
43
43
|
| --- | --- |
|
|
44
44
|
| `409` on a follow-up message | Refresh the `continuationToken` or confirm the session is a chat session. Task sessions do not accept follow-ups. |
|
|
45
|
-
| `409 session_busy` on `call --session` | Wait for the
|
|
45
|
+
| `409 session_busy` on `call --session` | The tool is a write (or declares no effect) and a model turn is running. Wait for the turn to finish, omit `--session` for a one-off call, or declare `effect: "read"` on a tool that only reads so it runs alongside turns. |
|
|
46
46
|
| `403` on stream or follow-up | Use the same auth identity that created the session. Off localhost, pass `--bearer-token` and send it on every request. |
|
|
47
47
|
| Works on localhost; blocked through a tunnel or LAN | Default auth allows only direct loopback callers. Share the host with `--bearer-token <secret>` (or authored `bearerAuth`). Use `--allow-anonymous` only on a trusted private network. |
|
|
48
48
|
| A channel route fails to compile with a schema type error | `GET` routes need a Zod `querySchema`. `POST` / `PUT` / `PATCH` need a Zod `bodySchema`. Use `z.object({})` or `z.unknown()` for open shapes. |
|
|
@@ -70,7 +70,7 @@ not on `PATH`, use `npx @cursor/july`.
|
|
|
70
70
|
| What you see | What to do |
|
|
71
71
|
| --- | --- |
|
|
72
72
|
| `must be defineConnection({ url, oauth: true })` | The connection file needs `oauth: true`, or you passed the wrong connection name to `agent-sdk mcp oauth`. |
|
|
73
|
-
| Local auth works; hosted calls unauthorized |
|
|
73
|
+
| Local auth works; hosted calls unauthorized | Finish Connect on the hosted engine, or run `agent-sdk mcp oauth <name> --store`. Confirm names with `agent-sdk secrets list <slug>`, then redeploy. |
|
|
74
74
|
| Model asks for `mcp_auth` or IDE MCP for a connector it already has | Attached MCP is behind meta-tools. Set `advertiseTools: true` for named tools on local turns, or call it from a host tool via `ctx.host.mcp`. |
|
|
75
75
|
|
|
76
76
|
See [Host MCP OAuth](./guides/mcp-oauth.md) and
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cursor/july",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.97",
|
|
4
4
|
"description": "(early alpha) Filesystem-first framework for defining Cursor agents as markdown and TypeScript and serving them over channels with the Cursor SDK.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
6
6
|
"repository": {
|
|
@@ -111,7 +111,8 @@ agent-sdk init ./<slug>
|
|
|
111
111
|
`subagents/<id>/` (needs `description`), `schedules/`, `hooks/`.
|
|
112
112
|
Slack: `agent-sdk slack create --dir ./<slug> --name "<Name>"`,
|
|
113
113
|
not a hand-written channel. Manual Slack app:
|
|
114
|
-
`agent-sdk slack init --manual
|
|
114
|
+
`agent-sdk slack init --manual` (Slack CLI, or paste at
|
|
115
|
+
api.slack.com).
|
|
115
116
|
4. `evals/evals.config.ts` with `maxConcurrency: 20` (required;
|
|
116
117
|
cap 200) plus `evals/**/*.eval.ts`. Assert `t.succeeded()` +
|
|
117
118
|
`t.calledTool(...)`. API: `skills/evals/SKILL.md`.
|
package/skills/mcp-auth/SKILL.md
CHANGED
|
@@ -30,8 +30,11 @@ can still call `ctx.host.mcp`.
|
|
|
30
30
|
3. **Allow egress** on hosted non-bootstrap hosts:
|
|
31
31
|
`hosting.egressDomains`.
|
|
32
32
|
4. **Authorize.** Local: `agent-sdk mcp oauth <name>`. Hosted:
|
|
33
|
-
|
|
34
|
-
`
|
|
33
|
+
finish Connect so the current process can retry, then
|
|
34
|
+
`agent-sdk mcp oauth <name> --store` and `agent-sdk deploy` so
|
|
35
|
+
the next pod gets `MCP_OAUTH_*`. `secrets list` shows the names.
|
|
36
|
+
Secrets are deployment-wide, not per caller. `cursorAccount: true`
|
|
37
|
+
stays on the Cursor backend.
|
|
35
38
|
|
|
36
39
|
```ts
|
|
37
40
|
// agent/mcp-connections/inventory.ts
|
|
@@ -75,7 +78,7 @@ the CLI config directory (`mcp-auth.json` or
|
|
|
75
78
|
| `must be defineConnection({ url, oauth: true })` | Wrong name or missing `oauth: true` |
|
|
76
79
|
| `Unknown MCP connection` | Filename must match the CLI arg |
|
|
77
80
|
| Callback hang | Free port 8787; finish the browser flow here |
|
|
78
|
-
| Hosted 401 | `secrets list`; `--store`; redeploy |
|
|
81
|
+
| Hosted 401 | `secrets list`; Connect or `--store`; redeploy |
|
|
79
82
|
| Model invents `mcp_auth` / IDE MCP | `advertiseTools: true` on local turns |
|
|
80
83
|
|
|
81
84
|
No raw tokens in git.
|
|
@@ -64,28 +64,38 @@ Local serve does not need a hosted engine. Next
|
|
|
64
64
|
|
|
65
65
|
## 2. Manual (`slack init --manual`)
|
|
66
66
|
|
|
67
|
-
Only when they own the app
|
|
67
|
+
Only when they own the app. Preferred: Slack CLI
|
|
68
|
+
(`~/.slack/bin/slack`). Paste at api.slack.com if the CLI is
|
|
69
|
+
missing. Never `slack deploy`; Agent SDK serve owns Socket Mode.
|
|
68
70
|
|
|
69
71
|
```bash
|
|
70
72
|
agent-sdk slack init --manual --dir . --name "My Agent"
|
|
73
|
+
# --slack-team T0123ABCD when several workspaces are logged in
|
|
74
|
+
# --no-install to scaffold only
|
|
71
75
|
```
|
|
72
76
|
|
|
73
77
|
Writes `agent/channels/slack.ts` (`envPrefix` from the directory),
|
|
74
|
-
manifests
|
|
75
|
-
`--channel-posts` subscribes `message.channels`
|
|
76
|
-
`message.groups`.
|
|
78
|
+
manifests, a `.slack/` project (`get-manifest` → those JSON files),
|
|
79
|
+
and `env.example`. `--channel-posts` subscribes `message.channels`
|
|
80
|
+
/ `message.groups`. If Slack CLI is logged in, this installs the
|
|
81
|
+
app. `--install` fails when that cannot run.
|
|
77
82
|
|
|
78
83
|
Human gates, one at a time. Stop after each.
|
|
79
84
|
|
|
80
|
-
1. **
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
85
|
+
1. **Install the app.** If `next` starts with "Ask the user to
|
|
86
|
+
install this Slack app", stop and prompt them. Slack CLI: they
|
|
87
|
+
run `slack login --no-prompt`, send `/slackauthticket <ticket>`,
|
|
88
|
+
then `slack login --ticket <ticket> --challenge <code>`, then
|
|
89
|
+
`slack app install --environment local --team <T> --force`.
|
|
90
|
+
Prod: `SLACK_ENV=deployed slack app install --environment
|
|
91
|
+
deployed --team <T> --force`. Fallback: Create New App → From a
|
|
92
|
+
manifest, start with `.slack/manifest.dev.json`.
|
|
93
|
+
2. **Tokens.** Slack CLI leaves xoxb / xapp in that process only.
|
|
94
|
+
Copy the bot token from the app's OAuth page. Mint an app-level
|
|
95
|
+
token with `connections:write`. Put both in `.env.local` using
|
|
96
|
+
`env.example` names. If Slack CLI wrote `SLACK_*` to `.env`,
|
|
97
|
+
copy those values to the prefixed keys.
|
|
98
|
+
3. **Doctor.**
|
|
89
99
|
|
|
90
100
|
## 3. Doctor and smoke
|
|
91
101
|
|
package/src/bin/agent-serve.ts
CHANGED
|
@@ -140,7 +140,7 @@ Usage:
|
|
|
140
140
|
${CLI} deploy [--dir <path>] [--slug <slug> | --all] [--team <id>] [--json]
|
|
141
141
|
[--no-wait] [--repo <url>] [--ref <ref>]
|
|
142
142
|
[--path <agentPath>] [--cursor-events-repo <owner/name>]...
|
|
143
|
-
[--allow-domain <domain>]...
|
|
143
|
+
[--allow-domain <domain>]... [--multi-tenant]
|
|
144
144
|
${CLI} manifest [--dir <path>] [--json]
|
|
145
145
|
${CLI} deployments [--team <id>] [--json]
|
|
146
146
|
${CLI} deployment <slug> [--team <id>] [--json]
|
|
@@ -268,6 +268,8 @@ Commands:
|
|
|
268
268
|
(flags always win). When --dir is a multi-agent parent,
|
|
269
269
|
pick one interactively, or pass --slug / --all. First deploy
|
|
270
270
|
of a slug prints the alias token exactly once — save it.
|
|
271
|
+
--multi-tenant adds a release to an existing Cursor-managed
|
|
272
|
+
product (v2 only); it cannot create a new multi-tenant app.
|
|
271
273
|
deployments List the team's deployments (slug, status, generation, kind).
|
|
272
274
|
deployment Show one deployment in full (status, lastError, engine info).
|
|
273
275
|
stop Stop a deployment and wait until it reports stopped.
|
|
@@ -430,6 +432,9 @@ Options:
|
|
|
430
432
|
--allow-domain deploy: egress domain the engine pod may reach
|
|
431
433
|
(repeatable; unioned with hosting.egressDomains from the
|
|
432
434
|
agent manifest). Repo-backed deploys only.
|
|
435
|
+
--multi-tenant deploy: add a release to an existing Cursor-managed
|
|
436
|
+
(multi-tenant) product. architecture v2 only. Cannot
|
|
437
|
+
create a new multi-tenant application.
|
|
433
438
|
--from-argv secrets set: allow NAME=VALUE on argv (leaks into shell
|
|
434
439
|
history and agent-captured terminals). Default is names
|
|
435
440
|
only with a hidden prompt or piped stdin.
|
|
@@ -439,6 +444,8 @@ Options:
|
|
|
439
444
|
GITHUB_WEBHOOK_SECRET). github: --events overrides the
|
|
440
445
|
derived webhook event list.
|
|
441
446
|
--install github: install the cli/gh-webhook extension if missing.
|
|
447
|
+
slack init --manual: require Slack CLI app install.
|
|
448
|
+
--no-install slack init --manual: skip Slack CLI app install.
|
|
442
449
|
--action github replay: event action (e.g. opened, synchronize).
|
|
443
450
|
--conclusion github replay: CI conclusion (check_run/suite/status).
|
|
444
451
|
--comment github replay: comment body for comment events.
|
|
@@ -557,6 +564,7 @@ async function main(argv: string[]): Promise<number> {
|
|
|
557
564
|
secret: { type: "string" },
|
|
558
565
|
channel: { type: "string", multiple: true },
|
|
559
566
|
install: { type: "boolean", default: false },
|
|
567
|
+
"no-install": { type: "boolean", default: false },
|
|
560
568
|
action: { type: "string" },
|
|
561
569
|
conclusion: { type: "string" },
|
|
562
570
|
context: { type: "string" },
|
|
@@ -570,6 +578,7 @@ async function main(argv: string[]): Promise<number> {
|
|
|
570
578
|
all: { type: "boolean", default: false },
|
|
571
579
|
"cursor-events-repo": { type: "string", multiple: true },
|
|
572
580
|
"allow-domain": { type: "string", multiple: true },
|
|
581
|
+
"multi-tenant": { type: "boolean", default: false },
|
|
573
582
|
"from-argv": { type: "boolean", default: false },
|
|
574
583
|
strict: { type: "boolean", default: false },
|
|
575
584
|
junit: { type: "string" },
|
|
@@ -622,6 +631,8 @@ async function main(argv: string[]): Promise<number> {
|
|
|
622
631
|
icon: values.icon,
|
|
623
632
|
force: values.force,
|
|
624
633
|
manual: values.manual,
|
|
634
|
+
install: values.install,
|
|
635
|
+
noInstall: values["no-install"],
|
|
625
636
|
iconSource: positionals[0] === "icon" ? positionals[1] : undefined,
|
|
626
637
|
});
|
|
627
638
|
}
|
|
@@ -757,6 +768,7 @@ async function main(argv: string[]): Promise<number> {
|
|
|
757
768
|
...(values["allow-domain"] === undefined
|
|
758
769
|
? {}
|
|
759
770
|
: { allowDomains: values["allow-domain"] }),
|
|
771
|
+
multiTenant: values["multi-tenant"] === true,
|
|
760
772
|
});
|
|
761
773
|
}
|
|
762
774
|
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
* from options first, then the environment: `ORIGIN_APP_ID` (or
|
|
10
10
|
* `AGENT_SERVE_ORIGIN_APP_ID`), `ORIGIN_APP_INSTALLATION_ID`,
|
|
11
11
|
* `ORIGIN_APP_PRIVATE_KEY` (PKCS8 PEM for the app's Ed25519 key; literal
|
|
12
|
-
* `\n` sequences are normalized),
|
|
13
|
-
*
|
|
12
|
+
* `\n` sequences are normalized), `ORIGIN_API_BASE_URL` for the public REST
|
|
13
|
+
* base, and `ORIGIN_RPC_BASE_URL` for the first-party ConnectRPC base.
|
|
14
14
|
*
|
|
15
15
|
* Hosted v2 forks configure none of that: their only credential is the
|
|
16
16
|
* deployment service account's `CURSOR_API_KEY`, exchanged for a Cursor
|
|
@@ -40,6 +40,15 @@ import {
|
|
|
40
40
|
*/
|
|
41
41
|
export const DEFAULT_ORIGIN_PUBLIC_API_BASE_URL = "https://api.cursor.com";
|
|
42
42
|
|
|
43
|
+
/**
|
|
44
|
+
* Origin's first-party ConnectRPC host (`origin.v1.OriginService`). Separate
|
|
45
|
+
* deployment from {@link DEFAULT_ORIGIN_PUBLIC_API_BASE_URL}: a handful of
|
|
46
|
+
* workflow operations — comment reactions among them — have no
|
|
47
|
+
* `/v1/origin/...` REST binding yet and are only reachable as Connect unary
|
|
48
|
+
* JSON here.
|
|
49
|
+
*/
|
|
50
|
+
export const DEFAULT_ORIGIN_RPC_BASE_URL = "https://api.origin.cursor.com";
|
|
51
|
+
|
|
43
52
|
/** Fixed audience for Origin app JWTs (`APP_TOKEN_AUDIENCE` backend-side). */
|
|
44
53
|
const ORIGIN_APP_TOKEN_AUDIENCE = "origin-apps";
|
|
45
54
|
const APP_JWT_TTL_SECONDS = 5 * 60;
|
|
@@ -139,6 +148,12 @@ export function originPublicApiBaseUrl(
|
|
|
139
148
|
return fromEnv ?? DEFAULT_ORIGIN_PUBLIC_API_BASE_URL;
|
|
140
149
|
}
|
|
141
150
|
|
|
151
|
+
/** Origin ConnectRPC base. Trailing slashes are stripped for path joins. */
|
|
152
|
+
export function originRpcBaseUrl(env: NodeJS.ProcessEnv = process.env): string {
|
|
153
|
+
const fromEnv = envValue(env.ORIGIN_RPC_BASE_URL)?.replace(/\/+$/, "");
|
|
154
|
+
return fromEnv ?? DEFAULT_ORIGIN_RPC_BASE_URL;
|
|
155
|
+
}
|
|
156
|
+
|
|
142
157
|
function base64UrlJson(value: unknown): string {
|
|
143
158
|
return Buffer.from(JSON.stringify(value)).toString("base64url");
|
|
144
159
|
}
|
|
@@ -376,9 +391,10 @@ export interface OriginClientOptions {
|
|
|
376
391
|
token?: string | OriginTokenProvider;
|
|
377
392
|
/**
|
|
378
393
|
* App credentials to mint installation tokens from. Defaults to the
|
|
379
|
-
* environment ({@link resolveOriginAppCredentials}).
|
|
394
|
+
* environment ({@link resolveOriginAppCredentials}). Pass `false` to
|
|
395
|
+
* disable app credential lookup and force the Cursor-account exchange.
|
|
380
396
|
*/
|
|
381
|
-
credentials?: OriginAppCredentials;
|
|
397
|
+
credentials?: OriginAppCredentials | false;
|
|
382
398
|
/** Public Origin REST base. Defaults to `ORIGIN_API_BASE_URL` / prod. */
|
|
383
399
|
apiBaseUrl?: string;
|
|
384
400
|
/** Injectable fetch for tests. */
|
|
@@ -441,7 +457,10 @@ export function createOriginClient(
|
|
|
441
457
|
return await options.token();
|
|
442
458
|
}
|
|
443
459
|
if (tokenProvider === undefined) {
|
|
444
|
-
const credentials =
|
|
460
|
+
const credentials =
|
|
461
|
+
options.credentials === false
|
|
462
|
+
? undefined
|
|
463
|
+
: (options.credentials ?? resolveOriginAppCredentials());
|
|
445
464
|
const exchange = options.cursorAccountExchange ?? true;
|
|
446
465
|
const exchangeOptions =
|
|
447
466
|
exchange === false ? undefined : exchange === true ? {} : exchange;
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
createOriginClient,
|
|
14
14
|
type OriginApiMethod,
|
|
15
15
|
type OriginClient,
|
|
16
|
+
originRpcBaseUrl,
|
|
16
17
|
resolveOriginAppCredentialParts,
|
|
17
18
|
} from "./api.js";
|
|
18
19
|
import {
|
|
@@ -20,6 +21,10 @@ import {
|
|
|
20
21
|
type OriginCheck,
|
|
21
22
|
type OriginCheckCreateInput,
|
|
22
23
|
} from "./checks.js";
|
|
24
|
+
import {
|
|
25
|
+
type OriginCommentReactionInput,
|
|
26
|
+
setOriginCommentReaction,
|
|
27
|
+
} from "./reactions.js";
|
|
23
28
|
import type { OriginAppOptions, OriginRepositoryRef } from "./types.js";
|
|
24
29
|
|
|
25
30
|
/** Origin operations exposed to hooks (`ctx.origin`). */
|
|
@@ -44,53 +49,77 @@ export interface OriginHandle {
|
|
|
44
49
|
createCheck(
|
|
45
50
|
input: Omit<OriginCheckCreateInput, "origin" | "owner" | "repo">
|
|
46
51
|
): Promise<OriginCheck>;
|
|
52
|
+
/**
|
|
53
|
+
* Add or remove one reaction on a PR comment — the Origin analogue of
|
|
54
|
+
* GitHub's `thread.react("eyes")`. Needs
|
|
55
|
+
* `repository:pull_requests:reviews:write`. Reactions have no REST
|
|
56
|
+
* binding, so this call goes to Origin's ConnectRPC host rather than the
|
|
57
|
+
* public API base {@link request} uses.
|
|
58
|
+
*/
|
|
59
|
+
reactToComment(input: OriginCommentReactionInput): Promise<void>;
|
|
47
60
|
}
|
|
48
61
|
|
|
49
62
|
export function buildOriginBinding(input: {
|
|
50
63
|
repository: OriginRepositoryRef;
|
|
51
64
|
/** Installation id from the delivery envelope, when present. */
|
|
52
65
|
installationId?: string;
|
|
66
|
+
/** Force the signed-in Cursor account / deployment SA credential path. */
|
|
67
|
+
cursorAccount?: boolean;
|
|
53
68
|
/** Channel-authored outbound app credentials / API base. */
|
|
54
69
|
app?: OriginAppOptions;
|
|
55
70
|
/** Injectable fetch for tests. */
|
|
56
71
|
fetch?: typeof fetch;
|
|
57
72
|
}): OriginHandle {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
73
|
+
const buildClient = (apiBaseUrl: string | undefined): OriginClient => {
|
|
74
|
+
const fromEnv = input.cursorAccount
|
|
75
|
+
? {}
|
|
76
|
+
: resolveOriginAppCredentialParts();
|
|
77
|
+
const appId = input.app?.appId ?? fromEnv.appId;
|
|
78
|
+
const installationId =
|
|
79
|
+
input.app?.installationId ??
|
|
80
|
+
input.installationId ??
|
|
81
|
+
fromEnv.installationId;
|
|
82
|
+
const privateKey = input.app?.privateKey ?? fromEnv.privateKey;
|
|
83
|
+
const credentials =
|
|
84
|
+
appId !== undefined &&
|
|
85
|
+
installationId !== undefined &&
|
|
86
|
+
privateKey !== undefined
|
|
87
|
+
? { appId, installationId, privateKey }
|
|
88
|
+
: undefined;
|
|
89
|
+
return createOriginClient({
|
|
90
|
+
token: input.cursorAccount ? undefined : input.app?.token,
|
|
91
|
+
credentials: input.cursorAccount ? false : credentials,
|
|
92
|
+
apiBaseUrl,
|
|
93
|
+
fetch: input.fetch,
|
|
94
|
+
});
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
// Public REST and ConnectRPC are separate Origin deployments, so the
|
|
98
|
+
// handle keeps a client per host. Both stay lazy: a hook that touches
|
|
99
|
+
// neither needs no credential.
|
|
100
|
+
let restClient: OriginClient | undefined;
|
|
101
|
+
const getRestClient = (): OriginClient => {
|
|
102
|
+
restClient ??= buildClient(input.app?.apiBaseUrl);
|
|
103
|
+
return restClient;
|
|
104
|
+
};
|
|
105
|
+
let rpcClient: OriginClient | undefined;
|
|
106
|
+
const getRpcClient = (): OriginClient => {
|
|
107
|
+
rpcClient ??= buildClient(input.app?.rpcBaseUrl ?? originRpcBaseUrl());
|
|
108
|
+
return rpcClient;
|
|
82
109
|
};
|
|
83
110
|
|
|
84
111
|
return {
|
|
85
112
|
installationId: input.app?.installationId ?? input.installationId,
|
|
86
113
|
repository: input.repository,
|
|
87
|
-
request: (request) =>
|
|
114
|
+
request: (request) => getRestClient().request(request),
|
|
88
115
|
createCheck: (check) =>
|
|
89
116
|
createOriginCheck({
|
|
90
117
|
...check,
|
|
91
|
-
origin:
|
|
118
|
+
origin: getRestClient(),
|
|
92
119
|
owner: input.repository.owner,
|
|
93
120
|
repo: input.repository.name,
|
|
94
121
|
}),
|
|
122
|
+
reactToComment: (reaction) =>
|
|
123
|
+
setOriginCommentReaction({ ...reaction, origin: getRpcClient() }),
|
|
95
124
|
};
|
|
96
125
|
}
|
|
@@ -306,6 +306,7 @@ export function parseOriginPullRequestEvent(input: {
|
|
|
306
306
|
repository,
|
|
307
307
|
pullRequestNumber: number,
|
|
308
308
|
pullRequestUrl: url,
|
|
309
|
+
pullRequestAuthor: author,
|
|
309
310
|
payload,
|
|
310
311
|
sender: originSender(input.envelope, payload),
|
|
311
312
|
},
|
|
@@ -432,6 +433,9 @@ function enrichEventContext(input: {
|
|
|
432
433
|
origin: buildOriginBinding({
|
|
433
434
|
repository: input.ctx.repository,
|
|
434
435
|
installationId: input.ctx.installationId,
|
|
436
|
+
cursorAccount:
|
|
437
|
+
input.options.cursorAccount !== undefined &&
|
|
438
|
+
input.options.cursorAccount !== false,
|
|
435
439
|
app: input.options.app,
|
|
436
440
|
}),
|
|
437
441
|
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Origin PR comment reactions — the Origin analogue of the GitHub channel's
|
|
3
|
+
* `thread.react("eyes")`.
|
|
4
|
+
*
|
|
5
|
+
* Unlike checks and comments, reactions have no `/v1/origin/...` REST
|
|
6
|
+
* binding. The only write is Connect unary JSON against Origin's first-party
|
|
7
|
+
* service (`origin.v1.OriginService/SetCommentReaction`), which lives on a
|
|
8
|
+
* different host than the public REST API — {@link originRpcBaseUrl}, not
|
|
9
|
+
* {@link originPublicApiBaseUrl}. `ctx.origin.reactToComment` already points
|
|
10
|
+
* at the right one; a hand-built client must too.
|
|
11
|
+
*
|
|
12
|
+
* Writing needs `repository:pull_requests:reviews:write`: an `oit_…`
|
|
13
|
+
* installation token for app channels, or a deployment service-account
|
|
14
|
+
* session (hosted v2 forks). Origin rejects reactions on comments that
|
|
15
|
+
* belong to an unsubmitted review. API failures throw `OriginApiError`.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import type { OriginApiMethod } from "./api.js";
|
|
19
|
+
|
|
20
|
+
/** Any client that can call Origin's ConnectRPC host. */
|
|
21
|
+
export interface OriginReactionClient {
|
|
22
|
+
request<T = unknown>(input: {
|
|
23
|
+
method: OriginApiMethod;
|
|
24
|
+
path: string;
|
|
25
|
+
body?: unknown;
|
|
26
|
+
}): Promise<T>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Connect unary route backing {@link setOriginCommentReaction}. */
|
|
30
|
+
export const SET_ORIGIN_COMMENT_REACTION_PATH =
|
|
31
|
+
"/origin.v1.OriginService/SetCommentReaction";
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* The eight reactions Origin accepts. Anything else is rejected with
|
|
35
|
+
* `invalid_argument`, so channels get a compile error instead of a 400.
|
|
36
|
+
*/
|
|
37
|
+
export const ORIGIN_COMMENT_REACTIONS = [
|
|
38
|
+
"👍",
|
|
39
|
+
"👎",
|
|
40
|
+
"😄",
|
|
41
|
+
"🎉",
|
|
42
|
+
"😕",
|
|
43
|
+
"❤️",
|
|
44
|
+
"🚀",
|
|
45
|
+
"👀",
|
|
46
|
+
] as const;
|
|
47
|
+
|
|
48
|
+
export type OriginCommentReaction = (typeof ORIGIN_COMMENT_REACTIONS)[number];
|
|
49
|
+
|
|
50
|
+
export interface OriginCommentReactionInput {
|
|
51
|
+
/** Origin comment TypeID (`cmt_…`), i.e. `comment.id` on a comment hook. */
|
|
52
|
+
commentId: string;
|
|
53
|
+
emoji: OriginCommentReaction;
|
|
54
|
+
/** `false` removes the reaction. Removing one that is absent is a no-op. */
|
|
55
|
+
active?: boolean;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Add (or, with `active: false`, remove) one reaction on an Origin PR
|
|
60
|
+
* comment as the client's own principal.
|
|
61
|
+
*
|
|
62
|
+
* ```ts
|
|
63
|
+
* await setOriginCommentReaction({
|
|
64
|
+
* origin: createOriginClient({ apiBaseUrl: originRpcBaseUrl() }),
|
|
65
|
+
* commentId: comment.id,
|
|
66
|
+
* emoji: "👀",
|
|
67
|
+
* });
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export async function setOriginCommentReaction(
|
|
71
|
+
input: OriginCommentReactionInput & { origin: OriginReactionClient }
|
|
72
|
+
): Promise<void> {
|
|
73
|
+
await input.origin.request({
|
|
74
|
+
method: "POST",
|
|
75
|
+
path: SET_ORIGIN_COMMENT_REACTION_PATH,
|
|
76
|
+
body: {
|
|
77
|
+
commentId: input.commentId,
|
|
78
|
+
emoji: input.emoji,
|
|
79
|
+
active: input.active ?? true,
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
}
|
|
@@ -58,6 +58,11 @@ export interface OriginEventContext {
|
|
|
58
58
|
repository: OriginRepositoryRef;
|
|
59
59
|
pullRequestNumber: number;
|
|
60
60
|
pullRequestUrl: string;
|
|
61
|
+
/**
|
|
62
|
+
* Who opened the pull request, when the payload carries it. Distinct from
|
|
63
|
+
* {@link sender} — on a comment event the sender is the commenter.
|
|
64
|
+
*/
|
|
65
|
+
pullRequestAuthor?: OriginActor;
|
|
61
66
|
/**
|
|
62
67
|
* Raw parsed `event.payload` record (`{}` when absent), for consumers
|
|
63
68
|
* whose normalization needs more than the typed event — the GitHub
|
|
@@ -152,6 +157,12 @@ export interface OriginAppOptions {
|
|
|
152
157
|
token?: string | OriginTokenProvider;
|
|
153
158
|
/** Public Origin REST base, e.g. `https://api.cursor.com`. */
|
|
154
159
|
apiBaseUrl?: string;
|
|
160
|
+
/**
|
|
161
|
+
* Origin ConnectRPC base for operations without a REST binding (comment
|
|
162
|
+
* reactions), e.g. `https://api.origin.cursor.com`. Falls back to
|
|
163
|
+
* `ORIGIN_RPC_BASE_URL`.
|
|
164
|
+
*/
|
|
165
|
+
rpcBaseUrl?: string;
|
|
155
166
|
}
|
|
156
167
|
|
|
157
168
|
export interface OriginChannelOptions {
|