@cursor/july 0.1.62 → 0.1.68
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 +8 -0
- package/dist/channels/slack/channel-watch.d.ts +2 -1
- package/dist/channels/slack/channel-watch.d.ts.map +1 -1
- package/dist/channels/slack/channel-watch.js +7 -3
- package/dist/channels/slack/dispatch.d.ts +9 -0
- package/dist/channels/slack/dispatch.d.ts.map +1 -1
- package/dist/channels/slack/dispatch.js +41 -21
- package/dist/channels/slack/manifest.d.ts.map +1 -1
- package/dist/channels/slack/manifest.js +1 -0
- package/dist/channels/slack/nudge-store.d.ts +16 -0
- package/dist/channels/slack/nudge-store.d.ts.map +1 -1
- package/dist/channels/slack/nudge-store.js +53 -0
- package/dist/channels/slack/slack-channel.d.ts.map +1 -1
- package/dist/channels/slack/slack-channel.js +4 -1
- package/dist/channels/slack/types.d.ts +22 -5
- package/dist/channels/slack/types.d.ts.map +1 -1
- package/dist/docs/404.html +2 -2
- package/dist/docs/ab.html +3 -3
- package/dist/docs/assets/{app.B-biogkN.js → app.C5XUTCw9.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.DvUR3lv9.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.DZqKtFZS.js → VPLocalSearchBox.CGDTAYHY.js} +1 -1
- package/dist/docs/assets/chunks/{theme.BwC5zP2r.js → theme.lPixh250.js} +2 -2
- package/dist/docs/assets/{reference_connections.md.CSQiNzre.js → reference_connections.md.Bwswbm6H.js} +13 -3
- package/dist/docs/assets/{reference_connections.md.CSQiNzre.lean.js → reference_connections.md.Bwswbm6H.lean.js} +1 -1
- package/dist/docs/assets/{reference_tools.md.kJfJAP2m.js → reference_tools.md.Wmvb7Lob.js} +2 -2
- package/dist/docs/assets/{reference_tools.md.kJfJAP2m.lean.js → reference_tools.md.Wmvb7Lob.lean.js} +1 -1
- package/dist/docs/building-with-agents.html +3 -3
- package/dist/docs/concepts.html +3 -3
- package/dist/docs/deployment.html +3 -3
- package/dist/docs/evals.html +3 -3
- package/dist/docs/example-agents/approval-buddy.html +3 -3
- package/dist/docs/example-agents/benny.html +3 -3
- package/dist/docs/example-agents/bugbot.html +3 -3
- package/dist/docs/example-agents/codebase-wiki.html +3 -3
- package/dist/docs/example-agents/codeowners-review.html +3 -3
- package/dist/docs/example-agents/concierge.html +3 -3
- package/dist/docs/example-agents/fsd.html +3 -3
- package/dist/docs/example-agents/index.html +3 -3
- package/dist/docs/example-agents/knowledge-base.html +3 -3
- package/dist/docs/example-agents/oncall.html +3 -3
- package/dist/docs/example-agents/security-reviewer.html +3 -3
- package/dist/docs/example-agents/slack-agent.html +3 -3
- package/dist/docs/example-agents/weather-agent.html +3 -3
- package/dist/docs/guides/agent-to-agent.html +3 -3
- package/dist/docs/guides/cloud-runtime.html +3 -3
- package/dist/docs/guides/convert-automation.html +3 -3
- package/dist/docs/guides/github.html +3 -3
- package/dist/docs/guides/human-in-the-loop.html +3 -3
- package/dist/docs/guides/mcp-oauth.html +3 -3
- package/dist/docs/guides/opentelemetry.html +3 -3
- package/dist/docs/guides/slack.html +3 -3
- package/dist/docs/guides/webhooks.html +3 -3
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +3 -3
- package/dist/docs/index.html +3 -3
- package/dist/docs/quickstart.html +3 -3
- package/dist/docs/reference/agent-config.html +3 -3
- package/dist/docs/reference/artifacts.html +3 -3
- package/dist/docs/reference/channels.html +3 -3
- package/dist/docs/reference/cli.html +3 -3
- package/dist/docs/reference/connections.html +15 -5
- package/dist/docs/reference/hooks.html +3 -3
- package/dist/docs/reference/http-api.html +3 -3
- package/dist/docs/reference/instructions.html +3 -3
- package/dist/docs/reference/playground.html +3 -3
- package/dist/docs/reference/project-layout.html +3 -3
- package/dist/docs/reference/prompt.html +3 -3
- package/dist/docs/reference/schedules.html +3 -3
- package/dist/docs/reference/sessions.html +3 -3
- package/dist/docs/reference/skills.html +3 -3
- package/dist/docs/reference/subagents.html +3 -3
- package/dist/docs/reference/tools.html +5 -5
- package/dist/docs/scaffolding-agents.html +3 -3
- package/dist/docs/storage.html +3 -3
- package/dist/docs/templates/agentic-owners.html +3 -3
- package/dist/docs/templates/demo.html +3 -3
- package/dist/docs/templates/pr-autofixer.html +3 -3
- package/dist/docs/templates/security-reviewer.html +3 -3
- package/dist/docs/templates/triage.html +3 -3
- package/dist/docs/troubleshooting.html +3 -3
- package/dist/files-backends/agent-store-presigned-url.js +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/internal/advertise-tools.d.ts +74 -0
- package/dist/internal/advertise-tools.d.ts.map +1 -0
- package/dist/internal/advertise-tools.js +152 -0
- package/dist/internal/cli-deploy.d.ts.map +1 -1
- package/dist/internal/cli-deploy.js +11 -3
- package/dist/internal/cli-manifest.d.ts +19 -0
- package/dist/internal/cli-manifest.d.ts.map +1 -0
- package/dist/internal/cli-manifest.js +49 -0
- package/dist/internal/cli-slack.d.ts.map +1 -1
- package/dist/internal/cli-slack.js +9 -1
- package/dist/internal/cursor-agent-template.d.ts +9 -0
- package/dist/internal/cursor-agent-template.d.ts.map +1 -0
- package/dist/internal/cursor-agent-template.js +37 -0
- package/dist/internal/deploy-client.d.ts +8 -0
- package/dist/internal/deploy-client.d.ts.map +1 -1
- package/dist/internal/deploy-client.js +21 -3
- package/dist/internal/deploy-manifest.d.ts +85 -0
- package/dist/internal/deploy-manifest.d.ts.map +1 -0
- package/dist/internal/deploy-manifest.js +106 -0
- package/dist/internal/deployment-scm-event-stream.d.ts +113 -0
- package/dist/internal/deployment-scm-event-stream.d.ts.map +1 -0
- package/dist/internal/deployment-scm-event-stream.js +460 -0
- package/dist/internal/discovery.d.ts.map +1 -1
- package/dist/internal/discovery.js +69 -0
- package/dist/internal/init-project.d.ts.map +1 -1
- package/dist/internal/init-project.js +5 -17
- package/dist/internal/mcp-host.d.ts +18 -0
- package/dist/internal/mcp-host.d.ts.map +1 -1
- package/dist/internal/mcp-host.js +41 -5
- package/dist/internal/sdk-runner.d.ts +1 -1
- package/dist/internal/sdk-runner.d.ts.map +1 -1
- package/dist/internal/sdk-runner.js +36 -13
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +18 -0
- package/dist/internal/session-engine.d.ts +66 -0
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +430 -110
- package/dist/internal/shallow-clone.d.ts +115 -0
- package/dist/internal/shallow-clone.d.ts.map +1 -0
- package/dist/internal/shallow-clone.js +292 -0
- package/dist/internal/slack-provision-client.d.ts +2 -0
- package/dist/internal/slack-provision-client.d.ts.map +1 -1
- package/dist/internal/slack-provision-client.js +1 -0
- package/dist/internal/turn-lease-store.d.ts +44 -0
- package/dist/internal/turn-lease-store.d.ts.map +1 -0
- package/dist/internal/turn-lease-store.js +139 -0
- package/dist/internal/workspace.d.ts +12 -0
- package/dist/internal/workspace.d.ts.map +1 -1
- package/dist/internal/workspace.js +28 -0
- package/dist/playground/assets/index-CoL7xCJl.css +1 -0
- package/dist/playground/assets/index-yxs1heea.js +85 -0
- package/dist/playground/index.html +2 -2
- package/dist/storage-protocol.d.ts +122 -0
- package/dist/storage-protocol.d.ts.map +1 -0
- package/dist/storage-protocol.js +173 -0
- package/dist/storage.d.ts +2 -72
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +2 -82
- package/dist/types.d.ts +113 -3
- package/dist/types.d.ts.map +1 -1
- package/docs/reference/connections.md +80 -0
- package/docs/reference/tools.md +14 -0
- package/package.json +4 -2
- package/src/bin/agent-serve.ts +9 -0
- package/src/channels/slack/channel-watch.ts +6 -3
- package/src/channels/slack/dispatch.ts +40 -3
- package/src/channels/slack/manifest.ts +1 -0
- package/src/channels/slack/nudge-store.ts +56 -0
- package/src/channels/slack/slack-channel.ts +3 -0
- package/src/channels/slack/types.ts +22 -5
- package/src/index.ts +5 -0
- package/src/internal/advertise-tools.ts +229 -0
- package/src/internal/cli-deploy.ts +22 -1
- package/src/internal/cli-manifest.ts +63 -0
- package/src/internal/cli-slack.ts +10 -1
- package/src/internal/cursor-agent-template.ts +46 -0
- package/src/internal/deploy-client.ts +35 -6
- package/src/internal/deploy-manifest.ts +167 -0
- package/src/internal/deployment-scm-event-stream.ts +577 -0
- package/src/internal/discovery.ts +85 -0
- package/src/internal/init-project.ts +11 -20
- package/src/internal/mcp-host.ts +66 -9
- package/src/internal/sdk-runner.ts +50 -11
- package/src/internal/server.ts +19 -0
- package/src/internal/session-engine.ts +385 -19
- package/src/internal/shallow-clone.ts +407 -0
- package/src/internal/slack-provision-client.ts +3 -0
- package/src/internal/turn-lease-store.ts +147 -0
- package/src/internal/workspace.ts +27 -0
- package/src/storage-protocol.ts +247 -0
- package/src/storage.ts +16 -110
- package/src/types.ts +117 -3
- package/templates/pr-autofixer/agent/lib/drive-schemas.ts +4 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.5ozYNf74.js +0 -1
- package/dist/playground/assets/index-B4rcOgeP.css +0 -1
- package/dist/playground/assets/index-DXcY42Jv.js +0 -85
|
@@ -3,10 +3,16 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { spawn } from "node:child_process";
|
|
6
|
-
import { existsSync
|
|
6
|
+
import { existsSync } 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";
|
|
10
|
+
import {
|
|
11
|
+
canonicalTemplateName,
|
|
12
|
+
isTemplateName,
|
|
13
|
+
readCursorAgentTemplate,
|
|
14
|
+
type TemplateName,
|
|
15
|
+
} from "./cursor-agent-template.js";
|
|
10
16
|
import {
|
|
11
17
|
CLI_COMMAND_NAME,
|
|
12
18
|
PACKAGE_NAME,
|
|
@@ -64,7 +70,7 @@ type TemplateEntry = {
|
|
|
64
70
|
overlay?: string;
|
|
65
71
|
};
|
|
66
72
|
|
|
67
|
-
const TEMPLATES: Readonly<Record<
|
|
73
|
+
const TEMPLATES: Readonly<Record<TemplateName, TemplateEntry>> = {
|
|
68
74
|
"agentic-owners": { dir: "agentic-owners" },
|
|
69
75
|
demo: { dir: "demo" },
|
|
70
76
|
"pr-autofixer": { dir: "pr-autofixer" },
|
|
@@ -73,10 +79,6 @@ const TEMPLATES: Readonly<Record<string, TemplateEntry>> = {
|
|
|
73
79
|
"triage-jira": { dir: "triage", overlay: "jira" },
|
|
74
80
|
};
|
|
75
81
|
|
|
76
|
-
function canonicalTemplateName(name: string): string {
|
|
77
|
-
return name === "triage" ? "triage-linear" : name;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
82
|
export function availableTemplates(): string[] {
|
|
81
83
|
return Object.keys(TEMPLATES).sort();
|
|
82
84
|
}
|
|
@@ -93,13 +95,13 @@ export function resolveTemplate(name: string): TemplateResolution {
|
|
|
93
95
|
};
|
|
94
96
|
}
|
|
95
97
|
const resolved = canonicalTemplateName(name);
|
|
96
|
-
|
|
97
|
-
if (entry === undefined) {
|
|
98
|
+
if (!isTemplateName(resolved)) {
|
|
98
99
|
return {
|
|
99
100
|
ok: false,
|
|
100
101
|
message: `unknown template "${name}" (available: ${availableTemplates().join(", ")})`,
|
|
101
102
|
};
|
|
102
103
|
}
|
|
104
|
+
const entry = TEMPLATES[resolved];
|
|
103
105
|
const dir = join(packageRootDir(), "templates", entry.dir);
|
|
104
106
|
return {
|
|
105
107
|
ok: true,
|
|
@@ -128,18 +130,7 @@ export function checkInitTarget(
|
|
|
128
130
|
if (!existsSync(pkgPath)) {
|
|
129
131
|
return { ok: true };
|
|
130
132
|
}
|
|
131
|
-
|
|
132
|
-
try {
|
|
133
|
-
const pkg = JSON.parse(readFileSync(pkgPath, "utf8")) as {
|
|
134
|
-
cursorAgentTemplate?: unknown;
|
|
135
|
-
};
|
|
136
|
-
marker =
|
|
137
|
-
typeof pkg.cursorAgentTemplate === "string"
|
|
138
|
-
? pkg.cursorAgentTemplate
|
|
139
|
-
: undefined;
|
|
140
|
-
} catch {
|
|
141
|
-
marker = undefined;
|
|
142
|
-
}
|
|
133
|
+
const marker = readCursorAgentTemplate(rootDir);
|
|
143
134
|
if (marker === template) {
|
|
144
135
|
return { ok: true };
|
|
145
136
|
}
|
package/src/internal/mcp-host.ts
CHANGED
|
@@ -29,6 +29,18 @@ interface OpenedConnection {
|
|
|
29
29
|
close: () => Promise<void>;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
/**
|
|
33
|
+
* A non-caching view of one connection: every operation opens a fresh
|
|
34
|
+
* client and closes it afterwards. See {@link McpHost.oneOff}.
|
|
35
|
+
*/
|
|
36
|
+
export interface HostMcpOneOff {
|
|
37
|
+
listTools(): Promise<HostMcpToolInfo[]>;
|
|
38
|
+
callTool(
|
|
39
|
+
toolName: string,
|
|
40
|
+
args?: Record<string, unknown>
|
|
41
|
+
): Promise<HostMcpCallResult>;
|
|
42
|
+
}
|
|
43
|
+
|
|
32
44
|
export class McpHost implements HostMcpRegistry {
|
|
33
45
|
private readonly byName = new Map<string, DiscoveredConnection>();
|
|
34
46
|
private readonly clients = new Map<string, Promise<OpenedConnection>>();
|
|
@@ -54,18 +66,47 @@ export class McpHost implements HostMcpRegistry {
|
|
|
54
66
|
async listTools(connectionName: string): Promise<HostMcpToolInfo[]> {
|
|
55
67
|
return this.withClient(connectionName, async (client) => {
|
|
56
68
|
const listed = await client.listTools();
|
|
57
|
-
return listed.tools.map(
|
|
58
|
-
name: tool.name,
|
|
59
|
-
...(tool.description === undefined
|
|
60
|
-
? {}
|
|
61
|
-
: { description: tool.description }),
|
|
62
|
-
...(tool.inputSchema === undefined
|
|
63
|
-
? {}
|
|
64
|
-
: { inputSchema: tool.inputSchema as JsonObject }),
|
|
65
|
-
}));
|
|
69
|
+
return listed.tools.map(toToolInfo);
|
|
66
70
|
});
|
|
67
71
|
}
|
|
68
72
|
|
|
73
|
+
/**
|
|
74
|
+
* A one-off view of a connection that is not (or not exactly) in the
|
|
75
|
+
* registry — e.g. a registered connection with per-session auth headers
|
|
76
|
+
* substituted in. Every operation opens a fresh client and closes it
|
|
77
|
+
* afterwards: the registry's cached per-name client would leak one
|
|
78
|
+
* session's identity into another, and stateless streamable-HTTP
|
|
79
|
+
* servers answer a fresh initialize cheaply. Results ride the same
|
|
80
|
+
* mapping as registry calls.
|
|
81
|
+
*/
|
|
82
|
+
oneOff(connection: DiscoveredConnection): HostMcpOneOff {
|
|
83
|
+
const withFreshClient = async <T>(
|
|
84
|
+
run: (client: Client) => Promise<T>
|
|
85
|
+
): Promise<T> => {
|
|
86
|
+
const opened = await openConnection(connection);
|
|
87
|
+
try {
|
|
88
|
+
return await run(opened.client);
|
|
89
|
+
} finally {
|
|
90
|
+
await opened.close();
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
return {
|
|
94
|
+
listTools: () =>
|
|
95
|
+
withFreshClient(async (client) => {
|
|
96
|
+
const listed = await client.listTools();
|
|
97
|
+
return listed.tools.map(toToolInfo);
|
|
98
|
+
}),
|
|
99
|
+
callTool: (toolName, args = {}) =>
|
|
100
|
+
withFreshClient(async (client) => {
|
|
101
|
+
const result = await client.callTool({
|
|
102
|
+
name: toolName,
|
|
103
|
+
arguments: args,
|
|
104
|
+
});
|
|
105
|
+
return normalizeCallResult(result);
|
|
106
|
+
}),
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
69
110
|
async callTool(
|
|
70
111
|
connectionName: string,
|
|
71
112
|
toolName: string,
|
|
@@ -172,6 +213,22 @@ export function isStaleMcpSessionError(error: unknown): boolean {
|
|
|
172
213
|
return code === 404;
|
|
173
214
|
}
|
|
174
215
|
|
|
216
|
+
function toToolInfo(tool: {
|
|
217
|
+
name: string;
|
|
218
|
+
description?: string;
|
|
219
|
+
inputSchema?: unknown;
|
|
220
|
+
}): HostMcpToolInfo {
|
|
221
|
+
return {
|
|
222
|
+
name: tool.name,
|
|
223
|
+
...(tool.description === undefined
|
|
224
|
+
? {}
|
|
225
|
+
: { description: tool.description }),
|
|
226
|
+
...(tool.inputSchema === undefined
|
|
227
|
+
? {}
|
|
228
|
+
: { inputSchema: tool.inputSchema as JsonObject }),
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
|
|
175
232
|
async function openConnection(
|
|
176
233
|
connection: DiscoveredConnection
|
|
177
234
|
): Promise<OpenedConnection> {
|
|
@@ -55,6 +55,7 @@ export type RunnerPrewarmRequest = Pick<
|
|
|
55
55
|
| "sandbox"
|
|
56
56
|
| "tools"
|
|
57
57
|
| "mcpServers"
|
|
58
|
+
| "perSendMcpServers"
|
|
58
59
|
| "subagents"
|
|
59
60
|
| "model"
|
|
60
61
|
>;
|
|
@@ -159,6 +160,28 @@ export function isAuthErrorMessage(message: string | undefined): boolean {
|
|
|
159
160
|
return /authentication error|try logging out and back in/i.test(message);
|
|
160
161
|
}
|
|
161
162
|
|
|
163
|
+
/** Cloud `wait()` copy for `stream_expired` / a missing start-state blob. */
|
|
164
|
+
function isStreamExpiredErrorMessage(message: string | undefined): boolean {
|
|
165
|
+
if (message === undefined) {
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
return /run stream is no longer available|\[stream_expired\]/i.test(message);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function retryReason(
|
|
172
|
+
message: string | undefined,
|
|
173
|
+
isFirstTurn: boolean
|
|
174
|
+
): string | undefined {
|
|
175
|
+
if (isStreamExpiredErrorMessage(message)) {
|
|
176
|
+
return "cloud run stream expired";
|
|
177
|
+
}
|
|
178
|
+
// First-turn auth is the credential; a fresh handle cannot fix it.
|
|
179
|
+
if (!isFirstTurn && isAuthErrorMessage(message)) {
|
|
180
|
+
return "authentication failure";
|
|
181
|
+
}
|
|
182
|
+
return undefined;
|
|
183
|
+
}
|
|
184
|
+
|
|
162
185
|
export class CursorSdkRunner implements AgentRunner {
|
|
163
186
|
private readonly agents = new Map<string, CachedAgentHandle>();
|
|
164
187
|
private readonly stores = new Map<string, Promise<LocalAgentStore>>();
|
|
@@ -187,26 +210,23 @@ export class CursorSdkRunner implements AgentRunner {
|
|
|
187
210
|
const outcome = await this.runTurnAttempt(tracked);
|
|
188
211
|
if (
|
|
189
212
|
outcome.status !== "error" ||
|
|
190
|
-
!isAuthErrorMessage(outcome.errorMessage) ||
|
|
191
213
|
sawUpdate ||
|
|
192
|
-
request.isFirstTurn ||
|
|
193
214
|
request.signal?.aborted === true
|
|
194
215
|
) {
|
|
195
216
|
return outcome;
|
|
196
217
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
//
|
|
202
|
-
//
|
|
218
|
+
const reason = retryReason(outcome.errorMessage, request.isFirstTurn);
|
|
219
|
+
if (reason === undefined) {
|
|
220
|
+
return outcome;
|
|
221
|
+
}
|
|
222
|
+
// Log the original error even when the retry succeeds so the expiry
|
|
223
|
+
// still shows up in Datadog.
|
|
203
224
|
this.log(
|
|
204
|
-
`[agent-sdk] session ${request.sessionId}: retrying the turn
|
|
225
|
+
`[agent-sdk] session ${request.sessionId}: ${reason}: ${outcome.errorMessage}; retrying the turn`
|
|
205
226
|
);
|
|
206
227
|
try {
|
|
207
228
|
return await this.runTurnAttempt(tracked);
|
|
208
229
|
} catch {
|
|
209
|
-
// The retry was best effort; report the original failure.
|
|
210
230
|
return outcome;
|
|
211
231
|
}
|
|
212
232
|
}
|
|
@@ -235,6 +255,12 @@ export class CursorSdkRunner implements AgentRunner {
|
|
|
235
255
|
// Stream mapping must never reject into the SDK transport.
|
|
236
256
|
}
|
|
237
257
|
},
|
|
258
|
+
// The SDK builds this send's MCP session from exactly this set, so
|
|
259
|
+
// a turn always runs on the headers the engine evaluated for it —
|
|
260
|
+
// never on the ones a previous turn opened the cached handle with.
|
|
261
|
+
...(request.runtime === "local" && request.perSendMcpServers === true
|
|
262
|
+
? { mcpServers: request.mcpServers as AgentOptions["mcpServers"] }
|
|
263
|
+
: {}),
|
|
238
264
|
...(request.runtime === "local"
|
|
239
265
|
? {
|
|
240
266
|
local: {
|
|
@@ -270,6 +296,14 @@ export class CursorSdkRunner implements AgentRunner {
|
|
|
270
296
|
if (request.onSdkAgentId !== undefined) {
|
|
271
297
|
await request.onSdkAgentId(agent.agentId);
|
|
272
298
|
}
|
|
299
|
+
// Readable on the handle as soon as send resolves, long before wait().
|
|
300
|
+
if (
|
|
301
|
+
request.onRequestId !== undefined &&
|
|
302
|
+
run.requestId !== undefined &&
|
|
303
|
+
run.requestId !== ""
|
|
304
|
+
) {
|
|
305
|
+
await request.onRequestId(run.requestId);
|
|
306
|
+
}
|
|
273
307
|
try {
|
|
274
308
|
const result = await run.wait();
|
|
275
309
|
let outcome = toTurnOutcome(result);
|
|
@@ -401,7 +435,12 @@ export class CursorSdkRunner implements AgentRunner {
|
|
|
401
435
|
return {
|
|
402
436
|
model: toModelSelection(request.model ?? DEFAULT_MODEL),
|
|
403
437
|
apiKey: this.requireApiKey(),
|
|
404
|
-
|
|
438
|
+
// Per-send servers ride each agent.send instead (fresh per-session
|
|
439
|
+
// auth headers every turn). Keeping them out of the create/resume
|
|
440
|
+
// options also keeps the local executor cache key — which hashes
|
|
441
|
+
// these options — stable while credentials rotate.
|
|
442
|
+
...(Object.keys(request.mcpServers).length > 0 &&
|
|
443
|
+
request.perSendMcpServers !== true
|
|
405
444
|
? { mcpServers: request.mcpServers as AgentOptions["mcpServers"] }
|
|
406
445
|
: {}),
|
|
407
446
|
...(subagents === undefined ? {} : { agents: subagents }),
|
package/src/internal/server.ts
CHANGED
|
@@ -70,12 +70,14 @@ import {
|
|
|
70
70
|
scmEventToGitHubPayload,
|
|
71
71
|
scmMetadataToOriginPayload,
|
|
72
72
|
} from "./cursor-event-relay.js";
|
|
73
|
+
import { AGENT_SERVE_GENERATION_ENV_VAR } from "./cursor-relay-core.js";
|
|
73
74
|
import {
|
|
74
75
|
type CursorSlackAgentRegistration,
|
|
75
76
|
CursorSlackRelay,
|
|
76
77
|
createCursorSlackApiCaller,
|
|
77
78
|
formatCursorSlackEventLog,
|
|
78
79
|
} from "./cursor-slack-relay.js";
|
|
80
|
+
import { buildAgentDeployManifest } from "./deploy-manifest.js";
|
|
79
81
|
import {
|
|
80
82
|
formatDiagnostics,
|
|
81
83
|
hasErrorDiagnostics,
|
|
@@ -1111,6 +1113,23 @@ function mountAgentRoutes(
|
|
|
1111
1113
|
handler: () => jsonResponse(projectInfo(project)),
|
|
1112
1114
|
});
|
|
1113
1115
|
|
|
1116
|
+
// Hosted-only: the control plane's provision flow reads the deploy manifest
|
|
1117
|
+
// from the running engine (same derivation as `july manifest`) right after
|
|
1118
|
+
// the health probe, so every deploy surface — CLI, UI, redeploy — gets its
|
|
1119
|
+
// declarations from the installed code without a client-side extraction
|
|
1120
|
+
// step. `auth: "none"` mirrors `/v1/health`: hosted engines are reachable
|
|
1121
|
+
// only through the anyrun port proxy (network token) or the alias route
|
|
1122
|
+
// (alias token), and the route is not registered outside hosted mode, so
|
|
1123
|
+
// self-hosted `july serve` never exposes the manifest unauthenticated.
|
|
1124
|
+
if (process.env[AGENT_SERVE_GENERATION_ENV_VAR] !== undefined) {
|
|
1125
|
+
router.add({
|
|
1126
|
+
method: "GET",
|
|
1127
|
+
pattern: `${base}/v1/manifest`,
|
|
1128
|
+
auth: "none",
|
|
1129
|
+
handler: () => jsonResponse(buildAgentDeployManifest(project)),
|
|
1130
|
+
});
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1114
1133
|
// Playground Logs tab: recent ServeOptions.logger lines (channels, sessions,
|
|
1115
1134
|
// webhook capture). `after` is an exclusive index cursor for polling.
|
|
1116
1135
|
router.add({
|