@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.
- package/DISCLAIMER.md +12 -0
- package/README.md +157 -0
- package/dist/src/agentTools/diff.d.ts +11 -0
- package/dist/src/agentTools/diff.js +88 -0
- package/dist/src/agentTools/policy.d.ts +3 -0
- package/dist/src/agentTools/policy.js +12 -0
- package/dist/src/agentTools/registry.d.ts +114 -0
- package/dist/src/agentTools/registry.js +663 -0
- package/dist/src/agentTools/results.d.ts +14 -0
- package/dist/src/agentTools/results.js +117 -0
- package/dist/src/agentTools/schemas.d.ts +3 -0
- package/dist/src/agentTools/schemas.js +89 -0
- package/dist/src/agentTools/surface.d.ts +11 -0
- package/dist/src/agentTools/surface.js +251 -0
- package/dist/src/certs.d.ts +8 -0
- package/dist/src/certs.js +34 -0
- package/dist/src/ck.d.ts +2 -0
- package/dist/src/ck.js +6 -0
- package/dist/src/ckLauncher.d.ts +150 -0
- package/dist/src/ckLauncher.js +1496 -0
- package/dist/src/cli.d.ts +2 -0
- package/dist/src/cli.js +265 -0
- package/dist/src/config.d.ts +52 -0
- package/dist/src/config.js +210 -0
- package/dist/src/connectEnvelope.d.ts +16 -0
- package/dist/src/connectEnvelope.js +70 -0
- package/dist/src/desktop.d.ts +19 -0
- package/dist/src/desktop.js +167 -0
- package/dist/src/desktopConnectProxy.d.ts +26 -0
- package/dist/src/desktopConnectProxy.js +175 -0
- package/dist/src/extensions/index.d.ts +2 -0
- package/dist/src/extensions/index.js +1 -0
- package/dist/src/extensions/registry.d.ts +8 -0
- package/dist/src/extensions/registry.js +52 -0
- package/dist/src/extensions/types.d.ts +42 -0
- package/dist/src/extensions/types.js +1 -0
- package/dist/src/fixtures/modelFusion.d.ts +103 -0
- package/dist/src/fixtures/modelFusion.js +404 -0
- package/dist/src/fixtures/replay.d.ts +9 -0
- package/dist/src/fixtures/replay.js +41 -0
- package/dist/src/fixtures/sanitizer.d.ts +9 -0
- package/dist/src/fixtures/sanitizer.js +43 -0
- package/dist/src/fixtures/schema.d.ts +38 -0
- package/dist/src/fixtures/schema.js +33 -0
- package/dist/src/gen/agent/v1/agent_pb.d.ts +21577 -0
- package/dist/src/gen/agent/v1/agent_pb.js +5325 -0
- package/dist/src/gen/aiserver/v1/aiserver_pb.d.ts +135242 -0
- package/dist/src/gen/aiserver/v1/aiserver_pb.js +34430 -0
- package/dist/src/gen/anyrun/v1/anyrun_pb.d.ts +1163 -0
- package/dist/src/gen/anyrun/v1/anyrun_pb.js +374 -0
- package/dist/src/gen/google/protobuf/google_pb.d.ts +142 -0
- package/dist/src/gen/google/protobuf/google_pb.js +54 -0
- package/dist/src/gen/internapi/v1/internapi_pb.d.ts +121 -0
- package/dist/src/gen/internapi/v1/internapi_pb.js +79 -0
- package/dist/src/logger.d.ts +8 -0
- package/dist/src/logger.js +37 -0
- package/dist/src/modelFusion/cursorHarness.d.ts +146 -0
- package/dist/src/modelFusion/cursorHarness.js +647 -0
- package/dist/src/modelFusion/index.d.ts +4 -0
- package/dist/src/modelFusion/index.js +2 -0
- package/dist/src/models/registry.d.ts +22 -0
- package/dist/src/models/registry.js +30 -0
- package/dist/src/proto.d.ts +13 -0
- package/dist/src/proto.js +61 -0
- package/dist/src/providers/openai.d.ts +64 -0
- package/dist/src/providers/openai.js +355 -0
- package/dist/src/redaction.d.ts +4 -0
- package/dist/src/redaction.js +65 -0
- package/dist/src/routeInventory.d.ts +16 -0
- package/dist/src/routeInventory.js +39 -0
- package/dist/src/routes.d.ts +37 -0
- package/dist/src/routes.js +227 -0
- package/dist/src/server.d.ts +50 -0
- package/dist/src/server.js +1353 -0
- package/dist/src/services/agent.d.ts +1 -0
- package/dist/src/services/agent.js +7 -0
- package/dist/src/services/agentRun.d.ts +60 -0
- package/dist/src/services/agentRun.js +391 -0
- package/dist/src/services/chat.d.ts +11 -0
- package/dist/src/services/chat.js +47 -0
- package/dist/src/services/models.d.ts +10 -0
- package/dist/src/services/models.js +216 -0
- package/dist/src/services/serverConfig.d.ts +2 -0
- package/dist/src/services/serverConfig.js +19 -0
- package/dist/src/testing/artifacts.d.ts +14 -0
- package/dist/src/testing/artifacts.js +92 -0
- package/dist/src/testing/cli.d.ts +4 -0
- package/dist/src/testing/cli.js +192 -0
- package/dist/src/testing/localBackend.d.ts +24 -0
- package/dist/src/testing/localBackend.js +310 -0
- package/dist/src/testing/processRunner.d.ts +7 -0
- package/dist/src/testing/processRunner.js +74 -0
- package/dist/src/testing/runner.d.ts +9 -0
- package/dist/src/testing/runner.js +85 -0
- package/dist/src/testing/scenarios.d.ts +3 -0
- package/dist/src/testing/scenarios.js +2535 -0
- package/dist/src/testing/types.d.ts +66 -0
- package/dist/src/testing/types.js +1 -0
- package/dist/src/tools/baselineInventory.d.ts +12 -0
- package/dist/src/tools/baselineInventory.js +680 -0
- package/dist/src/tools/checkModelFusionProtocol.d.ts +1 -0
- package/dist/src/tools/checkModelFusionProtocol.js +274 -0
- package/dist/src/tools/checkReleasePublishConfig.d.ts +1 -0
- package/dist/src/tools/checkReleasePublishConfig.js +99 -0
- package/dist/src/tools/generateProtoInventory.d.ts +1 -0
- package/dist/src/tools/generateProtoInventory.js +89 -0
- package/dist/src/tools/normalizeGeneratedCode.d.ts +1 -0
- package/dist/src/tools/normalizeGeneratedCode.js +18 -0
- package/dist/src/tools/releaseCheck.d.ts +26 -0
- package/dist/src/tools/releaseCheck.js +367 -0
- package/dist/src/trace.d.ts +39 -0
- package/dist/src/trace.js +106 -0
- package/dist/src/translation.d.ts +6 -0
- package/dist/src/translation.js +22 -0
- package/dist/src/upstream.d.ts +20 -0
- package/dist/src/upstream.js +270 -0
- package/docs/configuration.md +55 -0
- package/docs/cursor-app.md +263 -0
- package/docs/implementation-inventory.json +609 -0
- package/docs/learnings.md +363 -0
- package/docs/model-fusion-protocol-origin.json +126 -0
- package/docs/model-fusion-protocol.md +110 -0
- package/docs/plugin-authoring.md +24 -0
- package/docs/proto-inventory.md +1477 -0
- package/docs/protocol-surface-audit.md +92 -0
- package/docs/protocol.md +52 -0
- package/docs/refreshing-protos.md +78 -0
- package/docs/release-gates.md +110 -0
- package/docs/release-summary.json +86 -0
- package/docs/route-contract-manifest.json +288 -0
- package/docs/route-policy.json +133 -0
- package/docs/service-manifest.json +9490 -0
- package/docs/test-manifest.json +155 -0
- package/docs/testing-harness.md +204 -0
- package/docs/troubleshooting.md +36 -0
- package/docs/type-manifest-summary.json +28927 -0
- package/package.json +93 -0
- package/proto/agent/v1/agent.proto +5371 -0
- package/proto/aiserver/v1/aiserver.proto +32944 -0
- package/proto/anyrun/v1/anyrun.proto +294 -0
- package/proto/google/protobuf/google.proto +37 -0
- package/proto/internapi/v1/internapi.proto +32 -0
|
@@ -0,0 +1,680 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { format } from "prettier";
|
|
4
|
+
import { ROUTE_CONTRACT_SEEDS } from "../routes.js";
|
|
5
|
+
const ROUTE_CONTRACT_MANIFEST_PATH = "docs/route-contract-manifest.json";
|
|
6
|
+
const ROUTE_POLICY_PATH = "docs/route-policy.json";
|
|
7
|
+
const IMPLEMENTATION_INVENTORY_PATH = "docs/implementation-inventory.json";
|
|
8
|
+
const TEST_MANIFEST_PATH = "docs/test-manifest.json";
|
|
9
|
+
const RELEASE_SUMMARY_PATH = "docs/release-summary.json";
|
|
10
|
+
export const BASELINE_ARTIFACT_PATHS = [
|
|
11
|
+
ROUTE_CONTRACT_MANIFEST_PATH,
|
|
12
|
+
ROUTE_POLICY_PATH,
|
|
13
|
+
IMPLEMENTATION_INVENTORY_PATH,
|
|
14
|
+
TEST_MANIFEST_PATH,
|
|
15
|
+
RELEASE_SUMMARY_PATH,
|
|
16
|
+
];
|
|
17
|
+
const CONFIG_ENV_ANNOTATIONS = {
|
|
18
|
+
BRIDGE_AGENT_PUBLIC_ORIGIN: {
|
|
19
|
+
category: "desktop",
|
|
20
|
+
defaultValue: "undefined",
|
|
21
|
+
description: "Public origin advertised to Cursor Agent clients when different from the bridge public origin.",
|
|
22
|
+
},
|
|
23
|
+
BRIDGE_AGENT_CONTEXT_TIMEOUT_MS: {
|
|
24
|
+
category: "reliability",
|
|
25
|
+
defaultValue: "undefined",
|
|
26
|
+
description: "Optional timeout for gathering agent context before local model execution.",
|
|
27
|
+
},
|
|
28
|
+
BRIDGE_AGENT_NATIVE_CONTEXT: {
|
|
29
|
+
category: "agent-tools",
|
|
30
|
+
defaultValue: "true",
|
|
31
|
+
description: "Controls whether local agent runs include native Cursor context gathered before model execution.",
|
|
32
|
+
},
|
|
33
|
+
BRIDGE_AGENT_RUN_SSE_WAIT_TIMEOUT_MS: {
|
|
34
|
+
category: "reliability",
|
|
35
|
+
defaultValue: "undefined",
|
|
36
|
+
description: "Optional timeout for waiting on pending Agent RunSSE/Bidi state.",
|
|
37
|
+
},
|
|
38
|
+
BRIDGE_AGENT_TOOL_POLICY: {
|
|
39
|
+
category: "agent-tools",
|
|
40
|
+
defaultValue: "safe",
|
|
41
|
+
description: "Controls whether local agent runs advertise only safe tools or the approved extended tool set.",
|
|
42
|
+
},
|
|
43
|
+
BRIDGE_AGENT_TOOL_MAX_ITERATIONS: {
|
|
44
|
+
category: "agent-tools",
|
|
45
|
+
defaultValue: "8",
|
|
46
|
+
description: "Maximum number of tool-call iterations the bridge runs per local agent turn before stopping.",
|
|
47
|
+
},
|
|
48
|
+
BRIDGE_AGENT_TOOL_RESULT_TIMEOUT_MS: {
|
|
49
|
+
category: "reliability",
|
|
50
|
+
defaultValue: "undefined",
|
|
51
|
+
description: "Optional timeout for waiting on Cursor exec tool results during local agent runs.",
|
|
52
|
+
},
|
|
53
|
+
BRIDGE_AUTH_TOKEN: {
|
|
54
|
+
category: "safety",
|
|
55
|
+
defaultValue: "undefined",
|
|
56
|
+
requiredWhen: "BRIDGE_HOST is non-localhost unless BRIDGE_UNSAFE_ALLOW_NON_LOCALHOST=true",
|
|
57
|
+
description: "Bearer token required to protect non-localhost bridge binds unless explicitly bypassed.",
|
|
58
|
+
},
|
|
59
|
+
BRIDGE_CAPTURE_DIR: {
|
|
60
|
+
category: "capture",
|
|
61
|
+
defaultValue: "fixtures/captures",
|
|
62
|
+
description: "Directory for traffic captures when capture mode is enabled.",
|
|
63
|
+
},
|
|
64
|
+
BRIDGE_CAPTURE_ENABLED: {
|
|
65
|
+
category: "capture",
|
|
66
|
+
defaultValue: "false",
|
|
67
|
+
description: "Enables explicit traffic capture hooks; route inventory is separate.",
|
|
68
|
+
},
|
|
69
|
+
BRIDGE_CERT_PATH: {
|
|
70
|
+
category: "tls",
|
|
71
|
+
defaultValue: "undefined",
|
|
72
|
+
requiredWhen: "BRIDGE_USE_TLS=true and generated certs are not used",
|
|
73
|
+
description: "Path to TLS certificate material.",
|
|
74
|
+
},
|
|
75
|
+
BRIDGE_DESKTOP_AGENT_HTTP_PORT: {
|
|
76
|
+
category: "desktop",
|
|
77
|
+
defaultValue: "undefined",
|
|
78
|
+
description: "Optional secondary HTTP listener port for desktop agent compatibility experiments.",
|
|
79
|
+
},
|
|
80
|
+
BRIDGE_DESKTOP_MODE: {
|
|
81
|
+
category: "desktop",
|
|
82
|
+
defaultValue: "false",
|
|
83
|
+
description: "Enables desktop proxy defaults, including upstream, public origin, TLS hostnames, and route inventory.",
|
|
84
|
+
},
|
|
85
|
+
BRIDGE_EXTENSION_SETUP_TIMEOUT_MS: {
|
|
86
|
+
category: "reliability",
|
|
87
|
+
defaultValue: "undefined",
|
|
88
|
+
description: "Optional timeout for local extension/plugin setup during bridge startup.",
|
|
89
|
+
},
|
|
90
|
+
BRIDGE_FAIL_OPEN: {
|
|
91
|
+
category: "safety",
|
|
92
|
+
defaultValue: "true",
|
|
93
|
+
description: "Controls whether typed intercept failures return explicit bridge errors after consuming request bodies.",
|
|
94
|
+
},
|
|
95
|
+
BRIDGE_HARDCODED_RESPONSE: {
|
|
96
|
+
category: "model",
|
|
97
|
+
defaultValue: "undefined",
|
|
98
|
+
description: "Optional fixed local model response for deterministic experiments.",
|
|
99
|
+
},
|
|
100
|
+
BRIDGE_HOST: {
|
|
101
|
+
category: "core",
|
|
102
|
+
defaultValue: "127.0.0.1",
|
|
103
|
+
description: "Bridge bind host.",
|
|
104
|
+
},
|
|
105
|
+
BRIDGE_KEY_PATH: {
|
|
106
|
+
category: "tls",
|
|
107
|
+
defaultValue: "undefined",
|
|
108
|
+
requiredWhen: "BRIDGE_USE_TLS=true and generated certs are not used",
|
|
109
|
+
description: "Path to TLS private key material.",
|
|
110
|
+
},
|
|
111
|
+
BRIDGE_LOG_LEVEL: {
|
|
112
|
+
category: "diagnostics",
|
|
113
|
+
defaultValue: "info",
|
|
114
|
+
description: "Bridge log level: debug, info, warn, or error.",
|
|
115
|
+
},
|
|
116
|
+
BRIDGE_LOG_MODEL_PAYLOADS: {
|
|
117
|
+
category: "diagnostics",
|
|
118
|
+
defaultValue: "summary",
|
|
119
|
+
description: "Controls local model payload logging; full payload logging is explicit opt-in.",
|
|
120
|
+
},
|
|
121
|
+
BRIDGE_MAX_INTERCEPT_BODY_BYTES: {
|
|
122
|
+
category: "safety",
|
|
123
|
+
defaultValue: "52428800",
|
|
124
|
+
description: "Maximum buffered body size for typed intercept routes.",
|
|
125
|
+
},
|
|
126
|
+
BRIDGE_MODELS_JSON: {
|
|
127
|
+
category: "model",
|
|
128
|
+
defaultValue: "undefined",
|
|
129
|
+
description: "JSON array of local model registrations with Cursor-facing and provider-facing IDs.",
|
|
130
|
+
},
|
|
131
|
+
BRIDGE_PLUGIN_PATH: {
|
|
132
|
+
category: "plugins",
|
|
133
|
+
defaultValue: "undefined",
|
|
134
|
+
description: "Experimental local plugin module path.",
|
|
135
|
+
},
|
|
136
|
+
BRIDGE_PORT: {
|
|
137
|
+
category: "core",
|
|
138
|
+
defaultValue: "9443",
|
|
139
|
+
description: "Bridge bind port.",
|
|
140
|
+
},
|
|
141
|
+
BRIDGE_PUBLIC_ORIGIN: {
|
|
142
|
+
category: "desktop",
|
|
143
|
+
defaultValue: "desktop mode: https://api2.cursor.sh; otherwise undefined",
|
|
144
|
+
description: "Public origin advertised in rewritten server config responses.",
|
|
145
|
+
},
|
|
146
|
+
BRIDGE_ROUTE_INVENTORY: {
|
|
147
|
+
category: "diagnostics",
|
|
148
|
+
defaultValue: "desktop mode: true; otherwise false",
|
|
149
|
+
description: "Enables redacted method/path/content-type/status/framing route inventory logs.",
|
|
150
|
+
},
|
|
151
|
+
BRIDGE_TLS_HOSTNAMES: {
|
|
152
|
+
category: "tls",
|
|
153
|
+
defaultValue: "desktop mode: api2.cursor.sh,api3.cursor.sh,agent.api5.cursor.sh,agentn.api5.cursor.sh,agentn.global.api5.cursor.sh,localhost,127.0.0.1,::1; otherwise localhost,127.0.0.1,::1",
|
|
154
|
+
description: "Comma-separated hostnames/IPs for generated TLS certificate SANs.",
|
|
155
|
+
},
|
|
156
|
+
BRIDGE_UNSAFE_ALLOW_NON_LOCALHOST: {
|
|
157
|
+
category: "safety",
|
|
158
|
+
defaultValue: "false",
|
|
159
|
+
description: "Required override before binding the bridge to anything other than localhost.",
|
|
160
|
+
},
|
|
161
|
+
BRIDGE_USE_TLS: {
|
|
162
|
+
category: "tls",
|
|
163
|
+
defaultValue: "false",
|
|
164
|
+
description: "Runs the bridge over HTTPS when enabled.",
|
|
165
|
+
},
|
|
166
|
+
BRIDGE_UPSTREAM_REQUEST_TIMEOUT_MS: {
|
|
167
|
+
category: "reliability",
|
|
168
|
+
defaultValue: "undefined",
|
|
169
|
+
description: "Optional timeout for pass-through requests to Cursor upstream services.",
|
|
170
|
+
},
|
|
171
|
+
CURSOR_UPSTREAM_BASE_URL: {
|
|
172
|
+
category: "upstream",
|
|
173
|
+
defaultValue: "desktop mode: https://api2.cursor.sh; otherwise undefined",
|
|
174
|
+
description: "Logical Cursor upstream base URL for pass-through traffic.",
|
|
175
|
+
},
|
|
176
|
+
CURSOR_UPSTREAM_CONNECT_HOST: {
|
|
177
|
+
category: "upstream",
|
|
178
|
+
defaultValue: "undefined",
|
|
179
|
+
description: "Optional physical upstream host/IP while preserving logical Host and TLS SNI.",
|
|
180
|
+
},
|
|
181
|
+
CURSOR_UPSTREAM_CONNECT_PORT: {
|
|
182
|
+
category: "upstream",
|
|
183
|
+
defaultValue: "undefined",
|
|
184
|
+
description: "Optional physical upstream port paired with CURSOR_UPSTREAM_CONNECT_HOST.",
|
|
185
|
+
},
|
|
186
|
+
MODEL_API_KEY: {
|
|
187
|
+
category: "model",
|
|
188
|
+
defaultValue: "",
|
|
189
|
+
description: "API key sent to the OpenAI-compatible local model backend.",
|
|
190
|
+
},
|
|
191
|
+
MODEL_BASE_URL: {
|
|
192
|
+
category: "model",
|
|
193
|
+
defaultValue: "http://localhost:8080/v1",
|
|
194
|
+
description: "OpenAI-compatible local model endpoint.",
|
|
195
|
+
},
|
|
196
|
+
MODEL_CONTEXT_TOKEN_LIMIT: {
|
|
197
|
+
category: "model",
|
|
198
|
+
defaultValue: "128000",
|
|
199
|
+
description: "Advertised local model context window.",
|
|
200
|
+
},
|
|
201
|
+
MODEL_REQUEST_TIMEOUT_MS: {
|
|
202
|
+
category: "model",
|
|
203
|
+
defaultValue: "undefined",
|
|
204
|
+
description: "Optional request deadline for OpenAI-compatible local model backend calls.",
|
|
205
|
+
},
|
|
206
|
+
MODEL_NAME: {
|
|
207
|
+
category: "model",
|
|
208
|
+
defaultValue: "local-model",
|
|
209
|
+
description: "Default Cursor-facing local model ID.",
|
|
210
|
+
},
|
|
211
|
+
MODEL_PROVIDER_MODEL: {
|
|
212
|
+
category: "model",
|
|
213
|
+
defaultValue: "MODEL_NAME",
|
|
214
|
+
description: "Provider-facing model ID sent to the local backend when different from MODEL_NAME.",
|
|
215
|
+
},
|
|
216
|
+
};
|
|
217
|
+
export async function writeBaselineArtifacts(repoRoot = process.cwd()) {
|
|
218
|
+
const rendered = await renderBaselineArtifacts(repoRoot);
|
|
219
|
+
for (const [relativePath, contents] of Object.entries(rendered)) {
|
|
220
|
+
const absolutePath = path.join(repoRoot, relativePath);
|
|
221
|
+
fs.mkdirSync(path.dirname(absolutePath), { recursive: true });
|
|
222
|
+
fs.writeFileSync(absolutePath, contents);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
export async function checkBaselineArtifacts(repoRoot = process.cwd()) {
|
|
226
|
+
const rendered = await renderBaselineArtifacts(repoRoot);
|
|
227
|
+
const changed = [];
|
|
228
|
+
for (const [relativePath, expected] of Object.entries(rendered)) {
|
|
229
|
+
const absolutePath = path.join(repoRoot, relativePath);
|
|
230
|
+
const actual = fs.existsSync(absolutePath)
|
|
231
|
+
? fs.readFileSync(absolutePath, "utf8")
|
|
232
|
+
: "";
|
|
233
|
+
if (actual !== expected) {
|
|
234
|
+
changed.push(relativePath);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return changed;
|
|
238
|
+
}
|
|
239
|
+
export function buildBaselineArtifacts(repoRoot = process.cwd()) {
|
|
240
|
+
const serviceManifest = readServiceManifest(repoRoot);
|
|
241
|
+
const routeContracts = buildRouteContracts(serviceManifest);
|
|
242
|
+
const configInventory = buildConfigInventory(repoRoot);
|
|
243
|
+
const unknownRoutes = buildUnknownRoutes(serviceManifest);
|
|
244
|
+
const testManifest = buildTestManifest();
|
|
245
|
+
const releaseSummary = buildReleaseSummary(routeContracts, configInventory, unknownRoutes, testManifest);
|
|
246
|
+
return {
|
|
247
|
+
routeContractManifest: {
|
|
248
|
+
schemaVersion: 1,
|
|
249
|
+
generatedBy: "src/tools/baselineInventory.ts",
|
|
250
|
+
sources: ["docs/service-manifest.json", "src/routes.ts", "src/config.ts"],
|
|
251
|
+
routes: routeContracts,
|
|
252
|
+
},
|
|
253
|
+
routePolicy: [
|
|
254
|
+
...routeContracts.map((route) => ({
|
|
255
|
+
path: route.path,
|
|
256
|
+
package: route.packageName,
|
|
257
|
+
service: route.service,
|
|
258
|
+
method: route.method,
|
|
259
|
+
policy: route.policy,
|
|
260
|
+
supportLevel: route.supportLevel,
|
|
261
|
+
reason: route.reason,
|
|
262
|
+
uncertainty: route.uncertainty,
|
|
263
|
+
})),
|
|
264
|
+
{
|
|
265
|
+
path: "*",
|
|
266
|
+
policy: "pass-through",
|
|
267
|
+
supportLevel: "observe-first",
|
|
268
|
+
reason: "Default byte-preserving proxy policy for unknown or unverified routes.",
|
|
269
|
+
uncertainty: "Desktop-specific and proto-visible routes must be observed and decoded before interception.",
|
|
270
|
+
},
|
|
271
|
+
],
|
|
272
|
+
implementationInventory: {
|
|
273
|
+
schemaVersion: 1,
|
|
274
|
+
generatedBy: "src/tools/baselineInventory.ts",
|
|
275
|
+
sources: ["docs/service-manifest.json", "src/routes.ts", "src/config.ts"],
|
|
276
|
+
routes: routeContracts,
|
|
277
|
+
config: {
|
|
278
|
+
envVars: configInventory,
|
|
279
|
+
},
|
|
280
|
+
uncertaintyRegister: unknownRoutes,
|
|
281
|
+
},
|
|
282
|
+
testManifest: {
|
|
283
|
+
schemaVersion: 1,
|
|
284
|
+
generatedBy: "src/tools/baselineInventory.ts",
|
|
285
|
+
suites: testManifest,
|
|
286
|
+
},
|
|
287
|
+
releaseSummary,
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
async function renderBaselineArtifacts(repoRoot) {
|
|
291
|
+
const artifacts = buildBaselineArtifacts(repoRoot);
|
|
292
|
+
return {
|
|
293
|
+
[ROUTE_CONTRACT_MANIFEST_PATH]: await renderJson(artifacts.routeContractManifest),
|
|
294
|
+
[ROUTE_POLICY_PATH]: await renderJson(artifacts.routePolicy),
|
|
295
|
+
[IMPLEMENTATION_INVENTORY_PATH]: await renderJson(artifacts.implementationInventory),
|
|
296
|
+
[TEST_MANIFEST_PATH]: await renderJson(artifacts.testManifest),
|
|
297
|
+
[RELEASE_SUMMARY_PATH]: await renderJson(artifacts.releaseSummary),
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
function readServiceManifest(repoRoot) {
|
|
301
|
+
const manifestPath = path.join(repoRoot, "docs/service-manifest.json");
|
|
302
|
+
const parsed = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
|
|
303
|
+
if (!Array.isArray(parsed)) {
|
|
304
|
+
throw new Error("docs/service-manifest.json must contain an array");
|
|
305
|
+
}
|
|
306
|
+
return parsed.map((entry, index) => {
|
|
307
|
+
if (!isServiceMethod(entry)) {
|
|
308
|
+
throw new Error(`Invalid service manifest entry at index ${index}`);
|
|
309
|
+
}
|
|
310
|
+
return entry;
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
function buildRouteContracts(serviceManifest) {
|
|
314
|
+
return ROUTE_CONTRACT_SEEDS.map((seed) => {
|
|
315
|
+
const protoMethod = seed.packageName === undefined ||
|
|
316
|
+
seed.service === undefined ||
|
|
317
|
+
seed.method === undefined
|
|
318
|
+
? undefined
|
|
319
|
+
: findServiceMethod(serviceManifest, {
|
|
320
|
+
packageName: seed.packageName,
|
|
321
|
+
service: seed.service,
|
|
322
|
+
method: seed.method,
|
|
323
|
+
});
|
|
324
|
+
if (seed.packageName !== undefined &&
|
|
325
|
+
seed.service !== undefined &&
|
|
326
|
+
seed.method !== undefined &&
|
|
327
|
+
protoMethod === undefined) {
|
|
328
|
+
throw new Error(`Route ${seed.path} references missing proto method ${seed.packageName}.${seed.service}/${seed.method}`);
|
|
329
|
+
}
|
|
330
|
+
return {
|
|
331
|
+
path: seed.path,
|
|
332
|
+
policy: seed.policy,
|
|
333
|
+
owner: seed.owner,
|
|
334
|
+
packageName: seed.packageName,
|
|
335
|
+
service: seed.service,
|
|
336
|
+
method: seed.method,
|
|
337
|
+
inputType: protoMethod?.inputType,
|
|
338
|
+
outputType: protoMethod?.outputType,
|
|
339
|
+
serverStreaming: protoMethod?.serverStreaming,
|
|
340
|
+
protoBacked: protoMethod !== undefined,
|
|
341
|
+
supportLevel: seed.supportLevel,
|
|
342
|
+
expectedMethods: [...seed.expectedMethods],
|
|
343
|
+
expectedContentTypes: [...seed.expectedContentTypes],
|
|
344
|
+
fixtureStatus: seed.supportLevel === "implemented"
|
|
345
|
+
? "synthetic-or-unit-covered"
|
|
346
|
+
: "needs-captured-fixture",
|
|
347
|
+
testStatus: seed.supportLevel === "implemented"
|
|
348
|
+
? "focused-tests-present"
|
|
349
|
+
: "partial-tests-present",
|
|
350
|
+
realClientEvidence: seed.supportLevel === "implemented"
|
|
351
|
+
? "cli-or-unit-evidence"
|
|
352
|
+
: "traffic-gated",
|
|
353
|
+
reason: seed.reason,
|
|
354
|
+
uncertainty: seed.uncertainty,
|
|
355
|
+
};
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
function buildConfigInventory(repoRoot) {
|
|
359
|
+
const configPath = path.join(repoRoot, "src/config.ts");
|
|
360
|
+
const configSource = fs.readFileSync(configPath, "utf8");
|
|
361
|
+
const names = Array.from(new Set(Array.from(configSource.matchAll(/\benv\.([A-Z][A-Z0-9_]*)\b/g)).map((match) => match[1] ?? ""))).filter((name) => name.length > 0);
|
|
362
|
+
return names.sort().map((name) => {
|
|
363
|
+
const annotation = CONFIG_ENV_ANNOTATIONS[name];
|
|
364
|
+
if (annotation === undefined) {
|
|
365
|
+
throw new Error(`Missing config inventory annotation for ${name}`);
|
|
366
|
+
}
|
|
367
|
+
return { name, ...annotation };
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
function buildUnknownRoutes(serviceManifest) {
|
|
371
|
+
const protoUnknowns = [
|
|
372
|
+
{
|
|
373
|
+
packageName: "agent.v1",
|
|
374
|
+
service: "AgentService",
|
|
375
|
+
method: "RunPoll",
|
|
376
|
+
uncertainty: "Proto-visible alternate Agent transport; leave pass-through until real traffic proves request-id and poll framing.",
|
|
377
|
+
},
|
|
378
|
+
{
|
|
379
|
+
packageName: "aiserver.v1",
|
|
380
|
+
service: "ChatService",
|
|
381
|
+
method: "StreamUnifiedChatWithToolsSSE",
|
|
382
|
+
uncertainty: "Proto-visible Chat SSE variant; leave pass-through until content type, request-id flow, and response shape are captured.",
|
|
383
|
+
},
|
|
384
|
+
{
|
|
385
|
+
packageName: "aiserver.v1",
|
|
386
|
+
service: "ChatService",
|
|
387
|
+
method: "StreamUnifiedChatWithToolsPoll",
|
|
388
|
+
uncertainty: "Proto-visible Chat poll variant; leave pass-through until BidiPollRequest/BidiPollResponse framing is captured.",
|
|
389
|
+
},
|
|
390
|
+
{
|
|
391
|
+
packageName: "aiserver.v1",
|
|
392
|
+
service: "ChatService",
|
|
393
|
+
method: "StreamUnifiedChatWithToolsIdempotent",
|
|
394
|
+
uncertainty: "Proto-visible idempotent Chat route; leave pass-through until observed traffic proves it is needed.",
|
|
395
|
+
},
|
|
396
|
+
{
|
|
397
|
+
packageName: "aiserver.v1",
|
|
398
|
+
service: "ChatService",
|
|
399
|
+
method: "StreamUnifiedChatWithToolsIdempotentSSE",
|
|
400
|
+
uncertainty: "Proto-visible idempotent Chat SSE route; leave pass-through until observed and decoded.",
|
|
401
|
+
},
|
|
402
|
+
{
|
|
403
|
+
packageName: "aiserver.v1",
|
|
404
|
+
service: "ChatService",
|
|
405
|
+
method: "StreamUnifiedChatWithToolsIdempotentPoll",
|
|
406
|
+
uncertainty: "Proto-visible idempotent Chat poll route; leave pass-through until observed and decoded.",
|
|
407
|
+
},
|
|
408
|
+
];
|
|
409
|
+
return [
|
|
410
|
+
...protoUnknowns.map((unknown) => {
|
|
411
|
+
const method = findServiceMethod(serviceManifest, unknown);
|
|
412
|
+
if (method === undefined) {
|
|
413
|
+
throw new Error(`Unknown-route inventory references missing proto method ${unknown.packageName}.${unknown.service}/${unknown.method}`);
|
|
414
|
+
}
|
|
415
|
+
return {
|
|
416
|
+
path: `/${unknown.packageName}.${unknown.service}/${unknown.method}`,
|
|
417
|
+
packageName: unknown.packageName,
|
|
418
|
+
service: unknown.service,
|
|
419
|
+
method: unknown.method,
|
|
420
|
+
inputType: method.inputType,
|
|
421
|
+
outputType: method.outputType,
|
|
422
|
+
serverStreaming: method.serverStreaming,
|
|
423
|
+
policy: "pass-through",
|
|
424
|
+
supportLevel: "observe-first",
|
|
425
|
+
uncertainty: unknown.uncertainty,
|
|
426
|
+
};
|
|
427
|
+
}),
|
|
428
|
+
{
|
|
429
|
+
path: "desktop-route-set",
|
|
430
|
+
policy: "pass-through",
|
|
431
|
+
supportLevel: "observe-first",
|
|
432
|
+
uncertainty: "Cursor desktop route set remains uncertain; use redacted route inventory before adding desktop-only interceptors.",
|
|
433
|
+
},
|
|
434
|
+
];
|
|
435
|
+
}
|
|
436
|
+
function buildTestManifest() {
|
|
437
|
+
return [
|
|
438
|
+
{
|
|
439
|
+
id: "baseline-drift",
|
|
440
|
+
command: "pnpm baseline:check",
|
|
441
|
+
deterministic: true,
|
|
442
|
+
status: "implemented",
|
|
443
|
+
categories: ["baseline-drift", "protocol", "final-gate"],
|
|
444
|
+
releaseCheck: "required",
|
|
445
|
+
prerequisites: ["node>=22", "pnpm install"],
|
|
446
|
+
timeoutMs: 30_000,
|
|
447
|
+
artifactOutputs: [
|
|
448
|
+
ROUTE_CONTRACT_MANIFEST_PATH,
|
|
449
|
+
IMPLEMENTATION_INVENTORY_PATH,
|
|
450
|
+
TEST_MANIFEST_PATH,
|
|
451
|
+
RELEASE_SUMMARY_PATH,
|
|
452
|
+
],
|
|
453
|
+
completionCriteria: [
|
|
454
|
+
"Generated route/config/docs artifacts match committed files.",
|
|
455
|
+
"Every route in src/routes.ts has a route contract entry.",
|
|
456
|
+
"Every env var read by src/config.ts has a config inventory entry.",
|
|
457
|
+
],
|
|
458
|
+
},
|
|
459
|
+
{
|
|
460
|
+
id: "build",
|
|
461
|
+
command: "pnpm build",
|
|
462
|
+
deterministic: true,
|
|
463
|
+
status: "implemented",
|
|
464
|
+
categories: ["static", "final-gate"],
|
|
465
|
+
prerequisites: ["node>=22", "pnpm install"],
|
|
466
|
+
releaseCheck: "required",
|
|
467
|
+
timeoutMs: 60_000,
|
|
468
|
+
artifactOutputs: [".cursor-rpc/release-check/release-summary.json"],
|
|
469
|
+
completionCriteria: ["TypeScript build and declaration emit pass."],
|
|
470
|
+
},
|
|
471
|
+
{
|
|
472
|
+
id: "unit-tests",
|
|
473
|
+
command: "pnpm test",
|
|
474
|
+
deterministic: true,
|
|
475
|
+
status: "implemented",
|
|
476
|
+
categories: [
|
|
477
|
+
"protocol",
|
|
478
|
+
"mlx",
|
|
479
|
+
"tool",
|
|
480
|
+
"reliability-security",
|
|
481
|
+
"final-gate",
|
|
482
|
+
],
|
|
483
|
+
releaseCheck: "required",
|
|
484
|
+
prerequisites: ["node>=22", "pnpm install"],
|
|
485
|
+
timeoutMs: 120_000,
|
|
486
|
+
artifactOutputs: [".cursor-rpc/release-check/release-summary.json"],
|
|
487
|
+
completionCriteria: [
|
|
488
|
+
"Protocol route shapes, fixture replay, MLX contract, tool runtime, desktop proxy, and reliability/security regression tests pass.",
|
|
489
|
+
],
|
|
490
|
+
},
|
|
491
|
+
{
|
|
492
|
+
id: "format-check",
|
|
493
|
+
command: "pnpm format:check",
|
|
494
|
+
deterministic: true,
|
|
495
|
+
status: "implemented",
|
|
496
|
+
categories: ["static", "final-gate"],
|
|
497
|
+
releaseCheck: "required",
|
|
498
|
+
prerequisites: ["node>=22", "pnpm install"],
|
|
499
|
+
timeoutMs: 60_000,
|
|
500
|
+
artifactOutputs: [".cursor-rpc/release-check/release-summary.json"],
|
|
501
|
+
completionCriteria: [
|
|
502
|
+
"Source, tests, docs, JSON, YAML, and examples formatting pass.",
|
|
503
|
+
],
|
|
504
|
+
},
|
|
505
|
+
{
|
|
506
|
+
id: "examples-typecheck",
|
|
507
|
+
command: "pnpm examples:check",
|
|
508
|
+
deterministic: true,
|
|
509
|
+
status: "implemented",
|
|
510
|
+
categories: ["packaging", "final-gate"],
|
|
511
|
+
releaseCheck: "required",
|
|
512
|
+
prerequisites: ["node>=22", "pnpm install", "pnpm build"],
|
|
513
|
+
timeoutMs: 60_000,
|
|
514
|
+
artifactOutputs: [".cursor-rpc/release-check/release-summary.json"],
|
|
515
|
+
completionCriteria: [
|
|
516
|
+
"Examples typecheck against the built package exports that tarball consumers use.",
|
|
517
|
+
],
|
|
518
|
+
},
|
|
519
|
+
{
|
|
520
|
+
id: "pack-smoke",
|
|
521
|
+
command: "pnpm pack && pnpm add --offline <tarball> && cursorkit --help",
|
|
522
|
+
deterministic: true,
|
|
523
|
+
status: "implemented",
|
|
524
|
+
categories: ["packaging", "final-gate"],
|
|
525
|
+
releaseCheck: "required",
|
|
526
|
+
prerequisites: ["node>=22", "pnpm install", "pnpm build"],
|
|
527
|
+
timeoutMs: 60_000,
|
|
528
|
+
artifactOutputs: [".cursor-rpc/release-check/release-summary.json"],
|
|
529
|
+
completionCriteria: [
|
|
530
|
+
"Packed tarball contains required dist/src, proto, docs, README.md, and DISCLAIMER.md files.",
|
|
531
|
+
"Source examples are typechecked but intentionally excluded from the tarball.",
|
|
532
|
+
"A clean temporary project can install the tarball from the local pnpm store.",
|
|
533
|
+
"The packed cursorkit binary executes --help successfully.",
|
|
534
|
+
],
|
|
535
|
+
},
|
|
536
|
+
{
|
|
537
|
+
id: "mlx-live",
|
|
538
|
+
command: "pnpm test:harness -- --suite local-backend --base-url <mlx-url> --provider-model <mlx-model>",
|
|
539
|
+
deterministic: false,
|
|
540
|
+
status: "optional_live",
|
|
541
|
+
categories: ["mlx"],
|
|
542
|
+
releaseCheck: "reported_skipped_with_reason",
|
|
543
|
+
prerequisites: ["Running MLX OpenAI-compatible backend"],
|
|
544
|
+
timeoutMs: 30_000,
|
|
545
|
+
artifactOutputs: [".cursor-rpc/test-runs/*/local-backend-report.json"],
|
|
546
|
+
completionCriteria: [
|
|
547
|
+
"/v1/models returns the configured provider model.",
|
|
548
|
+
"/v1/chat/completions returns a non-empty response.",
|
|
549
|
+
],
|
|
550
|
+
},
|
|
551
|
+
{
|
|
552
|
+
id: "real-client-live",
|
|
553
|
+
command: "pnpm test:harness -- --suite traffic,acp --base-url <mlx-url> --model <cursor-model> --provider-model <mlx-model>",
|
|
554
|
+
deterministic: false,
|
|
555
|
+
status: "optional_live",
|
|
556
|
+
categories: ["protocol", "mlx", "tool"],
|
|
557
|
+
releaseCheck: "reported_skipped_with_reason",
|
|
558
|
+
prerequisites: [
|
|
559
|
+
"cursor-agent installed",
|
|
560
|
+
"Cursor auth available",
|
|
561
|
+
"Running MLX OpenAI-compatible backend",
|
|
562
|
+
],
|
|
563
|
+
timeoutMs: 120_000,
|
|
564
|
+
artifactOutputs: [".cursor-rpc/test-runs/*/summary.json"],
|
|
565
|
+
completionCriteria: [
|
|
566
|
+
"CLI, ACP, and desktop flows report passed or skipped_with_reason.",
|
|
567
|
+
],
|
|
568
|
+
},
|
|
569
|
+
{
|
|
570
|
+
id: "desktop-live",
|
|
571
|
+
command: "pnpm test:harness -- --suite desktop-ui-experimental --include-experimental --base-url <mlx-url> --model <cursor-model> --provider-model <mlx-model>",
|
|
572
|
+
deterministic: false,
|
|
573
|
+
status: "optional_live",
|
|
574
|
+
categories: ["desktop-optional-live"],
|
|
575
|
+
releaseCheck: "reported_skipped_with_reason",
|
|
576
|
+
prerequisites: [
|
|
577
|
+
"Cursor desktop installed",
|
|
578
|
+
"Cursor auth available",
|
|
579
|
+
"Running MLX OpenAI-compatible backend",
|
|
580
|
+
],
|
|
581
|
+
timeoutMs: 180_000,
|
|
582
|
+
artifactOutputs: [".cursor-rpc/test-runs/*/desktop-ui-report.json"],
|
|
583
|
+
completionCriteria: [
|
|
584
|
+
"Desktop route inventory, picker visibility, selected local model, submitted prompt, MLX request, and visible response pass or report skipped_with_reason with an actionable prerequisite.",
|
|
585
|
+
],
|
|
586
|
+
},
|
|
587
|
+
];
|
|
588
|
+
}
|
|
589
|
+
function buildReleaseSummary(routes, configInventory, uncertaintyRegister, testManifest) {
|
|
590
|
+
const interceptRoutes = routes.filter((route) => route.policy === "intercept");
|
|
591
|
+
const protoBackedRoutes = routes.filter((route) => route.protoBacked);
|
|
592
|
+
return {
|
|
593
|
+
schemaVersion: 1,
|
|
594
|
+
generatedBy: "src/tools/baselineInventory.ts",
|
|
595
|
+
phase: "baseline-drift",
|
|
596
|
+
status: "ci-release-scaffolded",
|
|
597
|
+
deterministicGate: "pnpm release:check",
|
|
598
|
+
categories: buildReleaseSummaryCategories(testManifest),
|
|
599
|
+
metrics: {
|
|
600
|
+
routeContractCoverage: `${routes.length}/${ROUTE_CONTRACT_SEEDS.length}`,
|
|
601
|
+
interceptRouteCount: interceptRoutes.length,
|
|
602
|
+
protoBackedRouteCount: protoBackedRoutes.length,
|
|
603
|
+
configEnvVarCount: configInventory.length,
|
|
604
|
+
uncertaintyCount: uncertaintyRegister.length,
|
|
605
|
+
implementedDeterministicSuites: testManifest.filter((suite) => suite.deterministic && suite.status === "implemented").length,
|
|
606
|
+
placeholderSuites: testManifest.filter((suite) => suite.status === "not_implemented").length,
|
|
607
|
+
optionalLiveSuites: testManifest.filter((suite) => suite.status === "optional_live").length,
|
|
608
|
+
},
|
|
609
|
+
remainingBlockers: [
|
|
610
|
+
"Captured fixture replay for conditional intercept routes.",
|
|
611
|
+
"Live cursor-agent, ACP, and desktop acceptance gates.",
|
|
612
|
+
"Final reliability/security hardening validation.",
|
|
613
|
+
"Final full-gate run with optional live MLX and desktop prerequisites available.",
|
|
614
|
+
],
|
|
615
|
+
};
|
|
616
|
+
}
|
|
617
|
+
function buildReleaseSummaryCategories(testManifest) {
|
|
618
|
+
const categoryIds = [
|
|
619
|
+
"baseline-drift",
|
|
620
|
+
"static",
|
|
621
|
+
"protocol",
|
|
622
|
+
"mlx",
|
|
623
|
+
"tool",
|
|
624
|
+
"desktop-optional-live",
|
|
625
|
+
"reliability-security",
|
|
626
|
+
"packaging",
|
|
627
|
+
"final-gate",
|
|
628
|
+
];
|
|
629
|
+
return categoryIds.map((category) => {
|
|
630
|
+
const suites = testManifest.filter((suite) => suite.categories.includes(category));
|
|
631
|
+
const deterministicSuites = suites
|
|
632
|
+
.filter((suite) => suite.deterministic)
|
|
633
|
+
.map((suite) => suite.id);
|
|
634
|
+
const optionalLiveSuites = suites
|
|
635
|
+
.filter((suite) => !suite.deterministic)
|
|
636
|
+
.map((suite) => suite.id);
|
|
637
|
+
return {
|
|
638
|
+
id: category,
|
|
639
|
+
deterministicSuites,
|
|
640
|
+
optionalLiveSuites,
|
|
641
|
+
releaseCheckStatus: deterministicSuites.length > 0
|
|
642
|
+
? "required"
|
|
643
|
+
: "skipped_with_reason_until_prerequisites_available",
|
|
644
|
+
};
|
|
645
|
+
});
|
|
646
|
+
}
|
|
647
|
+
function findServiceMethod(serviceManifest, key) {
|
|
648
|
+
return serviceManifest.find((entry) => entry.packageName === key.packageName &&
|
|
649
|
+
entry.service === key.service &&
|
|
650
|
+
entry.method === key.method);
|
|
651
|
+
}
|
|
652
|
+
async function renderJson(value) {
|
|
653
|
+
return format(`${JSON.stringify(value, null, 2)}\n`, { parser: "json" });
|
|
654
|
+
}
|
|
655
|
+
function isServiceMethod(value) {
|
|
656
|
+
if (typeof value !== "object" || value === null) {
|
|
657
|
+
return false;
|
|
658
|
+
}
|
|
659
|
+
const entry = value;
|
|
660
|
+
return (typeof entry.packageName === "string" &&
|
|
661
|
+
typeof entry.service === "string" &&
|
|
662
|
+
typeof entry.method === "string" &&
|
|
663
|
+
typeof entry.inputType === "string" &&
|
|
664
|
+
typeof entry.outputType === "string" &&
|
|
665
|
+
typeof entry.serverStreaming === "boolean");
|
|
666
|
+
}
|
|
667
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
668
|
+
if (process.argv.includes("--check")) {
|
|
669
|
+
const changed = await checkBaselineArtifacts();
|
|
670
|
+
if (changed.length > 0) {
|
|
671
|
+
console.error(`Baseline artifacts are out of date. Run pnpm baseline:generate.\nChanged files:\n${changed
|
|
672
|
+
.map((file) => `- ${file}`)
|
|
673
|
+
.join("\n")}`);
|
|
674
|
+
process.exitCode = 1;
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
else {
|
|
678
|
+
await writeBaselineArtifacts();
|
|
679
|
+
}
|
|
680
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function checkModelFusionProtocol(): string[];
|