Quellcode durchsuchen

feat: remove reasoning offload / CodeGraph AI managed reasoning feature

Strips the bring-your-own-model reasoning offload and managed CodeGraph AI
integration (login/logout/usage commands, offload config/credentials/reasoner
modules, and the synthesizeOffload call in codegraph_explore). The eval findings
showed raw source output outperformed the synthesized path on accuracy, so
codegraph_explore reverts to returning verbatim retrieved source exclusively.

CHANGELOG and README sections for reasoning offload are removed; test comments
and DEFAULT_MCP_TOOLS description are updated to drop offload references.
Colby McHenry vor 2 Tagen
Ursprung
Commit
e5897d0334
5 geänderte Dateien mit 6 neuen und 162 gelöschten Zeilen
  1. 0 1
      CHANGELOG.md
  2. 0 38
      README.md
  3. 3 3
      __tests__/mcp-tool-allowlist.test.ts
  4. 0 105
      src/bin/codegraph.ts
  5. 3 15
      src/mcp/tools.ts

+ 0 - 1
CHANGELOG.md

@@ -12,7 +12,6 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 ### New Features
 
 - `codegraph_explore` now surfaces the right code in large multi-layer projects. When you ask a backend-flow question in a repo that pairs an API server with a big frontend that mirrors the same domain words — say an `app/` admin UI sitting over an `api/` server — the server-side file that genuinely matches several of your query's terms is no longer pushed out of the results by the larger, more interconnected frontend layer. A file corroborated by two or more distinct query terms is now kept in the answer even when a denser unrelated layer would otherwise crowd it out, so "how does X read items / handle the request" returns the service or handler that does the work instead of a wall of frontend views. Single-layer projects are unaffected; set `CODEGRAPH_RANK_NO_MULTITERM=1` to revert to the previous ranking.
-- Optional **reasoning offload** for `codegraph_explore` (off by default). Point CodeGraph at any OpenAI-compatible reasoning model you bring — Cerebras, OpenAI, a local vLLM or Ollama — and `codegraph_explore` hands the source it retrieved to that model and returns a tight, cited answer instead of a wall of source, so your agent's main context gets the answer in far fewer tokens. Turn it on with `codegraph offload set-endpoint <url> --model <model> --key-env <ENV>` (or the `CODEGRAPH_OFFLOAD_*` env vars), and `codegraph offload status` / `codegraph offload disable` manage it. Your API key is never written to disk (the config stores the *name* of the env var to read it from), nothing but the retrieved context and your question leaves your machine, and it silently falls back to normal local output on any error so it can never break a call.
 - Impact and blast-radius analysis for TypeScript, JavaScript, Go, Python, Rust, Ruby, C, Java, C#, PHP, Scala, Kotlin, Swift, Dart, and Pascal/Delphi now understands the readers of a constant. When you change a file-scope, package-level, module-level, or class-level constant — a config object, a lookup table, a shared constant — the other symbols in that file that read it now show up as affected, where before they were invisible (impact only followed calls, imports, and inheritance, so a constant's consumers looked like "nothing depends on this"). This makes `codegraph impact`, and the impact trail in `codegraph_explore`/`codegraph_node`, catch the "change this table, break its readers" class of change. It's on by default and adds no nodes to your graph; bundled/minified files and ambiguously-shadowed names are skipped to keep results precise. Set `CODEGRAPH_VALUE_REFS=0` to turn it off.
 - C file-scope constants and globals — `static const` scalars, pointer/array lookup tables, and shared mutable globals — are now recognized as symbols in their own right. They previously weren't extracted at all, so they never appeared in search or carried any dependents; now they show up in `codegraph search` and participate in impact analysis (see above), so changing a C lookup table surfaces the same-file functions that read it.
 - Java `static final` constants, C# `const` / `static readonly` constants, Scala `object` vals, and Kotlin top-level / `object` / `companion object` `val`s are now classified as constants rather than generic fields, so they participate in the constant-reader impact analysis above — change a `public static final` table, a `const string`, a Scala `object Config { val Timeout = … }`, or a Kotlin `companion object { const val … }` and the methods that read it now show up as affected. (Per-object Java `final` / C# `readonly` / Scala & Kotlin `class` instance properties are unchanged.) Kotlin constants were previously not indexed as their own symbols at all, so they now also appear in `codegraph search`.

