import { EventEmitter } from 'node:events';
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';

import { beforeEach, describe, expect, it, vi } from 'vitest';

const buildProviderAwareCliEnvMock = vi.fn();
const resolveBinaryMock = vi.fn();
const clearBinaryCacheMock = vi.fn();
const execCliMock = vi.fn();
const spawnCliMock = vi.fn();
const resolveInteractiveShellEnvMock = vi.fn();

function createSpawnProcess(stdoutPayload: unknown, exitCode = 0): {
  child: {
    stdout: EventEmitter;
    stderr: EventEmitter;
    stdin: {
      write: ReturnType<typeof vi.fn>;
      end: ReturnType<typeof vi.fn>;
      once: EventEmitter['once'];
    };
    once: EventEmitter['once'];
  };
  stdinWrite: ReturnType<typeof vi.fn>;
} {
  const processEvents = new EventEmitter();
  const stdinEvents = new EventEmitter();
  const stdout = new EventEmitter();
  const stderr = new EventEmitter();
  const stdinWrite = vi.fn();
  const stdinEnd = vi.fn(() => {
    queueMicrotask(() => {
      stdout.emit('data', Buffer.from(JSON.stringify(stdoutPayload)));
      processEvents.emit('close', exitCode);
    });
  });

  return {
    child: {
      stdout,
      stderr,
      stdin: {
        write: stdinWrite,
        end: stdinEnd,
        once: stdinEvents.once.bind(stdinEvents),
      },
      once: processEvents.once.bind(processEvents),
    },
    stdinWrite,
  };
}

vi.mock('@main/services/runtime/providerAwareCliEnv', () => ({
  buildProviderAwareCliEnv: (...args: unknown[]) => buildProviderAwareCliEnvMock(...args),
}));

vi.mock('@main/services/team/ClaudeBinaryResolver', () => ({
  ClaudeBinaryResolver: {
    resolve: () => resolveBinaryMock(),
    clearCache: () => clearBinaryCacheMock(),
  },
}));

vi.mock('@main/utils/childProcess', () => ({
  execCli: (...args: unknown[]) => execCliMock(...args),
  spawnCli: (...args: unknown[]) => spawnCliMock(...args),
  killProcessTree: vi.fn(),
}));

vi.mock('@main/utils/shellEnv', () => ({
  resolveInteractiveShellEnvBestEffort: () => resolveInteractiveShellEnvMock(),
}));

vi.mock(
  '../../../../src/features/runtime-provider-management/main/infrastructure/openCodeWindowsNodeModulesJunction',
  () => ({
    isOpenCodeNodeModulesSymlinkError: vi.fn(),
    extractProfileIdFromSymlinkError: vi.fn(),
    ensureOpenCodeProfileNodeModulesJunction: vi.fn(),
  })
);

import { AgentTeamsRuntimeProviderManagementCliClient } from '../../../../src/features/runtime-provider-management/main/infrastructure/AgentTeamsRuntimeProviderManagementCliClient';
import {
  ensureOpenCodeProfileNodeModulesJunction as ensureOpenCodeProfileNodeModulesJunctionMock,
  extractProfileIdFromSymlinkError as extractProfileIdFromSymlinkErrorMock,
  isOpenCodeNodeModulesSymlinkError as isOpenCodeNodeModulesSymlinkErrorMock,
} from '../../../../src/features/runtime-provider-management/main/infrastructure/openCodeWindowsNodeModulesJunction';

