@rama_nigg/open-cursor 2.3.1 → 2.3.3

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.
@@ -37,6 +37,7 @@ type CheckResult = {
37
37
  };
38
38
 
39
39
  type StatusResult = {
40
+ installMethod: "symlink" | "npm-direct" | "none";
40
41
  plugin: {
41
42
  path: string;
42
43
  type: "symlink" | "file" | "missing";
@@ -110,9 +111,23 @@ function checkOpenCode(): CheckResult {
110
111
  }
111
112
  }
112
113
 
113
- function checkPluginFile(pluginPath: string): CheckResult {
114
+ function isNpmDirectInstalled(config: unknown): boolean {
115
+ if (!config || typeof config !== "object") return false;
116
+ const plugins = (config as Record<string, unknown>).plugin;
117
+ if (!Array.isArray(plugins)) return false;
118
+ return plugins.some((p) => typeof p === "string" && p.startsWith(NPM_PACKAGE_PREFIX));
119
+ }
120
+
121
+ function checkPluginFile(pluginPath: string, config: unknown): CheckResult {
114
122
  try {
115
123
  if (!existsSync(pluginPath)) {
124
+ if (isNpmDirectInstalled(config)) {
125
+ return {
126
+ name: "Plugin file",
127
+ passed: true,
128
+ message: "Installed via npm package (no symlink needed)",
129
+ };
130
+ }
116
131
  return {
117
132
  name: "Plugin file",
118
133
  passed: false,
@@ -185,12 +200,18 @@ function checkAiSdk(opencodeDir: string): CheckResult {
185
200
 
186
201
  export function runDoctorChecks(configPath: string, pluginPath: string): CheckResult[] {
187
202
  const opencodeDir = dirname(configPath);
203
+ let config: unknown;
204
+ try {
205
+ config = readConfig(configPath);
206
+ } catch {
207
+ config = undefined;
208
+ }
188
209
  return [
189
210
  checkBun(),
190
211
  checkCursorAgent(),
191
212
  checkCursorAgentLogin(),
192
213
  checkOpenCode(),
193
- checkPluginFile(pluginPath),
214
+ checkPluginFile(pluginPath, config),
194
215
  checkProviderConfig(configPath),
195
216
  checkAiSdk(opencodeDir),
196
217
  ];
@@ -209,6 +230,7 @@ type Options = {
209
230
  };
210
231
 
211
232
  const PROVIDER_ID = "cursor-acp";
233
+ const NPM_PACKAGE_PREFIX = "@rama_nigg/open-cursor";
212
234
  const DEFAULT_BASE_URL = "http://127.0.0.1:32124/v1";
213
235
 
214
236
  function printHelp() {
@@ -443,6 +465,8 @@ function commandSyncModels(options: Options) {
443
465
  console.log(`Config path: ${configPath}`);
444
466
  }
445
467
 
468
+ const NPM_PACKAGE = "@rama_nigg/open-cursor";
469
+
446
470
  function commandUninstall(options: Options) {
447
471
  const { configPath, pluginPath } = resolvePaths(options);
448
472
  rmSync(pluginPath, { force: true });
@@ -450,7 +474,12 @@ function commandUninstall(options: Options) {
450
474
  if (existsSync(configPath)) {
451
475
  const config = readConfig(configPath);
452
476
  if (Array.isArray(config.plugin)) {
453
- config.plugin = config.plugin.filter((name: string) => name !== PROVIDER_ID);
477
+ // Remove both cursor-acp (symlink) and @rama_nigg/open-cursor (npm-direct) entries
478
+ config.plugin = config.plugin.filter((name: string) => {
479
+ if (name === PROVIDER_ID) return false;
480
+ if (typeof name === "string" && name.startsWith(NPM_PACKAGE)) return false;
481
+ return true;
482
+ });
454
483
  }
455
484
  if (config.provider && typeof config.provider === "object") {
456
485
  delete config.provider[PROVIDER_ID];
@@ -487,17 +516,20 @@ export function getStatusResult(configPath: string, pluginPath: string): StatusR
487
516
  }
488
517
 
489
518
  // Provider
519
+ let config: any;
490
520
  let providerEnabled = false;
491
521
  let baseUrl = "http://127.0.0.1:32124/v1";
492
522
  let modelCount = 0;
493
523
  if (existsSync(configPath)) {
494
- const config = readConfig(configPath);
524
+ config = readConfig(configPath);
495
525
  const provider = config.provider?.["cursor-acp"];
496
526
  providerEnabled = !!provider;
497
527
  if (provider?.options?.baseURL) {
498
528
  baseUrl = provider.options.baseURL;
499
529
  }
500
530
  modelCount = Object.keys(provider?.models || {}).length;
531
+ } else {
532
+ config = undefined;
501
533
  }
502
534
 
503
535
  // AI SDK
@@ -505,7 +537,15 @@ export function getStatusResult(configPath: string, pluginPath: string): StatusR
505
537
  const sdkPath = join(opencodeDir, "node_modules", "@ai-sdk", "openai-compatible");
506
538
  const aiSdkInstalled = existsSync(sdkPath);
507
539
 
540
+ let installMethod: "symlink" | "npm-direct" | "none" = "none";
541
+ if (pluginType !== "missing") {
542
+ installMethod = "symlink";
543
+ } else if (isNpmDirectInstalled(config)) {
544
+ installMethod = "npm-direct";
545
+ }
546
+
508
547
  return {
548
+ installMethod,
509
549
  plugin: {
510
550
  path: pluginPath,
511
551
  type: pluginType,
@@ -543,6 +583,7 @@ function commandStatus(options: Options) {
543
583
  } else {
544
584
  console.log(` Type: missing`);
545
585
  }
586
+ console.log(` Install method: ${result.installMethod}`);
546
587
 
547
588
  console.log("");
548
589
  console.log("Provider");
@@ -3,6 +3,14 @@ import { homedir } from "os";
3
3
  import { join, resolve } from "path";
4
4
 
5
5
  const CURSOR_PROVIDER_ID = "cursor-acp";
6
+ const NPM_PACKAGE_NAME = "@rama_nigg/open-cursor";
7
+
8
+ function matchesPlugin(entry: string): boolean {
9
+ if (entry === CURSOR_PROVIDER_ID) return true;
10
+ if (entry === NPM_PACKAGE_NAME) return true;
11
+ if (entry.startsWith(`${NPM_PACKAGE_NAME}@`)) return true;
12
+ return false;
13
+ }
6
14
 
7
15
  type EnvLike = Record<string, string | undefined>;
8
16
 
@@ -26,7 +34,7 @@ export function isCursorPluginEnabledInConfig(config: unknown): boolean {
26
34
  const configObject = config as { plugin?: unknown; provider?: unknown };
27
35
 
28
36
  if (Array.isArray(configObject.plugin)) {
29
- return configObject.plugin.some((entry) => entry === CURSOR_PROVIDER_ID);
37
+ return configObject.plugin.some((entry) => matchesPlugin(entry));
30
38
  }
31
39
 
32
40
  return true;