@blxzer/cursor-trellis 0.3.4 → 0.3.5

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.
Files changed (95) hide show
  1. package/README.md +0 -13
  2. package/README.zh-CN.md +1 -1
  3. package/bin/cstl.js +1 -1
  4. package/bin/smart-search.js +1 -1
  5. package/dist/cli/index.d.ts.map +1 -1
  6. package/dist/cli/index.js +14 -2
  7. package/dist/cli/index.js.map +1 -1
  8. package/dist/commands/campaign/canvas-render.d.ts +68 -0
  9. package/dist/commands/campaign/canvas-render.d.ts.map +1 -0
  10. package/dist/commands/campaign/canvas-render.js +414 -0
  11. package/dist/commands/campaign/canvas-render.js.map +1 -0
  12. package/dist/commands/campaign/compose.d.ts +15 -0
  13. package/dist/commands/campaign/compose.d.ts.map +1 -0
  14. package/dist/commands/campaign/compose.js +110 -0
  15. package/dist/commands/campaign/compose.js.map +1 -0
  16. package/dist/commands/campaign/index.d.ts +13 -0
  17. package/dist/commands/campaign/index.d.ts.map +1 -0
  18. package/dist/commands/campaign/index.js +134 -0
  19. package/dist/commands/campaign/index.js.map +1 -0
  20. package/dist/commands/campaign/kind-map.d.ts +6 -0
  21. package/dist/commands/campaign/kind-map.d.ts.map +1 -0
  22. package/dist/commands/campaign/kind-map.js +21 -0
  23. package/dist/commands/campaign/kind-map.js.map +1 -0
  24. package/dist/commands/campaign/mcp-server.d.ts +6 -0
  25. package/dist/commands/campaign/mcp-server.d.ts.map +1 -0
  26. package/dist/commands/campaign/mcp-server.js +167 -0
  27. package/dist/commands/campaign/mcp-server.js.map +1 -0
  28. package/dist/commands/campaign/render.d.ts +5 -0
  29. package/dist/commands/campaign/render.d.ts.map +1 -0
  30. package/dist/commands/campaign/render.js +103 -0
  31. package/dist/commands/campaign/render.js.map +1 -0
  32. package/dist/commands/campaign/trellis-load.d.ts +13 -0
  33. package/dist/commands/campaign/trellis-load.d.ts.map +1 -0
  34. package/dist/commands/campaign/trellis-load.js +122 -0
  35. package/dist/commands/campaign/trellis-load.js.map +1 -0
  36. package/dist/commands/campaign/types.d.ts +61 -0
  37. package/dist/commands/campaign/types.d.ts.map +1 -0
  38. package/dist/commands/campaign/types.js +3 -0
  39. package/dist/commands/campaign/types.js.map +1 -0
  40. package/dist/commands/init.d.ts.map +1 -1
  41. package/dist/commands/init.js +11 -1
  42. package/dist/commands/init.js.map +1 -1
  43. package/dist/commands/rpc/client.d.ts +51 -0
  44. package/dist/commands/rpc/client.d.ts.map +1 -0
  45. package/dist/commands/rpc/client.js +147 -0
  46. package/dist/commands/rpc/client.js.map +1 -0
  47. package/dist/commands/rpc/index.d.ts +10 -0
  48. package/dist/commands/rpc/index.d.ts.map +1 -0
  49. package/dist/commands/rpc/index.js +157 -0
  50. package/dist/commands/rpc/index.js.map +1 -0
  51. package/dist/commands/rpc/serve.d.ts +23 -0
  52. package/dist/commands/rpc/serve.d.ts.map +1 -0
  53. package/dist/commands/rpc/serve.js +60 -0
  54. package/dist/commands/rpc/serve.js.map +1 -0
  55. package/dist/commands/rpc/smoke.d.ts +16 -0
  56. package/dist/commands/rpc/smoke.d.ts.map +1 -0
  57. package/dist/commands/rpc/smoke.js +92 -0
  58. package/dist/commands/rpc/smoke.js.map +1 -0
  59. package/dist/commands/sdk/index.d.ts +9 -0
  60. package/dist/commands/sdk/index.d.ts.map +1 -0
  61. package/dist/commands/sdk/index.js +58 -0
  62. package/dist/commands/sdk/index.js.map +1 -0
  63. package/dist/commands/sdk/run.d.ts +42 -0
  64. package/dist/commands/sdk/run.d.ts.map +1 -0
  65. package/dist/commands/sdk/run.js +245 -0
  66. package/dist/commands/sdk/run.js.map +1 -0
  67. package/dist/commands/sdk/status.d.ts +14 -0
  68. package/dist/commands/sdk/status.d.ts.map +1 -0
  69. package/dist/commands/sdk/status.js +69 -0
  70. package/dist/commands/sdk/status.js.map +1 -0
  71. package/dist/templates/common/bundled-skills/smart-search-cli/SKILL.md +35 -29
  72. package/dist/templates/common/bundled-skills/smart-search-cli/references/cli-contract.md +11 -25
  73. package/dist/templates/cursor/rules/retrieval-routing.mdc +1 -1
  74. package/dist/templates/markdown/agents.md +2 -0
  75. package/dist/templates/markdown/spec/guides/retrieval-daily-guide.md.txt +14 -0
  76. package/dist/templates/trellis/scripts/common/codebase_retrieval_router.py +14 -0
  77. package/dist/templates/trellis/scripts/common/parent_orchestration.py +341 -2
  78. package/dist/templates/trellis/scripts/common/task_map.py +638 -614
  79. package/dist/templates/trellis/scripts/common/task_store.py +47 -1
  80. package/dist/templates/trellis/scripts/task.py +32 -0
  81. package/dist/utils/codebase-retrieval-router.d.ts.map +1 -1
  82. package/dist/utils/codebase-retrieval-router.js +14 -0
  83. package/dist/utils/codebase-retrieval-router.js.map +1 -1
  84. package/dist/utils/cursor-sdk-gate.d.ts +10 -0
  85. package/dist/utils/cursor-sdk-gate.d.ts.map +1 -0
  86. package/dist/utils/cursor-sdk-gate.js +32 -0
  87. package/dist/utils/cursor-sdk-gate.js.map +1 -0
  88. package/dist/utils/project-capabilities.d.ts +30 -3
  89. package/dist/utils/project-capabilities.d.ts.map +1 -1
  90. package/dist/utils/project-capabilities.js +182 -11
  91. package/dist/utils/project-capabilities.js.map +1 -1
  92. package/dist/utils/readiness.d.ts.map +1 -1
  93. package/dist/utils/readiness.js +26 -0
  94. package/dist/utils/readiness.js.map +1 -1
  95. package/package.json +4 -3
