@playwo/opencode-cursor-oauth 0.0.0-dev.e3644b4a140d → 0.0.0-dev.e95256212849

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 (71) hide show
  1. package/dist/auth.js +1 -2
  2. package/dist/constants.d.ts +2 -0
  3. package/dist/constants.js +2 -0
  4. package/dist/cursor/bidi-session.d.ts +12 -0
  5. package/dist/cursor/bidi-session.js +164 -0
  6. package/dist/cursor/config.d.ts +4 -0
  7. package/dist/cursor/config.js +4 -0
  8. package/dist/cursor/connect-framing.d.ts +10 -0
  9. package/dist/cursor/connect-framing.js +80 -0
  10. package/dist/cursor/headers.d.ts +6 -0
  11. package/dist/cursor/headers.js +16 -0
  12. package/dist/cursor/index.d.ts +5 -0
  13. package/dist/cursor/index.js +5 -0
  14. package/dist/cursor/unary-rpc.d.ts +12 -0
  15. package/dist/cursor/unary-rpc.js +124 -0
  16. package/dist/index.d.ts +2 -14
  17. package/dist/index.js +2 -306
  18. package/dist/logger.js +7 -2
  19. package/dist/models.js +1 -23
  20. package/dist/openai/index.d.ts +3 -0
  21. package/dist/openai/index.js +3 -0
  22. package/dist/openai/messages.d.ts +39 -0
  23. package/dist/openai/messages.js +228 -0
  24. package/dist/openai/tools.d.ts +7 -0
  25. package/dist/openai/tools.js +58 -0
  26. package/dist/openai/types.d.ts +41 -0
  27. package/dist/openai/types.js +1 -0
  28. package/dist/plugin/cursor-auth-plugin.d.ts +3 -0
  29. package/dist/plugin/cursor-auth-plugin.js +139 -0
  30. package/dist/proto/agent_pb.js +637 -319
  31. package/dist/provider/index.d.ts +2 -0
  32. package/dist/provider/index.js +2 -0
  33. package/dist/provider/model-cost.d.ts +9 -0
  34. package/dist/provider/model-cost.js +206 -0
  35. package/dist/provider/models.d.ts +8 -0
  36. package/dist/provider/models.js +86 -0
  37. package/dist/proxy/bridge-non-streaming.d.ts +3 -0
  38. package/dist/proxy/bridge-non-streaming.js +119 -0
  39. package/dist/proxy/bridge-session.d.ts +5 -0
  40. package/dist/proxy/bridge-session.js +11 -0
  41. package/dist/proxy/bridge-streaming.d.ts +5 -0
  42. package/dist/proxy/bridge-streaming.js +342 -0
  43. package/dist/proxy/bridge.d.ts +3 -0
  44. package/dist/proxy/bridge.js +3 -0
  45. package/dist/proxy/chat-completion.d.ts +2 -0
  46. package/dist/proxy/chat-completion.js +114 -0
  47. package/dist/proxy/conversation-meta.d.ts +12 -0
  48. package/dist/proxy/conversation-meta.js +1 -0
  49. package/dist/proxy/conversation-state.d.ts +35 -0
  50. package/dist/proxy/conversation-state.js +95 -0
  51. package/dist/proxy/cursor-request.d.ts +6 -0
  52. package/dist/proxy/cursor-request.js +104 -0
  53. package/dist/proxy/index.d.ts +12 -0
  54. package/dist/proxy/index.js +12 -0
  55. package/dist/proxy/server.d.ts +6 -0
  56. package/dist/proxy/server.js +107 -0
  57. package/dist/proxy/sse.d.ts +5 -0
  58. package/dist/proxy/sse.js +5 -0
  59. package/dist/proxy/state-sync.d.ts +2 -0
  60. package/dist/proxy/state-sync.js +17 -0
  61. package/dist/proxy/stream-dispatch.d.ts +42 -0
  62. package/dist/proxy/stream-dispatch.js +614 -0
  63. package/dist/proxy/stream-state.d.ts +9 -0
  64. package/dist/proxy/stream-state.js +1 -0
  65. package/dist/proxy/title.d.ts +1 -0
  66. package/dist/proxy/title.js +103 -0
  67. package/dist/proxy/types.d.ts +27 -0
  68. package/dist/proxy/types.js +1 -0
  69. package/dist/proxy.d.ts +2 -20
  70. package/dist/proxy.js +2 -1689
  71. package/package.json +1 -1
