@cursor/july 0.1.1 → 0.1.2
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 +24 -2
- package/README.md +25 -15
- package/dist/bin/agent-serve.js +101 -12
- package/dist/channels/github/api.d.ts.map +1 -1
- package/dist/channels/github/api.js +31 -14
- package/dist/channels/github/cursor-account.d.ts +43 -0
- package/dist/channels/github/cursor-account.d.ts.map +1 -0
- package/dist/channels/github/cursor-account.js +95 -0
- package/dist/channels/github/github-channel.d.ts.map +1 -1
- package/dist/channels/github/github-channel.js +46 -9
- package/dist/channels/github/index.d.ts +2 -2
- package/dist/channels/github/index.js +2 -2
- package/dist/channels/github/types.d.ts +17 -0
- package/dist/channels/github/types.d.ts.map +1 -1
- package/dist/channels/slack/slack-channel.d.ts +8 -2
- package/dist/channels/slack/slack-channel.d.ts.map +1 -1
- package/dist/channels/slack/slack-channel.js +8 -0
- package/dist/channels/slack/types.d.ts +24 -3
- package/dist/channels/slack/types.d.ts.map +1 -1
- package/dist/channels/slack/types.js +15 -1
- package/dist/docs/404.html +2 -2
- package/dist/docs/ab.html +8 -8
- package/dist/docs/assets/{ab.md.COdXkces.js → ab.md.BMCZ6Hd7.js} +3 -3
- package/dist/docs/assets/{ab.md.COdXkces.lean.js → ab.md.BMCZ6Hd7.lean.js} +1 -1
- package/dist/docs/assets/{app.DqfFEmJd.js → app.Oje4vhlk.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.zwQ9RCQ7.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.BaLEdS15.js → VPLocalSearchBox.H5XZ2zCB.js} +1 -1
- package/dist/docs/assets/chunks/{theme.CZRvu_0q.js → theme.CTR_TuaE.js} +2 -2
- package/dist/docs/assets/{deployment.md.Dx1TYNk5.js → deployment.md.DTKwE15Z.js} +3 -3
- package/dist/docs/assets/{deployment.md.Dx1TYNk5.lean.js → deployment.md.DTKwE15Z.lean.js} +1 -1
- package/dist/docs/assets/{evals.md.DPZ_MAnI.js → evals.md.DAgEc_hL.js} +3 -3
- package/dist/docs/assets/{guides_agent-to-agent.md.CrtrsySy.js → guides_agent-to-agent.md.Bpzgq2Pq.js} +1 -1
- package/dist/docs/assets/{guides_cloud-runtime.md.CYlNMTNp.js → guides_cloud-runtime.md.gVzabdQL.js} +1 -1
- package/dist/docs/assets/{guides_github.md.DwbKhCeS.js → guides_github.md.DOOCpqsW.js} +11 -4
- package/dist/docs/assets/{guides_github.md.DwbKhCeS.lean.js → guides_github.md.DOOCpqsW.lean.js} +1 -1
- package/dist/docs/assets/{guides_human-in-the-loop.md.Dvuctx7s.js → guides_human-in-the-loop.md.DlUqsp1S.js} +2 -2
- package/dist/docs/assets/{guides_slack.md.bv41fHfW.js → guides_slack.md.CCwqHvSV.js} +4 -4
- package/dist/docs/assets/{guides_slack.md.bv41fHfW.lean.js → guides_slack.md.CCwqHvSV.lean.js} +1 -1
- package/dist/docs/assets/{guides_webhooks.md.hFTik3lf.js → guides_webhooks.md.B1EswtUu.js} +2 -2
- package/dist/docs/assets/index.md.m81y7TY7.js +20 -0
- package/dist/docs/assets/{index.md.BPKcj5AI.lean.js → index.md.m81y7TY7.lean.js} +1 -1
- package/dist/docs/assets/quickstart.md.CfU8_uTC.js +192 -0
- package/dist/docs/assets/quickstart.md.CfU8_uTC.lean.js +1 -0
- package/dist/docs/assets/{reference_agent-config.md.Bpd7HQwf.js → reference_agent-config.md.DrW2JUM8.js} +4 -4
- package/dist/docs/assets/{reference_agent-config.md.Bpd7HQwf.lean.js → reference_agent-config.md.DrW2JUM8.lean.js} +1 -1
- package/dist/docs/assets/{reference_channels.md.D7JTR03W.js → reference_channels.md.DdmiKgqf.js} +4 -4
- package/dist/docs/assets/{reference_channels.md.D7JTR03W.lean.js → reference_channels.md.DdmiKgqf.lean.js} +1 -1
- package/dist/docs/assets/{reference_connections.md.C3vNH_DE.js → reference_connections.md.zaEYCLHT.js} +1 -1
- package/dist/docs/assets/{reference_hooks.md.BCEc3MyM.js → reference_hooks.md.DyLVfE1O.js} +1 -1
- package/dist/docs/assets/{reference_hooks.md.BCEc3MyM.lean.js → reference_hooks.md.DyLVfE1O.lean.js} +1 -1
- package/dist/docs/assets/{reference_http-api.md.DBAahtdz.js → reference_http-api.md.Dx_nmDG6.js} +1 -1
- package/dist/docs/assets/{reference_instructions.md.BC05LEQ8.js → reference_instructions.md.CgoV-YEb.js} +9 -7
- package/dist/docs/assets/{reference_instructions.md.BC05LEQ8.lean.js → reference_instructions.md.CgoV-YEb.lean.js} +1 -1
- package/dist/docs/assets/{reference_schedules.md.D7qijxLk.js → reference_schedules.md.w_F2mXB6.js} +2 -2
- package/dist/docs/assets/{reference_skills.md.VQnlBT3Q.js → reference_skills.md.B_jHN7JL.js} +3 -3
- package/dist/docs/assets/{reference_skills.md.VQnlBT3Q.lean.js → reference_skills.md.B_jHN7JL.lean.js} +1 -1
- package/dist/docs/assets/{reference_subagents.md.CIRAVcPK.js → reference_subagents.md.zWAMNfi1.js} +1 -1
- package/dist/docs/assets/{reference_tools.md.DF5kwlt0.js → reference_tools.md.CqgJroI0.js} +2 -2
- package/dist/docs/assets/scaffolding-agents.md.C3pTrmoE.js +1 -0
- package/dist/docs/assets/scaffolding-agents.md.C3pTrmoE.lean.js +1 -0
- package/dist/docs/assets/storage.md.CVnInNiN.js +17 -0
- package/dist/docs/assets/storage.md.CVnInNiN.lean.js +1 -0
- package/dist/docs/building-with-agents.html +4 -4
- package/dist/docs/concepts.html +4 -4
- package/dist/docs/deployment.html +7 -7
- package/dist/docs/evals.html +7 -7
- package/dist/docs/guides/agent-to-agent.html +6 -6
- package/dist/docs/guides/cloud-runtime.html +5 -5
- package/dist/docs/guides/github.html +14 -7
- package/dist/docs/guides/human-in-the-loop.html +6 -6
- package/dist/docs/guides/slack.html +8 -8
- package/dist/docs/guides/webhooks.html +6 -6
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +5 -5
- package/dist/docs/index.html +7 -7
- package/dist/docs/quickstart.html +180 -23
- package/dist/docs/reference/agent-config.html +7 -7
- package/dist/docs/reference/channels.html +8 -8
- package/dist/docs/reference/cli.html +4 -4
- package/dist/docs/reference/connections.html +5 -5
- package/dist/docs/reference/hooks.html +5 -5
- package/dist/docs/reference/http-api.html +6 -6
- package/dist/docs/reference/instructions.html +13 -11
- package/dist/docs/reference/playground.html +4 -4
- package/dist/docs/reference/project-layout.html +4 -4
- package/dist/docs/reference/schedules.html +7 -7
- package/dist/docs/reference/sessions.html +4 -4
- package/dist/docs/reference/skills.html +6 -6
- package/dist/docs/reference/subagents.html +6 -6
- package/dist/docs/reference/tools.html +7 -7
- package/dist/docs/scaffolding-agents.html +5 -5
- package/dist/docs/storage.html +41 -0
- package/dist/docs/troubleshooting.html +4 -4
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/internal/cli-deploy.d.ts +52 -0
- package/dist/internal/cli-deploy.d.ts.map +1 -0
- package/dist/internal/cli-deploy.js +731 -0
- package/dist/internal/cursor/backend-client.d.ts +10 -1
- package/dist/internal/cursor/backend-client.d.ts.map +1 -1
- package/dist/internal/cursor/backend-client.js +79 -1
- package/dist/internal/cursor/github-credentials.d.ts +44 -0
- package/dist/internal/cursor/github-credentials.d.ts.map +1 -0
- package/dist/internal/cursor/github-credentials.js +195 -0
- package/dist/internal/deploy-client.d.ts +176 -0
- package/dist/internal/deploy-client.d.ts.map +1 -0
- package/dist/internal/deploy-client.js +375 -0
- package/dist/internal/discovery.d.ts.map +1 -1
- package/dist/internal/discovery.js +73 -5
- package/dist/internal/distribution.d.ts.map +1 -1
- package/dist/internal/distribution.js +1 -0
- package/dist/internal/eval-run-store.d.ts +22 -3
- package/dist/internal/eval-run-store.d.ts.map +1 -1
- package/dist/internal/eval-run-store.js +37 -19
- package/dist/internal/handleAgentServeTrigger.d.ts.map +1 -1
- package/dist/internal/handleAgentServeTrigger.js +10 -12
- package/dist/internal/host-platforms.d.ts +7 -2
- package/dist/internal/host-platforms.d.ts.map +1 -1
- package/dist/internal/host-platforms.js +15 -10
- package/dist/internal/hosting.d.ts +37 -0
- package/dist/internal/hosting.d.ts.map +1 -0
- package/dist/internal/hosting.js +67 -0
- package/dist/internal/reminder-runner.d.ts +7 -0
- package/dist/internal/reminder-runner.d.ts.map +1 -1
- package/dist/internal/reminder-runner.js +50 -6
- package/dist/internal/reminder-store.d.ts +2 -0
- package/dist/internal/reminder-store.d.ts.map +1 -1
- package/dist/internal/reminder-store.js +18 -0
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +173 -42
- package/dist/internal/session-engine.d.ts +49 -0
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +246 -17
- package/dist/internal/storage-coordinator.d.ts +139 -0
- package/dist/internal/storage-coordinator.d.ts.map +1 -0
- package/dist/internal/storage-coordinator.js +499 -0
- package/dist/playground/assets/cursor-icons-outline-BxTT_FVJ.woff2 +0 -0
- package/dist/playground/assets/index-B1Qc9h2u.css +1 -0
- package/dist/playground/assets/{index-FlWjhg3x.js → index-CpDYCj8W.js} +42 -42
- package/dist/playground/index.html +2 -2
- package/dist/storage.d.ts +204 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +153 -0
- package/dist/types.d.ts +44 -3
- package/dist/types.d.ts.map +1 -1
- package/docs/README.md +3 -2
- package/docs/guides/github.md +43 -8
- package/docs/guides/slack.md +1 -1
- package/docs/quickstart.md +329 -51
- package/docs/reference/instructions.md +8 -6
- package/docs/scaffolding-agents.md +1 -1
- package/docs/storage.md +98 -0
- package/package.json +8 -1
- package/skills/github/SKILL.md +9 -1
- package/src/bin/agent-serve.ts +139 -0
- package/src/channels/github/api.ts +42 -23
- package/src/channels/github/cursor-account.ts +165 -0
- package/src/channels/github/github-channel.ts +66 -6
- package/src/channels/github/index.ts +2 -2
- package/src/channels/github/types.ts +19 -0
- package/src/channels/slack/slack-channel.ts +17 -3
- package/src/channels/slack/types.ts +44 -3
- package/src/index.ts +13 -0
- package/src/internal/cli-deploy.ts +940 -0
- package/src/internal/cursor/backend-client.ts +103 -1
- package/src/internal/cursor/github-credentials.ts +248 -0
- package/src/internal/deploy-client.ts +591 -0
- package/src/internal/discovery.ts +88 -1
- package/src/internal/distribution.ts +1 -0
- package/src/internal/eval-run-store.ts +48 -19
- package/src/internal/handleAgentServeTrigger.ts +10 -12
- package/src/internal/host-platforms.ts +28 -11
- package/src/internal/hosting.ts +77 -0
- package/src/internal/reminder-runner.ts +50 -6
- package/src/internal/reminder-store.ts +21 -0
- package/src/internal/server.ts +213 -27
- package/src/internal/session-engine.ts +285 -7
- package/src/internal/storage-coordinator.ts +615 -0
- package/src/storage.ts +325 -0
- package/src/types.ts +40 -2
- package/dist/docs/assets/chunks/@localSearchIndexroot.CcVk1uKq.js +0 -1
- package/dist/docs/assets/index.md.BPKcj5AI.js +0 -20
- package/dist/docs/assets/quickstart.md.tVPiGK_L.js +0 -35
- package/dist/docs/assets/quickstart.md.tVPiGK_L.lean.js +0 -1
- package/dist/docs/assets/scaffolding-agents.md.CyYfWGdc.js +0 -1
- package/dist/docs/assets/scaffolding-agents.md.CyYfWGdc.lean.js +0 -1
- package/dist/playground/assets/cursor-icons-outline-oY2V_mvK.woff2 +0 -0
- package/dist/playground/assets/index-1K-hG-7p.css +0 -1
- /package/dist/docs/assets/{evals.md.DPZ_MAnI.lean.js → evals.md.DAgEc_hL.lean.js} +0 -0
- /package/dist/docs/assets/{guides_agent-to-agent.md.CrtrsySy.lean.js → guides_agent-to-agent.md.Bpzgq2Pq.lean.js} +0 -0
- /package/dist/docs/assets/{guides_cloud-runtime.md.CYlNMTNp.lean.js → guides_cloud-runtime.md.gVzabdQL.lean.js} +0 -0
- /package/dist/docs/assets/{guides_human-in-the-loop.md.Dvuctx7s.lean.js → guides_human-in-the-loop.md.DlUqsp1S.lean.js} +0 -0
- /package/dist/docs/assets/{guides_webhooks.md.hFTik3lf.lean.js → guides_webhooks.md.B1EswtUu.lean.js} +0 -0
- /package/dist/docs/assets/{reference_connections.md.C3vNH_DE.lean.js → reference_connections.md.zaEYCLHT.lean.js} +0 -0
- /package/dist/docs/assets/{reference_http-api.md.DBAahtdz.lean.js → reference_http-api.md.Dx_nmDG6.lean.js} +0 -0
- /package/dist/docs/assets/{reference_schedules.md.D7qijxLk.lean.js → reference_schedules.md.w_F2mXB6.lean.js} +0 -0
- /package/dist/docs/assets/{reference_subagents.md.CIRAVcPK.lean.js → reference_subagents.md.zWAMNfi1.lean.js} +0 -0
- /package/dist/docs/assets/{reference_tools.md.DF5kwlt0.lean.js → reference_tools.md.CqgJroI0.lean.js} +0 -0
package/src/internal/server.ts
CHANGED
|
@@ -14,12 +14,21 @@ import {
|
|
|
14
14
|
} from "node:http";
|
|
15
15
|
import type { AddressInfo } from "node:net";
|
|
16
16
|
import { join } from "node:path";
|
|
17
|
+
import {
|
|
18
|
+
type CursorGithubRepoScope,
|
|
19
|
+
createCursorAccountGithubTokenResolver,
|
|
20
|
+
type GithubCursorAccountRuntime,
|
|
21
|
+
getGithubCursorAccountRuntime,
|
|
22
|
+
parseCursorGithubRepoScope,
|
|
23
|
+
resolveCursorGithubPermissions,
|
|
24
|
+
} from "../channels/github/cursor-account.js";
|
|
17
25
|
import { findGitHubChannelTargets } from "../channels/github/forward.js";
|
|
18
26
|
import {
|
|
19
27
|
dispatchCursorSlackEnvelope,
|
|
20
28
|
getSlackCursorAccountRuntime,
|
|
21
29
|
type SlackCursorAccountRuntime,
|
|
22
30
|
} from "../channels/slack/cursor-account.js";
|
|
31
|
+
import { assertSlackCursorAgentName } from "../channels/slack/types.js";
|
|
23
32
|
import { allowAll, bearerAuth, localDevStrict } from "../channels.js";
|
|
24
33
|
import type {
|
|
25
34
|
AgentProject,
|
|
@@ -45,6 +54,7 @@ import {
|
|
|
45
54
|
resolveApiKey,
|
|
46
55
|
SIGN_IN_HINT,
|
|
47
56
|
} from "./cursor/credentials.js";
|
|
57
|
+
import { CursorGithubCredentialProvider } from "./cursor/github-credentials.js";
|
|
48
58
|
import {
|
|
49
59
|
CursorEventRelay,
|
|
50
60
|
formatCursorScmEventLog,
|
|
@@ -76,7 +86,7 @@ import {
|
|
|
76
86
|
collectGitHubTriggerTargets,
|
|
77
87
|
handleAgentServeTrigger,
|
|
78
88
|
} from "./handleAgentServeTrigger.js";
|
|
79
|
-
import { warmupHostGitHubAuth } from "./host-platforms.js";
|
|
89
|
+
import { createHostPlatforms, warmupHostGitHubAuth } from "./host-platforms.js";
|
|
80
90
|
import {
|
|
81
91
|
buildHttpChannelRoutes,
|
|
82
92
|
errorResponse,
|
|
@@ -187,9 +197,16 @@ export async function startServer(
|
|
|
187
197
|
// agentkit_enabled gate applies to every turn.
|
|
188
198
|
process.env.CURSOR_AGENTKIT_VERSION ??= packageVersion();
|
|
189
199
|
|
|
200
|
+
const cursorGithubTargets = collectCursorGithubTargets(mounts);
|
|
201
|
+
const cursorGithubConfig = resolveCursorGithubEventConfig({
|
|
202
|
+
configured: options.cursorEvents,
|
|
203
|
+
targets: cursorGithubTargets,
|
|
204
|
+
});
|
|
205
|
+
const effectiveCursorEvents = cursorGithubConfig.cursorEvents;
|
|
206
|
+
|
|
190
207
|
// One resolution for every Cursor credential consumer (SDK runner, account
|
|
191
|
-
// MCP bridge, SCM event relay): explicit option →
|
|
192
|
-
// `agent-serve login`.
|
|
208
|
+
// MCP bridge, SCM event relay, GitHub credentials): explicit option →
|
|
209
|
+
// CURSOR_API_KEY → stored `agent-serve login`.
|
|
193
210
|
const accountKey = await resolveApiKey(
|
|
194
211
|
options.apiKey === undefined ? {} : { apiKey: options.apiKey }
|
|
195
212
|
);
|
|
@@ -198,9 +215,53 @@ export async function startServer(
|
|
|
198
215
|
// `cursorEvents` cannot work signed out. Require the credential before any
|
|
199
216
|
// slow or stateful startup work (playground build, channel onStart, cron).
|
|
200
217
|
const cursorEventsAuth =
|
|
201
|
-
|
|
218
|
+
effectiveCursorEvents === undefined
|
|
202
219
|
? undefined
|
|
203
|
-
: requireCursorEventsAuth(
|
|
220
|
+
: requireCursorEventsAuth(effectiveCursorEvents, accountKey);
|
|
221
|
+
|
|
222
|
+
let cursorGithubCredentials: CursorGithubCredentialProvider | undefined;
|
|
223
|
+
if (cursorGithubConfig.scope !== undefined) {
|
|
224
|
+
if (cursorEventsAuth === undefined) {
|
|
225
|
+
throw new Error(
|
|
226
|
+
"githubChannel({ cursorAccount: true }) could not resolve Cursor event authentication."
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
if (options.allowAnonymous === true) {
|
|
230
|
+
throw new Error(
|
|
231
|
+
"githubChannel({ cursorAccount: true }) cannot be served with --allow-anonymous because admitted callers could use the signed-in account's GitHub access."
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
if (cursorGithubConfig.scope.permissions === "contents-write") {
|
|
235
|
+
logger(
|
|
236
|
+
'[agent-serve] warning: Cursor GitHub credentials include contents:write — the host holds a push-capable token shared with model-driven tools and untrusted webhook content; prefer permissions: "pr-write" unless this agent must push code'
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
const provider = new CursorGithubCredentialProvider({
|
|
240
|
+
client: new CursorBackendClient({
|
|
241
|
+
backendUrl: cursorEventsAuth.baseUrl,
|
|
242
|
+
apiKey: cursorEventsAuth.apiKey,
|
|
243
|
+
logger,
|
|
244
|
+
}),
|
|
245
|
+
scope: cursorGithubConfig.scope,
|
|
246
|
+
logger,
|
|
247
|
+
});
|
|
248
|
+
cursorGithubCredentials = provider;
|
|
249
|
+
for (const target of cursorGithubTargets) {
|
|
250
|
+
target.accountRuntime.credentials.bind(() => provider.getToken());
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
const resolvedCursorGithubCredentials = cursorGithubCredentials;
|
|
254
|
+
const hostPlatforms = createHostPlatforms(
|
|
255
|
+
resolvedCursorGithubCredentials === undefined
|
|
256
|
+
? {}
|
|
257
|
+
: {
|
|
258
|
+
githubCredentials: {
|
|
259
|
+
token: createCursorAccountGithubTokenResolver(() =>
|
|
260
|
+
resolvedCursorGithubCredentials.getToken()
|
|
261
|
+
),
|
|
262
|
+
},
|
|
263
|
+
}
|
|
264
|
+
);
|
|
204
265
|
|
|
205
266
|
if (playground) {
|
|
206
267
|
// Auto-build dist/playground when missing (monorepo / source checkout).
|
|
@@ -267,16 +328,42 @@ export async function startServer(
|
|
|
267
328
|
const baseStateRoot =
|
|
268
329
|
options.stateRoot ?? join(project.rootDir, ".agent-serve");
|
|
269
330
|
const stateRoot = slug === "" ? baseStateRoot : join(baseStateRoot, slug);
|
|
270
|
-
const engine = new SessionEngine({
|
|
331
|
+
const engine = new SessionEngine({
|
|
332
|
+
project,
|
|
333
|
+
stateRoot,
|
|
334
|
+
runner,
|
|
335
|
+
logger,
|
|
336
|
+
platforms: hostPlatforms,
|
|
337
|
+
});
|
|
338
|
+
// Rehydrate sessions from the authored storage sink before any
|
|
339
|
+
// channel or route can address them (continuation tokens must resolve).
|
|
340
|
+
await engine.restoreStoredSessions();
|
|
341
|
+
|
|
271
342
|
if (!githubAuthWarmed) {
|
|
272
343
|
// Soft ambient GitHub auth check before channel onStart (which may call
|
|
273
344
|
// host.github). Missing auth is a warning only — serve still starts.
|
|
274
|
-
await warmupHostGitHubAuth({
|
|
345
|
+
await warmupHostGitHubAuth({
|
|
346
|
+
logger,
|
|
347
|
+
github: engine.host.github,
|
|
348
|
+
...(cursorGithubCredentials === undefined
|
|
349
|
+
? {}
|
|
350
|
+
: { authSource: "cursor-account" }),
|
|
351
|
+
});
|
|
275
352
|
githubAuthWarmed = true;
|
|
276
353
|
}
|
|
277
354
|
const scheduleRunner = new ScheduleRunner(engine, project, logger);
|
|
278
355
|
const reminderRunner = new ReminderRunner(engine, logger);
|
|
279
|
-
const evalRuns = new EvalRunStore(
|
|
356
|
+
const evalRuns = new EvalRunStore(
|
|
357
|
+
project.rootDir,
|
|
358
|
+
logger,
|
|
359
|
+
// defineStorage fallback for playground eval history; explicit
|
|
360
|
+
// `evals.config.ts` persistRuns still wins inside the store.
|
|
361
|
+
engine.storage?.asEvalRunPersistence()
|
|
362
|
+
);
|
|
363
|
+
// Eval history restores with the same startup step as sessions (reads
|
|
364
|
+
// also hydrate lazily, but doing it here surfaces store problems at
|
|
365
|
+
// boot and makes /v1/dev/evals complete from the first request).
|
|
366
|
+
await evalRuns.hydrate();
|
|
280
367
|
engine.setReminders({
|
|
281
368
|
create: (input) => reminderRunner.create(input),
|
|
282
369
|
list: (filter) => reminderRunner.list(filter),
|
|
@@ -486,15 +573,6 @@ export async function startServer(
|
|
|
486
573
|
});
|
|
487
574
|
}
|
|
488
575
|
|
|
489
|
-
// Cursor SCM events relay (opt-in: serve({ cursorEvents }) / --cursor-events).
|
|
490
|
-
const cursorEventRelay = startCursorEventRelay({
|
|
491
|
-
options,
|
|
492
|
-
mounts,
|
|
493
|
-
auth: cursorEventsAuth,
|
|
494
|
-
logger,
|
|
495
|
-
collectTriggerTargets,
|
|
496
|
-
});
|
|
497
|
-
|
|
498
576
|
// Cursor Slack relay: automatic when a mounted agent authored
|
|
499
577
|
// `slackChannel({ cursorAccount: true })`. Inbound rides the account's
|
|
500
578
|
// Slack connection (`/v0/slack-events`); the classic Socket-Mode path is
|
|
@@ -505,6 +583,24 @@ export async function startServer(
|
|
|
505
583
|
accountKey,
|
|
506
584
|
logger,
|
|
507
585
|
});
|
|
586
|
+
try {
|
|
587
|
+
await cursorGithubCredentials?.start();
|
|
588
|
+
} catch (error) {
|
|
589
|
+
await cursorSlackRelay?.stop();
|
|
590
|
+
throw error;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
// Cursor SCM events relay (opt-in: serve({ cursorEvents }) / --cursor-events).
|
|
594
|
+
const cursorEventRelay = startCursorEventRelay({
|
|
595
|
+
config: effectiveCursorEvents,
|
|
596
|
+
stateRoot: options.stateRoot,
|
|
597
|
+
mounts,
|
|
598
|
+
auth: cursorEventsAuth,
|
|
599
|
+
logger,
|
|
600
|
+
collectTriggerTargets,
|
|
601
|
+
cursorAccountOnly:
|
|
602
|
+
options.cursorEvents === undefined && cursorGithubTargets.length > 0,
|
|
603
|
+
});
|
|
508
604
|
|
|
509
605
|
const server = createServer((req, res) => {
|
|
510
606
|
void handleRequest(router, req, res, logger);
|
|
@@ -512,8 +608,15 @@ export async function startServer(
|
|
|
512
608
|
|
|
513
609
|
const host = options.host ?? "127.0.0.1";
|
|
514
610
|
const port = options.port ?? 3000;
|
|
515
|
-
|
|
516
|
-
|
|
611
|
+
try {
|
|
612
|
+
server.listen(port, host);
|
|
613
|
+
await once(server, "listening");
|
|
614
|
+
} catch (error) {
|
|
615
|
+
await cursorEventRelay?.stop();
|
|
616
|
+
await cursorSlackRelay?.stop();
|
|
617
|
+
cursorGithubCredentials?.stop();
|
|
618
|
+
throw error;
|
|
619
|
+
}
|
|
517
620
|
const address = server.address() as AddressInfo;
|
|
518
621
|
const displayHost = host === "0.0.0.0" || host === "::" ? "127.0.0.1" : host;
|
|
519
622
|
const url = `http://${displayHost}:${address.port}`;
|
|
@@ -645,7 +748,11 @@ export async function startServer(
|
|
|
645
748
|
}
|
|
646
749
|
server.close();
|
|
647
750
|
server.closeAllConnections();
|
|
648
|
-
|
|
751
|
+
try {
|
|
752
|
+
await Promise.all(runtimes.map((runtime) => runtime.engine.close()));
|
|
753
|
+
} finally {
|
|
754
|
+
cursorGithubCredentials?.stop();
|
|
755
|
+
}
|
|
649
756
|
},
|
|
650
757
|
};
|
|
651
758
|
if (playgroundDev?.url !== undefined) {
|
|
@@ -1233,14 +1340,16 @@ function requireCursorEventsAuth(
|
|
|
1233
1340
|
* no github channel) warn and leave the relay off — serve still starts.
|
|
1234
1341
|
*/
|
|
1235
1342
|
function startCursorEventRelay(input: {
|
|
1236
|
-
|
|
1343
|
+
config: ServeOptions["cursorEvents"];
|
|
1344
|
+
stateRoot: string | undefined;
|
|
1237
1345
|
mounts: AgentMount[];
|
|
1238
1346
|
auth: CursorEventsAuth | undefined;
|
|
1239
1347
|
logger: (line: string) => void;
|
|
1240
1348
|
collectTriggerTargets: () => ReturnType<typeof collectGitHubTriggerTargets>;
|
|
1349
|
+
cursorAccountOnly: boolean;
|
|
1241
1350
|
}): CursorEventRelay | undefined {
|
|
1242
|
-
const {
|
|
1243
|
-
|
|
1351
|
+
const { config, stateRoot, mounts, auth, logger, collectTriggerTargets } =
|
|
1352
|
+
input;
|
|
1244
1353
|
if (config === undefined || auth === undefined) {
|
|
1245
1354
|
return undefined;
|
|
1246
1355
|
}
|
|
@@ -1262,7 +1371,7 @@ function startCursorEventRelay(input: {
|
|
|
1262
1371
|
return undefined;
|
|
1263
1372
|
}
|
|
1264
1373
|
const baseStateRoot =
|
|
1265
|
-
|
|
1374
|
+
stateRoot ??
|
|
1266
1375
|
join(mounts[0]?.project.rootDir ?? process.cwd(), ".agent-serve");
|
|
1267
1376
|
const relay = new CursorEventRelay({
|
|
1268
1377
|
baseUrl: auth.baseUrl,
|
|
@@ -1275,12 +1384,27 @@ function startCursorEventRelay(input: {
|
|
|
1275
1384
|
// envelope — rich pullRequest meta when present for onPullRequest Zod.
|
|
1276
1385
|
dispatch: async (event) => {
|
|
1277
1386
|
if (event.provider !== "github") return;
|
|
1387
|
+
const targets = collectTriggerTargets().filter((target) => {
|
|
1388
|
+
const cursorAccount = target.options.cursorAccount;
|
|
1389
|
+
if (
|
|
1390
|
+
input.cursorAccountOnly &&
|
|
1391
|
+
cursorAccount !== true &&
|
|
1392
|
+
typeof cursorAccount !== "object"
|
|
1393
|
+
) {
|
|
1394
|
+
return false;
|
|
1395
|
+
}
|
|
1396
|
+
return typeof cursorAccount !== "object"
|
|
1397
|
+
? true
|
|
1398
|
+
: cursorAccount.repos.some(
|
|
1399
|
+
(repo) => repo.toLowerCase() === event.repo.toLowerCase()
|
|
1400
|
+
);
|
|
1401
|
+
});
|
|
1278
1402
|
const result = await handleAgentServeTrigger({
|
|
1279
1403
|
type: "github",
|
|
1280
1404
|
bodyText: JSON.stringify(scmMetadataToGitHubPayload(event)),
|
|
1281
1405
|
eventName: event.eventName,
|
|
1282
1406
|
deliveryId: event.deliveryId,
|
|
1283
|
-
targets
|
|
1407
|
+
targets,
|
|
1284
1408
|
});
|
|
1285
1409
|
const outcomes = result.targets
|
|
1286
1410
|
.map((target) => `${target.slug || "default"}:${target.status}`)
|
|
@@ -1297,6 +1421,64 @@ function startCursorEventRelay(input: {
|
|
|
1297
1421
|
return relay;
|
|
1298
1422
|
}
|
|
1299
1423
|
|
|
1424
|
+
interface CursorGithubTarget {
|
|
1425
|
+
slug: string;
|
|
1426
|
+
channelId: string;
|
|
1427
|
+
accountRuntime: GithubCursorAccountRuntime;
|
|
1428
|
+
}
|
|
1429
|
+
|
|
1430
|
+
function collectCursorGithubTargets(
|
|
1431
|
+
mounts: AgentMount[]
|
|
1432
|
+
): CursorGithubTarget[] {
|
|
1433
|
+
const targets: CursorGithubTarget[] = [];
|
|
1434
|
+
for (const mount of mounts) {
|
|
1435
|
+
for (const channel of mount.project.channels) {
|
|
1436
|
+
const accountRuntime = getGithubCursorAccountRuntime(channel.definition);
|
|
1437
|
+
if (accountRuntime !== undefined) {
|
|
1438
|
+
targets.push({
|
|
1439
|
+
slug: mount.slug,
|
|
1440
|
+
channelId: channel.id,
|
|
1441
|
+
accountRuntime,
|
|
1442
|
+
});
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
}
|
|
1446
|
+
return targets;
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1449
|
+
interface CursorGithubConfigResolution {
|
|
1450
|
+
cursorEvents: ServeOptions["cursorEvents"];
|
|
1451
|
+
scope: CursorGithubRepoScope | undefined;
|
|
1452
|
+
}
|
|
1453
|
+
|
|
1454
|
+
function resolveCursorGithubEventConfig(input: {
|
|
1455
|
+
configured: ServeOptions["cursorEvents"];
|
|
1456
|
+
targets: CursorGithubTarget[];
|
|
1457
|
+
}): CursorGithubConfigResolution {
|
|
1458
|
+
if (input.targets.length === 0) {
|
|
1459
|
+
return { cursorEvents: input.configured, scope: undefined };
|
|
1460
|
+
}
|
|
1461
|
+
const repos = [
|
|
1462
|
+
...(input.configured?.repos ?? []),
|
|
1463
|
+
...input.targets.flatMap((target) => [
|
|
1464
|
+
...(target.accountRuntime.scope?.repos ?? []),
|
|
1465
|
+
]),
|
|
1466
|
+
];
|
|
1467
|
+
const permissions = resolveCursorGithubPermissions(
|
|
1468
|
+
input.targets.map(
|
|
1469
|
+
(target) => target.accountRuntime.scope?.permissions ?? "pr-write"
|
|
1470
|
+
)
|
|
1471
|
+
);
|
|
1472
|
+
const scope = parseCursorGithubRepoScope(repos, permissions);
|
|
1473
|
+
return {
|
|
1474
|
+
cursorEvents: {
|
|
1475
|
+
...input.configured,
|
|
1476
|
+
repos: [...scope.repos],
|
|
1477
|
+
},
|
|
1478
|
+
scope,
|
|
1479
|
+
};
|
|
1480
|
+
}
|
|
1481
|
+
|
|
1300
1482
|
interface CursorSlackTarget {
|
|
1301
1483
|
runtime: MountedRuntime;
|
|
1302
1484
|
channelId: string;
|
|
@@ -1304,13 +1486,16 @@ interface CursorSlackTarget {
|
|
|
1304
1486
|
accountRuntime: SlackCursorAccountRuntime;
|
|
1305
1487
|
}
|
|
1306
1488
|
|
|
1307
|
-
/**
|
|
1489
|
+
/**
|
|
1490
|
+
* `weather-agent` → `WeatherAgent` (single-token Cursor Slack handle).
|
|
1491
|
+
* Must not contain whitespace — see {@link assertSlackCursorAgentName}.
|
|
1492
|
+
*/
|
|
1308
1493
|
function slackAgentNameFromSlug(slug: string): string {
|
|
1309
1494
|
return slug
|
|
1310
1495
|
.split(/[-_\s]+/)
|
|
1311
1496
|
.filter((word) => word.length > 0)
|
|
1312
1497
|
.map((word) => word[0].toUpperCase() + word.slice(1))
|
|
1313
|
-
.join("
|
|
1498
|
+
.join("");
|
|
1314
1499
|
}
|
|
1315
1500
|
|
|
1316
1501
|
/**
|
|
@@ -1341,6 +1526,7 @@ function collectCursorSlackTargets(
|
|
|
1341
1526
|
`slackChannel({ cursorAccount: true }) on agent "${runtime.slug || runtime.project.name}" resolved an empty agent name; set agentName.`
|
|
1342
1527
|
);
|
|
1343
1528
|
}
|
|
1529
|
+
assertSlackCursorAgentName(agentName);
|
|
1344
1530
|
const nameKey = agentName.toLowerCase();
|
|
1345
1531
|
const existing = byName.get(nameKey);
|
|
1346
1532
|
if (existing !== undefined) {
|