@@ -0,0 +1,42 @@
1
+ export type SdkRunMode = "mock" | "live";
2
+ export interface SdkRunOptions {
3
+ task: string;
4
+ campaign: string;
5
+ mode: SdkRunMode;
6
+ prompt?: string;
7
+ cwd?: string;
8
+ rpcUrl?: string;
9
+ token?: string;
10
+ noRpc?: boolean;
11
+ /** When set, write dogfood under this absolute path instead of <task>/research/ */
12
+ evidencePath?: string;
13
+ }
14
+ export interface SdkRunResult {
15
+ ok: boolean;
16
+ runId: string;
17
+ mode: SdkRunMode;
18
+ taskPath: string;
19
+ evidencePath: string;
20
+ rpc: {
21
+ attempted: boolean;
22
+ ok: boolean;
23
+ url?: string;
24
+ detail: string;
25
+ };
26
+ agent: {
27
+ status: string;
28
+ result: string;
29
+ };
30
+ errors: string[];
31
+ }
32
+ /**
33
+ * Build the Agent prompt for SDK RUN. Always prepends an explicit --task binding
34
+ * block so SessionStart "Selected task: none" cannot be misread as unbound.
35
+ */
36
+ export declare function buildSdkRunPrompt(taskPath: string, userPrompt?: string): string;
37
+ /**
38
+ * Minimal Trellis SDK RUN: bind explicit task path, run mock/live agent, write dogfood, emit RPC.
39
+ */
40
+ export declare function runSdkRun(options: SdkRunOptions): Promise<SdkRunResult>;
41
+ export declare function runSdkRunCommand(options: SdkRunOptions): Promise<number>;
42
+ //# sourceMappingURL=run.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/commands/sdk/run.ts"],"names":[],"mappings":"AAaA,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,MAAM,CAAC;AAEzC,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,mFAAmF;IACnF,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,GAAG,EAAE;QACH,SAAS,EAAE,OAAO,CAAC;QACnB,EAAE,EAAE,OAAO,CAAC;QACZ,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,KAAK,EAAE;QACL,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAqBD;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,MAAM,GAClB,MAAM,CAeR;AAyKD;;GAEG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CAkE7E;AAED,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,MAAM,CAAC,CAuBjB"}
@@ -0,0 +1,245 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { randomUUID } from "node:crypto";
4
+ import { campaignBroadcastTopic } from "@blxzer/cursor-trellis-core/rpc";
5
+ import { resolveRpcToken, resolveRpcUrl, rpcPublish, rpcRegister, } from "../rpc/client.js";
6
+ const DEFAULT_PROMPT = "Trellis SDK RUN (S1 worker): confirm task path binding by restating the absolute taskPath; do not call integrate-child or start-execution --approved; summarize readiness in one short paragraph.";
7
+ function resolveTaskPath(taskArg) {
8
+ return path.resolve(process.cwd(), taskArg);
9
+ }
10
+ function assertTaskDir(taskPath) {
11
+ if (!fs.existsSync(taskPath) || !fs.statSync(taskPath).isDirectory()) {
12
+ throw new Error(`Task path is not a directory: ${taskPath}`);
13
+ }
14
+ const prd = path.join(taskPath, "prd.md");
15
+ if (!fs.existsSync(prd)) {
16
+ throw new Error(`Task path missing prd.md (refusing unbound SDK RUN; pass --task <dir> that contains prd.md): ${prd}`);
17
+ }
18
+ }
19
+ /**
20
+ * Build the Agent prompt for SDK RUN. Always prepends an explicit --task binding
21
+ * block so SessionStart "Selected task: none" cannot be misread as unbound.
22
+ */
23
+ export function buildSdkRunPrompt(taskPath, userPrompt) {
24
+ const absoluteTask = path.resolve(taskPath);
25
+ const prdPath = path.join(absoluteTask, "prd.md");
26
+ const instruction = userPrompt?.trim() || DEFAULT_PROMPT;
27
+ return [
28
+ "## SDK RUN task binding (authoritative)",
29
+ `- Bound via CLI \`--task\` (not \`selected_task\` / SessionStart).`,
30
+ `- taskPath (absolute): \`${absoluteTask}\``,
31
+ `- prd.md (absolute): \`${prdPath}\``,
32
+ `- Binding status: **BOUND**.`,
33
+ `- Do **not** report unbound solely because SessionStart says \`Selected task: none\` — that pointer is irrelevant for SDK RUN.`,
34
+ "",
35
+ "## Instructions",
36
+ instruction,
37
+ ].join("\n");
38
+ }
39
+ async function runMockAgent(prompt) {
40
+ return {
41
+ status: "completed",
42
+ result: `[mock] SDK RUN accepted prompt (${prompt.length} chars). No @cursor/sdk call. CAP: safe-task/SDK only; no Parent integrate.`,
43
+ };
44
+ }
45
+ async function runLiveAgent(prompt, cwd) {
46
+ const apiKey = process.env.CURSOR_API_KEY?.trim();
47
+ if (!apiKey) {
48
+ throw new Error([
49
+ "Live SDK RUN requires CURSOR_API_KEY (and prior user consent to use it).",
50
+ "Use --mock or omit --live.",
51
+ "Discovery: run `cstl sdk status` for setup steps (never commit the key).",
52
+ ].join(" "));
53
+ }
54
+ let Agent;
55
+ try {
56
+ // Avoid static resolution so mock/CI builds do not require @cursor/sdk installed.
57
+ const dynamicImport = new Function("specifier", "return import(specifier)");
58
+ const mod = await dynamicImport("@cursor/sdk");
59
+ Agent = mod.Agent;
60
+ }
61
+ catch {
62
+ throw new Error("@cursor/sdk is not installed. After explicit consent, add the optional dependency, or use --mock.");
63
+ }
64
+ const outcome = await Agent.prompt(prompt, {
65
+ apiKey,
66
+ model: { id: "composer-2.5" },
67
+ local: { cwd },
68
+ });
69
+ return {
70
+ status: outcome.status ?? "unknown",
71
+ result: outcome.result ?? "",
72
+ };
73
+ }
74
+ function writeDogfoodEvidence(options) {
75
+ const dir = path.dirname(options.evidencePath);
76
+ fs.mkdirSync(dir, { recursive: true });
77
+ const body = `# SDK RUN dogfood
78
+
79
+ generated: ${new Date().toISOString()}
80
+ runId: \`${options.result.runId}\`
81
+ mode: \`${options.result.mode}\`
82
+ taskPath: \`${options.result.taskPath}\`
83
+
84
+ ## Agent
85
+
86
+ - status: \`${options.result.agent.status}\`
87
+ - result:
88
+
89
+ \`\`\`text
90
+ ${options.result.agent.result}
91
+ \`\`\`
92
+
93
+ ## RPC
94
+
95
+ - attempted: ${options.result.rpc.attempted}
96
+ - ok: ${options.result.rpc.ok}
97
+ - url: ${options.result.rpc.url ?? "(none)"}
98
+ - detail: ${options.result.rpc.detail}
99
+
100
+ ## CAP / HITL
101
+
102
+ - Claim: SDK / safe-task automation RUN only
103
+ - Does **not** call \`task.py start-execution --approved\` or \`integrate-child\`
104
+ - Not an IDE chat tab
105
+
106
+ ## Errors
107
+
108
+ ${options.result.errors.length === 0
109
+ ? "(none)"
110
+ : options.result.errors.map((e) => `- ${e}`).join("\n")}
111
+ `;
112
+ fs.writeFileSync(options.evidencePath, body, "utf-8");
113
+ }
114
+ async function emitRpcEvents(options) {
115
+ const from = { kind: "sdk", id: options.runId };
116
+ const topic = campaignBroadcastTopic(options.campaign);
117
+ const reg = await rpcRegister({
118
+ url: options.url,
119
+ kind: from.kind,
120
+ id: from.id,
121
+ campaignId: options.campaign,
122
+ token: options.token,
123
+ });
124
+ if (reg.error) {
125
+ return {
126
+ ok: false,
127
+ detail: `register failed: ${reg.error.code} ${reg.error.message}`,
128
+ };
129
+ }
130
+ const body = {
131
+ event: "trellis.child.state",
132
+ taskPath: options.taskPath,
133
+ mode: options.mode,
134
+ status: options.status,
135
+ runId: options.runId,
136
+ clientKind: "sdk",
137
+ };
138
+ const published = await rpcPublish({
139
+ url: options.url,
140
+ from,
141
+ topic,
142
+ campaignId: options.campaign,
143
+ body,
144
+ token: options.token,
145
+ });
146
+ if (published.error) {
147
+ return {
148
+ ok: false,
149
+ detail: `publish failed: ${published.error.code} ${published.error.message}`,
150
+ };
151
+ }
152
+ const delivered = typeof published.payload.delivered === "number"
153
+ ? published.payload.delivered
154
+ : 0;
155
+ return {
156
+ ok: true,
157
+ detail: `registered sdk:${options.runId}; published ${topic} (delivered=${delivered})`,
158
+ };
159
+ }
160
+ /**
161
+ * Minimal Trellis SDK RUN: bind explicit task path, run mock/live agent, write dogfood, emit RPC.
162
+ */
163
+ export async function runSdkRun(options) {
164
+ const errors = [];
165
+ const runId = randomUUID().slice(0, 8);
166
+ const taskPath = resolveTaskPath(options.task);
167
+ assertTaskDir(taskPath);
168
+ const cwd = options.cwd ? path.resolve(options.cwd) : process.cwd();
169
+ const prompt = buildSdkRunPrompt(taskPath, options.prompt);
170
+ const evidencePath = options.evidencePath ??
171
+ path.join(taskPath, "research", "sdk-run-dogfood.md");
172
+ let agent;
173
+ if (options.mode === "live") {
174
+ agent = await runLiveAgent(prompt, cwd);
175
+ }
176
+ else {
177
+ agent = await runMockAgent(prompt);
178
+ }
179
+ let rpc = {
180
+ attempted: false,
181
+ ok: false,
182
+ detail: "skipped (--no-rpc)",
183
+ };
184
+ if (!options.noRpc) {
185
+ const url = resolveRpcUrl(options.rpcUrl);
186
+ const token = resolveRpcToken(options.token);
187
+ rpc = { attempted: true, ok: false, url, detail: "" };
188
+ try {
189
+ const outcome = await emitRpcEvents({
190
+ url,
191
+ token,
192
+ runId,
193
+ campaign: options.campaign,
194
+ taskPath,
195
+ mode: options.mode,
196
+ status: agent.status,
197
+ });
198
+ rpc.ok = outcome.ok;
199
+ rpc.detail = outcome.detail;
200
+ if (!outcome.ok) {
201
+ errors.push(`rpc: ${outcome.detail}`);
202
+ }
203
+ }
204
+ catch (error) {
205
+ const message = error instanceof Error ? error.message : String(error);
206
+ rpc.ok = false;
207
+ rpc.detail = `unavailable: ${message}`;
208
+ errors.push(`rpc: ${rpc.detail}`);
209
+ }
210
+ }
211
+ const partial = {
212
+ runId,
213
+ mode: options.mode,
214
+ taskPath,
215
+ evidencePath,
216
+ rpc,
217
+ agent,
218
+ errors,
219
+ };
220
+ writeDogfoodEvidence({ evidencePath, result: partial });
221
+ // RPC degrade is allowed (LAYERED); validation failures already threw.
222
+ const ok = options.mode === "mock" || agent.status.length > 0;
223
+ return { ok, ...partial };
224
+ }
225
+ export async function runSdkRunCommand(options) {
226
+ try {
227
+ const result = await runSdkRun(options);
228
+ if (result.ok) {
229
+ console.log(`SDK RUN OK mode=${result.mode} runId=${result.runId} task=${result.taskPath}`);
230
+ console.log(`evidence: ${result.evidencePath}`);
231
+ console.log(`rpc: ${result.rpc.detail}`);
232
+ if (result.errors.length > 0) {
233
+ console.warn(`notes: ${result.errors.join("; ")}`);
234
+ }
235
+ return 0;
236
+ }
237
+ console.error(`SDK RUN FAILED: ${result.errors.join("; ") || "unknown"}`);
238
+ return 1;
239
+ }
240
+ catch (error) {
241
+ console.error("SDK RUN error:", error instanceof Error ? error.message : error);
242
+ return 1;
243
+ }
244
+ }
245
+ //# sourceMappingURL=run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../../src/commands/sdk/run.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ export type SdkStatusResult = {
2
+ ok: boolean;
3
+ cwd: string;
4
+ keyPresent: boolean;
5
+ capabilitySelected: boolean;
6
+ sdkModuleResolvable: boolean | null;
7
+ nextSteps: string[];
8
+ };
9
+ export declare function collectSdkStatus(cwd?: string): Promise<SdkStatusResult>;
10
+ export declare function runSdkStatusCommand(options?: {
11
+ cwd?: string;
12
+ json?: boolean;
13
+ }): Promise<number>;
14
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/commands/sdk/status.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,EAAE,OAAO,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,OAAO,CAAC;IACpB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,mBAAmB,EAAE,OAAO,GAAG,IAAI,CAAC;IACpC,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB,CAAC;AAeF,wBAAsB,gBAAgB,CACpC,GAAG,GAAE,MAAsB,GAC1B,OAAO,CAAC,eAAe,CAAC,CAoC1B;AAED,wBAAsB,mBAAmB,CAAC,OAAO,CAAC,EAAE;IAClD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CAmClB"}
@@ -0,0 +1,69 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { cursorApiKeySetupGuide, hasCursorApiKey, } from "../../utils/cursor-sdk-gate.js";
4
+ import { loadProjectCapabilities } from "../../utils/project-capabilities.js";
5
+ async function probeSdkModuleResolvable() {
6
+ try {
7
+ const dynamicImport = new Function("specifier", "return import(specifier)");
8
+ await dynamicImport("@cursor/sdk");
9
+ return true;
10
+ }
11
+ catch {
12
+ return false;
13
+ }
14
+ }
15
+ export async function collectSdkStatus(cwd = process.cwd()) {
16
+ const keyPresent = hasCursorApiKey();
17
+ const selected = loadProjectCapabilities(cwd);
18
+ const capabilitySelected = selected.includes("cursor-sdk");
19
+ const sdkModuleResolvable = await probeSdkModuleResolvable();
20
+ const nextSteps = [];
21
+ if (!keyPresent) {
22
+ nextSteps.push("Set CURSOR_API_KEY in this process, then re-run `cstl sdk status` or re-select `cursor-sdk` during init/update.");
23
+ nextSteps.push("Use `cstl sdk run --task <path> --mock` without a key.");
24
+ }
25
+ else {
26
+ nextSteps.push("Key present. You may enable `cursor-sdk` at init/update and use `cstl sdk run --task <path> --live` after accepting billing/privacy risk.");
27
+ }
28
+ if (!capabilitySelected && fs.existsSync(path.join(cwd, ".cstl"))) {
29
+ nextSteps.push("Project has `.cstl/` but `cursor-sdk` is not in `.cstl/capabilities.json` selected list.");
30
+ }
31
+ if (sdkModuleResolvable === false) {
32
+ nextSteps.push("@cursor/sdk could not be imported from this CLI install; reinstall cursor-trellis / @blxzer/cursor-trellis.");
33
+ }
34
+ return {
35
+ ok: keyPresent,
36
+ cwd,
37
+ keyPresent,
38
+ capabilitySelected,
39
+ sdkModuleResolvable,
40
+ nextSteps,
41
+ };
42
+ }
43
+ export async function runSdkStatusCommand(options) {
44
+ const cwd = options?.cwd ? path.resolve(options.cwd) : process.cwd();
45
+ const status = await collectSdkStatus(cwd);
46
+ if (options?.json) {
47
+ console.log(JSON.stringify(status, null, 2));
48
+ return status.keyPresent ? 0 : 1;
49
+ }
50
+ console.log("Cursor SDK status");
51
+ console.log(` cwd: ${status.cwd}`);
52
+ console.log(` CURSOR_API_KEY: ${status.keyPresent ? "present" : "missing"} (value never printed)`);
53
+ console.log(` capability cursor-sdk selected: ${status.capabilitySelected ? "yes" : "no"}`);
54
+ console.log(` @cursor/sdk importable from CLI: ${status.sdkModuleResolvable === null
55
+ ? "unknown"
56
+ : status.sdkModuleResolvable
57
+ ? "yes"
58
+ : "no"}`);
59
+ console.log(" next steps:");
60
+ for (const step of status.nextSteps) {
61
+ console.log(` - ${step}`);
62
+ }
63
+ if (!status.keyPresent) {
64
+ console.log("");
65
+ console.log(cursorApiKeySetupGuide());
66
+ }
67
+ return status.keyPresent ? 0 : 1;
68
+ }
69
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/commands/sdk/status.ts"],"names":[],"mappings":"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"}
@@ -14,18 +14,17 @@ Use the local `smart-search` command as the default execution layer for web rese
14
14
  3. If OpenAI-compatible `search` hangs or times out after `doctor` succeeds, run `smart-search diagnose openai-compatible --format markdown` and use its summary/recommendation. This one command tests quick chat plus real search-shape `stream=false` and `stream=true`.
