claude-code-infinite 1.0.11 → 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.
Files changed (136) hide show
  1. package/README.md +214 -47
  2. package/dist/cc-request.d.ts +94 -0
  3. package/dist/cc-request.d.ts.map +1 -0
  4. package/dist/cc-request.js +194 -0
  5. package/dist/cc-request.js.map +1 -0
  6. package/dist/claude-env.d.ts +30 -0
  7. package/dist/claude-env.d.ts.map +1 -0
  8. package/dist/claude-env.js +55 -0
  9. package/dist/claude-env.js.map +1 -0
  10. package/dist/cli-args.d.ts +32 -0
  11. package/dist/cli-args.d.ts.map +1 -0
  12. package/dist/cli-args.js +72 -0
  13. package/dist/cli-args.js.map +1 -0
  14. package/dist/cli-lifecycle.d.ts +17 -0
  15. package/dist/cli-lifecycle.d.ts.map +1 -0
  16. package/dist/cli-lifecycle.js +30 -0
  17. package/dist/cli-lifecycle.js.map +1 -0
  18. package/dist/cli-main.d.ts +15 -0
  19. package/dist/cli-main.d.ts.map +1 -0
  20. package/dist/cli-main.js +464 -0
  21. package/dist/cli-main.js.map +1 -0
  22. package/dist/cli.js +13 -178
  23. package/dist/cli.js.map +1 -1
  24. package/dist/config.d.ts +3 -0
  25. package/dist/config.d.ts.map +1 -1
  26. package/dist/config.js +29 -3
  27. package/dist/config.js.map +1 -1
  28. package/dist/count-tokens.d.ts +78 -0
  29. package/dist/count-tokens.d.ts.map +1 -0
  30. package/dist/count-tokens.js +277 -0
  31. package/dist/count-tokens.js.map +1 -0
  32. package/dist/final-index.d.ts +10 -0
  33. package/dist/final-index.d.ts.map +1 -0
  34. package/dist/final-index.js +37 -0
  35. package/dist/final-index.js.map +1 -0
  36. package/dist/hooks.d.ts +239 -0
  37. package/dist/hooks.d.ts.map +1 -0
  38. package/dist/hooks.js +618 -0
  39. package/dist/hooks.js.map +1 -0
  40. package/dist/index.d.ts +9 -0
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +8 -0
  43. package/dist/index.js.map +1 -1
  44. package/dist/memtree-fetch.d.ts +24 -0
  45. package/dist/memtree-fetch.d.ts.map +1 -0
  46. package/dist/memtree-fetch.js +121 -0
  47. package/dist/memtree-fetch.js.map +1 -0
  48. package/dist/memtree-finder.d.ts +99 -0
  49. package/dist/memtree-finder.d.ts.map +1 -0
  50. package/dist/memtree-finder.js +235 -0
  51. package/dist/memtree-finder.js.map +1 -0
  52. package/dist/memtree-links.d.ts +16 -0
  53. package/dist/memtree-links.d.ts.map +1 -0
  54. package/dist/memtree-links.js +66 -0
  55. package/dist/memtree-links.js.map +1 -0
  56. package/dist/memtree-mcp-config.d.ts +28 -0
  57. package/dist/memtree-mcp-config.d.ts.map +1 -0
  58. package/dist/memtree-mcp-config.js +121 -0
  59. package/dist/memtree-mcp-config.js.map +1 -0
  60. package/dist/memtree-mcp.d.ts +265 -0
  61. package/dist/memtree-mcp.d.ts.map +1 -0
  62. package/dist/memtree-mcp.js +667 -0
  63. package/dist/memtree-mcp.js.map +1 -0
  64. package/dist/memtree-newest.d.ts +74 -0
  65. package/dist/memtree-newest.d.ts.map +1 -0
  66. package/dist/memtree-newest.js +217 -0
  67. package/dist/memtree-newest.js.map +1 -0
  68. package/dist/memtree-tools.d.ts +105 -0
  69. package/dist/memtree-tools.d.ts.map +1 -0
  70. package/dist/memtree-tools.js +408 -0
  71. package/dist/memtree-tools.js.map +1 -0
  72. package/dist/memtree.d.ts +398 -0
  73. package/dist/memtree.d.ts.map +1 -0
  74. package/dist/memtree.js +1231 -0
  75. package/dist/memtree.js.map +1 -0
  76. package/dist/notices.d.ts +177 -0
  77. package/dist/notices.d.ts.map +1 -0
  78. package/dist/notices.js +469 -0
  79. package/dist/notices.js.map +1 -0
  80. package/dist/payment-gate.d.ts +53 -0
  81. package/dist/payment-gate.d.ts.map +1 -0
  82. package/dist/payment-gate.js +97 -0
  83. package/dist/payment-gate.js.map +1 -0
  84. package/dist/project-meta.d.ts +15 -0
  85. package/dist/project-meta.d.ts.map +1 -0
  86. package/dist/project-meta.js +80 -0
  87. package/dist/project-meta.js.map +1 -0
  88. package/dist/prompt-accounting.d.ts +12 -0
  89. package/dist/prompt-accounting.d.ts.map +1 -0
  90. package/dist/prompt-accounting.js +70 -0
  91. package/dist/prompt-accounting.js.map +1 -0
  92. package/dist/proxy.d.ts +197 -0
  93. package/dist/proxy.d.ts.map +1 -0
  94. package/dist/proxy.js +4247 -0
  95. package/dist/proxy.js.map +1 -0
  96. package/dist/reqlog.d.ts +419 -0
  97. package/dist/reqlog.d.ts.map +1 -0
  98. package/dist/reqlog.js +146 -0
  99. package/dist/reqlog.js.map +1 -0
  100. package/dist/request-sizing.d.ts +52 -0
  101. package/dist/request-sizing.d.ts.map +1 -0
  102. package/dist/request-sizing.js +92 -0
  103. package/dist/request-sizing.js.map +1 -0
  104. package/dist/resume-repair-file.d.ts +17 -0
  105. package/dist/resume-repair-file.d.ts.map +1 -0
  106. package/dist/resume-repair-file.js +100 -0
  107. package/dist/resume-repair-file.js.map +1 -0
  108. package/dist/resume-repair.d.ts +27 -0
  109. package/dist/resume-repair.d.ts.map +1 -0
  110. package/dist/resume-repair.js +198 -0
  111. package/dist/resume-repair.js.map +1 -0
  112. package/dist/route-cache.d.ts +5 -0
  113. package/dist/route-cache.d.ts.map +1 -0
  114. package/dist/route-cache.js +63 -0
  115. package/dist/route-cache.js.map +1 -0
  116. package/dist/route-fallback.d.ts +29 -0
  117. package/dist/route-fallback.d.ts.map +1 -0
  118. package/dist/route-fallback.js +49 -0
  119. package/dist/route-fallback.js.map +1 -0
  120. package/dist/route-identity.d.ts +6 -0
  121. package/dist/route-identity.d.ts.map +1 -0
  122. package/dist/route-identity.js +100 -0
  123. package/dist/route-identity.js.map +1 -0
  124. package/dist/transcript-usage.d.ts +57 -0
  125. package/dist/transcript-usage.d.ts.map +1 -0
  126. package/dist/transcript-usage.js +570 -0
  127. package/dist/transcript-usage.js.map +1 -0
  128. package/dist/turns.d.ts +73 -0
  129. package/dist/turns.d.ts.map +1 -0
  130. package/dist/turns.js +298 -0
  131. package/dist/turns.js.map +1 -0
  132. package/dist/update-check.d.ts +38 -0
  133. package/dist/update-check.d.ts.map +1 -0
  134. package/dist/update-check.js +67 -0
  135. package/dist/update-check.js.map +1 -0
  136. package/package.json +6 -2
