@cursor/july 0.1.2 → 0.1.3
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 +16 -5
- package/README.md +8 -9
- package/dist/bin/agent-serve.d.ts +3 -1
- package/dist/bin/agent-serve.d.ts.map +1 -1
- package/dist/bin/agent-serve.js +389 -152
- package/dist/docs/404.html +2 -2
- package/dist/docs/ab.html +3 -3
- package/dist/docs/assets/{app.Oje4vhlk.js → app.BR0RbIdx.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.DtIOQzGj.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.H5XZ2zCB.js → VPLocalSearchBox.qjsVTneI.js} +1 -1
- package/dist/docs/assets/chunks/{theme.CTR_TuaE.js → theme.2Kg8jIp_.js} +2 -2
- package/dist/docs/assets/{quickstart.md.CfU8_uTC.js → quickstart.md.BU6Iwi_9.js} +18 -6
- package/dist/docs/assets/{reference_cli.md.DA730zCu.js → reference_cli.md.Bv6pOxcF.js} +11 -6
- package/dist/docs/assets/{reference_cli.md.DA730zCu.lean.js → reference_cli.md.Bv6pOxcF.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/guides/agent-to-agent.html +3 -3
- package/dist/docs/guides/cloud-runtime.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/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 +22 -10
- package/dist/docs/reference/agent-config.html +3 -3
- package/dist/docs/reference/channels.html +3 -3
- package/dist/docs/reference/cli.html +14 -9
- package/dist/docs/reference/connections.html +3 -3
- 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/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 +3 -3
- package/dist/docs/scaffolding-agents.html +3 -3
- package/dist/docs/storage.html +3 -3
- package/dist/docs/troubleshooting.html +3 -3
- package/dist/internal/chat-client.d.ts +29 -3
- package/dist/internal/chat-client.d.ts.map +1 -1
- package/dist/internal/chat-client.js +180 -27
- package/dist/internal/cli-ax.d.ts +75 -2
- package/dist/internal/cli-ax.d.ts.map +1 -1
- package/dist/internal/cli-ax.js +600 -52
- package/dist/internal/cli-cursor.d.ts.map +1 -1
- package/dist/internal/cli-cursor.js +8 -36
- package/dist/internal/cli-deploy.d.ts +59 -3
- package/dist/internal/cli-deploy.d.ts.map +1 -1
- package/dist/internal/cli-deploy.js +316 -38
- package/dist/internal/cursor/credentials.d.ts +9 -0
- package/dist/internal/cursor/credentials.d.ts.map +1 -1
- package/dist/internal/cursor/credentials.js +12 -0
- package/dist/internal/deploy-client.d.ts +9 -1
- package/dist/internal/deploy-client.d.ts.map +1 -1
- package/dist/internal/deploy-client.js +23 -3
- package/dist/internal/deploy-source.d.ts +35 -0
- package/dist/internal/deploy-source.d.ts.map +1 -0
- package/dist/internal/deploy-source.js +118 -0
- package/dist/internal/discovery.d.ts +11 -0
- package/dist/internal/discovery.d.ts.map +1 -1
- package/dist/internal/discovery.js +43 -14
- package/dist/internal/eval-run-store.d.ts.map +1 -1
- package/dist/internal/eval-run-store.js +2 -1
- package/dist/internal/eval-runner.d.ts +2 -0
- package/dist/internal/eval-runner.d.ts.map +1 -1
- package/dist/internal/eval-runner.js +2 -0
- package/dist/internal/event-mapper.d.ts +54 -1
- package/dist/internal/event-mapper.d.ts.map +1 -1
- package/dist/internal/event-mapper.js +151 -41
- package/dist/internal/init-project.d.ts +88 -1
- package/dist/internal/init-project.d.ts.map +1 -1
- package/dist/internal/init-project.js +221 -31
- package/dist/internal/install-cursor-skills.d.ts +64 -0
- package/dist/internal/install-cursor-skills.d.ts.map +1 -0
- package/dist/internal/install-cursor-skills.js +274 -0
- package/dist/internal/logs-client.d.ts +60 -0
- package/dist/internal/logs-client.d.ts.map +1 -0
- package/dist/internal/logs-client.js +311 -0
- package/dist/internal/open-browser.d.ts +5 -0
- package/dist/internal/open-browser.d.ts.map +1 -0
- package/dist/internal/open-browser.js +34 -0
- package/dist/internal/playground/toolchain.d.ts.map +1 -1
- package/dist/internal/playground/toolchain.js +16 -11
- package/dist/internal/playground-proxy.d.ts +69 -0
- package/dist/internal/playground-proxy.d.ts.map +1 -0
- package/dist/internal/playground-proxy.js +468 -0
- package/dist/internal/prompt-context.d.ts +35 -0
- package/dist/internal/prompt-context.d.ts.map +1 -0
- package/dist/internal/prompt-context.js +71 -0
- package/dist/internal/request-headers.d.ts +11 -0
- package/dist/internal/request-headers.d.ts.map +1 -0
- package/dist/internal/request-headers.js +14 -0
- package/dist/internal/resolve-prod-target.d.ts +42 -0
- package/dist/internal/resolve-prod-target.d.ts.map +1 -0
- package/dist/internal/resolve-prod-target.js +111 -0
- package/dist/internal/run-client.d.ts +2 -2
- package/dist/internal/run-client.d.ts.map +1 -1
- package/dist/internal/run-client.js +38 -23
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +10 -4
- package/dist/internal/session-engine.d.ts +1 -1
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +21 -6
- package/dist/internal/sessions-client.d.ts +21 -0
- package/dist/internal/sessions-client.d.ts.map +1 -0
- package/dist/internal/sessions-client.js +168 -0
- package/dist/internal/stream-progress.d.ts.map +1 -1
- package/dist/internal/stream-progress.js +31 -3
- package/dist/internal/terminal-style.d.ts +22 -0
- package/dist/internal/terminal-style.d.ts.map +1 -0
- package/dist/internal/terminal-style.js +49 -0
- package/dist/internal/trajectory.d.ts +10 -5
- package/dist/internal/trajectory.d.ts.map +1 -1
- package/dist/internal/trajectory.js +82 -10
- package/dist/internal/workspace.d.ts +11 -0
- package/dist/internal/workspace.d.ts.map +1 -1
- package/dist/internal/workspace.js +38 -4
- package/dist/playground/assets/index-D-vo2lV_.css +1 -0
- package/dist/playground/assets/index-x60b9q2j.js +312 -0
- package/dist/playground/index.html +2 -2
- package/dist/types.d.ts +26 -1
- package/dist/types.d.ts.map +1 -1
- package/docs/quickstart.md +22 -7
- package/docs/reference/cli.md +51 -3
- package/package.json +3 -1
- package/skills/ab/SKILL.md +8 -8
- package/skills/create-agent/SKILL.md +28 -22
- package/skills/debug/SKILL.md +11 -11
- package/skills/evals/SKILL.md +16 -16
- package/skills/framework-map/SKILL.md +6 -6
- package/skills/github/SKILL.md +13 -13
- package/skills/hillclimb/SKILL.md +10 -10
- package/skills/setup-slack/SKILL.md +13 -13
- package/src/bin/agent-serve.ts +422 -188
- package/src/internal/chat-client.ts +252 -37
- package/src/internal/cli-ax.ts +722 -72
- package/src/internal/cli-cursor.ts +14 -42
- package/src/internal/cli-deploy.ts +428 -49
- package/src/internal/cursor/credentials.ts +14 -0
- package/src/internal/deploy-client.ts +45 -4
- package/src/internal/deploy-source.ts +133 -0
- package/src/internal/discovery.ts +53 -16
- package/src/internal/eval-run-store.ts +2 -1
- package/src/internal/eval-runner.ts +5 -0
- package/src/internal/event-mapper.ts +222 -42
- package/src/internal/init-project.ts +333 -51
- package/src/internal/install-cursor-skills.ts +327 -0
- package/src/internal/logs-client.ts +442 -0
- package/src/internal/open-browser.ts +41 -0
- package/src/internal/playground/toolchain.ts +15 -13
- package/src/internal/playground-proxy.ts +576 -0
- package/src/internal/prompt-context.ts +95 -0
- package/src/internal/request-headers.ts +23 -0
- package/src/internal/resolve-prod-target.ts +150 -0
- package/src/internal/run-client.ts +39 -36
- package/src/internal/server.ts +12 -3
- package/src/internal/session-engine.ts +22 -3
- package/src/internal/sessions-client.ts +182 -0
- package/src/internal/stream-progress.ts +36 -2
- package/src/internal/terminal-style.ts +74 -0
- package/src/internal/trajectory.ts +91 -13
- package/src/internal/workspace.ts +42 -4
- package/src/types.ts +42 -6
- package/dist/docs/assets/chunks/@localSearchIndexroot.zwQ9RCQ7.js +0 -1
- package/dist/playground/assets/index-B1Qc9h2u.css +0 -1
- package/dist/playground/assets/index-CpDYCj8W.js +0 -79
- /package/dist/docs/assets/{quickstart.md.CfU8_uTC.lean.js → quickstart.md.BU6Iwi_9.lean.js} +0 -0
|
@@ -27,6 +27,18 @@ export type DeploymentStatus =
|
|
|
27
27
|
| "stopping"
|
|
28
28
|
| "stopped";
|
|
29
29
|
|
|
30
|
+
/** Customer-safe deploy progress (no hosting phase / infra names). */
|
|
31
|
+
export type DeploymentProgress =
|
|
32
|
+
| "queued"
|
|
33
|
+
| "preparing"
|
|
34
|
+
| "building"
|
|
35
|
+
| "finalizing"
|
|
36
|
+
| "running"
|
|
37
|
+
| "failed"
|
|
38
|
+
| "stopping"
|
|
39
|
+
| "stopped"
|
|
40
|
+
| "degraded";
|
|
41
|
+
|
|
30
42
|
export const TERMINAL_DEPLOY_STATUSES: ReadonlySet<DeploymentStatus> = new Set([
|
|
31
43
|
"running",
|
|
32
44
|
"degraded",
|
|
@@ -118,6 +130,11 @@ export interface Deployment {
|
|
|
118
130
|
agentPath?: string;
|
|
119
131
|
desiredState?: string;
|
|
120
132
|
status: DeploymentStatus;
|
|
133
|
+
/**
|
|
134
|
+
* Customer-safe deploy progress (no hosting internals). Present on newer
|
|
135
|
+
* backends; older responses omit it.
|
|
136
|
+
*/
|
|
137
|
+
progress?: DeploymentProgress;
|
|
121
138
|
generation: number;
|
|
122
139
|
observedGeneration?: number | null;
|
|
123
140
|
engineGeneration?: number | null;
|
|
@@ -131,7 +148,8 @@ export interface Deployment {
|
|
|
131
148
|
cursorEventRepos?: string[];
|
|
132
149
|
/** Normalized egress allowlist for the engine pod. */
|
|
133
150
|
egressAllowedDomains?: string[];
|
|
134
|
-
|
|
151
|
+
/** Service-account id (`sa_…`); null on legacy rows. */
|
|
152
|
+
serviceAccountId?: string | number | null;
|
|
135
153
|
/** Masked pod credential; the raw key is never returned. */
|
|
136
154
|
podCredentialMaskedKey?: string | null;
|
|
137
155
|
/** Names of the secrets set on the deployment (values never returned). */
|
|
@@ -196,6 +214,19 @@ const deploymentSchema = z.object({
|
|
|
196
214
|
"stopping",
|
|
197
215
|
"stopped",
|
|
198
216
|
]),
|
|
217
|
+
progress: z
|
|
218
|
+
.enum([
|
|
219
|
+
"queued",
|
|
220
|
+
"preparing",
|
|
221
|
+
"building",
|
|
222
|
+
"finalizing",
|
|
223
|
+
"running",
|
|
224
|
+
"failed",
|
|
225
|
+
"stopping",
|
|
226
|
+
"stopped",
|
|
227
|
+
"degraded",
|
|
228
|
+
])
|
|
229
|
+
.optional(),
|
|
199
230
|
generation: z.number(),
|
|
200
231
|
observedGeneration: z.number().nullable().optional(),
|
|
201
232
|
engineGeneration: z.number().nullable().optional(),
|
|
@@ -207,8 +238,9 @@ const deploymentSchema = z.object({
|
|
|
207
238
|
lastReconciledAt: z.string().nullable().optional(),
|
|
208
239
|
cursorEventRepos: z.array(z.string()).optional(),
|
|
209
240
|
egressAllowedDomains: z.array(z.string()).optional(),
|
|
210
|
-
//
|
|
211
|
-
|
|
241
|
+
// String ids (`sa_…`) in prod; older mocks/fixtures used numbers. Null on
|
|
242
|
+
// legacy rows that predate service-account-backed deploys.
|
|
243
|
+
serviceAccountId: z.union([z.string(), z.number()]).nullable().optional(),
|
|
212
244
|
podCredentialMaskedKey: z.string().nullable().optional(),
|
|
213
245
|
secretNames: z.array(z.string()).optional(),
|
|
214
246
|
});
|
|
@@ -552,13 +584,22 @@ function mapErrorResponse(
|
|
|
552
584
|
`${serverError ?? "Not authorized"} — deploying needs team-admin permission and the cloud-agent entitlement on that team.`,
|
|
553
585
|
403
|
|
554
586
|
);
|
|
555
|
-
case 404:
|
|
587
|
+
case 404: {
|
|
588
|
+
// Fastify's route-not-found envelope means we hit the wrong host
|
|
589
|
+
// (api2 vs api.cursor.com), not a missing deployment / closed gate.
|
|
590
|
+
if (/Route \S+ not found/i.test(bodyText)) {
|
|
591
|
+
return new DeployApiError(
|
|
592
|
+
`Agent Serve deploy API not found on this host — use the default api.cursor.com (unset CURSOR_API_BASE_URL), or point CURSOR_API_BASE_URL at a backend that mounts /internal/agent-serve/*.`,
|
|
593
|
+
404
|
|
594
|
+
);
|
|
595
|
+
}
|
|
556
596
|
return new DeployApiError(
|
|
557
597
|
context.slug === undefined
|
|
558
598
|
? `Not found — the agent_serve_mvp feature gate may not be enabled for your team.`
|
|
559
599
|
: `Deployment${slugPart} was not found — check the slug and --team, or the agent_serve_mvp feature gate may not be enabled for your team.`,
|
|
560
600
|
404
|
|
561
601
|
);
|
|
602
|
+
}
|
|
562
603
|
case 409:
|
|
563
604
|
return new DeployApiError(
|
|
564
605
|
`A concurrent deploy or stop is changing deployment${slugPart}; retry in a moment.`,
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Infer `agentkit deploy` git source fields from a local checkout.
|
|
3
|
+
*
|
|
4
|
+
* From an agent directory inside a git repo with an `origin` remote, the
|
|
5
|
+
* CLI can fill `--repo` / `--ref` / `--path` so `agentkit deploy` (no
|
|
6
|
+
* flags) is enough. Explicit flags always win.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { execFile } from "node:child_process";
|
|
10
|
+
import { relative, resolve, sep } from "node:path";
|
|
11
|
+
import { promisify } from "node:util";
|
|
12
|
+
|
|
13
|
+
const execFileAsync = promisify(execFile);
|
|
14
|
+
|
|
15
|
+
/** Injectable git runner (cwd + args → stdout, or undefined on failure). */
|
|
16
|
+
export type GitRunner = (
|
|
17
|
+
args: readonly string[],
|
|
18
|
+
cwd: string
|
|
19
|
+
) => Promise<string | undefined>;
|
|
20
|
+
|
|
21
|
+
export interface InferredDeploySource {
|
|
22
|
+
gitRepoUrl?: string;
|
|
23
|
+
gitRef?: string;
|
|
24
|
+
/** Agent directory relative to the repo root (posix). Omitted at root. */
|
|
25
|
+
agentPath?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const defaultGitRunner: GitRunner = async (args, cwd) => {
|
|
29
|
+
try {
|
|
30
|
+
const { stdout } = await execFileAsync("git", [...args], { cwd });
|
|
31
|
+
const trimmed = stdout.trim();
|
|
32
|
+
return trimmed === "" ? undefined : trimmed;
|
|
33
|
+
} catch {
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Normalize a git remote URL to the https form the control plane accepts
|
|
40
|
+
* (`https://host/owner/repo`, no `.git` suffix). Returns undefined for
|
|
41
|
+
* unrecognized shapes.
|
|
42
|
+
*/
|
|
43
|
+
export function httpsGitRepoUrlFromRemote(remote: string): string | undefined {
|
|
44
|
+
let url = remote.trim();
|
|
45
|
+
if (url === "") {
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
48
|
+
if (url.startsWith("git@")) {
|
|
49
|
+
// git@host:owner/repo.git → https://host/owner/repo.git
|
|
50
|
+
url = `https://${url.slice("git@".length).replace(":", "/")}`;
|
|
51
|
+
} else if (url.startsWith("ssh://git@")) {
|
|
52
|
+
url = `https://${url.slice("ssh://git@".length)}`;
|
|
53
|
+
} else if (!/^https?:\/\//i.test(url)) {
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
let parsed: URL;
|
|
58
|
+
try {
|
|
59
|
+
parsed = new URL(url);
|
|
60
|
+
} catch {
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
const path = parsed.pathname
|
|
64
|
+
.replace(/\.git$/i, "")
|
|
65
|
+
.replace(/\/+$/, "")
|
|
66
|
+
.replace(/^\/+/, "");
|
|
67
|
+
if (path === "" || !path.includes("/")) {
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
// Use hostname (not host) so ssh://git@github.com:22/… does not keep :22.
|
|
71
|
+
return `https://${parsed.hostname}/${path}`;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Path of `dir` relative to `gitRoot`, using `/` separators. Undefined when
|
|
76
|
+
* `dir` is outside the root; omitted (undefined) when `dir` *is* the root
|
|
77
|
+
* so the control plane treats the agent as living at the repo root.
|
|
78
|
+
*/
|
|
79
|
+
export function agentPathRelativeToGitRoot(
|
|
80
|
+
dir: string,
|
|
81
|
+
gitRoot: string
|
|
82
|
+
): string | undefined {
|
|
83
|
+
const absDir = resolve(dir);
|
|
84
|
+
const absRoot = resolve(gitRoot);
|
|
85
|
+
const rel = relative(absRoot, absDir);
|
|
86
|
+
if (rel === "") {
|
|
87
|
+
return undefined;
|
|
88
|
+
}
|
|
89
|
+
// Outside the repo (or a Windows drive mismatch) → cannot infer.
|
|
90
|
+
if (rel.startsWith("..") || rel.split(sep).includes("..")) {
|
|
91
|
+
return undefined;
|
|
92
|
+
}
|
|
93
|
+
return rel.split(sep).join("/");
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Probe the git checkout containing `dir` for deploy source fields.
|
|
98
|
+
* Missing pieces stay undefined (static deploy / server defaults).
|
|
99
|
+
*/
|
|
100
|
+
export async function inferDeployGitSource(
|
|
101
|
+
dir: string,
|
|
102
|
+
options?: { git?: GitRunner }
|
|
103
|
+
): Promise<InferredDeploySource> {
|
|
104
|
+
const git = options?.git ?? defaultGitRunner;
|
|
105
|
+
const absDir = resolve(dir);
|
|
106
|
+
|
|
107
|
+
const gitRoot = await git(["rev-parse", "--show-toplevel"], absDir);
|
|
108
|
+
if (gitRoot === undefined) {
|
|
109
|
+
return {};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const remote = await git(["remote", "get-url", "origin"], gitRoot);
|
|
113
|
+
const gitRepoUrl =
|
|
114
|
+
remote === undefined ? undefined : httpsGitRepoUrlFromRemote(remote);
|
|
115
|
+
|
|
116
|
+
const branch = await git(["rev-parse", "--abbrev-ref", "HEAD"], gitRoot);
|
|
117
|
+
let gitRef: string | undefined;
|
|
118
|
+
if (branch !== undefined && branch !== "HEAD") {
|
|
119
|
+
gitRef = branch;
|
|
120
|
+
} else {
|
|
121
|
+
// Detached HEAD — pin the exact commit so the control plane still
|
|
122
|
+
// has something concrete to build.
|
|
123
|
+
gitRef = await git(["rev-parse", "HEAD"], gitRoot);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const agentPath = agentPathRelativeToGitRoot(absDir, gitRoot);
|
|
127
|
+
|
|
128
|
+
return {
|
|
129
|
+
gitRepoUrl,
|
|
130
|
+
gitRef,
|
|
131
|
+
agentPath,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
@@ -61,6 +61,7 @@ import {
|
|
|
61
61
|
} from "./hosting.js";
|
|
62
62
|
import { toolInputJsonSchema } from "./json-schema.js";
|
|
63
63
|
import { MCP_ENDPOINT_PATH, mcpEndpointToolNames } from "./mcp-endpoint.js";
|
|
64
|
+
import { withIdentityPreamble } from "./workspace.js";
|
|
64
65
|
|
|
65
66
|
const MODULE_EXTENSIONS = new Set([".ts", ".mts", ".js", ".mjs"]);
|
|
66
67
|
const NAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9_-]*$/;
|
|
@@ -105,23 +106,26 @@ export async function isAgentProjectDir(dir: string): Promise<boolean> {
|
|
|
105
106
|
return hasFlatLayoutMarkers(resolved);
|
|
106
107
|
}
|
|
107
108
|
|
|
109
|
+
/** One immediate child agent directory under a multi-agent parent. */
|
|
110
|
+
export interface ChildAgentDir {
|
|
111
|
+
slug: string;
|
|
112
|
+
dir: string;
|
|
113
|
+
}
|
|
114
|
+
|
|
108
115
|
/**
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
* multi-agent serving, where one server hosts many agents under
|
|
113
|
-
* `/<slug>/...`. Throws when no child projects are found.
|
|
116
|
+
* List agent projects directly under `rootDir` (one level deep) without
|
|
117
|
+
* loading them. Empty when the path is missing or has no child agents.
|
|
118
|
+
* Slug rules match {@link loadAgentProjects} / multi-agent serve.
|
|
114
119
|
*/
|
|
115
|
-
export async function
|
|
116
|
-
rootDir: string
|
|
117
|
-
|
|
118
|
-
): Promise<Array<{ slug: string; project: AgentProject }>> {
|
|
120
|
+
export async function listChildAgentDirs(
|
|
121
|
+
rootDir: string
|
|
122
|
+
): Promise<ChildAgentDir[]> {
|
|
119
123
|
const resolved = resolve(rootDir);
|
|
120
124
|
if (!(await isDirectory(resolved))) {
|
|
121
|
-
|
|
125
|
+
return [];
|
|
122
126
|
}
|
|
123
127
|
|
|
124
|
-
const results:
|
|
128
|
+
const results: ChildAgentDir[] = [];
|
|
125
129
|
const seenSlugs = new Set<string>();
|
|
126
130
|
for (const entry of await sortedEntries(resolved)) {
|
|
127
131
|
if (!entry.isDirectory() || entry.name.startsWith(".")) {
|
|
@@ -139,14 +143,40 @@ export async function loadAgentProjects(
|
|
|
139
143
|
throw new Error(`Duplicate agent slug "${slug}" under ${resolved}.`);
|
|
140
144
|
}
|
|
141
145
|
seenSlugs.add(slug);
|
|
142
|
-
results.push({ slug,
|
|
146
|
+
results.push({ slug, dir: childDir });
|
|
147
|
+
}
|
|
148
|
+
return results;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Discover the agent projects directly under `rootDir` (one level deep):
|
|
153
|
+
* each immediate child directory that is itself an agent project becomes a
|
|
154
|
+
* mounted agent, keyed by a slug derived from its directory name. Used for
|
|
155
|
+
* multi-agent serving, where one server hosts many agents under
|
|
156
|
+
* `/<slug>/...`. Throws when no child projects are found.
|
|
157
|
+
*/
|
|
158
|
+
export async function loadAgentProjects(
|
|
159
|
+
rootDir: string,
|
|
160
|
+
options: LoadAgentProjectOptions = {}
|
|
161
|
+
): Promise<Array<{ slug: string; project: AgentProject }>> {
|
|
162
|
+
const resolved = resolve(rootDir);
|
|
163
|
+
if (!(await isDirectory(resolved))) {
|
|
164
|
+
throw new Error(`Agent projects directory does not exist: ${resolved}`);
|
|
143
165
|
}
|
|
144
166
|
|
|
145
|
-
|
|
167
|
+
const children = await listChildAgentDirs(resolved);
|
|
168
|
+
if (children.length === 0) {
|
|
146
169
|
throw new Error(
|
|
147
170
|
`No agent projects found directly under ${resolved}. Each agent should be a subdirectory with its own agent/ directory (or flat-layout markers).`
|
|
148
171
|
);
|
|
149
172
|
}
|
|
173
|
+
const results: Array<{ slug: string; project: AgentProject }> = [];
|
|
174
|
+
for (const child of children) {
|
|
175
|
+
results.push({
|
|
176
|
+
slug: child.slug,
|
|
177
|
+
project: await loadAgentProject(child.dir, options),
|
|
178
|
+
});
|
|
179
|
+
}
|
|
150
180
|
return results;
|
|
151
181
|
}
|
|
152
182
|
|
|
@@ -287,12 +317,19 @@ async function loadAgent(
|
|
|
287
317
|
options: { name: string; isRoot: boolean }
|
|
288
318
|
): Promise<ResolvedAgent> {
|
|
289
319
|
const config = await loadAgentConfig(ctx, agentDir, options.isRoot);
|
|
290
|
-
const
|
|
320
|
+
const name = config?.name ?? options.name;
|
|
321
|
+
const authoredInstructions = await loadInstructions(
|
|
291
322
|
ctx,
|
|
292
323
|
agentDir,
|
|
293
324
|
config,
|
|
294
325
|
options.isRoot
|
|
295
326
|
);
|
|
327
|
+
// Root agents without authored instructions stay undefined (diagnostic
|
|
328
|
+
// already recorded). Subagents still get the identity line alone.
|
|
329
|
+
const instructions =
|
|
330
|
+
authoredInstructions === undefined && options.isRoot
|
|
331
|
+
? undefined
|
|
332
|
+
: withIdentityPreamble(name, authoredInstructions);
|
|
296
333
|
|
|
297
334
|
// Subagents run as Cursor SDK custom subagents (prompt + description +
|
|
298
335
|
// model); their other slots are inert today, so don't load them — just
|
|
@@ -300,7 +337,7 @@ async function loadAgent(
|
|
|
300
337
|
if (!options.isRoot) {
|
|
301
338
|
await warnUnsupportedSubagentSlots(ctx, agentDir);
|
|
302
339
|
return {
|
|
303
|
-
name
|
|
340
|
+
name,
|
|
304
341
|
...(config?.description === undefined
|
|
305
342
|
? {}
|
|
306
343
|
: { description: config.description }),
|
|
@@ -347,7 +384,7 @@ async function loadAgent(
|
|
|
347
384
|
}
|
|
348
385
|
|
|
349
386
|
return {
|
|
350
|
-
name
|
|
387
|
+
name,
|
|
351
388
|
description: config?.description,
|
|
352
389
|
// Root agents always get a concrete model: authored value or DEFAULT_MODEL.
|
|
353
390
|
model: isValidModelSetting(config?.model) ? config.model : DEFAULT_MODEL,
|
|
@@ -400,7 +400,8 @@ export class EvalRunStore {
|
|
|
400
400
|
}
|
|
401
401
|
if (
|
|
402
402
|
event.type === "message.completed" &&
|
|
403
|
-
typeof event.data?.text === "string"
|
|
403
|
+
typeof event.data?.text === "string" &&
|
|
404
|
+
event.data.parentCallId === undefined
|
|
404
405
|
) {
|
|
405
406
|
c.finalText = event.data.text;
|
|
406
407
|
}
|
|
@@ -76,6 +76,8 @@ export interface RunEvalsOptions extends EvalSelectionOptions {
|
|
|
76
76
|
baseUrl: string;
|
|
77
77
|
timeoutMs?: number;
|
|
78
78
|
bearerToken?: string;
|
|
79
|
+
/** Extra request headers (e.g. hosted engineAccess). */
|
|
80
|
+
headers?: Record<string, string>;
|
|
79
81
|
verbose?: boolean;
|
|
80
82
|
onEvent?: (event: SessionEvent) => void;
|
|
81
83
|
/** Fired when a case begins executing (after concurrency slot acquired). */
|
|
@@ -240,6 +242,7 @@ export async function runDiscoveredEvals(
|
|
|
240
242
|
baseUrl: options.baseUrl,
|
|
241
243
|
defaultTimeoutMs,
|
|
242
244
|
bearerToken: options.bearerToken,
|
|
245
|
+
headers: options.headers,
|
|
243
246
|
verbose: Boolean(options.verbose),
|
|
244
247
|
onEvent: (event) => {
|
|
245
248
|
options.onCaseEvent?.(discovered.id, event);
|
|
@@ -268,6 +271,7 @@ async function runOneEval(
|
|
|
268
271
|
baseUrl: string;
|
|
269
272
|
defaultTimeoutMs: number;
|
|
270
273
|
bearerToken?: string;
|
|
274
|
+
headers?: Record<string, string>;
|
|
271
275
|
verbose: boolean;
|
|
272
276
|
onEvent?: (event: SessionEvent) => void;
|
|
273
277
|
}
|
|
@@ -330,6 +334,7 @@ async function runOneEval(
|
|
|
330
334
|
// Keep defineEval traffic out of live defineAB enrollment/metrics.
|
|
331
335
|
purpose: "eval",
|
|
332
336
|
bearerToken: opts.bearerToken,
|
|
337
|
+
headers: opts.headers,
|
|
333
338
|
workspaceDir: options.workspaceDir,
|
|
334
339
|
workspaceFiles: options.workspaceFiles,
|
|
335
340
|
timeoutMs,
|