15
15
  4. If `doctor` returns `ok: true`, use only `smart-search` CLI subcommands for web research. Do not call Codex native web search in the same task.
16
16
  5. For every research question, run a bilingual `smart-search search` pair: one Chinese-source query and one English-source query. Save both JSON outputs.
17
- 6. Use `smart-search search` as the first hop for realtime, broad exploration, community signals, multi-source summaries, and routing metadata. The default broad pass is bilingual, not Zhipu-backed.
18
- 7. Do not use `smart-search zhipu-search` in normal workflows. Zhipu is deprecated and not used by default routing because quota may be unavailable; the command remains only for manual legacy compatibility when the user explicitly asks for it.
19
- 8. Use `smart-search context7-library` / `context7-docs` first for library, SDK, API, framework, or documentation intent.
20
- 9. Use `smart-search exa-search` for official domains, papers, product pages, trusted sites, and low-noise discovery. Do not treat Exa as the universal second hop for every high-risk or verification task.
21
- 10. Use `smart-search search --extra-sources N` for Tavily/Firecrawl horizontal candidates, and `smart-search fetch` for page text that can support final claims.
22
- 11. Use `smart-search exa-similar` when the user gives a representative URL and wants related pages or neighboring sources.
23
- 12. Use `smart-search fetch` when the user gives a URL or a claim depends on page content.
24
- 13. Use `smart-search map` when a documentation site or domain structure matters.
25
- 14. To change the main-search model, use `smart-search config set OPENAI_COMPATIBLE_MODEL ...`.
26
- 15. For current-news, policy, finance, health, or other high-risk facts, do not answer from broad `search.content` alone. Use the bilingual search pair plus intent-specific sources: Context7 for docs/API, Exa for official/trusted domains or papers, then `fetch` key pages and summarize only what fetched text supports.
27
- 16. Use `smart-search research "question" --format json` when the user wants the CLI to run live Deep Research end to end instead of only planning. It executes plan -> discover -> fetch/read -> gap check -> evidence-only synthesis.
28
- 17. Preserve command lines and source URLs in your answer. Prefer citing fetched pages or `primary_sources`; treat `extra_sources` as follow-up candidates, not verified evidence for generated claims.
17
+ 6. Use `smart-search search` as the first hop for realtime, broad exploration, community signals, multi-source summaries, and routing metadata. The default broad pass is bilingual via Tavily / Firecrawl when configured.
18
+ 7. Use `smart-search context7-library` / `context7-docs` first for library, SDK, API, framework, or documentation intent.
19
+ 8. Use `smart-search exa-search` for official domains, papers, product pages, trusted sites, and low-noise discovery. Do not treat Exa as the universal second hop for every high-risk or verification task.
20
+ 9. Use `smart-search search --extra-sources N` for Tavily/Firecrawl horizontal candidates, and `smart-search fetch` for page text that can support final claims.
21
+ 10. Use `smart-search exa-similar` when the user gives a representative URL and wants related pages or neighboring sources.
22
+ 11. Use `smart-search fetch` when the user gives a URL or a claim depends on page content.
23
+ 12. Use `smart-search map` when a documentation site or domain structure matters.
24
+ 13. To change the main-search model, use `smart-search config set OPENAI_COMPATIBLE_MODEL ...` (or `XAI_MODEL ...` for the xAI route).
25
+ 14. For current-news, policy, finance, health, or other high-risk facts, do not answer from broad `search.content` alone. Use the bilingual search pair plus intent-specific sources: Context7 for docs/API, Exa for official/trusted domains or papers, then `fetch` key pages and summarize only what fetched text supports.
26
+ 15. Use `smart-search research "question" --format json` when the user wants the CLI to run live Deep Research end to end instead of only planning. It executes plan -> discover -> fetch/read -> gap check -> evidence-only synthesis.
27
+ 16. Preserve command lines and source URLs in your answer. Prefer citing fetched pages or `primary_sources`; treat `extra_sources` as follow-up candidates, not verified evidence for generated claims.
29
28
 
