Skip to content

fix(plugin): derive id from package name#92

Merged
NaNomicon merged 3 commits intotickernelz:mainfrom
regulusleow:feat/openai-chat-type-safety
Apr 10, 2026
Merged

fix(plugin): derive id from package name#92
NaNomicon merged 3 commits intotickernelz:mainfrom
regulusleow:feat/openai-chat-type-safety

Conversation

@regulusleow
Copy link
Copy Markdown

@regulusleow regulusleow commented Apr 9, 2026

Summary

Export plugin id in src/plugin.ts to satisfy the V1 PluginModule shape required by OpenCode's file/path plugin loading path.

Note: The type-safety refactor commits that were originally part of this PR have been cherry-picked and merged separately via #93.

Problem

When loading opencode-mem from a local filesystem path (rather than npm install), the V1 plugin module shape requires an explicit id. Without it, loading fails with:

Path plugin ... must export id

Changes

  • Export plugin id in src/plugin.ts, derived from package.json.name with a safe fallback
  • Keep V1 PluginModule default export shape: { id, server }
  • Add contract test assertions to verify id exists, is non-empty, and matches package.json.name

Validation

bun test tests/plugin-loader-contract.test.ts

Original work by @regulusleow.

machen added 2 commits April 9, 2026 15:46
Apply typed request/response guards directly in openai-chat-completion and remove any usage in the provider implementation. Add provider-focused tests and clarify config comments for OpenAI-compatible endpoints.
Export a stable PluginModule id for file-path loading by deriving it from package.json name with a safe fallback. Extend plugin loader contract tests to assert id presence and alignment with package name.
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors the OpenAI Chat Completions provider to use tighter internal typings and adds a plugin id export (derived from package.json.name) to satisfy the OpenCode 1.3.x plugin-loader contract, along with expanded tests and config guidance.

Changes:

  • Tightened typing in OpenAIChatCompletionProvider (request/response message shapes, config typing, and response parsing).
  • Exported plugin id (and included it in the default PluginModule export) and added a contract test asserting id matches the package name.
  • Added provider-focused tests for the OpenAI chat path and clarified config template comments for OpenAI-compatible endpoints.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tests/plugin-loader-contract.test.ts Adds an assertion that the built plugin default export includes a non-empty id matching package.json.name.
tests/openai-chat-completion-provider.test.ts New test suite covering OpenAI chat provider behavior (headers, apiUrl, request body, tool-call loop behavior).
src/services/ai/providers/openai-chat-completion.ts Refactors provider code to tighten types and introduce type guards + typed request/response objects.
src/plugin.ts Exports id derived from package.json.name and includes it in the default PluginModule export.
src/config.ts Updates config template comments to clarify OpenAI-compatible usage and examples.
Comments suppressed due to low confidence (1)

src/services/ai/providers/openai-chat-completion.ts:26

  • ToolCallResponse.choices[].message.content is typed as string | undefined, but OpenAI Chat Completions can return content: null when the assistant emits tool_calls. With the current type, isToolCallResponse() narrows data to ToolCallResponse even when content is actually null, making the typing unsound and undermining the goal of “tightened typing”. Consider widening this to string | null (and optionally reflecting that in APIMessage.content too).
interface ToolCallResponse {
  choices: Array<{
    message: {
      content?: string;
      tool_calls?: Array<{
        id: string;
        type: "function";
        function: {
          name: string;
          arguments: string;
        };
      }>;
    };
    finish_reason?: string;

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/services/ai/providers/openai-chat-completion.ts Outdated
Comment thread src/services/ai/providers/openai-chat-completion.ts
Comment thread src/plugin.ts
@regulusleow
Copy link
Copy Markdown
Author

@NaNomicon The Copilot-flagged items have been addressed and tested locally (18/18 passing):

  • isToolCallResponsehasNonEmptyChoices: renamed and strengthened with minimal field validation
  • content || "" → split ?? "" (session) / ?? null (API messages): preserves OpenAI's null for tool-calling responses

As for the plugin.ts id change — happy to drop it if it's not needed for mainline usage. Let me know either way.

@NaNomicon NaNomicon changed the title refactor(ai): tighten openai-chat typing and align plugin id export fix(plugin): derive id from package name Apr 10, 2026
@NaNomicon NaNomicon merged commit 4c6da77 into tickernelz:main Apr 10, 2026
1 check passed
@regulusleow regulusleow deleted the feat/openai-chat-type-safety branch April 10, 2026 08:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants