@playwo/opencode-cursor-oauth 0.0.0-dev.1b946f85e9b0 → 0.0.0-dev.2a59bf1639ea

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 (72) hide show
  1. package/README.md +19 -91
  2. package/dist/auth.js +1 -2
  3. package/dist/constants.d.ts +2 -0
  4. package/dist/constants.js +2 -0
  5. package/dist/cursor/bidi-session.d.ts +13 -0
  6. package/dist/cursor/bidi-session.js +149 -0
  7. package/dist/cursor/config.d.ts +4 -0
  8. package/dist/cursor/config.js +4 -0
  9. package/dist/cursor/connect-framing.d.ts +10 -0
  10. package/dist/cursor/connect-framing.js +80 -0
  11. package/dist/cursor/headers.d.ts +6 -0
  12. package/dist/cursor/headers.js +16 -0
  13. package/dist/cursor/index.d.ts +5 -0
  14. package/dist/cursor/index.js +5 -0
  15. package/dist/cursor/unary-rpc.d.ts +13 -0
  16. package/dist/cursor/unary-rpc.js +181 -0
  17. package/dist/index.d.ts +2 -14
  18. package/dist/index.js +2 -297
  19. package/dist/logger.js +7 -2
  20. package/dist/models.js +1 -23
  21. package/dist/openai/index.d.ts +3 -0
  22. package/dist/openai/index.js +3 -0
  23. package/dist/openai/messages.d.ts +39 -0
  24. package/dist/openai/messages.js +223 -0
  25. package/dist/openai/tools.d.ts +7 -0
  26. package/dist/openai/tools.js +58 -0
  27. package/dist/openai/types.d.ts +41 -0
  28. package/dist/openai/types.js +1 -0
  29. package/dist/plugin/cursor-auth-plugin.d.ts +3 -0
  30. package/dist/plugin/cursor-auth-plugin.js +140 -0
  31. package/dist/proto/agent_pb.js +637 -319
  32. package/dist/provider/index.d.ts +2 -0
  33. package/dist/provider/index.js +2 -0
  34. package/dist/provider/model-cost.d.ts +9 -0
  35. package/dist/provider/model-cost.js +206 -0
  36. package/dist/provider/models.d.ts +8 -0
  37. package/dist/provider/models.js +86 -0
  38. package/dist/proxy/bridge-non-streaming.d.ts +3 -0
  39. package/dist/proxy/bridge-non-streaming.js +119 -0
  40. package/dist/proxy/bridge-session.d.ts +5 -0
  41. package/dist/proxy/bridge-session.js +13 -0
  42. package/dist/proxy/bridge-streaming.d.ts +5 -0
  43. package/dist/proxy/bridge-streaming.js +311 -0
  44. package/dist/proxy/bridge.d.ts +3 -0
  45. package/dist/proxy/bridge.js +3 -0
  46. package/dist/proxy/chat-completion.d.ts +2 -0
  47. package/dist/proxy/chat-completion.js +113 -0
  48. package/dist/proxy/conversation-meta.d.ts +12 -0
  49. package/dist/proxy/conversation-meta.js +1 -0
  50. package/dist/proxy/conversation-state.d.ts +35 -0
  51. package/dist/proxy/conversation-state.js +95 -0
  52. package/dist/proxy/cursor-request.d.ts +5 -0
  53. package/dist/proxy/cursor-request.js +86 -0
  54. package/dist/proxy/index.d.ts +12 -0
  55. package/dist/proxy/index.js +12 -0
  56. package/dist/proxy/server.d.ts +6 -0
  57. package/dist/proxy/server.js +89 -0
  58. package/dist/proxy/sse.d.ts +5 -0
  59. package/dist/proxy/sse.js +5 -0
  60. package/dist/proxy/state-sync.d.ts +2 -0
  61. package/dist/proxy/state-sync.js +17 -0
  62. package/dist/proxy/stream-dispatch.d.ts +42 -0
  63. package/dist/proxy/stream-dispatch.js +491 -0
  64. package/dist/proxy/stream-state.d.ts +9 -0
  65. package/dist/proxy/stream-state.js +1 -0
  66. package/dist/proxy/title.d.ts +1 -0
  67. package/dist/proxy/title.js +103 -0
  68. package/dist/proxy/types.d.ts +27 -0
  69. package/dist/proxy/types.js +1 -0
  70. package/dist/proxy.d.ts +2 -20
  71. package/dist/proxy.js +2 -1385
  72. package/package.json +1 -1
