@velum-labs/cursorkit 0.1.0

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 (142) hide show
  1. package/DISCLAIMER.md +12 -0
  2. package/README.md +157 -0
  3. package/dist/src/agentTools/diff.d.ts +11 -0
  4. package/dist/src/agentTools/diff.js +88 -0
  5. package/dist/src/agentTools/policy.d.ts +3 -0
  6. package/dist/src/agentTools/policy.js +12 -0
  7. package/dist/src/agentTools/registry.d.ts +114 -0
  8. package/dist/src/agentTools/registry.js +663 -0
  9. package/dist/src/agentTools/results.d.ts +14 -0
  10. package/dist/src/agentTools/results.js +117 -0
  11. package/dist/src/agentTools/schemas.d.ts +3 -0
  12. package/dist/src/agentTools/schemas.js +89 -0
  13. package/dist/src/agentTools/surface.d.ts +11 -0
  14. package/dist/src/agentTools/surface.js +251 -0
  15. package/dist/src/certs.d.ts +8 -0
  16. package/dist/src/certs.js +34 -0
  17. package/dist/src/ck.d.ts +2 -0
  18. package/dist/src/ck.js +6 -0
  19. package/dist/src/ckLauncher.d.ts +150 -0
  20. package/dist/src/ckLauncher.js +1496 -0
  21. package/dist/src/cli.d.ts +2 -0
  22. package/dist/src/cli.js +265 -0
  23. package/dist/src/config.d.ts +52 -0
  24. package/dist/src/config.js +210 -0
  25. package/dist/src/connectEnvelope.d.ts +16 -0
  26. package/dist/src/connectEnvelope.js +70 -0
  27. package/dist/src/desktop.d.ts +19 -0
  28. package/dist/src/desktop.js +167 -0
  29. package/dist/src/desktopConnectProxy.d.ts +26 -0
  30. package/dist/src/desktopConnectProxy.js +175 -0
  31. package/dist/src/extensions/index.d.ts +2 -0
  32. package/dist/src/extensions/index.js +1 -0
  33. package/dist/src/extensions/registry.d.ts +8 -0
  34. package/dist/src/extensions/registry.js +52 -0
  35. package/dist/src/extensions/types.d.ts +42 -0
  36. package/dist/src/extensions/types.js +1 -0
  37. package/dist/src/fixtures/modelFusion.d.ts +103 -0
  38. package/dist/src/fixtures/modelFusion.js +404 -0
  39. package/dist/src/fixtures/replay.d.ts +9 -0
  40. package/dist/src/fixtures/replay.js +41 -0
  41. package/dist/src/fixtures/sanitizer.d.ts +9 -0
  42. package/dist/src/fixtures/sanitizer.js +43 -0
  43. package/dist/src/fixtures/schema.d.ts +38 -0
  44. package/dist/src/fixtures/schema.js +33 -0
  45. package/dist/src/gen/agent/v1/agent_pb.d.ts +21577 -0
  46. package/dist/src/gen/agent/v1/agent_pb.js +5325 -0
  47. package/dist/src/gen/aiserver/v1/aiserver_pb.d.ts +135242 -0
  48. package/dist/src/gen/aiserver/v1/aiserver_pb.js +34430 -0
  49. package/dist/src/gen/anyrun/v1/anyrun_pb.d.ts +1163 -0
  50. package/dist/src/gen/anyrun/v1/anyrun_pb.js +374 -0
  51. package/dist/src/gen/google/protobuf/google_pb.d.ts +142 -0
  52. package/dist/src/gen/google/protobuf/google_pb.js +54 -0
  53. package/dist/src/gen/internapi/v1/internapi_pb.d.ts +121 -0
  54. package/dist/src/gen/internapi/v1/internapi_pb.js +79 -0
  55. package/dist/src/logger.d.ts +8 -0
  56. package/dist/src/logger.js +37 -0
  57. package/dist/src/modelFusion/cursorHarness.d.ts +146 -0
  58. package/dist/src/modelFusion/cursorHarness.js +647 -0
  59. package/dist/src/modelFusion/index.d.ts +4 -0
  60. package/dist/src/modelFusion/index.js +2 -0
  61. package/dist/src/models/registry.d.ts +22 -0
  62. package/dist/src/models/registry.js +30 -0
  63. package/dist/src/proto.d.ts +13 -0
  64. package/dist/src/proto.js +61 -0
  65. package/dist/src/providers/openai.d.ts +64 -0
  66. package/dist/src/providers/openai.js +355 -0
  67. package/dist/src/redaction.d.ts +4 -0
  68. package/dist/src/redaction.js +65 -0
  69. package/dist/src/routeInventory.d.ts +16 -0
  70. package/dist/src/routeInventory.js +39 -0
  71. package/dist/src/routes.d.ts +37 -0
  72. package/dist/src/routes.js +227 -0
  73. package/dist/src/server.d.ts +50 -0
  74. package/dist/src/server.js +1353 -0
  75. package/dist/src/services/agent.d.ts +1 -0
  76. package/dist/src/services/agent.js +7 -0
  77. package/dist/src/services/agentRun.d.ts +60 -0
  78. package/dist/src/services/agentRun.js +391 -0
  79. package/dist/src/services/chat.d.ts +11 -0
  80. package/dist/src/services/chat.js +47 -0
  81. package/dist/src/services/models.d.ts +10 -0
  82. package/dist/src/services/models.js +216 -0
  83. package/dist/src/services/serverConfig.d.ts +2 -0
  84. package/dist/src/services/serverConfig.js +19 -0
  85. package/dist/src/testing/artifacts.d.ts +14 -0
  86. package/dist/src/testing/artifacts.js +92 -0
  87. package/dist/src/testing/cli.d.ts +4 -0
  88. package/dist/src/testing/cli.js +192 -0
  89. package/dist/src/testing/localBackend.d.ts +24 -0
  90. package/dist/src/testing/localBackend.js +310 -0
  91. package/dist/src/testing/processRunner.d.ts +7 -0
  92. package/dist/src/testing/processRunner.js +74 -0
  93. package/dist/src/testing/runner.d.ts +9 -0
  94. package/dist/src/testing/runner.js +85 -0
  95. package/dist/src/testing/scenarios.d.ts +3 -0
  96. package/dist/src/testing/scenarios.js +2535 -0
  97. package/dist/src/testing/types.d.ts +66 -0
  98. package/dist/src/testing/types.js +1 -0
  99. package/dist/src/tools/baselineInventory.d.ts +12 -0
  100. package/dist/src/tools/baselineInventory.js +680 -0
  101. package/dist/src/tools/checkModelFusionProtocol.d.ts +1 -0
  102. package/dist/src/tools/checkModelFusionProtocol.js +274 -0
  103. package/dist/src/tools/checkReleasePublishConfig.d.ts +1 -0
  104. package/dist/src/tools/checkReleasePublishConfig.js +99 -0
  105. package/dist/src/tools/generateProtoInventory.d.ts +1 -0
  106. package/dist/src/tools/generateProtoInventory.js +89 -0
  107. package/dist/src/tools/normalizeGeneratedCode.d.ts +1 -0
  108. package/dist/src/tools/normalizeGeneratedCode.js +18 -0
  109. package/dist/src/tools/releaseCheck.d.ts +26 -0
  110. package/dist/src/tools/releaseCheck.js +367 -0
  111. package/dist/src/trace.d.ts +39 -0
  112. package/dist/src/trace.js +106 -0
  113. package/dist/src/translation.d.ts +6 -0
  114. package/dist/src/translation.js +22 -0
  115. package/dist/src/upstream.d.ts +20 -0
  116. package/dist/src/upstream.js +270 -0
  117. package/docs/configuration.md +55 -0
  118. package/docs/cursor-app.md +263 -0
  119. package/docs/implementation-inventory.json +609 -0
  120. package/docs/learnings.md +363 -0
  121. package/docs/model-fusion-protocol-origin.json +126 -0
  122. package/docs/model-fusion-protocol.md +110 -0
  123. package/docs/plugin-authoring.md +24 -0
  124. package/docs/proto-inventory.md +1477 -0
  125. package/docs/protocol-surface-audit.md +92 -0
  126. package/docs/protocol.md +52 -0
  127. package/docs/refreshing-protos.md +78 -0
  128. package/docs/release-gates.md +110 -0
  129. package/docs/release-summary.json +86 -0
  130. package/docs/route-contract-manifest.json +288 -0
  131. package/docs/route-policy.json +133 -0
  132. package/docs/service-manifest.json +9490 -0
  133. package/docs/test-manifest.json +155 -0
  134. package/docs/testing-harness.md +204 -0
  135. package/docs/troubleshooting.md +36 -0
  136. package/docs/type-manifest-summary.json +28927 -0
  137. package/package.json +93 -0
  138. package/proto/agent/v1/agent.proto +5371 -0
  139. package/proto/aiserver/v1/aiserver.proto +32944 -0
  140. package/proto/anyrun/v1/anyrun.proto +294 -0
  141. package/proto/google/protobuf/google.proto +37 -0
  142. package/proto/internapi/v1/internapi.proto +32 -0
