@route_33/opencode 0.1.2 → 0.1.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.
package/README.md CHANGED
@@ -14,7 +14,7 @@ Add to the `plugin` array of your opencode config and restart opencode:
14
14
 
15
15
  ## Auth
16
16
 
17
- Run `opencode auth login` and choose `route_33`, or set the `ROUTE33_API_KEY` environment variable. Without a key, the TUI wizard offers to save one: per-project inside a git workspace, global otherwise. `ROUTE33_BASE_URL` overrides the default gateway URL; `ROUTE33_TUI_PROMPT=0` disables the wizard.
17
+ Run `opencode auth login` and choose `route_33`, or set the `ROUTE33_API_KEY` environment variable. Without a key, the TUI wizard offers to save one: per-project inside a git workspace, global otherwise. A globally stored key applies only outside git workspaces — inside a workspace, keys resolve from the environment, the workspace config, or `.opencode/route33.key` (per-project keys are the metering boundary). `ROUTE33_BASE_URL` overrides the default gateway URL; `ROUTE33_TUI_PROMPT=0` disables the wizard.
18
18
 
19
19
  ## License
20
20
 
package/dist/index.js CHANGED
@@ -32,7 +32,7 @@ function readAuthEntry(env = process.env) {
32
32
 
33
33
  // src/auth/workspace-key-file.ts
34
34
  import * as fs2 from "fs";
35
- import * as path3 from "path";
35
+ import * as path4 from "path";
36
36
 
37
37
  // src/shared/default-base-url.ts
38
38
  var DEFAULT_BASE_URL = "https://api.route33.ai/v1";
@@ -64,6 +64,23 @@ var ENV_ENRICH_CAPS = "ROUTE33_ENRICH_CAPS";
64
64
  // src/shared/env-strict.ts
65
65
  var ENV_STRICT = "ROUTE33_STRICT";
66
66
 
67
+ // src/shared/git-workspace.ts
68
+ import { existsSync } from "fs";
69
+ import * as path2 from "path";
70
+ function isInsideGitWorktree(startDir) {
71
+ try {
72
+ let dir = path2.resolve(startDir);
73
+ for (; ; ) {
74
+ if (existsSync(path2.join(dir, ".git"))) return true;
75
+ const parent = path2.dirname(dir);
76
+ if (parent === dir) return false;
77
+ dir = parent;
78
+ }
79
+ } catch {
80
+ return false;
81
+ }
82
+ }
83
+
67
84
  // src/shared/logger.ts
68
85
  var logger = {
69
86
  info: (...args) => {
@@ -82,18 +99,18 @@ var MODELS_DEV_TTL_MS = 864e5;
82
99
 
83
100
  // src/shared/resolve-cache-dir.ts
84
101
  import * as os2 from "os";
85
- import * as path2 from "path";
102
+ import * as path3 from "path";
86
103
  function resolveCacheDir(env = process.env) {
87
104
  const override = env[ENV_CACHE_DIR];
88
105
  if (override) return override;
89
106
  const xdgCacheHome = env.XDG_CACHE_HOME;
90
- const base = xdgCacheHome ?? path2.join(os2.homedir(), ".cache");
91
- return path2.join(base, "opencode-route33");
107
+ const base = xdgCacheHome ?? path3.join(os2.homedir(), ".cache");
108
+ return path3.join(base, "opencode-route33");
92
109
  }
93
110
 
94
111
  // src/auth/workspace-key-file.ts
95
- var WORKSPACE_KEY_RELATIVE_PATH = path3.join(".opencode", "route33.key");
96
- var WORKSPACE_GITIGNORE_RELATIVE_PATH = path3.join(".opencode", ".gitignore");
112
+ var WORKSPACE_KEY_RELATIVE_PATH = path4.join(".opencode", "route33.key");
113
+ var WORKSPACE_GITIGNORE_RELATIVE_PATH = path4.join(".opencode", ".gitignore");
97
114
  var GITIGNORE_ENTRIES = ["route33.key", "tui.json"];
98
115
  function usable2(value) {
99
116
  if (typeof value !== "string") return void 0;
@@ -107,7 +124,7 @@ function readWorkspaceKey(worktree) {
107
124
  if (worktree === void 0) return void 0;
108
125
  try {
109
126
  const raw = fs2.readFileSync(
110
- path3.join(worktree, WORKSPACE_KEY_RELATIVE_PATH),
127
+ path4.join(worktree, WORKSPACE_KEY_RELATIVE_PATH),
111
128
  "utf8"
112
129
  );
113
130
  const parsed = JSON.parse(raw);
@@ -119,10 +136,10 @@ function readWorkspaceKey(worktree) {
119
136
  }
120
137
  function ensureWorkspaceKeyGitignore(worktree) {
121
138
  if (worktree === void 0 || worktree.trim() === "") return;
122
- if (path3.resolve(worktree) === "/") return;
123
- const gitignorePath = path3.join(worktree, WORKSPACE_GITIGNORE_RELATIVE_PATH);
139
+ if (path4.resolve(worktree) === "/") return;
140
+ const gitignorePath = path4.join(worktree, WORKSPACE_GITIGNORE_RELATIVE_PATH);
124
141
  try {
125
- fs2.mkdirSync(path3.dirname(gitignorePath), { recursive: true });
142
+ fs2.mkdirSync(path4.dirname(gitignorePath), { recursive: true });
126
143
  let content = "";
127
144
  try {
128
145
  content = fs2.readFileSync(gitignorePath, "utf8");
@@ -157,8 +174,8 @@ function urlFromConfig(cfg) {
157
174
  return literal;
158
175
  return void 0;
159
176
  }
160
- function resolveBaseUrl(cfg, env = process.env) {
161
- return usable3(env[ENV_BASE_URL]) ?? urlFromConfig(cfg) ?? readAuthEntry(env).baseURL ?? DEFAULT_BASE_URL;
177
+ function resolveBaseUrl(cfg, env = process.env, worktree) {
178
+ return usable3(env[ENV_BASE_URL]) ?? urlFromConfig(cfg) ?? (worktree !== void 0 && isInsideGitWorktree(worktree) ? void 0 : readAuthEntry(env).baseURL) ?? DEFAULT_BASE_URL;
162
179
  }
163
180
 
164
181
  // src/auth/api-key-method.ts
@@ -208,7 +225,7 @@ function keyFromConfig(cfg) {
208
225
  return void 0;
209
226
  }
210
227
  function resolveKey(cfg, env = process.env, worktree) {
211
- return usable4(env[ENV_API_KEY]) ?? keyFromConfig(cfg) ?? readWorkspaceKey(worktree) ?? readAuthEntry(env).key;
228
+ return usable4(env[ENV_API_KEY]) ?? keyFromConfig(cfg) ?? readWorkspaceKey(worktree) ?? (worktree !== void 0 && isInsideGitWorktree(worktree) ? void 0 : readAuthEntry(env).key);
212
229
  }
213
230
 
214
231
  // src/auth/route33-auth.ts
@@ -229,20 +246,20 @@ function buildRoute33Auth(env = process.env, worktree) {
229
246
  }
230
247
 
231
248
  // src/bootstrap/ensure-tui-registration.ts
232
- import * as path7 from "path";
249
+ import * as path8 from "path";
233
250
 
234
251
  // src/bootstrap/global-context.ts
235
252
  import * as os3 from "os";
236
- import * as path4 from "path";
253
+ import * as path5 from "path";
237
254
  import { fileURLToPath } from "url";
238
255
  function isGlobalContext(worktree, moduleUrl) {
239
256
  try {
240
257
  if (moduleUrl === void 0) return false;
241
258
  if (worktree === void 0) return true;
242
- const root = path4.resolve(worktree);
259
+ const root = path5.resolve(worktree);
243
260
  if (root === "/") return true;
244
261
  const modulePath = fileURLToPath(moduleUrl);
245
- return !modulePath.startsWith(root + path4.sep);
262
+ return !modulePath.startsWith(root + path5.sep);
246
263
  } catch {
247
264
  return false;
248
265
  }
@@ -252,13 +269,13 @@ function usable5(value) {
252
269
  return trimmed === void 0 || trimmed === "" ? void 0 : trimmed;
253
270
  }
254
271
  function globalTuiJsonPath(env) {
255
- const configHome = usable5(env.XDG_CONFIG_HOME) ?? path4.join(os3.homedir(), ".config");
256
- return path4.join(configHome, "opencode", "tui.json");
272
+ const configHome = usable5(env.XDG_CONFIG_HOME) ?? path5.join(os3.homedir(), ".config");
273
+ return path5.join(configHome, "opencode", "tui.json");
257
274
  }
258
275
 
259
276
  // src/bootstrap/tui-json-upsert.ts
260
277
  import * as fs4 from "fs";
261
- import * as path6 from "path";
278
+ import * as path7 from "path";
262
279
  import {
263
280
  applyEdits,
264
281
  modify,
@@ -268,15 +285,17 @@ import {
268
285
  // src/bootstrap/tui-spec-resolution.ts
269
286
  import * as fs3 from "fs";
270
287
  import * as os4 from "os";
271
- import * as path5 from "path";
288
+ import * as path6 from "path";
272
289
  import { fileURLToPath as fileURLToPath2 } from "url";
273
- var NPM_TUI_SPEC = "@route_33/opencode/tui";
290
+ var NPM_TUI_SPEC = "@route_33/opencode";
291
+ var DEAD_SUBPATH_TUI_SPEC = "@route_33/opencode/tui";
274
292
  var OLD_NPM_TUI_SPEC = "opencode-route33/tui";
275
293
  var TUI_BUNDLE_NAME = "route33-tui.js";
276
294
  var TUI_SCHEMA = "https://opencode.ai/tui.json";
277
295
  var SERVER_BUNDLE_NAME = "route33.js";
278
296
  var DIST_TUI_ENTRY_SUFFIX = "/opencode-route33/dist/tui/index.js";
279
297
  var SCOPED_DIST_TUI_ENTRY_SUFFIX = "/@route_33/opencode/dist/tui/index.js";
298
+ var NPM_PACKAGE_DIR = path6.join("node_modules", "@route_33", "opencode");
280
299
  function fileExists(candidate) {
281
300
  try {
282
301
  return fs3.statSync(candidate).isFile();
@@ -284,17 +303,30 @@ function fileExists(candidate) {
284
303
  return false;
285
304
  }
286
305
  }
306
+ function npmSpecFromModulePath(selfPath) {
307
+ const segments = selfPath.split(path6.sep);
308
+ for (let i = 0; i < segments.length - 1; i++) {
309
+ const pkgDir = segments[i + 1];
310
+ if (segments[i] === "@route_33" && pkgDir !== void 0 && pkgDir.startsWith("opencode@")) {
311
+ const pin = pkgDir.slice("opencode@".length);
312
+ if (pin !== "") return `${NPM_TUI_SPEC}@${pin}`;
313
+ }
314
+ }
315
+ return selfPath.includes(`${NPM_PACKAGE_DIR}${path6.sep}`) ? NPM_TUI_SPEC : void 0;
316
+ }
287
317
  function specFromModuleUrl(moduleUrl) {
288
318
  try {
289
319
  if (moduleUrl === void 0) return void 0;
290
320
  const selfPath = fileURLToPath2(moduleUrl);
291
- const dir = path5.dirname(selfPath);
292
- if (path5.basename(selfPath) === SERVER_BUNDLE_NAME) {
293
- const sibling = path5.join(dir, TUI_BUNDLE_NAME);
321
+ const dir = path6.dirname(selfPath);
322
+ if (path6.basename(selfPath) === SERVER_BUNDLE_NAME) {
323
+ const sibling = path6.join(dir, TUI_BUNDLE_NAME);
294
324
  return fileExists(sibling) ? sibling : void 0;
295
325
  }
296
- if (path5.basename(selfPath) === "index.js" && path5.basename(dir) === "dist") {
297
- const tuiEntry = path5.join(dir, "tui", "index.js");
326
+ if (path6.basename(selfPath) === "index.js" && path6.basename(dir) === "dist") {
327
+ const npmSpec = npmSpecFromModulePath(selfPath);
328
+ if (npmSpec !== void 0) return npmSpec;
329
+ const tuiEntry = path6.join(dir, "tui", "index.js");
298
330
  return fileExists(tuiEntry) ? tuiEntry : void 0;
299
331
  }
300
332
  return void 0;
@@ -305,17 +337,17 @@ function specFromModuleUrl(moduleUrl) {
305
337
  function resolveTuiSpec(worktree, env, moduleUrl) {
306
338
  const fromModule = specFromModuleUrl(moduleUrl);
307
339
  if (fromModule !== void 0) return fromModule;
308
- if (worktree !== void 0 && worktree.trim() !== "" && path5.resolve(worktree) !== "/") {
309
- const local = path5.join(worktree, ".opencode", "plugins", TUI_BUNDLE_NAME);
340
+ if (worktree !== void 0 && worktree.trim() !== "" && path6.resolve(worktree) !== "/") {
341
+ const local = path6.join(worktree, ".opencode", "plugins", TUI_BUNDLE_NAME);
310
342
  if (fileExists(local)) return local;
311
343
  }
312
- const configHome = env.XDG_CONFIG_HOME?.trim() || path5.join(os4.homedir(), ".config");
313
- const global = path5.join(configHome, "opencode", "plugins", TUI_BUNDLE_NAME);
344
+ const configHome = env.XDG_CONFIG_HOME?.trim() || path6.join(os4.homedir(), ".config");
345
+ const global = path6.join(configHome, "opencode", "plugins", TUI_BUNDLE_NAME);
314
346
  if (fileExists(global)) return global;
315
347
  return NPM_TUI_SPEC;
316
348
  }
317
349
  function isOurEntry(entry) {
318
- return typeof entry === "string" && (entry === NPM_TUI_SPEC || entry === OLD_NPM_TUI_SPEC || entry.endsWith(`/${TUI_BUNDLE_NAME}`) || entry.endsWith(DIST_TUI_ENTRY_SUFFIX) || entry.endsWith(SCOPED_DIST_TUI_ENTRY_SUFFIX));
350
+ return typeof entry === "string" && (entry === NPM_TUI_SPEC || entry.startsWith(`${NPM_TUI_SPEC}@`) || entry === DEAD_SUBPATH_TUI_SPEC || entry === OLD_NPM_TUI_SPEC || entry.endsWith(`/${TUI_BUNDLE_NAME}`) || entry.endsWith(DIST_TUI_ENTRY_SUFFIX) || entry.endsWith(SCOPED_DIST_TUI_ENTRY_SUFFIX));
319
351
  }
320
352
 
321
353
  // src/bootstrap/tui-json-upsert.ts
@@ -332,7 +364,7 @@ function fileExists2(candidate) {
332
364
  function upsertTuiSpec(file, spec) {
333
365
  try {
334
366
  if (!fileExists2(file)) {
335
- fs4.mkdirSync(path6.dirname(file), { recursive: true });
367
+ fs4.mkdirSync(path7.dirname(file), { recursive: true });
336
368
  fs4.writeFileSync(
337
369
  file,
338
370
  JSON.stringify({ $schema: TUI_SCHEMA, plugin: [spec] }, null, 2) + "\n",
@@ -407,10 +439,10 @@ function ensureTuiRegistration(deps) {
407
439
  try {
408
440
  const { worktree, env } = deps;
409
441
  if (env.ROUTE33_TUI_PROMPT === "0") return;
410
- const usableWorktree = worktree !== void 0 && worktree.trim() !== "" && path7.resolve(worktree) !== "/" ? worktree : void 0;
442
+ const usableWorktree = worktree !== void 0 && worktree.trim() !== "" && path8.resolve(worktree) !== "/" ? worktree : void 0;
411
443
  const spec = resolveTuiSpec(usableWorktree, env, deps.moduleUrl);
412
444
  if (usableWorktree !== void 0) {
413
- upsertTuiSpec(path7.join(usableWorktree, ".opencode", "tui.json"), spec);
445
+ upsertTuiSpec(path8.join(usableWorktree, ".opencode", "tui.json"), spec);
414
446
  }
415
447
  if (isGlobalContext(worktree, deps.moduleUrl)) {
416
448
  upsertTuiSpec(globalTuiJsonPath(env), spec);
@@ -566,9 +598,9 @@ function hashKey(key) {
566
598
  import * as fs5 from "fs";
567
599
 
568
600
  // src/catalog/catalog-cache/cache-file-path.ts
569
- import * as path8 from "path";
601
+ import * as path9 from "path";
570
602
  function cacheFilePath(keyHash, env) {
571
- return path8.join(resolveCacheDir(env), `catalog-${keyHash}.json`);
603
+ return path9.join(resolveCacheDir(env), `catalog-${keyHash}.json`);
572
604
  }
573
605
 
574
606
  // src/catalog/catalog-cache/read-disk.ts
@@ -1172,7 +1204,7 @@ function enrichModel(slug2, sources) {
1172
1204
 
1173
1205
  // src/enrich/models-dev/load-models-dev.ts
1174
1206
  import * as fs7 from "fs";
1175
- import * as path9 from "path";
1207
+ import * as path10 from "path";
1176
1208
 
1177
1209
  // src/enrich/models-dev/is-record.ts
1178
1210
  function isRecord7(value) {
@@ -1273,10 +1305,10 @@ function swapLast(value, from, to) {
1273
1305
  return index === -1 ? value : `${value.slice(0, index)}${to}${value.slice(index + 1)}`;
1274
1306
  }
1275
1307
  function probeCandidates(slug2) {
1276
- const sep2 = slug2.indexOf("/");
1277
- if (sep2 <= 0 || sep2 >= slug2.length - 1) return [];
1278
- const vendor = slug2.slice(0, sep2);
1279
- const model = slug2.slice(sep2 + 1);
1308
+ const sep3 = slug2.indexOf("/");
1309
+ if (sep3 <= 0 || sep3 >= slug2.length - 1) return [];
1310
+ const vendor = slug2.slice(0, sep3);
1311
+ const model = slug2.slice(sep3 + 1);
1280
1312
  const vendors = [vendor];
1281
1313
  const alias = VENDOR_ALIASES[vendor];
1282
1314
  if (alias !== void 0 && alias !== vendor) vendors.push(alias);
@@ -1352,7 +1384,7 @@ function readCache(cachePath) {
1352
1384
  }
1353
1385
  function writeCache(cachePath, envelope) {
1354
1386
  try {
1355
- fs7.mkdirSync(path9.dirname(cachePath), { recursive: true });
1387
+ fs7.mkdirSync(path10.dirname(cachePath), { recursive: true });
1356
1388
  fs7.writeFileSync(cachePath, JSON.stringify(envelope), "utf8");
1357
1389
  } catch (error) {
1358
1390
  logger.warn("failed to write models.dev cache:", error);
@@ -1366,7 +1398,7 @@ async function loadModelsDev(options = {}) {
1366
1398
  const cacheDir = options.cacheDir ?? resolveCacheDir();
1367
1399
  const ttlMs = options.ttlMs ?? MODELS_DEV_TTL_MS;
1368
1400
  const now = options.now ?? Date.now;
1369
- const cachePath = path9.join(cacheDir, CACHE_FILE);
1401
+ const cachePath = path10.join(cacheDir, CACHE_FILE);
1370
1402
  const cached = readCache(cachePath);
1371
1403
  if (cached && now() - cached.fetchedAt < ttlMs)
1372
1404
  return makeSource("cache", cached.data);
@@ -1516,10 +1548,10 @@ function mergeConfig(cfg, blocks) {
1516
1548
 
1517
1549
  // src/config/collected-ref.ts
1518
1550
  function parseRef(ref, source) {
1519
- const sep2 = ref.indexOf("/");
1520
- if (sep2 <= 0 || sep2 >= ref.length - 1) return void 0;
1521
- const providerId = ref.slice(0, sep2);
1522
- const suffix = ref.slice(sep2 + 1);
1551
+ const sep3 = ref.indexOf("/");
1552
+ if (sep3 <= 0 || sep3 >= ref.length - 1) return void 0;
1553
+ const providerId = ref.slice(0, sep3);
1554
+ const suffix = ref.slice(sep3 + 1);
1523
1555
  if (providerId === "route_33")
1524
1556
  return { providerId, modelKey: suffix, ref, source };
1525
1557
  if (providerId !== "route_33_anthropic") return void 0;
@@ -1551,7 +1583,7 @@ function collectCfgRefs(cfg) {
1551
1583
  // src/config/collect-flavour-refs.ts
1552
1584
  import * as fs8 from "fs";
1553
1585
  import * as os5 from "os";
1554
- import * as path10 from "path";
1586
+ import * as path11 from "path";
1555
1587
  import { parse as parseJsonc2 } from "jsonc-parser";
1556
1588
  function isRecord8(value) {
1557
1589
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -1559,10 +1591,10 @@ function isRecord8(value) {
1559
1591
  function findFlavourPath(env, cwd) {
1560
1592
  const candidates = [];
1561
1593
  const configDir = env.OPENCODE_CONFIG_DIR?.trim();
1562
- if (configDir) candidates.push(path10.join(configDir, "oh-my-openagent.jsonc"));
1563
- candidates.push(path10.join(cwd, ".opencode", "oh-my-openagent.jsonc"));
1564
- const configHome = env.XDG_CONFIG_HOME?.trim() || path10.join(os5.homedir(), ".config");
1565
- candidates.push(path10.join(configHome, "opencode", "oh-my-openagent.jsonc"));
1594
+ if (configDir) candidates.push(path11.join(configDir, "oh-my-openagent.jsonc"));
1595
+ candidates.push(path11.join(cwd, ".opencode", "oh-my-openagent.jsonc"));
1596
+ const configHome = env.XDG_CONFIG_HOME?.trim() || path11.join(os5.homedir(), ".config");
1597
+ candidates.push(path11.join(configHome, "opencode", "oh-my-openagent.jsonc"));
1566
1598
  for (const candidate of candidates) {
1567
1599
  try {
1568
1600
  if (fs8.existsSync(candidate)) return candidate;
@@ -1725,7 +1757,7 @@ function createConfigHook(options = {}) {
1725
1757
  let key;
1726
1758
  try {
1727
1759
  key = resolveKey(cfg, env, cwd);
1728
- const baseURL = resolveBaseUrl(cfg, env);
1760
+ const baseURL = resolveBaseUrl(cfg, env, cwd);
1729
1761
  const catalog = await getCatalog({
1730
1762
  key,
1731
1763
  baseURL,
package/dist/tui/index.js CHANGED
@@ -1,6 +1,23 @@
1
1
  // src/shared/env-api-key.ts
2
2
  var ENV_API_KEY = "ROUTE33_API_KEY";
3
3
 
4
+ // src/shared/git-workspace.ts
5
+ import { existsSync } from "fs";
6
+ import * as path from "path";
7
+ function isInsideGitWorktree(startDir) {
8
+ try {
9
+ let dir = path.resolve(startDir);
10
+ for (; ; ) {
11
+ if (existsSync(path.join(dir, ".git"))) return true;
12
+ const parent = path.dirname(dir);
13
+ if (parent === dir) return false;
14
+ dir = parent;
15
+ }
16
+ } catch {
17
+ return false;
18
+ }
19
+ }
20
+
4
21
  // src/shared/logger.ts
5
22
  var logger = {
6
23
  info: (...args) => {
@@ -16,12 +33,12 @@ var logger = {
16
33
 
17
34
  // src/shared/resolve-cache-dir.ts
18
35
  import * as os from "os";
19
- import * as path from "path";
36
+ import * as path2 from "path";
20
37
 
21
38
  // src/auth/auth-json.ts
22
39
  import * as fs from "fs";
23
40
  import * as os2 from "os";
24
- import * as path2 from "path";
41
+ import * as path3 from "path";
25
42
  var PROVIDER_ID = "route_33";
26
43
  function usable(value) {
27
44
  if (typeof value !== "string") return void 0;
@@ -33,8 +50,8 @@ function isRecord(value) {
33
50
  }
34
51
  function readAuthEntry(env = process.env) {
35
52
  try {
36
- const dataHome = usable(env.XDG_DATA_HOME) ?? path2.join(os2.homedir(), ".local", "share");
37
- const authPath = path2.join(dataHome, "opencode", "auth.json");
53
+ const dataHome = usable(env.XDG_DATA_HOME) ?? path3.join(os2.homedir(), ".local", "share");
54
+ const authPath = path3.join(dataHome, "opencode", "auth.json");
38
55
  const parsed = JSON.parse(fs.readFileSync(authPath, "utf8"));
39
56
  if (!isRecord(parsed)) return {};
40
57
  const entry = parsed[PROVIDER_ID];
@@ -52,9 +69,9 @@ function readAuthEntry(env = process.env) {
52
69
 
53
70
  // src/auth/workspace-key-file.ts
54
71
  import * as fs2 from "fs";
55
- import * as path3 from "path";
56
- var WORKSPACE_KEY_RELATIVE_PATH = path3.join(".opencode", "route33.key");
57
- var WORKSPACE_GITIGNORE_RELATIVE_PATH = path3.join(".opencode", ".gitignore");
72
+ import * as path4 from "path";
73
+ var WORKSPACE_KEY_RELATIVE_PATH = path4.join(".opencode", "route33.key");
74
+ var WORKSPACE_GITIGNORE_RELATIVE_PATH = path4.join(".opencode", ".gitignore");
58
75
  var GITIGNORE_ENTRIES = ["route33.key", "tui.json"];
59
76
  function usable2(value) {
60
77
  if (typeof value !== "string") return void 0;
@@ -68,7 +85,7 @@ function readWorkspaceKey(worktree) {
68
85
  if (worktree === void 0) return void 0;
69
86
  try {
70
87
  const raw = fs2.readFileSync(
71
- path3.join(worktree, WORKSPACE_KEY_RELATIVE_PATH),
88
+ path4.join(worktree, WORKSPACE_KEY_RELATIVE_PATH),
72
89
  "utf8"
73
90
  );
74
91
  const parsed = JSON.parse(raw);
@@ -80,10 +97,10 @@ function readWorkspaceKey(worktree) {
80
97
  }
81
98
  function ensureWorkspaceKeyGitignore(worktree) {
82
99
  if (worktree === void 0 || worktree.trim() === "") return;
83
- if (path3.resolve(worktree) === "/") return;
84
- const gitignorePath = path3.join(worktree, WORKSPACE_GITIGNORE_RELATIVE_PATH);
100
+ if (path4.resolve(worktree) === "/") return;
101
+ const gitignorePath = path4.join(worktree, WORKSPACE_GITIGNORE_RELATIVE_PATH);
85
102
  try {
86
- fs2.mkdirSync(path3.dirname(gitignorePath), { recursive: true });
103
+ fs2.mkdirSync(path4.dirname(gitignorePath), { recursive: true });
87
104
  let content = "";
88
105
  try {
89
106
  content = fs2.readFileSync(gitignorePath, "utf8");
@@ -107,8 +124,8 @@ function ensureWorkspaceKeyGitignore(worktree) {
107
124
  }
108
125
  function writeWorkspaceKey(worktree, key) {
109
126
  ensureWorkspaceKeyGitignore(worktree);
110
- const filePath = path3.join(worktree, WORKSPACE_KEY_RELATIVE_PATH);
111
- fs2.mkdirSync(path3.dirname(filePath), { recursive: true });
127
+ const filePath = path4.join(worktree, WORKSPACE_KEY_RELATIVE_PATH);
128
+ fs2.mkdirSync(path4.dirname(filePath), { recursive: true });
112
129
  fs2.writeFileSync(
113
130
  filePath,
114
131
  `${JSON.stringify({ type: "api", key }, null, 2)}
@@ -130,7 +147,7 @@ function keyFromConfig(cfg) {
130
147
  return void 0;
131
148
  }
132
149
  function resolveKey(cfg, env = process.env, worktree) {
133
- return usable3(env[ENV_API_KEY]) ?? keyFromConfig(cfg) ?? readWorkspaceKey(worktree) ?? readAuthEntry(env).key;
150
+ return usable3(env[ENV_API_KEY]) ?? keyFromConfig(cfg) ?? readWorkspaceKey(worktree) ?? (worktree !== void 0 && isInsideGitWorktree(worktree) ? void 0 : readAuthEntry(env).key);
134
151
  }
135
152
 
136
153
  // src/tui/key-prompt-ui.ts
@@ -274,23 +291,6 @@ function createDismissalStore(kv, key = PROJECT_KEY_PROMPT_DISMISSED_AT_KEY) {
274
291
  };
275
292
  }
276
293
 
277
- // src/tui/git-workspace.ts
278
- import { existsSync } from "fs";
279
- import * as path4 from "path";
280
- function isInsideGitWorktree(startDir) {
281
- try {
282
- let dir = path4.resolve(startDir);
283
- for (; ; ) {
284
- if (existsSync(path4.join(dir, ".git"))) return true;
285
- const parent = path4.dirname(dir);
286
- if (parent === dir) return false;
287
- dir = parent;
288
- }
289
- } catch {
290
- return false;
291
- }
292
- }
293
-
294
294
  // src/tui/key-prompt-copy.ts
295
295
  var PROJECT_COPY = {
296
296
  selectTitle: KEY_SELECT_TITLE,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@route_33/opencode",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "type": "module",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "description": "opencode provider plugin for the route33.ai AI gateway — key-scoped model discovery, cost/limit enrichment, auth, and the key-setup wizard.",