Skip to content

[WEB] Question tool is not available immediately #20514

Closed as not planned
Closed as not planned

Description

@gund

Description

When running opencode serve, the question tool is not exposed to web interface clients on initial connection. However, after attaching a TUI client (opencode attach), the tool becomes available to all clients including web.

Root Cause Analysis

Root Cause

The ToolRegistry in packages/opencode/src/tool/registry.ts evaluates the question tool's availability at cache initialization time (in the all() function) rather than at request time (in ids() and tools() methods).

The all() function uses Effect's InstanceState scoped caching mechanism. When the first web client connects, the tool list is cached with the Flag.OPENCODE_CLIENT evaluation occurring during this initialization. Due to how the web client's request context is established, this flag evaluation happens incorrectly or in an incomplete context, causing the question tool to be excluded from the cached tool list.

When a TUI client attaches via opencode attach, it triggers Instance.provide() with proper InstanceBootstrap, which refreshes or invalidates the cache. Subsequent requests then receive the correct tool list including question.

Problematic Code Location

File: packages/opencode/src/tool/registry.ts (lines 119-120)

const all = Effect.fn('ToolRegistry.all')(function* (custom: Tool.Info[]) {
  const cfg = yield* config.get();
  const question =
    ['app', 'cli', 'desktop'].includes(Flag.OPENCODE_CLIENT) || Flag.OPENCODE_ENABLE_QUESTION_TOOL;
  // ^ Evaluated at cache init time, not per-request!

  return [
    InvalidTool,
    ...(question ? [QuestionTool] : []), // Cached incorrectly for web clients
    // ... other tools
  ];
});

Plugins

OpenCode version

v1.3.12

Steps to reproduce

  1. Start OC in server mode opencode serve --port 1234
  2. Open web interface in a browser (do not yet attach TUI)
  3. Create a new session and ask: "Do you have the question tool available?" and verify no question tool available
  4. Attach TUI to same server opencode attach http://localhost:1234
  5. Ask same question in the same session and now question tool is magically available

Screenshot and/or share link

Debug session with Kimi: https://opncd.ai/share/tg0yhnpM

Operating System

Ubuntu 24.04 LTS

Terminal

Windows Terminal

Activity

  1. added
    bugSomething isn't working
    on Apr 1, 2026
  2. added
    coreAnything pertaining to core functionality of the application (opencode server stuff)
    on Apr 1, 2026
  3. gund commented on Apr 1, 2026

    @gund
    Author
    If you are interested: Suggested Fix

    Suggested Fix

    Move the question tool filtering from cache-time to request-time:

    File: packages/opencode/src/tool/registry.ts

    1. Modify all() function (lines ~119-148)

    Remove the conditional and always include QuestionTool:

    const all = Effect.fn('ToolRegistry.all')(function* (custom: Tool.Info[]) {
      const cfg = yield* config.get();
    
      return [
        InvalidTool,
        QuestionTool, // Always include - will filter dynamically later
        BashTool,
        ReadTool,
        GlobTool,
        GrepTool,
        EditTool,
        WriteTool,
        TaskTool,
        WebFetchTool,
        TodoWriteTool,
        WebSearchTool,
        CodeSearchTool,
        SkillTool,
        ApplyPatchTool,
        ...(Flag.OPENCODE_EXPERIMENTAL_LSP_TOOL ? [LspTool] : []),
        ...(cfg.experimental?.batch_tool === true ? [BatchTool] : []),
        ...(Flag.OPENCODE_EXPERIMENTAL_PLAN_MODE && Flag.OPENCODE_CLIENT === 'cli'
          ? [PlanExitTool]
          : []),
        ...custom,
      ];
    });

    2. Modify ids() function (around line ~165)

    Add dynamic filtering at request time:

    const ids = Effect.fn('ToolRegistry.ids')(function* () {
      const s = yield* InstanceState.get(state);
      const tools = yield* all(s.custom);
    
      // Evaluate at request time, not cache time!
      const question =
        ['app', 'cli', 'desktop'].includes(Flag.OPENCODE_CLIENT) || Flag.OPENCODE_ENABLE_QUESTION_TOOL;
    
      return tools.filter((t) => t.id !== 'question' || question).map((t) => t.id);
    });

    3. Modify tools() function (around line ~173)

    Add dynamic filtering at request time:

    const tools = Effect.fn('ToolRegistry.tools')(function* (
      model: { providerID: ProviderID; modelID: ModelID },
      agent?: Agent.Info,
    ) {
      const s = yield* InstanceState.get(state);
      const allTools = yield* all(s.custom);
    
      // Evaluate at request time
      const question =
        ['app', 'cli', 'desktop'].includes(Flag.OPENCODE_CLIENT) || Flag.OPENCODE_ENABLE_QUESTION_TOOL;
    
      const filtered = allTools.filter((tool) => {
        if (tool.id === 'question') return question; // Dynamic check
    
        if (tool.id === 'codesearch' || tool.id === 'websearch') {
          return model.providerID === ProviderID.opencode || Flag.OPENCODE_ENABLE_EXA;
        }
    
        const usePatch =
          model.modelID.includes('gpt-') &&
          !model.modelID.includes('oss') &&
          !model.modelID.includes('gpt-4');
        if (tool.id === 'apply_patch') return usePatch;
        if (tool.id === 'edit' || tool.id === 'write') return !usePatch;
    
        return true;
      });
      // ... rest of method
    });

    Summary of Changes

    • Before: Flag.OPENCODE_CLIENT evaluation happens at InstanceState initialization → cached → wrong result for early web clients
    • After: Flag.OPENCODE_CLIENT evaluation happens at each API request → always fresh → correct result for all clients

    NOTE: This was analyzed and generated by Kimi K2.5 without any manual cross checking

  4. removed
    bugSomething isn't working
    coreAnything pertaining to core functionality of the application (opencode server stuff)
    on May 3, 2026
  5. rekram1-node commented on Jun 23, 2026

    @rekram1-node
    Collaborator

    Automated: closing question issues.

    GitHub Issues are for bug reports and feature requests only — questions / support are no longer tracked here.

    If this is a bug or feature request, please open a new issue with the appropriate template.

  6. rekram1-node commented on Jun 23, 2026

    @rekram1-node
    Collaborator

    Reopening – this was incorrectly closed by automated question-issue cleanup. Sorry for the noise.

  7. github-actions commented on Aug 23, 2026

    @github-actions
    Contributor

    To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions