oh-my-opencode 0.1.23 → 0.1.24

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
@@ -1571,6 +1571,9 @@ var SEVERITY_MAP = {
1571
1571
  3: "information",
1572
1572
  4: "hint"
1573
1573
  };
1574
+ var DEFAULT_MAX_REFERENCES = 200;
1575
+ var DEFAULT_MAX_SYMBOLS = 200;
1576
+ var DEFAULT_MAX_DIAGNOSTICS = 200;
1574
1577
  var BUILTIN_SERVERS = {
1575
1578
  typescript: {
1576
1579
  command: ["typescript-language-server", "--stdio"],
@@ -15025,7 +15028,14 @@ var lsp_find_references = tool({
15025
15028
  const output2 = "No references found";
15026
15029
  return output2;
15027
15030
  }
15028
- const output = result.map(formatLocation).join(`
15031
+ const total = result.length;
15032
+ const truncated = total > DEFAULT_MAX_REFERENCES;
15033
+ const limited = truncated ? result.slice(0, DEFAULT_MAX_REFERENCES) : result;
15034
+ const lines = limited.map(formatLocation);
15035
+ if (truncated) {
15036
+ lines.unshift(`Found ${total} references (showing first ${DEFAULT_MAX_REFERENCES}):`);
15037
+ }
15038
+ const output = lines.join(`
15029
15039
  `);
15030
15040
  return output;
15031
15041
  } catch (e) {
@@ -15045,18 +15055,23 @@ var lsp_document_symbols = tool({
15045
15055
  return await client.documentSymbols(args.filePath);
15046
15056
  });
15047
15057
  if (!result || result.length === 0) {
15048
- const output2 = "No symbols found";
15049
- return output2;
15058
+ const output = "No symbols found";
15059
+ return output;
15050
15060
  }
15051
- let output;
15052
- if ("range" in result[0]) {
15053
- output = result.map((s) => formatDocumentSymbol(s)).join(`
15054
- `);
15061
+ const total = result.length;
15062
+ const truncated = total > DEFAULT_MAX_SYMBOLS;
15063
+ const limited = truncated ? result.slice(0, DEFAULT_MAX_SYMBOLS) : result;
15064
+ const lines = [];
15065
+ if (truncated) {
15066
+ lines.push(`Found ${total} symbols (showing first ${DEFAULT_MAX_SYMBOLS}):`);
15067
+ }
15068
+ if ("range" in limited[0]) {
15069
+ lines.push(...limited.map((s) => formatDocumentSymbol(s)));
15055
15070
  } else {
15056
- output = result.map(formatSymbolInfo).join(`
15057
- `);
15071
+ lines.push(...limited.map(formatSymbolInfo));
15058
15072
  }
15059
- return output;
15073
+ return lines.join(`
15074
+ `);
15060
15075
  } catch (e) {
15061
15076
  const output = `Error: ${e instanceof Error ? e.message : String(e)}`;
15062
15077
  return output;
@@ -15079,8 +15094,15 @@ var lsp_workspace_symbols = tool({
15079
15094
  const output2 = "No symbols found";
15080
15095
  return output2;
15081
15096
  }
15082
- const limited = args.limit ? result.slice(0, args.limit) : result;
15083
- const output = limited.map(formatSymbolInfo).join(`
15097
+ const total = result.length;
15098
+ const limit = Math.min(args.limit ?? DEFAULT_MAX_SYMBOLS, DEFAULT_MAX_SYMBOLS);
15099
+ const truncated = total > limit;
15100
+ const limited = result.slice(0, limit);
15101
+ const lines = limited.map(formatSymbolInfo);
15102
+ if (truncated) {
15103
+ lines.unshift(`Found ${total} symbols (showing first ${limit}):`);
15104
+ }
15105
+ const output = lines.join(`
15084
15106
  `);
15085
15107
  return output;
15086
15108
  } catch (e) {
@@ -15113,7 +15135,14 @@ var lsp_diagnostics = tool({
15113
15135
  const output2 = "No diagnostics found";
15114
15136
  return output2;
15115
15137
  }
15116
- const output = diagnostics.map(formatDiagnostic).join(`
15138
+ const total = diagnostics.length;
15139
+ const truncated = total > DEFAULT_MAX_DIAGNOSTICS;
15140
+ const limited = truncated ? diagnostics.slice(0, DEFAULT_MAX_DIAGNOSTICS) : diagnostics;
15141
+ const lines = limited.map(formatDiagnostic);
15142
+ if (truncated) {
15143
+ lines.unshift(`Found ${total} diagnostics (showing first ${DEFAULT_MAX_DIAGNOSTICS}):`);
15144
+ }
15145
+ const output = lines.join(`
15117
15146
  `);
15118
15147
  return output;
15119
15148
  } catch (e) {
@@ -15475,6 +15504,9 @@ var CLI_LANGUAGES = [
15475
15504
  "yaml"
15476
15505
  ];
15477
15506
  var NAPI_LANGUAGES = ["html", "javascript", "tsx", "css", "typescript"];
15507
+ var DEFAULT_TIMEOUT_MS = 300000;
15508
+ var DEFAULT_MAX_OUTPUT_BYTES = 1 * 1024 * 1024;
15509
+ var DEFAULT_MAX_MATCHES = 500;
15478
15510
  var LANG_EXTENSIONS = {
15479
15511
  bash: [".bash", ".sh", ".zsh", ".bats"],
15480
15512
  c: [".c", ".h"],
@@ -15532,16 +15564,6 @@ async function getAstGrepPath() {
15532
15564
  })();
15533
15565
  return initPromise2;
15534
15566
  }
15535
- async function spawnSg(cliPath, args) {
15536
- const proc = spawn5([cliPath, ...args], {
15537
- stdout: "pipe",
15538
- stderr: "pipe"
15539
- });
15540
- const stdout = await new Response(proc.stdout).text();
15541
- const stderr = await new Response(proc.stderr).text();
15542
- const exitCode = await proc.exited;
15543
- return { stdout, stderr, exitCode };
15544
- }
15545
15567
  async function runSg(options) {
15546
15568
  const args = ["run", "-p", options.pattern, "--lang", options.lang, "--json=compact"];
15547
15569
  if (options.rewrite) {
@@ -15567,47 +15589,114 @@ async function runSg(options) {
15567
15589
  cliPath = downloadedPath;
15568
15590
  }
15569
15591
  }
15570
- let result;
15592
+ const timeout = DEFAULT_TIMEOUT_MS;
15593
+ const proc = spawn5([cliPath, ...args], {
15594
+ stdout: "pipe",
15595
+ stderr: "pipe"
15596
+ });
15597
+ const timeoutPromise = new Promise((_, reject) => {
15598
+ const id = setTimeout(() => {
15599
+ proc.kill();
15600
+ reject(new Error(`Search timeout after ${timeout}ms`));
15601
+ }, timeout);
15602
+ proc.exited.then(() => clearTimeout(id));
15603
+ });
15604
+ let stdout;
15605
+ let stderr;
15606
+ let exitCode;
15571
15607
  try {
15572
- result = await spawnSg(cliPath, args);
15608
+ stdout = await Promise.race([new Response(proc.stdout).text(), timeoutPromise]);
15609
+ stderr = await new Response(proc.stderr).text();
15610
+ exitCode = await proc.exited;
15573
15611
  } catch (e) {
15574
15612
  const error45 = e;
15575
- if (error45.code === "ENOENT" || error45.message?.includes("ENOENT") || error45.message?.includes("not found")) {
15613
+ if (error45.message?.includes("timeout")) {
15614
+ return {
15615
+ matches: [],
15616
+ totalMatches: 0,
15617
+ truncated: true,
15618
+ truncatedReason: "timeout",
15619
+ error: error45.message
15620
+ };
15621
+ }
15622
+ const nodeError = e;
15623
+ if (nodeError.code === "ENOENT" || nodeError.message?.includes("ENOENT") || nodeError.message?.includes("not found")) {
15576
15624
  const downloadedPath = await ensureAstGrepBinary();
15577
15625
  if (downloadedPath) {
15578
15626
  resolvedCliPath3 = downloadedPath;
15579
15627
  setSgCliPath(downloadedPath);
15580
- result = await spawnSg(downloadedPath, args);
15628
+ return runSg(options);
15581
15629
  } else {
15582
- throw new Error(`ast-grep CLI binary not found.
15630
+ return {
15631
+ matches: [],
15632
+ totalMatches: 0,
15633
+ truncated: false,
15634
+ error: `ast-grep CLI binary not found.
15583
15635
 
15584
15636
  ` + `Auto-download failed. Manual install options:
15585
15637
  ` + ` bun add -D @ast-grep/cli
15586
15638
  ` + ` cargo install ast-grep --locked
15587
- ` + ` brew install ast-grep`);
15639
+ ` + ` brew install ast-grep`
15640
+ };
15588
15641
  }
15589
- } else {
15590
- throw new Error(`Failed to spawn ast-grep: ${error45.message}`);
15591
15642
  }
15643
+ return {
15644
+ matches: [],
15645
+ totalMatches: 0,
15646
+ truncated: false,
15647
+ error: `Failed to spawn ast-grep: ${error45.message}`
15648
+ };
15592
15649
  }
15593
- const { stdout, stderr, exitCode } = result;
15594
15650
  if (exitCode !== 0 && stdout.trim() === "") {
15595
15651
  if (stderr.includes("No files found")) {
15596
- return [];
15652
+ return { matches: [], totalMatches: 0, truncated: false };
15597
15653
  }
15598
15654
  if (stderr.trim()) {
15599
- throw new Error(stderr.trim());
15655
+ return { matches: [], totalMatches: 0, truncated: false, error: stderr.trim() };
15600
15656
  }
15601
- return [];
15657
+ return { matches: [], totalMatches: 0, truncated: false };
15602
15658
  }
15603
15659
  if (!stdout.trim()) {
15604
- return [];
15660
+ return { matches: [], totalMatches: 0, truncated: false };
15605
15661
  }
15662
+ const outputTruncated = stdout.length >= DEFAULT_MAX_OUTPUT_BYTES;
15663
+ const outputToProcess = outputTruncated ? stdout.substring(0, DEFAULT_MAX_OUTPUT_BYTES) : stdout;
15664
+ let matches = [];
15606
15665
  try {
15607
- return JSON.parse(stdout);
15666
+ matches = JSON.parse(outputToProcess);
15608
15667
  } catch {
15609
- return [];
15668
+ if (outputTruncated) {
15669
+ try {
15670
+ const lastValidIndex = outputToProcess.lastIndexOf("}");
15671
+ if (lastValidIndex > 0) {
15672
+ const bracketIndex = outputToProcess.lastIndexOf("},", lastValidIndex);
15673
+ if (bracketIndex > 0) {
15674
+ const truncatedJson = outputToProcess.substring(0, bracketIndex + 1) + "]";
15675
+ matches = JSON.parse(truncatedJson);
15676
+ }
15677
+ }
15678
+ } catch {
15679
+ return {
15680
+ matches: [],
15681
+ totalMatches: 0,
15682
+ truncated: true,
15683
+ truncatedReason: "max_output_bytes",
15684
+ error: "Output too large and could not be parsed"
15685
+ };
15686
+ }
15687
+ } else {
15688
+ return { matches: [], totalMatches: 0, truncated: false };
15689
+ }
15610
15690
  }
15691
+ const totalMatches = matches.length;
15692
+ const matchesTruncated = totalMatches > DEFAULT_MAX_MATCHES;
15693
+ const finalMatches = matchesTruncated ? matches.slice(0, DEFAULT_MAX_MATCHES) : matches;
15694
+ return {
15695
+ matches: finalMatches,
15696
+ totalMatches,
15697
+ truncated: outputTruncated || matchesTruncated,
15698
+ truncatedReason: outputTruncated ? "max_output_bytes" : matchesTruncated ? "max_matches" : undefined
15699
+ };
15611
15700
  }
15612
15701
 
15613
15702
  // src/tools/ast-grep/napi.ts
@@ -15696,13 +15785,22 @@ function getRootInfo(code, lang) {
15696
15785
  }
15697
15786
 
15698
15787
  // src/tools/ast-grep/utils.ts
15699
- function formatSearchResult(matches) {
15700
- if (matches.length === 0) {
15788
+ function formatSearchResult(result) {
15789
+ if (result.error) {
15790
+ return `Error: ${result.error}`;
15791
+ }
15792
+ if (result.matches.length === 0) {
15701
15793
  return "No matches found";
15702
15794
  }
15703
- const lines = [`Found ${matches.length} match(es):
15704
- `];
15705
- for (const match of matches) {
15795
+ const lines = [];
15796
+ if (result.truncated) {
15797
+ const reason = result.truncatedReason === "max_matches" ? `showing first ${result.matches.length} of ${result.totalMatches}` : result.truncatedReason === "max_output_bytes" ? "output exceeded 1MB limit" : "search timed out";
15798
+ lines.push(`\u26A0\uFE0F Results truncated (${reason})
15799
+ `);
15800
+ }
15801
+ lines.push(`Found ${result.matches.length} match(es)${result.truncated ? ` (truncated from ${result.totalMatches})` : ""}:
15802
+ `);
15803
+ for (const match of result.matches) {
15706
15804
  const loc = `${match.file}:${match.range.start.line + 1}:${match.range.start.column + 1}`;
15707
15805
  lines.push(`${loc}`);
15708
15806
  lines.push(` ${match.lines.trim()}`);
@@ -15711,14 +15809,23 @@ function formatSearchResult(matches) {
15711
15809
  return lines.join(`
15712
15810
  `);
15713
15811
  }
15714
- function formatReplaceResult(matches, isDryRun) {
15715
- if (matches.length === 0) {
15812
+ function formatReplaceResult(result, isDryRun) {
15813
+ if (result.error) {
15814
+ return `Error: ${result.error}`;
15815
+ }
15816
+ if (result.matches.length === 0) {
15716
15817
  return "No matches found to replace";
15717
15818
  }
15718
15819
  const prefix = isDryRun ? "[DRY RUN] " : "";
15719
- const lines = [`${prefix}${matches.length} replacement(s):
15720
- `];
15721
- for (const match of matches) {
15820
+ const lines = [];
15821
+ if (result.truncated) {
15822
+ const reason = result.truncatedReason === "max_matches" ? `showing first ${result.matches.length} of ${result.totalMatches}` : result.truncatedReason === "max_output_bytes" ? "output exceeded 1MB limit" : "search timed out";
15823
+ lines.push(`\u26A0\uFE0F Results truncated (${reason})
15824
+ `);
15825
+ }
15826
+ lines.push(`${prefix}${result.matches.length} replacement(s):
15827
+ `);
15828
+ for (const match of result.matches) {
15722
15829
  const loc = `${match.file}:${match.range.start.line + 1}:${match.range.start.column + 1}`;
15723
15830
  lines.push(`${loc}`);
15724
15831
  lines.push(` ${match.text}`);
@@ -15796,15 +15903,15 @@ var ast_grep_search = tool({
15796
15903
  },
15797
15904
  execute: async (args, context) => {
15798
15905
  try {
15799
- const matches = await runSg({
15906
+ const result = await runSg({
15800
15907
  pattern: args.pattern,
15801
15908
  lang: args.lang,
15802
15909
  paths: args.paths,
15803
15910
  globs: args.globs,
15804
15911
  context: args.context
15805
15912
  });
15806
- let output = formatSearchResult(matches);
15807
- if (matches.length === 0) {
15913
+ let output = formatSearchResult(result);
15914
+ if (result.matches.length === 0 && !result.error) {
15808
15915
  const hint = getEmptyResultHint(args.pattern, args.lang);
15809
15916
  if (hint) {
15810
15917
  output += `
@@ -15833,7 +15940,7 @@ var ast_grep_replace = tool({
15833
15940
  },
15834
15941
  execute: async (args, context) => {
15835
15942
  try {
15836
- const matches = await runSg({
15943
+ const result = await runSg({
15837
15944
  pattern: args.pattern,
15838
15945
  rewrite: args.rewrite,
15839
15946
  lang: args.lang,
@@ -15841,7 +15948,7 @@ var ast_grep_replace = tool({
15841
15948
  globs: args.globs,
15842
15949
  updateAll: args.dryRun === false
15843
15950
  });
15844
- const output = formatReplaceResult(matches, args.dryRun !== false);
15951
+ const output = formatReplaceResult(result, args.dryRun !== false);
15845
15952
  showOutputToUser(context, output);
15846
15953
  return output;
15847
15954
  } catch (e) {
@@ -15980,8 +16087,8 @@ var DEFAULT_MAX_DEPTH = 20;
15980
16087
  var DEFAULT_MAX_FILESIZE = "10M";
15981
16088
  var DEFAULT_MAX_COUNT = 500;
15982
16089
  var DEFAULT_MAX_COLUMNS = 1000;
15983
- var DEFAULT_TIMEOUT_MS = 300000;
15984
- var DEFAULT_MAX_OUTPUT_BYTES = 10 * 1024 * 1024;
16090
+ var DEFAULT_TIMEOUT_MS2 = 300000;
16091
+ var DEFAULT_MAX_OUTPUT_BYTES2 = 10 * 1024 * 1024;
15985
16092
  var RG_SAFETY_FLAGS = [
15986
16093
  "--no-follow",
15987
16094
  "--color=never",
@@ -16082,7 +16189,7 @@ function parseOutput(output) {
16082
16189
  async function runRg(options) {
16083
16190
  const cli = resolveGrepCli();
16084
16191
  const args = buildArgs(options, cli.backend);
16085
- const timeout = Math.min(options.timeout ?? DEFAULT_TIMEOUT_MS, DEFAULT_TIMEOUT_MS);
16192
+ const timeout = Math.min(options.timeout ?? DEFAULT_TIMEOUT_MS2, DEFAULT_TIMEOUT_MS2);
16086
16193
  if (cli.backend === "rg") {
16087
16194
  args.push("--", options.pattern);
16088
16195
  } else {
@@ -16105,8 +16212,8 @@ async function runRg(options) {
16105
16212
  const stdout = await Promise.race([new Response(proc.stdout).text(), timeoutPromise]);
16106
16213
  const stderr = await new Response(proc.stderr).text();
16107
16214
  const exitCode = await proc.exited;
16108
- const truncated = stdout.length >= DEFAULT_MAX_OUTPUT_BYTES;
16109
- const outputToProcess = truncated ? stdout.substring(0, DEFAULT_MAX_OUTPUT_BYTES) : stdout;
16215
+ const truncated = stdout.length >= DEFAULT_MAX_OUTPUT_BYTES2;
16216
+ const outputToProcess = truncated ? stdout.substring(0, DEFAULT_MAX_OUTPUT_BYTES2) : stdout;
16110
16217
  if (exitCode > 1 && stderr.trim()) {
16111
16218
  return {
16112
16219
  matches: [],
@@ -1,4 +1,4 @@
1
- import type { CliMatch, CliLanguage } from "./types";
1
+ import type { CliLanguage, SgResult } from "./types";
2
2
  export interface RunOptions {
3
3
  pattern: string;
4
4
  lang: CliLanguage;
@@ -10,6 +10,6 @@ export interface RunOptions {
10
10
  }
11
11
  export declare function getAstGrepPath(): Promise<string | null>;
12
12
  export declare function startBackgroundInit(): void;
13
- export declare function runSg(options: RunOptions): Promise<CliMatch[]>;
13
+ export declare function runSg(options: RunOptions): Promise<SgResult>;
14
14
  export declare function isCliAvailable(): boolean;
15
15
  export declare function ensureCliAvailable(): Promise<boolean>;
@@ -4,6 +4,9 @@ export declare function setSgCliPath(path: string): void;
4
4
  export declare const SG_CLI_PATH: string;
5
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"];
6
6
  export declare const NAPI_LANGUAGES: readonly ["html", "javascript", "tsx", "css", "typescript"];
7
+ export declare const DEFAULT_TIMEOUT_MS = 300000;
8
+ export declare const DEFAULT_MAX_OUTPUT_BYTES: number;
9
+ export declare const DEFAULT_MAX_MATCHES = 500;
7
10
  export declare const LANG_EXTENSIONS: Record<string, string[]>;
8
11
  export interface EnvironmentCheckResult {
9
12
  cli: {
@@ -49,3 +49,10 @@ export interface TransformResult {
49
49
  transformed: string;
50
50
  editCount: number;
51
51
  }
52
+ export interface SgResult {
53
+ matches: CliMatch[];
54
+ totalMatches: number;
55
+ truncated: boolean;
56
+ truncatedReason?: "max_matches" | "max_output_bytes" | "timeout";
57
+ error?: string;
58
+ }
@@ -1,5 +1,5 @@
1
- import type { CliMatch, AnalyzeResult } from "./types";
2
- export declare function formatSearchResult(matches: CliMatch[]): string;
3
- export declare function formatReplaceResult(matches: CliMatch[], isDryRun: boolean): string;
1
+ import type { AnalyzeResult, SgResult } from "./types";
2
+ export declare function formatSearchResult(result: SgResult): string;
3
+ export declare function formatReplaceResult(result: SgResult, isDryRun: boolean): string;
4
4
  export declare function formatAnalyzeResult(results: AnalyzeResult[], extractedMetaVars: boolean): string;
5
5
  export declare function formatTransformResult(original: string, transformed: string, editCount: number): string;
@@ -1,5 +1,8 @@
1
1
  import type { LSPServerConfig } from "./types";
2
2
  export declare const SYMBOL_KIND_MAP: Record<number, string>;
3
3
  export declare const SEVERITY_MAP: Record<number, string>;
4
+ export declare const DEFAULT_MAX_REFERENCES = 200;
5
+ export declare const DEFAULT_MAX_SYMBOLS = 200;
6
+ export declare const DEFAULT_MAX_DIAGNOSTICS = 200;
4
7
  export declare const BUILTIN_SERVERS: Record<string, Omit<LSPServerConfig, "id">>;
5
8
  export declare const EXT_TO_LANG: Record<string, string>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oh-my-opencode",
3
- "version": "0.1.23",
3
+ "version": "0.1.24",
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",