oh-my-opencode 0.1.17 → 0.1.19

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/dist/index.js CHANGED
@@ -803,7 +803,7 @@ function detectErrorType(error) {
803
803
  if (message.includes("tool_use") && message.includes("tool_result")) {
804
804
  return "tool_result_missing";
805
805
  }
806
- if (message.includes("thinking") && message.includes("first block")) {
806
+ if (message.includes("thinking") && (message.includes("first block") || message.includes("must start with") || message.includes("preceeding"))) {
807
807
  return "thinking_block_order";
808
808
  }
809
809
  if (message.includes("thinking is disabled") && message.includes("cannot contain")) {
@@ -15258,9 +15258,120 @@ var lsp_code_action_resolve = tool({
15258
15258
  }
15259
15259
  });
15260
15260
  // src/tools/ast-grep/constants.ts
15261
+ import { createRequire as createRequire4 } from "module";
15262
+ import { dirname as dirname2, join as join5 } from "path";
15263
+ import { existsSync as existsSync7 } from "fs";
15264
+
15265
+ // src/tools/ast-grep/downloader.ts
15266
+ var {spawn: spawn4 } = globalThis.Bun;
15267
+ import { existsSync as existsSync6, mkdirSync as mkdirSync2, chmodSync as chmodSync2, unlinkSync as unlinkSync2 } from "fs";
15268
+ import { join as join4 } from "path";
15269
+ import { homedir as homedir3 } from "os";
15261
15270
  import { createRequire as createRequire3 } from "module";
15262
- import { dirname as dirname2, join as join4 } from "path";
15263
- import { existsSync as existsSync6 } from "fs";
15271
+ var REPO2 = "ast-grep/ast-grep";
15272
+ var DEFAULT_VERSION = "0.40.0";
15273
+ function getAstGrepVersion() {
15274
+ try {
15275
+ const require2 = createRequire3(import.meta.url);
15276
+ const pkg = require2("@ast-grep/cli/package.json");
15277
+ return pkg.version;
15278
+ } catch {
15279
+ return DEFAULT_VERSION;
15280
+ }
15281
+ }
15282
+ var PLATFORM_MAP2 = {
15283
+ "darwin-arm64": { arch: "aarch64", os: "apple-darwin" },
15284
+ "darwin-x64": { arch: "x86_64", os: "apple-darwin" },
15285
+ "linux-arm64": { arch: "aarch64", os: "unknown-linux-gnu" },
15286
+ "linux-x64": { arch: "x86_64", os: "unknown-linux-gnu" },
15287
+ "win32-x64": { arch: "x86_64", os: "pc-windows-msvc" },
15288
+ "win32-arm64": { arch: "aarch64", os: "pc-windows-msvc" },
15289
+ "win32-ia32": { arch: "i686", os: "pc-windows-msvc" }
15290
+ };
15291
+ function getCacheDir2() {
15292
+ if (process.platform === "win32") {
15293
+ const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
15294
+ const base2 = localAppData || join4(homedir3(), "AppData", "Local");
15295
+ return join4(base2, "oh-my-opencode", "bin");
15296
+ }
15297
+ const xdgCache = process.env.XDG_CACHE_HOME;
15298
+ const base = xdgCache || join4(homedir3(), ".cache");
15299
+ return join4(base, "oh-my-opencode", "bin");
15300
+ }
15301
+ function getBinaryName3() {
15302
+ return process.platform === "win32" ? "sg.exe" : "sg";
15303
+ }
15304
+ function getCachedBinaryPath2() {
15305
+ const binaryPath = join4(getCacheDir2(), getBinaryName3());
15306
+ return existsSync6(binaryPath) ? binaryPath : null;
15307
+ }
15308
+ async function extractZip2(archivePath, destDir) {
15309
+ const proc = process.platform === "win32" ? spawn4([
15310
+ "powershell",
15311
+ "-command",
15312
+ `Expand-Archive -Path '${archivePath}' -DestinationPath '${destDir}' -Force`
15313
+ ], { stdout: "pipe", stderr: "pipe" }) : spawn4(["unzip", "-o", archivePath, "-d", destDir], { stdout: "pipe", stderr: "pipe" });
15314
+ const exitCode = await proc.exited;
15315
+ if (exitCode !== 0) {
15316
+ const stderr = await new Response(proc.stderr).text();
15317
+ const toolHint = process.platform === "win32" ? "Ensure PowerShell is available on your system." : "Please install 'unzip' (e.g., apt install unzip, brew install unzip).";
15318
+ throw new Error(`zip extraction failed (exit ${exitCode}): ${stderr}
15319
+
15320
+ ${toolHint}`);
15321
+ }
15322
+ }
15323
+ async function downloadAstGrep(version2 = DEFAULT_VERSION) {
15324
+ const platformKey = `${process.platform}-${process.arch}`;
15325
+ const platformInfo = PLATFORM_MAP2[platformKey];
15326
+ if (!platformInfo) {
15327
+ console.error(`[oh-my-opencode] Unsupported platform for ast-grep: ${platformKey}`);
15328
+ return null;
15329
+ }
15330
+ const cacheDir = getCacheDir2();
15331
+ const binaryName = getBinaryName3();
15332
+ const binaryPath = join4(cacheDir, binaryName);
15333
+ if (existsSync6(binaryPath)) {
15334
+ return binaryPath;
15335
+ }
15336
+ const { arch, os } = platformInfo;
15337
+ const assetName = `app-${arch}-${os}.zip`;
15338
+ const downloadUrl = `https://github.com/${REPO2}/releases/download/${version2}/${assetName}`;
15339
+ console.log(`[oh-my-opencode] Downloading ast-grep binary...`);
15340
+ try {
15341
+ if (!existsSync6(cacheDir)) {
15342
+ mkdirSync2(cacheDir, { recursive: true });
15343
+ }
15344
+ const response = await fetch(downloadUrl, { redirect: "follow" });
15345
+ if (!response.ok) {
15346
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
15347
+ }
15348
+ const archivePath = join4(cacheDir, assetName);
15349
+ const arrayBuffer = await response.arrayBuffer();
15350
+ await Bun.write(archivePath, arrayBuffer);
15351
+ await extractZip2(archivePath, cacheDir);
15352
+ if (existsSync6(archivePath)) {
15353
+ unlinkSync2(archivePath);
15354
+ }
15355
+ if (process.platform !== "win32" && existsSync6(binaryPath)) {
15356
+ chmodSync2(binaryPath, 493);
15357
+ }
15358
+ console.log(`[oh-my-opencode] ast-grep binary ready.`);
15359
+ return binaryPath;
15360
+ } catch (err) {
15361
+ console.error(`[oh-my-opencode] Failed to download ast-grep: ${err instanceof Error ? err.message : err}`);
15362
+ return null;
15363
+ }
15364
+ }
15365
+ async function ensureAstGrepBinary() {
15366
+ const cachedPath = getCachedBinaryPath2();
15367
+ if (cachedPath) {
15368
+ return cachedPath;
15369
+ }
15370
+ const version2 = getAstGrepVersion();
15371
+ return downloadAstGrep(version2);
15372
+ }
15373
+
15374
+ // src/tools/ast-grep/constants.ts
15264
15375
  function getPlatformPackageName2() {
15265
15376
  const platform = process.platform;
15266
15377
  const arch = process.arch;
@@ -15275,32 +15386,60 @@ function getPlatformPackageName2() {
15275
15386
  };
15276
15387
  return platformMap[`${platform}-${arch}`] ?? null;
15277
15388
  }
15278
- function findSgCliPath() {
15389
+ function findSgCliPathSync() {
15390
+ const binaryName = process.platform === "win32" ? "sg.exe" : "sg";
15279
15391
  try {
15280
- const require2 = createRequire3(import.meta.url);
15392
+ const require2 = createRequire4(import.meta.url);
15281
15393
  const cliPkgPath = require2.resolve("@ast-grep/cli/package.json");
15282
15394
  const cliDir = dirname2(cliPkgPath);
15283
- const sgPath = join4(cliDir, process.platform === "win32" ? "sg.exe" : "sg");
15284
- if (existsSync6(sgPath)) {
15395
+ const sgPath = join5(cliDir, binaryName);
15396
+ if (existsSync7(sgPath)) {
15285
15397
  return sgPath;
15286
15398
  }
15287
15399
  } catch {}
15288
15400
  const platformPkg = getPlatformPackageName2();
15289
15401
  if (platformPkg) {
15290
15402
  try {
15291
- const require2 = createRequire3(import.meta.url);
15403
+ const require2 = createRequire4(import.meta.url);
15292
15404
  const pkgPath = require2.resolve(`${platformPkg}/package.json`);
15293
15405
  const pkgDir = dirname2(pkgPath);
15294
- const binaryName = process.platform === "win32" ? "ast-grep.exe" : "ast-grep";
15295
- const binaryPath = join4(pkgDir, binaryName);
15296
- if (existsSync6(binaryPath)) {
15406
+ const astGrepName = process.platform === "win32" ? "ast-grep.exe" : "ast-grep";
15407
+ const binaryPath = join5(pkgDir, astGrepName);
15408
+ if (existsSync7(binaryPath)) {
15297
15409
  return binaryPath;
15298
15410
  }
15299
15411
  } catch {}
15300
15412
  }
15413
+ if (process.platform === "darwin") {
15414
+ const homebrewPaths = ["/opt/homebrew/bin/sg", "/usr/local/bin/sg"];
15415
+ for (const path of homebrewPaths) {
15416
+ if (existsSync7(path)) {
15417
+ return path;
15418
+ }
15419
+ }
15420
+ }
15421
+ const cachedPath = getCachedBinaryPath2();
15422
+ if (cachedPath) {
15423
+ return cachedPath;
15424
+ }
15425
+ return null;
15426
+ }
15427
+ var resolvedCliPath2 = null;
15428
+ function getSgCliPath() {
15429
+ if (resolvedCliPath2 !== null) {
15430
+ return resolvedCliPath2;
15431
+ }
15432
+ const syncPath = findSgCliPathSync();
15433
+ if (syncPath) {
15434
+ resolvedCliPath2 = syncPath;
15435
+ return syncPath;
15436
+ }
15301
15437
  return "sg";
15302
15438
  }
15303
- var SG_CLI_PATH = findSgCliPath();
15439
+ function setSgCliPath(path) {
15440
+ resolvedCliPath2 = path;
15441
+ }
15442
+ var SG_CLI_PATH = getSgCliPath();
15304
15443
  var CLI_LANGUAGES = [
15305
15444
  "bash",
15306
15445
  "c",
@@ -15358,7 +15497,44 @@ var LANG_EXTENSIONS = {
15358
15497
  };
15359
15498
 
15360
15499
  // src/tools/ast-grep/cli.ts
15361
- var {spawn: spawn4 } = globalThis.Bun;
15500
+ var {spawn: spawn5 } = globalThis.Bun;
15501
+ import { existsSync as existsSync8 } from "fs";
15502
+ var resolvedCliPath3 = null;
15503
+ var initPromise2 = null;
15504
+ async function getAstGrepPath() {
15505
+ if (resolvedCliPath3 !== null && existsSync8(resolvedCliPath3)) {
15506
+ return resolvedCliPath3;
15507
+ }
15508
+ if (initPromise2) {
15509
+ return initPromise2;
15510
+ }
15511
+ initPromise2 = (async () => {
15512
+ const syncPath = findSgCliPathSync();
15513
+ if (syncPath && existsSync8(syncPath)) {
15514
+ resolvedCliPath3 = syncPath;
15515
+ setSgCliPath(syncPath);
15516
+ return syncPath;
15517
+ }
15518
+ const downloadedPath = await ensureAstGrepBinary();
15519
+ if (downloadedPath) {
15520
+ resolvedCliPath3 = downloadedPath;
15521
+ setSgCliPath(downloadedPath);
15522
+ return downloadedPath;
15523
+ }
15524
+ return null;
15525
+ })();
15526
+ return initPromise2;
15527
+ }
15528
+ async function spawnSg(cliPath, args) {
15529
+ const proc = spawn5([cliPath, ...args], {
15530
+ stdout: "pipe",
15531
+ stderr: "pipe"
15532
+ });
15533
+ const stdout = await new Response(proc.stdout).text();
15534
+ const stderr = await new Response(proc.stderr).text();
15535
+ const exitCode = await proc.exited;
15536
+ return { stdout, stderr, exitCode };
15537
+ }
15362
15538
  async function runSg(options) {
15363
15539
  const args = ["run", "-p", options.pattern, "--lang", options.lang, "--json=compact"];
15364
15540
  if (options.rewrite) {
@@ -15377,13 +15553,37 @@ async function runSg(options) {
15377
15553
  }
15378
15554
  const paths = options.paths && options.paths.length > 0 ? options.paths : ["."];
15379
15555
  args.push(...paths);
15380
- const proc = spawn4([SG_CLI_PATH, ...args], {
15381
- stdout: "pipe",
15382
- stderr: "pipe"
15383
- });
15384
- const stdout = await new Response(proc.stdout).text();
15385
- const stderr = await new Response(proc.stderr).text();
15386
- const exitCode = await proc.exited;
15556
+ let cliPath = getSgCliPath();
15557
+ if (!existsSync8(cliPath) && cliPath !== "sg") {
15558
+ const downloadedPath = await getAstGrepPath();
15559
+ if (downloadedPath) {
15560
+ cliPath = downloadedPath;
15561
+ }
15562
+ }
15563
+ let result;
15564
+ try {
15565
+ result = await spawnSg(cliPath, args);
15566
+ } catch (e) {
15567
+ const error45 = e;
15568
+ if (error45.code === "ENOENT" || error45.message?.includes("ENOENT") || error45.message?.includes("not found")) {
15569
+ const downloadedPath = await ensureAstGrepBinary();
15570
+ if (downloadedPath) {
15571
+ resolvedCliPath3 = downloadedPath;
15572
+ setSgCliPath(downloadedPath);
15573
+ result = await spawnSg(downloadedPath, args);
15574
+ } else {
15575
+ throw new Error(`ast-grep CLI binary not found.
15576
+
15577
+ ` + `Auto-download failed. Manual install options:
15578
+ ` + ` bun add -D @ast-grep/cli
15579
+ ` + ` cargo install ast-grep --locked
15580
+ ` + ` brew install ast-grep`);
15581
+ }
15582
+ } else {
15583
+ throw new Error(`Failed to spawn ast-grep: ${error45.message}`);
15584
+ }
15585
+ }
15586
+ const { stdout, stderr, exitCode } = result;
15387
15587
  if (exitCode !== 0 && stdout.trim() === "") {
15388
15588
  if (stderr.includes("No files found")) {
15389
15589
  return [];
@@ -15413,7 +15613,15 @@ var LANG_MAP = {
15413
15613
  typescript: Lang.TypeScript
15414
15614
  };
15415
15615
  function parseCode(code, lang) {
15416
- return parse5(LANG_MAP[lang], code);
15616
+ const parseLang = LANG_MAP[lang];
15617
+ if (!parseLang) {
15618
+ const supportedLangs = NAPI_LANGUAGES.join(", ");
15619
+ throw new Error(`Unsupported language for NAPI: "${lang}"
15620
+ ` + `Supported languages: ${supportedLangs}
15621
+
15622
+ ` + `Use ast_grep_search for other languages (25 supported via CLI).`);
15623
+ }
15624
+ return parse5(parseLang, code);
15417
15625
  }
15418
15626
  function findPattern(root, pattern) {
15419
15627
  return root.root().findAll(pattern);
@@ -15551,25 +15759,22 @@ function showOutputToUser(context, output) {
15551
15759
  const ctx = context;
15552
15760
  ctx.metadata?.({ metadata: { output } });
15553
15761
  }
15554
- var JS_TS_LANGUAGES = ["javascript", "typescript", "tsx"];
15555
- function validatePatternForCli(pattern, lang) {
15556
- if (!JS_TS_LANGUAGES.includes(lang)) {
15557
- return;
15558
- }
15762
+ function getEmptyResultHint(pattern, lang) {
15559
15763
  const src = pattern.trim();
15560
- const incompleteFunctionDecl = /^(export\s+)?(default\s+)?(async\s+)?function\s+\$[A-Z_][A-Z0-9_]*\s*$/i.test(src);
15561
- if (incompleteFunctionDecl) {
15562
- throw new Error(`Incomplete AST pattern for ${lang}: "${pattern}"
15563
-
15564
- ` + `ast-grep requires complete AST nodes. Function declarations must include parameters and body.
15565
-
15566
- ` + `Examples of correct patterns:
15567
- ` + ` - "export async function $NAME($$$) { $$$ }" (matches export async functions)
15568
- ` + ` - "function $NAME($$$) { $$$ }" (matches all function declarations)
15569
- ` + ` - "async function $NAME($$$) { $$$ }" (matches async functions)
15570
-
15571
- ` + `Your pattern "${pattern}" is missing the parameter list and body.`);
15764
+ if (lang === "python") {
15765
+ if (src.startsWith("class ") && src.endsWith(":")) {
15766
+ return `\uD83D\uDCA1 Hint: Python class patterns need body. Try "class $NAME" or include body with $$$BODY`;
15767
+ }
15768
+ if ((src.startsWith("def ") || src.startsWith("async def ")) && src.endsWith(":")) {
15769
+ return `\uD83D\uDCA1 Hint: Python function patterns need body. Try "def $FUNC($$$):\\n $$$BODY"`;
15770
+ }
15572
15771
  }
15772
+ if (["javascript", "typescript", "tsx"].includes(lang)) {
15773
+ if (/^(export\s+)?(async\s+)?function\s+\$[A-Z_]+\s*$/i.test(src)) {
15774
+ return `\uD83D\uDCA1 Hint: Function patterns need params and body. Try "function $NAME($$$) { $$$ }"`;
15775
+ }
15776
+ }
15777
+ return null;
15573
15778
  }
15574
15779
  var ast_grep_search = tool({
15575
15780
  description: "Search code patterns across filesystem using AST-aware matching. Supports 25 languages. " + "Use meta-variables: $VAR (single node), $$$ (multiple nodes). " + "IMPORTANT: Patterns must be complete AST nodes (valid code). " + "For functions, include params and body: 'export async function $NAME($$$) { $$$ }' not 'export async function $NAME'. " + "Examples: 'console.log($MSG)', 'def $FUNC($$$):', 'async function $NAME($$$)'",
@@ -15582,7 +15787,6 @@ var ast_grep_search = tool({
15582
15787
  },
15583
15788
  execute: async (args, context) => {
15584
15789
  try {
15585
- validatePatternForCli(args.pattern, args.lang);
15586
15790
  const matches = await runSg({
15587
15791
  pattern: args.pattern,
15588
15792
  lang: args.lang,
@@ -15590,7 +15794,15 @@ var ast_grep_search = tool({
15590
15794
  globs: args.globs,
15591
15795
  context: args.context
15592
15796
  });
15593
- const output = formatSearchResult(matches);
15797
+ let output = formatSearchResult(matches);
15798
+ if (matches.length === 0) {
15799
+ const hint = getEmptyResultHint(args.pattern, args.lang);
15800
+ if (hint) {
15801
+ output += `
15802
+
15803
+ ${hint}`;
15804
+ }
15805
+ }
15594
15806
  showOutputToUser(context, output);
15595
15807
  return output;
15596
15808
  } catch (e) {
@@ -15696,13 +15908,12 @@ var ast_grep_transform = tool({
15696
15908
  }
15697
15909
  }
15698
15910
  });
15699
-
15700
15911
  // src/tools/safe-grep/cli.ts
15701
- var {spawn: spawn5 } = globalThis.Bun;
15912
+ var {spawn: spawn6 } = globalThis.Bun;
15702
15913
 
15703
15914
  // src/tools/safe-grep/constants.ts
15704
- import { existsSync as existsSync7 } from "fs";
15705
- import { join as join5, dirname as dirname3 } from "path";
15915
+ import { existsSync as existsSync9 } from "fs";
15916
+ import { join as join6, dirname as dirname3 } from "path";
15706
15917
  import { spawnSync } from "child_process";
15707
15918
  var cachedCli = null;
15708
15919
  function findExecutable(name) {
@@ -15723,13 +15934,13 @@ function getOpenCodeBundledRg() {
15723
15934
  const isWindows = process.platform === "win32";
15724
15935
  const rgName = isWindows ? "rg.exe" : "rg";
15725
15936
  const candidates = [
15726
- join5(execDir, rgName),
15727
- join5(execDir, "bin", rgName),
15728
- join5(execDir, "..", "bin", rgName),
15729
- join5(execDir, "..", "libexec", rgName)
15937
+ join6(execDir, rgName),
15938
+ join6(execDir, "bin", rgName),
15939
+ join6(execDir, "..", "bin", rgName),
15940
+ join6(execDir, "..", "libexec", rgName)
15730
15941
  ];
15731
15942
  for (const candidate of candidates) {
15732
- if (existsSync7(candidate)) {
15943
+ if (existsSync9(candidate)) {
15733
15944
  return candidate;
15734
15945
  }
15735
15946
  }
@@ -15870,7 +16081,7 @@ async function runRg(options) {
15870
16081
  }
15871
16082
  const paths = options.paths?.length ? options.paths : ["."];
15872
16083
  args.push(...paths);
15873
- const proc = spawn5([cli.path, ...args], {
16084
+ const proc = spawn6([cli.path, ...args], {
15874
16085
  stdout: "pipe",
15875
16086
  stderr: "pipe"
15876
16087
  });
@@ -16168,7 +16379,14 @@ var OhMyOpenCodePlugin = async (ctx) => {
16168
16379
  sessionID,
16169
16380
  error: error45
16170
16381
  };
16171
- await sessionRecovery.handleSessionRecovery(messageInfo);
16382
+ const recovered = await sessionRecovery.handleSessionRecovery(messageInfo);
16383
+ if (recovered && sessionID && sessionID === mainSessionID) {
16384
+ await ctx.client.session.prompt({
16385
+ path: { id: sessionID },
16386
+ body: { parts: [{ type: "text", text: "continue" }] },
16387
+ query: { directory: ctx.directory }
16388
+ }).catch(() => {});
16389
+ }
16172
16390
  }
16173
16391
  if (sessionID && sessionID === mainSessionID) {
16174
16392
  updateTerminalTitle({
@@ -8,4 +8,8 @@ export interface RunOptions {
8
8
  context?: number;
9
9
  updateAll?: boolean;
10
10
  }
11
+ export declare function getAstGrepPath(): Promise<string | null>;
12
+ export declare function startBackgroundInit(): void;
11
13
  export declare function runSg(options: RunOptions): Promise<CliMatch[]>;
14
+ export declare function isCliAvailable(): boolean;
15
+ export declare function ensureCliAvailable(): Promise<boolean>;
@@ -1,4 +1,27 @@
1
+ export declare function findSgCliPathSync(): string | null;
2
+ export declare function getSgCliPath(): string;
3
+ export declare function setSgCliPath(path: string): void;
1
4
  export declare const SG_CLI_PATH: string;
2
5
  export declare const CLI_LANGUAGES: readonly ["bash", "c", "cpp", "csharp", "css", "elixir", "go", "haskell", "html", "java", "javascript", "json", "kotlin", "lua", "nix", "php", "python", "ruby", "rust", "scala", "solidity", "swift", "typescript", "tsx", "yaml"];
3
6
  export declare const NAPI_LANGUAGES: readonly ["html", "javascript", "tsx", "css", "typescript"];
4
7
  export declare const LANG_EXTENSIONS: Record<string, string[]>;
8
+ export interface EnvironmentCheckResult {
9
+ cli: {
10
+ available: boolean;
11
+ path: string;
12
+ error?: string;
13
+ };
14
+ napi: {
15
+ available: boolean;
16
+ error?: string;
17
+ };
18
+ }
19
+ /**
20
+ * Check if ast-grep CLI and NAPI are available.
21
+ * Call this at startup to provide early feedback about missing dependencies.
22
+ */
23
+ export declare function checkEnvironment(): EnvironmentCheckResult;
24
+ /**
25
+ * Format environment check result as user-friendly message.
26
+ */
27
+ export declare function formatEnvironmentCheck(result: EnvironmentCheckResult): string;
@@ -0,0 +1,5 @@
1
+ export declare function getCacheDir(): string;
2
+ export declare function getBinaryName(): string;
3
+ export declare function getCachedBinaryPath(): string | null;
4
+ export declare function downloadAstGrep(version?: string): Promise<string | null>;
5
+ export declare function ensureAstGrepBinary(): Promise<string | null>;
@@ -89,4 +89,8 @@ export declare const builtinTools: {
89
89
  }, context: import("@opencode-ai/plugin").ToolContext): Promise<string>;
90
90
  };
91
91
  };
92
- export { ast_grep_search, ast_grep_replace, };
92
+ export { ast_grep_search, ast_grep_replace };
93
+ export { ensureAstGrepBinary, getCachedBinaryPath, getCacheDir } from "./downloader";
94
+ export { getAstGrepPath, isCliAvailable, ensureCliAvailable, startBackgroundInit } from "./cli";
95
+ export { checkEnvironment, formatEnvironmentCheck } from "./constants";
96
+ export type { EnvironmentCheckResult } from "./constants";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oh-my-opencode",
3
- "version": "0.1.17",
3
+ "version": "0.1.19",
4
4
  "description": "OpenCode plugin - custom agents (oracle, librarian) and enhanced features",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",