30
29
  ## Deep Research Mode
31
30
 
@@ -101,7 +100,6 @@ Allowed `steps[].tool` values are `search`, `exa-search`, `exa-similar`, `contex
101
100
  Capability boundaries:
102
101
 
103
102
  - `search`: broad bilingual discovery and synthesis through `main_search`; inspect `routing_decision`, `provider_attempts`, `fallback_used`, and `source_warning`. Do not treat broad answers as proof for high-risk claims.
104
- - `zhipu-search`: deprecated manual compatibility command. Do not include it in default plans or workflows unless the user explicitly requests Zhipu.
105
103
  - `context7-library` / `context7-docs`: library, SDK, API, framework, and documentation intent. Prefer Context7 before Exa for docs/API questions.
106
104
  - `exa-search`: low-noise discovery for official domains, papers, product pages, known domains, and trusted pages. Use it when that boundary fits; it is not the default second hop for every verification task.
107
105
  - `exa-similar`: adjacent-source discovery when a known reliable URL is available.
@@ -122,9 +120,10 @@ Default evidence policy is `fetch_before_claim`: key claims in the final answer
122
120
 
123
121
  Live Deep Research executor:
124
122
 
125
- - `smart-search research QUERY [--budget quick|standard|deep] [--locale-scope cn|en|both] [--evidence-dir PATH] [--fallback auto|off] [--dry-run] [--progress] [--format json|markdown|content] [--output PATH]` runs the staged workflow directly. Use `--dry-run` to preview plan/routing without live providers; `--progress` for stderr stage logs; `--locale-scope cn` or `en` to skip bilingual discovery when cost matters.
123
+ - `smart-search research QUERY [--budget quick|standard|deep] [--locale-scope cn|en|both] [--evidence-dir PATH] [--fallback auto|off] [--dry-run] [--progress] [--timeout SECONDS] [--format json|markdown|content] [--output PATH]` runs the staged workflow directly. Use `--dry-run` to preview plan/routing without live providers; `--progress` for stderr stage logs; `--locale-scope cn` or `en` to skip bilingual discovery when cost matters. Docs/API intent is precision-first (weak language/product tokens alone do not trigger). If docs discovery yields no HTTP evidence, the executor fail-opens to `web_discovery` (`stage_results` may include `fail_open_web_after_docs`). Default `--timeout` is 600 seconds for the full research run.
126
124
  - Default `--fallback auto` permits same-capability fallback inside selected routes. Use `--fallback off` only for debugging or deterministic provider checks.
127
- - Research output includes `final_answer`, `citations`, `evidence_items`, `gap_check`, `provider_attempts`, `fallback_used`, `degraded`, `route_policy_version`, and `evidence_dir`.
125
+ - Research output includes `final_answer`, `citations`, `evidence_items`, `gap_check`, `provider_attempts`, `fallback_used`, `degraded`, `route_policy_version`, `output_schema_version`, and `evidence_dir`.
126
+ - Contract fields for agents: always read `output_schema_version` (currently `1`), `route_policy_version`, `minimum_profile_ok`, and `cache_hit` on attempts/stages. Treat `cache_hit: true` as possibly stale only if the local config model/endpoint changed without process restart — keys include model identity, but process-local TTL still applies. Prefer `doctor --format json` when `minimum_profile_ok` is false (fail-closed).
128
127
  - The synthesis is evidence-only. It may cite fetched/read evidence, but it must not cite unfetched discovery candidates as proof.
129
128
  - If providers are exhausted or evidence cannot close, return the degraded gaps rather than inventing missing claims.
130
129
 
@@ -151,7 +150,7 @@ smart-search research "https://example.com/source" --format json
151
150
 
152
151
  ## Provider Routing
153
152
 
154
- - `search` builds `main_search` from `OPENAI_COMPATIBLE_API_URL` + `OPENAI_COMPATIBLE_API_KEY`, which registers OpenAI-compatible Chat Completions.
153
+ - `search` builds `main_search` from `XAI_API_KEY` (xAI Responses with server-side `web_search`/`x_search` tools) and/or `OPENAI_COMPATIBLE_API_URL` + `OPENAI_COMPATIBLE_API_KEY` (Chat Completions). One is enough; when both are configured, `SMART_SEARCH_MAIN_SEARCH_ROUTE` (ordered CSV of `xai-responses,openai-compatible`) sets priority, and a single entry disables cross-route fallback.
155
154
  - `search` is the default first hop for broad exploration, current synthesis, and routing metadata.
156
155
  - OpenAI-compatible relays/gateways use Chat Completions `/chat/completions` through `OPENAI_COMPATIBLE_*`.
157
156
  - `OPENAI_COMPATIBLE_STREAM=true` or `search --stream` sets `stream=true` only for OpenAI-compatible `search` and provider-side `fetch`; it is a relay compatibility switch and does not affect URL description or source ranking.
@@ -160,7 +159,7 @@ smart-search research "https://example.com/source" --format json
160
159
  - Jina Reader is `web_fetch` only, not a general search provider. `JINA_API_KEY` is required before Jina satisfies the standard minimum profile; anonymous `r.jina.ai` is explicit/experimental fetch behavior.
161
160
  - `search` exposes `--validation fast|balanced|strict`, `--fallback auto|off`, and `--providers auto|CSV`. Default validation is `balanced`; fallback only happens within the same capability.
162
161
  - `search --validation strict` uses the same bilingual web_search policy as balanced mode when source discovery providers are configured. Strict queries without primary, docs, fetch, or explicit source evidence can still fail with `evidence_error`; use `--extra-sources N`, source-first commands such as `exa-search`, or `fetch` when citable evidence is required.
163
- - `search` runs bilingual web_search source discovery through Tavily / Firecrawl when configured. Zhipu is deprecated from default routing and is not the first hop for Chinese/current/domestic searches.
162
+ - `search` runs bilingual web_search source discovery through Tavily / Firecrawl when configured.
164
163
  - Docs/API/library routing stays explicit keyword intent-based and should prefer Context7 first. Exa is for official-domain or low-noise supplemental discovery, not the default docs answer route.
165
164
  - `search` calls Tavily and/or Firecrawl for `extra_sources` only when `--extra-sources N` is greater than 0.
166
165
  - With both Tavily and Firecrawl configured, `search --extra-sources N` splits extra sources between them, with Tavily receiving about 60% and Firecrawl the rest.
@@ -170,11 +169,8 @@ smart-search research "https://example.com/source" --format json
170
169
  - `map` currently uses Tavily only.
171
170
  - `exa-search` and `exa-similar` use Exa only.
172
171
  - `context7-library` and `context7-docs` use Context7 only.
173
- - `zhipu-search` uses Zhipu only and is retained as a deprecated manual compatibility command.
174
- - `zhipu-search` corresponds to the official Zhipu Web Search API route, using `ZHIPU_API_URL` plus `ZHIPU_SEARCH_ENGINE`; it is not Zhipu Chat Completions `tools=[web_search]`, not Search Agent, and not the MCP Server.
175
- - `ZHIPU_SEARCH_ENGINE` defaults to `search_std`. Official Web Search API service values include `search_std`, `search_pro`, `search_pro_sogou`, and `search_pro_quark`; keep custom values possible because official services may change.
176
- - `TAVILY_API_URL` only affects Tavily REST calls and does not proxy Zhipu. Zhipu defaults to `https://open.bigmodel.cn/api` unless `ZHIPU_API_URL` is set.
177
- - `doctor` tests configured main-search providers, Exa, Tavily, Jina, Zhipu Web Search API, and Context7 connectivity. Firecrawl status currently means the key is configured, not that a live Firecrawl request succeeded.
172
+ - `TAVILY_API_URL` only affects Tavily REST calls.
173
+ - `doctor` tests configured main-search providers, Exa, Tavily, Jina, and Context7 connectivity. Firecrawl status currently means the key is configured, not that a live Firecrawl request succeeded.
178
174
 
