feat: LSP code intelligence + parallel sub-agent mutation gate

Code intelligence (LSP):
- src/codeintel/lspManager.ts: lazy per-language LSP server lifecycle
  (tsserver/pyright/gopls/clangd/rust-analyzer), didOpen/didChange sync,
  definition/references/diagnostics, notifyFileChanged, shutdownAll.
  Fix stream typing (StreamMessageReader/Writer) + MarkupContent→string.
- src/tools/codeIntel.ts: definition/references/diagnostics read-only tools.
- tools/index.ts: register the three LSP tools.
- agent/loop.ts: wire notifyFileChanged into the FileChanged hook path
  (fire-and-forget, best-effort) so live servers stay in sync with disk.
- ui/ink/index.tsx: shutdownAll on exit so spawned servers aren't orphaned.

Parallel sub-agent orchestration:
- agent/session.ts: session.mutationGate promise chain serializes every
  mutating tool call across the session (incl. parallel sub-agents that
  share the parent session) so they can't race on the single permission
  slot or interleave filesystem writes. Read-only tools stay concurrent.
- agent/loop.ts: runUnderMutationGate wraps mutating tool execution;
  sub-agents inherit the parent's gate.
- tools/agentTool.ts: `tasks` array runs N sub-agents in parallel; one
  failure surfaces as that task's error, not a rejected batch.
- tools/types.ts: SubAgentResult type.

Other:
- cli.ts + mcp/client.ts: read version from package.json instead of
  hardcoding "0.3.1".
- agent/parallelAgents.test.ts: parallel batch + mutation-gate tests.
- Remove scratch guardtest2.mjs.

Verified: typecheck clean, build 245.85 KB, 219 tests pass.
This commit is contained in:
kim
2026-08-21 13:22:34 +09:00
parent 6fe98887d5
commit cb950891d5
13 changed files with 826 additions and 31 deletions
+2 -1
View File
@@ -2,6 +2,7 @@ import { execa } from "execa";
import { existsSync, mkdirSync } from "node:fs";
import path from "node:path";
import { Command } from "commander";
import pkg from "../package.json" with { type: "json" };
import { makeClient } from "./backend/client.js";
import { ConfigError, resolveBackendConfig, resolveModel } from "./config/config.js";
import { configFilePath, loadStoredConfig, saveStoredConfig, type StoredConfig } from "./config/store.js";
@@ -24,7 +25,7 @@ function addBackendOptions(cmd: Command): Command {
program
.name("locode")
.description("Agentic coding CLI for local models via Ollama and LM Studio")
.version("0.3.1");
.version(pkg.version);
addBackendOptions(program)
.option("-m, --model <name>", "model name as known to the backend")