claude-code-infinite 1.0.9 → 1.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +230 -37
- package/dist/cc-request.d.ts +94 -0
- package/dist/cc-request.d.ts.map +1 -0
- package/dist/cc-request.js +194 -0
- package/dist/cc-request.js.map +1 -0
- package/dist/claude-env.d.ts +30 -0
- package/dist/claude-env.d.ts.map +1 -0
- package/dist/claude-env.js +55 -0
- package/dist/claude-env.js.map +1 -0
- package/dist/cli-args.d.ts +32 -0
- package/dist/cli-args.d.ts.map +1 -0
- package/dist/cli-args.js +72 -0
- package/dist/cli-args.js.map +1 -0
- package/dist/cli-lifecycle.d.ts +17 -0
- package/dist/cli-lifecycle.d.ts.map +1 -0
- package/dist/cli-lifecycle.js +30 -0
- package/dist/cli-lifecycle.js.map +1 -0
- package/dist/cli-main.d.ts +15 -0
- package/dist/cli-main.d.ts.map +1 -0
- package/dist/cli-main.js +464 -0
- package/dist/cli-main.js.map +1 -0
- package/dist/cli.js +13 -177
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +3 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +29 -3
- package/dist/config.js.map +1 -1
- package/dist/count-tokens.d.ts +78 -0
- package/dist/count-tokens.d.ts.map +1 -0
- package/dist/count-tokens.js +277 -0
- package/dist/count-tokens.js.map +1 -0
- package/dist/final-index.d.ts +10 -0
- package/dist/final-index.d.ts.map +1 -0
- package/dist/final-index.js +37 -0
- package/dist/final-index.js.map +1 -0
- package/dist/hooks.d.ts +239 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +618 -0
- package/dist/hooks.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/memtree-fetch.d.ts +24 -0
- package/dist/memtree-fetch.d.ts.map +1 -0
- package/dist/memtree-fetch.js +121 -0
- package/dist/memtree-fetch.js.map +1 -0
- package/dist/memtree-finder.d.ts +99 -0
- package/dist/memtree-finder.d.ts.map +1 -0
- package/dist/memtree-finder.js +235 -0
- package/dist/memtree-finder.js.map +1 -0
- package/dist/memtree-links.d.ts +16 -0
- package/dist/memtree-links.d.ts.map +1 -0
- package/dist/memtree-links.js +66 -0
- package/dist/memtree-links.js.map +1 -0
- package/dist/memtree-mcp-config.d.ts +28 -0
- package/dist/memtree-mcp-config.d.ts.map +1 -0
- package/dist/memtree-mcp-config.js +121 -0
- package/dist/memtree-mcp-config.js.map +1 -0
- package/dist/memtree-mcp.d.ts +265 -0
- package/dist/memtree-mcp.d.ts.map +1 -0
- package/dist/memtree-mcp.js +667 -0
- package/dist/memtree-mcp.js.map +1 -0
- package/dist/memtree-newest.d.ts +74 -0
- package/dist/memtree-newest.d.ts.map +1 -0
- package/dist/memtree-newest.js +217 -0
- package/dist/memtree-newest.js.map +1 -0
- package/dist/memtree-tools.d.ts +105 -0
- package/dist/memtree-tools.d.ts.map +1 -0
- package/dist/memtree-tools.js +408 -0
- package/dist/memtree-tools.js.map +1 -0
- package/dist/memtree.d.ts +398 -0
- package/dist/memtree.d.ts.map +1 -0
- package/dist/memtree.js +1231 -0
- package/dist/memtree.js.map +1 -0
- package/dist/notices.d.ts +177 -0
- package/dist/notices.d.ts.map +1 -0
- package/dist/notices.js +469 -0
- package/dist/notices.js.map +1 -0
- package/dist/payment-gate.d.ts +53 -0
- package/dist/payment-gate.d.ts.map +1 -0
- package/dist/payment-gate.js +97 -0
- package/dist/payment-gate.js.map +1 -0
- package/dist/project-meta.d.ts +15 -0
- package/dist/project-meta.d.ts.map +1 -0
- package/dist/project-meta.js +80 -0
- package/dist/project-meta.js.map +1 -0
- package/dist/prompt-accounting.d.ts +12 -0
- package/dist/prompt-accounting.d.ts.map +1 -0
- package/dist/prompt-accounting.js +70 -0
- package/dist/prompt-accounting.js.map +1 -0
- package/dist/proxy.d.ts +197 -0
- package/dist/proxy.d.ts.map +1 -0
- package/dist/proxy.js +4247 -0
- package/dist/proxy.js.map +1 -0
- package/dist/reqlog.d.ts +419 -0
- package/dist/reqlog.d.ts.map +1 -0
- package/dist/reqlog.js +146 -0
- package/dist/reqlog.js.map +1 -0
- package/dist/request-sizing.d.ts +52 -0
- package/dist/request-sizing.d.ts.map +1 -0
- package/dist/request-sizing.js +92 -0
- package/dist/request-sizing.js.map +1 -0
- package/dist/resume-repair-file.d.ts +17 -0
- package/dist/resume-repair-file.d.ts.map +1 -0
- package/dist/resume-repair-file.js +100 -0
- package/dist/resume-repair-file.js.map +1 -0
- package/dist/resume-repair.d.ts +27 -0
- package/dist/resume-repair.d.ts.map +1 -0
- package/dist/resume-repair.js +198 -0
- package/dist/resume-repair.js.map +1 -0
- package/dist/route-cache.d.ts +5 -0
- package/dist/route-cache.d.ts.map +1 -0
- package/dist/route-cache.js +63 -0
- package/dist/route-cache.js.map +1 -0
- package/dist/route-fallback.d.ts +29 -0
- package/dist/route-fallback.d.ts.map +1 -0
- package/dist/route-fallback.js +49 -0
- package/dist/route-fallback.js.map +1 -0
- package/dist/route-identity.d.ts +6 -0
- package/dist/route-identity.d.ts.map +1 -0
- package/dist/route-identity.js +100 -0
- package/dist/route-identity.js.map +1 -0
- package/dist/transcript-usage.d.ts +57 -0
- package/dist/transcript-usage.d.ts.map +1 -0
- package/dist/transcript-usage.js +570 -0
- package/dist/transcript-usage.js.map +1 -0
- package/dist/turns.d.ts +73 -0
- package/dist/turns.d.ts.map +1 -0
- package/dist/turns.js +298 -0
- package/dist/turns.js.map +1 -0
- package/dist/update-check.d.ts +38 -0
- package/dist/update-check.d.ts.map +1 -0
- package/dist/update-check.js +67 -0
- package/dist/update-check.js.map +1 -0
- package/package.json +6 -2
package/dist/cli-main.js
ADDED
|
@@ -0,0 +1,464 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Claude Code Infinite launcher (plans/2026-06-09_PLAN_local_proxy_app.md).
|
|
4
|
+
*
|
|
5
|
+
* Starts the local proxy on 127.0.0.1 and execs `claude` with
|
|
6
|
+
* ANTHROPIC_BASE_URL pointed at it. Claude Code's automatic compaction is
|
|
7
|
+
* disabled because MemTree owns context management; manual `/compact` remains
|
|
8
|
+
* available. Auth is untouched by design ("mirror vanilla"):
|
|
9
|
+
* Claude Code keeps its native login — token refresh, plan-default model
|
|
10
|
+
* resolution, and limit handling behave exactly like vanilla — and its OAuth
|
|
11
|
+
* token never leaves this machine. polychat.co only ever sees message content
|
|
12
|
+
* for compression/indexing, authenticated by the user's MemTree API key.
|
|
13
|
+
*/
|
|
14
|
+
import spawn from "cross-spawn";
|
|
15
|
+
import { exec } from "node:child_process";
|
|
16
|
+
import * as readline from "node:readline";
|
|
17
|
+
import { MEMTREE_COMPACT_MIN_TOKENS, parseTokenCount, startProxy } from "./proxy.js";
|
|
18
|
+
import { MemtreeLinkStore } from "./memtree-links.js";
|
|
19
|
+
import { NewestTreeLookup } from "./memtree-newest.js";
|
|
20
|
+
import { ClaudeTranscriptUsage } from "./transcript-usage.js";
|
|
21
|
+
import { createSessionNoticePlugin, supportsMessageDisplay, terminalSupportsColor, withSessionNoticePluginArgs, } from "./hooks.js";
|
|
22
|
+
import { CLIENT_NAME, CLIENT_VERSION, MemtreeClient } from "./memtree.js";
|
|
23
|
+
import { RequestLogger } from "./reqlog.js";
|
|
24
|
+
import { startupNoticeText } from "./notices.js";
|
|
25
|
+
import { FALLBACK_SUBSCRIBE_URL, PAYMENT_GATE_PROMPT, formatPaymentNotice, parsePaymentChoice, parsePaymentStatus, hyperlink, } from "./payment-gate.js";
|
|
26
|
+
import { checkForUpdate } from "./update-check.js";
|
|
27
|
+
import { compactTargetFromEnv, isPrintInvocation, parseWrapperArgs, memtreeLinkPlacementFromEnv, } from "./cli-args.js";
|
|
28
|
+
import { runMemtreeFetchCommand } from "./memtree-fetch.js";
|
|
29
|
+
import { runMemtreeMcpServer } from "./memtree-mcp.js";
|
|
30
|
+
import { readProjectMeta } from "./project-meta.js";
|
|
31
|
+
import { argsConfigureMemtreeMcp, MEMTREE_TOOLS_HEADER_VALUE, memtreeMcpEnabledByEnv, withMemtreeMcpArgs, writeMemtreeMcpConfig, } from "./memtree-mcp-config.js";
|
|
32
|
+
import { claudeChildEnv, claudeNativeOneMillionContextEnabled, } from "./claude-env.js";
|
|
33
|
+
import { createSignalShutdownHandler, exitCodeForChild, } from "./cli-lifecycle.js";
|
|
34
|
+
import { getPolychatApiKey, setPolychatApiKey, getLocalPolychatApiKey, setLocalPolychatApiKey, getStagingPolychatApiKey, setStagingPolychatApiKey, } from "./config.js";
|
|
35
|
+
import { repairStrandedResume, resumeSessionId } from "./resume-repair.js";
|
|
36
|
+
// MemTree (polychat) API hosts — /v1/context_memory lives at the app root.
|
|
37
|
+
const POLYCHAT_BASE_URL = "https://api.polychat.co";
|
|
38
|
+
const STAGING_BASE_URL = "https://polychat-staging-421312241218.us-west2.run.app";
|
|
39
|
+
const LOCAL_BASE_URL = "http://localhost:8080";
|
|
40
|
+
const POLYCHAT_AUTH_URL = "https://polychat.co/auth?memtree=true";
|
|
41
|
+
const SHUTDOWN_PROXY_DRAIN_MS = 5_000;
|
|
42
|
+
const SHUTDOWN_MEMTREE_DRAIN_MS = 2_000;
|
|
43
|
+
const SHUTDOWN_LOG_FLUSH_MS = 2_000;
|
|
44
|
+
// Payment gate: how long "subscribe now" waits for the Stripe webhook to flip
|
|
45
|
+
// the key to paid, and how often it re-asks the status probe meanwhile.
|
|
46
|
+
const SUBSCRIBE_WAIT_MS = 180_000;
|
|
47
|
+
const SUBSCRIBE_POLL_MS = 3_000;
|
|
48
|
+
function openUrl(url) {
|
|
49
|
+
const platform = process.platform;
|
|
50
|
+
const command = platform === "darwin" ? "open" : platform === "win32" ? "explorer" : "xdg-open";
|
|
51
|
+
platform === "win32"
|
|
52
|
+
? exec(`${command} "${url}"`, { shell: "cmd.exe" })
|
|
53
|
+
: exec(`${command} "${url}"`);
|
|
54
|
+
}
|
|
55
|
+
async function promptForApiKey(mode) {
|
|
56
|
+
const rl = readline.createInterface({
|
|
57
|
+
input: process.stdin,
|
|
58
|
+
output: process.stdout,
|
|
59
|
+
});
|
|
60
|
+
const url = mode === "local"
|
|
61
|
+
? "http://local.polychat.co:5173/memtree-api"
|
|
62
|
+
: POLYCHAT_AUTH_URL;
|
|
63
|
+
// The label is a clickable link (OSC 8) where the terminal supports it, and
|
|
64
|
+
// the URL is printed too, for other terminals and for opening it elsewhere.
|
|
65
|
+
console.log(`\nGet your ${hyperlink("MemTree API key", url)}:\n ${url}`);
|
|
66
|
+
await new Promise((resolve) => {
|
|
67
|
+
rl.question(`\nPress Enter to open it in your browser...`, () => resolve());
|
|
68
|
+
});
|
|
69
|
+
openUrl(url);
|
|
70
|
+
return new Promise((resolve) => {
|
|
71
|
+
rl.question("Copy your API key and paste it here: ", (answer) => {
|
|
72
|
+
rl.close();
|
|
73
|
+
resolve(answer.trim());
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Startup payment check: GET /v1/context_memory/status, so an unpaid key is
|
|
79
|
+
* handled BEFORE the first degraded turn. The endpoint may not be deployed
|
|
80
|
+
* yet — 404/405/401/503, network errors, timeouts and unexpected bodies all
|
|
81
|
+
* mean "unknown" (null): the caller stays quiet. Bounded by a short timeout
|
|
82
|
+
* and never throws, so startup is never gated on polychat availability.
|
|
83
|
+
*/
|
|
84
|
+
async function fetchPaymentStatus(baseUrl, apiKey, timeoutMs = 2000) {
|
|
85
|
+
try {
|
|
86
|
+
const res = await fetch(`${baseUrl.replace(/\/$/, "")}/v1/context_memory/status`, {
|
|
87
|
+
headers: {
|
|
88
|
+
authorization: `Bearer ${apiKey}`,
|
|
89
|
+
"x-client": CLIENT_NAME,
|
|
90
|
+
"x-client-version": CLIENT_VERSION,
|
|
91
|
+
},
|
|
92
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
93
|
+
});
|
|
94
|
+
if (!res.ok)
|
|
95
|
+
return null;
|
|
96
|
+
return parsePaymentStatus(await res.json());
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Interactive gate for an unpaid key. The TUI covers the terminal within a
|
|
104
|
+
* second of launch, so a printed warning is never read; instead stop here
|
|
105
|
+
* until the user picks: subscribe now (open the checkout link, then wait for
|
|
106
|
+
* the webhook to flip the key to paid), use claude without MemTree (launch
|
|
107
|
+
* uncompressed, the in-session notice still fires), or quit.
|
|
108
|
+
*/
|
|
109
|
+
async function runPaymentGate(status, recheck) {
|
|
110
|
+
let current = status;
|
|
111
|
+
for (;;) {
|
|
112
|
+
console.warn(`\x1b[1;33m${formatPaymentNotice(current, { hyperlinks: true })}\x1b[0m\n`);
|
|
113
|
+
const choice = parsePaymentChoice(await askLine(PAYMENT_GATE_PROMPT));
|
|
114
|
+
if (choice === "quit")
|
|
115
|
+
process.exit(0);
|
|
116
|
+
if (choice === "continue") {
|
|
117
|
+
console.log("\nStarting claude without MemTree.\n");
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
openUrl(current.url ?? FALLBACK_SUBSCRIBE_URL);
|
|
121
|
+
console.log("\nOpened the subscribe page. Waiting for payment to complete…");
|
|
122
|
+
const paid = await waitUntilPaid(recheck, SUBSCRIBE_WAIT_MS, SUBSCRIBE_POLL_MS);
|
|
123
|
+
if (paid) {
|
|
124
|
+
console.log("\x1b[1;32m✓ MemTree is on — thank you.\x1b[0m\n");
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
console.warn("\nStill unpaid.\n");
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/** Poll the status probe until it reports paid, or give up after `totalMs`. */
|
|
131
|
+
async function waitUntilPaid(recheck, totalMs, everyMs) {
|
|
132
|
+
const deadline = Date.now() + totalMs;
|
|
133
|
+
while (Date.now() < deadline) {
|
|
134
|
+
await new Promise((resolve) => setTimeout(resolve, everyMs));
|
|
135
|
+
const status = await recheck();
|
|
136
|
+
if (status?.paid === true)
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
function askLine(question) {
|
|
142
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
143
|
+
return new Promise((resolve) => {
|
|
144
|
+
rl.question(question, (answer) => {
|
|
145
|
+
rl.close();
|
|
146
|
+
resolve(answer);
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
function printBanner() {
|
|
151
|
+
console.log(`\n\x1b[38;5;209m∞\x1b[0m \x1b[1;38;5;209mClaude Code Infinite\x1b[0m \x1b[38;5;209m∞\x1b[0m \x1b[38;5;48mfrom \x1b]8;;https://MemTree.dev\x1b\\MemTree\x1b]8;;\x1b\\\x1b[0m\n`);
|
|
152
|
+
}
|
|
153
|
+
/** Unknown/old versions get the longstanding Stop fallback only. */
|
|
154
|
+
function installedClaudeSupportsMessageDisplay() {
|
|
155
|
+
try {
|
|
156
|
+
const result = spawn.sync("claude", ["--version"], { encoding: "utf-8" });
|
|
157
|
+
return supportsMessageDisplay(`${result.stdout ?? ""}\n${result.stderr ?? ""}`);
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
async function main() {
|
|
164
|
+
const parsedArgs = parseWrapperArgs(process.argv.slice(2));
|
|
165
|
+
const isDebugMode = parsedArgs.debug;
|
|
166
|
+
const filteredArgs = parsedArgs.claudeArgs;
|
|
167
|
+
// `ccc fetch <memtree-url>`: read one of the user's MemTree pages with the
|
|
168
|
+
// stored key and print it. No proxy, no Claude — an agent's escape hatch
|
|
169
|
+
// when it is not running inside a ccc session.
|
|
170
|
+
if (filteredArgs[0] === "fetch") {
|
|
171
|
+
process.exit(await runMemtreeFetchCommand(filteredArgs.slice(1)));
|
|
172
|
+
}
|
|
173
|
+
// `ccc memtree-mcp`: the `memtree` MCP server over stdio (memtree-mcp.ts),
|
|
174
|
+
// for an --mcp-config a caller writes (e.g. the memory recall probe). It
|
|
175
|
+
// reads the tree through the ccc proxy in its inherited ANTHROPIC_BASE_URL.
|
|
176
|
+
if (filteredArgs[0] === "memtree-mcp") {
|
|
177
|
+
runMemtreeMcpServer();
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
const mode = filteredArgs[0] === "local" ? "local" :
|
|
181
|
+
filteredArgs[0] === "staging" ? "staging" :
|
|
182
|
+
"production";
|
|
183
|
+
const claudeArgs = mode !== "production" ? filteredArgs.slice(1) : filteredArgs;
|
|
184
|
+
printBanner();
|
|
185
|
+
if (isDebugMode) {
|
|
186
|
+
console.log("\x1b[1;36m🔍 DEBUG MODE\x1b[0m\n");
|
|
187
|
+
}
|
|
188
|
+
if (mode === "local") {
|
|
189
|
+
console.log("\x1b[1;33m🏠 LOCAL MODE\x1b[0m\n");
|
|
190
|
+
}
|
|
191
|
+
else if (mode === "staging") {
|
|
192
|
+
console.log("\x1b[1;35m🚧 STAGING MODE\x1b[0m\n");
|
|
193
|
+
}
|
|
194
|
+
// Get or prompt for the MemTree API key (separate keys per environment)
|
|
195
|
+
let polychatApiKey = mode === "local" ? getLocalPolychatApiKey() :
|
|
196
|
+
mode === "staging" ? getStagingPolychatApiKey() :
|
|
197
|
+
getPolychatApiKey();
|
|
198
|
+
if (!polychatApiKey) {
|
|
199
|
+
polychatApiKey = await promptForApiKey(mode);
|
|
200
|
+
if (!polychatApiKey) {
|
|
201
|
+
console.error("A MemTree API key is required.");
|
|
202
|
+
process.exit(1);
|
|
203
|
+
}
|
|
204
|
+
if (mode === "local") {
|
|
205
|
+
setLocalPolychatApiKey(polychatApiKey);
|
|
206
|
+
}
|
|
207
|
+
else if (mode === "staging") {
|
|
208
|
+
setStagingPolychatApiKey(polychatApiKey);
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
setPolychatApiKey(polychatApiKey);
|
|
212
|
+
}
|
|
213
|
+
console.log("API key saved.\n");
|
|
214
|
+
}
|
|
215
|
+
const memtreeBaseUrl = mode === "local" ? LOCAL_BASE_URL :
|
|
216
|
+
mode === "staging" ? STAGING_BASE_URL :
|
|
217
|
+
POLYCHAT_BASE_URL;
|
|
218
|
+
// Interactive UI only: print/non-TTY invocations are programmatic
|
|
219
|
+
// interfaces whose output must stay byte-for-byte vanilla, and they get no
|
|
220
|
+
// notice plugin to deliver a banner anyway.
|
|
221
|
+
const interactiveUi = !isPrintInvocation(claudeArgs) &&
|
|
222
|
+
process.stdin.isTTY === true &&
|
|
223
|
+
process.stdout.isTTY === true;
|
|
224
|
+
// Check the key's payment status before claude takes over the terminal.
|
|
225
|
+
// Bounded (2s) and null on error — startup never fails or hangs on polychat
|
|
226
|
+
// availability. The npm update check runs concurrently under the same
|
|
227
|
+
// bound; its result goes into the SessionStart banner below, since the TUI
|
|
228
|
+
// covers this terminal within a second. Both resolve rather than reject, so
|
|
229
|
+
// Promise.all cannot throw.
|
|
230
|
+
// The project (directory, git repo, branch, commit) goes with every MemTree
|
|
231
|
+
// call so sessions can be found by project; read once, never fails.
|
|
232
|
+
const [paymentStatus, updateAvailable, projectMeta] = await Promise.all([
|
|
233
|
+
fetchPaymentStatus(memtreeBaseUrl, polychatApiKey),
|
|
234
|
+
checkForUpdate({ currentVersion: CLIENT_VERSION }),
|
|
235
|
+
readProjectMeta(process.cwd()),
|
|
236
|
+
]);
|
|
237
|
+
if (paymentStatus?.paid === false) {
|
|
238
|
+
if (interactiveUi) {
|
|
239
|
+
await runPaymentGate(paymentStatus, () => fetchPaymentStatus(memtreeBaseUrl, polychatApiKey));
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
console.warn(`\x1b[1;33m${formatPaymentNotice(paymentStatus)}\x1b[0m`);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
if (isDebugMode && updateAvailable) {
|
|
246
|
+
console.log(`[DEBUG] Update available: ${updateAvailable.current} → ${updateAvailable.latest}`);
|
|
247
|
+
}
|
|
248
|
+
// Always-on request/timing log (reqlog.ts): messages, MemTree calls, and
|
|
249
|
+
// successful notice claims, so incidents can be reconstructed after the
|
|
250
|
+
// fact without --debug. Never blocks or throws.
|
|
251
|
+
const reqlog = new RequestLogger();
|
|
252
|
+
// The `memtree` MCP server (memtree-mcp-config.ts): registered by ccc for
|
|
253
|
+
// interactive sessions unless CCC_MEMTREE_MCP=0; print/non-TTY runs have it
|
|
254
|
+
// only when their own --mcp-config names it. Either way MemTree is told
|
|
255
|
+
// (x-memtree-tools) only when the session really has the tools.
|
|
256
|
+
const autoMemtreeMcp = interactiveUi && memtreeMcpEnabledByEnv(process.env);
|
|
257
|
+
const memtreeToolsConfigured = autoMemtreeMcp || argsConfigureMemtreeMcp(claudeArgs);
|
|
258
|
+
// Start the local proxy. Claude Code's OAuth token flows through it straight
|
|
259
|
+
// to api.anthropic.com and never reaches polychat.co.
|
|
260
|
+
const memtree = new MemtreeClient({
|
|
261
|
+
baseUrl: memtreeBaseUrl,
|
|
262
|
+
apiKey: polychatApiKey,
|
|
263
|
+
debug: isDebugMode,
|
|
264
|
+
reqlog,
|
|
265
|
+
// Mutable below: a failed config write withdraws it before any call.
|
|
266
|
+
memtreeTools: memtreeToolsConfigured ? MEMTREE_TOOLS_HEADER_VALUE : undefined,
|
|
267
|
+
});
|
|
268
|
+
const nativeOneMillionContext = claudeNativeOneMillionContextEnabled(process.env);
|
|
269
|
+
const memtreeLinkPlacement = memtreeLinkPlacementFromEnv(process.env.CCC_MEMTREE_LINK);
|
|
270
|
+
const transcriptUsage = new ClaudeTranscriptUsage();
|
|
271
|
+
const proxy = await startProxy({
|
|
272
|
+
memtree,
|
|
273
|
+
debug: isDebugMode,
|
|
274
|
+
reqlog,
|
|
275
|
+
nativeOneMillionContext,
|
|
276
|
+
// Kill switch for tool-turn COMPACTION only: CCC_TOOL_ROUTE_RECOVERY=0
|
|
277
|
+
// makes tool turns pure passthrough — no size check, no compress call;
|
|
278
|
+
// they ride their lane's route when one exists and otherwise go out whole
|
|
279
|
+
// (with background indexing). Human turns keep compacting. It
|
|
280
|
+
// deliberately does NOT revert classification-time clear gating or
|
|
281
|
+
// same-session-only eviction of a rejected route, because those are what
|
|
282
|
+
// stop a side request from stranding the tool loop.
|
|
283
|
+
toolRouteRecovery: process.env.CCC_TOOL_ROUTE_RECOVERY !== "0",
|
|
284
|
+
// Exact sizes from Count Tokens where an estimate would decide alone
|
|
285
|
+
// (unknown, a big jump near the budget, or a refusal). CCC_COUNT_TOKENS=0
|
|
286
|
+
// keeps estimates only.
|
|
287
|
+
countTokens: process.env.CCC_COUNT_TOKENS !== "0",
|
|
288
|
+
// Programs launched from inside Claude Code inherit ANTHROPIC_BASE_URL;
|
|
289
|
+
// only Claude Code's own requests get MemTree. CCC_CLAUDE_CODE_ONLY=0
|
|
290
|
+
// turns the filter off.
|
|
291
|
+
claudeCodeOnly: process.env.CCC_CLAUDE_CODE_ONLY !== "0",
|
|
292
|
+
defaultCompactTarget: defaultCompactTargetFromEnv(process.env.CCC_COMPACT_TARGET),
|
|
293
|
+
// Debugging: write every forwarded Anthropic request body to this directory.
|
|
294
|
+
...(process.env.CCC_CAPTURE_DIR ? { captureDir: process.env.CCC_CAPTURE_DIR } : {}),
|
|
295
|
+
// Test-only: a small budget so a cheap session crosses it in a few turns.
|
|
296
|
+
budgetTokensOverride: budgetFromEnv(process.env.CCC_BUDGET_TOKENS),
|
|
297
|
+
// CCC_MEMTREE_LINK=message|stop|success|off picks where the MemTree page
|
|
298
|
+
// link is shown while the placement is being tried out; see ProxyOptions.
|
|
299
|
+
memtreeLinkPlacement,
|
|
300
|
+
memtreeLinkStore: new MemtreeLinkStore(),
|
|
301
|
+
// The link shown to the user follows the session's newest tree on the server.
|
|
302
|
+
newestTrees: new NewestTreeLookup((path, signal) => memtree.fetchMemTree(path, "application/json", signal)),
|
|
303
|
+
transcriptUsage,
|
|
304
|
+
projectMeta,
|
|
305
|
+
});
|
|
306
|
+
// One unobtrusive (dim) line so users can find the log during an incident.
|
|
307
|
+
console.log(`\x1b[2mRequest log: ${reqlog.path}\x1b[0m\n`);
|
|
308
|
+
reportStrandedResumeRepair(claudeArgs, nativeOneMillionContext);
|
|
309
|
+
// The first request after a resume must count the whole session's thinking.
|
|
310
|
+
const resumedSession = resumeSessionId(claudeArgs);
|
|
311
|
+
if (resumedSession !== undefined)
|
|
312
|
+
transcriptUsage.catchUp(resumedSession);
|
|
313
|
+
if (isDebugMode) {
|
|
314
|
+
console.log(`[DEBUG] Local proxy listening on http://127.0.0.1:${proxy.port}`);
|
|
315
|
+
console.log(`[DEBUG] MemTree API: ${memtreeBaseUrl}`);
|
|
316
|
+
console.log(`[DEBUG] Claude Code auto-compaction: ${process.env.CCC_AUTO_COMPACT === "1"
|
|
317
|
+
? "native setting (CCC_AUTO_COMPACT=1)"
|
|
318
|
+
: "disabled by ccc"}`);
|
|
319
|
+
console.log(`[DEBUG] Claude Code native 1M context: ${nativeOneMillionContext
|
|
320
|
+
? "enabled through trusted localhost relay"
|
|
321
|
+
: "disabled by CLAUDE_CODE_DISABLE_1M_CONTEXT"}`);
|
|
322
|
+
}
|
|
323
|
+
// Interactive notices are provided by a minimal, ephemeral plugin. Prepending
|
|
324
|
+
// --plugin-dir composes with user hooks/settings; adding another --settings
|
|
325
|
+
// would not, because Claude keeps only its final --settings occurrence.
|
|
326
|
+
// Print/non-TTY calls are programmatic interfaces: omit all UI hooks so their
|
|
327
|
+
// stdout/events remain byte-for-byte vanilla.
|
|
328
|
+
let noticePlugin = null;
|
|
329
|
+
let childArgs = [...claudeArgs];
|
|
330
|
+
if (interactiveUi) {
|
|
331
|
+
try {
|
|
332
|
+
noticePlugin = createSessionNoticePlugin(proxy.hookUrl, {
|
|
333
|
+
messageDisplay: installedClaudeSupportsMessageDisplay(),
|
|
334
|
+
startupMessage: startupNoticeText(terminalSupportsColor(), updateAvailable),
|
|
335
|
+
resumeLink: memtreeLinkPlacement !== "off",
|
|
336
|
+
});
|
|
337
|
+
// Global option must precede a user-supplied `--`, positional prompt, or
|
|
338
|
+
// subcommand; --plugin-dir itself is repeatable, so existing dirs remain.
|
|
339
|
+
childArgs = withSessionNoticePluginArgs(childArgs, noticePlugin.dir);
|
|
340
|
+
}
|
|
341
|
+
catch (err) {
|
|
342
|
+
// Notices are optional UI. A full/unwritable temp directory must never
|
|
343
|
+
// prevent the underlying Claude session from launching.
|
|
344
|
+
if (isDebugMode) {
|
|
345
|
+
console.error(`[DEBUG] Notice plugin disabled: ${String(err)}`);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
let memtreeMcpConfig = null;
|
|
350
|
+
if (autoMemtreeMcp) {
|
|
351
|
+
try {
|
|
352
|
+
memtreeMcpConfig = writeMemtreeMcpConfig(`http://127.0.0.1:${proxy.port}`);
|
|
353
|
+
childArgs = withMemtreeMcpArgs(childArgs, memtreeMcpConfig.path);
|
|
354
|
+
}
|
|
355
|
+
catch (err) {
|
|
356
|
+
// Optional like the notice plugin; without it MemTree must not name
|
|
357
|
+
// tools the session lacks.
|
|
358
|
+
if (!argsConfigureMemtreeMcp(claudeArgs))
|
|
359
|
+
memtree.setMemtreeTools(undefined);
|
|
360
|
+
if (isDebugMode) {
|
|
361
|
+
console.error(`[DEBUG] MemTree MCP server disabled: ${String(err)}`);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
// Never set ANTHROPIC_AUTH_TOKEN / ANTHROPIC_API_KEY — Claude Code keeps its
|
|
366
|
+
// native login and sends its own OAuth bearer to the local base URL.
|
|
367
|
+
const child = spawn("claude", childArgs, {
|
|
368
|
+
env: claudeChildEnv(process.env, `http://127.0.0.1:${proxy.port}`),
|
|
369
|
+
stdio: "inherit",
|
|
370
|
+
});
|
|
371
|
+
let shuttingDown = false;
|
|
372
|
+
const shutdown = async (code) => {
|
|
373
|
+
if (shuttingDown)
|
|
374
|
+
return;
|
|
375
|
+
shuttingDown = true;
|
|
376
|
+
noticePlugin?.close();
|
|
377
|
+
memtreeMcpConfig?.close();
|
|
378
|
+
// Stop new proxy work and give active handlers a bounded chance to
|
|
379
|
+
// finalize their records. Background indexing is a separate log producer:
|
|
380
|
+
// stop and drain it too before waiting for scheduled JSONL appends on
|
|
381
|
+
// disk.
|
|
382
|
+
await proxy.drain(SHUTDOWN_PROXY_DRAIN_MS);
|
|
383
|
+
// A session ending now sends its final index at once (the idle timer
|
|
384
|
+
// would never fire), inside the same bounded background drain.
|
|
385
|
+
memtree.flushFinalIndexes();
|
|
386
|
+
await memtree.drainBackground(SHUTDOWN_MEMTREE_DRAIN_MS);
|
|
387
|
+
await reqlog.flush(SHUTDOWN_LOG_FLUSH_MS);
|
|
388
|
+
process.exit(code);
|
|
389
|
+
};
|
|
390
|
+
const handleShutdownSignal = createSignalShutdownHandler({
|
|
391
|
+
forward: (signal) => {
|
|
392
|
+
// A terminal normally signals the whole foreground process group, while
|
|
393
|
+
// `kill <ccc-pid>` reaches only this wrapper. Forwarding covers the
|
|
394
|
+
// latter; duplicate delivery to Claude is harmless.
|
|
395
|
+
if (child.exitCode !== null || child.signalCode !== null)
|
|
396
|
+
return;
|
|
397
|
+
try {
|
|
398
|
+
child.kill(signal);
|
|
399
|
+
}
|
|
400
|
+
catch {
|
|
401
|
+
// The child may have exited between the state check and kill().
|
|
402
|
+
}
|
|
403
|
+
},
|
|
404
|
+
shutdown: (code) => void shutdown(code),
|
|
405
|
+
// A second signal is an explicit escape hatch from bounded cleanup.
|
|
406
|
+
forceExit: (code) => process.exit(code),
|
|
407
|
+
});
|
|
408
|
+
process.on("SIGINT", () => handleShutdownSignal("SIGINT"));
|
|
409
|
+
process.on("SIGTERM", () => handleShutdownSignal("SIGTERM"));
|
|
410
|
+
child.on("error", (err) => {
|
|
411
|
+
if (err.code === "ENOENT") {
|
|
412
|
+
console.error("Could not find 'claude' command. Make sure Claude Code is installed.");
|
|
413
|
+
}
|
|
414
|
+
else {
|
|
415
|
+
console.error("Failed to start claude:", err.message);
|
|
416
|
+
}
|
|
417
|
+
void shutdown(1);
|
|
418
|
+
});
|
|
419
|
+
child.on("exit", (code, signal) => {
|
|
420
|
+
void shutdown(exitCodeForChild(code, signal));
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
main().catch((err) => {
|
|
424
|
+
console.error(err);
|
|
425
|
+
process.exit(1);
|
|
426
|
+
});
|
|
427
|
+
/** `CCC_COMPACT_TARGET` ("500k", "20000", "off"): see cli-args.ts. */
|
|
428
|
+
/**
|
|
429
|
+
* A resumed session whose last response was recorded past Claude Code's limit
|
|
430
|
+
* would refuse every prompt; lower that record first (resume-repair.ts).
|
|
431
|
+
* Never blocks the launch.
|
|
432
|
+
*/
|
|
433
|
+
function reportStrandedResumeRepair(claudeArgs, nativeOneMillionContext) {
|
|
434
|
+
try {
|
|
435
|
+
const repair = repairStrandedResume(claudeArgs, { nativeOneMillionContext });
|
|
436
|
+
if (!repair)
|
|
437
|
+
return;
|
|
438
|
+
const k = (tokens) => `${Math.round(tokens / 1000)}k`;
|
|
439
|
+
console.log(`\x1b[2mThis session last recorded ${k(repair.recordedTokens)} tokens, past Claude ` +
|
|
440
|
+
`Code's limit; lowered to ${k(repair.loweredTokens)} so MemTree can compress the ` +
|
|
441
|
+
`next message. Backup: ${repair.backupPath}\x1b[0m\n`);
|
|
442
|
+
}
|
|
443
|
+
catch (err) {
|
|
444
|
+
console.error(`\x1b[2mCould not check the resumed session's size: ${String(err)}\x1b[0m`);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
function defaultCompactTargetFromEnv(raw) {
|
|
448
|
+
const { value, warning } = compactTargetFromEnv(raw, parseTokenCount, MEMTREE_COMPACT_MIN_TOKENS);
|
|
449
|
+
if (warning)
|
|
450
|
+
console.error(warning);
|
|
451
|
+
return value;
|
|
452
|
+
}
|
|
453
|
+
/** `CCC_BUDGET_TOKENS` ("60k"): a test-only whole-request budget, or undefined. */
|
|
454
|
+
function budgetFromEnv(raw) {
|
|
455
|
+
if (!raw)
|
|
456
|
+
return undefined;
|
|
457
|
+
const budget = parseTokenCount(raw);
|
|
458
|
+
if (budget === undefined || budget < 2 * MEMTREE_COMPACT_MIN_TOKENS) {
|
|
459
|
+
console.error(`ccc: ignoring CCC_BUDGET_TOKENS=${raw} (use a token count of at least ${(2 * MEMTREE_COMPACT_MIN_TOKENS) / 1000}k)`);
|
|
460
|
+
return undefined;
|
|
461
|
+
}
|
|
462
|
+
return budget;
|
|
463
|
+
}
|
|
464
|
+
//# sourceMappingURL=cli-main.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-main.js","sourceRoot":"","sources":["../src/cli-main.ts"],"names":[],"mappings":"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"}
|