@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,117 @@
1
+ export function formatCursorToolResult(message) {
2
+ for (const value of [
3
+ message.readResult,
4
+ message.lsResult,
5
+ message.grepResult,
6
+ message.shellResult,
7
+ message.writeResult,
8
+ message.deleteResult,
9
+ message.fetchResult,
10
+ message.mcpResult,
11
+ ]) {
12
+ if (value === undefined) {
13
+ continue;
14
+ }
15
+ return JSON.stringify(normalizeToolResult(value), null, 2);
16
+ }
17
+ return JSON.stringify({
18
+ status: "unknown",
19
+ variant: "exec_client_message",
20
+ result: summarizeToolResult(message),
21
+ }, null, 2);
22
+ }
23
+ export function formatCursorToolError(error) {
24
+ return JSON.stringify({
25
+ status: "error",
26
+ error_code: error.code,
27
+ tool_name: error.toolName,
28
+ tool_call_id: error.toolCallId,
29
+ message: error.message,
30
+ ...(error.details === undefined ? {} : { details: error.details }),
31
+ }, null, 2);
32
+ }
33
+ export function agentExecClientMessageFields(message) {
34
+ return [
35
+ ["shellResult", message.shellResult],
36
+ ["writeResult", message.writeResult],
37
+ ["deleteResult", message.deleteResult],
38
+ ["grepResult", message.grepResult],
39
+ ["readResult", message.readResult],
40
+ ["lsResult", message.lsResult],
41
+ ["diagnosticsResult", message.diagnosticsResult],
42
+ ["requestContextResult", message.requestContextResult],
43
+ ["mcpResult", message.mcpResult],
44
+ ["shellStream", message.shellStream],
45
+ ["mcpStateExecResult", message.mcpStateExecResult],
46
+ ["fetchResult", message.fetchResult],
47
+ ["gitDiffResponse", message.gitDiffResponse],
48
+ ]
49
+ .filter(([, value]) => value !== undefined)
50
+ .map(([name]) => name);
51
+ }
52
+ function normalizeToolResult(value) {
53
+ const variant = toolResultVariant(value);
54
+ if (variant === undefined) {
55
+ return {
56
+ status: "unknown",
57
+ variant: "unknown",
58
+ result: summarizeToolResult(value),
59
+ };
60
+ }
61
+ const status = variant.name === "success" && mcpSuccessIsError(variant.value)
62
+ ? "error"
63
+ : variant.status;
64
+ return {
65
+ status,
66
+ variant: variant.name,
67
+ result: summarizeToolResult(variant.value),
68
+ };
69
+ }
70
+ function toolResultVariant(value) {
71
+ if (value === null || typeof value !== "object") {
72
+ return undefined;
73
+ }
74
+ const record = value;
75
+ for (const [name, status] of [
76
+ ["success", "success"],
77
+ ["failure", "error"],
78
+ ["error", "error"],
79
+ ["timeout", "timeout"],
80
+ ["rejected", "rejected"],
81
+ ["spawnError", "error"],
82
+ ["permissionDenied", "rejected"],
83
+ ["fileNotFound", "error"],
84
+ ["notFile", "error"],
85
+ ["fileBusy", "error"],
86
+ ]) {
87
+ const variantValue = record[name];
88
+ if (variantValue !== undefined) {
89
+ return { name, status, value: variantValue };
90
+ }
91
+ }
92
+ return undefined;
93
+ }
94
+ function mcpSuccessIsError(value) {
95
+ return (value !== null &&
96
+ typeof value === "object" &&
97
+ value.isError === true);
98
+ }
99
+ function summarizeToolResult(value) {
100
+ if (Array.isArray(value)) {
101
+ return value.slice(0, 40).map((entry) => summarizeToolResult(entry));
102
+ }
103
+ if (value === null || typeof value !== "object") {
104
+ if (typeof value === "bigint") {
105
+ return value.toString();
106
+ }
107
+ return typeof value === "string" ? value.slice(0, 20_000) : value;
108
+ }
109
+ const result = {};
110
+ for (const [key, entry] of Object.entries(value)) {
111
+ if (key === "$typeName") {
112
+ continue;
113
+ }
114
+ result[key] = summarizeToolResult(entry);
115
+ }
116
+ return result;
117
+ }
@@ -0,0 +1,3 @@
1
+ import type { AgentToolPolicy } from "../config.js";
2
+ import type { OpenAIToolDefinition } from "../providers/openai.js";
3
+ export declare function cursorOpenAITools(policy: AgentToolPolicy): OpenAIToolDefinition[];
@@ -0,0 +1,89 @@
1
+ import { toolEnabledByPolicy } from "./policy.js";
2
+ import { CURSOR_TOOL_SURFACE } from "./surface.js";
3
+ export function cursorOpenAITools(policy) {
4
+ return CURSOR_TOOL_SURFACE.filter((entry) => toolEnabledByPolicy(entry, policy)).flatMap((entry) => {
5
+ switch (entry.openAIToolName) {
6
+ case "read_file":
7
+ return [
8
+ tool("read_file", "Read a file from the Cursor workspace using Cursor's native file tool.", {
9
+ path: { type: "string" },
10
+ offset: { type: "integer" },
11
+ limit: { type: "integer" },
12
+ }, ["path"]),
13
+ ];
14
+ case "list_dir":
15
+ return [
16
+ tool("list_dir", "List a directory from the Cursor workspace using Cursor's native ls tool.", { path: { type: "string" } }, ["path"]),
17
+ ];
18
+ case "grep":
19
+ return [
20
+ tool("grep", "Search workspace files using Cursor's native grep tool.", {
21
+ pattern: { type: "string" },
22
+ path: { type: "string" },
23
+ glob: { type: "string" },
24
+ head_limit: { type: "integer" },
25
+ }, ["pattern"]),
26
+ ];
27
+ case "run_shell":
28
+ return [
29
+ tool("run_shell", "Run a shell command through Cursor's native shell tool. Cursor handles permissions and approval.", {
30
+ command: { type: "string" },
31
+ working_directory: { type: "string" },
32
+ timeout: { type: "integer" },
33
+ description: { type: "string" },
34
+ }, ["command"]),
35
+ ];
36
+ case "write_file":
37
+ return [
38
+ tool("write_file", "Write a file through Cursor's native write tool. Cursor handles permissions and approval.", {
39
+ path: { type: "string" },
40
+ content: { type: "string" },
41
+ return_file_content_after_write: { type: "boolean" },
42
+ }, ["path", "content"]),
43
+ ];
44
+ case "apply_patch":
45
+ return [
46
+ tool("apply_patch", "Apply a targeted edit to a file by replacing old_string with new_string. Cursor reads the file, applies the change, writes it back, and returns a unified diff. Include enough surrounding context in old_string to match exactly once, or set replace_all. To create a new file, pass an empty old_string and the full file content as new_string.", {
47
+ path: { type: "string" },
48
+ old_string: { type: "string" },
49
+ new_string: { type: "string" },
50
+ replace_all: { type: "boolean" },
51
+ }, ["path", "old_string", "new_string"]),
52
+ ];
53
+ case "delete_path":
54
+ return [
55
+ tool("delete_path", "Delete a path through Cursor's native delete tool. Cursor handles permissions and approval.", { path: { type: "string" } }, ["path"]),
56
+ ];
57
+ case "fetch_url":
58
+ return [
59
+ tool("fetch_url", "Fetch a URL through Cursor's native fetch tool.", { url: { type: "string" } }, ["url"]),
60
+ ];
61
+ case "mcp_tool":
62
+ return [
63
+ tool("mcp_tool", "Call an MCP tool through Cursor's native MCP execution path.", {
64
+ provider_identifier: { type: "string" },
65
+ tool_name: { type: "string" },
66
+ name: { type: "string" },
67
+ arguments: { type: "object" },
68
+ }, ["provider_identifier", "tool_name"]),
69
+ ];
70
+ default:
71
+ return [];
72
+ }
73
+ });
74
+ }
75
+ function tool(name, description, properties, required) {
76
+ return {
77
+ type: "function",
78
+ function: {
79
+ name,
80
+ description,
81
+ parameters: {
82
+ type: "object",
83
+ properties,
84
+ required,
85
+ additionalProperties: false,
86
+ },
87
+ },
88
+ };
89
+ }
@@ -0,0 +1,11 @@
1
+ export type CursorToolSupport = "supported" | "policy-gated" | "internal" | "not-supported";
2
+ export interface CursorToolSurfaceEntry {
3
+ execServerField: string;
4
+ execClientField: string;
5
+ openAIToolName?: string;
6
+ support: CursorToolSupport;
7
+ safety: "read" | "network" | "interactive" | "mutating" | "destructive" | "subagent" | "internal";
8
+ notes: string;
9
+ }
10
+ export declare const CURSOR_TOOL_SURFACE: CursorToolSurfaceEntry[];
11
+ export declare function supportedOpenAIToolNames(): string[];
@@ -0,0 +1,251 @@
1
+ export const CURSOR_TOOL_SURFACE = [
2
+ {
3
+ execServerField: "requestContextArgs",
4
+ execClientField: "requestContextResult",
5
+ support: "internal",
6
+ safety: "internal",
7
+ notes: "Bridge uses this to collect native Cursor request context before model execution.",
8
+ },
9
+ {
10
+ execServerField: "readArgs",
11
+ execClientField: "readResult",
12
+ openAIToolName: "read_file",
13
+ support: "supported",
14
+ safety: "read",
15
+ notes: "Read file contents through Cursor permissions.",
16
+ },
17
+ {
18
+ execServerField: "redactedReadArgs",
19
+ execClientField: "redactedReadResult",
20
+ openAIToolName: "redacted_read_file",
21
+ support: "not-supported",
22
+ safety: "read",
23
+ notes: "Same arg/result shape as read, but redaction semantics need live traffic validation.",
24
+ },
25
+ {
26
+ execServerField: "lsArgs",
27
+ execClientField: "lsResult",
28
+ openAIToolName: "list_dir",
29
+ support: "supported",
30
+ safety: "read",
31
+ notes: "List directory tree through Cursor permissions.",
32
+ },
33
+ {
34
+ execServerField: "grepArgs",
35
+ execClientField: "grepResult",
36
+ openAIToolName: "grep",
37
+ support: "supported",
38
+ safety: "read",
39
+ notes: "Search workspace files through Cursor grep.",
40
+ },
41
+ {
42
+ execServerField: "diagnosticsArgs",
43
+ execClientField: "diagnosticsResult",
44
+ openAIToolName: "read_diagnostics",
45
+ support: "not-supported",
46
+ safety: "read",
47
+ notes: "Needs result formatting for diagnostics severity/ranges.",
48
+ },
49
+ {
50
+ execServerField: "shellArgs",
51
+ execClientField: "shellResult",
52
+ openAIToolName: "run_shell",
53
+ support: "policy-gated",
54
+ safety: "destructive",
55
+ notes: "Mapped, but exposed only through policy because shell execution can mutate state.",
56
+ },
57
+ {
58
+ execServerField: "shellStreamArgs",
59
+ execClientField: "shellStream",
60
+ openAIToolName: "stream_shell",
61
+ support: "not-supported",
62
+ safety: "destructive",
63
+ notes: "Streaming shell requires incremental result forwarding and lifecycle management.",
64
+ },
65
+ {
66
+ execServerField: "backgroundShellSpawnArgs",
67
+ execClientField: "backgroundShellSpawnResult",
68
+ openAIToolName: "spawn_background_shell",
69
+ support: "not-supported",
70
+ safety: "destructive",
71
+ notes: "Requires background process tracking and cleanup.",
72
+ },
73
+ {
74
+ execServerField: "writeShellStdinArgs",
75
+ execClientField: "writeShellStdinResult",
76
+ openAIToolName: "write_shell_stdin",
77
+ support: "not-supported",
78
+ safety: "destructive",
79
+ notes: "Requires pairing to a running shell id.",
80
+ },
81
+ {
82
+ execServerField: "writeArgs",
83
+ execClientField: "writeResult",
84
+ openAIToolName: "write_file",
85
+ support: "policy-gated",
86
+ safety: "mutating",
87
+ notes: "Mapped, but exposed only through policy because it mutates files.",
88
+ },
89
+ {
90
+ execServerField: "writeArgs",
91
+ execClientField: "writeResult",
92
+ openAIToolName: "apply_patch",
93
+ support: "policy-gated",
94
+ safety: "mutating",
95
+ notes: "Targeted search/replace edit synthesized from a read + write round trip; returns a unified diff. Policy-gated because it mutates files.",
96
+ },
97
+ {
98
+ execServerField: "deleteArgs",
99
+ execClientField: "deleteResult",
100
+ openAIToolName: "delete_path",
101
+ support: "policy-gated",
102
+ safety: "destructive",
103
+ notes: "Mapped, but exposed only through policy because it deletes files.",
104
+ },
105
+ {
106
+ execServerField: "fetchArgs",
107
+ execClientField: "fetchResult",
108
+ openAIToolName: "fetch_url",
109
+ support: "supported",
110
+ safety: "network",
111
+ notes: "Fetch URL through Cursor network/tool policy.",
112
+ },
113
+ {
114
+ execServerField: "mcpArgs",
115
+ execClientField: "mcpResult",
116
+ openAIToolName: "mcp_tool",
117
+ support: "policy-gated",
118
+ safety: "interactive",
119
+ notes: "Mapped, but real MCP auth/approval/result variants need per-provider validation.",
120
+ },
121
+ {
122
+ execServerField: "listMcpResourcesExecArgs",
123
+ execClientField: "listMcpResourcesExecResult",
124
+ openAIToolName: "list_mcp_resources",
125
+ support: "not-supported",
126
+ safety: "interactive",
127
+ notes: "Needs MCP resource result schema formatting.",
128
+ },
129
+ {
130
+ execServerField: "readMcpResourceExecArgs",
131
+ execClientField: "readMcpResourceExecResult",
132
+ openAIToolName: "read_mcp_resource",
133
+ support: "not-supported",
134
+ safety: "interactive",
135
+ notes: "Needs download-path handling and resource payload formatting.",
136
+ },
137
+ {
138
+ execServerField: "mcpStateExecArgs",
139
+ execClientField: "mcpStateExecResult",
140
+ openAIToolName: "mcp_state",
141
+ support: "not-supported",
142
+ safety: "interactive",
143
+ notes: "Needs state-specific result handling.",
144
+ },
145
+ {
146
+ execServerField: "recordScreenArgs",
147
+ execClientField: "recordScreenResult",
148
+ openAIToolName: "record_screen",
149
+ support: "not-supported",
150
+ safety: "interactive",
151
+ notes: "Requires media artifact capture/formatting.",
152
+ },
153
+ {
154
+ execServerField: "computerUseArgs",
155
+ execClientField: "computerUseResult",
156
+ openAIToolName: "computer_use",
157
+ support: "not-supported",
158
+ safety: "interactive",
159
+ notes: "Requires UI input action policy and screenshot/result formatting.",
160
+ },
161
+ {
162
+ execServerField: "executeHookArgs",
163
+ execClientField: "executeHookResult",
164
+ openAIToolName: "execute_hook",
165
+ support: "not-supported",
166
+ safety: "mutating",
167
+ notes: "Requires hook policy and side-effect accounting.",
168
+ },
169
+ {
170
+ execServerField: "subagentArgs",
171
+ execClientField: "subagentResult",
172
+ openAIToolName: "subagent",
173
+ support: "not-supported",
174
+ safety: "subagent",
175
+ notes: "Requires subagent lifecycle, model selection, and background handling.",
176
+ },
177
+ {
178
+ execServerField: "forceBackgroundSubagentArgs",
179
+ execClientField: "forceBackgroundSubagentResult",
180
+ openAIToolName: "force_background_subagent",
181
+ support: "not-supported",
182
+ safety: "subagent",
183
+ notes: "Requires existing subagent state.",
184
+ },
185
+ {
186
+ execServerField: "subagentAwaitArgs",
187
+ execClientField: "subagentAwaitResult",
188
+ openAIToolName: "subagent_await",
189
+ support: "not-supported",
190
+ safety: "subagent",
191
+ notes: "Requires existing subagent state.",
192
+ },
193
+ {
194
+ execServerField: "gitDiffRequest",
195
+ execClientField: "gitDiffResponse",
196
+ openAIToolName: "git_diff",
197
+ support: "not-supported",
198
+ safety: "read",
199
+ notes: "Needs aiserver git diff request/result formatting.",
200
+ },
201
+ {
202
+ execServerField: "shellAllowlistPrecheckArgs",
203
+ execClientField: "shellAllowlistPrecheckResult",
204
+ support: "not-supported",
205
+ safety: "internal",
206
+ notes: "Precheck flow for shell tools, not exposed directly to model.",
207
+ },
208
+ {
209
+ execServerField: "mcpAllowlistPrecheckArgs",
210
+ execClientField: "mcpAllowlistPrecheckResult",
211
+ support: "not-supported",
212
+ safety: "internal",
213
+ notes: "Precheck flow for MCP tools, not exposed directly to model.",
214
+ },
215
+ {
216
+ execServerField: "webFetchAllowlistPrecheckArgs",
217
+ execClientField: "webFetchAllowlistPrecheckResult",
218
+ support: "not-supported",
219
+ safety: "internal",
220
+ notes: "Precheck flow for web fetch, not exposed directly to model.",
221
+ },
222
+ {
223
+ execServerField: "smartModeClassifierArgs",
224
+ execClientField: "smartModeClassifierResult",
225
+ support: "not-supported",
226
+ safety: "internal",
227
+ notes: "Classifier/precheck flow, not exposed directly to model.",
228
+ },
229
+ {
230
+ execServerField: "canvasDiagnosticsArgs",
231
+ execClientField: "canvasDiagnosticsResult",
232
+ openAIToolName: "canvas_diagnostics",
233
+ support: "not-supported",
234
+ safety: "read",
235
+ notes: "Needs canvas-specific result formatting.",
236
+ },
237
+ {
238
+ execServerField: "forceBackgroundShellArgs",
239
+ execClientField: "forceBackgroundShellResult",
240
+ support: "not-supported",
241
+ safety: "destructive",
242
+ notes: "Requires existing shell state.",
243
+ },
244
+ ];
245
+ export function supportedOpenAIToolNames() {
246
+ return CURSOR_TOOL_SURFACE.flatMap((entry) => entry.support === "supported" || entry.support === "policy-gated"
247
+ ? entry.openAIToolName === undefined
248
+ ? []
249
+ : [entry.openAIToolName]
250
+ : []);
251
+ }
@@ -0,0 +1,8 @@
1
+ import type { BridgeConfig } from "./config.js";
2
+ export interface TlsMaterial {
3
+ cert: string;
4
+ key: string;
5
+ generated: boolean;
6
+ }
7
+ export declare function loadTlsMaterial(config: BridgeConfig): Promise<TlsMaterial>;
8
+ export declare function generateTlsMaterial(hostnames: string[]): Promise<TlsMaterial>;
@@ -0,0 +1,34 @@
1
+ import fs from "node:fs";
2
+ import { isIP } from "node:net";
3
+ import { generate } from "selfsigned";
4
+ export async function loadTlsMaterial(config) {
5
+ if (config.certPath !== undefined || config.keyPath !== undefined) {
6
+ if (config.certPath === undefined || config.keyPath === undefined) {
7
+ throw new Error("Both BRIDGE_CERT_PATH and BRIDGE_KEY_PATH must be set when using custom TLS material");
8
+ }
9
+ return {
10
+ cert: fs.readFileSync(config.certPath, "utf8"),
11
+ key: fs.readFileSync(config.keyPath, "utf8"),
12
+ generated: false,
13
+ };
14
+ }
15
+ return generateTlsMaterial(config.tlsHostnames);
16
+ }
17
+ export async function generateTlsMaterial(hostnames) {
18
+ const primaryHostname = hostnames[0] ?? "localhost";
19
+ const attrs = [{ name: "commonName", value: primaryHostname }];
20
+ const pem = await generate(attrs, {
21
+ notAfterDate: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000),
22
+ keySize: 2048,
23
+ algorithm: "sha256",
24
+ extensions: [
25
+ {
26
+ name: "subjectAltName",
27
+ altNames: hostnames.map((hostname) => isIP(hostname) === 0
28
+ ? { type: 2, value: hostname }
29
+ : { type: 7, ip: hostname }),
30
+ },
31
+ ],
32
+ });
33
+ return { cert: pem.cert, key: pem.private, generated: true };
34
+ }
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/src/ck.js ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ import { runCk } from "./ckLauncher.js";
3
+ runCk().catch((error) => {
4
+ console.error(error instanceof Error ? error.message : String(error));
5
+ process.exitCode = 1;
6
+ });
@@ -0,0 +1,150 @@
1
+ import { type ChildProcess } from "node:child_process";
2
+ import fs from "node:fs";
3
+ import { type LocalModelConfig } from "./config.js";
4
+ import { type DesktopConnectProxy } from "./desktopConnectProxy.js";
5
+ export type CkCommand = "launch" | "test" | "doctor" | "cert" | "route" | "stop" | "help";
6
+ export type CkProfileMode = "isolated" | "default";
7
+ export type CkRouteMethod = "pf" | "direct";
8
+ export type CkRouteAction = "plan" | "status" | "rollback";
9
+ export interface CkArgs {
10
+ command: CkCommand;
11
+ dryRun: boolean;
12
+ profileMode: CkProfileMode;
13
+ timeoutMs: number;
14
+ routeMethod: CkRouteMethod;
15
+ routeAction: CkRouteAction;
16
+ debugPort?: number;
17
+ instanceId?: string;
18
+ seedAuthFromDefault?: boolean;
19
+ }
20
+ export interface CommandSpec {
21
+ executable: string;
22
+ args: string[];
23
+ env?: Record<string, string>;
24
+ }
25
+ export interface CkLaunchPlan {
26
+ bridge: CommandSpec;
27
+ cursor: CommandSpec;
28
+ bridgePort: number;
29
+ connectProxyPort?: number;
30
+ agentHttpPort?: number;
31
+ stateDir: string;
32
+ statePath: string;
33
+ logPath: string;
34
+ connectProxyLogPath?: string;
35
+ userDataDir: string | undefined;
36
+ extensionsDir: string;
37
+ workspacePath: string;
38
+ profileMode: CkProfileMode;
39
+ debugPort?: number;
40
+ instanceId?: string;
41
+ seedAuthFromDefault: boolean;
42
+ authSeedStatus?: CursorAuthSeedStatus;
43
+ localModelSeedStatus?: CursorLocalModelSeedStatus;
44
+ }
45
+ export type CursorAuthSeedStatus = "not-requested" | "not-isolated" | "sqlite-unavailable" | "source-missing" | "no-auth-rows" | "seeded";
46
+ export type CursorLocalModelSeedStatus = "not-isolated" | "sqlite-unavailable" | "state-missing" | "no-local-models" | "seeded";
47
+ export interface CkRoutePlan {
48
+ method: CkRouteMethod;
49
+ hostname: string;
50
+ hostnames: string[];
51
+ bridgePort: number;
52
+ upstreamConnectHost: string | undefined;
53
+ warnings: string[];
54
+ setupCommands: CommandSpec[];
55
+ verificationCommands: CommandSpec[];
56
+ rollbackCommands: CommandSpec[];
57
+ }
58
+ export interface RouteInventoryObservation {
59
+ method: string;
60
+ path: string;
61
+ contentType: string;
62
+ status: number;
63
+ framing: string;
64
+ policy: string;
65
+ outcome: string;
66
+ }
67
+ export interface RouteInventoryPathSummary {
68
+ path: string;
69
+ count: number;
70
+ methods: string[];
71
+ statuses: number[];
72
+ framings: string[];
73
+ policies: string[];
74
+ outcomes: string[];
75
+ }
76
+ export type DesktopRouteCategory = "model-metadata" | "local-agent-candidate" | "pass-through" | "decoded-only" | "unsupported" | "unknown";
77
+ export interface DesktopRouteCategorySummary {
78
+ path: string;
79
+ category: DesktopRouteCategory;
80
+ reason: string;
81
+ }
82
+ export interface DesktopTestReport {
83
+ routeInventorySeen: boolean;
84
+ modelRoutesSeen: string[];
85
+ missingModelRoutes: string[];
86
+ observedPaths: string[];
87
+ routeSummary: RouteInventoryPathSummary[];
88
+ routeCategories: DesktopRouteCategorySummary[];
89
+ failedRoutes: RouteInventoryObservation[];
90
+ passThroughRoutes: RouteInventoryObservation[];
91
+ diagnosis: string[];
92
+ }
93
+ export interface CkProcessGroup {
94
+ bridge: ChildProcess;
95
+ log: fs.WriteStream;
96
+ connectProxy?: DesktopConnectProxy;
97
+ }
98
+ interface CkState {
99
+ bridgePid?: number;
100
+ bridgeCommand?: string;
101
+ bridgePort?: number;
102
+ connectProxyPort?: number;
103
+ agentHttpPort?: number;
104
+ logPath?: string;
105
+ connectProxyLogPath?: string;
106
+ profileMode?: CkProfileMode;
107
+ userDataDir?: string;
108
+ extensionsDir?: string;
109
+ workspacePath?: string;
110
+ debugPort?: number;
111
+ instanceId?: string;
112
+ seedAuthFromDefault?: boolean;
113
+ authSeedStatus?: CursorAuthSeedStatus;
114
+ localModelSeedStatus?: CursorLocalModelSeedStatus;
115
+ startedAt?: string;
116
+ }
117
+ export declare const CK_STATE_DIR: string;
118
+ export declare const CK_STATE_PATH: string;
119
+ export declare function parseCkArgs(argv: string[]): CkArgs;
120
+ export declare function buildCkLaunchPlan(options: {
121
+ env: NodeJS.ProcessEnv;
122
+ bridgePort: number;
123
+ connectProxyPort?: number;
124
+ agentHttpPort?: number;
125
+ profileMode?: CkProfileMode;
126
+ debugPort?: number;
127
+ instanceId?: string;
128
+ seedAuthFromDefault?: boolean;
129
+ cwd?: string;
130
+ }): CkLaunchPlan;
131
+ export declare function commandForDisplay(spec: CommandSpec): string;
132
+ export declare function buildCkRoutePlan(options?: {
133
+ method?: CkRouteMethod;
134
+ bridgePort?: number;
135
+ upstreamConnectHost?: string;
136
+ cwd?: string;
137
+ }): Promise<CkRoutePlan>;
138
+ export declare function containsPrivilegedCommand(spec: CommandSpec): boolean;
139
+ export declare function routeInventoryTimeoutDiagnosis(): string[];
140
+ export declare function analyzeRouteInventoryLog(logText: string): DesktopTestReport;
141
+ export declare function runCk(argv?: string[]): Promise<void>;
142
+ export declare function chooseBridgePort(): Promise<number>;
143
+ export declare function seedCursorAuthFromDefault(plan: Pick<CkLaunchPlan, "profileMode" | "userDataDir" | "seedAuthFromDefault">): CursorAuthSeedStatus;
144
+ export declare function seedLocalModelsIntoCursorState(plan: Pick<CkLaunchPlan, "agentHttpPort" | "bridge" | "profileMode" | "userDataDir">): CursorLocalModelSeedStatus;
145
+ export declare function mergeLocalAgentBackendUrlsIntoApplicationUser(applicationUser: Record<string, unknown>, agentOrigin: string): void;
146
+ export declare function mergeLocalDesktopModelsIntoApplicationUser(applicationUser: Record<string, unknown>, models: LocalModelConfig[]): void;
147
+ export declare function buildLocalDesktopModelEntry(model: LocalModelConfig): Record<string, unknown>;
148
+ export declare function cleanupIsolatedCursorProcesses(userDataDir: string): number[];
149
+ export declare function bridgeProcessMatchesState(command: string, state?: Pick<CkState, "bridgeCommand">): boolean;
150
+ export {};