cursor-route 0.1.7 → 0.1.9
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/CHANGELOG.md +22 -0
- package/CONTRIBUTING.md +1 -0
- package/README.md +52 -10
- package/SUPPORT.md +1 -0
- package/dist/adapters/claude-ds.js +18 -0
- package/dist/adapters/deepseek.js +127 -8
- package/dist/cli.js +13 -8
- package/dist/config.js +5 -2
- package/dist/health.js +16 -0
- package/dist/jobs.js +29 -2
- package/docs/DEMO_GIF.md +17 -1
- package/docs/briefs/WORKING.md +16 -7
- package/docs/demo-notes.md +6 -3
- package/docs/fixtures/generate-hero-demo.sh +109 -0
- package/docs/fixtures/hero-demo.log +53 -0
- package/llms.txt +1 -1
- package/package.json +1 -1
- package/skills/route-orch/SKILL.md +45 -8
- package/src/adapters/claude-ds.ts +19 -0
- package/src/adapters/deepseek.ts +145 -11
- package/src/adapters/types.ts +3 -1
- package/src/cli.test.ts +465 -27
- package/src/cli.ts +13 -7
- package/src/config.ts +9 -3
- package/src/health.ts +21 -0
- package/src/jobs.ts +54 -4
package/src/health.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { execSync } from "node:child_process";
|
|
2
2
|
import { allAdapters } from "./adapters/index.ts";
|
|
3
|
+
import { isMidDeepSeekProven, midDeepSeekProofDetail } from "./adapters/claude-ds.ts";
|
|
3
4
|
import { config } from "./config.ts";
|
|
4
5
|
import { isTmuxAvailable } from "./tmux.ts";
|
|
5
6
|
import { commandExists } from "./util.ts";
|
|
@@ -13,6 +14,9 @@ export interface HealthReport {
|
|
|
13
14
|
ok: boolean;
|
|
14
15
|
detail: string;
|
|
15
16
|
}>;
|
|
17
|
+
lanes: {
|
|
18
|
+
mid: { worker: "claude-ds"; deepseek: boolean; detail: string };
|
|
19
|
+
};
|
|
16
20
|
}
|
|
17
21
|
|
|
18
22
|
export function runHealth(): HealthReport {
|
|
@@ -58,6 +62,15 @@ export function runHealth(): HealthReport {
|
|
|
58
62
|
});
|
|
59
63
|
}
|
|
60
64
|
|
|
65
|
+
// Informational: mid is proven DeepSeek (not the overall OR-gate).
|
|
66
|
+
const midOk = isMidDeepSeekProven();
|
|
67
|
+
const midDetail = midDeepSeekProofDetail();
|
|
68
|
+
checks.push({
|
|
69
|
+
name: "lane:mid",
|
|
70
|
+
ok: midOk,
|
|
71
|
+
detail: midDetail,
|
|
72
|
+
});
|
|
73
|
+
|
|
61
74
|
// Optional supervisor probe (v0 skill-only; Cursor CLI agent is informational)
|
|
62
75
|
const agentBin =
|
|
63
76
|
(commandExists("agent") && "agent") ||
|
|
@@ -99,6 +112,9 @@ export function runHealth(): HealthReport {
|
|
|
99
112
|
product: config.product,
|
|
100
113
|
version: config.version,
|
|
101
114
|
checks,
|
|
115
|
+
lanes: {
|
|
116
|
+
mid: { worker: "claude-ds", deepseek: midOk, detail: midDetail },
|
|
117
|
+
},
|
|
102
118
|
};
|
|
103
119
|
}
|
|
104
120
|
|
|
@@ -118,5 +134,10 @@ export function printHealth(report: HealthReport, asJson: boolean): void {
|
|
|
118
134
|
console.log("");
|
|
119
135
|
console.log("Fix the ✗ items, then re-run: cursor-route health");
|
|
120
136
|
console.log("Tip: start with one worker (grok OR claude-ds) before parallel demos.");
|
|
137
|
+
} else if (report.checks.some((c) => c.name === "lane:mid" && !c.ok)) {
|
|
138
|
+
console.log("");
|
|
139
|
+
console.log(
|
|
140
|
+
"Tip: health OK without a DeepSeek mid — --lane mid will fail until lane:mid is ✓.",
|
|
141
|
+
);
|
|
121
142
|
}
|
|
122
143
|
}
|
package/src/jobs.ts
CHANGED
|
@@ -37,7 +37,7 @@ export interface Job {
|
|
|
37
37
|
status: JobStatus;
|
|
38
38
|
worker: WorkerKind;
|
|
39
39
|
lane?: Lane;
|
|
40
|
-
/** Mid-lane DeepSeek model alias (flash|pro).
|
|
40
|
+
/** Mid-lane DeepSeek model alias (flash|pro). Set for claude-ds and deepseek. */
|
|
41
41
|
model?: DsModelAlias;
|
|
42
42
|
prompt: string;
|
|
43
43
|
cwd: string;
|
|
@@ -105,6 +105,53 @@ export function writeJob(job: Job): void {
|
|
|
105
105
|
writeSecure(jobPaths(job.id).json, JSON.stringify(job, null, 2));
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
+
/** Evidence tree for status --json. Parent must capture; claim is never auto-green. */
|
|
109
|
+
export interface JobEvidence {
|
|
110
|
+
spawn: {
|
|
111
|
+
jobId: string;
|
|
112
|
+
worker: WorkerKind;
|
|
113
|
+
lane: Lane | null;
|
|
114
|
+
model: DsModelAlias | null;
|
|
115
|
+
startedAt: string;
|
|
116
|
+
};
|
|
117
|
+
execute: {
|
|
118
|
+
status: JobStatus;
|
|
119
|
+
exitCode: number | null;
|
|
120
|
+
tmuxSession: string;
|
|
121
|
+
pid: number | null;
|
|
122
|
+
sessionAlive: boolean;
|
|
123
|
+
};
|
|
124
|
+
verify: {
|
|
125
|
+
captureHint: string;
|
|
126
|
+
logBytes: number | null;
|
|
127
|
+
claim: "unverified";
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function jobEvidence(job: Job, sessionAlive: boolean): JobEvidence {
|
|
132
|
+
return {
|
|
133
|
+
spawn: {
|
|
134
|
+
jobId: job.id,
|
|
135
|
+
worker: job.worker,
|
|
136
|
+
lane: job.lane ?? null,
|
|
137
|
+
model: job.model ?? null,
|
|
138
|
+
startedAt: job.startedAt ?? job.createdAt,
|
|
139
|
+
},
|
|
140
|
+
execute: {
|
|
141
|
+
status: job.status,
|
|
142
|
+
exitCode: job.exitCode ?? null,
|
|
143
|
+
tmuxSession: job.tmuxSession,
|
|
144
|
+
pid: job.pid ?? null,
|
|
145
|
+
sessionAlive,
|
|
146
|
+
},
|
|
147
|
+
verify: {
|
|
148
|
+
captureHint: `cursor-route capture ${job.id}`,
|
|
149
|
+
logBytes: job.logBytes ?? null,
|
|
150
|
+
claim: "unverified",
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
|
|
108
155
|
function pidAlive(pid: number): boolean {
|
|
109
156
|
try {
|
|
110
157
|
process.kill(pid, 0);
|
|
@@ -118,6 +165,8 @@ function pidAlive(pid: number): boolean {
|
|
|
118
165
|
encoding: "utf8",
|
|
119
166
|
stdio: ["ignore", "pipe", "ignore"],
|
|
120
167
|
});
|
|
168
|
+
// spawnSync does not throw on EPERM (macOS sandbox); empty stdout is not "dead".
|
|
169
|
+
if (r.error || r.status !== 0) return true;
|
|
121
170
|
const state = (r.stdout || "").trim();
|
|
122
171
|
return state !== "" && !state.startsWith("Z");
|
|
123
172
|
} catch {
|
|
@@ -231,7 +280,7 @@ export interface StartOptions {
|
|
|
231
280
|
prompt: string;
|
|
232
281
|
worker?: WorkerKind;
|
|
233
282
|
lane?: Lane;
|
|
234
|
-
/** Mid-lane DeepSeek: flash (default) | pro. Ignored by grok/openrouter. */
|
|
283
|
+
/** Mid-lane DeepSeek: flash (default) | pro (claude-ds + deepseek). Ignored by grok/openrouter. */
|
|
235
284
|
model?: DsModelAlias;
|
|
236
285
|
/** Concrete DeepSeek id (preserves pro[1m]). Derived from --model / env when unset. */
|
|
237
286
|
modelId?: string;
|
|
@@ -284,7 +333,7 @@ export function startJob(opts: StartOptions): {
|
|
|
284
333
|
|
|
285
334
|
let model: DsModelAlias | undefined;
|
|
286
335
|
let modelId: string | undefined;
|
|
287
|
-
if (worker === "claude-ds") {
|
|
336
|
+
if (worker === "claude-ds" || worker === "deepseek") {
|
|
288
337
|
if (opts.model) {
|
|
289
338
|
model = opts.model;
|
|
290
339
|
modelId = opts.modelId ?? DS_MODEL_IDS[opts.model];
|
|
@@ -312,6 +361,7 @@ export function startJob(opts: StartOptions): {
|
|
|
312
361
|
alwaysApprove,
|
|
313
362
|
model,
|
|
314
363
|
modelId,
|
|
364
|
+
dryRun: Boolean(opts.dryRun),
|
|
315
365
|
});
|
|
316
366
|
} catch (e) {
|
|
317
367
|
try {
|
|
@@ -493,7 +543,7 @@ export function cleanJobs(olderThanDays = 7): number {
|
|
|
493
543
|
t < cutoff &&
|
|
494
544
|
(job.status === "completed" || job.status === "failed" || job.status === "killed")
|
|
495
545
|
) {
|
|
496
|
-
for (const ext of [".json", ".prompt", ".log"] as const) {
|
|
546
|
+
for (const ext of [".json", ".prompt", ".log", ".dsh-patch.yml"] as const) {
|
|
497
547
|
const fp = underJobsDir(id, ext);
|
|
498
548
|
if (existsSync(fp)) unlinkSync(fp);
|
|
499
549
|
}
|