@@ -0,0 +1,12 @@
1
+ export * from "./server";
2
+ export * from "./bridge";
3
+ export * from "./chat-completion";
4
+ export * from "./conversation-meta";
5
+ export * from "./conversation-state";
6
+ export * from "./cursor-request";
7
+ export * from "./sse";
8
+ export * from "./state-sync";
9
+ export * from "./stream-dispatch";
10
+ export * from "./stream-state";
11
+ export * from "./title";
12
+ export * from "./types";
@@ -0,0 +1,12 @@
1
+ export * from "./server";
2
+ export * from "./bridge";
3
+ export * from "./chat-completion";
4
+ export * from "./conversation-meta";
5
+ export * from "./conversation-state";
6
+ export * from "./cursor-request";
7
+ export * from "./sse";
8
+ export * from "./state-sync";
9
+ export * from "./stream-dispatch";
10
+ export * from "./stream-state";
11
+ export * from "./title";
12
+ export * from "./types";
@@ -0,0 +1,6 @@
1
+ export declare function getProxyPort(): number | undefined;
2
+ export declare function startProxy(getAccessToken: () => Promise<string>, models?: ReadonlyArray<{
3
+ id: string;
4
+ name: string;
5
+ }>): Promise<number>;
6
+ export declare function stopProxy(): void;
@@ -0,0 +1,89 @@
1
+ import { errorDetails, logPluginError } from "../logger";
2
+ import { handleChatCompletion } from "./chat-completion";
3
+ import { activeBridges, conversationStates } from "./conversation-state";
4
+ let proxyServer;
5
+ let proxyPort;
6
+ let proxyAccessTokenProvider;
7
+ let proxyModels = [];
8
+ function buildOpenAIModelList(models) {
9
+ return models.map((model) => ({
10
+ id: model.id,
11
+ object: "model",
12
+ created: 0,
13
+ owned_by: "cursor",
14
+ }));
15
+ }
16
+ export function getProxyPort() {
17
+ return proxyPort;
18
+ }
19
+ export async function startProxy(getAccessToken, models = []) {
20
+ proxyAccessTokenProvider = getAccessToken;
21
+ proxyModels = models.map((model) => ({
22
+ id: model.id,
23
+ name: model.name,
24
+ }));
25
+ if (proxyServer && proxyPort)
26
+ return proxyPort;
27
+ proxyServer = Bun.serve({
28
+ port: 0,
29
+ idleTimeout: 255, // max — Cursor responses can take 30s+
30
+ async fetch(req) {
31
+ const url = new URL(req.url);
32
+ if (req.method === "GET" && url.pathname === "/v1/models") {
33
+ return new Response(JSON.stringify({
34
+ object: "list",
35
+ data: buildOpenAIModelList(proxyModels),
36
+ }), { headers: { "Content-Type": "application/json" } });
37
+ }
38
+ if (req.method === "POST" && url.pathname === "/v1/chat/completions") {
39
+ try {
40
+ const body = (await req.json());
41
+ if (!proxyAccessTokenProvider) {
42
+ throw new Error("Cursor proxy access token provider not configured");
43
+ }
44
+ const accessToken = await proxyAccessTokenProvider();
45
+ const sessionId = req.headers.get("x-opencode-session-id") ??
46
+ req.headers.get("x-session-id") ??
47
+ undefined;
48
+ const agentKey = req.headers.get("x-opencode-agent") ?? undefined;
49
+ return handleChatCompletion(body, accessToken, {
50
+ sessionId,
51
+ agentKey,
52
+ });
53
+ }
54
+ catch (err) {
55
+ const message = err instanceof Error ? err.message : String(err);
56
+ logPluginError("Cursor proxy request failed", {
57
+ path: url.pathname,
58
+ method: req.method,
59
+ ...errorDetails(err),
60
+ });
61
+ return new Response(JSON.stringify({
62
+ error: { message, type: "server_error", code: "internal_error" },
63
+ }), { status: 500, headers: { "Content-Type": "application/json" } });
64
+ }
65
+ }
66
+ return new Response("Not Found", { status: 404 });
67
+ },
68
+ });
69
+ proxyPort = proxyServer.port;
70
+ if (!proxyPort)
71
+ throw new Error("Failed to bind proxy to a port");
72
+ return proxyPort;
73
+ }
74
+ export function stopProxy() {
75
+ if (proxyServer) {
76
+ proxyServer.stop();
77
+ proxyServer = undefined;
78
+ proxyPort = undefined;
79
+ proxyAccessTokenProvider = undefined;
80
+ proxyModels = [];
81
+ }
82
+ // Clean up any lingering bridges
83
+ for (const active of activeBridges.values()) {
84
+ clearInterval(active.heartbeatTimer);
85
+ active.bridge.end();
86
+ }
87
+ activeBridges.clear();
88
+ conversationStates.clear();
89
+ }
@@ -0,0 +1,5 @@
1
+ export declare const SSE_HEADERS: {
2
+ readonly "Content-Type": "text/event-stream";
3
+ readonly "Cache-Control": "no-cache";
4
+ readonly Connection: "keep-alive";
5
+ };
@@ -0,0 +1,5 @@
1
+ export const SSE_HEADERS = {
2
+ "Content-Type": "text/event-stream",
3
+ "Cache-Control": "no-cache",
4
+ Connection: "keep-alive",
5
+ };
@@ -0,0 +1,2 @@
1
+ export declare function updateConversationCheckpoint(convKey: string, checkpointBytes: Uint8Array): void;
2
+ export declare function syncStoredBlobStore(convKey: string, blobStore: Map<string, Uint8Array>): void;
@@ -0,0 +1,17 @@
1
+ import { conversationStates } from "./conversation-state";
2
+ export function updateConversationCheckpoint(convKey, checkpointBytes) {
3
+ const stored = conversationStates.get(convKey);
4
+ if (!stored)
5
+ return;
6
+ stored.checkpoint = checkpointBytes;
7
+ stored.lastAccessMs = Date.now();
8
+ }
9
+ export function syncStoredBlobStore(convKey, blobStore) {
10
+ const stored = conversationStates.get(convKey);
11
+ if (!stored)
12
+ return;
13
+ for (const [key, value] of blobStore) {
14
+ stored.blobStore.set(key, value);
15
+ }
16
+ stored.lastAccessMs = Date.now();
17
+ }
@@ -0,0 +1,42 @@
1
+ import { type AgentServerMessage, type McpToolDefinition } from "../proto/agent_pb";
2
+ import type { CursorSession } from "../cursor/bidi-session";
3
+ import type { StreamState } from "./stream-state";
4
+ import type { PendingExec } from "./types";
5
+ export interface UnhandledExecInfo {
6
+ execCase: string;
7
+ execId: string;
8
+ execMsgId: number;
9
+ }
10
+ export interface UnsupportedServerMessageInfo {
11
+ category: "agentMessage" | "interactionUpdate" | "interactionQuery" | "execServerControl" | "toolCall";
12
+ caseName: string;
13
+ detail?: string;
14
+ }
15
+ export declare function parseConnectEndStream(data: Uint8Array): Error | null;
16
+ export declare function makeHeartbeatBytes(): Uint8Array;
17
+ export declare function scheduleBridgeEnd(bridge: CursorSession): void;
18
+ /**
19
+ * Create a stateful parser for Connect protocol frames.
20
+ * Handles buffering partial data across chunks.
21
+ */
22
+ export declare function createConnectFrameParser(onMessage: (bytes: Uint8Array) => void, onEndStream: (bytes: Uint8Array) => void): (incoming: Buffer) => void;
23
+ /**
24
+ * Strip thinking tags from streamed text, routing tagged content to reasoning.
25
+ * Buffers partial tags across chunk boundaries.
26
+ */
27
+ export declare function createThinkingTagFilter(): {
28
+ process(text: string): {
29
+ content: string;
30
+ reasoning: string;
31
+ };
32
+ flush(): {
33
+ content: string;
34
+ reasoning: string;
35
+ };
36
+ };
37
+ export declare function computeUsage(state: StreamState): {
38
+ prompt_tokens: number;
39
+ completion_tokens: number;
40
+ total_tokens: number;
41
+ };
42
+ export declare function processServerMessage(msg: AgentServerMessage, blobStore: Map<string, Uint8Array>, mcpTools: McpToolDefinition[], sendFrame: (data: Uint8Array) => void, state: StreamState, onText: (text: string, isThinking?: boolean) => void, onMcpExec: (exec: PendingExec) => void, onCheckpoint?: (checkpointBytes: Uint8Array) => void, onTurnEnded?: () => void, onUnsupportedMessage?: (info: UnsupportedServerMessageInfo) => void, onUnhandledExec?: (info: UnhandledExecInfo) => void): void;