@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
|
@@ -2,14 +2,20 @@
|
|
|
2
2
|
* Scaffold a minimal agent-serve project (`agent-serve init`).
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
import { spawn } from "node:child_process";
|
|
5
6
|
import { mkdir, writeFile } from "node:fs/promises";
|
|
6
|
-
import { basename, dirname, join, resolve } from "node:path";
|
|
7
|
+
import { basename, dirname, join, relative, resolve } from "node:path";
|
|
7
8
|
import type { ModelSetting } from "../types.js";
|
|
8
9
|
import {
|
|
9
10
|
CLI_COMMAND_NAME,
|
|
10
11
|
PACKAGE_NAME,
|
|
11
12
|
packageVersion,
|
|
12
13
|
} from "./distribution.js";
|
|
14
|
+
import {
|
|
15
|
+
makePalette,
|
|
16
|
+
stdoutPalette,
|
|
17
|
+
type TerminalPalette,
|
|
18
|
+
} from "./terminal-style.js";
|
|
13
19
|
|
|
14
20
|
export interface InitProjectOptions {
|
|
15
21
|
/** Directory to create (created if missing). */
|
|
@@ -20,9 +26,21 @@ export interface InitProjectOptions {
|
|
|
20
26
|
model?: string;
|
|
21
27
|
}
|
|
22
28
|
|
|
29
|
+
export type InitFileAction = "create" | "exist";
|
|
30
|
+
|
|
31
|
+
export interface InitFileEntry {
|
|
32
|
+
path: string;
|
|
33
|
+
action: InitFileAction;
|
|
34
|
+
}
|
|
35
|
+
|
|
23
36
|
export interface InitProjectResult {
|
|
24
37
|
rootDir: string;
|
|
25
|
-
files
|
|
38
|
+
/** Scaffold files in write order, with create/exist for each. */
|
|
39
|
+
files: InitFileEntry[];
|
|
40
|
+
/** Paths newly written. */
|
|
41
|
+
created: string[];
|
|
42
|
+
/** Paths left alone because they already existed. */
|
|
43
|
+
skipped: string[];
|
|
26
44
|
}
|
|
27
45
|
|
|
28
46
|
const DEFAULT_MODEL: ModelSetting = {
|
|
@@ -33,6 +51,23 @@ const DEFAULT_MODEL: ModelSetting = {
|
|
|
33
51
|
],
|
|
34
52
|
};
|
|
35
53
|
|
|
54
|
+
/**
|
|
55
|
+
* Empty capability folders the scaffold creates (each gets a `.gitkeep`).
|
|
56
|
+
* `agent/tools/` is omitted — the demo `echo.ts` already keeps it in git.
|
|
57
|
+
*/
|
|
58
|
+
const SCAFFOLD_EMPTY_DIRS: readonly string[] = [
|
|
59
|
+
"agent/skills",
|
|
60
|
+
"agent/mcp-connections",
|
|
61
|
+
"agent/subagents",
|
|
62
|
+
"agent/channels",
|
|
63
|
+
"agent/hooks",
|
|
64
|
+
"agent/ab",
|
|
65
|
+
"agent/schedules",
|
|
66
|
+
"agent/sandbox/workspace",
|
|
67
|
+
"agent/lib",
|
|
68
|
+
"evals",
|
|
69
|
+
];
|
|
70
|
+
|
|
36
71
|
export async function initProject(
|
|
37
72
|
options: InitProjectOptions
|
|
38
73
|
): Promise<InitProjectResult> {
|
|
@@ -42,52 +77,85 @@ export async function initProject(
|
|
|
42
77
|
const agentDir = join(rootDir, "agent");
|
|
43
78
|
await mkdir(agentDir, { recursive: true });
|
|
44
79
|
|
|
45
|
-
const
|
|
80
|
+
const files: InitFileEntry[] = [];
|
|
46
81
|
const write = async (rel: string, contents: string): Promise<void> => {
|
|
47
82
|
const abs = join(rootDir, rel);
|
|
48
83
|
await mkdir(dirname(abs), { recursive: true });
|
|
49
|
-
|
|
50
|
-
|
|
84
|
+
try {
|
|
85
|
+
await writeFile(abs, contents, { flag: "wx" });
|
|
86
|
+
files.push({ path: rel, action: "create" });
|
|
87
|
+
} catch (error) {
|
|
88
|
+
if (isEexist(error)) {
|
|
89
|
+
// Rails generators leave existing files alone (`exist`).
|
|
90
|
+
files.push({ path: rel, action: "exist" });
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
throw error;
|
|
94
|
+
}
|
|
51
95
|
};
|
|
52
96
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
97
|
+
await write(
|
|
98
|
+
"package.json",
|
|
99
|
+
`${JSON.stringify(
|
|
100
|
+
{
|
|
101
|
+
name,
|
|
102
|
+
private: true,
|
|
103
|
+
type: "module",
|
|
104
|
+
description: `agent project: ${name}`,
|
|
105
|
+
scripts: {
|
|
106
|
+
check: "tsc --noEmit",
|
|
107
|
+
},
|
|
108
|
+
dependencies: {
|
|
109
|
+
[PACKAGE_NAME]: `^${packageVersion()}`,
|
|
110
|
+
zod: "^3.25.0",
|
|
66
111
|
},
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
112
|
+
devDependencies: {
|
|
113
|
+
"@types/node": "^22.14.0",
|
|
114
|
+
typescript: "^5.8.0",
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
null,
|
|
118
|
+
2
|
|
119
|
+
)}\n`
|
|
120
|
+
);
|
|
121
|
+
await write(
|
|
122
|
+
"tsconfig.json",
|
|
123
|
+
`{
|
|
124
|
+
// Type-checking only (npm run check): the framework runs agent/ code
|
|
125
|
+
// directly through tsx, so nothing is compiled.
|
|
126
|
+
"compilerOptions": {
|
|
127
|
+
"target": "ES2022",
|
|
128
|
+
"module": "ESNext",
|
|
129
|
+
"moduleResolution": "bundler",
|
|
130
|
+
"strict": true,
|
|
131
|
+
"noEmit": true,
|
|
132
|
+
"skipLibCheck": true,
|
|
133
|
+
"types": ["node"]
|
|
134
|
+
},
|
|
135
|
+
"include": ["agent/**/*", "evals/**/*"]
|
|
136
|
+
}
|
|
137
|
+
`
|
|
138
|
+
);
|
|
139
|
+
await write(
|
|
140
|
+
"agent/agent.ts",
|
|
141
|
+
`import { defineAgent } from "${PACKAGE_NAME}";
|
|
74
142
|
|
|
75
143
|
export default defineAgent({
|
|
76
144
|
model: ${model},
|
|
77
145
|
});
|
|
78
146
|
`
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
147
|
+
);
|
|
148
|
+
await write(
|
|
149
|
+
"agent/instructions.md",
|
|
150
|
+
`# ${name}
|
|
83
151
|
|
|
84
152
|
You are a helpful agent. Prefer tools when they fit the request.
|
|
85
153
|
Keep answers concise unless the user asks for detail.
|
|
86
154
|
`
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
155
|
+
);
|
|
156
|
+
await write(
|
|
157
|
+
"agent/tools/echo.ts",
|
|
158
|
+
`import { defineTool } from "${PACKAGE_NAME}/tools";
|
|
91
159
|
import { z } from "zod";
|
|
92
160
|
|
|
93
161
|
export default defineTool({
|
|
@@ -98,22 +166,99 @@ export default defineTool({
|
|
|
98
166
|
},
|
|
99
167
|
});
|
|
100
168
|
`
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
typeof error === "object" &&
|
|
106
|
-
"code" in error &&
|
|
107
|
-
(error as { code: string }).code === "EEXIST"
|
|
108
|
-
) {
|
|
109
|
-
throw new Error(
|
|
110
|
-
`Refusing to overwrite existing files under ${rootDir}. Pick an empty directory or remove the conflicting files.`
|
|
111
|
-
);
|
|
112
|
-
}
|
|
113
|
-
throw error;
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
for (const dir of SCAFFOLD_EMPTY_DIRS) {
|
|
172
|
+
await write(`${dir}/.gitkeep`, "");
|
|
114
173
|
}
|
|
115
174
|
|
|
116
|
-
return {
|
|
175
|
+
return {
|
|
176
|
+
rootDir,
|
|
177
|
+
files,
|
|
178
|
+
created: files
|
|
179
|
+
.filter((entry) => entry.action === "create")
|
|
180
|
+
.map((entry) => entry.path),
|
|
181
|
+
skipped: files
|
|
182
|
+
.filter((entry) => entry.action === "exist")
|
|
183
|
+
.map((entry) => entry.path),
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function isEexist(error: unknown): boolean {
|
|
188
|
+
return (
|
|
189
|
+
error !== null &&
|
|
190
|
+
typeof error === "object" &&
|
|
191
|
+
"code" in error &&
|
|
192
|
+
(error as { code: string }).code === "EEXIST"
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export interface InstallScaffoldDependenciesOptions {
|
|
197
|
+
/**
|
|
198
|
+
* `inherit` streams npm output to the terminal (human `init`);
|
|
199
|
+
* `pipe` captures it ( `--json` / tests).
|
|
200
|
+
*/
|
|
201
|
+
stdio?: "inherit" | "pipe";
|
|
202
|
+
/** Test seam — replaces the real `npm install` spawn. */
|
|
203
|
+
runner?: (args: {
|
|
204
|
+
command: string;
|
|
205
|
+
args: string[];
|
|
206
|
+
cwd: string;
|
|
207
|
+
stdio: "inherit" | "pipe";
|
|
208
|
+
}) => Promise<{ exitCode: number; stderr: string }>;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export interface InstallScaffoldDependenciesResult {
|
|
212
|
+
ok: boolean;
|
|
213
|
+
exitCode: number;
|
|
214
|
+
stderr: string;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Install the scaffold's npm dependencies so `dev` / `run` can resolve
|
|
219
|
+
* `@cursor/july` immediately after `init`.
|
|
220
|
+
*/
|
|
221
|
+
export async function installScaffoldDependencies(
|
|
222
|
+
rootDir: string,
|
|
223
|
+
options: InstallScaffoldDependenciesOptions = {}
|
|
224
|
+
): Promise<InstallScaffoldDependenciesResult> {
|
|
225
|
+
const stdio = options.stdio ?? "inherit";
|
|
226
|
+
const command = process.platform === "win32" ? "npm.cmd" : "npm";
|
|
227
|
+
const args = ["install", "--no-fund", "--no-audit"];
|
|
228
|
+
const runner = options.runner ?? defaultNpmInstallRunner;
|
|
229
|
+
const result = await runner({ command, args, cwd: rootDir, stdio });
|
|
230
|
+
return {
|
|
231
|
+
ok: result.exitCode === 0,
|
|
232
|
+
exitCode: result.exitCode,
|
|
233
|
+
stderr: result.stderr,
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
async function defaultNpmInstallRunner(args: {
|
|
238
|
+
command: string;
|
|
239
|
+
args: string[];
|
|
240
|
+
cwd: string;
|
|
241
|
+
stdio: "inherit" | "pipe";
|
|
242
|
+
}): Promise<{ exitCode: number; stderr: string }> {
|
|
243
|
+
return await new Promise((resolvePromise, reject) => {
|
|
244
|
+
const child = spawn(args.command, args.args, {
|
|
245
|
+
cwd: args.cwd,
|
|
246
|
+
stdio: args.stdio === "inherit" ? "inherit" : ["ignore", "pipe", "pipe"],
|
|
247
|
+
env: process.env,
|
|
248
|
+
});
|
|
249
|
+
let stderr = "";
|
|
250
|
+
if (args.stdio === "pipe") {
|
|
251
|
+
child.stderr?.setEncoding("utf8");
|
|
252
|
+
child.stderr?.on("data", (chunk: string) => {
|
|
253
|
+
stderr += chunk;
|
|
254
|
+
});
|
|
255
|
+
child.stdout?.resume();
|
|
256
|
+
}
|
|
257
|
+
child.on("error", reject);
|
|
258
|
+
child.on("close", (code) => {
|
|
259
|
+
resolvePromise({ exitCode: code ?? 1, stderr });
|
|
260
|
+
});
|
|
261
|
+
});
|
|
117
262
|
}
|
|
118
263
|
|
|
119
264
|
function formatModelLiteral(model: string | ModelSetting): string {
|
|
@@ -137,6 +282,142 @@ ${model.params
|
|
|
137
282
|
}`;
|
|
138
283
|
}
|
|
139
284
|
|
|
285
|
+
export interface InitScaffoldSummaryOptions {
|
|
286
|
+
/** Scaffolded project root (absolute). */
|
|
287
|
+
rootDir: string;
|
|
288
|
+
/** Scaffold files in write order (`create` / `exist`). */
|
|
289
|
+
files: InitFileEntry[];
|
|
290
|
+
/** Override TTY color detection (tests / `--json` callers). */
|
|
291
|
+
color?: boolean;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
export interface InitNextStepsOptions {
|
|
295
|
+
/** Scaffolded project root (absolute). */
|
|
296
|
+
rootDir: string;
|
|
297
|
+
/** Directory the command ran from. */
|
|
298
|
+
cwd: string;
|
|
299
|
+
/**
|
|
300
|
+
* True when a Cursor credential resolves. When false, next steps include
|
|
301
|
+
* `login` (used for `--json` and when an interactive login attempt failed).
|
|
302
|
+
*/
|
|
303
|
+
signedIn: boolean;
|
|
304
|
+
/** Override TTY color detection (tests / `--json` callers). */
|
|
305
|
+
color?: boolean;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
export type InitSummaryOptions = InitScaffoldSummaryOptions &
|
|
309
|
+
InitNextStepsOptions;
|
|
310
|
+
|
|
311
|
+
function initPalette(color?: boolean): TerminalPalette {
|
|
312
|
+
return color === undefined ? stdoutPalette() : makePalette(color);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Created/skipped files plus the project path. Printed before an interactive
|
|
317
|
+
* login so the scaffold is visible while the browser flow runs.
|
|
318
|
+
*/
|
|
319
|
+
export function formatInitScaffoldSummary(
|
|
320
|
+
options: InitScaffoldSummaryOptions
|
|
321
|
+
): string {
|
|
322
|
+
const c = initPalette(options.color);
|
|
323
|
+
const name = basename(options.rootDir);
|
|
324
|
+
const lines: string[] = [];
|
|
325
|
+
lines.push(`Initialized agent ${name}`);
|
|
326
|
+
lines.push("");
|
|
327
|
+
for (const file of options.files) {
|
|
328
|
+
// Empty-dir placeholders stay on disk but clutter the summary.
|
|
329
|
+
if (file.path.endsWith("/.gitkeep") || file.path === ".gitkeep") {
|
|
330
|
+
continue;
|
|
331
|
+
}
|
|
332
|
+
// Thor/Rails status column is 12 chars, right-aligned.
|
|
333
|
+
lines.push(c.dim(`${file.action.padStart(12)} ${file.path}`));
|
|
334
|
+
}
|
|
335
|
+
lines.push("");
|
|
336
|
+
lines.push(c.dim(`Project: ${options.rootDir}`));
|
|
337
|
+
lines.push("");
|
|
338
|
+
return `${lines.join("\n")}\n`;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Numbered next steps after scaffold (and after login when init ran it).
|
|
343
|
+
* Includes `cd` when init did not already run inside the project.
|
|
344
|
+
*/
|
|
345
|
+
export function formatInitNextSteps(options: InitNextStepsOptions): string {
|
|
346
|
+
const c = initPalette(options.color);
|
|
347
|
+
const lines: string[] = [];
|
|
348
|
+
lines.push("Next steps:");
|
|
349
|
+
lines.push("");
|
|
350
|
+
|
|
351
|
+
const steps = initNextStepEntries(options);
|
|
352
|
+
const width = Math.max(...steps.map((step) => step.command.length));
|
|
353
|
+
for (const [index, step] of steps.entries()) {
|
|
354
|
+
const command =
|
|
355
|
+
step.note === undefined
|
|
356
|
+
? step.command
|
|
357
|
+
: `${step.command.padEnd(width)} ${c.dim(`# ${step.note}`)}`;
|
|
358
|
+
lines.push(` ${index + 1}. ${command}`);
|
|
359
|
+
}
|
|
360
|
+
return `${lines.join("\n")}\n`;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Full human-readable scaffold summary (scaffold + next steps).
|
|
365
|
+
*/
|
|
366
|
+
export function formatInitSummary(options: InitSummaryOptions): string {
|
|
367
|
+
return formatInitScaffoldSummary(options) + formatInitNextSteps(options);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* `cd` into the scaffold when init did not already run inside it. Relative
|
|
372
|
+
* when the target sits under the invoking directory, absolute otherwise.
|
|
373
|
+
*/
|
|
374
|
+
export function formatCdCommand(
|
|
375
|
+
cwd: string,
|
|
376
|
+
rootDir: string
|
|
377
|
+
): string | undefined {
|
|
378
|
+
const rel = relative(cwd, rootDir);
|
|
379
|
+
if (rel === "") {
|
|
380
|
+
return undefined;
|
|
381
|
+
}
|
|
382
|
+
const path = rel.startsWith("..") ? rootDir : rel;
|
|
383
|
+
const quoted = /\s/.test(path) ? JSON.stringify(path) : path;
|
|
384
|
+
return `cd ${quoted}`;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
function initNextStepEntries(options: InitNextStepsOptions): Array<{
|
|
388
|
+
command: string;
|
|
389
|
+
note?: string;
|
|
390
|
+
}> {
|
|
391
|
+
const steps: Array<{ command: string; note?: string }> = [];
|
|
392
|
+
const cd = formatCdCommand(options.cwd, options.rootDir);
|
|
393
|
+
if (cd !== undefined) {
|
|
394
|
+
steps.push({ command: cd });
|
|
395
|
+
}
|
|
396
|
+
if (!options.signedIn) {
|
|
397
|
+
steps.push({
|
|
398
|
+
command: `${CLI_COMMAND_NAME} login`,
|
|
399
|
+
note: "connect your Cursor account (powers model turns)",
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
steps.push({
|
|
403
|
+
command: `${CLI_COMMAND_NAME} dev`,
|
|
404
|
+
note: "start the local playground",
|
|
405
|
+
});
|
|
406
|
+
return steps;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Next-step commands for the `--json` scaffold summary (login omitted when
|
|
411
|
+
* the host already has a Cursor credential).
|
|
412
|
+
*/
|
|
413
|
+
export function initNextCommands(options: {
|
|
414
|
+
rootDir: string;
|
|
415
|
+
cwd: string;
|
|
416
|
+
signedIn: boolean;
|
|
417
|
+
}): string[] {
|
|
418
|
+
return initNextStepEntries(options).map((step) => step.command);
|
|
419
|
+
}
|
|
420
|
+
|
|
140
421
|
/**
|
|
141
422
|
* Coding-agent setup guide printed by `agent-serve init`
|
|
142
423
|
* with no target directory (does not scaffold).
|
|
@@ -144,15 +425,16 @@ ${model.params
|
|
|
144
425
|
export function printInitGuide(): void {
|
|
145
426
|
process.stdout.write(`${CLI_COMMAND_NAME} — coding agent setup
|
|
146
427
|
|
|
147
|
-
|
|
428
|
+
Scaffold a project, then open the playground:
|
|
429
|
+
${CLI_COMMAND_NAME} init ./my-agent # installs deps; signs you in when needed
|
|
430
|
+
cd ./my-agent && ${CLI_COMMAND_NAME} dev
|
|
431
|
+
|
|
432
|
+
Recommended loop once the project exists:
|
|
148
433
|
1. Edit agent/ + tools under agent/tools/
|
|
149
434
|
2. ${CLI_COMMAND_NAME} info --dir . --json
|
|
150
435
|
3. ${CLI_COMMAND_NAME} run --dir . --message "..."
|
|
151
436
|
4. ${CLI_COMMAND_NAME} eval --dir .
|
|
152
437
|
|
|
153
|
-
Scaffold a project:
|
|
154
|
-
${CLI_COMMAND_NAME} init ./my-agent
|
|
155
|
-
|
|
156
438
|
Evals:
|
|
157
439
|
Create evals/**/*.eval.ts using defineEval from ${PACKAGE_NAME}/evals
|
|
158
440
|
Case id is the path: evals/weather/nyc.eval.ts → weather/nyc
|