@cgasgarth/opencode-for-rust 1.1.1 → 1.1.2-next.1

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 (3) hide show
  1. package/README.md +14 -3
  2. package/dist/index.js +71 -38
  3. package/package.json +6 -2
package/README.md CHANGED
@@ -6,10 +6,10 @@ OpenCode plugin for Rust
6
6
 
7
7
  ## Features
8
8
 
9
- - Automatic Type Injection: Automatically analyzes Rust files and injects relevant type definitions (structs, enums, traits) into the context when you read a file.
10
- - Type Lookup: Includes a `lookup_type` tool to find specific Rust type definitions by name.
9
+ - Automatic Type Injection: Automatically analyzes Rust files and injects an outline of defined types (structs, enums, traits, functions) at the end of file content when you read a `.rs` file.
10
+ - Type Lookup: Includes a `lookup_type` tool to find specific Rust type definitions by name across the entire project.
11
11
  - Type Listing: Includes a `list_types` tool to see all available Rust types in the project.
12
- - Regex-based Parser: Uses a lightweight regex-based parser for robust compatibility across all JavaScript runtimes.
12
+ - Regex-based Parser: Uses a lightweight, zero-dependency regex-based parser that works reliably in all JavaScript environments (Node.js, Bun, OpenCode).
13
13
  - Zero Configuration: Works out of the box for standard Rust projects.
14
14
 
15
15
  ## Tools
@@ -56,3 +56,14 @@ https://github.com/cgasgarth/opencode-for-rust
56
56
  ## License
57
57
 
58
58
  MIT
59
+
60
+ ## Known Limitations
61
+
62
+ **Automatic Type Injection**: The hook for automatic type injection when reading `.rs` files is currently not functional in OpenCode's environment. This appears to be due to differences in how OpenCode's plugin system processes hook registration or type expectations compared to the TypeScript plugin.
63
+
64
+ **Manual Tools**: The following tools work correctly and can be used as alternatives:
65
+
66
+ - `lookup_type`: Successfully retrieves Rust type definitions by name (verified: 413 types found in kalshi-tools)
67
+ - `list_types`: Successfully lists all Rust type names in the project (verified: 413 types found in kalshi-tools)
68
+
69
+ The plugin loads without errors and uses a cross-platform regex-based parser that eliminates the WASM dependency issues that caused earlier crashes.
package/dist/index.js CHANGED
@@ -239,58 +239,58 @@ class RustContentFormatter {
239
239
  }
240
240
 
241
241
  // src/index.ts
