import type { ToolDef, ToolJsonSchema } from './types.js';
import { viewFile, listDir, grep, findFiles, viewTruncatedOutput } from './fs-tools.js';
import { gitStatus, skillFind, skillUse, skillResource, askUserInput } from './misc-tools.js';
import { webSearch } from '../web_search.js';
import { webFetch } from '../web_fetch.js';
// v2.8.24: All codecontext tools removed. Boocontext MCP tools are appended
// at startup via appendMcpTools(). Agent tool lists reference the MCP tool
// names (boocontext_boocontext_*), boocontext_boocontext_*) directly.
// v1.13.17-cross-repo-reads: cross-repo read grant request tool. Paired
// with the pause-on-pending-grant branch in inference/tool-phase.ts and the
// POST /api/chats/:id/grant_read_access endpoint in routes/messages.ts.
import { requestReadAccess } from '../request_read_access.js';
// v2.6.x: read-only tool that reads a tab's transcript by its session-scoped
// tab number. Needs DB/session context (ToolExecCtx 4th arg).
import { readTabByNumber } from '../read_tab_by_number.js';
// v2.x: memory management tools. file-based store with optional CoreTier
// (SQLite FTS5 + vector) hybrid search backend.
import { extractMemoryTool } from './extract_memory.js';
import { manageMemoryTool } from './manage_memory.js';
import { searchMemoryTool } from './search_memory.js';
// vWhale: command execution tool. Spawns processes in the project worktree
// with timeout and output cap. No shell — args are passed as array.
import { runCommand } from './execute-command.js';
// v2.x: background subagent tools. Non-blocking subagent execution with
// spawn/poll/collect lifecycle. Reuses existing sessions/chats/messages/tasks.
import {
  spawnSubagent,
  subagentStatus,
  subagentResult,
} from './background-subagent-tools.js';

// v1.13.3: alpha-sorted by tool.name at module load. llama.cpp's prompt
// cache hits on byte-identical prefixes; the tool list lives near the top
// of the system prompt, so any order drift would invalidate every cached
// turn. Single source of truth for ordering lives here — toolJsonSchemas()
// and TOOLS_BY_NAME inherit it.
// v1.14.1-mcp-poc: changed from ReadonlyArray to let-bound mutable array
// so appendMcpTools() can push MCP-discovered tools at startup.
export let ALL_TOOLS: ToolDef<unknown>[] = [
  viewFile as ToolDef<unknown>,
  viewTruncatedOutput as ToolDef<unknown>,
  listDir as ToolDef<unknown>,
  grep as ToolDef<unknown>,
  findFiles as ToolDef<unknown>,
  gitStatus as ToolDef<unknown>,
  skillFind as ToolDef<unknown>,
  skillUse as ToolDef<unknown>,
  skillResource as ToolDef<unknown>,
  askUserInput as ToolDef<unknown>,
  // v1.11.8: web tools. Gated per-chat via session.web_search_enabled
  // (with project default fallback) — see effectiveTools filter in
  // services/inference.ts.
  webSearch as ToolDef<unknown>,
  webFetch as ToolDef<unknown>,
  // v2.8.24: Old codecontext tools removed. Boocontext MCP tools are appended
  // at startup via appendMcpTools(). Agent tool lists in AGENTS.md use the
  // boocontext_* MCP tool names directly.
  // v1.13.17-cross-repo-reads: paired with the pause-on-pending-grant
  // branch in tool-phase.ts. Read-only — only ever READS files; the only
  // state change is appending to sessions.allowed_read_paths via the
  // grant endpoint, gated by user consent.
  requestReadAccess as ToolDef<unknown>,
  // v2.6.x: read a tab's transcript by its session-scoped tab number.
  // Read-only; uses the ToolExecCtx 4th arg for DB/session access.
  readTabByNumber as ToolDef<unknown>,
  // v2.x: memory management tools. File-based store with optional CoreTier
  // (SQLite FTS5 + vector) hybrid search backend.
  extractMemoryTool as ToolDef<unknown>,
  manageMemoryTool as ToolDef<unknown>,
  searchMemoryTool as ToolDef<unknown>,
  // vWhale: command execution. Spawns processes in the project worktree.
  // Read-write; use with guard: restricted to project root via path_guard,
  // no shell injection (execFile, not exec).
  runCommand as ToolDef<unknown>,
  // v2.x: background subagent tools. Non-blocking spawn/poll/collect lifecycle.
  spawnSubagent as ToolDef<unknown>,
  subagentStatus as ToolDef<unknown>,
  subagentResult as ToolDef<unknown>,
].sort((a, b) => a.name.localeCompare(b.name));

export let TOOLS_BY_NAME: Record<string, ToolDef<unknown>> = Object.fromEntries(
  ALL_TOOLS.map((t) => [t.name, t])
);

// v1.14.1-mcp-poc: append MCP-discovered tools at startup. Called once
// from index.ts after mcpClient.initialize(). Re-sorts ALL_TOOLS and
// rebuilds TOOLS_BY_NAME. MCP tools are all read-only by construction
// (the read-only guard in mcp-client.ts rejects readOnlyHint: false).
export function appendMcpTools(mcpTools: ToolDef<unknown>[]): void {
  if (mcpTools.length === 0) return;
  ALL_TOOLS = [...ALL_TOOLS, ...mcpTools].sort((a, b) => a.name.localeCompare(b.name));
  TOOLS_BY_NAME = Object.fromEntries(ALL_TOOLS.map((t) => [t.name, t]));
}

export function toolJsonSchemas(): ToolJsonSchema[] {
  return ALL_TOOLS.map((t) => t.jsonSchema);
}