package/dist/auth.js CHANGED
@@ -111,7 +111,6 @@ export function getTokenExpiry(token) {
111
111
  return decoded.exp * 1000 - 5 * 60 * 1000;
112
112
  }
113
113
  }
114
- catch {
115
- }
114
+ catch { }
116
115
  return Date.now() + 3600 * 1000;
117
116
  }
@@ -0,0 +1,2 @@
1
+ export declare const CURSOR_PROVIDER_ID: "cursor";
2
+ export declare const OPENCODE_TITLE_REQUEST_MARKER = "Generate a title for this conversation:";
@@ -0,0 +1,2 @@
1
+ export const CURSOR_PROVIDER_ID = "cursor";
2
+ export const OPENCODE_TITLE_REQUEST_MARKER = "Generate a title for this conversation:";
@@ -0,0 +1,12 @@
1
+ import { type CursorBaseRequestOptions } from "./headers";
2
+ export interface CursorSession {
3
+ write: (data: Uint8Array) => void;
4
+ end: () => void;
5
+ onData: (cb: (chunk: Buffer) => void) => void;
6
+ onClose: (cb: (code: number) => void) => void;
7
+ readonly alive: boolean;
8
+ }
9
+ export interface CreateCursorSessionOptions extends CursorBaseRequestOptions {
10
+ initialRequestBytes: Uint8Array;
11
+ }
12
+ export declare function createCursorSession(options: CreateCursorSessionOptions): Promise<CursorSession>;
@@ -0,0 +1,164 @@
1
+ import { connect as connectHttp2, } from "node:http2";
2
+ import { CURSOR_API_URL, CURSOR_CONNECT_PROTOCOL_VERSION } from "./config";
3
+ import { frameConnectMessage } from "./connect-framing";
4
+ import { buildCursorHeaderValues, } from "./headers";
5
+ import { errorDetails, logPluginError } from "../logger";
6
+ const CURSOR_BIDI_RUN_PATH = "/agent.v1.AgentService/Run";
7
+ export async function createCursorSession(options) {
8
+ if (options.initialRequestBytes.length === 0) {
9
+ throw new Error("Cursor sessions require an initial request message");
10
+ }
11
+ const target = new URL(CURSOR_BIDI_RUN_PATH, options.url ?? CURSOR_API_URL);
12
+ const authority = `${target.protocol}//${target.host}`;
13
+ const requestId = crypto.randomUUID();
14
+ return new Promise((resolve, reject) => {
15
+ const cbs = {
16
+ data: null,
17
+ close: null,
18
+ };
19
+ let session;
20
+ let stream;
21
+ let alive = true;
22
+ let closeCode = 0;
23
+ let opened = false;
24
+ let settled = false;
25
+ let statusCode = 0;
26
+ const pendingChunks = [];
27
+ const errorChunks = [];
28
+ const closeTransport = () => {
29
+ try {
30
+ stream?.close();
31
+ }
32
+ catch { }
33
+ try {
34
+ session?.close();
35
+ }
36
+ catch { }
37
+ };
38
+ const finish = (code) => {
39
+ if (!alive)
40
+ return;
41
+ alive = false;
42
+ closeCode = code;
43
+ cbs.close?.(code);
44
+ closeTransport();
45
+ };
46
+ const rejectOpen = (error) => {
47
+ if (settled)
48
+ return;
49
+ settled = true;
50
+ alive = false;
51
+ closeTransport();
52
+ reject(error);
53
+ };
54
+ const resolveOpen = (sessionHandle) => {
55
+ if (settled)
56
+ return;
57
+ settled = true;
58
+ opened = true;
59
+ resolve(sessionHandle);
60
+ };
61
+ const handleTransportError = (message, error) => {
62
+ logPluginError(message, {
63
+ requestId,
64
+ url: target.toString(),
65
+ ...errorDetails(error),
66
+ });
67
+ if (!opened) {
68
+ rejectOpen(new Error(error instanceof Error ? error.message : String(error ?? message)));
69
+ return;
70
+ }
71
+ finish(1);
72
+ };
73
+ const sessionHandle = {
74
+ get alive() {
75
+ return alive;
76
+ },
77
+ write(data) {
78
+ if (!alive || !stream)
79
+ return;
80
+ try {
81
+ stream.write(frameConnectMessage(data));
82
+ }
83
+ catch (error) {
84
+ handleTransportError("Cursor HTTP/2 write failed", error);
85
+ }
86
+ },
87
+ end() {
88
+ finish(0);
89
+ },
90
+ onData(cb) {
91
+ cbs.data = cb;
92
+ while (pendingChunks.length > 0) {
93
+ cb(pendingChunks.shift());
94
+ }
95
+ },
96
+ onClose(cb) {
97
+ if (!alive) {
98
+ queueMicrotask(() => cb(closeCode));
99
+ }
100
+ else {
101
+ cbs.close = cb;
102
+ }
103
+ },
104
+ };
105
+ try {
106
+ session = connectHttp2(authority);
107
+ session.once("error", (error) => {
108
+ handleTransportError("Cursor HTTP/2 session failed", error);
109
+ });
110
+ const headers = {
111
+ ":method": "POST",
112
+ ":path": `${target.pathname}${target.search}`,
113
+ ...buildCursorHeaderValues(options, "application/connect+proto", {
114
+ accept: "application/connect+proto",
115
+ "connect-protocol-version": CURSOR_CONNECT_PROTOCOL_VERSION,
116
+ }),
117
+ };
118
+ stream = session.request(headers);
119
+ stream.once("response", (responseHeaders) => {
120
+ const statusHeader = responseHeaders[":status"];
121
+ statusCode =
122
+ typeof statusHeader === "number"
123
+ ? statusHeader
124
+ : Number(statusHeader ?? 0);
125
+ if (statusCode >= 200 && statusCode < 300) {
126
+ resolveOpen(sessionHandle);
127
+ }
128
+ });
129
+ stream.on("data", (chunk) => {
130
+ const buffer = Buffer.from(chunk);
131
+ if (!opened && statusCode >= 400) {
132
+ errorChunks.push(buffer);
133
+ return;
134
+ }
135
+ if (cbs.data) {
136
+ cbs.data(buffer);
137
+ }
138
+ else {
139
+ pendingChunks.push(buffer);
140
+ }
141
+ });
142
+ stream.once("end", () => {
143
+ if (!opened) {
144
+ const errorBody = Buffer.concat(errorChunks).toString("utf8").trim();
145
+ logPluginError("Cursor HTTP/2 Run request failed", {
146
+ requestId,
147
+ status: statusCode,
148
+ responseBody: errorBody,
149
+ });
150
+ rejectOpen(new Error(`Run failed: ${statusCode || 1}${errorBody ? ` ${errorBody}` : ""}`));
151
+ return;
152
+ }
153
+ finish(statusCode >= 200 && statusCode < 300 ? 0 : statusCode || 1);
154
+ });
155
+ stream.once("error", (error) => {
156
+ handleTransportError("Cursor HTTP/2 stream failed", error);
157
+ });
158
+ stream.write(frameConnectMessage(options.initialRequestBytes));
159
+ }
160
+ catch (error) {
161
+ handleTransportError("Cursor HTTP/2 transport setup failed", error);
162
+ }
163
+ });
164
+ }
@@ -0,0 +1,4 @@
1
+ export declare const CURSOR_API_URL: string;
2
+ export declare const CURSOR_CLIENT_VERSION = "cli-2026.01.09-231024f";
3
+ export declare const CURSOR_CONNECT_PROTOCOL_VERSION = "1";
4
+ export declare const CONNECT_END_STREAM_FLAG = 2;
@@ -0,0 +1,4 @@
1
+ export const CURSOR_API_URL = process.env.CURSOR_API_URL ?? "https://api2.cursor.sh";
2
+ export const CURSOR_CLIENT_VERSION = "cli-2026.01.09-231024f";
3
+ export const CURSOR_CONNECT_PROTOCOL_VERSION = "1";
4
+ export const CONNECT_END_STREAM_FLAG = 0b00000010;
@@ -0,0 +1,10 @@
1
+ /** Connect protocol frame: [1-byte flags][4-byte BE length][payload] */
2
+ export declare function frameConnectMessage(data: Uint8Array, flags?: number): Buffer;
3
+ export declare function decodeConnectUnaryBody(payload: Uint8Array): Uint8Array | null;
4
+ export declare function encodeVarint(value: number): Uint8Array;
5
+ export declare function encodeProtoField(tag: number, wireType: number, value: Uint8Array): Uint8Array;
6
+ export declare function encodeProtoStringField(tag: number, value: string): Uint8Array;
7
+ export declare function encodeProtoMessageField(tag: number, value: Uint8Array): Uint8Array;
8
+ export declare function encodeProtoVarintField(tag: number, value: number): Uint8Array;
9
+ export declare function concatBytes(parts: Uint8Array[]): Uint8Array;
10
+ export declare function toFetchBody(data: Uint8Array): ArrayBuffer;
@@ -0,0 +1,80 @@
1
+ import { CONNECT_END_STREAM_FLAG } from "./config";
2
+ /** Connect protocol frame: [1-byte flags][4-byte BE length][payload] */
3
+ export function frameConnectMessage(data, flags = 0) {
4
+ const frame = Buffer.alloc(5 + data.length);
5
+ frame[0] = flags;
6
+ frame.writeUInt32BE(data.length, 1);
7
+ frame.set(data, 5);
8
+ return frame;
9
+ }
10
+ export function decodeConnectUnaryBody(payload) {
11
+ if (payload.length < 5)
12
+ return null;
13
+ let offset = 0;
14
+ while (offset + 5 <= payload.length) {
15
+ const flags = payload[offset];
16
+ const view = new DataView(payload.buffer, payload.byteOffset + offset, payload.byteLength - offset);
17
+ const messageLength = view.getUint32(1, false);
18
+ const frameEnd = offset + 5 + messageLength;
19
+ if (frameEnd > payload.length)
20
+ return null;
21
+ if ((flags & 0b0000_0001) !== 0)
22
+ return null;
23
+ if ((flags & CONNECT_END_STREAM_FLAG) === 0) {
24
+ return payload.subarray(offset + 5, frameEnd);
25
+ }
26
+ offset = frameEnd;
27
+ }
28
+ return null;
29
+ }
30
+ export function encodeVarint(value) {
31
+ if (!Number.isSafeInteger(value) || value < 0) {
32
+ throw new Error(`Unsupported varint value: ${value}`);
33
+ }
34
+ const bytes = [];
35
+ let current = value;
36
+ while (current >= 0x80) {
37
+ bytes.push((current & 0x7f) | 0x80);
38
+ current = Math.floor(current / 128);
39
+ }
40
+ bytes.push(current);
41
+ return Uint8Array.from(bytes);
42
+ }
43
+ export function encodeProtoField(tag, wireType, value) {
44
+ const key = encodeVarint((tag << 3) | wireType);
45
+ const out = new Uint8Array(key.length + value.length);
46
+ out.set(key, 0);
47
+ out.set(value, key.length);
48
+ return out;
49
+ }
50
+ export function encodeProtoStringField(tag, value) {
51
+ const bytes = new TextEncoder().encode(value);
52
+ const len = encodeVarint(bytes.length);
53
+ const payload = new Uint8Array(len.length + bytes.length);
54
+ payload.set(len, 0);
55
+ payload.set(bytes, len.length);
56
+ return encodeProtoField(tag, 2, payload);
57
+ }
58
+ export function encodeProtoMessageField(tag, value) {
59
+ const len = encodeVarint(value.length);
60
+ const payload = new Uint8Array(len.length + value.length);
61
+ payload.set(len, 0);
62
+ payload.set(value, len.length);
63
+ return encodeProtoField(tag, 2, payload);
64
+ }
65
+ export function encodeProtoVarintField(tag, value) {
66
+ return encodeProtoField(tag, 0, encodeVarint(value));
67
+ }
68
+ export function concatBytes(parts) {
69
+ const total = parts.reduce((sum, part) => sum + part.length, 0);
70
+ const out = new Uint8Array(total);
71
+ let offset = 0;
72
+ for (const part of parts) {
73
+ out.set(part, offset);
74
+ offset += part.length;
75
+ }
76
+ return out;
77
+ }
78
+ export function toFetchBody(data) {
79
+ return data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
80
+ }
@@ -0,0 +1,6 @@
1
+ export interface CursorBaseRequestOptions {
2
+ accessToken: string;
3
+ url?: string;
4
+ }
5
+ export declare function buildCursorHeaders(options: CursorBaseRequestOptions, contentType: string, extra?: Record<string, string>): Headers;
6
+ export declare function buildCursorHeaderValues(options: CursorBaseRequestOptions, contentType: string, extra?: Record<string, string>): Record<string, string>;
@@ -0,0 +1,16 @@
1
+ import { CURSOR_CLIENT_VERSION } from "./config";
2
+ export function buildCursorHeaders(options, contentType, extra = {}) {
3
+ const headers = new Headers(buildCursorHeaderValues(options, contentType, extra));
4
+ return headers;
5
+ }
6
+ export function buildCursorHeaderValues(options, contentType, extra = {}) {
7
+ return {
8
+ authorization: `Bearer ${options.accessToken}`,
9
+ "content-type": contentType,
10
+ "x-ghost-mode": "true",
11
+ "x-cursor-client-version": CURSOR_CLIENT_VERSION,
12
+ "x-cursor-client-type": "cli",
13
+ "x-request-id": crypto.randomUUID(),
14
+ ...extra,
15
+ };
16
+ }
@@ -0,0 +1,5 @@
1
+ export { CURSOR_API_URL, CURSOR_CLIENT_VERSION, CURSOR_CONNECT_PROTOCOL_VERSION, CONNECT_END_STREAM_FLAG, } from "./config";
2
+ export { concatBytes, decodeConnectUnaryBody, encodeProtoMessageField, encodeProtoStringField, encodeProtoVarintField, encodeVarint, frameConnectMessage, toFetchBody, } from "./connect-framing";
3
+ export { buildCursorHeaders, buildCursorHeaderValues, type CursorBaseRequestOptions, } from "./headers";
4
+ export { createCursorSession, type CreateCursorSessionOptions, type CursorSession, } from "./bidi-session";
5
+ export { callCursorUnaryRpc, type CursorUnaryRpcOptions } from "./unary-rpc";
@@ -0,0 +1,5 @@
1
+ export { CURSOR_API_URL, CURSOR_CLIENT_VERSION, CURSOR_CONNECT_PROTOCOL_VERSION, CONNECT_END_STREAM_FLAG, } from "./config";
2
+ export { concatBytes, decodeConnectUnaryBody, encodeProtoMessageField, encodeProtoStringField, encodeProtoVarintField, encodeVarint, frameConnectMessage, toFetchBody, } from "./connect-framing";
3
+ export { buildCursorHeaders, buildCursorHeaderValues, } from "./headers";
4
+ export { createCursorSession, } from "./bidi-session";
5
+ export { callCursorUnaryRpc } from "./unary-rpc";
@@ -0,0 +1,12 @@
1
+ export interface CursorUnaryRpcOptions {
2
+ accessToken: string;
3
+ rpcPath: string;
4
+ requestBody: Uint8Array;
5
+ url?: string;
6
+ timeoutMs?: number;
7
+ }
8
+ export declare function callCursorUnaryRpc(options: CursorUnaryRpcOptions): Promise<{
9
+ body: Uint8Array;
10
+ exitCode: number;
11
+ timedOut: boolean;
12
+ }>;
@@ -0,0 +1,124 @@
1
+ import { connect as connectHttp2, } from "node:http2";
2
+ import { CURSOR_API_URL, CURSOR_CONNECT_PROTOCOL_VERSION } from "./config";
3
+ import { buildCursorHeaderValues } from "./headers";
4
+ import { errorDetails, logPluginError } from "../logger";
5
+ export async function callCursorUnaryRpc(options) {
6
+ const target = new URL(options.rpcPath, options.url ?? CURSOR_API_URL);
7
+ return callCursorUnaryRpcOverHttp2(options, target);
8
+ }
9
+ async function callCursorUnaryRpcOverHttp2(options, target) {
10
+ const timeoutMs = options.timeoutMs ?? 5_000;
11
+ const authority = `${target.protocol}//${target.host}`;
12
+ return new Promise((resolve) => {
13
+ let settled = false;
14
+ let timedOut = false;
15
+ let session;
16
+ let stream;
17
+ const finish = (result) => {
18
+ if (settled)
19
+ return;
20
+ settled = true;
21
+ if (timeout)
22
+ clearTimeout(timeout);
23
+ try {
24
+ stream?.close();
25
+ }
26
+ catch { }
27
+ try {
28
+ session?.close();
29
+ }
30
+ catch { }
31
+ resolve(result);
32
+ };
33
+ const timeout = timeoutMs > 0
34
+ ? setTimeout(() => {
35
+ timedOut = true;
36
+ finish({
37
+ body: new Uint8Array(),
38
+ exitCode: 124,
39
+ timedOut: true,
40
+ });
41
+ }, timeoutMs)
42
+ : undefined;
43
+ try {
44
+ session = connectHttp2(authority);
45
+ session.once("error", (error) => {
46
+ logPluginError("Cursor unary HTTP/2 session failed", {
47
+ rpcPath: options.rpcPath,
48
+ url: target.toString(),
49
+ timedOut,
50
+ ...errorDetails(error),
51
+ });
52
+ finish({
53
+ body: new Uint8Array(),
54
+ exitCode: timedOut ? 124 : 1,
55
+ timedOut,
56
+ });
57
+ });
58
+ const headers = {
59
+ ":method": "POST",
60
+ ":path": `${target.pathname}${target.search}`,
61
+ ...buildCursorHeaderValues(options, "application/proto", {
62
+ accept: "application/proto, application/json",
63
+ "connect-protocol-version": CURSOR_CONNECT_PROTOCOL_VERSION,
64
+ "connect-timeout-ms": String(timeoutMs),
65
+ }),
66
+ };
67
+ stream = session.request(headers);
68
+ let statusCode = 0;
69
+ const chunks = [];
70
+ stream.once("response", (responseHeaders) => {
71
+ const statusHeader = responseHeaders[":status"];
72
+ statusCode =
73
+ typeof statusHeader === "number"
74
+ ? statusHeader
75
+ : Number(statusHeader ?? 0);
76
+ });
77
+ stream.on("data", (chunk) => {
78
+ chunks.push(Buffer.from(chunk));
79
+ });
80
+ stream.once("end", () => {
81
+ const body = new Uint8Array(Buffer.concat(chunks));
82
+ finish({
83
+ body,
84
+ exitCode: statusCode >= 200 && statusCode < 300 ? 0 : statusCode || 1,
85
+ timedOut,
86
+ });
87
+ });
88
+ stream.once("error", (error) => {
89
+ logPluginError("Cursor unary HTTP/2 stream failed", {
90
+ rpcPath: options.rpcPath,
91
+ url: target.toString(),
92
+ timedOut,
93
+ ...errorDetails(error),
94
+ });
95
+ finish({
96
+ body: new Uint8Array(),
97
+ exitCode: timedOut ? 124 : 1,
98
+ timedOut,
99
+ });
100
+ });
101
+ // Bun's node:http2 client currently breaks on end(Buffer.alloc(0)) against
102
+ // Cursor's HTTPS endpoint, but a header-only end() succeeds for empty unary bodies.
103
+ if (options.requestBody.length > 0) {
104
+ stream.end(Buffer.from(options.requestBody));
105
+ }
106
+ else {
107
+ stream.end();
108
+ }
109
+ }
110
+ catch (error) {
111
+ logPluginError("Cursor unary HTTP/2 setup failed", {
112
+ rpcPath: options.rpcPath,
113
+ url: target.toString(),
114
+ timedOut,
115
+ ...errorDetails(error),
116
+ });
117
+ finish({
118
+ body: new Uint8Array(),
119
+ exitCode: timedOut ? 124 : 1,
120
+ timedOut,
121
+ });
122
+ }
123
+ });
124
+ }
package/dist/index.d.ts CHANGED
@@ -1,14 +1,2 @@
1
- /**
2
- * OpenCode Cursor Auth Plugin
3
- *
4
- * Enables using Cursor models (Claude, GPT, etc.) inside OpenCode via:
5
- * 1. Browser-based OAuth login to Cursor
6
- * 2. Local proxy translating OpenAI format → Cursor gRPC protocol
7
- */
8
- import type { Plugin } from "@opencode-ai/plugin";
9
- /**
10
- * OpenCode plugin that provides Cursor authentication and model access.
11
- * Register in opencode.json: { "plugin": ["opencode-cursor-oauth"] }
12
- */
13
- export declare const CursorAuthPlugin: Plugin;
14
- export default CursorAuthPlugin;
1
+ export { CursorAuthPlugin } from "./plugin/cursor-auth-plugin";
2
+ export { CursorAuthPlugin as default } from "./plugin/cursor-auth-plugin";