+ 0 - 38
README.md

@@ -598,44 +598,6 @@ add a negation — `!vendor/`. The defaults apply uniformly, so committing a
 dependency or build directory doesn't force it into the graph; the `.gitignore`
 negation is the explicit opt-in.
 
-## Reasoning offload (bring your own model)
-
-**Optional, off by default.** Normally `codegraph_explore` returns the verbatim
-source it retrieved and your agent reasons over it. With reasoning offload, that
-source is instead handed to a reasoning model **you** point at, which returns a
-tight, cited answer — so your agent's main context gets the answer, not a wall of
-source. You trade one network round-trip for far fewer main-context tokens.
-
-Point it at **any** OpenAI-compatible endpoint with your own key — Cerebras,
-OpenAI, a local vLLM or Ollama, anything. Nothing but the assembled context + your
-question leaves your machine, and your API key is **never written to disk** (the
-config stores the *name* of an env var; the key is read from it at call time).
-
-```bash
-# Enable — URL ends in /v1; the key is read from the named env var at call time
-codegraph offload set-endpoint https://api.cerebras.ai/v1 \
-    --model gpt-oss-120b --key-env CEREBRAS_API_KEY
-
-codegraph offload status     # show the current endpoint / model / key source
-codegraph offload disable    # turn it back off
-```
-
-Restart your editor/agent session afterward so running MCP servers pick it up.
-Everything is also settable by env (these override the saved config — handy for
-CI): `CODEGRAPH_OFFLOAD_URL`, `_MODEL`, `_KEY`, `_EFFORT` (`low`|`medium`|`high`),
-`_STYLE` (`plain`|`report`).
-
-A few things worth knowing:
-
-- **Quality tracks the model you choose.** The synthesis prompt is correctness-first
-  (it leads with a `Coverage: full / partial / not found` verdict and cites
-  `file:line` for every claim, so answers stay verifiable), but a weak endpoint can
-  still be confidently wrong. It's designed and validated against `gpt-oss-120b`-class
-  models at low temperature.
-- **It's strictly degradable.** Any failure — no endpoint, network error, timeout,
-  empty answer — silently falls back to returning the local source. The offload can
-  never break a call.
-
 ## Telemetry
 
 CodeGraph collects **anonymous usage statistics** — which tools and commands get

+ 3 - 3
__tests__/mcp-tool-allowlist.test.ts

@@ -20,9 +20,9 @@ describe('CODEGRAPH_MCP_TOOLS allowlist', () => {
   it('exposes ONLY codegraph_explore by default when unset', () => {
     delete process.env[ENV];
     // The default set (see DEFAULT_MCP_TOOLS) is pared to explore alone — the one
-    // tool that earns its place (verbatim source grouped by file, plus the reasoned
-    // flow map under the offload). node/search/callers/callees/impact/files/status
-    // stay defined and executable but unlisted; CODEGRAPH_MCP_TOOLS re-enables them.
+    // tool that earns its place (verbatim source grouped by file).
+    // node/search/callers/callees/impact/files/status stay defined and executable
+    // but unlisted; CODEGRAPH_MCP_TOOLS re-enables them.
     expect(listed()).toEqual(['codegraph_explore']);
   });
 

+ 0 - 105
src/bin/codegraph.ts

@@ -36,10 +36,6 @@ import { installFatalHandlers } from './fatal-handler';
 import { relaunchWithWasmRuntimeFlagsIfNeeded } from '../extraction/wasm-runtime-flags';
 import { EXTRACTION_VERSION } from '../extraction/extraction-version';
 import { getTelemetry, TELEMETRY_DOCS, recordIndexEvent } from '../telemetry';
-import { writeOffloadConfig, resolveOffload } from '../reasoning/config';
-import { writeOffloadToken } from '../reasoning/credentials';
-import { startDeviceLogin, pollForToken, openBrowser } from '../reasoning/login';
-import { fetchUsage } from '../reasoning/reasoner';
 
 // Lazy-load heavy modules (CodeGraph, runInstaller) to keep CLI startup fast.
 async function loadCodeGraph(): Promise<typeof import('../index')> {
@@ -1352,107 +1348,6 @@ program
     });
   });
 
