@cursor/july 0.1.55 → 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.CVQxhV85.js → app.CW3KJh72.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.BuymfBAo.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.QAPzJjql.js → VPLocalSearchBox.Bk6EWpPj.js} +1 -1
- package/dist/docs/assets/chunks/{theme.CSxTCOFu.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.D_CCfG8R.js → reference_cli.md.Cl14Jfo3.js} +8 -2
- package/dist/docs/assets/{reference_cli.md.D_CCfG8R.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/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 +12 -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 +5 -5
- 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 +20 -0
- package/dist/internal/cli-slack.d.ts +2 -0
- package/dist/internal/cli-slack.d.ts.map +1 -1
- package/dist/internal/cli-slack.js +11 -2
- 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 +4 -0
- package/dist/internal/init-project.d.ts.map +1 -1
- package/dist/internal/init-project.js +40 -16
- 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/playground/assets/index-ClbuaLpm.css +1 -0
- package/dist/playground/assets/{index-0oqXUkrR.js → index-SqkR13k_.js} +39 -39
- 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 +34 -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/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 +23 -0
- package/src/internal/cli-slack.ts +11 -1
- 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 +70 -15
- 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/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/dist/docs/assets/chunks/@localSearchIndexroot.BFpWSo6D.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/playground/assets/index-tHCjJxv4.css +0 -1
package/src/internal/cli-ax.ts
CHANGED
|
@@ -40,6 +40,7 @@ import {
|
|
|
40
40
|
snapshotToEvalRunResults,
|
|
41
41
|
startRemoteEvalRun,
|
|
42
42
|
} from "./evals-client.js";
|
|
43
|
+
import { runTemplateInit, type TemplateInitSpec } from "./init-interview.js";
|
|
43
44
|
import {
|
|
44
45
|
checkInitTarget,
|
|
45
46
|
formatInitNextSteps,
|
|
@@ -134,6 +135,8 @@ export interface AxCliOptions {
|
|
|
134
135
|
/** Scaffold target directory for `init`. */
|
|
135
136
|
initTarget?: string;
|
|
136
137
|
template?: string;
|
|
138
|
+
/** `init --var id=value` (repeatable). */
|
|
139
|
+
vars?: string[];
|
|
137
140
|
/** Tool name for `call`. */
|
|
138
141
|
toolName?: string;
|
|
139
142
|
/** JSON input for `call`. */
|
|
@@ -311,11 +314,31 @@ export async function cmdInit(options: AxCliOptions): Promise<number> {
|
|
|
311
314
|
process.stderr.write(`${targetCheck.message}\n`);
|
|
312
315
|
return 1;
|
|
313
316
|
}
|
|
317
|
+
let answers: Record<string, string> | undefined;
|
|
318
|
+
let initSpec: TemplateInitSpec | undefined;
|
|
319
|
+
if (templateDir !== undefined) {
|
|
320
|
+
const interview = await runTemplateInit({
|
|
321
|
+
templateDir,
|
|
322
|
+
vars: options.vars,
|
|
323
|
+
interactive:
|
|
324
|
+
options.json !== true &&
|
|
325
|
+
process.stdin.isTTY === true &&
|
|
326
|
+
process.stdout.isTTY === true,
|
|
327
|
+
});
|
|
328
|
+
if (!interview.ok) {
|
|
329
|
+
process.stderr.write(`${interview.error}\n`);
|
|
330
|
+
return 1;
|
|
331
|
+
}
|
|
332
|
+
answers = interview.answers;
|
|
333
|
+
initSpec = interview.spec;
|
|
334
|
+
}
|
|
314
335
|
const result = await initProject({
|
|
315
336
|
dir,
|
|
316
337
|
templateDir,
|
|
317
338
|
overlayDir,
|
|
318
339
|
templateName,
|
|
340
|
+
answers,
|
|
341
|
+
initSpec,
|
|
319
342
|
});
|
|
320
343
|
let signedIn = (await resolveApiKey()) !== undefined;
|
|
321
344
|
|
|
@@ -64,6 +64,8 @@ export interface SlackCliOptions {
|
|
|
64
64
|
manual?: boolean;
|
|
65
65
|
/** `slack icon <source>` positional (same URL-or-file forms as --icon). */
|
|
66
66
|
iconSource?: string;
|
|
67
|
+
/** doctor: watched channel ids (`C…`) to verify visibility/membership. */
|
|
68
|
+
channels?: string[];
|
|
67
69
|
/** Test seams. */
|
|
68
70
|
fetchImpl?: typeof fetch;
|
|
69
71
|
openBrowserImpl?: (url: string) => void;
|
|
@@ -91,6 +93,7 @@ Usage:
|
|
|
91
93
|
${CLI} slack manifest --env dev|prod|both [--dir .] [--name NAME]
|
|
92
94
|
[--print]
|
|
93
95
|
${CLI} slack doctor [--dir .] [--prefix PREFIX | --no-prefix] [--json]
|
|
96
|
+
[--channel C0123ABCD]...
|
|
94
97
|
|
|
95
98
|
create/destroy/icon — dedicated Socket Mode app via the Cursor dashboard:
|
|
96
99
|
create Opens the signed-in dashboard wizard. Finish name, workspace,
|
|
@@ -155,7 +158,11 @@ async function runDoctor(options: SlackCliOptions): Promise<number> {
|
|
|
155
158
|
loadAgentLocalEnv(dir);
|
|
156
159
|
const envPrefix = resolveDoctorEnvPrefix(options, dir);
|
|
157
160
|
const doctor = options.doctorImpl ?? runSlackDoctor;
|
|
158
|
-
const
|
|
161
|
+
const channels = options.channels ?? [];
|
|
162
|
+
const result = await doctor({
|
|
163
|
+
envPrefix,
|
|
164
|
+
channels: channels.length > 0 ? channels : undefined,
|
|
165
|
+
});
|
|
159
166
|
if (options.json) {
|
|
160
167
|
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
161
168
|
} else {
|
|
@@ -879,6 +886,9 @@ function renderDoctorReport(result: SlackDoctorResult): string {
|
|
|
879
886
|
text += `${check.ok ? "ok" : "!!"} ${check.id}: ${check.message}\n`;
|
|
880
887
|
}
|
|
881
888
|
text += result.ok ? "doctor: pass\n" : "doctor: fail\n";
|
|
889
|
+
for (const note of result.notes ?? []) {
|
|
890
|
+
text += `\nnote: ${note}\n`;
|
|
891
|
+
}
|
|
882
892
|
return text;
|
|
883
893
|
}
|
|
884
894
|
|
|
@@ -115,6 +115,12 @@ export interface CursorScmEvent {
|
|
|
115
115
|
* Zod-valid `issue_comment` / `pull_request_review_comment` webhook body.
|
|
116
116
|
*/
|
|
117
117
|
comment?: CursorScmCommentMeta;
|
|
118
|
+
/**
|
|
119
|
+
* Origin comment snapshot. Ids are Origin string ids, not GitHub integers.
|
|
120
|
+
*/
|
|
121
|
+
originComment?: CursorScmOriginCommentMeta;
|
|
122
|
+
/** Origin actor (author / pusher / commenter) when present. */
|
|
123
|
+
originActor?: CursorScmOriginActorMeta;
|
|
118
124
|
/** `check_run` snapshot; enough to stub `onCheckRun`. */
|
|
119
125
|
checkRun?: CursorScmCheckRunMeta;
|
|
120
126
|
/** `check_suite` snapshot; enough to stub `onCheckSuite`. */
|
|
@@ -125,6 +131,25 @@ export interface CursorScmEvent {
|
|
|
125
131
|
occurredAtMs?: number;
|
|
126
132
|
}
|
|
127
133
|
|
|
134
|
+
export type CursorScmOriginActorMeta = {
|
|
135
|
+
id: string;
|
|
136
|
+
kind?: string;
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
export type CursorScmOriginCommentMeta = {
|
|
140
|
+
id: string;
|
|
141
|
+
body?: string;
|
|
142
|
+
author?: CursorScmOriginActorMeta;
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
export type CursorScmProvider = "github" | "origin";
|
|
146
|
+
|
|
147
|
+
export interface CursorScmSubscription {
|
|
148
|
+
provider: CursorScmProvider;
|
|
149
|
+
repo: string;
|
|
150
|
+
events: readonly string[];
|
|
151
|
+
}
|
|
152
|
+
|
|
128
153
|
interface SubscriptionStatus {
|
|
129
154
|
provider: string;
|
|
130
155
|
repo: string;
|
|
@@ -135,8 +160,17 @@ interface SubscriptionStatus {
|
|
|
135
160
|
export interface CursorEventRelayOptions {
|
|
136
161
|
baseUrl: string;
|
|
137
162
|
apiKey: string;
|
|
138
|
-
|
|
139
|
-
|
|
163
|
+
/**
|
|
164
|
+
* GitHub-only shorthand. Ignored when {@link subscriptions} is set.
|
|
165
|
+
* Existing `--cursor-events --repo` hosts keep passing these.
|
|
166
|
+
*/
|
|
167
|
+
repos?: readonly string[];
|
|
168
|
+
events?: readonly string[];
|
|
169
|
+
/**
|
|
170
|
+
* Mixed GitHub + Origin registrations. Provider is part of the
|
|
171
|
+
* subscription key: mirrored `owner/name` slugs must not collide.
|
|
172
|
+
*/
|
|
173
|
+
subscriptions?: readonly CursorScmSubscription[];
|
|
140
174
|
stateDir: string;
|
|
141
175
|
/**
|
|
142
176
|
* Called for each matching event; failures retry a bounded number of
|
|
@@ -430,30 +464,149 @@ function stubGitHubWorkflowRun(
|
|
|
430
464
|
}
|
|
431
465
|
|
|
432
466
|
/**
|
|
433
|
-
*
|
|
467
|
+
* Origin webhook envelope from an SCM-events metadata record. One parser
|
|
468
|
+
* handles both live Origin deliveries and this stub: `{ deliveryId, event }`.
|
|
469
|
+
*/
|
|
470
|
+
export function scmMetadataToOriginPayload(event: {
|
|
471
|
+
repo: string;
|
|
472
|
+
eventName: string;
|
|
473
|
+
deliveryId?: string;
|
|
474
|
+
action?: string;
|
|
475
|
+
prNumber?: number;
|
|
476
|
+
prUrl?: string;
|
|
477
|
+
pullRequest?: CursorScmPullRequestMeta;
|
|
478
|
+
originComment?: CursorScmOriginCommentMeta;
|
|
479
|
+
originActor?: CursorScmOriginActorMeta;
|
|
480
|
+
occurredAtMs?: number;
|
|
481
|
+
}): Record<string, unknown> {
|
|
482
|
+
const slash = event.repo.indexOf("/");
|
|
483
|
+
const owner = slash === -1 ? "" : event.repo.slice(0, slash);
|
|
484
|
+
const name = slash === -1 ? event.repo : event.repo.slice(slash + 1);
|
|
485
|
+
const prMeta = event.pullRequest;
|
|
486
|
+
const prNumber = prMeta?.number ?? event.prNumber;
|
|
487
|
+
const prUrl =
|
|
488
|
+
prMeta?.url ??
|
|
489
|
+
event.prUrl ??
|
|
490
|
+
(prNumber !== undefined
|
|
491
|
+
? `https://cursor.com/codebase/${owner}/${name}/pull/${prNumber}`
|
|
492
|
+
: undefined);
|
|
493
|
+
|
|
494
|
+
const payload: Record<string, unknown> = {
|
|
495
|
+
repository: {
|
|
496
|
+
name,
|
|
497
|
+
owner: { slug: owner },
|
|
498
|
+
},
|
|
499
|
+
};
|
|
500
|
+
|
|
501
|
+
if (prNumber !== undefined) {
|
|
502
|
+
const pullRequest: Record<string, unknown> = {
|
|
503
|
+
number: prNumber,
|
|
504
|
+
url: prUrl,
|
|
505
|
+
};
|
|
506
|
+
if (prMeta?.title !== undefined) pullRequest.title = prMeta.title;
|
|
507
|
+
if (prMeta?.body !== undefined) pullRequest.body = prMeta.body;
|
|
508
|
+
if (prMeta?.draft !== undefined) pullRequest.draft = prMeta.draft;
|
|
509
|
+
if (prMeta?.merged !== undefined) pullRequest.merged = prMeta.merged;
|
|
510
|
+
if (prMeta?.headRef !== undefined || prMeta?.headSha !== undefined) {
|
|
511
|
+
pullRequest.head = {
|
|
512
|
+
ref: prMeta.headRef,
|
|
513
|
+
sha: prMeta.headSha,
|
|
514
|
+
};
|
|
515
|
+
}
|
|
516
|
+
if (prMeta?.baseRef !== undefined || prMeta?.baseSha !== undefined) {
|
|
517
|
+
pullRequest.base = {
|
|
518
|
+
ref: prMeta.baseRef,
|
|
519
|
+
sha: prMeta.baseSha,
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
if (prMeta?.authorLogin !== undefined) {
|
|
523
|
+
pullRequest.author = { id: prMeta.authorLogin };
|
|
524
|
+
}
|
|
525
|
+
payload.pullRequest = pullRequest;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
const commentMeta = event.originComment;
|
|
529
|
+
if (commentMeta !== undefined) {
|
|
530
|
+
const comment: Record<string, unknown> = { id: commentMeta.id };
|
|
531
|
+
if (commentMeta.body !== undefined) comment.body = commentMeta.body;
|
|
532
|
+
if (commentMeta.author !== undefined) comment.author = commentMeta.author;
|
|
533
|
+
payload.comment = comment;
|
|
534
|
+
}
|
|
535
|
+
if (event.originActor !== undefined) {
|
|
536
|
+
payload.actor = event.originActor;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
return {
|
|
540
|
+
deliveryId: event.deliveryId,
|
|
541
|
+
event: {
|
|
542
|
+
type: event.eventName,
|
|
543
|
+
...(event.occurredAtMs === undefined
|
|
544
|
+
? {}
|
|
545
|
+
: { eventTime: new Date(event.occurredAtMs).toISOString() }),
|
|
546
|
+
payload,
|
|
547
|
+
},
|
|
548
|
+
};
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
function subscriptionKey(provider: string, repo: string): string {
|
|
552
|
+
return `${provider}:${repo.toLowerCase()}`;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
function subscriptionLabel(provider: string, repo: string): string {
|
|
556
|
+
return provider === "github" ? repo : `${provider}:${repo}`;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
export function resolveCursorScmSubscriptions(
|
|
560
|
+
options: Pick<CursorEventRelayOptions, "repos" | "events" | "subscriptions">
|
|
561
|
+
): CursorScmSubscription[] {
|
|
562
|
+
if (options.subscriptions !== undefined) {
|
|
563
|
+
return options.subscriptions.map((subscription) => ({
|
|
564
|
+
provider: subscription.provider,
|
|
565
|
+
repo: subscription.repo.trim().toLowerCase(),
|
|
566
|
+
events: [...subscription.events],
|
|
567
|
+
}));
|
|
568
|
+
}
|
|
569
|
+
const events = [...(options.events ?? [])];
|
|
570
|
+
return (options.repos ?? []).map((repo) => ({
|
|
571
|
+
provider: "github" as const,
|
|
572
|
+
repo: repo.trim().toLowerCase(),
|
|
573
|
+
events,
|
|
574
|
+
}));
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
/**
|
|
578
|
+
* SCM-events relay: a thin {@link CursorRelayCore} adapter. Consumers
|
|
434
579
|
* keep the same `new CursorEventRelay(options).start()/.stop()` surface.
|
|
435
580
|
*/
|
|
436
581
|
export class CursorEventRelay {
|
|
437
582
|
private readonly core: CursorRelayCore<CursorScmEvent>;
|
|
583
|
+
private readonly subscriptions: CursorScmSubscription[];
|
|
438
584
|
/**
|
|
439
|
-
*
|
|
440
|
-
* shared with sibling consumers
|
|
441
|
-
*
|
|
585
|
+
* Confirmed `provider:repo` keys for THIS consumer, with the event kinds
|
|
586
|
+
* requested for each. The stream is shared with sibling consumers, so
|
|
587
|
+
* GitHub and Origin deliveries for the same owner/name must not mix.
|
|
442
588
|
*/
|
|
443
|
-
private
|
|
444
|
-
private readonly
|
|
589
|
+
private subscribedEvents = new Map<string, ReadonlySet<string>>();
|
|
590
|
+
private readonly loggedSkippedKeys = new Set<string>();
|
|
445
591
|
|
|
446
592
|
constructor(private readonly options: CursorEventRelayOptions) {
|
|
593
|
+
this.subscriptions = resolveCursorScmSubscriptions(options);
|
|
594
|
+
const requestedEvents = new Map(
|
|
595
|
+
this.subscriptions.map((subscription) => [
|
|
596
|
+
subscriptionKey(subscription.provider, subscription.repo),
|
|
597
|
+
new Set(subscription.events),
|
|
598
|
+
])
|
|
599
|
+
);
|
|
447
600
|
const adapter: RelayAdapter<CursorScmEvent> = {
|
|
448
601
|
logPrefix: "cursor-events",
|
|
449
602
|
subscribePath: "/v0/scm-events/subscriptions",
|
|
450
603
|
pollPath: "/v0/scm-events",
|
|
451
604
|
buildRegistrationBody: (consumerId) => ({
|
|
452
605
|
consumerId,
|
|
453
|
-
subscriptions: this.
|
|
454
|
-
provider:
|
|
455
|
-
repo,
|
|
456
|
-
events: [...
|
|
606
|
+
subscriptions: this.subscriptions.map((subscription) => ({
|
|
607
|
+
provider: subscription.provider,
|
|
608
|
+
repo: subscription.repo,
|
|
609
|
+
events: [...subscription.events],
|
|
457
610
|
})),
|
|
458
611
|
}),
|
|
459
612
|
// Empty subscriptions drop this consumer's registration on clean stop
|
|
@@ -465,20 +618,27 @@ export class CursorEventRelay {
|
|
|
465
618
|
applyRegistrationResponse: (json) => {
|
|
466
619
|
const result = json as { repos?: SubscriptionStatus[] };
|
|
467
620
|
const statuses = result.repos ?? [];
|
|
468
|
-
this.
|
|
469
|
-
statuses
|
|
470
|
-
.filter((status) => status.isSubscribed)
|
|
471
|
-
.map((status) => status.repo)
|
|
472
|
-
);
|
|
621
|
+
this.subscribedEvents = new Map();
|
|
473
622
|
const lines: string[] = [];
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
);
|
|
623
|
+
const confirmed: string[] = [];
|
|
624
|
+
for (const status of statuses) {
|
|
625
|
+
const provider = status.provider || "github";
|
|
626
|
+
const key = subscriptionKey(provider, status.repo);
|
|
627
|
+
if (!status.isSubscribed) {
|
|
628
|
+
lines.push(
|
|
629
|
+
`not subscribed to ${subscriptionLabel(provider, status.repo)}: ${status.detail ?? "unknown reason"}`
|
|
630
|
+
);
|
|
631
|
+
continue;
|
|
632
|
+
}
|
|
633
|
+
this.subscribedEvents.set(key, requestedEvents.get(key) ?? new Set());
|
|
634
|
+
confirmed.push(subscriptionLabel(provider, status.repo));
|
|
478
635
|
}
|
|
479
|
-
if (
|
|
636
|
+
if (confirmed.length > 0) {
|
|
637
|
+
const eventKinds = [
|
|
638
|
+
...new Set(this.subscriptions.flatMap((s) => [...s.events])),
|
|
639
|
+
];
|
|
480
640
|
lines.push(
|
|
481
|
-
`subscribed to ${
|
|
641
|
+
`subscribed to ${confirmed.join(", ")} for events: ${eventKinds.join(", ")}`
|
|
482
642
|
);
|
|
483
643
|
}
|
|
484
644
|
return lines;
|
|
@@ -503,21 +663,23 @@ export class CursorEventRelay {
|
|
|
503
663
|
|
|
504
664
|
/**
|
|
505
665
|
* Whether an event from the shared stream belongs to THIS consumer: the
|
|
506
|
-
* repo must be one the server confirmed for us and the event kind
|
|
507
|
-
*
|
|
508
|
-
*
|
|
666
|
+
* provider+repo must be one the server confirmed for us and the event kind
|
|
667
|
+
* one that subscription declared. GitHub and Origin share owner/name slugs
|
|
668
|
+
* on mirrors, so the provider is part of the key.
|
|
509
669
|
*/
|
|
510
670
|
private shouldDispatch(event: CursorScmEvent): boolean {
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
671
|
+
const key = subscriptionKey(event.provider || "github", event.repo);
|
|
672
|
+
const events = this.subscribedEvents.get(key);
|
|
673
|
+
if (events === undefined) {
|
|
674
|
+
if (!this.loggedSkippedKeys.has(key)) {
|
|
675
|
+
this.loggedSkippedKeys.add(key);
|
|
514
676
|
this.options.logger(
|
|
515
|
-
`[agent-sdk] cursor-events: skipping events for ${event.repo}: not in this host's subscription (another consumer of this API key likely subscribed it)`
|
|
677
|
+
`[agent-sdk] cursor-events: skipping events for ${subscriptionLabel(event.provider || "github", event.repo)}: not in this host's subscription (another consumer of this API key likely subscribed it)`
|
|
516
678
|
);
|
|
517
679
|
}
|
|
518
680
|
return false;
|
|
519
681
|
}
|
|
520
|
-
return
|
|
682
|
+
return events.has(event.eventName);
|
|
521
683
|
}
|
|
522
684
|
|
|
523
685
|
start(): void {
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
relative,
|
|
17
17
|
resolve,
|
|
18
18
|
} from "node:path";
|
|
19
|
+
import { pathToFileURL } from "node:url";
|
|
19
20
|
import { type ABConfigFile, resolveABMaxPlaygroundSessions } from "../ab.js";
|
|
20
21
|
import { resolveArtifactsMax } from "../artifacts.js";
|
|
21
22
|
import { httpChannel } from "../channels.js";
|
|
@@ -60,10 +61,7 @@ import {
|
|
|
60
61
|
type ToolDefinition,
|
|
61
62
|
toPublicCloudInfo,
|
|
62
63
|
} from "../types.js";
|
|
63
|
-
import {
|
|
64
|
-
importAuthoredModule,
|
|
65
|
-
registerAuthoredModuleLoaders,
|
|
66
|
-
} from "./authored-loaders.js";
|
|
64
|
+
import { registerAuthoredModuleLoaders } from "./authored-loaders.js";
|
|
67
65
|
import { normalizePositiveInt } from "./bounded-int.js";
|
|
68
66
|
import { getDefinitionKind } from "./brand.js";
|
|
69
67
|
import {
|
|
@@ -96,6 +94,15 @@ export interface LoadAgentProjectOptions {
|
|
|
96
94
|
|
|
97
95
|
type ImportModule = (absolutePath: string) => Promise<Record<string, unknown>>;
|
|
98
96
|
|
|
97
|
+
async function defaultImportModule(
|
|
98
|
+
absolutePath: string
|
|
99
|
+
): Promise<Record<string, unknown>> {
|
|
100
|
+
return (await import(pathToFileURL(absolutePath).href)) as Record<
|
|
101
|
+
string,
|
|
102
|
+
unknown
|
|
103
|
+
>;
|
|
104
|
+
}
|
|
105
|
+
|
|
99
106
|
interface DiscoveryContext {
|
|
100
107
|
rootDir: string;
|
|
101
108
|
diagnostics: Diagnostic[];
|
|
@@ -275,7 +282,7 @@ export async function loadAgentProject(
|
|
|
275
282
|
const ctx: DiscoveryContext = {
|
|
276
283
|
rootDir,
|
|
277
284
|
diagnostics,
|
|
278
|
-
importModule: options.importModule ??
|
|
285
|
+
importModule: options.importModule ?? defaultImportModule,
|
|
279
286
|
};
|
|
280
287
|
|
|
281
288
|
const name = (await readPackageName(rootDir)) ?? basename(rootDir);
|
|
@@ -1998,6 +2005,9 @@ export function projectInfo(project: AgentProject): AgentProjectInfo {
|
|
|
1998
2005
|
if (meta?.githubWebhookEvents !== undefined) {
|
|
1999
2006
|
info.githubWebhookEvents = meta.githubWebhookEvents;
|
|
2000
2007
|
}
|
|
2008
|
+
if (meta?.originWebhookEvents !== undefined) {
|
|
2009
|
+
info.originWebhookEvents = meta.originWebhookEvents;
|
|
2010
|
+
}
|
|
2001
2011
|
if (meta?.slackChannelPosts !== undefined) {
|
|
2002
2012
|
info.slackChannelPosts = meta.slackChannelPosts;
|
|
2003
2013
|
}
|
|
@@ -96,6 +96,7 @@ export const AUTHORING_ENTRY_FILES: ReadonlyArray<
|
|
|
96
96
|
["channels", "channels.js"],
|
|
97
97
|
["channels/slack", "channels/slack/index.js"],
|
|
98
98
|
["channels/github", "channels/github/index.js"],
|
|
99
|
+
["channels/origin", "channels/origin/index.js"],
|
|
99
100
|
["skills", "skills.js"],
|
|
100
101
|
["schedules", "schedules.js"],
|
|
101
102
|
["reminders", "reminders.js"],
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Unified entry for dispatching agent-serve triggers from an external ingress
|
|
3
|
-
* (e.g. the Cursor backend GitHub webhook).
|
|
4
|
-
* `handleAutomationTrigger
|
|
3
|
+
* (e.g. the Cursor backend GitHub webhook or Origin cursor-internal tap).
|
|
4
|
+
* Mirrors Automations' `handleAutomationTrigger`.
|
|
5
5
|
*
|
|
6
6
|
* Callers must authenticate the delivery before invoking this (the backend
|
|
7
|
-
* verifies GitHub HMAC at `/github_webhook`
|
|
8
|
-
*
|
|
7
|
+
* verifies GitHub HMAC at `/github_webhook` and Origin v1ed at the
|
|
8
|
+
* cursor-internal app). This fan-out does not re-check signatures — same
|
|
9
|
+
* trust model as Bugbot after `verifyGithubRequest`.
|
|
9
10
|
*
|
|
10
11
|
* Each agent's `onPullRequest` / `onComment` / … hooks decide whether to run.
|
|
11
12
|
*/
|
|
@@ -15,6 +16,12 @@ import {
|
|
|
15
16
|
getGitHubChannelOptions,
|
|
16
17
|
} from "../channels/github/github-channel.js";
|
|
17
18
|
import type { GitHubChannelOptions } from "../channels/github/types.js";
|
|
19
|
+
import {
|
|
20
|
+
dispatchOriginWebhook,
|
|
21
|
+
getOriginChannelOptions,
|
|
22
|
+
parseOriginWebhookEnvelope,
|
|
23
|
+
} from "../channels/origin/origin-channel.js";
|
|
24
|
+
import type { OriginChannelOptions } from "../channels/origin/types.js";
|
|
18
25
|
import type { ChannelHandlerArgs } from "../types.js";
|
|
19
26
|
|
|
20
27
|
export interface AgentServeGitHubTriggerTarget {
|
|
@@ -35,7 +42,22 @@ export interface AgentServeGitHubTriggerEvent {
|
|
|
35
42
|
targets: AgentServeGitHubTriggerTarget[];
|
|
36
43
|
}
|
|
37
44
|
|
|
38
|
-
export
|
|
45
|
+
export interface AgentServeOriginTriggerTarget {
|
|
46
|
+
slug: string;
|
|
47
|
+
options: OriginChannelOptions;
|
|
48
|
+
args: ChannelHandlerArgs;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface AgentServeOriginTriggerEvent {
|
|
52
|
+
type: "origin";
|
|
53
|
+
/** Origin envelope JSON (signature already verified by the caller). */
|
|
54
|
+
bodyText: string;
|
|
55
|
+
targets: AgentServeOriginTriggerTarget[];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export type AgentServeTriggerEvent =
|
|
59
|
+
| AgentServeGitHubTriggerEvent
|
|
60
|
+
| AgentServeOriginTriggerEvent;
|
|
39
61
|
|
|
40
62
|
export interface AgentServeTriggerTargetResult {
|
|
41
63
|
slug: string;
|
|
@@ -78,17 +100,46 @@ export function collectGitHubTriggerTargets(input: {
|
|
|
78
100
|
}
|
|
79
101
|
|
|
80
102
|
/**
|
|
81
|
-
*
|
|
103
|
+
* Build fan-out targets from mounted agent projects that export an origin
|
|
104
|
+
* channel created via {@link originChannel}.
|
|
105
|
+
*/
|
|
106
|
+
export function collectOriginTriggerTargets(input: {
|
|
107
|
+
mounts: Array<{
|
|
108
|
+
slug: string;
|
|
109
|
+
channels: Array<{ id: string; definition: object }>;
|
|
110
|
+
buildHandlerArgs: (channelId: string) => ChannelHandlerArgs;
|
|
111
|
+
}>;
|
|
112
|
+
}): AgentServeOriginTriggerTarget[] {
|
|
113
|
+
const targets: AgentServeOriginTriggerTarget[] = [];
|
|
114
|
+
for (const mount of input.mounts) {
|
|
115
|
+
for (const channel of mount.channels) {
|
|
116
|
+
const options = getOriginChannelOptions(channel.definition);
|
|
117
|
+
if (options === undefined) {
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
targets.push({
|
|
121
|
+
slug: mount.slug,
|
|
122
|
+
options,
|
|
123
|
+
args: mount.buildHandlerArgs(channel.id),
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return targets;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Dispatch an agent-serve trigger. GitHub and Origin webhook fan-out.
|
|
82
132
|
*/
|
|
83
133
|
export async function handleAgentServeTrigger(
|
|
84
134
|
event: AgentServeTriggerEvent
|
|
85
135
|
): Promise<AgentServeTriggerResult> {
|
|
86
136
|
switch (event.type) {
|
|
87
|
-
// TODO: Add support for other event types (e.g. Linear, Slack, etc.).
|
|
88
137
|
case "github":
|
|
89
138
|
return handleAgentServeGitHubTrigger(event);
|
|
139
|
+
case "origin":
|
|
140
|
+
return handleAgentServeOriginTrigger(event);
|
|
90
141
|
default: {
|
|
91
|
-
const _: never = event
|
|
142
|
+
const _: never = event;
|
|
92
143
|
throw new Error(
|
|
93
144
|
`handleAgentServeTrigger: unknown event type: ${String(_)}`
|
|
94
145
|
);
|
|
@@ -133,17 +184,7 @@ async function handleAgentServeGitHubTrigger(
|
|
|
133
184
|
deliveryId: event.deliveryId,
|
|
134
185
|
args: target.args,
|
|
135
186
|
});
|
|
136
|
-
|
|
137
|
-
try {
|
|
138
|
-
body = await response.json();
|
|
139
|
-
} catch {
|
|
140
|
-
body = { ok: false, error: "invalid_response_json" };
|
|
141
|
-
}
|
|
142
|
-
targets.push({
|
|
143
|
-
slug: target.slug,
|
|
144
|
-
status: response.status,
|
|
145
|
-
body,
|
|
146
|
-
});
|
|
187
|
+
targets.push(await triggerTargetResult(target.slug, response));
|
|
147
188
|
}
|
|
148
189
|
|
|
149
190
|
return {
|
|
@@ -152,3 +193,72 @@ async function handleAgentServeGitHubTrigger(
|
|
|
152
193
|
targets,
|
|
153
194
|
};
|
|
154
195
|
}
|
|
196
|
+
|
|
197
|
+
async function handleAgentServeOriginTrigger(
|
|
198
|
+
event: AgentServeOriginTriggerEvent
|
|
199
|
+
): Promise<AgentServeTriggerResult> {
|
|
200
|
+
let payload: unknown;
|
|
201
|
+
try {
|
|
202
|
+
payload = JSON.parse(event.bodyText) as unknown;
|
|
203
|
+
} catch {
|
|
204
|
+
return {
|
|
205
|
+
ok: false,
|
|
206
|
+
event: null,
|
|
207
|
+
targets: [
|
|
208
|
+
{
|
|
209
|
+
slug: "",
|
|
210
|
+
status: 400,
|
|
211
|
+
body: { ok: false, error: "invalid_json" },
|
|
212
|
+
},
|
|
213
|
+
],
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const envelope = parseOriginWebhookEnvelope(payload);
|
|
218
|
+
if (envelope === null) {
|
|
219
|
+
return {
|
|
220
|
+
ok: false,
|
|
221
|
+
event: null,
|
|
222
|
+
targets: [
|
|
223
|
+
{
|
|
224
|
+
slug: "",
|
|
225
|
+
status: 400,
|
|
226
|
+
body: { ok: false, error: "invalid_origin_payload" },
|
|
227
|
+
},
|
|
228
|
+
],
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const targets: AgentServeTriggerTargetResult[] = [];
|
|
233
|
+
for (const target of event.targets) {
|
|
234
|
+
const response = await dispatchOriginWebhook({
|
|
235
|
+
options: target.options,
|
|
236
|
+
envelope,
|
|
237
|
+
args: target.args,
|
|
238
|
+
});
|
|
239
|
+
targets.push(await triggerTargetResult(target.slug, response));
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
return {
|
|
243
|
+
ok: true,
|
|
244
|
+
event: envelope.event.type,
|
|
245
|
+
targets,
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
async function triggerTargetResult(
|
|
250
|
+
slug: string,
|
|
251
|
+
response: Response
|
|
252
|
+
): Promise<AgentServeTriggerTargetResult> {
|
|
253
|
+
let body: unknown;
|
|
254
|
+
try {
|
|
255
|
+
body = await response.json();
|
|
256
|
+
} catch {
|
|
257
|
+
body = { ok: false, error: "invalid_response_json" };
|
|
258
|
+
}
|
|
259
|
+
return {
|
|
260
|
+
slug,
|
|
261
|
+
status: response.status,
|
|
262
|
+
body,
|
|
263
|
+
};
|
|
264
|
+
}
|