179
175
  ## Evidence Files
180
176
 
@@ -270,13 +266,11 @@ Use this when the user wants work that can be inspected, resumed, or audited.
270
266
  - Use `smart-search doctor --format json` for agent/script parsing and `smart-search doctor --format markdown` when a human wants a detailed diagnostic report.
271
267
  - If `smart-search doctor --format json` returns `ok: false`, follow the `error` field's guidance (`smart-search setup` or `smart-search config set KEY VALUE`); do not silently fall back to native web search.
272
268
  - Use `smart-search diagnose openai-compatible --format markdown` when `doctor` succeeds but OpenAI-compatible `search` appears to hang, returns a timeout, or differs between `--stream` and `--no-stream`. It is the beginner-facing one-command report for upstream/relay compatibility.
273
- - Interactive `smart-search setup` is a language-selecting grouped wizard with arrow-key / Space / Enter provider selection. It guides users through required `main_search`, `docs_search`, and fetch capability. Zhipu is no longer recommended or prompted in the default setup flow.
269
+ - Interactive `smart-search setup` is a language-selecting grouped wizard with arrow-key / Space / Enter provider selection. It guides users through required `main_search`, `docs_search`, and fetch capability.
274
270
  - The setup wizard prints beginner filling examples for official-service and relay/pooled-endpoint minimum profiles. Keep that guidance on stderr so stdout remains parseable JSON/Markdown/content output.