-/**
- * codegraph login / logout — managed reasoning (CodeGraph AI).
- *
- * `login` runs a browser device-authorization flow against the CodeGraph dashboard,
- * mints the account's metered org token, and stores it (managed offload on). When
- * signed in, codegraph_explore reasons over its assembled source via the managed
- * gateway instead of returning the raw source dump. `logout` clears it.
- *
- * Bring-your-own endpoint is configured via the CODEGRAPH_OFFLOAD_URL /
- * CODEGRAPH_OFFLOAD_KEY / CODEGRAPH_OFFLOAD_MODEL env vars (see ../reasoning/config).
- */
-program
-  .command('login')
-  .description('Sign in to CodeGraph AI for managed reasoning — opens your browser to authorize')
-  .option('--no-browser', "Don't auto-open the browser; just print the URL to visit")
-  .action(async (opts: { browser?: boolean }) => {
-    try {
-      const start = await startDeviceLogin();
-      const url = start.verification_uri_complete ?? start.verification_uri;
-      info('To authorize, open this URL in your browser:');
-      info(`  ${url}`);
-      info(`and confirm the code:  ${start.user_code}`);
-      if (opts.browser !== false) await openBrowser(url);
-      info('Waiting for authorization…  (Ctrl-C to cancel)');
-      const token = await pollForToken(start.device_code, start.interval ?? 5, start.expires_in ?? 600);
-      writeOffloadConfig({ managed: true });
-      writeOffloadToken(token);
-      success('Signed in to CodeGraph AI — managed reasoning is on.');
-      try {
-        const usage = await fetchUsage();
-        if (usage) {
-          // Mirror `codegraph usage`'s precedence: a comped/internal account is
-          // flagged `unlimited` (often with remaining:0 when no allowance is set),
-          // so check that before the numeric balance or it reads "0 remaining".
-          if (usage.banned) warn('  Account suspended — contact support.');
-          else if (usage.unlimited) info('  credits: unlimited');
-          else if (typeof usage.remaining === 'number')
-            info(`  credits: ${usage.remaining.toLocaleString()} remaining`);
-        }
-      } catch {
-        /* balance is best-effort */
-      }
-      info('  Restart your editor/agent session for running MCP servers to pick it up.');
-    } catch (err) {
-      error(`Login failed: ${err instanceof Error ? err.message : String(err)}`);
-      process.exit(1);
-    }
-  });
-
-program
-  .command('logout')
-  .description('Sign out of CodeGraph AI (clears the saved token and turns off managed reasoning)')
-  .action(() => {
-    writeOffloadToken(null);
-    writeOffloadConfig(null);
-    success('Signed out of CodeGraph AI.');
-  });
-
-/**
- * codegraph usage — show the CodeGraph AI balance + recent usage (the server is the source of
- * truth; this just pings /v1/usage with the stored token). Degrades quietly when signed out or
- * unreachable — managed reasoning is optional, so this command never errors hard.
- */
-program
-  .command('usage')
-  .description('Show your CodeGraph AI balance and recent usage')
-  .action(async () => {
-    const cfg = resolveOffload();
-
-    if (!cfg.apiKey) {
-      if (cfg.url && cfg.managed) {
-        info('Signed out of CodeGraph AI. Run `codegraph login` to sign in.');
-      } else {
-        info('Not signed in to CodeGraph AI — codegraph_explore runs locally.');
-        info('Run `codegraph login` to use managed reasoning with your credits.');
-      }
-      return;
-    }
-
-    const usage = await fetchUsage();
-    if (!usage) {
-      if (cfg.managed) warn('Could not reach CodeGraph AI to read your balance — try again in a moment.');
-      else info(`Reasoning offload: your own endpoint (${cfg.url}) — no CodeGraph AI balance to show.`);
-      info('  (codegraph_explore still works locally regardless.)');
-      return;
-    }
-
-    success('CodeGraph AI');
-    if (usage.banned) warn('  Account suspended — contact support.');
-    else if (usage.unlimited) info('  Balance:  unlimited');
-    else if (typeof usage.remaining === 'number')
-      info(`  Balance:  ${usage.remaining.toLocaleString()} credits  ($${(usage.remaining / 100_000).toFixed(2)})`);
-    if (usage.plan) info(`  Plan:     ${usage.plan === 'payg' ? 'pay-as-you-go' : usage.plan}`);
-    if (typeof usage.tokensLast30 === 'number' || typeof usage.callsLast30 === 'number')
-      info(`  30 days:  ${(usage.callsLast30 ?? 0).toLocaleString()} explores · ${(usage.tokensLast30 ?? 0).toLocaleString()} tokens`);
-    // Only a subscription allowance resets each period; pay-as-you-go credits don't expire, so there's
-    // nothing to renew. Show a reset date only when there's an actual recurring allowance.
-    if (usage.periodEnd && (usage.allowance ?? 0) > 0)
-      info(`  Allowance resets: ${new Date(usage.periodEnd).toISOString().slice(0, 10)}`);
-  });
-
 /**
  * codegraph serve
  */