242
+ import { z } from "zod";
243
+ import { appendFileSync } from "fs";
244
+ var DEBUG_LOG = "/tmp/opencode-rust-plugin.log";
245
+ function debugLog(msg) {
246
+ const timestamp = new Date().toISOString();
247
+ appendFileSync(DEBUG_LOG, `[${timestamp}] ${msg}
248
+ `);
249
+ }
242
250
  var RustPlugin = async (context) => {
251
+ debugLog(`Plugin initializing with context: ${JSON.stringify(context)}`);
243
252
  const config = {
244
253
  enabled: true,
245
- debug: false,
254
+ debug: true,
246
255
  budget: 50,
247
256
  excludePatterns: [],
248
257
  imports: false
249
258
  };
250
- const directory = context.directory || context.cwd || process.cwd();
259
+ const directory = context.directory || process.cwd();
260
+ debugLog(`Using directory: ${directory}`);
251
261
  const lookup = new RustTypeLookup(directory, config);
252
262
  const formatter = new RustContentFormatter(config);
253
263
  const extractor = new RegexRustTypeExtractor(config);
254
- return {
255
- hooks: {
256
- "tool.execute.after": async (args, result) => {
257
- if (args.tool !== "read" || !config.enabled)
258
- return result;
259
- const filePath = args.args.filePath;
260
- if (!filePath || !filePath.endsWith(".rs"))
261
- return result;
262
- try {
263
- await lookup.refresh();
264
- const types = await extractor.extract(filePath, result.content);
265
- const formatted = formatter.formatInjectedTypes(types);
266
- if (formatted) {
267
- return {
268
- ...result,
269
- content: result.content + formatted
270
- };
271
- }
272
- } catch (error) {
273
- if (config.debug) {
274
- throw error;
275
- }
276
- }
277
- return result;
278
- }
279
- },
264
+ debugLog("Created lookup, formatter, extractor");
265
+ try {
266
+ await lookup.refresh();
267
+ debugLog("Initial refresh completed");
268
+ } catch (e) {
269
+ debugLog(`Initial refresh failed: ${e}`);
270
+ }
271
+ const hooks = {
280
272
  tool: {
281
273
  lookup_type: tool({
282
274
  description: "Find a Rust type definition by name",
283
275
  args: {
284
- name: tool.schema.string().describe("The name of the type to find")
276
+ name: z.string().describe("The name of the type to look up")
285
277
  },
286
278
  async execute(args) {
279
+ debugLog(`lookup_type called with: ${JSON.stringify(args)}`);
287
280
  try {
281
+ await lookup.refresh();
282
+ debugLog("lookup_type: refresh done");
288
283
  const type = await lookup.findType(args.name);
289
- if (!type)
290
- return `Type "${args.name}" not found.`;
291
- return type.body || type.signature;
292
- } catch (error) {
293
- return `Error looking up type: ${error instanceof Error ? error.message : String(error)}`;
284
+ debugLog(`lookup_type: findType result: ${type ? "found" : "not found"}`);
285
+ if (!type) {
286
+ return `Type '${args.name}' not found`;
287
+ }
288
+ const result = formatter.formatInjectedTypes([type]);
289
+ debugLog(`lookup_type: returning ${result.length} chars`);
290
+ return result;
291
+ } catch (e) {
292
+ debugLog(`lookup_type error: ${e}`);
293
+ throw e;
294
294
  }
295
295
  }
296
296
  }),
@@ -298,17 +298,50 @@ var RustPlugin = async (context) => {
298
298
  description: "List all available Rust type names in the project",
299
299
  args: {},
300
300
  async execute() {
301
+ debugLog("list_types called");
301
302
  try {
302
- const types = await lookup.listTypeNames();
303
- return types.join(`
303
+ await lookup.refresh();
304
+ debugLog("list_types: refresh done");
305
+ const names = await lookup.listTypeNames();
306
+ debugLog(`list_types: found ${names.length} types`);
307
+ if (names.length === 0) {
308
+ return "No Rust types found in project";
309
+ }
310
+ return names.join(`
304
311
  `);
305
- } catch (error) {
306
- return `Error listing types: ${error instanceof Error ? error.message : String(error)}`;
312
+ } catch (e) {
313
+ debugLog(`list_types error: ${e}`);
314
+ throw e;
307
315
  }
308
316
  }
309
317
  })
318
+ },
319
+ "tool.execute.after": async (input, output) => {
320
+ debugLog(`tool.execute.after: tool=${input.tool}`);
321
+ if (input.tool !== "read") {
322
+ return;
323
+ }
324
+ const metadata = output.metadata;
325
+ const filePath = metadata?.filePath;
326
+ debugLog(`tool.execute.after: filePath=${filePath}`);
327
+ if (!filePath || !filePath.endsWith(".rs")) {
328
+ return;
329
+ }
330
+ try {
331
+ const types = await extractor.extract(filePath);
332
+ debugLog(`tool.execute.after: extracted ${types.length} types`);
333
+ const formatted = formatter.formatInjectedTypes(types);
334
+ if (formatted) {
335
+ output.output = output.output + formatted;
336
+ debugLog(`tool.execute.after: appended ${formatted.length} chars`);
337
+ }
338
+ } catch (error) {
339
+ debugLog(`tool.execute.after error: ${error}`);
340
+ }
310
341
  }
311
342
  };
343
+ debugLog("Hooks created, returning");
344
+ return hooks;
312
345
  };
313
346
  var src_default = RustPlugin;
314
347
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cgasgarth/opencode-for-rust",
3
- "version": "1.1.1",
3
+ "version": "1.1.2-next.1",
4
4
  "description": "OpenCode plugin for Rust",
5
5
  "author": {
6
6
  "name": "Sisyphus",
@@ -28,6 +28,9 @@
28
28
  "dependencies": {
29
29
  "@opencode-ai/plugin": "1.0.85"
30
30
  },
31
+ "peerDependencies": {
32
+ "zod": "^4.0.0"
33
+ },
31
34
  "devDependencies": {
32
35
  "@eslint/js": "^9.39.1",
33
36
  "@types/bun": "latest",
@@ -35,6 +38,7 @@
35
38
  "@typescript-eslint/eslint-plugin": "8.47.0",
36
39
  "@typescript-eslint/parser": "8.47.0",
37
40
  "bun-types": "latest",
41
+ "esbuild": "^0.27.2",
38
42
  "eslint": "^9.39.1",
39
43
  "eslint-config-prettier": "10.1.8",
40
44
  "eslint-plugin-prettier": "^5.2.1",
@@ -48,7 +52,7 @@
48
52
  "scripts": {
49
53
  "test": "bun test tests/",
50
54
  "typecheck": "tsc --noEmit",
51
- "build": "bun build ./src/index.ts --outdir dist --target node --external @opencode-ai/plugin && tsc --project tsconfig.build.json",
55
+ "build": "esbuild ./src/index.ts --bundle --format=esm --platform=node --outdir=dist --external:zod && tsc --project tsconfig.build.json",
52
56
  "lint": "eslint src --max-warnings 0",
53
57
  "format": "prettier --check .",
54
58
  "prepare": "husky"