275
271
  - Use `smart-search setup --lang en` for an English wizard and `smart-search setup --advanced` only when low-level config keys must be shown one by one.
276
- - Use `smart-search config set ZHIPU_API_KEY ...` only for explicit legacy Zhipu compatibility. Do not set it up for default workflows.
277
272
  - Use `smart-search setup --non-interactive --jina-key "key"` to let Jina satisfy `web_fetch`; `JINA_RESPOND_WITH=readerlm-v2` also requires `JINA_API_KEY`.
278
273
  - Use `smart-search setup --non-interactive --openai-compatible-stream true` only when an OpenAI-compatible relay benefits from SSE streaming for long requests. Default is true.
279
- - Interactive setup does not ask for Zhipu by default.
280
274
  - Use `TAVILY_API_URL=https://<host>/api/tavily` for Tavily Hikari / pooled endpoints. Root host and `/mcp` inputs are normalized by setup; `/mcp` itself is not the REST base Smart Search should call.
281
275
  - `TAVILY_TIMEOUT_SECONDS` controls the Tavily `doctor` connectivity timeout and defaults to `30`. Raise it for slower pooled/community Tavily endpoints before judging the provider unhealthy.
282
276
  - Use `FIRECRAWL_API_URL` only for a Firecrawl-compatible REST base. Official default is `https://api.firecrawl.dev/v2`.
