@cursor/july 0.1.54 → 0.1.61
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/dist/bin/agent-serve.js +30 -23
- package/dist/channels/github/github-channel.d.ts +12 -0
- package/dist/channels/github/github-channel.d.ts.map +1 -1
- package/dist/channels/github/github-channel.js +67 -15
- package/dist/channels/github/types.d.ts +27 -1
- package/dist/channels/github/types.d.ts.map +1 -1
- package/dist/channels/origin/cursor-account.d.ts +22 -0
- package/dist/channels/origin/cursor-account.d.ts.map +1 -0
- package/dist/channels/origin/cursor-account.js +35 -0
- package/dist/channels/origin/events.d.ts +10 -0
- package/dist/channels/origin/events.d.ts.map +1 -0
- package/dist/channels/origin/events.js +27 -0
- package/dist/channels/origin/index.d.ts +29 -0
- package/dist/channels/origin/index.d.ts.map +1 -0
- package/dist/channels/origin/index.js +28 -0
- package/dist/channels/origin/origin-channel.d.ts +68 -0
- package/dist/channels/origin/origin-channel.d.ts.map +1 -0
- package/dist/channels/origin/origin-channel.js +567 -0
- package/dist/channels/origin/origin-webhook.d.ts +38 -0
- package/dist/channels/origin/origin-webhook.d.ts.map +1 -0
- package/dist/channels/origin/origin-webhook.js +151 -0
- package/dist/channels/origin/types.d.ts +152 -0
- package/dist/channels/origin/types.d.ts.map +1 -0
- package/dist/channels/origin/types.js +1 -0
- package/dist/channels/slack/doctor.d.ts +17 -1
- package/dist/channels/slack/doctor.d.ts.map +1 -1
- package/dist/channels/slack/doctor.js +186 -10
- package/dist/docs/404.html +2 -2
- package/dist/docs/ab.html +4 -4
- package/dist/docs/assets/{app.DAKcDclS.js → app.CW3KJh72.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.BuymfBAo.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.BNIaCSfG.js → VPLocalSearchBox.Bk6EWpPj.js} +1 -1
- package/dist/docs/assets/chunks/{theme.B47GzJjc.js → theme.Bz9AodBA.js} +2 -2
- package/dist/docs/assets/{example-agents_fsd.md.DPz9ezO4.js → example-agents_fsd.md.ZeGEpAw_.js} +2 -2
- package/dist/docs/assets/{example-agents_fsd.md.DPz9ezO4.lean.js → example-agents_fsd.md.ZeGEpAw_.lean.js} +1 -1
- package/dist/docs/assets/{example-agents_security-reviewer.md.Dkf1gyo6.js → example-agents_security-reviewer.md.DBL1TwtP.js} +2 -2
- package/dist/docs/assets/{example-agents_security-reviewer.md.Dkf1gyo6.lean.js → example-agents_security-reviewer.md.DBL1TwtP.lean.js} +1 -1
- package/dist/docs/assets/guides_convert-automation.md.BhMzTkE5.js +12 -0
- package/dist/docs/assets/guides_convert-automation.md.BhMzTkE5.lean.js +1 -0
- package/dist/docs/assets/{guides_github.md.B8QKtIpw.js → guides_github.md.CLLQJKRB.js} +4 -4
- package/dist/docs/assets/{guides_github.md.B8QKtIpw.lean.js → guides_github.md.CLLQJKRB.lean.js} +1 -1
- package/dist/docs/assets/index.md.DhRHS_-L.js +5 -0
- package/dist/docs/assets/{index.md.COeoSkcF.lean.js → index.md.DhRHS_-L.lean.js} +1 -1
- package/dist/docs/assets/{reference_cli.md.-V6J7Cl8.js → reference_cli.md.Cl14Jfo3.js} +10 -2
- package/dist/docs/assets/{reference_cli.md.-V6J7Cl8.lean.js → reference_cli.md.Cl14Jfo3.lean.js} +1 -1
- package/dist/docs/assets/scaffolding-agents.md.CrWSA0Ko.js +1 -0
- package/dist/docs/assets/{scaffolding-agents.md.mkc3B_ZW.lean.js → scaffolding-agents.md.CrWSA0Ko.lean.js} +1 -1
- package/dist/docs/assets/templates_agentic-owners.md.BkTLORaU.js +14 -0
- package/dist/docs/assets/templates_agentic-owners.md.BkTLORaU.lean.js +1 -0
- package/dist/docs/assets/templates_demo.md.Bgd6MBaZ.js +4 -0
- package/dist/docs/assets/templates_demo.md.Bgd6MBaZ.lean.js +1 -0
- package/dist/docs/assets/templates_pr-autofixer.md.DcmoeUNZ.js +8 -0
- package/dist/docs/assets/templates_pr-autofixer.md.DcmoeUNZ.lean.js +1 -0
- package/dist/docs/assets/templates_security-reviewer.md.C0yIUaYs.js +2 -0
- package/dist/docs/assets/templates_security-reviewer.md.C0yIUaYs.lean.js +1 -0
- package/dist/docs/assets/templates_triage.md.DWuQ1bZz.js +9 -0
- package/dist/docs/assets/templates_triage.md.DWuQ1bZz.lean.js +1 -0
- package/dist/docs/building-with-agents.html +4 -4
- package/dist/docs/concepts.html +5 -5
- package/dist/docs/deployment.html +4 -4
- package/dist/docs/evals.html +4 -4
- package/dist/docs/example-agents/approval-buddy.html +4 -4
- package/dist/docs/example-agents/benny.html +4 -4
- package/dist/docs/example-agents/bugbot.html +4 -4
- package/dist/docs/example-agents/codebase-wiki.html +4 -4
- package/dist/docs/example-agents/codeowners-review.html +4 -4
- package/dist/docs/example-agents/concierge.html +4 -4
- package/dist/docs/example-agents/fsd.html +5 -5
- package/dist/docs/example-agents/index.html +4 -4
- package/dist/docs/example-agents/knowledge-base.html +4 -4
- package/dist/docs/example-agents/oncall.html +4 -4
- package/dist/docs/example-agents/security-reviewer.html +5 -5
- package/dist/docs/example-agents/slack-agent.html +4 -4
- package/dist/docs/example-agents/weather-agent.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 +36 -0
- package/dist/docs/guides/github.html +7 -7
- package/dist/docs/guides/human-in-the-loop.html +4 -4
- package/dist/docs/guides/mcp-oauth.html +4 -4
- package/dist/docs/guides/opentelemetry.html +4 -4
- package/dist/docs/guides/slack.html +4 -4
- 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/quickstart.html +4 -4
- package/dist/docs/reference/agent-config.html +4 -4
- package/dist/docs/reference/artifacts.html +4 -4
- package/dist/docs/reference/channels.html +4 -4
- package/dist/docs/reference/cli.html +14 -6
- package/dist/docs/reference/connections.html +4 -4
- package/dist/docs/reference/hooks.html +4 -4
- package/dist/docs/reference/http-api.html +4 -4
- 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 +4 -4
- package/dist/docs/reference/skills.html +4 -4
- package/dist/docs/reference/subagents.html +4 -4
- package/dist/docs/reference/tools.html +4 -4
- package/dist/docs/scaffolding-agents.html +5 -5
- package/dist/docs/storage.html +4 -4
- package/dist/docs/templates/agentic-owners.html +38 -0
- package/dist/docs/templates/demo.html +28 -0
- package/dist/docs/templates/pr-autofixer.html +32 -0
- package/dist/docs/templates/security-reviewer.html +26 -0
- package/dist/docs/templates/triage.html +14 -16
- package/dist/docs/troubleshooting.html +4 -4
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/internal/cli-ax.d.ts +2 -0
- package/dist/internal/cli-ax.d.ts.map +1 -1
- package/dist/internal/cli-ax.js +30 -1
- package/dist/internal/cli-deploy.js +1 -1
- package/dist/internal/cli-slack.d.ts +4 -0
- package/dist/internal/cli-slack.d.ts.map +1 -1
- package/dist/internal/cli-slack.js +46 -20
- package/dist/internal/cursor-event-relay.d.ts +59 -11
- package/dist/internal/cursor-event-relay.d.ts.map +1 -1
- package/dist/internal/cursor-event-relay.js +133 -26
- package/dist/internal/discovery.d.ts.map +1 -1
- package/dist/internal/discovery.js +11 -2
- package/dist/internal/distribution.d.ts.map +1 -1
- package/dist/internal/distribution.js +1 -0
- package/dist/internal/handleAgentServeTrigger.d.ts +33 -6
- package/dist/internal/handleAgentServeTrigger.d.ts.map +1 -1
- package/dist/internal/handleAgentServeTrigger.js +97 -19
- package/dist/internal/init-interview.d.ts +67 -0
- package/dist/internal/init-interview.d.ts.map +1 -0
- package/dist/internal/init-interview.js +300 -0
- package/dist/internal/init-project.d.ts +7 -0
- package/dist/internal/init-project.d.ts.map +1 -1
- package/dist/internal/init-project.js +99 -43
- package/dist/internal/mcp-endpoint.d.ts +7 -0
- package/dist/internal/mcp-endpoint.d.ts.map +1 -1
- package/dist/internal/mcp-endpoint.js +7 -0
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +159 -57
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +20 -21
- package/dist/internal/session-links.d.ts +14 -0
- package/dist/internal/session-links.d.ts.map +1 -0
- package/dist/internal/session-links.js +69 -0
- package/dist/internal/sessions-client.d.ts.map +1 -1
- package/dist/internal/sessions-client.js +1 -0
- package/dist/internal/slack-provision-client.js +1 -1
- package/dist/playground/assets/index-ClbuaLpm.css +1 -0
- package/dist/playground/assets/index-SqkR13k_.js +85 -0
- package/dist/playground/index.html +2 -2
- package/dist/types.d.ts +19 -12
- package/dist/types.d.ts.map +1 -1
- package/docs/README.md +15 -0
- package/docs/example-agents/fsd.md +3 -0
- package/docs/example-agents/security-reviewer.md +3 -0
- package/docs/guides/convert-automation.md +176 -0
- package/docs/guides/github.md +6 -2
- package/docs/reference/cli.md +36 -10
- package/docs/scaffolding-agents.md +3 -0
- package/docs/templates/agentic-owners.md +97 -0
- package/docs/templates/demo.md +84 -0
- package/docs/templates/pr-autofixer.md +136 -0
- package/docs/templates/security-reviewer.md +89 -0
- package/docs/templates/triage.md +59 -101
- package/package.json +9 -1
- package/skills/github/SKILL.md +4 -5
- package/src/bin/agent-serve.ts +13 -6
- package/src/channels/github/github-channel.ts +95 -18
- package/src/channels/github/types.ts +31 -0
- package/src/channels/origin/cursor-account.ts +64 -0
- package/src/channels/origin/events.ts +41 -0
- package/src/channels/origin/index.ts +29 -0
- package/src/channels/origin/origin-channel.ts +784 -0
- package/src/channels/origin/origin-webhook.ts +202 -0
- package/src/channels/origin/types.ts +186 -0
- package/src/channels/slack/doctor.ts +218 -5
- package/src/index.ts +3 -1
- package/src/internal/cli-ax.ts +33 -1
- package/src/internal/cli-deploy.ts +2 -2
- package/src/internal/cli-slack.ts +68 -19
- package/src/internal/cursor-event-relay.ts +193 -31
- package/src/internal/discovery.ts +15 -5
- package/src/internal/distribution.ts +1 -0
- package/src/internal/handleAgentServeTrigger.ts +129 -19
- package/src/internal/init-interview.ts +384 -0
- package/src/internal/init-project.ts +146 -46
- package/src/internal/mcp-endpoint.ts +7 -0
- package/src/internal/server.ts +188 -58
- package/src/internal/session-engine.ts +5 -21
- package/src/internal/session-links.ts +88 -0
- package/src/internal/sessions-client.ts +1 -0
- package/src/internal/slack-provision-client.ts +1 -1
- package/src/types.ts +19 -12
- package/templates/agentic-owners/README.md +73 -0
- package/templates/agentic-owners/agent/agent.ts +15 -0
- package/templates/agentic-owners/agent/channels/github.ts +85 -0
- package/templates/agentic-owners/agent/instructions.md +34 -0
- package/templates/agentic-owners/agent/lib/config.ts +13 -0
- package/templates/agentic-owners/agent/lib/github.ts +241 -0
- package/templates/agentic-owners/agent/lib/owners/README.md +50 -0
- package/templates/agentic-owners/agent/lib/owners/constants.ts +22 -0
- package/templates/agentic-owners/agent/lib/owners/decision.ts +485 -0
- package/templates/agentic-owners/agent/lib/owners/handles.ts +54 -0
- package/templates/agentic-owners/agent/lib/owners/match.ts +177 -0
- package/templates/agentic-owners/agent/lib/owners/matching.ts +95 -0
- package/templates/agentic-owners/agent/lib/owners/parse.ts +589 -0
- package/templates/agentic-owners/agent/lib/owners/policyMode.ts +65 -0
- package/templates/agentic-owners/agent/lib/owners/prompt.ts +66 -0
- package/templates/agentic-owners/agent/lib/owners/prompts/base-review.md +105 -0
- package/templates/agentic-owners/agent/lib/owners/types.ts +45 -0
- package/templates/agentic-owners/agent/lib/review.ts +777 -0
- package/templates/agentic-owners/agent/tools/record_review.ts +69 -0
- package/templates/agentic-owners/evals/evals.config.ts +5 -0
- package/templates/agentic-owners/evals/owners.eval.ts +116 -0
- package/templates/agentic-owners/package.json +20 -0
- package/templates/agentic-owners/tsconfig.json +12 -0
- package/templates/demo/README.md +33 -0
- package/templates/demo/agent/agent.ts +15 -0
- package/templates/demo/agent/channels/github.ts +50 -0
- package/templates/demo/agent/channels/queue.ts +30 -0
- package/templates/demo/agent/instructions.md +8 -0
- package/templates/demo/agent/lib/collect.ts +78 -0
- package/templates/demo/agent/tools/record_demo.ts +40 -0
- package/templates/demo/evals/demo.eval.ts +33 -0
- package/templates/demo/evals/evals.config.ts +5 -0
- package/templates/demo/package.json +18 -0
- package/templates/demo/tsconfig.json +12 -0
- package/templates/pr-autofixer/README.md +44 -0
- package/templates/pr-autofixer/agent/agent.ts +22 -0
- package/templates/pr-autofixer/agent/channels/drive.ts +40 -0
- package/templates/pr-autofixer/agent/channels/github.ts +167 -0
- package/templates/pr-autofixer/agent/channels/slack.ts +17 -0
- package/templates/pr-autofixer/agent/hooks/bind-agent.ts +19 -0
- package/templates/pr-autofixer/agent/instructions.md +83 -0
- package/templates/pr-autofixer/agent/lib/affinity.ts +33 -0
- package/templates/pr-autofixer/agent/lib/drive-schemas.ts +15 -0
- package/templates/pr-autofixer/agent/lib/drive.ts +79 -0
- package/templates/pr-autofixer/agent/lib/merge-watch.ts +123 -0
- package/templates/pr-autofixer/agent/lib/pr-state.ts +54 -0
- package/templates/pr-autofixer/agent/lib/repos.ts +19 -0
- package/templates/pr-autofixer/agent/lib/start-drive.ts +122 -0
- package/templates/pr-autofixer/agent/lib/webhook-buffer.ts +225 -0
- package/templates/pr-autofixer/agent/lib/webhook-routing.ts +231 -0
- package/templates/pr-autofixer/agent/storage.ts +7 -0
- package/templates/pr-autofixer/agent/tools/drive_pr.ts +22 -0
- package/templates/pr-autofixer/evals/coordinator.eval.ts +16 -0
- package/templates/pr-autofixer/evals/evals.config.ts +5 -0
- package/templates/pr-autofixer/init.json +25 -0
- package/templates/pr-autofixer/package.json +18 -0
- package/templates/pr-autofixer/tsconfig.json +12 -0
- package/templates/security-reviewer/README.md +31 -0
- package/templates/security-reviewer/agent/agent.ts +15 -0
- package/templates/security-reviewer/agent/channels/github.ts +46 -0
- package/templates/security-reviewer/agent/instructions.md +22 -0
- package/templates/security-reviewer/agent/lib/repos.ts +5 -0
- package/templates/security-reviewer/agent/tools/post_findings.ts +72 -0
- package/templates/security-reviewer/evals/evals.config.ts +5 -0
- package/templates/security-reviewer/evals/review.eval.ts +53 -0
- package/templates/security-reviewer/init.json +25 -0
- package/templates/security-reviewer/package.json +18 -0
- package/templates/security-reviewer/tsconfig.json +12 -0
- package/templates/triage/README.md +27 -29
- package/templates/triage/agent/agent.ts +1 -0
- package/templates/triage/agent/channels/queue.ts +47 -0
- package/templates/triage/agent/channels/webhook.ts +50 -0
- package/templates/triage/agent/instructions.md +24 -13
- package/templates/triage/agent/lib/actuate.ts +759 -0
- package/templates/triage/agent/lib/parse-queue-event.ts +168 -0
- package/templates/triage/agent/lib/tracker.ts +5 -0
- package/templates/triage/agent/lib/types.ts +52 -0
- package/templates/triage/agent/lib/verify-webhook.ts +81 -0
- package/templates/triage/agent/skills/triage-rubric.md +6 -5
- package/templates/triage/agent/tools/record_triage.ts +24 -5
- package/templates/triage/evals/triage.eval.ts +25 -3
- package/templates/triage/overlays/jira/README.md +21 -0
- package/templates/triage/overlays/jira/agent/lib/tracker.ts +8 -0
- package/templates/triage/overlays/jira/agent/mcp-connections/tracker.ts +7 -0
- package/templates/triage/overlays/linear/README.md +21 -0
- package/templates/triage/overlays/linear/agent/lib/tracker.ts +8 -0
- package/templates/triage/overlays/linear/agent/mcp-connections/tracker.ts +7 -0
- package/templates/triage/package.json +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.C4uxzYEU.js +0 -1
- package/dist/docs/assets/index.md.COeoSkcF.js +0 -5
- package/dist/docs/assets/scaffolding-agents.md.mkc3B_ZW.js +0 -1
- package/dist/docs/assets/templates_triage.md.CConZt1z.js +0 -11
- package/dist/docs/assets/templates_triage.md.CConZt1z.lean.js +0 -1
- package/dist/playground/assets/index-BHAPd9KT.js +0 -85
- package/dist/playground/assets/index-DpKH0HcT.css +0 -1
- package/templates/triage/agent/channels/intake.ts +0 -20
- package/templates/triage/agent/channels/slack.ts +0 -3
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { spawn } from "node:child_process";
|
|
6
|
-
import { existsSync,
|
|
6
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
7
7
|
import { mkdir, readdir, readFile, writeFile } from "node:fs/promises";
|
|
8
8
|
import { basename, dirname, join, relative, resolve } from "node:path";
|
|
9
9
|
import type { ModelSetting } from "../types.js";
|
|
@@ -13,6 +13,14 @@ import {
|
|
|
13
13
|
packageRootDir,
|
|
14
14
|
packageVersion,
|
|
15
15
|
} from "./distribution.js";
|
|
16
|
+
import {
|
|
17
|
+
applyInitReplacements,
|
|
18
|
+
isTemplateMetaPath,
|
|
19
|
+
loadTemplateInitSpec,
|
|
20
|
+
posixRel,
|
|
21
|
+
type TemplateInitSpec,
|
|
22
|
+
templateFileHasReplacements,
|
|
23
|
+
} from "./init-interview.js";
|
|
16
24
|
import {
|
|
17
25
|
makePalette,
|
|
18
26
|
stdoutPalette,
|
|
@@ -27,6 +35,11 @@ export interface InitProjectOptions {
|
|
|
27
35
|
/** Model id override written into agent.ts. */
|
|
28
36
|
model?: string;
|
|
29
37
|
templateDir?: string;
|
|
38
|
+
overlayDir?: string;
|
|
39
|
+
templateName?: string;
|
|
40
|
+
/** Answers collected from `init.json` / `--var`. */
|
|
41
|
+
answers?: Record<string, string>;
|
|
42
|
+
initSpec?: TemplateInitSpec;
|
|
30
43
|
}
|
|
31
44
|
|
|
32
45
|
export type InitFileAction = "create" | "exist";
|
|
@@ -46,23 +59,30 @@ export interface InitProjectResult {
|
|
|
46
59
|
skipped: string[];
|
|
47
60
|
}
|
|
48
61
|
|
|
62
|
+
type TemplateEntry = {
|
|
63
|
+
dir: string;
|
|
64
|
+
overlay?: string;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const TEMPLATES: Readonly<Record<string, TemplateEntry>> = {
|
|
68
|
+
"agentic-owners": { dir: "agentic-owners" },
|
|
69
|
+
demo: { dir: "demo" },
|
|
70
|
+
"pr-autofixer": { dir: "pr-autofixer" },
|
|
71
|
+
"security-reviewer": { dir: "security-reviewer" },
|
|
72
|
+
"triage-linear": { dir: "triage", overlay: "linear" },
|
|
73
|
+
"triage-jira": { dir: "triage", overlay: "jira" },
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
function canonicalTemplateName(name: string): string {
|
|
77
|
+
return name === "triage" ? "triage-linear" : name;
|
|
78
|
+
}
|
|
79
|
+
|
|
49
80
|
export function availableTemplates(): string[] {
|
|
50
|
-
|
|
51
|
-
try {
|
|
52
|
-
return readdirSync(templatesDir, { withFileTypes: true })
|
|
53
|
-
.filter((entry) => entry.isDirectory())
|
|
54
|
-
.map((entry) => entry.name)
|
|
55
|
-
.sort();
|
|
56
|
-
} catch (error) {
|
|
57
|
-
if (hasErrorCode(error, "ENOENT")) {
|
|
58
|
-
return [];
|
|
59
|
-
}
|
|
60
|
-
throw error;
|
|
61
|
-
}
|
|
81
|
+
return Object.keys(TEMPLATES).sort();
|
|
62
82
|
}
|
|
63
83
|
|
|
64
84
|
export type TemplateResolution =
|
|
65
|
-
| { ok: true; name: string; dir: string }
|
|
85
|
+
| { ok: true; name: string; dir: string; overlayDir?: string }
|
|
66
86
|
| { ok: false; message: string };
|
|
67
87
|
|
|
68
88
|
export function resolveTemplate(name: string): TemplateResolution {
|
|
@@ -72,21 +92,23 @@ export function resolveTemplate(name: string): TemplateResolution {
|
|
|
72
92
|
message: "template name must match /^[a-z][a-z0-9-]*$/",
|
|
73
93
|
};
|
|
74
94
|
}
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
available.length === 0
|
|
79
|
-
? "no templates ship with this build"
|
|
80
|
-
: `available: ${available.join(", ")}`;
|
|
95
|
+
const resolved = canonicalTemplateName(name);
|
|
96
|
+
const entry = TEMPLATES[resolved];
|
|
97
|
+
if (entry === undefined) {
|
|
81
98
|
return {
|
|
82
99
|
ok: false,
|
|
83
|
-
message: `unknown template "${name}" (${
|
|
100
|
+
message: `unknown template "${name}" (available: ${availableTemplates().join(", ")})`,
|
|
84
101
|
};
|
|
85
102
|
}
|
|
103
|
+
const dir = join(packageRootDir(), "templates", entry.dir);
|
|
86
104
|
return {
|
|
87
105
|
ok: true,
|
|
88
|
-
name,
|
|
89
|
-
dir
|
|
106
|
+
name: resolved,
|
|
107
|
+
dir,
|
|
108
|
+
overlayDir:
|
|
109
|
+
entry.overlay === undefined
|
|
110
|
+
? undefined
|
|
111
|
+
: join(dir, "overlays", entry.overlay),
|
|
90
112
|
};
|
|
91
113
|
}
|
|
92
114
|
|
|
@@ -121,6 +143,13 @@ export function checkInitTarget(
|
|
|
121
143
|
if (marker === template) {
|
|
122
144
|
return { ok: true };
|
|
123
145
|
}
|
|
146
|
+
if (
|
|
147
|
+
marker !== undefined &&
|
|
148
|
+
template !== undefined &&
|
|
149
|
+
canonicalTemplateName(marker) === canonicalTemplateName(template)
|
|
150
|
+
) {
|
|
151
|
+
return { ok: true };
|
|
152
|
+
}
|
|
124
153
|
if (template === undefined) {
|
|
125
154
|
return {
|
|
126
155
|
ok: false,
|
|
@@ -194,28 +223,38 @@ export async function initProject(
|
|
|
194
223
|
|
|
195
224
|
if (options.templateDir !== undefined) {
|
|
196
225
|
const templateDir = options.templateDir;
|
|
197
|
-
const
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
226
|
+
const overlayDir = options.overlayDir;
|
|
227
|
+
const overlayPaths = overlayDir ? await listTemplateFiles(overlayDir) : [];
|
|
228
|
+
const overlaySet = new Set(overlayPaths);
|
|
229
|
+
const corePaths = (await listTemplateFiles(templateDir)).filter(
|
|
230
|
+
(rel) => !overlaySet.has(rel)
|
|
231
|
+
);
|
|
232
|
+
const templateName = options.templateName ?? basename(templateDir);
|
|
233
|
+
const initSpec =
|
|
234
|
+
options.initSpec ?? (await loadTemplateInitSpec(templateDir));
|
|
235
|
+
const answers = options.answers ?? {};
|
|
236
|
+
for (const rel of corePaths) {
|
|
237
|
+
await writeTemplateFile({
|
|
238
|
+
write,
|
|
239
|
+
sourceDir: templateDir,
|
|
240
|
+
rel,
|
|
241
|
+
projectName,
|
|
242
|
+
templateName,
|
|
243
|
+
initSpec,
|
|
244
|
+
answers,
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
if (overlayDir !== undefined) {
|
|
248
|
+
for (const rel of overlayPaths) {
|
|
249
|
+
await writeTemplateFile({
|
|
250
|
+
write,
|
|
251
|
+
sourceDir: overlayDir,
|
|
252
|
+
rel,
|
|
253
|
+
projectName,
|
|
254
|
+
templateName,
|
|
255
|
+
initSpec,
|
|
256
|
+
answers,
|
|
257
|
+
});
|
|
219
258
|
}
|
|
220
259
|
}
|
|
221
260
|
return {
|
|
@@ -346,6 +385,60 @@ export default memoryHook();
|
|
|
346
385
|
};
|
|
347
386
|
}
|
|
348
387
|
|
|
388
|
+
async function listTemplateFiles(root: string): Promise<string[]> {
|
|
389
|
+
const entries = await readdir(root, {
|
|
390
|
+
recursive: true,
|
|
391
|
+
withFileTypes: true,
|
|
392
|
+
});
|
|
393
|
+
return entries
|
|
394
|
+
.filter((entry) => entry.isFile())
|
|
395
|
+
.map((entry) =>
|
|
396
|
+
posixRel(relative(root, join(entry.parentPath, entry.name)))
|
|
397
|
+
)
|
|
398
|
+
.filter((rel) => !isTemplateMetaPath(rel))
|
|
399
|
+
.sort();
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
async function writeTemplateFile(input: {
|
|
403
|
+
write: (rel: string, contents: string | Uint8Array) => Promise<void>;
|
|
404
|
+
sourceDir: string;
|
|
405
|
+
rel: string;
|
|
406
|
+
projectName: string;
|
|
407
|
+
templateName: string;
|
|
408
|
+
initSpec?: TemplateInitSpec;
|
|
409
|
+
answers: Record<string, string>;
|
|
410
|
+
}): Promise<void> {
|
|
411
|
+
const source = join(input.sourceDir, input.rel);
|
|
412
|
+
if (input.rel === "package.json") {
|
|
413
|
+
const packageJson: {
|
|
414
|
+
name: string;
|
|
415
|
+
dependencies: Record<string, string>;
|
|
416
|
+
[key: string]: unknown;
|
|
417
|
+
} = JSON.parse(await readFile(source, "utf8"));
|
|
418
|
+
packageJson.name = input.projectName;
|
|
419
|
+
packageJson.dependencies[PACKAGE_NAME] = `^${packageVersion()}`;
|
|
420
|
+
packageJson.cursorAgentTemplate = input.templateName;
|
|
421
|
+
await input.write(input.rel, `${JSON.stringify(packageJson, null, 2)}\n`);
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
if (
|
|
425
|
+
input.initSpec !== undefined &&
|
|
426
|
+
templateFileHasReplacements(input.initSpec, input.rel)
|
|
427
|
+
) {
|
|
428
|
+
await input.write(
|
|
429
|
+
input.rel,
|
|
430
|
+
applyInitReplacements(
|
|
431
|
+
await readFile(source, "utf8"),
|
|
432
|
+
input.rel,
|
|
433
|
+
input.initSpec,
|
|
434
|
+
input.answers
|
|
435
|
+
)
|
|
436
|
+
);
|
|
437
|
+
return;
|
|
438
|
+
}
|
|
439
|
+
await input.write(input.rel, await readFile(source));
|
|
440
|
+
}
|
|
441
|
+
|
|
349
442
|
export function isEexist(error: unknown): boolean {
|
|
350
443
|
return hasErrorCode(error, "EEXIST");
|
|
351
444
|
}
|
|
@@ -740,7 +833,14 @@ export function printInitGuide(): void {
|
|
|
740
833
|
|
|
741
834
|
Scaffold a project, then open the playground:
|
|
742
835
|
npx ${PACKAGE_NAME} init ./my-agent # installs deps + links agent-sdk onto PATH
|
|
743
|
-
npx ${PACKAGE_NAME} init ./my-
|
|
836
|
+
npx ${PACKAGE_NAME} init ./my-demo --template demo # record a PR walkthrough
|
|
837
|
+
npx ${PACKAGE_NAME} init ./my-reviewer --template security-reviewer # review PRs for security bugs
|
|
838
|
+
npx ${PACKAGE_NAME} init ./my-triage --template triage-linear # comment on Linear issues
|
|
839
|
+
npx ${PACKAGE_NAME} init ./my-triage --template triage-jira # comment on Jira issues
|
|
840
|
+
npx ${PACKAGE_NAME} init ./my-owners --template agentic-owners # review PRs via owners policies
|
|
841
|
+
npx ${PACKAGE_NAME} init ./pr-autofixer --template pr-autofixer # fix PRs on a cloud VM
|
|
842
|
+
# TTY asks for GitHub repos. Scripts pass --var:
|
|
843
|
+
# --var repos=acme/widgets,acme/api
|
|
744
844
|
cd ./my-agent && agent-sdk dev # or: npx ${PACKAGE_NAME} dev
|
|
745
845
|
|
|
746
846
|
Recommended loop once the project exists (from the project directory):
|
|
@@ -82,6 +82,13 @@ interface ConnectableMcpServer {
|
|
|
82
82
|
* transport per POST, JSON response mode, spec-compliant 405 on other
|
|
83
83
|
* methods. Shared by the per-agent MCP endpoint and the Cursor account
|
|
84
84
|
* bridge so the subtle transport/error plumbing exists once.
|
|
85
|
+
*
|
|
86
|
+
* Origin MCP in `backend/server/src/origin/mcp/originMcpHttpHandler.ts`
|
|
87
|
+
* is not a 1:1 copy: it races `request.signal` so a tool that ignores abort
|
|
88
|
+
* cannot hang, while this helper has no such backstop and still leaks an
|
|
89
|
+
* unsettled promise. backend/server cannot import `@cursor/july` internals,
|
|
90
|
+
* so Origin diverges on purpose. Do not extract a shared package, and do
|
|
91
|
+
* not port the abort race here, in that stack.
|
|
85
92
|
*/
|
|
86
93
|
export async function handleStatelessMcpRequest(args: {
|
|
87
94
|
request: Request;
|
package/src/internal/server.ts
CHANGED
|
@@ -17,7 +17,6 @@ import { join } from "node:path";
|
|
|
17
17
|
import {
|
|
18
18
|
type CursorGithubRepoScope,
|
|
19
19
|
createCursorAccountGithubTokenResolver,
|
|
20
|
-
cursorGithubPermissionsForChannel,
|
|
21
20
|
type GithubCursorAccountRuntime,
|
|
22
21
|
getGithubCursorAccountRuntime,
|
|
23
22
|
parseCursorGithubRepoScope,
|
|
@@ -25,6 +24,12 @@ import {
|
|
|
25
24
|
resolveCursorGithubProxyUrl,
|
|
26
25
|
} from "../channels/github/cursor-account.js";
|
|
27
26
|
import { findGitHubChannelTargets } from "../channels/github/forward.js";
|
|
27
|
+
import {
|
|
28
|
+
getOriginCursorAccountRuntime,
|
|
29
|
+
type OriginCursorAccountRuntime,
|
|
30
|
+
parseCursorOriginRepoScope,
|
|
31
|
+
} from "../channels/origin/cursor-account.js";
|
|
32
|
+
import { findOriginChannelTargets } from "../channels/origin/origin-channel.js";
|
|
28
33
|
import {
|
|
29
34
|
dispatchCursorSlackEnvelope,
|
|
30
35
|
getSlackCursorAccountRuntime,
|
|
@@ -59,9 +64,11 @@ import {
|
|
|
59
64
|
import { CursorGithubCredentialProvider } from "./cursor/github-credentials.js";
|
|
60
65
|
import {
|
|
61
66
|
CursorEventRelay,
|
|
67
|
+
type CursorScmSubscription,
|
|
62
68
|
formatCursorScmDispatchOutcome,
|
|
63
69
|
formatCursorScmEventLog,
|
|
64
70
|
scmMetadataToGitHubPayload,
|
|
71
|
+
scmMetadataToOriginPayload,
|
|
65
72
|
} from "./cursor-event-relay.js";
|
|
66
73
|
import {
|
|
67
74
|
type CursorSlackAgentRegistration,
|
|
@@ -89,6 +96,7 @@ import {
|
|
|
89
96
|
} from "./eval-run-store.js";
|
|
90
97
|
import {
|
|
91
98
|
collectGitHubTriggerTargets,
|
|
99
|
+
collectOriginTriggerTargets,
|
|
92
100
|
handleAgentServeTrigger,
|
|
93
101
|
} from "./handleAgentServeTrigger.js";
|
|
94
102
|
import { createHostPlatforms, warmupHostGitHubAuth } from "./host-platforms.js";
|
|
@@ -151,11 +159,7 @@ import {
|
|
|
151
159
|
} from "./resolved-connections.js";
|
|
152
160
|
import { Router } from "./router.js";
|
|
153
161
|
import { ScheduleRunner, UnknownScheduleError } from "./schedule-runner.js";
|
|
154
|
-
import {
|
|
155
|
-
type AgentRunner,
|
|
156
|
-
CursorSdkRunner,
|
|
157
|
-
resolveServeWorkspaceScanCacheTtlMs,
|
|
158
|
-
} from "./sdk-runner.js";
|
|
162
|
+
import { type AgentRunner, CursorSdkRunner } from "./sdk-runner.js";
|
|
159
163
|
import {
|
|
160
164
|
SessionAuthError,
|
|
161
165
|
SessionBusyError,
|
|
@@ -267,11 +271,20 @@ export async function startServer(
|
|
|
267
271
|
}
|
|
268
272
|
|
|
269
273
|
const cursorGithubTargets = collectCursorGithubTargets(mounts);
|
|
274
|
+
const cursorOriginTargets = collectCursorOriginTargets(mounts);
|
|
270
275
|
const cursorGithubConfig = resolveCursorGithubEventConfig({
|
|
271
276
|
configured: options.cursorEvents,
|
|
272
277
|
targets: cursorGithubTargets,
|
|
273
278
|
});
|
|
274
|
-
const
|
|
279
|
+
const cursorOriginScope = resolveCursorOriginRepoScope({
|
|
280
|
+
explicitRepos: options.cursorEvents?.repos ?? [],
|
|
281
|
+
targets: cursorOriginTargets,
|
|
282
|
+
});
|
|
283
|
+
const effectiveCursorEvents =
|
|
284
|
+
cursorGithubConfig.cursorEvents ??
|
|
285
|
+
(cursorOriginScope === undefined
|
|
286
|
+
? undefined
|
|
287
|
+
: { repos: [...cursorOriginScope.repos] });
|
|
275
288
|
|
|
276
289
|
// One resolution for every Cursor credential consumer (SDK runner, account
|
|
277
290
|
// MCP bridge, SCM event relay, GitHub credentials): explicit option →
|
|
@@ -379,17 +392,11 @@ export async function startServer(
|
|
|
379
392
|
"[agent-sdk] warning: --allow-anonymous admits every HTTP caller as the same principal; use only on a trusted network (e.g. Tailscale) and prefer --bearer-token for shared hosts"
|
|
380
393
|
);
|
|
381
394
|
}
|
|
382
|
-
const workspaceScanCacheTtlMs = resolveServeWorkspaceScanCacheTtlMs({
|
|
383
|
-
dev,
|
|
384
|
-
});
|
|
385
395
|
const runner =
|
|
386
396
|
options.runner ??
|
|
387
397
|
new CursorSdkRunner({
|
|
388
398
|
...(accountKey === undefined ? {} : { apiKey: accountKey.apiKey }),
|
|
389
399
|
logger,
|
|
390
|
-
...(workspaceScanCacheTtlMs === undefined
|
|
391
|
-
? {}
|
|
392
|
-
: { workspaceScanCacheTtlMs }),
|
|
393
400
|
});
|
|
394
401
|
|
|
395
402
|
const router = new Router();
|
|
@@ -684,7 +691,7 @@ export async function startServer(
|
|
|
684
691
|
// job (backend `/github_webhook` already verified); we only admit loopback
|
|
685
692
|
// so this route is not a public unsigned endpoint. Agents decide whether
|
|
686
693
|
// to run via their onPullRequest / onComment / … hooks.
|
|
687
|
-
const
|
|
694
|
+
const collectGitHubTargets = () =>
|
|
688
695
|
collectGitHubTriggerTargets({
|
|
689
696
|
mounts: runtimes.map((runtime) => ({
|
|
690
697
|
slug: runtime.slug,
|
|
@@ -693,6 +700,15 @@ export async function startServer(
|
|
|
693
700
|
buildChannelHandlerArgs({ runtime, channelId }),
|
|
694
701
|
})),
|
|
695
702
|
});
|
|
703
|
+
const collectOriginTargets = () =>
|
|
704
|
+
collectOriginTriggerTargets({
|
|
705
|
+
mounts: runtimes.map((runtime) => ({
|
|
706
|
+
slug: runtime.slug,
|
|
707
|
+
channels: runtime.project.channels,
|
|
708
|
+
buildHandlerArgs: (channelId) =>
|
|
709
|
+
buildChannelHandlerArgs({ runtime, channelId }),
|
|
710
|
+
})),
|
|
711
|
+
});
|
|
696
712
|
router.add({
|
|
697
713
|
method: "POST",
|
|
698
714
|
pattern: "/v1/webhooks/github",
|
|
@@ -704,7 +720,7 @@ export async function startServer(
|
|
|
704
720
|
bodyText,
|
|
705
721
|
eventName: request.headers.get("x-github-event"),
|
|
706
722
|
deliveryId: request.headers.get("x-github-delivery") ?? undefined,
|
|
707
|
-
targets:
|
|
723
|
+
targets: collectGitHubTargets(),
|
|
708
724
|
});
|
|
709
725
|
const status = result.ok ? 202 : (result.targets[0]?.status ?? 500);
|
|
710
726
|
return jsonResponse(result, { status });
|
|
@@ -743,13 +759,17 @@ export async function startServer(
|
|
|
743
759
|
// Cursor SCM events relay (opt-in: serve({ cursorEvents }) / --cursor-events).
|
|
744
760
|
const cursorEventRelay = startCursorEventRelay({
|
|
745
761
|
config: effectiveCursorEvents,
|
|
762
|
+
githubRepos: cursorGithubConfig.cursorEvents?.repos ?? [],
|
|
763
|
+
originRepos: cursorOriginScope?.repos ?? [],
|
|
746
764
|
stateRoot: options.stateRoot,
|
|
747
765
|
mounts,
|
|
748
766
|
auth: cursorEventsAuth,
|
|
749
767
|
logger,
|
|
750
|
-
|
|
768
|
+
collectGitHubTargets,
|
|
769
|
+
collectOriginTargets,
|
|
751
770
|
cursorAccountOnly:
|
|
752
|
-
options.cursorEvents === undefined &&
|
|
771
|
+
options.cursorEvents === undefined &&
|
|
772
|
+
(cursorGithubTargets.length > 0 || cursorOriginTargets.length > 0),
|
|
753
773
|
});
|
|
754
774
|
|
|
755
775
|
const server = createServer((req, res) => {
|
|
@@ -1759,37 +1779,73 @@ function requireCursorEventsAuth(
|
|
|
1759
1779
|
/**
|
|
1760
1780
|
* Opt-in Cursor SCM events relay. Credentials are already required by
|
|
1761
1781
|
* {@link requireCursorEventsAuth}; the remaining unusable configs (no repos,
|
|
1762
|
-
* no github channel) warn and leave the relay off — serve still starts.
|
|
1782
|
+
* no github/origin channel) warn and leave the relay off — serve still starts.
|
|
1783
|
+
*
|
|
1784
|
+
* GitHub and Origin subscriptions are registered independently so mirrored
|
|
1785
|
+
* `owner/name` slugs do not mix. `--cursor-events --repo` feeds GitHub
|
|
1786
|
+
* channels; Origin is subscribed only when an `originChannel({ cursorAccount })`
|
|
1787
|
+
* opted in.
|
|
1763
1788
|
*/
|
|
1764
1789
|
function startCursorEventRelay(input: {
|
|
1765
1790
|
config: ServeOptions["cursorEvents"];
|
|
1791
|
+
githubRepos: readonly string[];
|
|
1792
|
+
originRepos: readonly string[];
|
|
1766
1793
|
stateRoot: string | undefined;
|
|
1767
1794
|
mounts: AgentMount[];
|
|
1768
1795
|
auth: CursorEventsAuth | undefined;
|
|
1769
1796
|
logger: (line: string) => void;
|
|
1770
|
-
|
|
1797
|
+
collectGitHubTargets: () => ReturnType<typeof collectGitHubTriggerTargets>;
|
|
1798
|
+
collectOriginTargets: () => ReturnType<typeof collectOriginTriggerTargets>;
|
|
1771
1799
|
cursorAccountOnly: boolean;
|
|
1772
1800
|
}): CursorEventRelay | undefined {
|
|
1773
|
-
const { config, stateRoot, mounts, auth, logger
|
|
1774
|
-
input;
|
|
1801
|
+
const { config, stateRoot, mounts, auth, logger } = input;
|
|
1775
1802
|
if (config === undefined || auth === undefined) {
|
|
1776
1803
|
return undefined;
|
|
1777
1804
|
}
|
|
1778
|
-
const repos = [...new Set(config.repos.map((repo) => repo.trim()))].filter(
|
|
1779
|
-
(repo) => repo.length > 0
|
|
1780
|
-
);
|
|
1781
|
-
if (repos.length === 0) {
|
|
1782
|
-
logger(
|
|
1783
|
-
"[agent-sdk] cursor-events: no repos configured (pass --repo owner/name); relay disabled"
|
|
1784
|
-
);
|
|
1785
|
-
return undefined;
|
|
1786
|
-
}
|
|
1787
1805
|
const githubTargets = findGitHubChannelTargets(mounts);
|
|
1788
|
-
const
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1806
|
+
const originTargets = findOriginChannelTargets(mounts);
|
|
1807
|
+
const githubEvents = [
|
|
1808
|
+
...new Set(githubTargets.flatMap((target) => target.events)),
|
|
1809
|
+
];
|
|
1810
|
+
const originEvents = [
|
|
1811
|
+
...new Set(originTargets.flatMap((target) => target.events)),
|
|
1812
|
+
];
|
|
1813
|
+
const githubRepos = [
|
|
1814
|
+
...new Set(input.githubRepos.map((repo) => repo.trim().toLowerCase())),
|
|
1815
|
+
].filter((repo) => repo.length > 0);
|
|
1816
|
+
const originRepos = [
|
|
1817
|
+
...new Set(input.originRepos.map((repo) => repo.trim().toLowerCase())),
|
|
1818
|
+
].filter((repo) => repo.length > 0);
|
|
1819
|
+
|
|
1820
|
+
const subscriptions: CursorScmSubscription[] = [];
|
|
1821
|
+
if (githubEvents.length > 0 && githubRepos.length > 0) {
|
|
1822
|
+
for (const repo of githubRepos) {
|
|
1823
|
+
subscriptions.push({
|
|
1824
|
+
provider: "github",
|
|
1825
|
+
repo,
|
|
1826
|
+
events: githubEvents,
|
|
1827
|
+
});
|
|
1828
|
+
}
|
|
1829
|
+
}
|
|
1830
|
+
if (originEvents.length > 0 && originRepos.length > 0) {
|
|
1831
|
+
for (const repo of originRepos) {
|
|
1832
|
+
subscriptions.push({
|
|
1833
|
+
provider: "origin",
|
|
1834
|
+
repo,
|
|
1835
|
+
events: originEvents,
|
|
1836
|
+
});
|
|
1837
|
+
}
|
|
1838
|
+
}
|
|
1839
|
+
if (subscriptions.length === 0) {
|
|
1840
|
+
if (githubRepos.length === 0 && originRepos.length === 0) {
|
|
1841
|
+
logger(
|
|
1842
|
+
"[agent-sdk] cursor-events: no repos configured (pass --repo owner/name); relay disabled"
|
|
1843
|
+
);
|
|
1844
|
+
} else {
|
|
1845
|
+
logger(
|
|
1846
|
+
"[agent-sdk] cursor-events: no mounted agent declares a github or origin channel; relay disabled"
|
|
1847
|
+
);
|
|
1848
|
+
}
|
|
1793
1849
|
return undefined;
|
|
1794
1850
|
}
|
|
1795
1851
|
const baseStateRoot =
|
|
@@ -1798,15 +1854,36 @@ function startCursorEventRelay(input: {
|
|
|
1798
1854
|
const relay = new CursorEventRelay({
|
|
1799
1855
|
baseUrl: auth.baseUrl,
|
|
1800
1856
|
apiKey: auth.apiKey,
|
|
1801
|
-
|
|
1802
|
-
events,
|
|
1857
|
+
subscriptions,
|
|
1803
1858
|
stateDir: join(baseStateRoot, "cursor-events"),
|
|
1804
1859
|
logger,
|
|
1805
|
-
// Stream is compact metadata (Sand-style); stub a GitHub body from the
|
|
1806
|
-
// envelope — rich pullRequest meta when present for onPullRequest Zod.
|
|
1807
1860
|
dispatch: async (event) => {
|
|
1861
|
+
if (event.provider === "origin") {
|
|
1862
|
+
const targets = input.collectOriginTargets().filter((target) => {
|
|
1863
|
+
const cursorAccount = target.options.cursorAccount;
|
|
1864
|
+
if (
|
|
1865
|
+
input.cursorAccountOnly &&
|
|
1866
|
+
cursorAccount !== true &&
|
|
1867
|
+
typeof cursorAccount !== "object"
|
|
1868
|
+
) {
|
|
1869
|
+
return false;
|
|
1870
|
+
}
|
|
1871
|
+
return typeof cursorAccount !== "object"
|
|
1872
|
+
? true
|
|
1873
|
+
: cursorAccount.repos.some(
|
|
1874
|
+
(repo) => repo.toLowerCase() === event.repo.toLowerCase()
|
|
1875
|
+
);
|
|
1876
|
+
});
|
|
1877
|
+
const result = await handleAgentServeTrigger({
|
|
1878
|
+
type: "origin",
|
|
1879
|
+
bodyText: JSON.stringify(scmMetadataToOriginPayload(event)),
|
|
1880
|
+
targets,
|
|
1881
|
+
});
|
|
1882
|
+
logCursorScmDispatch(logger, event, result);
|
|
1883
|
+
return;
|
|
1884
|
+
}
|
|
1808
1885
|
if (event.provider !== "github") return;
|
|
1809
|
-
const targets =
|
|
1886
|
+
const targets = input.collectGitHubTargets().filter((target) => {
|
|
1810
1887
|
const cursorAccount = target.options.cursorAccount;
|
|
1811
1888
|
if (
|
|
1812
1889
|
input.cursorAccountOnly &&
|
|
@@ -1828,27 +1905,35 @@ function startCursorEventRelay(input: {
|
|
|
1828
1905
|
deliveryId: event.deliveryId,
|
|
1829
1906
|
targets,
|
|
1830
1907
|
});
|
|
1831
|
-
|
|
1832
|
-
.map((target) => formatCursorScmDispatchOutcome(target))
|
|
1833
|
-
.join(", ");
|
|
1834
|
-
const rejected = result.targets.filter((target) => target.status >= 400);
|
|
1835
|
-
if (rejected.length > 0) {
|
|
1836
|
-
logger(
|
|
1837
|
-
`[agent-sdk] cursor-events: dropped ${formatCursorScmEventLog(event)} before hook: ${rejected.map(formatCursorScmDispatchOutcome).join(", ")}`
|
|
1838
|
-
);
|
|
1839
|
-
}
|
|
1840
|
-
logger(
|
|
1841
|
-
`[agent-sdk] cursor-events: dispatched ${formatCursorScmEventLog(event)}${outcomes === "" ? "" : ` → ${outcomes}`}`
|
|
1842
|
-
);
|
|
1908
|
+
logCursorScmDispatch(logger, event, result);
|
|
1843
1909
|
},
|
|
1844
1910
|
});
|
|
1845
1911
|
relay.start();
|
|
1846
1912
|
logger(
|
|
1847
|
-
`[agent-sdk] cursor-events: relaying ${
|
|
1913
|
+
`[agent-sdk] cursor-events: relaying ${subscriptions.length} subscription(s) from ${auth.baseUrl}`
|
|
1848
1914
|
);
|
|
1849
1915
|
return relay;
|
|
1850
1916
|
}
|
|
1851
1917
|
|
|
1918
|
+
function logCursorScmDispatch(
|
|
1919
|
+
logger: (line: string) => void,
|
|
1920
|
+
event: Parameters<typeof formatCursorScmEventLog>[0],
|
|
1921
|
+
result: Awaited<ReturnType<typeof handleAgentServeTrigger>>
|
|
1922
|
+
): void {
|
|
1923
|
+
const outcomes = result.targets
|
|
1924
|
+
.map((target) => formatCursorScmDispatchOutcome(target))
|
|
1925
|
+
.join(", ");
|
|
1926
|
+
const rejected = result.targets.filter((target) => target.status >= 400);
|
|
1927
|
+
if (rejected.length > 0) {
|
|
1928
|
+
logger(
|
|
1929
|
+
`[agent-sdk] cursor-events: dropped ${formatCursorScmEventLog(event)} before hook: ${rejected.map(formatCursorScmDispatchOutcome).join(", ")}`
|
|
1930
|
+
);
|
|
1931
|
+
}
|
|
1932
|
+
logger(
|
|
1933
|
+
`[agent-sdk] cursor-events: dispatched ${formatCursorScmEventLog(event)}${outcomes === "" ? "" : ` → ${outcomes}`}`
|
|
1934
|
+
);
|
|
1935
|
+
}
|
|
1936
|
+
|
|
1852
1937
|
interface CursorGithubTarget {
|
|
1853
1938
|
slug: string;
|
|
1854
1939
|
channelId: string;
|
|
@@ -1893,11 +1978,8 @@ function resolveCursorGithubEventConfig(input: {
|
|
|
1893
1978
|
]),
|
|
1894
1979
|
];
|
|
1895
1980
|
const permissions = resolveCursorGithubPermissions(
|
|
1896
|
-
input.targets.map(
|
|
1897
|
-
|
|
1898
|
-
target.accountRuntime.options,
|
|
1899
|
-
target.accountRuntime.scope?.permissions
|
|
1900
|
-
)
|
|
1981
|
+
input.targets.map(
|
|
1982
|
+
(target) => target.accountRuntime.scope?.permissions ?? "pr-write"
|
|
1901
1983
|
)
|
|
1902
1984
|
);
|
|
1903
1985
|
const scope = parseCursorGithubRepoScope(repos, permissions);
|
|
@@ -1910,6 +1992,54 @@ function resolveCursorGithubEventConfig(input: {
|
|
|
1910
1992
|
};
|
|
1911
1993
|
}
|
|
1912
1994
|
|
|
1995
|
+
interface CursorOriginTarget {
|
|
1996
|
+
slug: string;
|
|
1997
|
+
channelId: string;
|
|
1998
|
+
accountRuntime: OriginCursorAccountRuntime;
|
|
1999
|
+
}
|
|
2000
|
+
|
|
2001
|
+
function collectCursorOriginTargets(
|
|
2002
|
+
mounts: AgentMount[]
|
|
2003
|
+
): CursorOriginTarget[] {
|
|
2004
|
+
const targets: CursorOriginTarget[] = [];
|
|
2005
|
+
for (const mount of mounts) {
|
|
2006
|
+
for (const channel of mount.project.channels) {
|
|
2007
|
+
const accountRuntime = getOriginCursorAccountRuntime(channel.definition);
|
|
2008
|
+
if (accountRuntime !== undefined) {
|
|
2009
|
+
targets.push({
|
|
2010
|
+
slug: mount.slug,
|
|
2011
|
+
channelId: channel.id,
|
|
2012
|
+
accountRuntime,
|
|
2013
|
+
});
|
|
2014
|
+
}
|
|
2015
|
+
}
|
|
2016
|
+
}
|
|
2017
|
+
return targets;
|
|
2018
|
+
}
|
|
2019
|
+
|
|
2020
|
+
/**
|
|
2021
|
+
* Origin cursorAccount repos. `true` takes the host's explicit `--repo`
|
|
2022
|
+
* list (not GitHub channel-declared repos). `{ repos }` is self-contained.
|
|
2023
|
+
*/
|
|
2024
|
+
function resolveCursorOriginRepoScope(input: {
|
|
2025
|
+
explicitRepos: readonly string[];
|
|
2026
|
+
targets: CursorOriginTarget[];
|
|
2027
|
+
}): ReturnType<typeof parseCursorOriginRepoScope> | undefined {
|
|
2028
|
+
if (input.targets.length === 0) {
|
|
2029
|
+
return undefined;
|
|
2030
|
+
}
|
|
2031
|
+
const wantsHostRepos = input.targets.some(
|
|
2032
|
+
(target) => target.accountRuntime.options.cursorAccount === true
|
|
2033
|
+
);
|
|
2034
|
+
const repos = [
|
|
2035
|
+
...(wantsHostRepos ? input.explicitRepos : []),
|
|
2036
|
+
...input.targets.flatMap(
|
|
2037
|
+
(target) => target.accountRuntime.scope?.repos ?? []
|
|
2038
|
+
),
|
|
2039
|
+
];
|
|
2040
|
+
return parseCursorOriginRepoScope(repos);
|
|
2041
|
+
}
|
|
2042
|
+
|
|
1913
2043
|
interface CursorSlackTarget {
|
|
1914
2044
|
runtime: MountedRuntime;
|
|
1915
2045
|
channelId: string;
|