describe('AgentTeamsRuntimeProviderManagementCliClient', () => {
  beforeEach(() => {
    vi.clearAllMocks();
    resolveBinaryMock.mockResolvedValue('/repo/cli-dev');
    resolveInteractiveShellEnvMock.mockResolvedValue({ PATH: '/Users/test/.bun/bin:/usr/bin' });
    buildProviderAwareCliEnvMock.mockResolvedValue({
      env: { PATH: '/Users/test/.bun/bin:/usr/bin' },
      connectionIssues: {},
      providerArgs: [],
    });
  });

  it('returns stderr details for failed model tests instead of hiding them behind the command', async () => {
    const error = new Error('Command failed: /repo/cli-dev runtime providers test-model');
    Object.assign(error, {
      stderr: './cli-dev: line 47: exec: bun: not found\n',
      stdout: '',
    });
    execCliMock.mockRejectedValue(error);

    const client = new AgentTeamsRuntimeProviderManagementCliClient();
    const response = await client.testModel({
      runtimeId: 'opencode',
      providerId: 'opencode',
      modelId: 'opencode/nemotron-3-super-free',
    });

    expect(response.error?.message).toContain(
      'OpenCode provider settings could not read the runtime response.'
    );
    expect(response.error?.message).toContain('stderr preview:');
    expect(response.error?.message).toContain('./cli-dev: line 47: exec: bun: not found');
    expect(response.error?.diagnostics?.command).toContain('runtime providers test-model');
    expect(response.error?.diagnostics?.stderrPreview).toBe(
      './cli-dev: line 47: exec: bun: not found'
    );
  });

  it('redacts secrets from generic command stderr details', async () => {
    const error = new Error('Command failed: /repo/cli-dev runtime providers view');
    Object.assign(error, {
      stderr: 'Provider failed with api_key: sk-secret-value-123456\n',
      stdout: '',
    });
    execCliMock.mockRejectedValue(error);

    const client = new AgentTeamsRuntimeProviderManagementCliClient();
    const response = await client.loadView({
      runtimeId: 'opencode',
    });

    expect(response.error?.message).toContain('Provider failed with api_key: ...redacted');
    expect(response.error?.message).not.toContain('sk-secret-value-123456');
    expect(response.error?.diagnostics?.stderrPreview).toBe(
      'Provider failed with api_key: ...redacted'
    );
    expect(response.error?.diagnostics?.command).toBe(
      '/repo/cli-dev runtime providers view --runtime opencode --json --compact'
    );
  });

  it('strips terminal formatting and redacts bearer tokens from command previews', async () => {
    const error = new Error('Command failed: /repo/cli-dev runtime providers models');
    Object.assign(error, {
      stderr:
        '\u001B]8;;https://logs.example/secret\u0007\u001B[31mAuthorization: Bearer live-token-123456789\u001B[0m\u001B]8;;\u0007\n',
      stdout: '',
    });
    execCliMock.mockRejectedValue(error);

    const client = new AgentTeamsRuntimeProviderManagementCliClient();
    const response = await client.loadModels({
      runtimeId: 'opencode',
      providerId: 'openrouter',
    });

    expect(response.error?.message).toContain('Authorization: Bearer ...redacted');
    expect(response.error?.message).not.toContain('live-token-123456789');
    expect(response.error?.message).not.toContain('logs.example/secret');
    expect(response.error?.message).not.toContain('[31m');
    expect(response.error?.message).not.toContain(']8;;');
    expect(response.error?.diagnostics?.stderrPreview).toBe(
      'Authorization: Bearer ...redacted'
    );
  });

  it('redacts non-OpenAI provider keys and generic token labels from diagnostics', async () => {
    const error = new Error('Command failed: /repo/cli-dev runtime providers view');
    Object.assign(error, {
      stderr:
        'Google key=AIzaSyD-test-secret-value-123456789 and token=provider-token-123456789 and OPENAI_API_KEY=plain_provider_secret_123456 and PROVIDER_TOKEN=provider_token_value_123456\n',
      stdout: '',
    });
    execCliMock.mockRejectedValue(error);

    const client = new AgentTeamsRuntimeProviderManagementCliClient();
    const response = await client.loadView({
      runtimeId: 'opencode',
    });

    expect(response.error?.message).toContain('key=...redacted');
    expect(response.error?.message).toContain('token=...redacted');
    expect(response.error?.message).toContain('OPENAI_API_KEY=...redacted');
    expect(response.error?.message).toContain('PROVIDER_TOKEN=...redacted');
    expect(response.error?.message).not.toContain('AIzaSyD-test-secret-value-123456789');
    expect(response.error?.message).not.toContain('provider-token-123456789');
    expect(response.error?.message).not.toContain('plain_provider_secret_123456');
    expect(response.error?.message).not.toContain('provider_token_value_123456');
    expect(response.error?.diagnostics?.stderrPreview).toContain('key=...redacted');
    expect(response.error?.diagnostics?.stderrPreview).toContain('token=...redacted');
  });

  it('returns structured diagnostics for empty non-JSON command output', async () => {
    execCliMock.mockResolvedValue({
      stdout: '',
      stderr: '',
    });

    const client = new AgentTeamsRuntimeProviderManagementCliClient();
    const response = await client.loadView({
      runtimeId: 'opencode',
    });

    expect(response.error?.message).toContain('No stdout or stderr was captured');
    expect(response.error?.diagnostics?.command).toBe(
      '/repo/cli-dev runtime providers view --runtime opencode --json --compact'
    );
    expect(response.error?.diagnostics?.stdoutPreview).toBeNull();
    expect(response.error?.diagnostics?.stderrPreview).toBeNull();
  });

  it('keeps stderr diagnostics when a zero-exit command prints malformed stdout', async () => {
    execCliMock.mockResolvedValue({
      stdout: 'not json',
      stderr: 'warning: api_key: sk-secret-value-123456\n',
    });

    const client = new AgentTeamsRuntimeProviderManagementCliClient();
    const response = await client.loadView({
      runtimeId: 'opencode',
    });

    expect(response.error?.message).toContain('stderr preview:');
    expect(response.error?.message).toContain('warning: api_key: ...redacted');
    expect(response.error?.message).not.toContain('sk-secret-value-123456');
    expect(response.error?.diagnostics?.stdoutPreview).toBe('not json');
    expect(response.error?.diagnostics?.stderrPreview).toBe('warning: api_key: ...redacted');
  });

  it('returns structured diagnostics when the runtime binary cannot be resolved', async () => {
    resolveBinaryMock.mockResolvedValue(null);

    const client = new AgentTeamsRuntimeProviderManagementCliClient();
    const response = await client.loadView({
      runtimeId: 'opencode',
      projectPath: '/Users/test/project',
    });

    expect(response.error?.code).toBe('runtime-missing');
    expect(response.error?.message).toContain(
      'OpenCode provider settings could not find the Agent Teams runtime binary.'
    );
    expect(response.error?.diagnostics?.summary).toBe(
      'OpenCode provider settings could not find the Agent Teams runtime binary.'
    );
    expect(response.error?.diagnostics?.binaryPath).toBeNull();
    expect(response.error?.diagnostics?.command).toBeNull();
    expect(response.error?.diagnostics?.projectPath).toBe('/Users/test/project');
    expect(response.error?.diagnostics?.hints).toContain(
      'The expected binary is the Agent Teams runtime/orchestrator CLI, not the OpenCode CLI.'
    );
    expect(buildProviderAwareCliEnvMock).not.toHaveBeenCalled();
  });

  it('returns structured diagnostics for process errors without stdout or stderr', async () => {
    execCliMock.mockRejectedValue(
      new Error('spawn EACCES /repo/cli-dev with api_key: sk-secret-value-123456')
    );

    const client = new AgentTeamsRuntimeProviderManagementCliClient();
    const response = await client.loadView({
      runtimeId: 'opencode',
      projectPath: '/Users/test/project',
    });

    expect(response.error?.message).toContain(
      'OpenCode provider settings could not run the runtime command.'
    );
    expect(response.error?.message).toContain(
      'Error:\nspawn EACCES /repo/cli-dev with api_key: ...redacted'
    );
    expect(response.error?.message).not.toContain('sk-secret-value-123456');
    expect(response.error?.diagnostics?.command).toBe(
      '/repo/cli-dev runtime providers view --runtime opencode --json --compact --project-path /Users/test/project'
    );
    expect(response.error?.diagnostics?.stderrPreview).toBe(
      'spawn EACCES /repo/cli-dev with api_key: ...redacted'
    );
  });

  it('returns structured diagnostics when provider directory loading times out', async () => {
    const error = new Error(
      'Command timed out after 45000ms: /repo/cli-dev runtime providers directory --runtime opencode --json'
    );
    Object.assign(error, {
      stdout: 'inventory started\n',
      stderr: 'OpenCode provider key=sk-secret-value-123456 still probing\n',
    });
    execCliMock.mockRejectedValue(error);

    const client = new AgentTeamsRuntimeProviderManagementCliClient();
    const response = await client.loadProviderDirectory({
      runtimeId: 'opencode',
      projectPath: '/Users/test/project',
      query: null,
      filter: 'all',
      limit: 50,
      cursor: null,
      refresh: false,
    });

    expect(response.error?.message).toContain(
      'OpenCode provider settings timed out while waiting for the Agent Teams runtime.'
    );
    expect(response.error?.message).toContain(
      'This is not enough evidence to conclude that OpenCode auth is missing.'
    );
    expect(response.error?.message).toContain('OpenCode provider key=...redacted');
    expect(response.error?.message).not.toContain('sk-secret-value-123456');
    expect(response.error?.diagnostics?.summary).toBe(
      'OpenCode provider settings timed out while waiting for the Agent Teams runtime.'
    );
    expect(response.error?.diagnostics?.command).toBe(
      '/repo/cli-dev runtime providers directory --runtime opencode --json --project-path /Users/test/project --filter all --limit 50'
    );
    expect(response.error?.diagnostics?.stderrPreview).toBe(
      'OpenCode provider key=...redacted still probing'
    );
    expect(response.error?.diagnostics?.stdoutPreview).toBe('inventory started');
    expect(response.error?.diagnostics?.hints).toContain(
      'If the runtime binary is stale, update Agent Teams so the runtime can return a degraded OpenCode diagnostic instead of timing out.'
    );
  });

  it('preserves runtime-side degraded JSON errors from rejected command output', async () => {
    const error = new Error('Command failed after runtime returned degraded JSON');
    Object.assign(error, {
      stdout: '',
      stderr: JSON.stringify({
        schemaVersion: 1,
        runtimeId: 'opencode',
        error: {
          code: 'runtime-unhealthy',
          message:
            'OpenCode inventory probe timed out after 12000ms during opencode providers list',
          recoverable: true,
          diagnostics: {
            summary: 'OpenCode inventory probe timed out',
            likelyCause: 'OpenCode providers list did not finish before the runtime budget.',
            command:
              '/repo/cli-dev runtime providers view --runtime opencode --json --compact',
            stderrPreview: 'provider api_key: sk-secret-value-123456',
            hints: ['Check OpenCode CLI startup and local OpenCode plugins.'],
          },
        },
      }),
    });
    execCliMock.mockRejectedValue(error);

    const client = new AgentTeamsRuntimeProviderManagementCliClient();
    const response = await client.loadView({
      runtimeId: 'opencode',
    });

    expect(response.error?.message).toBe(
      'OpenCode inventory probe timed out after 12000ms during opencode providers list'
    );
    expect(response.error?.diagnostics?.summary).toBe('OpenCode inventory probe timed out');
    expect(response.error?.diagnostics?.likelyCause).toBe(
      'OpenCode providers list did not finish before the runtime budget.'
    );
    expect(response.error?.diagnostics?.stderrPreview).toBe(
      'provider api_key: ...redacted'
    );
    expect(response.error?.diagnostics?.stderrPreview).not.toContain('sk-secret-value-123456');
    expect(response.error?.diagnostics?.hints).toContain(
      'Check OpenCode CLI startup and local OpenCode plugins.'
    );
  });

  it('preserves degraded JSON from stderr when stdout contains noisy logs', async () => {
    const error = new Error('Command failed after mixed runtime output');
    Object.assign(error, {
      stdout: 'runtime preflight log {not json}\n',
      stderr: JSON.stringify({
        schemaVersion: 1,
        runtimeId: 'opencode',
        error: {
          code: 'runtime-unhealthy',
          message:
            'OpenCode inventory probe timed out after 12000ms during opencode agent list',
          recoverable: true,
          diagnostics: {
            summary: 'OpenCode inventory probe timed out',
            likelyCause: 'OpenCode agent inventory did not finish before the runtime budget.',
            stderrPreview: 'agent token=sk-secret-value-123456',
            hints: ['Check OpenCode agent listing and local OpenCode plugins.'],
          },
        },
      }),
    });
    execCliMock.mockRejectedValue(error);

    const client = new AgentTeamsRuntimeProviderManagementCliClient();
    const response = await client.loadView({
      runtimeId: 'opencode',
    });

    expect(response.error?.message).toBe(
      'OpenCode inventory probe timed out after 12000ms during opencode agent list'
    );
    expect(response.error?.diagnostics?.likelyCause).toBe(
      'OpenCode agent inventory did not finish before the runtime budget.'
    );
    expect(response.error?.diagnostics?.stderrPreview).toBe(
      'agent token=...redacted'
    );
    expect(JSON.stringify(response.error?.diagnostics)).not.toContain('sk-secret-value-123456');
  });

  it('preserves degraded JSON printed to stdout before a desktop timeout', async () => {
    const error = new Error(
      'Command timed out after 45000ms: /repo/cli-dev runtime providers view --runtime opencode --json --compact'
    );
    Object.assign(error, {
      stdout: JSON.stringify({
        schemaVersion: 1,
        runtimeId: 'opencode',
        error: {
          code: 'runtime-unhealthy',
          message:
            'OpenCode inventory probe timed out after 12000ms during opencode models --verbose',
          recoverable: true,
          diagnostics: {
            summary: 'OpenCode inventory probe timed out',
            likelyCause: 'OpenCode model inventory did not finish before the runtime budget.',
            command:
              '/repo/cli-dev runtime providers view --runtime opencode --json --compact',
            stdoutPreview: 'model api_key: sk-secret-value-123456',
            hints: ['Check OpenCode model listing and local OpenCode plugins.'],
          },
        },
      }),
      stderr: 'outer timeout after runtime json\n',
    });
    execCliMock.mockRejectedValue(error);

    const client = new AgentTeamsRuntimeProviderManagementCliClient();
    const response = await client.loadView({
      runtimeId: 'opencode',
    });

    expect(response.error?.message).toBe(
      'OpenCode inventory probe timed out after 12000ms during opencode models --verbose'
    );
    expect(response.error?.diagnostics?.summary).toBe('OpenCode inventory probe timed out');
    expect(response.error?.diagnostics?.likelyCause).toBe(
      'OpenCode model inventory did not finish before the runtime budget.'
    );
    expect(response.error?.diagnostics?.stdoutPreview).toBe(
      'model api_key: ...redacted'
    );
    expect(JSON.stringify(response.error?.diagnostics)).not.toContain('sk-secret-value-123456');
  });

  it('parses the runtime JSON response after noisy brace logs', async () => {
    const validResponse = {
      schemaVersion: 1,
      runtimeId: 'opencode',
      view: {
        runtimeId: 'opencode',
        title: 'OpenCode',
        runtime: {
          state: 'ready',
          cliPath: '/opt/homebrew/bin/opencode',
          version: '1.15.6',
          managedProfile: 'active',
          localAuth: 'synced',
        },
        providers: [],
        defaultModel: null,
        fallbackModel: null,
        diagnostics: [],
      },
    };
    execCliMock.mockResolvedValue({
      stdout: `debug {"noise":true}\n${JSON.stringify(validResponse)}\n`,
      stderr: '',
    });

    const client = new AgentTeamsRuntimeProviderManagementCliClient();
    const response = await client.loadView({
      runtimeId: 'opencode',
    });

    expect(response.error).toBeUndefined();
    expect(response.view?.runtime.state).toBe('ready');
    expect(response.view?.runtime.cliPath).toBe('/opt/homebrew/bin/opencode');
  });

  it('accepts successful runtime responses that include an explicit null error field', async () => {
    execCliMock.mockResolvedValue({
      stdout: JSON.stringify({
        schemaVersion: 1,
        runtimeId: 'opencode',
        error: null,
        view: {
          runtimeId: 'opencode',
          title: 'OpenCode',
          runtime: {
            state: 'ready',
            cliPath: '/opt/homebrew/bin/opencode',
            version: '1.15.6',
            managedProfile: 'active',
            localAuth: 'synced',
          },
          providers: [],
          defaultModel: null,
          fallbackModel: null,
          diagnostics: [],
        },
      }),
      stderr: '',
    });

    const client = new AgentTeamsRuntimeProviderManagementCliClient();
    const response = await client.loadView({
      runtimeId: 'opencode',
    });

    expect(response.error).toBeUndefined();
    expect(response.view?.runtime.state).toBe('ready');
  });

  it('skips contract-looking noise that does not include a response payload', async () => {
    const validResponse = {
      schemaVersion: 1,
      runtimeId: 'opencode',
      view: {
        runtimeId: 'opencode',
        title: 'OpenCode',
        runtime: {
          state: 'ready',
          cliPath: '/opt/homebrew/bin/opencode',
          version: '1.15.6',
          managedProfile: 'active',
          localAuth: 'synced',
        },
        providers: [],
        defaultModel: null,
        fallbackModel: null,
        diagnostics: [],
      },
    };
    execCliMock.mockResolvedValue({
      stdout: [
        JSON.stringify({
          schemaVersion: 1,
          runtimeId: 'opencode',
          debug: 'preflight',
        }),
        JSON.stringify(validResponse),
      ].join('\n'),
      stderr: '',
    });

    const client = new AgentTeamsRuntimeProviderManagementCliClient();
    const response = await client.loadView({
      runtimeId: 'opencode',
    });

    expect(response.error).toBeUndefined();
    expect(response.view?.runtime.state).toBe('ready');
    expect(response.view?.title).toBe('OpenCode');
  });

  it('does not treat JSON logs without a response payload as a successful runtime response', async () => {
    execCliMock.mockResolvedValue({
      stdout: JSON.stringify({
        schemaVersion: 1,
        runtimeId: 'opencode',
        debug: 'preflight',
      }),
      stderr: '',
    });

    const client = new AgentTeamsRuntimeProviderManagementCliClient();
    const response = await client.loadView({
      runtimeId: 'opencode',
    });

    expect(response.error?.message).toContain(
      'OpenCode provider settings could not read the runtime response.'
    );
    expect(response.error?.diagnostics?.stdoutPreview).toContain('"debug":"preflight"');
    expect(response.view).toBeUndefined();
  });

  it('does not treat malformed view payloads as successful runtime responses', async () => {
    execCliMock.mockResolvedValue({
      stdout: JSON.stringify({
        schemaVersion: 1,
        runtimeId: 'opencode',
        view: {
          runtimeId: 'opencode',
          title: 'OpenCode',
        },
      }),
      stderr: '',
    });

    const client = new AgentTeamsRuntimeProviderManagementCliClient();
    const response = await client.loadView({
      runtimeId: 'opencode',
    });

    expect(response.error?.message).toContain(
      'OpenCode provider settings could not read the runtime response.'
    );
    expect(response.error?.diagnostics?.stdoutPreview).toContain('"title":"OpenCode"');
    expect(response.view).toBeUndefined();
  });

  it('does not pass malformed provider entries to the renderer', async () => {
    execCliMock.mockResolvedValue({
      stdout: JSON.stringify({
        schemaVersion: 1,
        runtimeId: 'opencode',
        view: {
          runtimeId: 'opencode',
          title: 'OpenCode',
          runtime: {
            state: 'ready',
            cliPath: '/opt/homebrew/bin/opencode',
            version: '1.15.6',
            managedProfile: 'active',
            localAuth: 'synced',
          },
          providers: [
            {
              providerId: 'openrouter',
              displayName: 'OpenRouter',
              state: 'connected',
              ownership: ['managed'],
              recommended: true,
              modelCount: 4,
              defaultModelId: null,
              authMethods: ['api'],
              detail: null,
            },
          ],
          defaultModel: null,
          fallbackModel: null,
          diagnostics: [],
        },
      }),
      stderr: '',
    });

    const client = new AgentTeamsRuntimeProviderManagementCliClient();
    const response = await client.loadView({
      runtimeId: 'opencode',
    });

    expect(response.error?.message).toContain(
      'OpenCode provider settings could not read the runtime response.'
    );
    expect(response.view).toBeUndefined();
  });

  it('parses JSON error responses from stdout when the CLI exits non-zero', async () => {
    const error = new Error('Command failed: /repo/cli-dev runtime providers test-model');
    Object.assign(error, {
      stdout: JSON.stringify({
        schemaVersion: 1,
        runtimeId: 'opencode',
        error: {
          code: 'auth-required',
          message: 'Provider opencode must be connected before testing a model',
          recoverable: true,
        },
      }),
      stderr: '',
    });
    execCliMock.mockRejectedValue(error);

    const client = new AgentTeamsRuntimeProviderManagementCliClient();
    const response = await client.testModel({
      runtimeId: 'opencode',
      providerId: 'opencode',
      modelId: 'opencode/nemotron-3-super-free',
    });

    expect(response.error?.code).toBe('auth-required');
    expect(response.error?.message).toBe(
      'Provider opencode must be connected before testing a model'
    );
  });

  it('redacts secrets from structured JSON error responses returned by the runtime', async () => {
    const error = new Error('Command failed: /repo/cli-dev runtime providers view');
    Object.assign(error, {
      stdout: JSON.stringify({
        schemaVersion: 1,
        runtimeId: 'opencode',
        error: {
          code: 'auth-failed',
          message: 'Provider failed with api_key: sk-secret-value-123456',
          recoverable: true,
          diagnostics: {
            summary: 'Auth failed for sk-secret-value-123456',
            likelyCause: 'Authorization: Bearer live-token-123456789 was rejected',
            binaryPath: '/repo/cli-dev',
            command: '/repo/cli-dev runtime providers view',
            projectPath: null,
            exitCode: 1,
            stderrPreview: 'api_key: sk-secret-value-123456',
            stdoutPreview: 'Authorization: Bearer live-token-123456789',
            hints: ['Remove sk-secret-value-123456 from config output.'],
          },
        },
      }),
      stderr: '',
    });
    execCliMock.mockRejectedValue(error);

    const client = new AgentTeamsRuntimeProviderManagementCliClient();
    const response = await client.loadView({
      runtimeId: 'opencode',
    });
    const serialized = JSON.stringify(response);

    expect(response.error?.message).toContain('api_key: ...redacted');
    expect(response.error?.diagnostics?.summary).toBe('Auth failed for sk-...redacted');
    expect(response.error?.diagnostics?.errorCode).toBe('auth-failed');
    expect(response.error?.diagnostics?.likelyCause).toBe(
      'Authorization: Bearer ...redacted was rejected'
    );
    expect(response.error?.diagnostics?.stderrPreview).toBe('api_key: ...redacted');
    expect(response.error?.diagnostics?.stdoutPreview).toBe(
      'Authorization: Bearer ...redacted'
    );
    expect(response.error?.diagnostics?.hints[0]).toBe(
      'Remove sk-...redacted from config output.'
    );
    expect(serialized).not.toContain('sk-secret-value-123456');
    expect(serialized).not.toContain('live-token-123456789');
  });

  it('redacts secrets from successful runtime diagnostics before they reach the renderer', async () => {
    execCliMock.mockResolvedValue({
      stdout: JSON.stringify({
        schemaVersion: 1,
        runtimeId: 'opencode',
        view: {
          runtimeId: 'opencode',
          title: 'OpenCode',
          runtime: {
            state: 'ready',
            cliPath: '/opt/homebrew/bin/opencode',
            version: '1.15.6',
            managedProfile: 'active',
            localAuth: 'synced',
          },
          providers: [
            {
              providerId: 'openrouter',
              displayName: 'OpenRouter',
              state: 'connected',
              ownership: ['managed'],
              recommended: true,
              modelCount: 4,
              defaultModelId: null,
              authMethods: ['api'],
              actions: [],
              detail: 'Connected with api_key: sk-secret-value-123456',
            },
          ],
          defaultModel: null,
          fallbackModel: null,
          diagnostics: [
            'Authorization: Bearer live-token-123456789',
            '\u001B[31mapi_key: sk-secret-value-123456\u001B[0m',
          ],
        },
      }),
      stderr: '',
    });

    const client = new AgentTeamsRuntimeProviderManagementCliClient();
    const response = await client.loadView({
      runtimeId: 'opencode',
    });
    const serialized = JSON.stringify(response);

    expect(response.view?.diagnostics).toEqual([
      'Authorization: Bearer ...redacted',
      'api_key: ...redacted',
    ]);
    expect(response.view?.providers[0]?.detail).toBe('Connected with api_key: ...redacted');
    expect(serialized).not.toContain('sk-secret-value-123456');
    expect(serialized).not.toContain('live-token-123456789');
    expect(serialized).not.toContain('[31m');
  });

  it('keeps structured runtime errors when optional diagnostic fields are malformed', async () => {
    const error = new Error('Command failed: /repo/cli-dev runtime providers view');
    Object.assign(error, {
      stdout: JSON.stringify({
        schemaVersion: 1,
        runtimeId: 'opencode',
        error: {
          code: 'runtime-unhealthy',
          message: 'Runtime returned malformed diagnostics',
          recoverable: true,
          diagnostics: {
            summary: 'Runtime returned malformed diagnostics',
            likelyCause: null,
            binaryPath: '/repo/cli-dev',
            command: '/repo/cli-dev runtime providers view',
            projectPath: null,
            exitCode: '1',
            stderrPreview: null,
            stdoutPreview: null,
          },
        },
      }),
      stderr: '',
    });
    execCliMock.mockRejectedValue(error);

    const client = new AgentTeamsRuntimeProviderManagementCliClient();
    const response = await client.loadView({
      runtimeId: 'opencode',
    });

    expect(response.error?.message).toBe('Runtime returned malformed diagnostics');
    expect(response.error?.diagnostics?.summary).toBe('Runtime returned malformed diagnostics');
    expect(response.error?.diagnostics?.exitCode).toBeNull();
    expect(response.error?.diagnostics?.hints).toEqual([]);
  });

  it('normalizes malformed structured runtime error objects instead of leaking them to the renderer', async () => {
    const error = new Error('Command failed: /repo/cli-dev runtime providers view');
    Object.assign(error, {
      stdout: JSON.stringify({
        schemaVersion: 1,
        runtimeId: 'opencode',
        error: {
          code: 'not-a-real-code',
          message: 123,
          recoverable: 'yes',
          diagnostics: {
            summary: 'api_key: sk-secret-value-123456',
          },
        },
      }),
      stderr: '',
    });
    execCliMock.mockRejectedValue(error);

    const client = new AgentTeamsRuntimeProviderManagementCliClient();
    const response = await client.loadView({
      runtimeId: 'opencode',
    });

    expect(response.error?.code).toBe('runtime-unhealthy');
    expect(response.error?.message).toBe('Runtime provider management command failed');
    expect(response.error?.diagnostics?.summary).toBe('api_key: ...redacted');
    expect(JSON.stringify(response)).not.toContain('sk-secret-value-123456');
  });

  it('adds actionable diagnostics for OpenCode managed profile node_modules symlink failures', async () => {
    const runtimeMessage = [
      'Runtime provider management command failed unexpectedly:',
      "EPERM: operation not permitted, symlink 'C:\\Users\\Swarog\\AppData\\Local\\claude-multimodel-nodejs\\Cache\\opencode\\shared-cache\\config-node_modules'",
      "-> 'C:\\Users\\Swarog\\AppData\\Local\\claude-multimodel-nodejs\\Data\\opencode\\profiles\\abc123\\config\\opencode\\node_modules'",
    ].join(' ');
    const error = new Error('Command failed: /repo/cli-dev runtime providers view');
    Object.assign(error, {
      stdout: JSON.stringify({
        schemaVersion: 1,
        runtimeId: 'opencode',
        error: {
          code: 'runtime-unhealthy',
          message: runtimeMessage,
          recoverable: true,
        },
      }),
      stderr: '',
    });
    execCliMock.mockRejectedValue(error);

    const client = new AgentTeamsRuntimeProviderManagementCliClient();
    const response = await client.loadView({
      runtimeId: 'opencode',
    });

    expect(response.error?.message).toBe(runtimeMessage);
    expect(response.error?.diagnostics?.summary).toBe(
      'OpenCode managed profile node_modules link was blocked.'
    );
    expect(response.error?.diagnostics?.likelyCause).toContain(
      'Windows denied creating the managed OpenCode profile node_modules link'
    );
    expect(response.error?.diagnostics?.stderrPreview).toBe(runtimeMessage);
    expect(response.error?.diagnostics?.hints).toEqual(
      expect.arrayContaining([
        'The app attempts automatic junction fallback for this Windows link failure before showing this error.',
        'As a temporary workaround, enable Windows Developer Mode or run Agent Teams AI as Administrator.',
      ])
    );
  });

  it('attempts junction pre-seed and retry on Windows when EPERM symlink error is detected in loadView', async () => {
    const runtimeMessage = [
      'Runtime provider management command failed unexpectedly:',
      "EPERM: operation not permitted, symlink 'C:\\Users\\test\\AppData\\Local\\claude-multimodel-nodejs\\Cache\\opencode\\shared-cache\\config-node_modules'",
      "-> 'C:\\Users\\test\\AppData\\Local\\claude-multimodel-nodejs\\Data\\opencode\\profiles\\abc123\\config\\opencode\\node_modules'",
    ].join(' ');
    const firstError = new Error('Command failed: /repo/cli-dev runtime providers view');
    Object.assign(firstError, {
      stdout: JSON.stringify({
        schemaVersion: 1,
        runtimeId: 'opencode',
        error: { code: 'runtime-unhealthy', message: runtimeMessage, recoverable: true },
      }),
      stderr: '',
    });

    const successResponse = {
      schemaVersion: 1,
      runtimeId: 'opencode',
      view: {
        runtimeId: 'opencode',
        title: 'OpenCode',
        runtime: { state: 'ready', cliPath: '/repo/cli-dev', version: '1.15.6', managedProfile: 'active', localAuth: 'synced' },
        providers: [],
        defaultModel: null,
        fallbackModel: null,
        diagnostics: [],
      },
    };

    execCliMock
      .mockRejectedValueOnce(firstError)
      .mockResolvedValueOnce({ stdout: JSON.stringify(successResponse), stderr: '' });

    const originalPlatform = process.platform;
    Object.defineProperty(process, 'platform', { value: 'win32' });
    (isOpenCodeNodeModulesSymlinkErrorMock as ReturnType<typeof vi.fn>).mockReturnValue(true);
    (extractProfileIdFromSymlinkErrorMock as ReturnType<typeof vi.fn>).mockReturnValue('abc123');
    (ensureOpenCodeProfileNodeModulesJunctionMock as ReturnType<typeof vi.fn>).mockReturnValue(true);

    try {
      const client = new AgentTeamsRuntimeProviderManagementCliClient();
      const response = await client.loadView({ runtimeId: 'opencode' });

      expect(ensureOpenCodeProfileNodeModulesJunctionMock).toHaveBeenCalledWith('abc123', expect.any(String));
      expect(execCliMock).toHaveBeenCalledTimes(2);
      expect(response.error).toBeUndefined();
      expect(response.view?.runtime?.state).toBe('ready');
    } finally {
      Object.defineProperty(process, 'platform', { value: originalPlatform });
      vi.mocked(isOpenCodeNodeModulesSymlinkErrorMock).mockRestore();
      vi.mocked(extractProfileIdFromSymlinkErrorMock).mockRestore();
      vi.mocked(ensureOpenCodeProfileNodeModulesJunctionMock).mockRestore();
    }
  });

  it('falls back to error response when junction pre-seed succeeds but retry also fails in loadView', async () => {
    const runtimeMessage = [
      'Runtime provider management command failed unexpectedly:',
      "EPERM: operation not permitted, symlink 'C:\\Users\\test\\AppData\\Local\\claude-multimodel-nodejs\\Cache\\opencode\\shared-cache\\config-node_modules'",
      "-> 'C:\\Users\\test\\AppData\\Local\\claude-multimodel-nodejs\\Data\\opencode\\profiles\\abc123\\config\\opencode\\node_modules'",
    ].join(' ');
    const error = new Error('Command failed: /repo/cli-dev runtime providers view');
    Object.assign(error, {
      stdout: JSON.stringify({
        schemaVersion: 1,
        runtimeId: 'opencode',
        error: { code: 'runtime-unhealthy', message: runtimeMessage, recoverable: true },
      }),
      stderr: '',
    });

    execCliMock.mockRejectedValue(error);

    const originalPlatform = process.platform;
    Object.defineProperty(process, 'platform', { value: 'win32' });
    (isOpenCodeNodeModulesSymlinkErrorMock as ReturnType<typeof vi.fn>).mockReturnValue(true);
    (extractProfileIdFromSymlinkErrorMock as ReturnType<typeof vi.fn>).mockReturnValue('abc123');
    (ensureOpenCodeProfileNodeModulesJunctionMock as ReturnType<typeof vi.fn>).mockReturnValue(true);

    try {
      const client = new AgentTeamsRuntimeProviderManagementCliClient();
      const response = await client.loadView({ runtimeId: 'opencode' });

      expect(ensureOpenCodeProfileNodeModulesJunctionMock).toHaveBeenCalledWith('abc123', expect.any(String));
      expect(execCliMock).toHaveBeenCalledTimes(2);
      expect(response.error?.message).toBe(runtimeMessage);
    } finally {
      Object.defineProperty(process, 'platform', { value: originalPlatform });
      vi.mocked(isOpenCodeNodeModulesSymlinkErrorMock).mockRestore();
      vi.mocked(extractProfileIdFromSymlinkErrorMock).mockRestore();
      vi.mocked(ensureOpenCodeProfileNodeModulesJunctionMock).mockRestore();
    }
  });

  it('does not retry when junction pre-seed fails in loadView', async () => {
    const runtimeMessage = [
      'Runtime provider management command failed unexpectedly:',
      "EPERM: operation not permitted, symlink 'C:\\Users\\test\\AppData\\Local\\claude-multimodel-nodejs\\Cache\\opencode\\shared-cache\\config-node_modules'",
      "-> 'C:\\Users\\test\\AppData\\Local\\claude-multimodel-nodejs\\Data\\opencode\\profiles\\abc123\\config\\opencode\\node_modules'",
    ].join(' ');
    const error = new Error('Command failed: /repo/cli-dev runtime providers view');
    Object.assign(error, {
      stdout: JSON.stringify({
        schemaVersion: 1,
        runtimeId: 'opencode',
        error: { code: 'runtime-unhealthy', message: runtimeMessage, recoverable: true },
      }),
      stderr: '',
    });

    execCliMock.mockRejectedValue(error);

    const originalPlatform = process.platform;
    Object.defineProperty(process, 'platform', { value: 'win32' });
    (isOpenCodeNodeModulesSymlinkErrorMock as ReturnType<typeof vi.fn>).mockReturnValue(true);
    (extractProfileIdFromSymlinkErrorMock as ReturnType<typeof vi.fn>).mockReturnValue('abc123');
    (ensureOpenCodeProfileNodeModulesJunctionMock as ReturnType<typeof vi.fn>).mockReturnValue(false);

    try {
      const client = new AgentTeamsRuntimeProviderManagementCliClient();
      const response = await client.loadView({ runtimeId: 'opencode' });

      expect(ensureOpenCodeProfileNodeModulesJunctionMock).toHaveBeenCalledWith('abc123', expect.any(String));
      expect(execCliMock).toHaveBeenCalledTimes(1);
      expect(response.error?.message).toBe(runtimeMessage);
    } finally {
      Object.defineProperty(process, 'platform', { value: originalPlatform });
      vi.mocked(isOpenCodeNodeModulesSymlinkErrorMock).mockRestore();
      vi.mocked(extractProfileIdFromSymlinkErrorMock).mockRestore();
      vi.mocked(ensureOpenCodeProfileNodeModulesJunctionMock).mockRestore();
    }
  });

  it('does not attempt junction retry on non-Windows platforms in loadView', async () => {
    const runtimeMessage = [
      'Runtime provider management command failed unexpectedly:',
      "EPERM: operation not permitted, symlink 'opencode' -> 'node_modules'",
    ].join(' ');
    const error = new Error('Command failed: /repo/cli-dev runtime providers view');
    Object.assign(error, {
      stdout: JSON.stringify({
        schemaVersion: 1,
        runtimeId: 'opencode',
        error: { code: 'runtime-unhealthy', message: runtimeMessage, recoverable: true },
      }),
      stderr: '',
    });

    execCliMock.mockRejectedValue(error);

    const originalPlatform = process.platform;
    Object.defineProperty(process, 'platform', { value: 'darwin' });
    (isOpenCodeNodeModulesSymlinkErrorMock as ReturnType<typeof vi.fn>).mockReturnValue(true);
    (extractProfileIdFromSymlinkErrorMock as ReturnType<typeof vi.fn>).mockReturnValue('abc123');

    try {
      const client = new AgentTeamsRuntimeProviderManagementCliClient();
      const response = await client.loadView({ runtimeId: 'opencode' });

      expect(ensureOpenCodeProfileNodeModulesJunctionMock).not.toHaveBeenCalled();
      expect(execCliMock).toHaveBeenCalledTimes(1);
      expect(response.error?.message).toBe(runtimeMessage);
    } finally {
      Object.defineProperty(process, 'platform', { value: originalPlatform });
      vi.mocked(isOpenCodeNodeModulesSymlinkErrorMock).mockRestore();
      vi.mocked(extractProfileIdFromSymlinkErrorMock).mockRestore();
    }
  });

  it('attempts junction pre-seed and retry on Windows for loadProviderDirectory', async () => {
    const runtimeMessage = [
      'Runtime provider management command failed unexpectedly:',
      "EPERM: operation not permitted, symlink 'C:\\Users\\test\\AppData\\Local\\claude-multimodel-nodejs\\Cache\\opencode\\shared-cache\\config-node_modules'",
      "-> 'C:\\Users\\test\\AppData\\Local\\claude-multimodel-nodejs\\Data\\opencode\\profiles\\def456\\config\\opencode\\node_modules'",
    ].join(' ');
    const firstError = new Error('Command failed: /repo/cli-dev runtime providers directory');
    Object.assign(firstError, {
      stdout: '',
      stderr: runtimeMessage,
    });

    const successResponse = {
      schemaVersion: 1,
      runtimeId: 'opencode',
      directory: {
        runtimeId: 'opencode',
        totalCount: 0,
        returnedCount: 0,
        query: null,
        filter: 'all',
        limit: 50,
        cursor: null,
        nextCursor: null,
        entries: [],
        diagnostics: [],
        fetchedAt: new Date().toISOString(),
      },
    };

    execCliMock
      .mockRejectedValueOnce(firstError)
      .mockResolvedValueOnce({ stdout: JSON.stringify(successResponse), stderr: '' });

    const originalPlatform = process.platform;
    Object.defineProperty(process, 'platform', { value: 'win32' });
    (isOpenCodeNodeModulesSymlinkErrorMock as ReturnType<typeof vi.fn>).mockReturnValue(true);
    (extractProfileIdFromSymlinkErrorMock as ReturnType<typeof vi.fn>).mockReturnValue('def456');
    (ensureOpenCodeProfileNodeModulesJunctionMock as ReturnType<typeof vi.fn>).mockReturnValue(true);

    try {
      const client = new AgentTeamsRuntimeProviderManagementCliClient();
      const response = await client.loadProviderDirectory({ runtimeId: 'opencode' });

      expect(ensureOpenCodeProfileNodeModulesJunctionMock).toHaveBeenCalledWith('def456', expect.any(String));
      expect(execCliMock).toHaveBeenCalledTimes(2);
      expect(response.directory?.entries).toEqual([]);
    } finally {
      Object.defineProperty(process, 'platform', { value: originalPlatform });
      vi.mocked(isOpenCodeNodeModulesSymlinkErrorMock).mockRestore();
      vi.mocked(extractProfileIdFromSymlinkErrorMock).mockRestore();
      vi.mocked(ensureOpenCodeProfileNodeModulesJunctionMock).mockRestore();
    }
  });

  it('does not let non-object error logs shadow a later valid runtime response', async () => {
    const validResponse = {
      schemaVersion: 1,
      runtimeId: 'opencode',
      view: {
        runtimeId: 'opencode',
        title: 'OpenCode',
        runtime: {
          state: 'ready',
          cliPath: '/opt/homebrew/bin/opencode',
          version: '1.15.6',
          managedProfile: 'active',
          localAuth: 'synced',
        },
        providers: [],
        defaultModel: null,
        fallbackModel: null,
        diagnostics: [],
      },
    };
    execCliMock.mockResolvedValue({
      stdout: [
        JSON.stringify({
          schemaVersion: 1,
          runtimeId: 'opencode',
          error: 'debug preflight',
        }),
        JSON.stringify(validResponse),
      ].join('\n'),
      stderr: '',
    });

    const client = new AgentTeamsRuntimeProviderManagementCliClient();
    const response = await client.loadView({
      runtimeId: 'opencode',
    });

    expect(response.error).toBeUndefined();
    expect(response.view?.runtime.state).toBe('ready');
  });

  it('does not let non-contract error object logs shadow a later valid runtime response', async () => {
    const validResponse = {
      schemaVersion: 1,
      runtimeId: 'opencode',
      view: {
        runtimeId: 'opencode',
        title: 'OpenCode',
        runtime: {
          state: 'ready',
          cliPath: '/opt/homebrew/bin/opencode',
          version: '1.15.6',
          managedProfile: 'active',
          localAuth: 'synced',
        },
        providers: [],
        defaultModel: null,
        fallbackModel: null,
        diagnostics: [],
      },
    };
    execCliMock.mockResolvedValue({
      stdout: [
        JSON.stringify({
          schemaVersion: 1,
          runtimeId: 'opencode',
          error: { debug: true },
        }),
        JSON.stringify(validResponse),
      ].join('\n'),
      stderr: '',
    });

    const client = new AgentTeamsRuntimeProviderManagementCliClient();
    const response = await client.loadView({
      runtimeId: 'opencode',
    });

    expect(response.error).toBeUndefined();
    expect(response.view?.runtime.state).toBe('ready');
  });

  it('parses JSON error responses from failed forget commands', async () => {
    const error = new Error('Command failed: /repo/cli-dev runtime providers forget');
    Object.assign(error, {
      stdout: JSON.stringify({
        schemaVersion: 1,
        runtimeId: 'opencode',
        error: {
          code: 'unsupported-action',
          message: 'This OpenCode runtime does not advertise credential removal through /doc',
          recoverable: true,
        },
      }),
      stderr: '',
    });
    execCliMock.mockRejectedValue(error);

    const client = new AgentTeamsRuntimeProviderManagementCliClient();
    const response = await client.forgetCredential({
      runtimeId: 'opencode',
      providerId: 'openrouter',
    });

    expect(response.error?.code).toBe('unsupported-action');
    expect(response.error?.message).toBe(
      'This OpenCode runtime does not advertise credential removal through /doc'
    );
  });

  it('rejects the OpenCode CLI binary before running runtime provider commands', async () => {
    resolveBinaryMock.mockResolvedValue('/opt/homebrew/bin/opencode');
    execCliMock.mockResolvedValue({
      stdout: JSON.stringify({ shouldNotRun: true }),
      stderr: '',
    });

    const client = new AgentTeamsRuntimeProviderManagementCliClient();
    const response = await client.loadView({
      runtimeId: 'opencode',
      projectPath: '/Users/test/My Project',
    });

    expect(execCliMock).not.toHaveBeenCalled();
    expect(buildProviderAwareCliEnvMock).not.toHaveBeenCalled();
    expect(clearBinaryCacheMock).toHaveBeenCalledTimes(1);
    expect(response.error?.code).toBe('runtime-misconfigured');
    expect(response.error?.message).toContain(
      'OpenCode provider settings are using the wrong runtime binary.'
    );
    expect(response.error?.message).toContain(
      'Command that was blocked: /opt/homebrew/bin/opencode runtime providers view --runtime opencode --json --compact --project-path'
    );
    expect(response.error?.message).toContain(
      'The app resolved the OpenCode CLI itself as the Agent Teams runtime binary.'
    );
    expect(response.error?.diagnostics?.errorCode).toBe('runtime-misconfigured');
    expect(response.error?.diagnostics?.binaryPath).toBe('/opt/homebrew/bin/opencode');
    expect(response.error?.diagnostics?.command).toBe(
      "/opt/homebrew/bin/opencode runtime providers view --runtime opencode --json --compact --project-path '/Users/test/My Project'"
    );
    expect(response.error?.diagnostics?.projectPath).toBe('/Users/test/My Project');
    expect(response.error?.diagnostics?.stdoutPreview).toBeNull();
    expect(response.error?.diagnostics?.stderrPreview).toBeNull();
    expect(response.error?.diagnostics?.hints).toContain(
      'Those environment variables must not point to opencode.'
    );
  });

  it('rejects runtime symlinks that resolve to the OpenCode CLI binary', async () => {
    const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'opencode-runtime-'));
    const opencodeTarget = path.join(tempDir, 'opencode');
    const runtimeLink = path.join(tempDir, 'claude-multimodel');
    try {
      fs.writeFileSync(opencodeTarget, '#!/bin/sh\n');
      fs.symlinkSync(opencodeTarget, runtimeLink);
      resolveBinaryMock.mockResolvedValue(runtimeLink);

      const client = new AgentTeamsRuntimeProviderManagementCliClient();
      const response = await client.loadView({
        runtimeId: 'opencode',
      });

      expect(execCliMock).not.toHaveBeenCalled();
      expect(buildProviderAwareCliEnvMock).not.toHaveBeenCalled();
      expect(clearBinaryCacheMock).toHaveBeenCalledTimes(1);
      expect(response.error?.code).toBe('runtime-misconfigured');
      expect(response.error?.diagnostics?.binaryPath).toBe(runtimeLink);
      expect(response.error?.message).toContain(
        'OpenCode provider settings are using the wrong runtime binary.'
      );
    } finally {
      fs.rmSync(tempDir, { recursive: true, force: true });
    }
  });

  it('rejects OpenCode CLI connect commands before spawning or writing secrets', async () => {
    resolveBinaryMock.mockResolvedValue('/opt/homebrew/bin/opencode.cmd');

    const client = new AgentTeamsRuntimeProviderManagementCliClient();
    const response = await client.connectProvider({
      runtimeId: 'opencode',
      providerId: 'openrouter',
      method: 'api',
      apiKey: 'sk-secret-value-123456',
      metadata: {
        region: 'us',
      },
      projectPath: '/Users/test/project',
    });

    expect(spawnCliMock).not.toHaveBeenCalled();
    expect(buildProviderAwareCliEnvMock).not.toHaveBeenCalled();
    expect(clearBinaryCacheMock).toHaveBeenCalledTimes(1);
    expect(response.error?.code).toBe('runtime-misconfigured');
    expect(response.error?.diagnostics?.binaryPath).toBe('/opt/homebrew/bin/opencode.cmd');
    expect(response.error?.diagnostics?.command).toBe(
      '/opt/homebrew/bin/opencode.cmd runtime providers connect --runtime opencode --provider openrouter --stdin-json --json --project-path /Users/test/project'
    );
    expect(JSON.stringify(response)).not.toContain('sk-secret-value-123456');
  });

  it('does not reject valid orchestrator paths that only contain opencode in a parent directory', async () => {
    resolveBinaryMock.mockResolvedValue('/repo/opencode-runtime/cli-source');
    execCliMock.mockResolvedValue({
      stdout: JSON.stringify({
        schemaVersion: 1,
        runtimeId: 'opencode',
        view: {
          runtimeId: 'opencode',
          title: 'OpenCode',
          runtime: {
            state: 'ready',
            cliPath: '/opt/homebrew/bin/opencode',
            version: '1.15.6',
            managedProfile: 'active',
            localAuth: 'synced',
          },
          providers: [],
          defaultModel: null,
          fallbackModel: null,
          diagnostics: [],
        },
      }),
      stderr: '',
    });

    const client = new AgentTeamsRuntimeProviderManagementCliClient();
    const response = await client.loadView({
      runtimeId: 'opencode',
    });

    expect(response.error).toBeUndefined();
    expect(response.view?.runtime.cliPath).toBe('/opt/homebrew/bin/opencode');
    expect(execCliMock).toHaveBeenCalledWith(
      '/repo/opencode-runtime/cli-source',
      expect.arrayContaining(['runtime', 'providers', 'view']),
      expect.any(Object)
    );
    expect(execCliMock.mock.calls[0]?.[2]).toMatchObject({ timeout: 90_000 });
  });

  it('explains OpenCode CLI help output instead of returning a generic JSON error', async () => {
    execCliMock.mockResolvedValue({
      stdout: [
        'Usage: opencode [command]',
        '',
        'Commands:',
        '  opencode providers',
        '  opencode models',
        'api_key: sk-secret-value-123456',
      ].join('\n'),
      stderr: '',
    });

    const client = new AgentTeamsRuntimeProviderManagementCliClient();
    const response = await client.loadView({
      runtimeId: 'opencode',
      projectPath: '/Users/test/My Project',
    });

    expect(response.error?.message).toContain(
      'OpenCode provider settings could not read the runtime response.'
    );
    expect(response.error?.message).toContain(
      'Expected a JSON object from the Agent Teams runtime provider command.'
    );
    expect(response.error?.message).toContain(
      'Resolved runtime binary: /repo/cli-dev'
    );
    expect(response.error?.message).toContain(
      "Command: /repo/cli-dev runtime providers view --runtime opencode --json --compact --project-path '/Users/test/My Project'"
    );
    expect(response.error?.message).toContain(
      'Likely cause: The app is launching the OpenCode CLI itself instead of the Agent Teams runtime'
    );
    expect(response.error?.message).toContain('CLAUDE_AGENT_TEAMS_ORCHESTRATOR_CLI_PATH');
    expect(response.error?.message).toContain('stdout preview:');
    expect(response.error?.message).toContain('opencode providers');
    expect(response.error?.message).not.toContain('sk-secret-value-123456');
    expect(response.error?.message).toContain('api_key: ...redacted');
    expect(response.error?.diagnostics?.binaryPath).toBe('/repo/cli-dev');
    expect(response.error?.diagnostics?.command).toBe(
      "/repo/cli-dev runtime providers view --runtime opencode --json --compact --project-path '/Users/test/My Project'"
    );
    expect(response.error?.diagnostics?.projectPath).toBe('/Users/test/My Project');
    expect(response.error?.diagnostics?.likelyCause).toContain('OpenCode CLI itself');
    expect(response.error?.diagnostics?.hints).toContain(
      'Those environment variables must not point to opencode.'
    );
    expect(response.error?.diagnostics?.stdoutPreview).toContain('api_key: ...redacted');
    expect(response.error?.diagnostics?.stdoutPreview).not.toContain('sk-secret-value-123456');
  });

  it('formats non-JSON spawn output with exit code and stderr preview', async () => {
    const { child } = createSpawnProcess('not-json', 1);
    const processEvents = new EventEmitter();
    const stdinEvents = new EventEmitter();
    const stdout = new EventEmitter();
    const stderr = new EventEmitter();
    const stdinWrite = vi.fn();
    const stdinEnd = vi.fn(() => {
      queueMicrotask(() => {
        stdout.emit('data', Buffer.from('not-json'));
        stderr.emit('data', Buffer.from('runtime crashed before JSON'));
        processEvents.emit('close', 1);
      });
    });
    spawnCliMock.mockReturnValue({
      ...child,
      stdout,
      stderr,
      stdin: {
        write: stdinWrite,
        end: stdinEnd,
        once: stdinEvents.once.bind(stdinEvents),
      },
      once: processEvents.once.bind(processEvents),
    });

    const client = new AgentTeamsRuntimeProviderManagementCliClient();
    const response = await client.connectProvider({
      runtimeId: 'opencode',
      providerId: 'openrouter',
      method: 'api',
      apiKey: 'sk-secret-value-123456',
      metadata: {},
    });

    expect(response.error?.message).toContain('Exit code: 1');
    expect(response.error?.message).toContain('stderr preview:');
    expect(response.error?.message).toContain('runtime crashed before JSON');
    expect(response.error?.message).toContain('stdout preview:');
    expect(response.error?.message).toContain('not-json');
    expect(response.error?.diagnostics?.exitCode).toBe(1);
    expect(response.error?.diagnostics?.stderrPreview).toBe('runtime crashed before JSON');
    expect(response.error?.diagnostics?.stdoutPreview).toBe('not-json');
    expect(stdinWrite).toHaveBeenCalledWith(
      JSON.stringify({
        method: 'api',
        apiKey: 'sk-secret-value-123456',
        metadata: {},
      })
    );
  });

  it('captures provider stdin errors without dropping runtime diagnostics', async () => {
    const processEvents = new EventEmitter();
    const stdinEvents = new EventEmitter();
    const stdout = new EventEmitter();
    const stderr = new EventEmitter();
    const stdinWrite = vi.fn(() => {
      queueMicrotask(() => {
        stdinEvents.emit('error', new Error('write EPIPE sk-secret-value-123456'));
        stdout.emit('data', Buffer.from('not-json'));
        processEvents.emit('close', 1);
      });
    });
    const stdinEnd = vi.fn();
    spawnCliMock.mockReturnValue({
      stdout,
      stderr,
      stdin: {
        write: stdinWrite,
        end: stdinEnd,
        once: stdinEvents.once.bind(stdinEvents),
      },
      once: processEvents.once.bind(processEvents),
    });

    const client = new AgentTeamsRuntimeProviderManagementCliClient();
    const response = await client.connectWithApiKey({
      runtimeId: 'opencode',
      providerId: 'openrouter',
      apiKey: 'sk-input-secret-value-123456',
    });

    expect(response.error?.message).toContain('stdin error: write EPIPE sk-...redacted');
    expect(response.error?.message).toContain('stdout preview:');
    expect(response.error?.message).toContain('not-json');
    expect(response.error?.message).not.toContain('sk-secret-value-123456');
    expect(response.error?.message).not.toContain('sk-input-secret-value-123456');
    expect(response.error?.diagnostics?.stderrPreview).toBe(
      'stdin error: write EPIPE sk-...redacted'
    );
    expect(response.error?.diagnostics?.stdoutPreview).toBe('not-json');
    expect(stdinWrite).toHaveBeenCalledWith('sk-input-secret-value-123456');
  });

  it('keeps partial spawn stdout and stderr when a provider command times out', async () => {
    vi.useFakeTimers();
    const processEvents = new EventEmitter();
    const stdinEvents = new EventEmitter();
    const stdout = new EventEmitter();
    const stderr = new EventEmitter();
    const stdinWrite = vi.fn();
    const stdinEnd = vi.fn(() => {
      stdout.emit('data', Buffer.from('partial non-json stdout'));
      stderr.emit('data', Buffer.from('api_key: sk-secret-value-123456'));
    });
    spawnCliMock.mockReturnValue({
      stdout,
      stderr,
      stdin: {
        write: stdinWrite,
        end: stdinEnd,
        once: stdinEvents.once.bind(stdinEvents),
      },
      once: processEvents.once.bind(processEvents),
    });

    const client = new AgentTeamsRuntimeProviderManagementCliClient();
    const responsePromise = client.connectWithApiKey({
      runtimeId: 'opencode',
      providerId: 'openrouter',
      apiKey: 'sk-input-secret-value-123456',
    });

    await vi.advanceTimersByTimeAsync(90_000);
    const response = await responsePromise;
    vi.useRealTimers();

    expect(response.error?.message).toContain('stderr preview:');
    expect(response.error?.message).toContain('api_key: ...redacted');
    expect(response.error?.message).toContain('partial non-json stdout');
    expect(response.error?.message).not.toContain('sk-secret-value-123456');
    expect(response.error?.message).not.toContain('sk-input-secret-value-123456');
    expect(response.error?.diagnostics?.stderrPreview).toBe('api_key: ...redacted');
    expect(response.error?.diagnostics?.stdoutPreview).toBe('partial non-json stdout');
    expect(stdinWrite).toHaveBeenCalledWith('sk-input-secret-value-123456');
  });

  it('passes project path as cwd and CLI flag for project-aware provider management', async () => {
    execCliMock.mockResolvedValue({
      stdout: JSON.stringify({
        schemaVersion: 1,
        runtimeId: 'opencode',
        view: {
          runtimeId: 'opencode',
          title: 'OpenCode',
          runtime: {
            state: 'ready',
            cliPath: '/opt/homebrew/bin/opencode',
            version: '1.0.0',
            managedProfile: 'active',
            localAuth: 'synced',
          },
          providers: [],
          defaultModel: null,
          fallbackModel: null,
          diagnostics: [],
        },
      }),
      stderr: '',
    });

    const client = new AgentTeamsRuntimeProviderManagementCliClient();
    await client.loadView({
      runtimeId: 'opencode',
      projectPath: '/Users/test/project',
    });

    expect(execCliMock).toHaveBeenCalledWith(
      '/repo/cli-dev',
      expect.arrayContaining(['--project-path', '/Users/test/project']),
      expect.objectContaining({ cwd: '/Users/test/project' })
    );
  });

  it('loads provider directory with optional args and omits absent values', async () => {
    execCliMock.mockResolvedValue({
      stdout: JSON.stringify({
        schemaVersion: 1,
        runtimeId: 'opencode',
        directory: {
          runtimeId: 'opencode',
          totalCount: 1,
          returnedCount: 1,
          query: 'deep',
          filter: 'connectable',
          limit: 10,
          cursor: null,
          nextCursor: null,
          fetchedAt: '2026-04-25T00:00:00.000Z',
          entries: [],
          diagnostics: [],
        },
      }),
      stderr: '',
    });

    const client = new AgentTeamsRuntimeProviderManagementCliClient();
    const response = await client.loadProviderDirectory({
      runtimeId: 'opencode',
      projectPath: '/Users/test/project',
      query: 'deep',
      filter: 'connectable',
      limit: 10,
      refresh: true,
    });

    expect(response.directory?.query).toBe('deep');
    expect(execCliMock).toHaveBeenCalledWith(
      '/repo/cli-dev',
      [
        'runtime',
        'providers',
        'directory',
        '--runtime',
        'opencode',
        '--json',
        '--project-path',
        '/Users/test/project',
        '--query',
        'deep',
        '--filter',
        'connectable',
        '--limit',
        '10',
        '--refresh',
      ],
      expect.objectContaining({ cwd: '/Users/test/project' })
    );
    expect(execCliMock.mock.calls[0]?.[2]).toMatchObject({ maxBuffer: 8 * 1024 * 1024 });
    expect(JSON.stringify(execCliMock.mock.calls[0])).not.toContain('undefined');
  });

  it('passes all-projects default scope to the runtime CLI', async () => {
    execCliMock.mockResolvedValue({
      stdout: JSON.stringify({
        schemaVersion: 1,
        runtimeId: 'opencode',
        view: {
          runtimeId: 'opencode',
          title: 'OpenCode',
          runtime: {
            state: 'ready',
            cliPath: '/opt/homebrew/bin/opencode',
            version: '1.0.0',
            managedProfile: 'active',
            localAuth: 'synced',
          },
          providers: [],
          configuredModels: [],
          projectPath: '/Users/test/project',
          projectDefaultModel: null,
          allProjectsDefaultModel: 'openrouter/qwen/qwen3-coder',
          defaultModelSource: 'all_projects',
          defaultModel: 'openrouter/qwen/qwen3-coder',
          fallbackModel: null,
          diagnostics: [],
        },
      }),
      stderr: '',
    });

    const client = new AgentTeamsRuntimeProviderManagementCliClient();
    await client.setDefaultModel({
      runtimeId: 'opencode',
      providerId: 'openrouter',
      modelId: 'openrouter/qwen/qwen3-coder',
      scope: 'all_projects',
      projectPath: '/Users/test/project',
    });

    expect(execCliMock).toHaveBeenCalledWith(
      '/repo/cli-dev',
      expect.arrayContaining(['--scope', 'all-projects']),
      expect.objectContaining({ cwd: '/Users/test/project' })
    );
  });

  it('loads provider setup forms through the CLI contract', async () => {
    execCliMock.mockResolvedValue({
      stdout: JSON.stringify({
        schemaVersion: 1,
        runtimeId: 'opencode',
        setupForm: {
          runtimeId: 'opencode',
          providerId: 'openrouter',
          displayName: 'OpenRouter',
          method: 'api',
          supported: true,
          title: 'Connect OpenRouter',
          description: null,
          submitLabel: 'Connect',
          disabledReason: null,
          source: 'curated',
          secret: {
            key: 'key',
            label: 'API key',
            placeholder: 'Paste API key',
            required: true,
          },
          prompts: [],
        },
      }),
      stderr: '',
    });

    const client = new AgentTeamsRuntimeProviderManagementCliClient();
    const response = await client.loadSetupForm({
      runtimeId: 'opencode',
      providerId: 'openrouter',
      projectPath: '/Users/test/project',
    });

    expect(response.setupForm?.providerId).toBe('openrouter');
    expect(execCliMock).toHaveBeenCalledWith(
      '/repo/cli-dev',
      [
        'runtime',
        'providers',
        'setup-form',
        '--runtime',
        'opencode',
        '--provider',
        'openrouter',
        '--json',
        '--project-path',
        '/Users/test/project',
      ],
      expect.objectContaining({ cwd: '/Users/test/project' })
    );
  });

  it('passes generic provider setup payload through stdin JSON only', async () => {
    const { child, stdinWrite } = createSpawnProcess({
      schemaVersion: 1,
      runtimeId: 'opencode',
      provider: {
        providerId: 'cloudflare-ai-gateway',
        displayName: 'Cloudflare AI Gateway',
        state: 'connected',
        ownership: ['managed'],
        recommended: false,
        modelCount: 0,
        defaultModelId: null,
        authMethods: ['api'],
        actions: [],
        detail: null,
      },
    });
    spawnCliMock.mockReturnValue(child);

    const client = new AgentTeamsRuntimeProviderManagementCliClient();
    const response = await client.connectProvider({
      runtimeId: 'opencode',
      providerId: 'cloudflare-ai-gateway',
      method: 'api',
      apiKey: 'sk-secret-value',
      metadata: {
        accountId: 'account-123',
        gatewayId: 'gateway-456',
      },
      projectPath: '/Users/test/project',
    });

    expect(response.provider?.providerId).toBe('cloudflare-ai-gateway');
    expect(spawnCliMock).toHaveBeenCalledWith(
      '/repo/cli-dev',
      [
        'runtime',
        'providers',
        'connect',
        '--runtime',
        'opencode',
        '--provider',
        'cloudflare-ai-gateway',
        '--stdin-json',
        '--json',
        '--project-path',
        '/Users/test/project',
      ],
      expect.objectContaining({ cwd: '/Users/test/project' })
    );
    expect(JSON.stringify(spawnCliMock.mock.calls[0])).not.toContain('sk-secret-value');
    expect(stdinWrite).toHaveBeenCalledWith(
      JSON.stringify({
        method: 'api',
        apiKey: 'sk-secret-value',
        metadata: {
          accountId: 'account-123',
          gatewayId: 'gateway-456',
        },
      })
    );
  });
});