@@ -311,11 +305,11 @@ smart-search config set OPENAI_COMPATIBLE_API_URL "https://api.openai.com/v1" --
311
305
  smart-search config set OPENAI_COMPATIBLE_API_KEY "key" --format json
312
306
  smart-search config set OPENAI_COMPATIBLE_MODEL "model-id" --format json
313
307
  smart-search config set OPENAI_COMPATIBLE_STREAM "true" --format json
308
+ smart-search config set XAI_API_KEY "key" --format json
309
+ smart-search config set XAI_MODEL "grok-4.5" --format json
310
+ smart-search config set SMART_SEARCH_MAIN_SEARCH_ROUTE "xai-responses,openai-compatible" --format json
314
311
  smart-search config set EXA_API_KEY "key" --format json
315
312
  smart-search config set CONTEXT7_API_KEY "key" --format json
316
- smart-search config set ZHIPU_API_KEY "key" --format json
317
- smart-search config set ZHIPU_API_URL "https://open.bigmodel.cn/api" --format json
318
- smart-search config set ZHIPU_SEARCH_ENGINE "search_pro" --format json
319
313
  smart-search config set TAVILY_API_URL "https://api.tavily.com" --format json
320
314
  smart-search config set TAVILY_TIMEOUT_SECONDS "45" --format json