@@ -0,0 +1,15 @@
1
+ export interface ProjectMeta {
2
+ project_dir?: string;
3
+ git_repo?: string;
4
+ git_branch?: string;
5
+ git_commit?: string;
6
+ }
7
+ export type GitRunner = (args: string[], cwd: string) => Promise<string | undefined>;
8
+ export declare function readProjectMeta(cwd?: string, git?: GitRunner): Promise<ProjectMeta>;
9
+ /**
10
+ * `owner/repo` from a remote URL in any of git's forms (`https://…`,
11
+ * `ssh://…`, `git@host:owner/repo.git`, a local path): the last two path
12
+ * segments, `.git` dropped. Host, user, password and query never survive.
13
+ */
14
+ export declare function repoNameFromRemote(remote: string): string | undefined;
15
+ //# sourceMappingURL=project-meta.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-meta.d.ts","sourceRoot":"","sources":["../src/project-meta.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,WAAW;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAMD,MAAM,MAAM,SAAS,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;AAErF,wBAAsB,eAAe,CACnC,GAAG,GAAE,MAAsB,EAC3B,GAAG,GAAE,SAAkB,GACtB,OAAO,CAAC,WAAW,CAAC,CAiBtB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAuBrE"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * The project a ccc session runs in, sent with every MemTree call in
3
+ * `x-client-meta` (cc-request.ts memtreeClientMeta) so the user can list and
4
+ * search their sessions by project (`GET /v1/memtree/sessions?project=`).
5
+ *
6
+ * Read once at startup from the working directory: its name, the `origin`
7
+ * remote reduced to `owner/repo` (never the URL, so no host, user or token
8
+ * leaves the machine), the branch and the short HEAD commit. Every part is
9
+ * optional: outside a git repository, with git missing, or when a command is
10
+ * slow, the part is simply left out. Never throws.
11
+ */
12
+ import { execFile } from "node:child_process";
13
+ import path from "node:path";
14
+ /** What the server keeps: short printable ASCII (client_session.py). */
15
+ const META_VALUE = /^[\x20-\x7e]{1,128}$/;
16
+ const GIT_TIMEOUT_MS = 1_500;
17
+ export async function readProjectMeta(cwd = process.cwd(), git = runGit) {
18
+ const [remote, branch, commit] = await Promise.all([
19
+ git(["remote", "get-url", "origin"], cwd),
20
+ git(["rev-parse", "--abbrev-ref", "HEAD"], cwd),
21
+ git(["rev-parse", "--short", "HEAD"], cwd),
22
+ ]);
23
+ const candidate = {
24
+ project_dir: path.basename(path.resolve(cwd)),
25
+ git_repo: remote ? repoNameFromRemote(remote) : undefined,
26
+ git_branch: branch && branch !== "HEAD" ? branch : undefined,
27
+ git_commit: commit && /^[0-9a-f]{4,40}$/.test(commit) ? commit : undefined,
28
+ };
29
+ const meta = {};
30
+ for (const [key, value] of Object.entries(candidate)) {
31
+ if (value && META_VALUE.test(value))
32
+ meta[key] = value;
33
+ }
34
+ return meta;
35
+ }
36
+ /**
37
+ * `owner/repo` from a remote URL in any of git's forms (`https://…`,
38
+ * `ssh://…`, `git@host:owner/repo.git`, a local path): the last two path
39
+ * segments, `.git` dropped. Host, user, password and query never survive.
40
+ */
41
+ export function repoNameFromRemote(remote) {
42
+ let pathPart = remote.trim();
43
+ if (!pathPart)
44
+ return undefined;
45
+ const scheme = /^[A-Za-z][A-Za-z0-9+.-]*:\/\//.exec(pathPart);
46
+ if (scheme) {
47
+ try {
48
+ pathPart = new URL(pathPart).pathname;
49
+ }
50
+ catch {
51
+ return undefined;
52
+ }
53
+ }
54
+ else {
55
+ // scp-like `user@host:owner/repo`: everything after the first colon.
56
+ const scp = /^[^/:]+:(.*)$/.exec(pathPart);
57
+ if (scp)
58
+ pathPart = scp[1];
59
+ }
60
+ const segments = pathPart
61
+ .replace(/[?#].*$/, "")
62
+ .split(/[/\\]+/)
63
+ .filter(Boolean);
64
+ if (!segments.length)
65
+ return undefined;
66
+ segments[segments.length - 1] = segments[segments.length - 1].replace(/\.git$/, "");
67
+ const name = segments.slice(-2).join("/");
68
+ return name && !name.includes("@") ? name : undefined;
69
+ }
70
+ function runGit(args, cwd) {
71
+ return new Promise((resolve) => {
72
+ try {
73
+ execFile("git", args, { cwd, timeout: GIT_TIMEOUT_MS, windowsHide: true }, (err, stdout) => resolve(err ? undefined : String(stdout).trim() || undefined));
74
+ }
75
+ catch {
76
+ resolve(undefined);
77
+ }
78
+ });
79
+ }
80
+ //# sourceMappingURL=project-meta.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-meta.js","sourceRoot":"","sources":["../src/project-meta.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /** Display-only accounting: this class has no route authority. */
2
+ export declare class PromptAccounting {
3
+ private readonly now;
4
+ private records;
5
+ constructor(now?: () => number);
6
+ add(sessionId: string | undefined, id: string | undefined, text: string | undefined): void;
7
+ hasId(id: string): boolean;
8
+ capture(sessionId: string | undefined, message: any): (delivered: boolean) => void;
9
+ pending(sessionId?: string): number;
10
+ private expire;
11
+ }
12
+ //# sourceMappingURL=prompt-accounting.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt-accounting.d.ts","sourceRoot":"","sources":["../src/prompt-accounting.ts"],"names":[],"mappings":"AAQA,kEAAkE;AAClE,qBAAa,gBAAgB;IAEf,OAAO,CAAC,QAAQ,CAAC,GAAG;IADhC,OAAO,CAAC,OAAO,CAAsB;gBACR,GAAG,eAAW;IAE3C,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE,EAAE,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAW1F,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAK1B,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,GAAG,GAAG,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI;IAmBlF,OAAO,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM;IAKnC,OAAO,CAAC,MAAM;CAGf"}
@@ -0,0 +1,70 @@
1
+ import { stripSystemReminderText } from "./turns.js";
2
+ const SESSION_PROMPT_LIMIT = 32;
3
+ const TOTAL_PROMPT_LIMIT = 4096;
4
+ const PROMPT_TTL_MS = 10 * 60_000;
5
+ /** Display-only accounting: this class has no route authority. */
6
+ export class PromptAccounting {
7
+ now;
8
+ records = [];
9
+ constructor(now = Date.now) {
10
+ this.now = now;
11
+ }
12
+ add(sessionId, id, text) {
13
+ this.expire();
14
+ const sameSession = this.records.filter((item) => item.sessionId === sessionId);
15
+ if (sameSession.length >= SESSION_PROMPT_LIMIT) {
16
+ this.records.splice(this.records.indexOf(sameSession[0]), 1);
17
+ }
18
+ // Also bound process-wide state when one proxy observes many sessions.
19
+ if (this.records.length >= TOTAL_PROMPT_LIMIT)
20
+ this.records.shift();
21
+ this.records.push({ sessionId, id, text, createdAt: this.now() });
22
+ }
23
+ hasId(id) {
24
+ this.expire();
25
+ return this.records.some((item) => item.id === id);
26
+ }
27
+ capture(sessionId, message) {
28
+ this.expire();
29
+ const texts = new Set(deliveredTexts(message).map(normalizeDeliveryText).filter(Boolean));
30
+ const candidates = new Set(this.records.filter((item) => item.sessionId === sessionId &&
31
+ texts.has(normalizeDeliveryText(item.text ?? ""))));
32
+ let settled = false;
33
+ return (delivered) => {
34
+ if (settled)
35
+ return;
36
+ settled = true;
37
+ if (!delivered)
38
+ return;
39
+ // Select the oldest still-pending snapshot record at settlement. Two
40
+ // concurrent deliveries can then retire two duplicates, while neither
41
+ // may consume a hook record that arrived after its request started.
42
+ this.expire();
43
+ this.records = this.records.filter((item) => !candidates.has(item) || !texts.delete(normalizeDeliveryText(item.text ?? "")));
44
+ };
45
+ }
46
+ pending(sessionId) {
47
+ this.expire();
48
+ return this.records.filter((item) => item.sessionId === sessionId).length;
49
+ }
50
+ expire() {
51
+ this.records = this.records.filter((item) => this.now() - item.createdAt < PROMPT_TTL_MS);
52
+ }
53
+ }
54
+ function deliveredTexts(message) {
55
+ if (message?.role !== "user")
56
+ return [];
57
+ if (typeof message.content === "string")
58
+ return [message.content];
59
+ if (!Array.isArray(message.content))
60
+ return [];
61
+ return message.content.flatMap((part) => {
62
+ if (typeof part === "string")
63
+ return [part];
64
+ return part?.type === "text" && typeof part.text === "string" ? [part.text] : [];
65
+ });
66
+ }
67
+ function normalizeDeliveryText(text) {
68
+ return stripSystemReminderText(text).replace(/\s+/g, " ").trim();
69
+ }
70
+ //# sourceMappingURL=prompt-accounting.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt-accounting.js","sourceRoot":"","sources":["../src/prompt-accounting.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,197 @@
1
+ /**
2
+ * Claude Code Infinite local proxy (plans/2026-06-09_PLAN_local_proxy_app.md,
3
+ * refined by plans/2026-07-05_PLAN_first_user_turn_nonblocking.md).
4
+ *
5
+ * Claude Code points ANTHROPIC_BASE_URL at this 127.0.0.1 server. We never
6
+ * read, store, or refresh credentials: Claude Code keeps its native login and
7
+ * sends its own OAuth bearer here, and we forward its headers and query string
8
+ * verbatim to api.anthropic.com (the anthropic-beta flag list churns across CC
9
+ * versions — never reconstruct it). Only the `messages` body is ever altered
10
+ * (compression, plus defensive removal of legacy notice markers);
11
+ * auth, identity, and routing are never touched.
12
+ *
13
+ * Turn classification for POST /v1/messages:
14
+ * - Tool turn (last message isn't a real user input): background indexing,
15
+ * forward as-is — riding its lane's memory route (routes live in a small
16
+ * map keyed by request identity: session + main/away/agent-id), on the main
17
+ * thread the session's stable prefix, or verbatim — while the estimated
18
+ * size is under the budget, with no compress call. At the budget it
19
+ * compresses once to the target (planToolCompaction), the same rule human
20
+ * turns follow; on the main thread the result becomes the stable prefix
21
+ * later tool and human turns ride. Failure degrades to the old ride or the
22
+ * verbatim forward. Every identity installs into its own lane — isolation
23
+ * is structural, not defended.
24
+ * - First user turn (no earlier real user input): background indexing, forward
25
+ * as-is — nothing is indexed yet, so blocking would be a guaranteed no-op.
26
+ * - Followup user turn: blocking compress + substitute. The compressed body
27
+ * remains the prefix for that turn's tool loop. On the main thread a
28
+ * compaction also becomes the session's stable prefix (planEdgeCompaction):
29
+ * later human turns ride it byte for byte, with no compress call, until
30
+ * prefix + newer turns reach the budget or the covered messages change.
31
+ * - MemTree failure/timeout degrades to passthrough. A display-only success
32
+ * notice is queued only when the memory response is selected AND MemTree's
33
+ * index coverage grew since the last announcement (unchanged coverage means
34
+ * the turn was appended after an index that learned nothing new); degraded
35
+ * and unpaid states get their own notices.
36
+ *
37
+ * Every /v1/messages and count_tokens body is run through the legacy notice
38
+ * strip pass before hashing/forwarding. Live notices use Claude Code hooks and
39
+ * upstream response bytes pass through to the client unchanged.
40
+ */
41
+ import { capCacheBreakpoints } from "./route-cache.js";
42
+ import { estimateRequestTokens } from "./request-sizing.js";
43
+ import { MemtreeClient } from "./memtree.js";
44
+ import type { MemtreeLinkPlacement } from "./cli-args.js";
45
+ import { type MemtreeLinkStore } from "./memtree-links.js";
46
+ import type { NewestTreeLookup } from "./memtree-newest.js";
47
+ import type { TranscriptUsageSource } from "./transcript-usage.js";
48
+ import type { ProjectMeta } from "./project-meta.js";
49
+ import { type RequestLogSink } from "./reqlog.js";
50
+ export interface ProxyOptions {
51
+ memtree: MemtreeClient;
52
+ /**
53
+ * Treat current native-1M Anthropic model ids as 1M without requiring the
54
+ * legacy context-1m beta header. Defaults to true. Set false only when the
55
+ * client deliberately disables native 1M context.
56
+ */
57
+ nativeOneMillionContext?: boolean;
58
+ /**
59
+ * Tool-turn compaction (default true): a tool turn on any lane whose
60
+ * estimated size reaches the budget compresses once to the target, like a
61
+ * main human turn (planToolCompaction); on the main thread the result is
62
+ * the session's stable prefix. A soft fuse, not a hard payload cap: MemTree
63
+ * failure degrades to the old prefix or the original body. `false` (the
64
+ * CLI's `CCC_TOOL_ROUTE_RECOVERY=0`) is a pure-passthrough switch for tool
65
+ * turns: no size check and no compress call; they ride their lane's route
66
+ * when one exists and otherwise go out whole.
67
+ */
68
+ toolRouteRecovery?: boolean;
69
+ /**
70
+ * Size requests exactly with Anthropic's Count Tokens endpoint, using the
71
+ * request's own credentials (count-tokens.ts): before a compaction decision
72
+ * when the estimate is unknown or a jump nears the budget, and always before
73
+ * refusing a request on an estimate. The CLI turns this on
74
+ * (`CCC_COUNT_TOKENS=0` turns it off); embedders and tests keep estimates.
75
+ */
76
+ countTokens?: boolean;
77
+ /**
78
+ * Handle only Claude Code's own requests. ccc launches Claude Code with
79
+ * ANTHROPIC_BASE_URL pointing here, and every program Claude Code runs
80
+ * inherits it (scripts, test suites, SDK apps, a benchmark's judge calls).
81
+ * Claude Code's API client always sends `X-Claude-Code-Session-Id`; a
82
+ * request without it is another program's and is forwarded to Anthropic
83
+ * byte for byte: no MemTree compress or index, no route state, logged as
84
+ * `turnType: "foreign"`. The CLI turns this on; embedders and tests that
85
+ * send bare requests keep the old behaviour by default.
86
+ */
87
+ claudeCodeOnly?: boolean;
88
+ /**
89
+ * Compaction target (tokens) for every session that has not run
90
+ * `/memtree-compact`: `CCC_COMPACT_TARGET`. For benchmarks and headless
91
+ * runs, where the hook-driven command is unavailable. It sets what each
92
+ * compaction aims at (instead of half the budget); it does not trigger
93
+ * one — that is still the budget. `/memtree-compact off` still turns
94
+ * compaction off for one session. null (`CCC_COMPACT_TARGET=off`) starts
95
+ * every session in the `/memtree-compact off` state, for headless runs that
96
+ * cannot type the command; `/memtree-compact [N]` still turns it back on.
97
+ */
98
+ defaultCompactTarget?: number | null;
99
+ /**
100
+ * Test-only whole-request budget (tokens) for every session:
101
+ * `CCC_BUDGET_TOKENS`. Replaces the server-reported model budget (and the
102
+ * context-window fallback) so a cheap session crosses it in a few turns.
103
+ */
104
+ budgetTokensOverride?: number;
105
+ /** Test-only overrides for the first-tree probe (5s) and total wait (60s). */
106
+ awaitedIndexProbeTimeoutMs?: number;
107
+ awaitedIndexWaitTimeoutMs?: number;
108
+ debug?: boolean;
109
+ /**
110
+ * Always-on request/timing JSONL log (see reqlog.ts). Includes messages,
111
+ * MemTree calls, and successful notice claims; omitted means no logging.
112
+ */
113
+ reqlog?: RequestLogSink;
114
+ /**
115
+ * Where the MemTree page link is shown (default "turn"):
116
+ * - "turn": `• MemTree · <url>` once at the end of a user turn (Stop), and
117
+ * only when the index behind the link changed since it was last shown.
118
+ * - "message": `• MemTree · <url>` under every finished assistant message,
119
+ * Stop as the fallback for a turn that rendered none; the first message
120
+ * after a newly finished index came into use is green, later ones dim.
121
+ * - "stop": the same trailer, on Stop only, once per turn.
122
+ * - "success": only under the `✓ MemTree · conversation optimized` line.
123
+ * In "turn" (the default) and "success", the success line carries the
124
+ * current page link on its own line below it; in "turn" the end-of-turn
125
+ * trailer then skips a link that line already showed.
126
+ * - "off": no link anywhere (the page still reaches the request log).
127
+ * The CLI maps `CCC_MEMTREE_LINK` onto this.
128
+ */
129
+ memtreeLinkPlacement?: MemtreeLinkPlacement;
130
+ /**
131
+ * Where the newest page per session is persisted so a resumed session can
132
+ * show its link (SessionStart hook). Omitted means no persistence (tests);
133
+ * the CLI passes the default store under ~/.claude-code-infinite.
134
+ */
135
+ memtreeLinkStore?: MemtreeLinkStore;
136
+ /**
137
+ * The session's newest completed tree, asked of the server, which the link
138
+ * shown to the user points at (the compress page is only the tree the memory
139
+ * came from, and can be days old). Omitted means the link is the compress
140
+ * page (tests); the CLI passes a lookup over the user's key.
141
+ */
142
+ newestTrees?: NewestTreeLookup;
143
+ /**
144
+ * Per-response token usage (thinking share on the MemTree page), read from
145
+ * Claude Code's transcript. Omitted means none is sent (tests); the CLI
146
+ * passes the reader for ~/.claude/projects.
147
+ */
148
+ transcriptUsage?: TranscriptUsageSource;
149
+ /**
150
+ * The session's project (project-meta.ts: directory name, `owner/repo`,
151
+ * branch, commit), added to every MemTree call's `x-client-meta` so the
152
+ * user can find sessions by project. Omitted means none is sent.
153
+ */
154
+ projectMeta?: ProjectMeta;
155
+ /** Test-only: forward to this origin instead of api.anthropic.com. */
156
+ upstreamOrigin?: string;
157
+ /** Test-only: dump each forwarded /v1/messages body to this directory. */
158
+ captureDir?: string;
159
+ /**
160
+ * Test-only fault-injection seam: invoked inside installMemoryRoute after
161
+ * its guards pass, immediately before the route is stored. Throwing here
162
+ * simulates route bookkeeping failing (the cloneJson/JSON.stringify
163
+ * calls), which no natural input can trigger — every install input has
164
+ * already survived JSON.parse. Exists solely so the "activation-error"
165
+ * install fate (label precedence over clientAborted, release keeping the
166
+ * lane's backoff) is pinnable by tests. Undefined in production.
167
+ */
168
+ routeInstallFault?: () => void;
169
+ }
170
+ export interface RunningProxy {
171
+ port: number;
172
+ /** Random per-process endpoint used by the ephemeral Claude plugin. */
173
+ hookUrl: string;
174
+ close: () => void;
175
+ /**
176
+ * Stop accepting work and give active requests a bounded grace period.
177
+ * On expiry, every accepted request and upstream is cancelled, then request
178
+ * finalizers are awaited; false reports that forced cancellation was needed.
179
+ */
180
+ drain: (timeoutMs?: number) => Promise<boolean>;
181
+ }
182
+ /**
183
+ * Budget fallback until the server reports `model_budget_tokens`: this share
184
+ * of the model's context window (800k of Opus 5.5's 1M, matching the server's
185
+ * large-context threshold).
186
+ */
187
+ export declare const FALLBACK_BUDGET_WINDOW_RATIO = 0.8;
188
+ export declare function startProxy(opts: ProxyOptions): Promise<RunningProxy>;
189
+ /** The page id in a server-stamped link (`…/m/<id>` or `…/usage/memtree/<id>`). */
190
+ export declare function memtreePageId(pageUrl: string): string | undefined;
191
+ export declare const MEMTREE_COMPACT_MIN_TOKENS = 20000;
192
+ /** "50k", "50000", "1.5m" → tokens; undefined when not a positive count. */
193
+ export declare function parseTokenCount(text: string): number | undefined;
194
+ /** Test seam. */
195
+ export declare const __testCapCacheBreakpoints: typeof capCacheBreakpoints;
196
+ export declare const __testEstimateRequestTokens: typeof estimateRequestTokens;
197
+ //# sourceMappingURL=proxy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AASvD,OAAO,EAAiB,qBAAqB,EACD,MAAM,qBAAqB,CAAC;AAiBxE,OAAO,EAIL,aAAa,EAMd,MAAM,cAAc,CAAC;AAyCtB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,EAA8B,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACvF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAS5D,OAAO,KAAK,EAAgB,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACjF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAOL,KAAK,cAAc,EAGpB,MAAM,aAAa,CAAC;AAgCrB,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,aAAa,CAAC;IACvB;;;;OAIG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC;;;;;;;;;OASG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;;;;;;OASG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;;;;;;OASG;IACH,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,8EAA8E;IAC9E,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;OAGG;IACH,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB;;;;;;;;;;;;;;OAcG;IACH,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC;;;;;OAKG;IACH,WAAW,CAAC,EAAE,gBAAgB,CAAC;IAC/B;;;;OAIG;IACH,eAAe,CAAC,EAAE,qBAAqB,CAAC;IACxC;;;;OAIG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,sEAAsE;IACtE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,0EAA0E;IAC1E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;;;OAQG;IACH,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB;;;;OAIG;IACH,KAAK,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACjD;AA6MD;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,MAAM,CAAC;AAyMhD,wBAAgB,UAAU,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAkIpE;AAuQD,mFAAmF;AACnF,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAOjE;AA05CD,eAAO,MAAM,0BAA0B,QAAS,CAAC;AA4CjD,4EAA4E;AAC5E,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAMhE;AAy2FD,iBAAiB;AACjB,eAAO,MAAM,yBAAyB,4BAAsB,CAAC;AAC7D,eAAO,MAAM,2BAA2B,8BAAwB,CAAC"}