@@ -0,0 +1,310 @@
1
+ import { parseOpenAIStream } from "../providers/openai.js";
2
+ export async function probeLocalBackend(options) {
3
+ const models = await fetchModels(options);
4
+ if (!models.ok) {
5
+ return models;
6
+ }
7
+ if (!models.models.includes(options.model)) {
8
+ return {
9
+ ok: false,
10
+ failureCode: "backend_unreachable",
11
+ message: `Model ${options.model} was not returned by /models`,
12
+ modelsStatus: models.modelsStatus,
13
+ models: models.models,
14
+ selectedModelFound: false,
15
+ };
16
+ }
17
+ const chat = await fetchChatCompletion(options);
18
+ if (!chat.ok) {
19
+ return {
20
+ ...chat,
21
+ modelsStatus: models.modelsStatus,
22
+ models: models.models,
23
+ selectedModelFound: true,
24
+ };
25
+ }
26
+ if (options.checkToolCalls === true) {
27
+ const toolCall = await fetchToolCallCompletion(options);
28
+ if (!toolCall.ok) {
29
+ return {
30
+ ...toolCall,
31
+ modelsStatus: models.modelsStatus,
32
+ chatStatus: chat.chatStatus,
33
+ streamingChatStatus: chat.streamingChatStatus,
34
+ models: models.models,
35
+ selectedModelFound: true,
36
+ nonStreamingSupported: chat.nonStreamingSupported,
37
+ streamingSupported: chat.streamingSupported,
38
+ };
39
+ }
40
+ return {
41
+ ok: true,
42
+ message: "Local backend returned the selected model, completed a chat probe, and streamed a tool call",
43
+ modelsStatus: models.modelsStatus,
44
+ chatStatus: chat.chatStatus,
45
+ streamingChatStatus: chat.streamingChatStatus,
46
+ toolChatStatus: toolCall.toolChatStatus,
47
+ models: models.models,
48
+ selectedModelFound: true,
49
+ nonStreamingSupported: chat.nonStreamingSupported,
50
+ streamingSupported: chat.streamingSupported,
51
+ toolCallsSupported: true,
52
+ completionPreview: chat.completionPreview,
53
+ };
54
+ }
55
+ return {
56
+ ok: true,
57
+ message: `Local backend returned ${options.model} and completed a chat probe`,
58
+ modelsStatus: models.modelsStatus,
59
+ chatStatus: chat.chatStatus,
60
+ streamingChatStatus: chat.streamingChatStatus,
61
+ models: models.models,
62
+ selectedModelFound: true,
63
+ nonStreamingSupported: chat.nonStreamingSupported,
64
+ streamingSupported: chat.streamingSupported,
65
+ completionPreview: chat.completionPreview,
66
+ };
67
+ }
68
+ async function fetchModels(options) {
69
+ const url = `${trimTrailingSlash(options.baseUrl)}/models`;
70
+ try {
71
+ const response = await fetchWithTimeout(url, {
72
+ method: "GET",
73
+ headers: authHeaders(options.apiKey),
74
+ timeoutMs: options.timeoutMs,
75
+ });
76
+ if (!response.ok) {
77
+ return {
78
+ ok: false,
79
+ failureCode: "backend_unreachable",
80
+ message: `/models returned HTTP ${response.status}`,
81
+ modelsStatus: response.status,
82
+ models: [],
83
+ };
84
+ }
85
+ const json = (await response.json());
86
+ return {
87
+ ok: true,
88
+ message: "/models returned model data",
89
+ modelsStatus: response.status,
90
+ models: (json.data ?? [])
91
+ .map((model) => model.id)
92
+ .filter((id) => id !== undefined),
93
+ selectedModelFound: (json.data ?? []).some((model) => model.id === options.model),
94
+ };
95
+ }
96
+ catch (error) {
97
+ return {
98
+ ok: false,
99
+ failureCode: "backend_unreachable",
100
+ message: `/models request failed: ${errorMessage(error)}`,
101
+ models: [],
102
+ };
103
+ }
104
+ }
105
+ async function fetchChatCompletion(options) {
106
+ const url = `${trimTrailingSlash(options.baseUrl)}/chat/completions`;
107
+ try {
108
+ const response = await fetchWithTimeout(url, {
109
+ method: "POST",
110
+ headers: {
111
+ ...authHeaders(options.apiKey),
112
+ "content-type": "application/json",
113
+ },
114
+ body: JSON.stringify({
115
+ model: options.model,
116
+ messages: [{ role: "user", content: "Reply with exactly: ok" }],
117
+ max_tokens: 128,
118
+ stream: false,
119
+ }),
120
+ timeoutMs: options.timeoutMs,
121
+ });
122
+ if (!response.ok) {
123
+ return {
124
+ ok: false,
125
+ failureCode: "local_completion_failed",
126
+ message: `/chat/completions returned HTTP ${response.status}`,
127
+ chatStatus: response.status,
128
+ models: [],
129
+ };
130
+ }
131
+ const json = (await response.json());
132
+ const content = json.choices?.[0]?.message?.content ?? "";
133
+ if (content.length === 0) {
134
+ return fetchStreamingChatCompletion(options);
135
+ }
136
+ return {
137
+ ok: true,
138
+ message: "/chat/completions returned a response",
139
+ chatStatus: response.status,
140
+ models: [],
141
+ nonStreamingSupported: true,
142
+ streamingSupported: false,
143
+ completionPreview: content.slice(0, 120),
144
+ };
145
+ }
146
+ catch (error) {
147
+ return {
148
+ ok: false,
149
+ failureCode: "local_completion_failed",
150
+ message: `/chat/completions request failed: ${errorMessage(error)}`,
151
+ models: [],
152
+ };
153
+ }
154
+ }
155
+ async function fetchStreamingChatCompletion(options) {
156
+ const url = `${trimTrailingSlash(options.baseUrl)}/chat/completions`;
157
+ try {
158
+ const response = await fetchWithTimeout(url, {
159
+ method: "POST",
160
+ headers: {
161
+ ...authHeaders(options.apiKey),
162
+ "content-type": "application/json",
163
+ },
164
+ body: JSON.stringify({
165
+ model: options.model,
166
+ messages: [{ role: "user", content: "Reply with exactly: ok" }],
167
+ max_tokens: 128,
168
+ stream: true,
169
+ }),
170
+ timeoutMs: options.timeoutMs,
171
+ });
172
+ if (!response.ok || response.body === null) {
173
+ return {
174
+ ok: false,
175
+ failureCode: "local_completion_failed",
176
+ message: `/chat/completions streaming returned HTTP ${response.status}`,
177
+ streamingChatStatus: response.status,
178
+ models: [],
179
+ };
180
+ }
181
+ let content = "";
182
+ for await (const chunk of parseOpenAIStream(response.body)) {
183
+ if (typeof chunk !== "string") {
184
+ continue;
185
+ }
186
+ content += chunk;
187
+ if (content.length >= 120) {
188
+ break;
189
+ }
190
+ }
191
+ if (content.length === 0) {
192
+ return {
193
+ ok: false,
194
+ failureCode: "local_completion_failed",
195
+ message: "/chat/completions returned an empty or malformed non-streaming and streaming completion",
196
+ streamingChatStatus: response.status,
197
+ models: [],
198
+ };
199
+ }
200
+ return {
201
+ ok: true,
202
+ message: "/chat/completions returned a streaming response",
203
+ streamingChatStatus: response.status,
204
+ models: [],
205
+ nonStreamingSupported: false,
206
+ streamingSupported: true,
207
+ completionPreview: content.slice(0, 120),
208
+ };
209
+ }
210
+ catch (error) {
211
+ return {
212
+ ok: false,
213
+ failureCode: "local_completion_failed",
214
+ message: `/chat/completions streaming request failed: ${errorMessage(error)}`,
215
+ models: [],
216
+ };
217
+ }
218
+ }
219
+ async function fetchToolCallCompletion(options) {
220
+ const url = `${trimTrailingSlash(options.baseUrl)}/chat/completions`;
221
+ try {
222
+ const response = await fetchWithTimeout(url, {
223
+ method: "POST",
224
+ headers: {
225
+ ...authHeaders(options.apiKey),
226
+ "content-type": "application/json",
227
+ },
228
+ body: JSON.stringify({
229
+ model: options.model,
230
+ messages: [{ role: "user", content: "Call the probe_tool function." }],
231
+ stream: true,
232
+ tools: [
233
+ {
234
+ type: "function",
235
+ function: {
236
+ name: "probe_tool",
237
+ description: "A deterministic probe tool.",
238
+ parameters: {
239
+ type: "object",
240
+ properties: { value: { type: "string" } },
241
+ required: ["value"],
242
+ },
243
+ },
244
+ },
245
+ ],
246
+ }),
247
+ timeoutMs: options.timeoutMs,
248
+ });
249
+ if (!response.ok || response.body === null) {
250
+ return {
251
+ ok: false,
252
+ failureCode: "local_completion_failed",
253
+ message: `/chat/completions tool-call streaming returned HTTP ${response.status}`,
254
+ toolChatStatus: response.status,
255
+ models: [],
256
+ };
257
+ }
258
+ for await (const chunk of parseOpenAIStream(response.body)) {
259
+ if (typeof chunk !== "string" &&
260
+ chunk.toolCalls.some((toolCall) => toolCall.function.name === "probe_tool")) {
261
+ return {
262
+ ok: true,
263
+ message: "/chat/completions streamed a tool call",
264
+ toolChatStatus: response.status,
265
+ models: [],
266
+ toolCallsSupported: true,
267
+ };
268
+ }
269
+ }
270
+ return {
271
+ ok: false,
272
+ failureCode: "local_completion_failed",
273
+ message: "/chat/completions did not stream a probe tool call",
274
+ toolChatStatus: response.status,
275
+ models: [],
276
+ toolCallsSupported: false,
277
+ };
278
+ }
279
+ catch (error) {
280
+ return {
281
+ ok: false,
282
+ failureCode: "local_completion_failed",
283
+ message: `/chat/completions tool-call streaming request failed: ${errorMessage(error)}`,
284
+ models: [],
285
+ toolCallsSupported: false,
286
+ };
287
+ }
288
+ }
289
+ async function fetchWithTimeout(url, options) {
290
+ const controller = new AbortController();
291
+ const timer = setTimeout(() => controller.abort(), options.timeoutMs);
292
+ try {
293
+ return await fetch(url, {
294
+ ...options,
295
+ signal: controller.signal,
296
+ });
297
+ }
298
+ finally {
299
+ clearTimeout(timer);
300
+ }
301
+ }
302
+ function authHeaders(apiKey) {
303
+ return apiKey.length === 0 ? {} : { authorization: `Bearer ${apiKey}` };
304
+ }
305
+ function trimTrailingSlash(value) {
306
+ return value.replace(/\/$/, "");
307
+ }
308
+ function errorMessage(error) {
309
+ return error instanceof Error ? error.message : String(error);
310
+ }
@@ -0,0 +1,7 @@
1
+ import type { ArtifactWriter, ProcessRunOptions, ProcessRunResult, ProcessRunner } from "./types.js";
2
+ export declare class ChildProcessRunner implements ProcessRunner {
3
+ private readonly cwd;
4
+ private readonly artifacts;
5
+ constructor(cwd: string, artifacts: ArtifactWriter);
6
+ run(options: ProcessRunOptions): Promise<ProcessRunResult>;
7
+ }
@@ -0,0 +1,74 @@
1
+ import { spawn } from "node:child_process";
2
+ export class ChildProcessRunner {
3
+ cwd;
4
+ artifacts;
5
+ constructor(cwd, artifacts) {
6
+ this.cwd = cwd;
7
+ this.artifacts = artifacts;
8
+ }
9
+ async run(options) {
10
+ const started = Date.now();
11
+ const commandLine = [options.command, ...options.args].join(" ");
12
+ const child = spawn(options.command, options.args, {
13
+ cwd: this.cwd,
14
+ env: mergeEnv(process.env, options.env ?? {}),
15
+ stdio: ["ignore", "pipe", "pipe"],
16
+ });
17
+ let stdout = "";
18
+ let stderr = "";
19
+ let timedOut = false;
20
+ const timer = options.timeoutMs === undefined
21
+ ? undefined
22
+ : setTimeout(() => {
23
+ timedOut = true;
24
+ child.kill("SIGTERM");
25
+ }, options.timeoutMs);
26
+ child.stdout?.on("data", (chunk) => {
27
+ stdout += chunk.toString("utf8");
28
+ });
29
+ child.stderr?.on("data", (chunk) => {
30
+ stderr += chunk.toString("utf8");
31
+ });
32
+ const exit = await new Promise((resolve, reject) => {
33
+ child.on("error", reject);
34
+ child.on("exit", (exitCode, signal) => resolve({ exitCode, signal }));
35
+ });
36
+ if (timer !== undefined) {
37
+ clearTimeout(timer);
38
+ }
39
+ const result = {
40
+ command: options.command,
41
+ args: options.args,
42
+ exitCode: exit.exitCode,
43
+ signal: exit.signal,
44
+ timedOut,
45
+ durationMs: Date.now() - started,
46
+ stdout,
47
+ stderr,
48
+ logPath: "",
49
+ };
50
+ result.logPath = this.artifacts.writeText(`logs/${options.logName}.log`, [
51
+ `$ ${commandLine}`,
52
+ "",
53
+ "## stdout",
54
+ stdout,
55
+ "",
56
+ "## stderr",
57
+ stderr,
58
+ "",
59
+ ].join("\n"));
60
+ return result;
61
+ }
62
+ }
63
+ function mergeEnv(base, overrides) {
64
+ const env = { ...base };
65
+ for (const [key, value] of Object.entries(overrides)) {
66
+ if (value === undefined) {
67
+ delete env[key];
68
+ }
69
+ else {
70
+ env[key] = value;
71
+ }
72
+ }
73
+ return env;
74
+ }
@@ -0,0 +1,9 @@
1
+ import type { ArtifactWriter, HarnessOptions, HarnessSuite, HarnessSuiteInput, ProcessRunner, Scenario, ScenarioResult } from "./types.js";
2
+ export declare class ScenarioRunner {
3
+ private readonly scenarios;
4
+ private readonly artifacts;
5
+ private readonly processRunner;
6
+ constructor(scenarios: Scenario[], artifacts: ArtifactWriter, processRunner: ProcessRunner);
7
+ run(options: HarnessOptions): Promise<ScenarioResult[]>;
8
+ }
9
+ export declare function expandSuites(inputs: HarnessSuiteInput[], options: Pick<HarnessOptions, "includeExperimental">): HarnessSuite[];
@@ -0,0 +1,85 @@
1
+ export class ScenarioRunner {
2
+ scenarios;
3
+ artifacts;
4
+ processRunner;
5
+ constructor(scenarios, artifacts, processRunner) {
6
+ this.scenarios = scenarios;
7
+ this.artifacts = artifacts;
8
+ this.processRunner = processRunner;
9
+ }
10
+ async run(options) {
11
+ const suites = expandSuites(options.suites, options);
12
+ const selected = this.scenarios.filter((scenario) => suites.includes(scenario.suite));
13
+ const context = {
14
+ options,
15
+ artifacts: this.artifacts,
16
+ processRunner: this.processRunner,
17
+ };
18
+ const results = [];
19
+ for (const scenario of selected) {
20
+ const started = Date.now();
21
+ try {
22
+ results.push(await scenario.run(context));
23
+ }
24
+ catch (error) {
25
+ results.push({
26
+ id: scenario.id,
27
+ suite: scenario.suite,
28
+ status: "failed",
29
+ durationMs: Date.now() - started,
30
+ message: error instanceof Error ? error.message : String(error),
31
+ failureCode: "command_failed",
32
+ });
33
+ }
34
+ }
35
+ return results;
36
+ }
37
+ }
38
+ export function expandSuites(inputs, options) {
39
+ const expanded = [];
40
+ for (const input of inputs.length === 0 ? ["all"] : inputs) {
41
+ switch (input) {
42
+ case "all":
43
+ pushUnique(expanded, "static");
44
+ pushUnique(expanded, "bridge-protocol");
45
+ pushUnique(expanded, "cursor-agent");
46
+ if (options.includeExperimental) {
47
+ pushUnique(expanded, "cursor-agent-acp-experimental");
48
+ pushUnique(expanded, "desktop-ui-experimental");
49
+ }
50
+ break;
51
+ case "acp":
52
+ pushUnique(expanded, "cursor-agent-acp-experimental");
53
+ break;
54
+ case "cli":
55
+ pushUnique(expanded, "cursor-agent");
56
+ break;
57
+ case "traffic":
58
+ pushUnique(expanded, "cursor-agent-traffic");
59
+ break;
60
+ case "desktop":
61
+ pushUnique(expanded, "desktop-route");
62
+ break;
63
+ case "static":
64
+ case "bridge-protocol":
65
+ case "local-backend":
66
+ case "cursor-agent":
67
+ case "cursor-agent-traffic":
68
+ case "cursor-agent-acp-experimental":
69
+ case "desktop-route":
70
+ case "desktop-ui-experimental":
71
+ pushUnique(expanded, input);
72
+ break;
73
+ default: {
74
+ const exhaustive = input;
75
+ throw new Error(`Unhandled suite: ${exhaustive}`);
76
+ }
77
+ }
78
+ }
79
+ return expanded;
80
+ }
81
+ function pushUnique(suites, suite) {
82
+ if (!suites.includes(suite)) {
83
+ suites.push(suite);
84
+ }
85
+ }
@@ -0,0 +1,3 @@
1
+ import type { HarnessOptions, Scenario } from "./types.js";
2
+ export declare function createScenarios(): Scenario[];
3
+ export declare function desktopUiCkArgs(options: Pick<HarnessOptions, "timeoutMs" | "useDefaultProfile">, debugPort: number, instanceId: string): string[];