@cursor/july 0.1.68 → 0.1.74
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 +17 -13
- package/README.md +23 -11
- package/dist/bin/agent-serve.js +10 -7
- package/dist/channels/github/api.d.ts +2 -0
- package/dist/channels/github/api.d.ts.map +1 -1
- package/dist/channels/github/api.js +2 -1
- package/dist/channels/github/binding.d.ts +7 -0
- package/dist/channels/github/binding.d.ts.map +1 -1
- package/dist/channels/github/binding.js +4 -0
- package/dist/channels/github/checks.d.ts +99 -0
- package/dist/channels/github/checks.d.ts.map +1 -0
- package/dist/channels/github/checks.js +108 -0
- package/dist/channels/github/cursor-account.d.ts +4 -4
- package/dist/channels/github/cursor-account.d.ts.map +1 -1
- package/dist/channels/github/cursor-account.js +7 -5
- package/dist/channels/github/index.d.ts +1 -0
- package/dist/channels/github/index.d.ts.map +1 -1
- package/dist/channels/github/index.js +1 -0
- package/dist/channels/github/types.d.ts +8 -0
- package/dist/channels/github/types.d.ts.map +1 -1
- package/dist/channels/slack/manifest.d.ts +2 -2
- package/dist/channels/slack/manifest.d.ts.map +1 -1
- package/dist/channels/slack/manifest.js +13 -11
- package/dist/channels/slack/types.d.ts +2 -2
- package/dist/channels/slack/types.d.ts.map +1 -1
- package/dist/connections.d.ts +17 -5
- package/dist/connections.d.ts.map +1 -1
- package/dist/connections.js +17 -5
- package/dist/docs/404.html +2 -2
- package/dist/docs/ab.html +3 -3
- package/dist/docs/assets/{app.C5XUTCw9.js → app.BETd-WqU.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.DM5INS71.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.CGDTAYHY.js → VPLocalSearchBox.wEaGEmV9.js} +1 -1
- package/dist/docs/assets/chunks/{theme.lPixh250.js → theme.DNDicFOP.js} +2 -2
- package/dist/docs/assets/{concepts.md.CqOsxbMU.js → concepts.md.BXAm6G-C.js} +1 -1
- package/dist/docs/assets/{guides_mcp-oauth.md.C7G7IykG.js → guides_mcp-oauth.md.CzEB6RaG.js} +1 -1
- package/dist/docs/assets/{reference_agent-config.md.DHkkvcEZ.js → reference_agent-config.md.BZnEKfEc.js} +3 -4
- package/dist/docs/assets/{reference_agent-config.md.DHkkvcEZ.lean.js → reference_agent-config.md.BZnEKfEc.lean.js} +1 -1
- package/dist/docs/assets/{reference_cli.md.Cl14Jfo3.js → reference_cli.md.TAaYU8br.js} +3 -3
- package/dist/docs/assets/{reference_cli.md.Cl14Jfo3.lean.js → reference_cli.md.TAaYU8br.lean.js} +1 -1
- package/dist/docs/assets/{reference_connections.md.Bwswbm6H.js → reference_connections.md.Cu3N-S3Q.js} +18 -11
- package/dist/docs/assets/{reference_connections.md.Bwswbm6H.lean.js → reference_connections.md.Cu3N-S3Q.lean.js} +1 -1
- package/dist/docs/assets/{reference_sessions.md.DBVFi2Sx.js → reference_sessions.md.B0DdlM-K.js} +1 -1
- package/dist/docs/assets/{reference_tools.md.Wmvb7Lob.js → reference_tools.md.DTg_kEsx.js} +1 -1
- package/dist/docs/assets/scaffolding-agents.md.CiGsJ1aw.js +1 -0
- package/dist/docs/assets/{scaffolding-agents.md.CrWSA0Ko.lean.js → scaffolding-agents.md.CiGsJ1aw.lean.js} +1 -1
- package/dist/docs/assets/troubleshooting.md.DQ-hYuZT.js +1 -0
- package/dist/docs/building-with-agents.html +3 -3
- package/dist/docs/concepts.html +5 -5
- package/dist/docs/deployment.html +3 -3
- package/dist/docs/evals.html +3 -3
- package/dist/docs/example-agents/approval-buddy.html +3 -3
- package/dist/docs/example-agents/benny.html +3 -3
- package/dist/docs/example-agents/bugbot.html +3 -3
- package/dist/docs/example-agents/codebase-wiki.html +3 -3
- package/dist/docs/example-agents/codeowners-review.html +3 -3
- package/dist/docs/example-agents/concierge.html +3 -3
- package/dist/docs/example-agents/fsd.html +3 -3
- package/dist/docs/example-agents/index.html +3 -3
- package/dist/docs/example-agents/knowledge-base.html +3 -3
- package/dist/docs/example-agents/oncall.html +3 -3
- package/dist/docs/example-agents/security-reviewer.html +3 -3
- package/dist/docs/example-agents/slack-agent.html +3 -3
- package/dist/docs/example-agents/weather-agent.html +3 -3
- package/dist/docs/guides/agent-to-agent.html +3 -3
- package/dist/docs/guides/cloud-runtime.html +3 -3
- package/dist/docs/guides/convert-automation.html +3 -3
- package/dist/docs/guides/github.html +3 -3
- package/dist/docs/guides/human-in-the-loop.html +3 -3
- package/dist/docs/guides/mcp-oauth.html +5 -5
- package/dist/docs/guides/opentelemetry.html +3 -3
- package/dist/docs/guides/slack.html +3 -3
- package/dist/docs/guides/webhooks.html +3 -3
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +3 -3
- package/dist/docs/index.html +3 -3
- package/dist/docs/quickstart.html +3 -3
- package/dist/docs/reference/agent-config.html +5 -6
- package/dist/docs/reference/artifacts.html +3 -3
- package/dist/docs/reference/channels.html +3 -3
- package/dist/docs/reference/cli.html +6 -6
- package/dist/docs/reference/connections.html +20 -13
- package/dist/docs/reference/hooks.html +3 -3
- package/dist/docs/reference/http-api.html +3 -3
- package/dist/docs/reference/instructions.html +3 -3
- package/dist/docs/reference/playground.html +3 -3
- package/dist/docs/reference/project-layout.html +3 -3
- package/dist/docs/reference/prompt.html +3 -3
- package/dist/docs/reference/schedules.html +3 -3
- package/dist/docs/reference/sessions.html +5 -5
- package/dist/docs/reference/skills.html +3 -3
- package/dist/docs/reference/subagents.html +3 -3
- package/dist/docs/reference/tools.html +5 -5
- package/dist/docs/scaffolding-agents.html +5 -5
- package/dist/docs/storage.html +3 -3
- package/dist/docs/templates/agentic-owners.html +3 -3
- package/dist/docs/templates/demo.html +3 -3
- package/dist/docs/templates/pr-autofixer.html +3 -3
- package/dist/docs/templates/security-reviewer.html +3 -3
- package/dist/docs/templates/triage.html +3 -3
- package/dist/docs/troubleshooting.html +5 -5
- package/dist/internal/advertise-tools.d.ts +11 -6
- package/dist/internal/advertise-tools.d.ts.map +1 -1
- package/dist/internal/advertise-tools.js +63 -30
- package/dist/internal/cli-deploy.d.ts.map +1 -1
- package/dist/internal/cli-deploy.js +2 -4
- package/dist/internal/cli-skills.d.ts +4 -2
- package/dist/internal/cli-skills.d.ts.map +1 -1
- package/dist/internal/cli-skills.js +8 -3
- package/dist/internal/convert-automation/convert-workflow.d.ts.map +1 -1
- package/dist/internal/convert-automation/convert-workflow.js +2 -10
- package/dist/internal/cursor/account-mcp.d.ts +29 -3
- package/dist/internal/cursor/account-mcp.d.ts.map +1 -1
- package/dist/internal/cursor/account-mcp.js +147 -67
- package/dist/internal/cursor/backend-client.d.ts +11 -6
- package/dist/internal/cursor/backend-client.d.ts.map +1 -1
- package/dist/internal/cursor/backend-client.js +32 -10
- package/dist/internal/cursor-account-mcp-auth.d.ts +11 -0
- package/dist/internal/cursor-account-mcp-auth.d.ts.map +1 -1
- package/dist/internal/cursor-account-mcp-auth.js +69 -0
- package/dist/internal/deploy-client.d.ts +0 -7
- package/dist/internal/deploy-client.d.ts.map +1 -1
- package/dist/internal/deploy-client.js +2 -4
- package/dist/internal/deploy-manifest.d.ts +15 -24
- package/dist/internal/deploy-manifest.d.ts.map +1 -1
- package/dist/internal/deploy-manifest.js +38 -27
- package/dist/internal/deployment-scm-event-stream.d.ts +4 -1
- package/dist/internal/deployment-scm-event-stream.d.ts.map +1 -1
- package/dist/internal/deployment-scm-event-stream.js +15 -1
- package/dist/internal/discovery.d.ts.map +1 -1
- package/dist/internal/discovery.js +42 -10
- package/dist/internal/init-project.d.ts.map +1 -1
- package/dist/internal/init-project.js +7 -106
- package/dist/internal/init-scaffold.d.ts +8 -0
- package/dist/internal/init-scaffold.d.ts.map +1 -0
- package/dist/internal/init-scaffold.js +168 -0
- package/dist/internal/inline-stdio-mcp.d.ts +2 -0
- package/dist/internal/inline-stdio-mcp.d.ts.map +1 -1
- package/dist/internal/inline-stdio-mcp.js +10 -8
- package/dist/internal/install-cursor-skills.d.ts +71 -16
- package/dist/internal/install-cursor-skills.d.ts.map +1 -1
- package/dist/internal/install-cursor-skills.js +160 -48
- package/dist/internal/json-schema.d.ts +7 -0
- package/dist/internal/json-schema.d.ts.map +1 -1
- package/dist/internal/json-schema.js +18 -3
- package/dist/internal/mcp-endpoint.js +7 -7
- package/dist/internal/mcp-host.js +4 -2
- package/dist/internal/mcp-oauth.d.ts +22 -0
- package/dist/internal/mcp-oauth.d.ts.map +1 -1
- package/dist/internal/mcp-oauth.js +40 -1
- package/dist/internal/package-inline-stdio.d.ts.map +1 -1
- package/dist/internal/package-inline-stdio.js +5 -5
- package/dist/internal/review-comments.d.ts +97 -0
- package/dist/internal/review-comments.d.ts.map +1 -1
- package/dist/internal/review-comments.js +151 -0
- package/dist/internal/sanitize-mcp-tool-name.d.ts +20 -0
- package/dist/internal/sanitize-mcp-tool-name.d.ts.map +1 -0
- package/dist/internal/sanitize-mcp-tool-name.js +30 -0
- package/dist/internal/sdk-runner.d.ts.map +1 -1
- package/dist/internal/sdk-runner.js +6 -2
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +4 -6
- package/dist/internal/shallow-clone.d.ts +94 -39
- package/dist/internal/shallow-clone.d.ts.map +1 -1
- package/dist/internal/shallow-clone.js +188 -68
- package/dist/internal/terminal-style.d.ts +18 -0
- package/dist/internal/terminal-style.d.ts.map +1 -1
- package/dist/internal/terminal-style.js +46 -1
- package/dist/internal/workspace.d.ts +2 -0
- package/dist/internal/workspace.d.ts.map +1 -1
- package/dist/internal/workspace.js +5 -0
- package/dist/playground/assets/index-D_8I9TM0.js +85 -0
- package/dist/playground/assets/index-M3nSMc6_.css +1 -0
- package/dist/playground/index.html +2 -2
- package/dist/tools.d.ts +7 -0
- package/dist/tools.d.ts.map +1 -1
- package/dist/types.d.ts +28 -3
- package/dist/types.d.ts.map +1 -1
- package/docs/concepts.md +4 -4
- package/docs/guides/mcp-oauth.md +3 -1
- package/docs/reference/agent-config.md +11 -12
- package/docs/reference/cli.md +16 -8
- package/docs/reference/connections.md +44 -26
- package/docs/reference/sessions.md +2 -2
- package/docs/reference/tools.md +1 -1
- package/docs/scaffolding-agents.md +14 -6
- package/docs/troubleshooting.md +3 -2
- package/package.json +6 -1
- package/scripts/install-cursor-skills.mjs +36 -0
- package/skills/ab/SKILL.md +1 -1
- package/skills/create-agent/SKILL.md +13 -10
- package/skills/debug/SKILL.md +3 -2
- package/skills/evals/SKILL.md +1 -1
- package/skills/framework-map/SKILL.md +7 -7
- package/skills/github/SKILL.md +1 -1
- package/skills/hillclimb/SKILL.md +1 -1
- package/skills/mcp-auth/SKILL.md +9 -7
- package/skills/otel/SKILL.md +1 -1
- package/skills/setup-slack/SKILL.md +1 -1
- package/src/bin/agent-serve.ts +10 -7
- package/src/channels/github/api.ts +6 -1
- package/src/channels/github/binding.ts +21 -0
- package/src/channels/github/checks.ts +179 -0
- package/src/channels/github/cursor-account.ts +9 -6
- package/src/channels/github/index.ts +1 -0
- package/src/channels/github/types.ts +8 -0
- package/src/channels/slack/manifest.ts +8 -10
- package/src/channels/slack/types.ts +2 -2
- package/src/connections.ts +17 -5
- package/src/internal/advertise-tools.ts +72 -23
- package/src/internal/cli-deploy.ts +4 -15
- package/src/internal/cli-skills.ts +10 -2
- package/src/internal/convert-automation/convert-workflow.ts +2 -11
- package/src/internal/cursor/account-mcp.ts +208 -73
- package/src/internal/cursor/backend-client.ts +45 -11
- package/src/internal/cursor-account-mcp-auth.ts +83 -0
- package/src/internal/deploy-client.ts +0 -10
- package/src/internal/deploy-manifest.ts +33 -39
- package/src/internal/deployment-scm-event-stream.ts +17 -1
- package/src/internal/discovery.ts +47 -3
- package/src/internal/init-project.ts +7 -133
- package/src/internal/init-scaffold.ts +176 -0
- package/src/internal/inline-stdio-mcp.ts +13 -0
- package/src/internal/install-cursor-skills.ts +204 -49
- package/src/internal/json-schema.ts +24 -3
- package/src/internal/mcp-endpoint.ts +6 -0
- package/src/internal/mcp-host.ts +4 -0
- package/src/internal/mcp-oauth.ts +55 -1
- package/src/internal/package-inline-stdio.ts +5 -1
- package/src/internal/review-comments.ts +245 -0
- package/src/internal/sanitize-mcp-tool-name.ts +33 -0
- package/src/internal/sdk-runner.ts +6 -3
- package/src/internal/session-engine.ts +7 -0
- package/src/internal/shallow-clone.ts +293 -105
- package/src/internal/terminal-style.ts +67 -1
- package/src/internal/workspace.ts +6 -0
- package/src/tools.ts +7 -0
- package/src/types.ts +32 -4
- package/templates/agentic-owners/agent/agent.ts +3 -0
- package/templates/demo/agent/agent.ts +3 -0
- package/templates/security-reviewer/agent/agent.ts +3 -0
- package/templates/triage/agent/agent.ts +3 -0
- package/dist/docs/assets/chunks/@localSearchIndexroot.DvUR3lv9.js +0 -1
- package/dist/docs/assets/scaffolding-agents.md.CrWSA0Ko.js +0 -1
- package/dist/docs/assets/troubleshooting.md.CuVztCKs.js +0 -1
- package/dist/playground/assets/index-CoL7xCJl.css +0 -1
- package/dist/playground/assets/index-yxs1heea.js +0 -85
- /package/dist/docs/assets/{concepts.md.CqOsxbMU.lean.js → concepts.md.BXAm6G-C.lean.js} +0 -0
- /package/dist/docs/assets/{guides_mcp-oauth.md.C7G7IykG.lean.js → guides_mcp-oauth.md.CzEB6RaG.lean.js} +0 -0
- /package/dist/docs/assets/{reference_sessions.md.DBVFi2Sx.lean.js → reference_sessions.md.B0DdlM-K.lean.js} +0 -0
- /package/dist/docs/assets/{reference_tools.md.Wmvb7Lob.lean.js → reference_tools.md.DTg_kEsx.lean.js} +0 -0
- /package/dist/docs/assets/{troubleshooting.md.CuVztCKs.lean.js → troubleshooting.md.DQ-hYuZT.lean.js} +0 -0
|
@@ -16,13 +16,21 @@ into a small working project. Have Cursor read that file and follow it.
|
|
|
16
16
|
|
|
17
17
|
Where to find the file depends on how you got the package:
|
|
18
18
|
|
|
19
|
-
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
- Installing `@cursor/july` (`npm install`, `npx @cursor/july`, a
|
|
20
|
+
version bump) copies every package skill into
|
|
21
|
+
`~/.cursor/skills/agentsdk/` with `alwaysApply: true`, so Cursor
|
|
22
|
+
injects the skill body into context instead of waiting for the
|
|
23
|
+
model to pick it from the catalog. The `/` menu lists them as
|
|
24
|
+
`/agentsdk-create-agent`, `/agentsdk-hillclimb`, and the rest. Re-installing overwrites those
|
|
25
|
+
copies with the package version. Set
|
|
26
|
+
`CURSOR_JULY_SKIP_SKILL_INSTALL=1` to skip the copy.
|
|
27
|
+
- Installed `@cursor/july` as a dependency? The skill also ships inside
|
|
28
|
+
the package at `node_modules/@cursor/july/skills/create-agent/SKILL.md`.
|
|
24
29
|
- Working in the monorepo? It's at
|
|
25
|
-
`packages/agent-serve/skills/create-agent/SKILL.md`.
|
|
30
|
+
`packages/agent-serve/skills/create-agent/SKILL.md`. Run
|
|
31
|
+
`agent-sdk install-skills` if you want the same copies in
|
|
32
|
+
`~/.cursor/skills/agentsdk/` (the package postinstall skips the
|
|
33
|
+
source checkout).
|
|
26
34
|
|
|
27
35
|
Cursor will:
|
|
28
36
|
|
package/docs/troubleshooting.md
CHANGED
|
@@ -31,7 +31,8 @@ Match your symptom below. Keep the commands as `agent-sdk`; see
|
|
|
31
31
|
| --- | --- |
|
|
32
32
|
| Built-in file reads and greps fail; the turn retries for a long time | Run under Node 22.13+ (or `tsx`), never Bun. Look for `NGHTTP2_FRAME_SIZE_ERROR` in logs. |
|
|
33
33
|
| The turn fails immediately with an API-key error | Sign in with `agent-sdk login`, or set `CURSOR_API_KEY`. Discovery, `info`, `call`, and serve bring-up work without a key; model turns need one. |
|
|
34
|
-
| Replies quote rules or `AGENTS.md` from outside your agent project | The session workspace inherited parent-folder config. Point `defineAgent({ local: { cwd } })`
|
|
34
|
+
| Replies quote rules or `AGENTS.md` from outside your agent project | The session workspace inherited parent-folder config. Nested git checkouts default `local.cwd` to `~/.cache/agent-serve/<dir>`. Point `defineAgent({ local: { cwd } })` at a checkout only when the agent should inherit that tree, or set `--state-root` to a clean directory (for example under `/tmp`). |
|
|
35
|
+
| Yellow box shows Datadog/Linear tools, but the model lists `GetDynamicTools` / IDE `cursor` tools and never calls them | Attached MCP sits behind harness meta-tools, or `hostOnly` hid the connection, or the harness cwd is still inside another checkout. Set `advertiseTools: true` for named tools on local turns. Check `GET /v1/info` `local.cwd` and `connections[].advertiseTools`. |
|
|
35
36
|
| Server tools, skills, or workspace seed files never appear | The agent runtime is `cloud`. Those features apply on the local runtime. `validate` warns when this combination is present. |
|
|
36
37
|
| `validate` and `run` succeed, but typecheck fails in CI | The CLI runs TypeScript with type-stripping only. Keep tool `execute` return types as object literals or `type` aliases, not `interface` types. |
|
|
37
38
|
| Login works, but turns are rejected when using custom API hosts | Point login and model traffic at the same host (`CURSOR_API_BASE_URL` and `CURSOR_BACKEND_URL`). A key from one host is rejected by the other. |
|
|
@@ -70,7 +71,7 @@ Match your symptom below. Keep the commands as `agent-sdk`; see
|
|
|
70
71
|
| --- | --- |
|
|
71
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`. |
|
|
72
73
|
| Local auth works; hosted calls unauthorized | Run `agent-sdk mcp oauth <name> --store`, confirm names with `agent-sdk secrets list <slug>`, then redeploy. |
|
|
73
|
-
| Model asks for `mcp_auth` or IDE MCP for a privileged server | That connection is
|
|
74
|
+
| Model asks for `mcp_auth` or IDE MCP for a privileged server | That connection is `hostOnly`. Call it from a host tool via `ctx.host.mcp`, and update instructions. |
|
|
74
75
|
|
|
75
76
|
See [Host MCP OAuth](./guides/mcp-oauth.md) and
|
|
76
77
|
[`skills/mcp-auth/SKILL.md`](../skills/mcp-auth/SKILL.md).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cursor/july",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.74",
|
|
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": {
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
"templates/**/*",
|
|
35
35
|
"docs/**/*.md",
|
|
36
36
|
"!docs/.cursor/**",
|
|
37
|
+
"scripts/install-cursor-skills.mjs",
|
|
37
38
|
"package.json",
|
|
38
39
|
"LICENSE.md",
|
|
39
40
|
"README.md",
|
|
@@ -150,18 +151,21 @@
|
|
|
150
151
|
},
|
|
151
152
|
"./kv": {
|
|
152
153
|
"anysphere-source": "./src/kv.ts",
|
|
154
|
+
"bun": "./dist/kv.js",
|
|
153
155
|
"types": "./dist/kv.d.ts",
|
|
154
156
|
"import": "./dist/kv.js",
|
|
155
157
|
"default": "./dist/kv.js"
|
|
156
158
|
},
|
|
157
159
|
"./kv/memory": {
|
|
158
160
|
"anysphere-source": "./src/kv/memory-kv.ts",
|
|
161
|
+
"bun": "./dist/kv/memory-kv.js",
|
|
159
162
|
"types": "./dist/kv/memory-kv.d.ts",
|
|
160
163
|
"import": "./dist/kv/memory-kv.js",
|
|
161
164
|
"default": "./dist/kv/memory-kv.js"
|
|
162
165
|
},
|
|
163
166
|
"./ledger": {
|
|
164
167
|
"anysphere-source": "./src/ledger.ts",
|
|
168
|
+
"bun": "./dist/ledger.js",
|
|
165
169
|
"types": "./dist/ledger.d.ts",
|
|
166
170
|
"import": "./dist/ledger.js",
|
|
167
171
|
"default": "./dist/ledger.js"
|
|
@@ -200,6 +204,7 @@
|
|
|
200
204
|
},
|
|
201
205
|
"scripts": {
|
|
202
206
|
"build": "tsgo -p tsconfig.build.json && node scripts/bundle-publish-shims.mjs && pnpm run build:playground && pnpm run docs:build",
|
|
207
|
+
"postinstall": "node -e \"try{const p='./scripts/install-cursor-skills.mjs';if(require('fs').existsSync(p))require('child_process').execFileSync(process.execPath,[p],{stdio:'inherit'})}catch{}\"",
|
|
203
208
|
"build:playground": "vite build --config playground/vite.config.ts",
|
|
204
209
|
"build:playground:central": "vite build --mode central --config playground/vite.config.ts",
|
|
205
210
|
"dev:playground": "vite --config playground/vite.config.ts",
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* postinstall: copy Agent SDK coding-agent skills into ~/.cursor/skills/agentsdk
|
|
4
|
+
* so Cursor discovers them after `npm install` / `npx @cursor/july`.
|
|
5
|
+
*
|
|
6
|
+
* Never fails the package install. No-op in the monorepo source checkout
|
|
7
|
+
* (package root is not under node_modules) and when dist is missing.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { existsSync } from "node:fs";
|
|
11
|
+
import { dirname, join } from "node:path";
|
|
12
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
13
|
+
|
|
14
|
+
const packageRoot = join(dirname(fileURLToPath(import.meta.url)), "..");
|
|
15
|
+
const distEntry = join(
|
|
16
|
+
packageRoot,
|
|
17
|
+
"dist",
|
|
18
|
+
"internal",
|
|
19
|
+
"install-cursor-skills.js"
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
if (!existsSync(distEntry)) {
|
|
24
|
+
process.exit(0);
|
|
25
|
+
}
|
|
26
|
+
// Windows: Node's ESM loader rejects bare drive-letter paths
|
|
27
|
+
// (`ERR_UNSUPPORTED_ESM_URL_SCHEME`). file:// is valid on every platform.
|
|
28
|
+
const { syncCursorSkillsOnPackageInstall } = await import(
|
|
29
|
+
pathToFileURL(distEntry).href
|
|
30
|
+
);
|
|
31
|
+
await syncCursorSkillsOnPackageInstall({ packageRoot });
|
|
32
|
+
} catch {
|
|
33
|
+
// Swallow: a skill copy must not fail `npm install`.
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
process.exit(0);
|
package/skills/ab/SKILL.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: agentsdk-create-agent
|
|
3
3
|
description: >-
|
|
4
4
|
Scaffold a new Agent SDK agent through a guided AskQuestion interview —
|
|
5
5
|
purpose, name, runtime, model, channels, MCP connections, capabilities —
|
|
@@ -62,7 +62,7 @@ questions, concrete options, the recommended option listed first and labeled
|
|
|
62
62
|
| **Runtime** | `local` (default) · `cloud` | Local = Cursor SDK harness on this machine; server tools, skills, sandbox seeds, and tool approvals all work. Cloud = Cursor cloud agents; needs `cloud.repos`, no server tools/skills/sandbox seeds (instructions are prepended to the first prompt). Recommend local unless the purpose needs a repo checkout on a cloud VM. |
|
|
63
63
|
| **Model** | `grok-4.5` with `effort=high`, `fast=true` (default) · Other model id | Effort and fast are params, not id suffixes: `{ id: "grok-4.5", params: [{ id: "effort", value: "high" }, { id: "fast", value: "true" }] }` — the SDK rejects suffix-style ids. |
|
|
64
64
|
| **Channels** (multi) | playground + HTTP API only (always mounted) · Slack · GitHub webhooks · custom webhook · schedule (cron) | Slack has two connections: the Cursor-hosted connection (`cursorAccount: true` — zero Slack admin, recommended default) and a dedicated Socket Mode app (own bot user + one app/token pair per agent; needed for channel watching or approval buttons). When Slack is picked, resolve the connection with the Step 0 gate in `setup-slack/SKILL.md` — either fold its AskQuestion into this round or ask it before channel setup; default to Cursor-hosted when you cannot ask. GitHub verifies `X-Hub-Signature-256` when a secret is set. Discord/Teams packs do not exist yet — offer custom webhook instead. |
|
|
65
|
-
| **MCP connections** (multi) | none · remote server (URL + header auth) · local stdio server · Other | One file per server under `agent/mcp-connections/`; filename = server name;
|
|
65
|
+
| **MCP connections** (multi) | none · remote server (URL + header auth) · local stdio server · Cursor account connectors · Other | One file per server under `agent/mcp-connections/`; filename = server name. Do not name an account connection `cursor.ts` (collides with the IDE `cursor` namespace); use `account.ts`. Tokens via env vars, never hardcoded. Connections serve the model and host code (`ctx.host.mcp`). If the model should call them by name on local turns, set `advertiseTools: true`. Set `hostOnly: true` only when host tools call the server and the playground must not. |
|
|
66
66
|
| **Capabilities** (multi) | server tools · agent tools (scripts) · skills · subagents · hooks · sandbox seed files · tool approvals (HITL) · evals (recommend) | Server tools, skills, sandbox seeds, approvals are local-runtime only. Agent tools (`execution: "agent"`) work on both runtimes. Always recommend at least one smoke eval. |
|
|
67
67
|
|
|
68
68
|
Close the round with a one-screen plan — chosen options plus the file tree you
|
|
@@ -87,6 +87,10 @@ Defaults that make first cuts good:
|
|
|
87
87
|
|
|
88
88
|
- **Minimal surface.** Instructions + 1–2 real tools + the chosen channels +
|
|
89
89
|
one smoke eval. Unpicked capabilities are follow-ups, not scope.
|
|
90
|
+
- **`local.cwd`.** Keep the harness outside a monorepo checkout
|
|
91
|
+
(`~/.cache/agent-serve/<slug>`). Discovery does this for nested git
|
|
92
|
+
projects. Point cwd at a checkout only when the agent must inherit that
|
|
93
|
+
tree.
|
|
90
94
|
- **Instructions** (`agent/instructions.md`, required): a few lines — identity,
|
|
91
95
|
when to use which tool, output shape. Not an essay.
|
|
92
96
|
- **Tool per file**, filename = tool name the model sees. Prefer
|
|
@@ -139,9 +143,9 @@ agent-sdk init ./<slug>
|
|
|
139
143
|
```
|
|
140
144
|
|
|
141
145
|
`init` writes `package.json` (with `typescript` dev deps and a
|
|
142
|
-
`check` script), `tsconfig.json`, `
|
|
143
|
-
a demo `agent/tools/echo.ts`, and empty capability
|
|
144
|
-
(`skills/`, `channels/`, `evals/`, …) each with a `.gitkeep`; existing
|
|
146
|
+
`check` script), `tsconfig.json`, `AGENTS.md`, `.gitignore`, `agent/agent.ts`,
|
|
147
|
+
`agent/instructions.md`, a demo `agent/tools/echo.ts`, and empty capability
|
|
148
|
+
folders (`skills/`, `channels/`, `evals/`, …) each with a `.gitkeep`; existing
|
|
145
149
|
files are left alone (`exist`) and missing ones are filled in. It then
|
|
146
150
|
runs `npm install`, and when the host is unsigned runs `login` and waits
|
|
147
151
|
before printing `cd` (when needed) and `agent-sdk dev`. Then shape it to the
|
|
@@ -149,8 +153,7 @@ plan:
|
|
|
149
153
|
|
|
150
154
|
1. `tsconfig.json` — init writes a strict, `noEmit` config covering `agent/`
|
|
151
155
|
and `evals/`; extend it only when the project needs more.
|
|
152
|
-
2. `agent/agent.ts` — chosen model/runtime via `defineAgent({...})
|
|
153
|
-
`cloud: { repos: [...] }` block for cloud runtime.
|
|
156
|
+
2. `agent/agent.ts` — chosen model/runtime via `defineAgent({...})`. Nested git checkouts get `local.cwd` under `~/.cache/agent-serve/<slug>` at discovery even if omitted. Add the `cloud: { repos: [...] }` block for cloud runtime.
|
|
154
157
|
3. `agent/instructions.md` — real instructions; delete or replace `echo.ts`
|
|
155
158
|
with the real tools.
|
|
156
159
|
4. Add the chosen `channels/`, `mcp-connections/`, `skills/`, `subagents/<id>/`
|
|
@@ -210,9 +213,9 @@ agent-sdk eval --dir ./<slug>
|
|
|
210
213
|
|
|
211
214
|
Serve only the new agent's directory during bring-up — pointing `serve` at a
|
|
212
215
|
parent folder also mounts every sibling agent it contains.
|
|
213
|
-
Runtime state lands in `<project>/.agent-serve/` (gitignored)
|
|
214
|
-
|
|
215
|
-
`
|
|
216
|
+
Runtime state lands in `<project>/.agent-serve/` (gitignored). Nested
|
|
217
|
+
checkouts default `local.cwd` to `~/.cache/agent-serve/<slug>` at
|
|
218
|
+
discovery. `--state-root` is for session files, not harness cwd.
|
|
216
219
|
|
|
217
220
|
## Channel setup with the user
|
|
218
221
|
|
package/skills/debug/SKILL.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: agentsdk-debug
|
|
3
3
|
description: >-
|
|
4
4
|
Diagnose a misbehaving Agent SDK agent, server, or playground — blank
|
|
5
5
|
playground, sessions missing, HMR not reloading, failing reads/retry
|
|
@@ -47,7 +47,8 @@ curl -sN 'localhost:3000/<slug>/v1/session/<id>/stream?startIndex=0' | head -50
|
|
|
47
47
|
| Every built-in read/grep the model makes fails; turns crawl through retry loops | You ran the CLI under **Bun**. Kill it, rerun under Node/tsx. (`NGHTTP2_FRAME_SIZE_ERROR` in SDK logs is the tell.) |
|
|
48
48
|
| `gh webhook forward` / `agent-sdk github forward` deliveries all 401 — but hook creation succeeded | `GITHUB_TOKEN`/`GH_TOKEN` in the env. The relay authenticates with the gh CLI login and rejects env tokens. `GITHUB_TOKEN= GH_TOKEN= agent-sdk github forward ...` |
|
|
49
49
|
| `Hook already exists` starting a forwarder | GitHub allows one forwarder per repo. Use one `github forward --dir <parent>` (it fans out to every matching channel) instead of N processes; kill stale forwarders. |
|
|
50
|
-
| Agent's answers reference monorepo rules / AGENTS.md it shouldn't know | Session workspace sits inside
|
|
50
|
+
| Agent's answers reference monorepo rules / AGENTS.md it shouldn't know | Session workspace sits inside another git checkout, so the harness loaded ancestor config. Nested projects default `local.cwd` to `~/.cache/agent-serve/<dir>`. Point cwd at a checkout only when the agent should inherit that tree. |
|
|
51
|
+
| Yellow box lists Datadog/Linear tools; model recites `GetDynamicTools` / IDE `cursor` tools and never calls MCP | Attached MCP is behind meta-tools, or `hostOnly` hid it, or cwd still leaked IDE MCP. Set `advertiseTools: true` for named tools on local turns. Confirm `GET /v1/info` `local.cwd` and `connections[].advertiseTools`. |
|
|
51
52
|
| Port 3000/5273 in use; stray processes after crashes | `lsof -iTCP:3000 -sTCP:LISTEN`, kill the pids; also check companion processes (e.g. vite). |
|
|
52
53
|
| Pending tool approval vanished after server restart | By design: parked SDK calls don't survive host restart; they resolve as interrupted. Re-run the turn. |
|
|
53
54
|
| Schedule / reminder never fires under `--dev` | Dev never auto-fires. `POST /<slug>/v1/dev/schedules/<id>` or `POST /<slug>/v1/dev/reminders/<id>` (list at `GET /v1/dev/reminders`). |
|
package/skills/evals/SKILL.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: agentsdk-framework-map
|
|
3
3
|
description: >-
|
|
4
4
|
Orientation for @cursor/july — folder structure, local vs cloud
|
|
5
5
|
runtimes, sessions, state layout, and invariants (Node not Bun, root
|
|
@@ -38,11 +38,11 @@ pnpm exec tsx src/bin/agent-serve.ts <cmd> ...
|
|
|
38
38
|
before shipping. Classic miss: a tool `execute` return that fails
|
|
39
39
|
`ToolExecuteResult` — returns must be JSON-shaped, so use object
|
|
40
40
|
literals or `type` aliases, not `interface` types.
|
|
41
|
-
4. **
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
the
|
|
45
|
-
|
|
41
|
+
4. **Harness cwd in a nested git repo.** Discovery defaults `local.cwd` to
|
|
42
|
+
`~/.cache/agent-serve/<dir>` so ancestor `AGENTS.md` / `.cursor` / IDE
|
|
43
|
+
MCP do not leak into playground turns. Set cwd at a checkout only when
|
|
44
|
+
the agent must inherit that tree. Attached MCP is invisible by name
|
|
45
|
+
until `advertiseTools: true`. `hostOnly` hides it from the model.
|
|
46
46
|
5. **A model turn needs `CURSOR_API_KEY`.** Everything structural
|
|
47
47
|
(`validate`, `info`, `call`, `serve` bring-up) works without one.
|
|
48
48
|
|
|
@@ -57,7 +57,7 @@ path live under README "Folder structure".
|
|
|
57
57
|
| `agent/instructions.md` | Always-on system prompt (required; `.ts`/dir forms exist) |
|
|
58
58
|
| `agent/tools/<name>.ts` | One typed tool; filename = tool name. `execution: "server"` (in-process, default) or `"agent"` (script that runs where the agent runs) |
|
|
59
59
|
| `agent/skills/*` | SKILL.md-convention procedures, loaded on demand |
|
|
60
|
-
| `agent/mcp-connections/<name>.ts` | MCP servers
|
|
60
|
+
| `agent/mcp-connections/<name>.ts` | MCP servers. Do not name an account connection `cursor.ts`. `advertiseTools: true` for named tools on local turns; `hostOnly` keeps them off the model. `{ tools }` authors TypeScript the Agent SDK packages as stdio MCP. |
|
|
61
61
|
| `agent/subagents/<id>/` | Child agent dir (`description` required; per-subagent tools/skills/MCP connections ignored for now) |
|
|
62
62
|
| `agent/channels/*.ts` | HTTP surfaces beyond the built-in session API; `slack.ts` / `github.ts` use the platform packs |
|
|
63
63
|
| `agent/hooks/*.ts` | Observe-only event subscribers (never fatal) |
|
package/skills/github/SKILL.md
CHANGED
package/skills/mcp-auth/SKILL.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: agentsdk-mcp-auth
|
|
3
3
|
description: >-
|
|
4
4
|
Authorize host MCP OAuth for defineConnection({ url, oauth: true }):
|
|
5
5
|
agent-sdk mcp oauth, local mcp-auth.json, --store deployment secrets,
|
|
6
|
-
hostOnly, and egress. Read when wiring or debugging MCP auth.
|
|
6
|
+
hostOnly, advertiseTools, and egress. Read when wiring or debugging MCP auth.
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Host MCP OAuth (mcp auth)
|
|
@@ -26,13 +26,15 @@ Docs: `docs/guides/mcp-oauth.md`, `docs/reference/connections.md`,
|
|
|
26
26
|
| Remote URL that speaks OAuth; host must hold tokens | `defineConnection({ url, oauth: true })` + this skill |
|
|
27
27
|
| Static bearer / API key | `headers` / env on a plain `{ url }` connection |
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
those tools.
|
|
29
|
+
Set `hostOnly: true` only when host tools / channel handlers should call
|
|
30
|
+
the server and the model should not (admin APIs, privileged writes).
|
|
31
|
+
Playground chat will not see those tools. For connectors the model should
|
|
32
|
+
call on local turns (Linear, Datadog, account MCP), omit `hostOnly` and
|
|
33
|
+
set `advertiseTools: true`.
|
|
32
34
|
|
|
33
35
|
## Goal checklist
|
|
34
36
|
|
|
35
|
-
- [ ] `agent/mcp-connections/<name>.ts` with `url` + `oauth: true` (
|
|
37
|
+
- [ ] `agent/mcp-connections/<name>.ts` with `url` + `oauth: true` (`hostOnly` if privileged; `advertiseTools` if the model should call it)
|
|
36
38
|
- [ ] `hosting.secretNames` lists `MCP_OAUTH_<NAME>_{ACCESS_TOKEN,REFRESH_TOKEN,CLIENT_ID}` when you will `--store`
|
|
37
39
|
- [ ] Hosted engines that reach non-bootstrap hosts declare `hosting.egressDomains`
|
|
38
40
|
- [ ] Local: `agent-sdk mcp oauth <name>` succeeds
|
|
@@ -127,7 +129,7 @@ redeploy completed, then exercise the same host tool once.
|
|
|
127
129
|
| `Unknown MCP connection` | Filename under `agent/mcp-connections/` must match CLI arg |
|
|
128
130
|
| Callback hang | Free port 8787; finish browser flow on this machine |
|
|
129
131
|
| Hosted 401 / unauthorized | `secrets list`; re-run `--store`; redeploy |
|
|
130
|
-
| Model invents `mcp_auth` / IDE MCP |
|
|
132
|
+
| Model invents `mcp_auth` / IDE MCP | `hostOnly` hid it, or attached MCP is behind meta-tools. Use host tools for privileged servers. Set `advertiseTools: true` for named tools on local turns. |
|
|
131
133
|
| Tokens ignored after URL edit | Expected; run `mcp oauth` again for the new resource URL |
|
|
132
134
|
|
|
133
135
|
## Don't
|
package/skills/otel/SKILL.md
CHANGED
package/src/bin/agent-serve.ts
CHANGED
|
@@ -216,11 +216,13 @@ Commands:
|
|
|
216
216
|
-> MCP). Review the project, then run \`validate\` / \`dev\`.
|
|
217
217
|
Warnings never fail the command.
|
|
218
218
|
install-skills
|
|
219
|
-
|
|
220
|
-
~/.cursor/skills/
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
219
|
+
Refresh the Agent SDK skills for coding agents in
|
|
220
|
+
~/.cursor/skills/agentsdk and print where they landed.
|
|
221
|
+
Installed copies set alwaysApply so Cursor injects them
|
|
222
|
+
into context. \`npm install\` / \`npx\` already copies them
|
|
223
|
+
(postinstall); this command overwrites with the package
|
|
224
|
+
version without asking. \`init\` also offers a TTY refresh.
|
|
225
|
+
--print previews without writing.
|
|
224
226
|
mcp Serve this agent's MCP endpoint over stdio for MCP clients
|
|
225
227
|
that spawn local servers (e.g. Cursor). Proxies
|
|
226
228
|
newline-delimited JSON-RPC to <target>/v1/mcp. --prod resolves
|
|
@@ -1260,7 +1262,8 @@ async function main(argv: string[]): Promise<number> {
|
|
|
1260
1262
|
values["cursor-events"] === true
|
|
1261
1263
|
? { repos: values.repo ?? [] }
|
|
1262
1264
|
: undefined,
|
|
1263
|
-
// Soft boot logs
|
|
1265
|
+
// Soft boot logs stay secondary to the banner. `dim` is a no-op on
|
|
1266
|
+
// already-styled lines (the MCP warning box).
|
|
1264
1267
|
logger: (line: string) => {
|
|
1265
1268
|
process.stdout.write(`${style.dim(line)}\n`);
|
|
1266
1269
|
},
|
|
@@ -1700,7 +1703,7 @@ installTransportErrorGuards();
|
|
|
1700
1703
|
|
|
1701
1704
|
// Authored agent files are TypeScript imported at runtime; install the tsx
|
|
1702
1705
|
// loader (and the framework import aliases on compiled runs) before any
|
|
1703
|
-
// command touches a project.
|
|
1706
|
+
// command touches a project. In-repo CLI is `bin/agentsdk`.
|
|
1704
1707
|
registerAuthoredModuleLoaders()
|
|
1705
1708
|
.then(() => main(process.argv.slice(2)))
|
|
1706
1709
|
.then(
|
|
@@ -535,7 +535,12 @@ function isOctokitRequestError(error: unknown): error is {
|
|
|
535
535
|
);
|
|
536
536
|
}
|
|
537
537
|
|
|
538
|
-
|
|
538
|
+
/** Normalize an Octokit request failure into {@link GitHubApiError}. */
|
|
539
|
+
export function wrapOctokitError(
|
|
540
|
+
error: unknown,
|
|
541
|
+
method: string,
|
|
542
|
+
path: string
|
|
543
|
+
): Error {
|
|
539
544
|
if (isOctokitRequestError(error)) {
|
|
540
545
|
return new GitHubApiError({
|
|
541
546
|
body: error.response?.data,
|
|
@@ -17,6 +17,11 @@ import {
|
|
|
17
17
|
type GitHubPostedComment,
|
|
18
18
|
type GitHubReactionContent,
|
|
19
19
|
} from "./api.js";
|
|
20
|
+
import {
|
|
21
|
+
createGitHubCheck,
|
|
22
|
+
type GitHubCheck,
|
|
23
|
+
type GitHubCheckCreateInput,
|
|
24
|
+
} from "./checks.js";
|
|
20
25
|
import type {
|
|
21
26
|
GitHubChannelCredentials,
|
|
22
27
|
GitHubConversationKind,
|
|
@@ -79,6 +84,14 @@ export interface GitHubHandle {
|
|
|
79
84
|
description?: string;
|
|
80
85
|
targetUrl?: string;
|
|
81
86
|
}): Promise<GitHubApiResponse>;
|
|
87
|
+
/**
|
|
88
|
+
* Open a CI check run (Checks API) on `sha` and get a handle for updating
|
|
89
|
+
* and concluding it. Needs `checks:write` — with `cursorAccount`, declare
|
|
90
|
+
* `githubChannel({ checks: true })` to opt the lease up.
|
|
91
|
+
*/
|
|
92
|
+
createCheck(
|
|
93
|
+
input: Omit<GitHubCheckCreateInput, "github" | "owner" | "repo">
|
|
94
|
+
): Promise<GitHubCheck>;
|
|
82
95
|
}
|
|
83
96
|
|
|
84
97
|
/** Thread-scoped operations for the current conversation (`ctx.thread`). */
|
|
@@ -149,6 +162,14 @@ export function buildGitHubBinding(input: {
|
|
|
149
162
|
: { targetUrl: status.targetUrl }),
|
|
150
163
|
});
|
|
151
164
|
},
|
|
165
|
+
createCheck(check) {
|
|
166
|
+
return createGitHubCheck({
|
|
167
|
+
...check,
|
|
168
|
+
github: { getOctokit },
|
|
169
|
+
owner: state.owner,
|
|
170
|
+
repo: state.repo,
|
|
171
|
+
});
|
|
172
|
+
},
|
|
152
173
|
};
|
|
153
174
|
|
|
154
175
|
const thread: GitHubThread = {
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic CI checks (GitHub Checks API) for agent authors.
|
|
3
|
+
*
|
|
4
|
+
* `createGitHubCheck` opens a merge-box check run on a commit and returns a
|
|
5
|
+
* handle for updating and concluding it, so an agent can report its own CI
|
|
6
|
+
* result (name, summary, and a "Details" link — e.g. the agent session run).
|
|
7
|
+
* Works with any client exposing `getOctokit()` (`ctx.github`,
|
|
8
|
+
* `ctx.host.github`), and is also reachable as `ctx.github.createCheck(...)`.
|
|
9
|
+
*
|
|
10
|
+
* Posting checks needs `checks:write`. With `cursorAccount`, declare
|
|
11
|
+
* `githubChannel({ checks: true })` so the hosted lease is minted on the
|
|
12
|
+
* `contents-write` tier; GitHub App / PAT credentials need the equivalent
|
|
13
|
+
* permission.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import type { Octokit } from "@octokit/rest";
|
|
17
|
+
import {
|
|
18
|
+
type GitHubCheckRunConclusion,
|
|
19
|
+
type GitHubCheckRunStatus,
|
|
20
|
+
wrapOctokitError,
|
|
21
|
+
} from "./api.js";
|
|
22
|
+
|
|
23
|
+
/** Any client that can hand out an authenticated Octokit. */
|
|
24
|
+
export interface GitHubCheckClient {
|
|
25
|
+
getOctokit(): Promise<Octokit>;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Output shown on the check page (both fields required by GitHub). */
|
|
29
|
+
export interface GitHubCheckOutput {
|
|
30
|
+
/** Heading on the check page. */
|
|
31
|
+
title: string;
|
|
32
|
+
/** Markdown body (supports links, e.g. `[View session](…)`). */
|
|
33
|
+
summary: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface GitHubCheckCreateInput {
|
|
37
|
+
/** Client used for every API call on the returned handle. */
|
|
38
|
+
github: GitHubCheckClient;
|
|
39
|
+
/** Repository owner login, e.g. `"acme"`. */
|
|
40
|
+
owner: string;
|
|
41
|
+
/** Repository name, e.g. `"widgets"`. */
|
|
42
|
+
repo: string;
|
|
43
|
+
/** Check name shown in the PR merge box, e.g. `"Cursor Security Review"`. */
|
|
44
|
+
name: string;
|
|
45
|
+
/** Commit the check attaches to (usually the PR head SHA). */
|
|
46
|
+
sha: string;
|
|
47
|
+
/** Initial status. Defaults to `"in_progress"`. */
|
|
48
|
+
status?: "queued" | "in_progress";
|
|
49
|
+
/** "Details" link on the check, e.g. the agent session run URL. */
|
|
50
|
+
detailsUrl?: string;
|
|
51
|
+
/** Title + markdown summary shown on the check page. */
|
|
52
|
+
output?: GitHubCheckOutput;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface GitHubCheckUpdateInput {
|
|
56
|
+
status?: GitHubCheckRunStatus;
|
|
57
|
+
conclusion?: GitHubCheckRunConclusion;
|
|
58
|
+
detailsUrl?: string;
|
|
59
|
+
output?: GitHubCheckOutput;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface GitHubCheckConcludeInput {
|
|
63
|
+
/** Final result shown in the merge box. */
|
|
64
|
+
conclusion: GitHubCheckRunConclusion;
|
|
65
|
+
detailsUrl?: string;
|
|
66
|
+
output?: GitHubCheckOutput;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** A created check run. All methods throw `GitHubApiError` on API failure. */
|
|
70
|
+
export interface GitHubCheck {
|
|
71
|
+
/** Check run id (for reuse across process restarts). */
|
|
72
|
+
readonly id: number;
|
|
73
|
+
/** GitHub web URL of the check run page, when returned by the API. */
|
|
74
|
+
readonly url: string | undefined;
|
|
75
|
+
/** Patch status / output / details link while the check is running. */
|
|
76
|
+
update(input: GitHubCheckUpdateInput): Promise<void>;
|
|
77
|
+
/** Complete the check with a conclusion (sets `completed_at`). */
|
|
78
|
+
conclude(input: GitHubCheckConcludeInput): Promise<void>;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Create a CI check run on a commit and return a handle for later updates.
|
|
83
|
+
*
|
|
84
|
+
* ```ts
|
|
85
|
+
* const check = await createGitHubCheck({
|
|
86
|
+
* github: ctx.github,
|
|
87
|
+
* owner: ctx.repository.owner,
|
|
88
|
+
* repo: ctx.repository.name,
|
|
89
|
+
* name: "Cursor Security Review",
|
|
90
|
+
* sha: pr.headSha,
|
|
91
|
+
* detailsUrl: sessionUrl,
|
|
92
|
+
* output: { title: "Running…", summary: `[View session](${sessionUrl})` },
|
|
93
|
+
* });
|
|
94
|
+
* // …do the work…
|
|
95
|
+
* await check.conclude({ conclusion: "success", output: { … } });
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
export async function createGitHubCheck(
|
|
99
|
+
input: GitHubCheckCreateInput
|
|
100
|
+
): Promise<GitHubCheck> {
|
|
101
|
+
const octokit = await input.github.getOctokit();
|
|
102
|
+
let created: { id: number; html_url?: string | null };
|
|
103
|
+
try {
|
|
104
|
+
const response = await octokit.rest.checks.create({
|
|
105
|
+
owner: input.owner,
|
|
106
|
+
repo: input.repo,
|
|
107
|
+
name: input.name,
|
|
108
|
+
head_sha: input.sha,
|
|
109
|
+
status: input.status ?? "in_progress",
|
|
110
|
+
started_at: new Date().toISOString(),
|
|
111
|
+
details_url: input.detailsUrl,
|
|
112
|
+
output: input.output,
|
|
113
|
+
});
|
|
114
|
+
created = response.data;
|
|
115
|
+
} catch (error) {
|
|
116
|
+
throw wrapOctokitError(
|
|
117
|
+
error,
|
|
118
|
+
"POST",
|
|
119
|
+
`/repos/${input.owner}/${input.repo}/check-runs`
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
return resumeGitHubCheck({
|
|
123
|
+
github: input.github,
|
|
124
|
+
owner: input.owner,
|
|
125
|
+
repo: input.repo,
|
|
126
|
+
name: input.name,
|
|
127
|
+
checkRunId: created.id,
|
|
128
|
+
url: typeof created.html_url === "string" ? created.html_url : undefined,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Rebuild a {@link GitHubCheck} handle for an existing check run id (e.g.
|
|
134
|
+
* after a process restart). No API call is made until the first update.
|
|
135
|
+
*/
|
|
136
|
+
export function resumeGitHubCheck(input: {
|
|
137
|
+
github: GitHubCheckClient;
|
|
138
|
+
owner: string;
|
|
139
|
+
repo: string;
|
|
140
|
+
name: string;
|
|
141
|
+
checkRunId: number;
|
|
142
|
+
url?: string;
|
|
143
|
+
}): GitHubCheck {
|
|
144
|
+
const patch = async (update: GitHubCheckUpdateInput): Promise<void> => {
|
|
145
|
+
const octokit = await input.github.getOctokit();
|
|
146
|
+
try {
|
|
147
|
+
await octokit.rest.checks.update({
|
|
148
|
+
owner: input.owner,
|
|
149
|
+
repo: input.repo,
|
|
150
|
+
check_run_id: input.checkRunId,
|
|
151
|
+
name: input.name,
|
|
152
|
+
status: update.status,
|
|
153
|
+
conclusion: update.conclusion,
|
|
154
|
+
completed_at:
|
|
155
|
+
update.status === "completed" ? new Date().toISOString() : undefined,
|
|
156
|
+
details_url: update.detailsUrl,
|
|
157
|
+
output: update.output,
|
|
158
|
+
});
|
|
159
|
+
} catch (error) {
|
|
160
|
+
throw wrapOctokitError(
|
|
161
|
+
error,
|
|
162
|
+
"PATCH",
|
|
163
|
+
`/repos/${input.owner}/${input.repo}/check-runs/${input.checkRunId}`
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
return {
|
|
168
|
+
id: input.checkRunId,
|
|
169
|
+
url: input.url,
|
|
170
|
+
update: patch,
|
|
171
|
+
conclude: (conclude) =>
|
|
172
|
+
patch({
|
|
173
|
+
status: "completed",
|
|
174
|
+
conclusion: conclude.conclusion,
|
|
175
|
+
detailsUrl: conclude.detailsUrl,
|
|
176
|
+
output: conclude.output,
|
|
177
|
+
}),
|
|
178
|
+
};
|
|
179
|
+
}
|