321
315
  smart-search config set FIRECRAWL_API_URL "https://api.firecrawl.dev/v2" --format json
@@ -344,6 +338,18 @@ smart-search d --format markdown
344
338
 
345
339
  When `smart-search search` returns `ok: false` with `error_type: "network_error"` and an error message containing `timed out`, treat it as a retryable CLI-level timeout, not as a terminal research failure.
346
340
 
341
+ ### Error contract (U1/U2)
342
+
343
+ Failed JSON payloads expose a stable triple for Agent/JSON consumers:
344
+
345
+ | Field | Meaning |
346
+ | --- | --- |
347
+ | `error_type` | Category enum string: `config_error`, `parameter_error`, `network_error`, `evidence_error`, `auth_error`, `rate_limited`, `timeout`, `parse_error`, `quality_error`, `runtime_error` |
348
+ | `error_code` | Stable `SCREAMING_SNAKE` code (defaults from `error_type`, e.g. `CONFIG_ERROR`; specific codes such as `MISSING_API_KEY`, `SEARCH_TIMEOUT` when applicable) |
349
+ | `error` | Default **English** human message (no locale framework; Chinese remains only in interactive setup prompts via existing `_t`) |
350
+
351
+ CLI exit codes stay mapped from `error_type` only: `parameter_error→2`, `config_error→3`, `network_error`/`evidence_error→4`, other→`5`.
352
+
347
353
  1. Retry up to 3 total attempts with `--timeout 180`, waiting about 5 seconds between attempts.
348
354
  2. Use `--format json` and `--output PATH` for each attempt; after each attempt, inspect the saved JSON and stop on the first `"ok": true`.
349
355
  3. Use `--extra-sources 1` during retry attempts to keep Tavily/Firecrawl overhead small.
@@ -380,7 +386,7 @@ smart-search fetch "https://example.com/source" --format markdown --output fetch
380
386
  - Do not use legacy MCP tool names in prompts, notes, or generated instructions for this workflow.
381
387
  - Treat key rotation as a hard safety gate when previous key values were pasted into chat or logs.
382
388
  - For provider architecture maintenance, verify the distributable contract rather than the current developer machine's wrappers or local config. Keep fallback same-capability only.
383
- - `main_search` is OpenAI-compatible Chat Completions configured through `OPENAI_COMPATIBLE_*`. Do not fabricate a second `main_search` provider or reuse another capability's URL/key as a `main_search` fallback.
389
+ - `main_search` is a user choice between xAI Responses (`XAI_*`) and OpenAI-compatible Chat Completions (`OPENAI_COMPATIBLE_*`). Never send xAI server tools (`web_search`, `x_search`) or xAI-only parameters into the OpenAI-compatible route, and never point the xAI route at `/chat/completions`. Do not fabricate additional `main_search` providers or reuse another capability's URL/key as a `main_search` fallback.
384
390
 
385
391
  ## Supporting Reference
386
392