feat(offload): managed tier (CodeGraph AI) — metered reasoning via org token [WIP]

Adds the managed offload mode: point codegraph_explore at the CodeGraph AI metered
gateway (https://ai.getcodegraph.com) with an org token instead of a BYO provider key.
Same synthesis client, pointed at codegraph-ai-proxy (a metered OpenAI-compatible gateway).

- credentials.ts — org token in ~/.codegraph/credentials.json (0600); unlike a BYO
  provider key it's a revocable org-scoped auth token (gh/npm-login style), kept out
  of config.json
- config.ts — managed branch in resolveOffload: default gateway URL + public model id
  (openai/gpt-oss-120b) + login token as bearer; managed requires a token to be enabled
- reasoner.ts — fetchUsage() reads the credit balance from /v1/usage
- bin/codegraph.ts — `codegraph offload login --token <t>` / `logout`; status shows the
  managed tier + live balance

Proven GREEN end-to-end against a local wrangler-dev of the proxy: org token validated,
credits prechecked, real Cerebras synthesis returned, and credits metered + charged
(250,000 → 248,473). Graceful degrade on upstream failure; balance via /v1/usage.
Phase 3 (codegraph login device flow) replaces the manual --token.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Colby McHenry
2026-06-17 15:06:42 -05:00
co-authored by Claude Opus 4.8
parent db4c9f3641
commit da5c6c2f79
5 changed files with 229 additions and 27 deletions
+46 -4
View File
@@ -37,6 +37,8 @@ import { relaunchWithWasmRuntimeFlagsIfNeeded } from '../extraction/wasm-runtime
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 { fetchUsage } from '../reasoning/reasoner';
// Lazy-load heavy modules (CodeGraph, runInstaller) to keep CLI startup fast.
async function loadCodeGraph(): Promise<typeof import('../index')> {
@@ -1382,12 +1384,52 @@ offloadCmd
});
offloadCmd
.command('status')
.description('Show the current reasoning-offload configuration')
.command('login')
.description('Use the managed CodeGraph AI tier (metered) with your account token')
.requiredOption('--token <token>', 'Your CodeGraph AI org token')
.option('--url <url>', 'Override the managed gateway URL (advanced/testing)')
.option('--model <model>', 'Override the model id')
.action((opts: { token: string; url?: string; model?: string }) => {
// Phase 2: the token is pasted in. A future `codegraph login` device flow will
// mint and store it automatically.
writeOffloadConfig({ managed: true, url: opts.url, model: opts.model });
writeOffloadToken(opts.token);
success('Reasoning offload: signed in to CodeGraph AI (managed).');
info(' Credits burn from your account. Check the balance with `codegraph offload status`.');
info(' Restart your editor/agent session for running MCP servers to pick it up.');
});
offloadCmd
.command('logout')
.description('Sign out of CodeGraph AI and clear the stored token')
.action(() => {
writeOffloadToken(null);
writeOffloadConfig(null);
success('Signed out of CodeGraph AI; offload turned off.');
});
offloadCmd
.command('status')
.description('Show the current reasoning-offload configuration (and managed balance)')
.action(async () => {
const c = resolveOffload();
if (!c.enabled) {
info('Reasoning offload: off. Enable with `codegraph offload set-endpoint <url>`.');
if (c.managed) info('Reasoning offload: managed, but signed out. Run `codegraph offload login --token <token>`.');
else info('Reasoning offload: off. Enable with `codegraph offload set-endpoint <url>` or `codegraph offload login`.');
return;
}
if (c.managed) {
success(`Reasoning offload: on — CodeGraph AI (managed)`);
info(` endpoint: ${c.url}`);
info(` model: ${c.model}`);
info(` token: present (from ${c.keySource})`);
const usage = await fetchUsage();
if (usage && typeof usage.remaining === 'number') {
const reset = usage.periodEnd ? ` · allowance resets ${new Date(usage.periodEnd).toISOString().slice(0, 10)}` : '';
info(` credits: ${usage.remaining.toLocaleString()} remaining (plan ${usage.plan ?? '—'})${reset}`);
} else {
warn(' credits: could not reach CodeGraph AI to read your balance (the offload still degrades gracefully).');
}
return;
}
success(`Reasoning offload: on (${c.origin === 'env' ? 'from environment' : 'configured'})`);
@@ -1400,7 +1442,7 @@ offloadCmd
offloadCmd
.command('disable')
.description('Turn off the reasoning offload')
.description('Turn off the reasoning offload (keeps any saved login token)')
.action(() => {
writeOffloadConfig(null);
success('Reasoning offload disabled.');