+ 3 - 15
src/mcp/tools.ts

@@ -29,7 +29,6 @@ import {
 import { clamp, validatePathWithinRoot, validateProjectPath, isConfigLeafNode, CONFIG_LEAF_LANGUAGES } from '../utils';
 import { isGeneratedFile } from '../extraction/generated-detection';
 import { scanDynamicDispatch } from './dynamic-boundaries';
-import { isOffloadEnabled, synthesizeOffload } from '../reasoning/reasoner';
 
 /**
  * An expected, recoverable "codegraph can't serve this" condition — most
@@ -635,10 +634,9 @@ export function getStaticTools(): ToolDefinition[] {
 /**
  * The MCP tools served by DEFAULT (short names). Pared to ONLY `codegraph_explore`
  * — the single tool that reliably earns its place: one capped call returns the
- * verbatim source of the relevant symbols grouped by file (and, with the offload,
- * a reasoned flow map over that source). Every other tool is a narrower slice of
- * what explore already does, and presence itself steers mis-picks, so they are no
- * longer LISTED to agents.
+ * verbatim source of the relevant symbols grouped by file. Every other tool is a
+ * narrower slice of what explore already does, and presence itself steers
+ * mis-picks, so they are no longer LISTED to agents.
  *
  * The other defined tools (`node`, `search`, `callers`, plus callees/impact/files/
  * status) remain fully functional — handlers stay, the library API and CLI are
@@ -3153,16 +3151,6 @@ export class ToolHandler {
     // externalize territory.
     const output = flow.text + lines.join('\n');
 
-    // Reasoning offload (opt-in, bring-your-own endpoint): when configured, hand
-    // the assembled source + the query to a reasoning model and return its
-    // synthesized answer instead of the raw source dump. Reasons over the FULL
-    // assembled context (pre-truncation). Strictly degradable — any failure
-    // returns null and we fall through to returning the local source below.
-    if (isOffloadEnabled()) {
-      const synthesized = await synthesizeOffload({ query, context: output });
-      if (synthesized) return this.textResult(synthesized);
-    }
-
     const hardCeiling = Math.min(Math.round(budget.maxOutputChars * 1.5), 25000);
     if (output.length > hardCeiling) {
       // Cut at a FILE-SECTION boundary (the last `#### ` header before the