claude-code-infinite 1.0.29 → 1.0.31
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 +65 -7
- package/dist/cli-args.d.ts +10 -0
- package/dist/cli-args.d.ts.map +1 -1
- package/dist/cli-args.js +30 -0
- package/dist/cli-args.js.map +1 -1
- package/dist/cli-lifecycle.d.ts +45 -1
- package/dist/cli-lifecycle.d.ts.map +1 -1
- package/dist/cli-lifecycle.js +59 -0
- package/dist/cli-lifecycle.js.map +1 -1
- package/dist/cli-main.js +61 -16
- package/dist/cli-main.js.map +1 -1
- package/dist/count-tokens.d.ts +15 -0
- package/dist/count-tokens.d.ts.map +1 -1
- package/dist/count-tokens.js +23 -1
- package/dist/count-tokens.js.map +1 -1
- package/dist/diagnostics-schema.d.ts.map +1 -1
- package/dist/diagnostics-schema.js +5 -0
- package/dist/diagnostics-schema.js.map +1 -1
- package/dist/diagnostics.d.ts.map +1 -1
- package/dist/diagnostics.js +18 -1
- package/dist/diagnostics.js.map +1 -1
- package/dist/final-index.d.ts +7 -1
- package/dist/final-index.d.ts.map +1 -1
- package/dist/final-index.js +10 -3
- package/dist/final-index.js.map +1 -1
- package/dist/hooks.d.ts +24 -1
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +24 -2
- package/dist/hooks.js.map +1 -1
- package/dist/image-refs.d.ts +51 -0
- package/dist/image-refs.d.ts.map +1 -0
- package/dist/image-refs.js +169 -0
- package/dist/image-refs.js.map +1 -0
- package/dist/image-tokens.d.ts +37 -0
- package/dist/image-tokens.d.ts.map +1 -0
- package/dist/image-tokens.js +158 -0
- package/dist/image-tokens.js.map +1 -0
- package/dist/memtree-body.d.ts +52 -0
- package/dist/memtree-body.d.ts.map +1 -0
- package/dist/memtree-body.js +99 -0
- package/dist/memtree-body.js.map +1 -0
- package/dist/memtree-mcp.d.ts.map +1 -1
- package/dist/memtree-mcp.js +4 -0
- package/dist/memtree-mcp.js.map +1 -1
- package/dist/memtree.d.ts +86 -3
- package/dist/memtree.d.ts.map +1 -1
- package/dist/memtree.js +283 -53
- package/dist/memtree.js.map +1 -1
- package/dist/model-context.d.ts +80 -0
- package/dist/model-context.d.ts.map +1 -0
- package/dist/model-context.js +192 -0
- package/dist/model-context.js.map +1 -0
- package/dist/paused-session.d.ts.map +1 -1
- package/dist/paused-session.js +11 -8
- package/dist/paused-session.js.map +1 -1
- package/dist/payment-gate.d.ts +2 -0
- package/dist/payment-gate.d.ts.map +1 -1
- package/dist/payment-gate.js +1 -1
- package/dist/payment-gate.js.map +1 -1
- package/dist/prefix-store.d.ts +2 -0
- package/dist/prefix-store.d.ts.map +1 -1
- package/dist/prefix-store.js +4 -0
- package/dist/prefix-store.js.map +1 -1
- package/dist/prepared-compression.d.ts +78 -0
- package/dist/prepared-compression.d.ts.map +1 -0
- package/dist/prepared-compression.js +127 -0
- package/dist/prepared-compression.js.map +1 -0
- package/dist/proxy.d.ts +370 -14
- package/dist/proxy.d.ts.map +1 -1
- package/dist/proxy.js +797 -94
- package/dist/proxy.js.map +1 -1
- package/dist/reqlog.d.ts +55 -0
- package/dist/reqlog.d.ts.map +1 -1
- package/dist/reqlog.js.map +1 -1
- package/dist/request-sizing.d.ts +21 -2
- package/dist/request-sizing.d.ts.map +1 -1
- package/dist/request-sizing.js +57 -11
- package/dist/request-sizing.js.map +1 -1
- package/dist/route-identity.d.ts +27 -0
- package/dist/route-identity.d.ts.map +1 -1
- package/dist/route-identity.js +88 -8
- package/dist/route-identity.js.map +1 -1
- package/dist/token-estimate.d.ts +3 -20
- package/dist/token-estimate.d.ts.map +1 -1
- package/dist/token-estimate.js +9 -50
- package/dist/token-estimate.js.map +1 -1
- package/dist/tool-output-store.d.ts +12 -0
- package/dist/tool-output-store.d.ts.map +1 -0
- package/dist/tool-output-store.js +146 -0
- package/dist/tool-output-store.js.map +1 -0
- package/dist/tool-result-truncation.d.ts +32 -0
- package/dist/tool-result-truncation.d.ts.map +1 -0
- package/dist/tool-result-truncation.js +135 -0
- package/dist/tool-result-truncation.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
# Claude Code Infinite
|
|
6
6
|
|
|
7
7
|
<p align="center">
|
|
8
|
-
<a href="#long-session-benchmark"><img width="640" alt="Long-session benchmark, Claude Opus 5.5, graded blind
|
|
8
|
+
<a href="#long-session-benchmark"><img width="640" alt="Long-session benchmark, Claude Opus 5.5, graded blind, on a ~800k-token Claude Code session: MemTree 69% (~420k tokens after MemTree), /compact 49% (~13k tokens after /compact)" src="https://raw.githubusercontent.com/crizCraig/claude-code-infinite/main/docs/images/benchmark-chart.png"></a>
|
|
9
9
|
</p>
|
|
10
|
-
<p align="center"><sub>Long-session benchmark
|
|
11
|
-
|
|
10
|
+
<p align="center"><sub>Long-session benchmark (Claude Opus 5.5, graded blind): MemTree beat <code>/compact</code> by 20 points,
|
|
11
|
+
on a ~800k-token Claude Code session. It also matched full context on this test (69 vs 69).
|
|
12
12
|
<a href="#long-session-benchmark">Full results</a></sub></p>
|
|
13
13
|
|
|
14
14
|
Infinite context for Claude Code: memory for long-running agents. Claude Code Infinite indexes your Claude Code sessions with
|
|
@@ -24,8 +24,10 @@ follows it down to the original messages.
|
|
|
24
24
|
* **Search across every session.** Claude can find what was decided, tried or ruled out in any of
|
|
25
25
|
your past sessions, by exact words or by meaning, filtered by project and date
|
|
26
26
|
* **Browse each session's MemTree** in your browser, from the link `ccc` prints in the terminal
|
|
27
|
-
* **Never loses anything vs Claude Code.**
|
|
28
|
-
|
|
27
|
+
* **Never loses anything vs Claude Code.** On Opus 5 and up, you get the vast majority of the
|
|
28
|
+
1M-token window word for word, exactly as Claude Code sends it. Only near the limit does MemTree
|
|
29
|
+
compress, to about half the window to minimize the number of compressions: recent messages stay word for word
|
|
30
|
+
and older ones become a searchable memory, the originals one tool call away. MemTree matched full context (69 vs 69) and beat `/compact` by 20 ([benchmark](#long-session-benchmark))
|
|
29
31
|
* **Unlimited-length sessions**, with relevant past information recalled automatically
|
|
30
32
|
* **A local proxy, so no slowdown.** Requests go straight from your machine to Anthropic and
|
|
31
33
|
MemTree indexes in the background; only the occasional compression step, when a session
|
|
@@ -80,6 +82,54 @@ for MemTree and 38 min for full context. Input tokens count uncached, cache-read
|
|
|
80
82
|
tokens; `/compact`'s exclude the one-time `/compact` step. This is one task family, one model and
|
|
81
83
|
3 rounds, not a general benchmark.
|
|
82
84
|
|
|
85
|
+
MemTree compresses as late as possible: the whole ~775k-token history went out word for word,
|
|
86
|
+
exactly as Claude Code would send it, and MemTree compressed only once, near the limit, keeping the
|
|
87
|
+
most recent messages word for word.
|
|
88
|
+
|
|
89
|
+
A rerun on Oct 20, with MemTree's lookup tools loaded and the same outputs graded again at a
|
|
90
|
+
higher reasoning effort, gave the same shape: MemTree 65, full context 66, `/compact` 45.
|
|
91
|
+
MemTree's figure there is the mean of its 2 clean rounds (a harness bug let the third round read
|
|
92
|
+
another round's work); full context still fixed more of the issues (21 vs 17 on average).
|
|
93
|
+
|
|
94
|
+
## Past the context window: MemTree keeps the work, `/compact` loses it
|
|
95
|
+
|
|
96
|
+
<p align="center">
|
|
97
|
+
<img width="560" alt="Past the context window, 1M+-token session, Claude Opus 5.5, graded blind, mean of 6 rounds: MemTree 70% with 8 of 8 findings addressed (3 fully, 5 partly); /compact 23% with 0 of 8" src="docs/images/benchmark-past-1m.png">
|
|
98
|
+
</p>
|
|
99
|
+
|
|
100
|
+
The benchmark above fits inside Claude Opus 5.5's 1M-token window. This one does not. Each setup
|
|
101
|
+
resumes the same **1M+**-token history, built in time order from real Claude Code sessions of our
|
|
102
|
+
own engineering work: the design and implementation of a backend feature, four rounds of code
|
|
103
|
+
review in which an outside reviewer's findings were confirmed and, for several, re-scoped by the
|
|
104
|
+
session, then about 550k tokens of later, unrelated work. The task comes at the end: the commits
|
|
105
|
+
that fixed review rounds 2–4 were lost, so re-implement every fix as the session approved it, each
|
|
106
|
+
with a regression test, in one commit. The findings and decisions exist only in the conversation,
|
|
107
|
+
and the task forbids re-reviewing the code to find them again. Since the history is already past
|
|
108
|
+
the window, MemTree compressed it on the first turn: the most recent messages stayed word for word,
|
|
109
|
+
and the older ones became a memory tree whose original messages Claude can read back with one tool
|
|
110
|
+
call. An independent grader scored each
|
|
111
|
+
result blind (0–100) against the real fixes, their regression tests and the session's decisions.
|
|
112
|
+
|
|
113
|
+
| Setup | Score | Findings addressed (of 8) | How it handles the history |
|
|
114
|
+
| --- | --- | --- | --- |
|
|
115
|
+
| **Claude Code Infinite** | **69.9** | **8: 3 fully, 5 partly** | Compressed to ~200–290k on the first turn; looked up the review rounds with its MemTree tools |
|
|
116
|
+
| `/compact` | 23.0 | 0 | Claude Code's `/compact` before the task; made no changes and asked for the findings |
|
|
117
|
+
| Full context | n/a | n/a | Not possible: the history is larger than the 1M-token window |
|
|
118
|
+
|
|
119
|
+
`/compact` failed because its summary dropped the findings: it recorded the reviews only as
|
|
120
|
+
confirmed reviewer findings, with no finding or decision in it, so there was nothing to fix. Its
|
|
121
|
+
23 points are for reporting that honestly (regrading the same empty diffs gave 23 every time). MemTree recovered all 8 findings from the
|
|
122
|
+
session's memory in every round, fixed 3 fully and 5 partly every round, and implemented the
|
|
123
|
+
session's decisions rather than the reviewer's original proposals. Before writing any code, it searched its tree for the review rounds and read about 400 lines of the original exchange word for word with `read_lines`. MemTree's round scores were
|
|
124
|
+
74.6, 67.6, 67.1, 69.4, 68.1 and 72.6, with 5 regressions charged across the 6 rounds.
|
|
125
|
+
|
|
126
|
+
Caveats: 6 rounds, one task, one model, one grader; no significance claims. Blinding is weak: `/compact` made no changes and its report says it worked from a summary,
|
|
127
|
+
so a grader can tell the setups apart. The same task prompt went to both setups and mentions
|
|
128
|
+
MemTree's lookup tools, which plain Claude Code doesn't have. There is no full-context arm, since
|
|
129
|
+
the history doesn't fit. Grading used a fixed rubric (coverage 30, fix quality 30, fidelity to the
|
|
130
|
+
session's decisions 15, report accuracy 20, process 5); the harness and the answer key stay
|
|
131
|
+
private because they come from a private codebase.
|
|
132
|
+
|
|
83
133
|
## Requirements
|
|
84
134
|
|
|
85
135
|
* **[Claude Code in your terminal](https://code.claude.com/docs/en/quickstart), signed in
|
|
@@ -171,6 +221,14 @@ kitty, VS Code, JetBrains, Windows Terminal); elsewhere you get the plain URL.
|
|
|
171
221
|
|
|
172
222
|
`ccc` disables Claude Code's automatic conversation compaction for the Claude process it launches. MemTree manages the context sent to the model, so letting Claude Code independently summarize the full local transcript can compact a conversation MemTree already reduced. Manual `/compact` remains available.
|
|
173
223
|
|
|
224
|
+
Manual `/compact` also asks once: while MemTree is compressing, the first `/compact` answers
|
|
225
|
+
"MemTree already keeps this session within its budget; /compact would discard detail…" and
|
|
226
|
+
suggests `/ccc:memtree-compact`; typing `/compact` again within two minutes runs Claude Code's
|
|
227
|
+
own. While MemTree is paused or its key is refused, `/compact` runs at once, and under
|
|
228
|
+
`CCC_AUTO_COMPACT=1` it is never intercepted. Claude itself is told the same: context is
|
|
229
|
+
MemTree's job, so it won't suggest `/compact`, `/clear` or a fresh session to free context,
|
|
230
|
+
and if MemTree is paused it is told why (MemTree's usage limit, not Claude's) and how to fix it.
|
|
231
|
+
|
|
174
232
|
That includes idle compaction (Claude Code 2.1.286 and later), which summarizes a
|
|
175
233
|
long conversation while you're away, just before the prompt cache expires
|
|
176
234
|
("Compacted while idle, before the prompt cache expired"). The
|
|
@@ -184,7 +242,7 @@ recommendation as well; it does not disable the manual `/compact` command.
|
|
|
184
242
|
|
|
185
243
|
With auto-compaction off, Claude Code still refuses a request itself, without
|
|
186
244
|
sending it, once its own estimate reaches the window minus 23k (977k on a 1M
|
|
187
|
-
window). MemTree compresses at
|
|
245
|
+
window). MemTree compresses at 960k, so a single large tool round could reach that
|
|
188
246
|
refusal before `ccc` ever saw the request. `ccc` sets
|
|
189
247
|
`CLAUDE_CODE_BLOCKING_LIMIT_OVERRIDE` (unless you exported your own) so such a
|
|
190
248
|
request reaches the proxy, which compresses it mid-turn.
|
|
@@ -280,7 +338,7 @@ The full guide for agent platforms (setup, output parsing, memory tools, tree li
|
|
|
280
338
|
|
|
281
339
|
When you send a message, we retrieve relevant details and summaries from the prior messages in your thread. These details and summaries populate a **memory message**. Following the memory message, we append a compressed version of your recent message history. The resulting context-window is dramatically smaller, allowing Claude to process your request with much greater efficacy, lower latency, and reduced cost.
|
|
282
340
|
|
|
283
|
-
**Compaction keeps a stable prefix.** While a conversation fits the model's budget (900k tokens for Opus 5.5, where plain Claude Code would auto-compact at 967k), it is sent whole. When a request reaches the budget, `ccc` compresses it once, to half the budget (or your `/memtree-compact N`), and keeps those compressed bytes as the session's prefix. Every later request, human turns included, is that same prefix followed by the messages that came after it, verbatim, with no compression call (MemTree still indexes in the background). Because the prefix does not change, Anthropic reads it from the prompt cache on every turn after the one that compacted, instead of writing the whole compressed context again. `ccc` compresses again only when prefix plus newer turns reach the budget (measured from the size Anthropic reported for the previous request, plus an estimate for what was added), or when the messages the prefix stands for change (rewind, edit, fork, `/clear`). If that recompression fails, the turn is sent on the old prefix rather than the whole history. The prefix is also kept on disk, one file per session under `~/.claude-code-infinite/stable-prefixes/` (mode 600 in a private directory, at most 64 sessions and 256 MB, oldest dropped first), so the first turn after `ccc --resume` rides it instead of waiting on a fresh compression. A stored prefix belongs to the MemTree backend and key that wrote it (identified by a hash, never the key itself) and is never used with another. It is used only if the resumed history still matches what it replaced; a main-thread history that no longer matches discards it, while side requests (such as Claude Code's web-search helper) leave it alone. Only the main thread's prefix is stored, never a subagent's. The budget is the one MemTree reports for the model; until the server reports one, `ccc` uses
|
|
341
|
+
**Compaction keeps a stable prefix.** While a conversation fits the model's budget (900k tokens for Opus 5.5, where plain Claude Code would auto-compact at 967k), it is sent whole. When a request reaches the budget, `ccc` compresses it once, to half the budget (or your `/memtree-compact N`), and keeps those compressed bytes as the session's prefix. Every later request, human turns included, is that same prefix followed by the messages that came after it, verbatim, with no compression call (MemTree still indexes in the background). Because the prefix does not change, Anthropic reads it from the prompt cache on every turn after the one that compacted, instead of writing the whole compressed context again. `ccc` compresses again only when prefix plus newer turns reach the budget (measured from the size Anthropic reported for the previous request, plus an estimate for what was added), or when the messages the prefix stands for change (rewind, edit, fork, `/clear`). If that recompression fails, the turn is sent on the old prefix rather than the whole history. The prefix is also kept on disk, one file per session under `~/.claude-code-infinite/stable-prefixes/` (mode 600 in a private directory, at most 64 sessions and 256 MB, oldest dropped first), so the first turn after `ccc --resume` rides it instead of waiting on a fresh compression. A stored prefix belongs to the MemTree backend and key that wrote it (identified by a hash, never the key itself) and is never used with another. It is used only if the resumed history still matches what it replaced; a main-thread history that no longer matches discards it, while side requests (such as Claude Code's web-search helper) leave it alone. Only the main thread's prefix is stored, never a subagent's. The budget is the one MemTree reports for the model; until the server reports one, `ccc` uses the context window less 40k for the reply for every Claude model (960k of 1M, just under where plain Claude Code would auto-compact at 967k; never below 80%, so 160k of a 200k window; at most 400k for Sonnet 4.x and 550k for Sonnet 5 / 5.5, which degrade before their window), and 80% for other models. A request is sized as it will be sent (history plus the new tool results), and compressed when that size reaches the budget or would leave less than 40k of the window for the reply. On a 1M window, once a main-thread request passes ~850k, `ccc` asks MemTree in the background for the compressed prefix and refreshes it every ~50k of growth; the request that crosses the budget (say a 100k tool result at 940k) is then sent at once on that prepared prefix plus the messages after it, with no compression wait (`compaction.prepared: "used"` in `requests.jsonl`), and falls back to compressing then when no prepared prefix fits. MemTree bills a preparation as the compression it replaces. If even after compression a single tool result cannot fit the window, `ccc` saves it whole under `~/.claude-code-infinite/tool-outputs/` (mode 600, at most 64 files and 512 MB, oldest dropped first, never one under an hour old) and sends its beginning and end word for word with the middle replaced by a pointer to that file, which Claude reads with its Read tool, instead of refusing the request. A human turn clearly under the budget by its token count is sent at once, with its MemTree call in the background (`turnType: "followup-under-budget"`). `CCC_BUDGET_TOKENS=60k` overrides it for testing. Every `requests.jsonl` line carries the `pid` of the `ccc` process that wrote it, which tells apart concurrent sessions sharing the log. The same rule holds inside a tool loop, so a long single turn (a headless `-p` run, or a long agentic loop) is compacted as it grows rather than only when you next type: each tool request under the budget goes out with no compression call, the one that reaches it is compressed once and becomes the stable prefix, and later tool requests and your next message ride that prefix until it reaches the budget again. `requests.jsonl` shows the `compaction` of each main-thread human turn and of every tool turn (budget, its source, the size estimate, and the reason for a compaction: `budget`, `prefix-mismatch`, `manual` or `target-change`); a human turn sent on the stable prefix is `turnType: "followup-prefix"`, a tool turn `tool-memory` (on its route) or `tool-prefix` (on the prefix directly), and a tool turn that compacted `tool-recompressed`.
|
|
284
342
|
|
|
285
343
|
That compressed context stays in force for the rest of the turn: the tool loop it kicks off, and the matching Count Tokens calls, are routed through the same compressed prefix. The Count Tokens part matters — Claude Code sizes its context from those replies, so counting the uncompressed history would make it auto-compact a conversation memory had already shrunk. A mismatched or resumed conversation shape drops the route rather than grafting one session's prefix onto another.
|
|
286
344
|
|
package/dist/cli-args.d.ts
CHANGED
|
@@ -48,5 +48,15 @@ export declare function compactTargetFromEnv(raw: string | undefined, parseToken
|
|
|
48
48
|
value: number | null | undefined;
|
|
49
49
|
warning?: string;
|
|
50
50
|
};
|
|
51
|
+
/**
|
|
52
|
+
* `CCC_ANTHROPIC_UPSTREAM` (test-only, e.g. "http://127.0.0.1:8123"): where the proxy sends
|
|
53
|
+
* Anthropic traffic instead of api.anthropic.com, for a local mock (scripts/long-session).
|
|
54
|
+
* Claude Code's credentials flow through to it, so only a loopback http(s) origin is taken;
|
|
55
|
+
* `value` is undefined when unset or refused, and `warning` explains a refused one.
|
|
56
|
+
*/
|
|
57
|
+
export declare function anthropicUpstreamFromEnv(raw: string | undefined): {
|
|
58
|
+
value: string | undefined;
|
|
59
|
+
warning?: string;
|
|
60
|
+
};
|
|
51
61
|
export {};
|
|
52
62
|
//# sourceMappingURL=cli-args.d.ts.map
|
package/dist/cli-args.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-args.d.ts","sourceRoot":"","sources":["../src/cli-args.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,+EAA+E;AAC/E,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAMzD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAIjE;AAED,4DAA4D;AAC5D,QAAA,MAAM,WAAW,2CAA4C,CAAC;AAG9D,MAAM,MAAM,cAAc,GAAG,YAAY,GAAG,SAAS,GAAG,OAAO,CAAC;AAEhE,kFAAkF;AAClF,wBAAgB,aAAa,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,cAAc,CAErE;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,SAAS,MAAM,EAAE,GACtB;IAAE,IAAI,EAAE,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,SAAS,CAIpE;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,WAAW,CAmB5D;AAED,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,KAAK,CAAC;AACnF,eAAO,MAAM,uBAAuB,EAAE,SAAS,oBAAoB,EAMlE,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,MAAM,GAAG,SAAS,GACxB,oBAAoB,GAAG,SAAS,CAKlC;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,MAAM,GAAG,SAAS,EACvB,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,EACjD,SAAS,EAAE,MAAM,GAChB;IAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAWxD"}
|
|
1
|
+
{"version":3,"file":"cli-args.d.ts","sourceRoot":"","sources":["../src/cli-args.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,+EAA+E;AAC/E,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAMzD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAIjE;AAED,4DAA4D;AAC5D,QAAA,MAAM,WAAW,2CAA4C,CAAC;AAG9D,MAAM,MAAM,cAAc,GAAG,YAAY,GAAG,SAAS,GAAG,OAAO,CAAC;AAEhE,kFAAkF;AAClF,wBAAgB,aAAa,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,cAAc,CAErE;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,SAAS,MAAM,EAAE,GACtB;IAAE,IAAI,EAAE,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,SAAS,CAIpE;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,WAAW,CAmB5D;AAED,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,KAAK,CAAC;AACnF,eAAO,MAAM,uBAAuB,EAAE,SAAS,oBAAoB,EAMlE,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,MAAM,GAAG,SAAS,GACxB,oBAAoB,GAAG,SAAS,CAKlC;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,MAAM,GAAG,SAAS,EACvB,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,EACjD,SAAS,EAAE,MAAM,GAChB;IAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAWxD;AAKD;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,MAAM,GAAG,SAAS,GACtB;IAAE,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAmBjD"}
|
package/dist/cli-args.js
CHANGED
|
@@ -95,4 +95,34 @@ export function compactTargetFromEnv(raw, parseTokens, minTokens) {
|
|
|
95
95
|
}
|
|
96
96
|
return { value: target };
|
|
97
97
|
}
|
|
98
|
+
/** Hosts `CCC_ANTHROPIC_UPSTREAM` may name: this machine only. */
|
|
99
|
+
const LOOPBACK_HOSTS = new Set(["127.0.0.1", "localhost"]);
|
|
100
|
+
/**
|
|
101
|
+
* `CCC_ANTHROPIC_UPSTREAM` (test-only, e.g. "http://127.0.0.1:8123"): where the proxy sends
|
|
102
|
+
* Anthropic traffic instead of api.anthropic.com, for a local mock (scripts/long-session).
|
|
103
|
+
* Claude Code's credentials flow through to it, so only a loopback http(s) origin is taken;
|
|
104
|
+
* `value` is undefined when unset or refused, and `warning` explains a refused one.
|
|
105
|
+
*/
|
|
106
|
+
export function anthropicUpstreamFromEnv(raw) {
|
|
107
|
+
if (!raw || !raw.trim())
|
|
108
|
+
return { value: undefined };
|
|
109
|
+
let url;
|
|
110
|
+
try {
|
|
111
|
+
url = new URL(raw.trim());
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
url = undefined;
|
|
115
|
+
}
|
|
116
|
+
const loopback = url !== undefined && /^https?:$/.test(url.protocol) &&
|
|
117
|
+
LOOPBACK_HOSTS.has(url.hostname) && !url.username && !url.password &&
|
|
118
|
+
(url.pathname === "/" || url.pathname === "");
|
|
119
|
+
if (!loopback) {
|
|
120
|
+
return {
|
|
121
|
+
value: undefined,
|
|
122
|
+
// Never echo the value: a refused one may carry credentials.
|
|
123
|
+
warning: "ccc: ignoring CCC_ANTHROPIC_UPSTREAM (only a loopback origin such as http://127.0.0.1:8123)",
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
return { value: url.origin };
|
|
127
|
+
}
|
|
98
128
|
//# sourceMappingURL=cli-args.js.map
|
package/dist/cli-args.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-args.js","sourceRoot":"","sources":["../src/cli-args.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cli-args.js","sourceRoot":"","sources":["../src/cli-args.ts"],"names":[],"mappings":"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"}
|
package/dist/cli-lifecycle.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type ShutdownSignal = "SIGINT" | "SIGTERM";
|
|
1
|
+
export type ShutdownSignal = "SIGINT" | "SIGTERM" | "SIGHUP";
|
|
2
2
|
/** Conventional shell status for a process terminated by a POSIX signal. */
|
|
3
3
|
export declare function exitCodeForSignal(signal: NodeJS.Signals): number;
|
|
4
4
|
/** Preserve a child's numeric status or translate its terminating signal. */
|
|
@@ -23,4 +23,48 @@ export declare function createSignalShutdownHandler(actions: SignalShutdownActio
|
|
|
23
23
|
export declare function writeStdout(text: string, stream?: Pick<NodeJS.WriteStream, "write">): Promise<void>;
|
|
24
24
|
/** Waits for `pending` at most `ms`; a bound for cleanup that must not hang exit. */
|
|
25
25
|
export declare function settleWithin(pending: Promise<unknown>, ms: number): Promise<void>;
|
|
26
|
+
/** The exit drain's wait for MemTree calls in flight (the final index above all). */
|
|
27
|
+
export declare const SHUTDOWN_MEMTREE_DRAIN_MS = 2000;
|
|
28
|
+
/** Windows: the final index of a large session needs longer than 2 s to upload. */
|
|
29
|
+
export declare const WIN32_MEMTREE_DRAIN_MS = 4000;
|
|
30
|
+
/**
|
|
31
|
+
* Closing a Windows console window (SIGHUP) leaves ccc ~5 s before it is killed, and
|
|
32
|
+
* the final index was cut at 2 s on every close. From the close, each shutdown step
|
|
33
|
+
* ends by its mark here, so the diagnostics flush (exit_index_cut too) still fits.
|
|
34
|
+
*/
|
|
35
|
+
export declare const CONSOLE_CLOSE_MARKS_MS: {
|
|
36
|
+
readonly proxyDrain: 1000;
|
|
37
|
+
readonly memtreeDrain: 3500;
|
|
38
|
+
readonly childWait: 3750;
|
|
39
|
+
readonly flush: 4500;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* How a closed terminal reaches ccc. Windows: the console window closed, and Windows ends
|
|
43
|
+
* ccc ~5 s later ("console-close", each shutdown step ends by its mark). macOS and Linux:
|
|
44
|
+
* the terminal hung up ("terminal-hangup"); nothing ends ccc after it, but its terminal is
|
|
45
|
+
* gone. Either way it is SIGHUP, whose default is to exit at once: before this, closing a
|
|
46
|
+
* macOS or Linux terminal killed ccc with no final index.
|
|
47
|
+
*/
|
|
48
|
+
export type HangupKind = "console-close" | "terminal-hangup";
|
|
49
|
+
/**
|
|
50
|
+
* Calls `handler` on SIGHUP with the kind of close it means. On macOS and Linux only
|
|
51
|
+
* with a terminal to hang up (`terminal`: stdout or stderr is a TTY): under nohup, which
|
|
52
|
+
* points both away from the terminal, SIGHUP stays ignored as nohup asked. There a
|
|
53
|
+
* hangup can arrive more than once (the shell's, then the terminal's) and is one close:
|
|
54
|
+
* a repeat must not become the second signal that skips the final index.
|
|
55
|
+
*/
|
|
56
|
+
export declare function onHangup(proc: Pick<NodeJS.Process, "on" | "platform">, handler: (kind: HangupKind) => void, terminal: boolean): void;
|
|
57
|
+
/** Claude Code ended by the same hangup (macOS, Linux), possibly before ccc saw it. */
|
|
58
|
+
export declare function childExitMeansHangup(platform: NodeJS.Platform, code: number | null, signal: NodeJS.Signals | null): boolean;
|
|
59
|
+
/** After a hangup, writes to the gone terminal fail (EIO, EPIPE): never fatal to the drain. */
|
|
60
|
+
export declare function ignoreStreamErrors(streams: Array<Pick<NodeJS.EventEmitter, "on">>): void;
|
|
61
|
+
/**
|
|
62
|
+
* The exit drain's wait for MemTree calls after a terminal hangup (macOS, Linux): nobody
|
|
63
|
+
* waits for ccc then, and a large session's final index takes seconds to upload.
|
|
64
|
+
*/
|
|
65
|
+
export declare const HANGUP_MEMTREE_DRAIN_MS = 10000;
|
|
66
|
+
/** How long the exit drain may wait for MemTree calls, starting `now`. */
|
|
67
|
+
export declare function shutdownMemtreeDrainMs(platform: NodeJS.Platform, consoleClosedAt: number | undefined, now?: number): number;
|
|
68
|
+
/** `ms`, or less when it would end past `markMs` after the console's close. */
|
|
69
|
+
export declare function closeBoundedMs(ms: number, consoleClosedAt: number | undefined, markMs: number, now?: number): number;
|
|
26
70
|
//# sourceMappingURL=cli-lifecycle.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-lifecycle.d.ts","sourceRoot":"","sources":["../src/cli-lifecycle.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"cli-lifecycle.d.ts","sourceRoot":"","sources":["../src/cli-lifecycle.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;AAE7D,4EAA4E;AAC5E,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,MAAM,CAGhE;AAED,6EAA6E;AAC7E,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,GAAG,IAAI,EACnB,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,GAC5B,MAAM,CAGR;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,GAAG,IAAI,EACnB,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,EAC7B,SAAS,EAAE,MAAM,EACjB,GAAG,GAAE,MAAmB,GACvB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC,CAO7C;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAAC;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,qBAAqB,GAC7B,CAAC,MAAM,EAAE,cAAc,KAAK,IAAI,CASlC;AAED,oFAAoF;AACpF,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,EACZ,MAAM,GAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAkB,GACzD,OAAO,CAAC,IAAI,CAAC,CAQf;AAED,qFAAqF;AACrF,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQjF;AAED,qFAAqF;AACrF,eAAO,MAAM,yBAAyB,OAAQ,CAAC;AAC/C,mFAAmF;AACnF,eAAO,MAAM,sBAAsB,OAAQ,CAAC;AAC5C;;;;GAIG;AACH,eAAO,MAAM,sBAAsB;;;;;CAEzB,CAAC;AAEX;;;;;;GAMG;AACH,MAAM,MAAM,UAAU,GAAG,eAAe,GAAG,iBAAiB,CAAC;AAE7D;;;;;;GAMG;AACH,wBAAgB,QAAQ,CACtB,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,GAAG,UAAU,CAAC,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,EAClF,QAAQ,EAAE,OAAO,GAChB,IAAI,CAYN;AAED,uFAAuF;AACvF,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,GAC5E,OAAO,CAET;AAED,+FAA+F;AAC/F,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC,GAAG,IAAI,CAExF;AAED;;;GAGG;AACH,eAAO,MAAM,uBAAuB,QAAS,CAAC;AAE9C,0EAA0E;AAC1E,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,eAAe,EAAE,MAAM,GAAG,SAAS,EAAE,GAAG,SAAa,GAC/E,MAAM,CAGR;AAED,+EAA+E;AAC/E,wBAAgB,cAAc,CAC5B,EAAE,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,SAAa,GAChF,MAAM,CAGR"}
|
package/dist/cli-lifecycle.js
CHANGED
|
@@ -58,4 +58,63 @@ export function settleWithin(pending, ms) {
|
|
|
58
58
|
pending.then(() => { clearTimeout(timer); resolve(); }, () => { clearTimeout(timer); resolve(); });
|
|
59
59
|
});
|
|
60
60
|
}
|
|
61
|
+
/** The exit drain's wait for MemTree calls in flight (the final index above all). */
|
|
62
|
+
export const SHUTDOWN_MEMTREE_DRAIN_MS = 2_000;
|
|
63
|
+
/** Windows: the final index of a large session needs longer than 2 s to upload. */
|
|
64
|
+
export const WIN32_MEMTREE_DRAIN_MS = 4_000;
|
|
65
|
+
/**
|
|
66
|
+
* Closing a Windows console window (SIGHUP) leaves ccc ~5 s before it is killed, and
|
|
67
|
+
* the final index was cut at 2 s on every close. From the close, each shutdown step
|
|
68
|
+
* ends by its mark here, so the diagnostics flush (exit_index_cut too) still fits.
|
|
69
|
+
*/
|
|
70
|
+
export const CONSOLE_CLOSE_MARKS_MS = {
|
|
71
|
+
proxyDrain: 1_000, memtreeDrain: 3_500, childWait: 3_750, flush: 4_500,
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Calls `handler` on SIGHUP with the kind of close it means. On macOS and Linux only
|
|
75
|
+
* with a terminal to hang up (`terminal`: stdout or stderr is a TTY): under nohup, which
|
|
76
|
+
* points both away from the terminal, SIGHUP stays ignored as nohup asked. There a
|
|
77
|
+
* hangup can arrive more than once (the shell's, then the terminal's) and is one close:
|
|
78
|
+
* a repeat must not become the second signal that skips the final index.
|
|
79
|
+
*/
|
|
80
|
+
export function onHangup(proc, handler, terminal) {
|
|
81
|
+
if (proc.platform === "win32") {
|
|
82
|
+
proc.on("SIGHUP", () => handler("console-close"));
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (!terminal)
|
|
86
|
+
return;
|
|
87
|
+
let hungUp = false;
|
|
88
|
+
proc.on("SIGHUP", () => {
|
|
89
|
+
if (hungUp)
|
|
90
|
+
return;
|
|
91
|
+
hungUp = true;
|
|
92
|
+
handler("terminal-hangup");
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
/** Claude Code ended by the same hangup (macOS, Linux), possibly before ccc saw it. */
|
|
96
|
+
export function childExitMeansHangup(platform, code, signal) {
|
|
97
|
+
return platform !== "win32" && (signal === "SIGHUP" || code === exitCodeForSignal("SIGHUP"));
|
|
98
|
+
}
|
|
99
|
+
/** After a hangup, writes to the gone terminal fail (EIO, EPIPE): never fatal to the drain. */
|
|
100
|
+
export function ignoreStreamErrors(streams) {
|
|
101
|
+
for (const stream of streams)
|
|
102
|
+
stream.on("error", () => { });
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* The exit drain's wait for MemTree calls after a terminal hangup (macOS, Linux): nobody
|
|
106
|
+
* waits for ccc then, and a large session's final index takes seconds to upload.
|
|
107
|
+
*/
|
|
108
|
+
export const HANGUP_MEMTREE_DRAIN_MS = 10_000;
|
|
109
|
+
/** How long the exit drain may wait for MemTree calls, starting `now`. */
|
|
110
|
+
export function shutdownMemtreeDrainMs(platform, consoleClosedAt, now = Date.now()) {
|
|
111
|
+
const base = platform === "win32" ? WIN32_MEMTREE_DRAIN_MS : SHUTDOWN_MEMTREE_DRAIN_MS;
|
|
112
|
+
return closeBoundedMs(base, consoleClosedAt, CONSOLE_CLOSE_MARKS_MS.memtreeDrain, now);
|
|
113
|
+
}
|
|
114
|
+
/** `ms`, or less when it would end past `markMs` after the console's close. */
|
|
115
|
+
export function closeBoundedMs(ms, consoleClosedAt, markMs, now = Date.now()) {
|
|
116
|
+
if (consoleClosedAt === undefined)
|
|
117
|
+
return ms;
|
|
118
|
+
return Math.max(0, Math.min(ms, consoleClosedAt + markMs - now));
|
|
119
|
+
}
|
|
61
120
|
//# sourceMappingURL=cli-lifecycle.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-lifecycle.js","sourceRoot":"","sources":["../src/cli-lifecycle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,IAAI,WAAW,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAIrD,4EAA4E;AAC5E,MAAM,UAAU,iBAAiB,CAAC,MAAsB;IACtD,MAAM,YAAY,GAAG,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACjD,OAAO,OAAO,YAAY,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;AACnE,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,gBAAgB,CAC9B,IAAmB,EACnB,MAA6B;IAE7B,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC/B,OAAO,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;AACzD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAC9B,IAAmB,EACnB,MAA6B,EAC7B,SAAiB,EACjB,MAAc,IAAI,CAAC,GAAG,EAAE;IAExB,OAAO;QACL,IAAI,EAAE,IAAI,IAAI,SAAS;QACvB,QAAQ,EAAE,IAAI,IAAI,SAAS;QAC3B,MAAM,EAAE,UAAU,CAAC,MAAM,CAAC;QAC1B,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,SAAS,CAAC;KACxC,CAAC;AACJ,CAAC;AAQD;;;;GAIG;AACH,MAAM,UAAU,2BAA2B,CACzC,OAA8B;IAE9B,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,OAAO,CAAC,MAAM,EAAE,EAAE;QAChB,QAAQ,EAAE,CAAC;QACX,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACxB,MAAM,IAAI,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;QACvC,IAAI,QAAQ,KAAK,CAAC;YAAE,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;;YACtC,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC,CAAC;AACJ,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,WAAW,CACzB,IAAY,EACZ,SAA4C,OAAO,CAAC,MAAM;IAE1D,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,IAAI,CAAC;YACH,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;QACtC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,YAAY,CAAC,OAAyB,EAAE,EAAU;IAChE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QACtC,OAAO,CAAC,IAAI,CACV,GAAG,EAAE,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EACzC,GAAG,EAAE,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAC1C,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
1
|
+
{"version":3,"file":"cli-lifecycle.js","sourceRoot":"","sources":["../src/cli-lifecycle.ts"],"names":[],"mappings":"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"}
|
package/dist/cli-main.js
CHANGED
|
@@ -20,6 +20,7 @@ import { MEMTREE_COMPACT_MIN_TOKENS, parseTokenCount, startProxy } from "./proxy
|
|
|
20
20
|
import { MemtreeLinkStore } from "./memtree-links.js";
|
|
21
21
|
import { FirstTreeMarker } from "./first-tree.js";
|
|
22
22
|
import { StablePrefixStore } from "./prefix-store.js";
|
|
23
|
+
import { ToolOutputStore } from "./tool-output-store.js";
|
|
23
24
|
import { NewestTreeLookup } from "./memtree-newest.js";
|
|
24
25
|
import { ClaudeTranscriptUsage } from "./transcript-usage.js";
|
|
25
26
|
import { createSessionNoticePlugin, supportsMessageDisplay, terminalSupportsColor, withSessionNoticePluginArgs, } from "./hooks.js";
|
|
@@ -32,7 +33,7 @@ import { resumesSession, runWithoutMemtree } from "./paused-session.js";
|
|
|
32
33
|
import { KEY_PAGE_URL, LOCAL_KEY_PAGE_URL, fetchKeyStatus, keyPageUrl, resolveInvalidKey, } from "./key-status.js";
|
|
33
34
|
import { UPDATE_CHECK_CACHE_FILE, checkForUpdate } from "./update-check.js";
|
|
34
35
|
import { setupAutoUpdate } from "./auto-update-setup.js";
|
|
35
|
-
import { compactTargetFromEnv, isPrintInvocation, parseWrapperArgs, memtreeLinkPlacementFromEnv, environmentOf, isVersionRequest, subcommandArgs, } from "./cli-args.js";
|
|
36
|
+
import { anthropicUpstreamFromEnv, compactTargetFromEnv, isPrintInvocation, parseWrapperArgs, memtreeLinkPlacementFromEnv, environmentOf, isVersionRequest, subcommandArgs, } from "./cli-args.js";
|
|
36
37
|
import { routeConsoleToStderr } from "./cli-output.js";
|
|
37
38
|
import { runMemtreeFetchCommand } from "./memtree-fetch.js";
|
|
38
39
|
import { runLinkCommand } from "./link-command.js";
|
|
@@ -41,10 +42,10 @@ import { readProjectMeta } from "./project-meta.js";
|
|
|
41
42
|
import { projectTreesHintFor } from "./project-trees.js";
|
|
42
43
|
import { planMemtreeMcp, withMemtreeMcpArgs, writeMemtreeMcpConfig, } from "./memtree-mcp-config.js";
|
|
43
44
|
import { claudeChildEnv, claudeNativeOneMillionContextEnabled, } from "./claude-env.js";
|
|
44
|
-
import { createSignalShutdownHandler, claudeExitFields, exitCodeForChild, settleWithin, writeStdout, } from "./cli-lifecycle.js";
|
|
45
|
+
import { createSignalShutdownHandler, claudeExitFields, exitCodeForChild, closeBoundedMs, CONSOLE_CLOSE_MARKS_MS, HANGUP_MEMTREE_DRAIN_MS, childExitMeansHangup, ignoreStreamErrors, onHangup, settleWithin, shutdownMemtreeDrainMs, writeStdout, } from "./cli-lifecycle.js";
|
|
45
46
|
import { getPolychatApiKey, setPolychatApiKey, getLocalPolychatApiKey, setLocalPolychatApiKey, getStagingPolychatApiKey, setStagingPolychatApiKey, getConfigDir, loadConfig, } from "./config.js";
|
|
46
47
|
import { repairStrandedResume, resumeSessionId } from "./resume-repair.js";
|
|
47
|
-
import { Diagnostics, DiagnosticsRequestSink, recordError } from "./diagnostics.js";
|
|
48
|
+
import { Diagnostics, DiagnosticsRequestSink, recordError, SHUTDOWN_FLUSH_MS, } from "./diagnostics.js";
|
|
48
49
|
import { PACKAGE_DIR, detectInstallMethod, takeUnreportedOutcome, updateFiles, } from "./auto-update.js";
|
|
49
50
|
import { claudeDesktopInstalled, claudeDesktopOnlyText, claudeMissingText, cwdHintText, locateClaude, withClaudeOnPath, } from "./claude-locate.js";
|
|
50
51
|
import { INSTALL_PROMPT_ENV, offerClaudeInstall, runInstaller } from "./claude-install.js";
|
|
@@ -57,7 +58,6 @@ const POLYCHAT_BASE_URL = "https://api.polychat.co";
|
|
|
57
58
|
const STAGING_BASE_URL = "https://polychat-staging-421312241218.us-west2.run.app";
|
|
58
59
|
const LOCAL_BASE_URL = "http://localhost:8080";
|
|
59
60
|
const SHUTDOWN_PROXY_DRAIN_MS = 5_000;
|
|
60
|
-
const SHUTDOWN_MEMTREE_DRAIN_MS = 2_000;
|
|
61
61
|
const SHUTDOWN_LOG_FLUSH_MS = 2_000;
|
|
62
62
|
/** Shutdown's wait for the child's exit and the resume hint's (asynchronous) write. */
|
|
63
63
|
const SHUTDOWN_OUTPUT_FLUSH_MS = 1_000;
|
|
@@ -542,6 +542,8 @@ async function main() {
|
|
|
542
542
|
...(process.env.CCC_CAPTURE_DIR ? { captureDir: process.env.CCC_CAPTURE_DIR } : {}),
|
|
543
543
|
// Test-only: a small budget so a cheap session crosses it in a few turns.
|
|
544
544
|
budgetTokensOverride: budgetFromEnv(process.env.CCC_BUDGET_TOKENS),
|
|
545
|
+
// Test-only: a loopback mock in place of api.anthropic.com (scripts/long-session).
|
|
546
|
+
upstreamOrigin: upstreamFromEnv(process.env.CCC_ANTHROPIC_UPSTREAM),
|
|
545
547
|
// CCC_MEMTREE_LINK=message|stop|success|off picks where the MemTree page
|
|
546
548
|
// link is shown while the placement is being tried out; see ProxyOptions.
|
|
547
549
|
memtreeLinkPlacement,
|
|
@@ -551,6 +553,8 @@ async function main() {
|
|
|
551
553
|
// Each session's adopted compressed prefix, so a resumed session's first
|
|
552
554
|
// turn rides it instead of blocking on a fresh compress.
|
|
553
555
|
stablePrefixStore: new StablePrefixStore(),
|
|
556
|
+
// Full copies of tool results shortened to fit the window (the safety net).
|
|
557
|
+
toolOutputs: new ToolOutputStore(),
|
|
554
558
|
// The link shown to the user follows the session's newest tree on the server.
|
|
555
559
|
newestTrees: new NewestTreeLookup((path, signal) => memtree.fetchMemTree(path, "application/json", signal)),
|
|
556
560
|
transcriptUsage,
|
|
@@ -605,6 +609,8 @@ async function main() {
|
|
|
605
609
|
// Also carries the unpaid-key notice on resume, so it is on even
|
|
606
610
|
// when MemTree links are off (the proxy then answers links-free).
|
|
607
611
|
resumeLink: true,
|
|
612
|
+
// CCC_AUTO_COMPACT=1 hands compaction back to Claude Code: /compact runs as typed.
|
|
613
|
+
interceptCompact: process.env.CCC_AUTO_COMPACT !== "1",
|
|
608
614
|
});
|
|
609
615
|
// Global option must precede a user-supplied `--`, positional prompt, or
|
|
610
616
|
// subcommand; --plugin-dir itself is repeatable, so existing dirs remain.
|
|
@@ -642,6 +648,21 @@ async function main() {
|
|
|
642
648
|
stdio: "inherit",
|
|
643
649
|
});
|
|
644
650
|
let shuttingDown = false;
|
|
651
|
+
/** When the Windows console window was closed (SIGHUP): the exit drain counts from it. */
|
|
652
|
+
let consoleClosedAt;
|
|
653
|
+
/** When the terminal hung up (macOS, Linux SIGHUP). */
|
|
654
|
+
let terminalHungUp = false;
|
|
655
|
+
/**
|
|
656
|
+
* A terminal to hang up: under nohup neither stdout nor stderr is one. Without one
|
|
657
|
+
* (`ccc -p ... >out 2>&1`) SIGHUP keeps its default, as before: it ends ccc at once.
|
|
658
|
+
*/
|
|
659
|
+
const hasTerminal = Boolean(process.stdout.isTTY || process.stderr.isTTY);
|
|
660
|
+
const markTerminalHungUp = () => {
|
|
661
|
+
if (terminalHungUp)
|
|
662
|
+
return;
|
|
663
|
+
terminalHungUp = true;
|
|
664
|
+
ignoreStreamErrors([process.stdout, process.stderr]);
|
|
665
|
+
};
|
|
645
666
|
// Settles once the child has exited and the resume hint (if any) is written,
|
|
646
667
|
// or the child failed to start. Awaited (bounded) just before exiting, so a
|
|
647
668
|
// signal whose cleanup finishes first still lets the hint print.
|
|
@@ -660,14 +681,22 @@ async function main() {
|
|
|
660
681
|
// finalize their records. Background indexing is a separate log producer:
|
|
661
682
|
// stop and drain it too before waiting for scheduled JSONL appends on
|
|
662
683
|
// disk.
|
|
663
|
-
|
|
684
|
+
// After a console close every step ends by its mark (cli-lifecycle.ts).
|
|
685
|
+
const marks = CONSOLE_CLOSE_MARKS_MS;
|
|
686
|
+
await proxy.drain(closeBoundedMs(SHUTDOWN_PROXY_DRAIN_MS, consoleClosedAt, marks.proxyDrain));
|
|
664
687
|
// A session ending now sends its final index at once (the idle timer
|
|
665
688
|
// would never fire), inside the same bounded background drain.
|
|
666
|
-
|
|
667
|
-
|
|
689
|
+
const memtreeDrainMs = terminalHungUp
|
|
690
|
+
? HANGUP_MEMTREE_DRAIN_MS
|
|
691
|
+
: shutdownMemtreeDrainMs(process.platform, consoleClosedAt);
|
|
692
|
+
memtree.flushFinalIndexes(memtreeDrainMs);
|
|
693
|
+
await memtree.drainBackground(memtreeDrainMs);
|
|
668
694
|
// Before the final flushes, so a late child exit's diagnostics event is sent.
|
|
669
|
-
await settleWithin(childDone, SHUTDOWN_OUTPUT_FLUSH_MS);
|
|
670
|
-
await Promise.all([
|
|
695
|
+
await settleWithin(childDone, closeBoundedMs(SHUTDOWN_OUTPUT_FLUSH_MS, consoleClosedAt, marks.childWait));
|
|
696
|
+
await Promise.all([
|
|
697
|
+
reqlog.flush(closeBoundedMs(SHUTDOWN_LOG_FLUSH_MS, consoleClosedAt, marks.flush)),
|
|
698
|
+
diagnostics.flush(closeBoundedMs(SHUTDOWN_FLUSH_MS, consoleClosedAt, marks.flush)),
|
|
699
|
+
]);
|
|
671
700
|
process.exit(code);
|
|
672
701
|
};
|
|
673
702
|
const handleShutdownSignal = createSignalShutdownHandler({
|
|
@@ -690,15 +719,21 @@ async function main() {
|
|
|
690
719
|
});
|
|
691
720
|
process.on("SIGINT", () => handleShutdownSignal("SIGINT"));
|
|
692
721
|
process.on("SIGTERM", () => handleShutdownSignal("SIGTERM"));
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
722
|
+
onHangup(process, (kind) => {
|
|
723
|
+
diagnostics.record("console_closed");
|
|
724
|
+
if (kind === "console-close") {
|
|
725
|
+
// Windows ends ccc a few seconds after its console window closes: start the
|
|
726
|
+
// update first, since the drains in shutdown may not finish in time.
|
|
727
|
+
consoleClosedAt ??= Date.now();
|
|
698
728
|
autoUpdate?.installOnExit((result) => diagnostics.record("auto_update", { result }));
|
|
699
729
|
handleShutdownSignal("SIGTERM");
|
|
700
|
-
|
|
701
|
-
|
|
730
|
+
return;
|
|
731
|
+
}
|
|
732
|
+
// macOS, Linux: the terminal is gone, but nothing ends ccc, so the final index
|
|
733
|
+
// gets a longer drain than an ordinary exit.
|
|
734
|
+
markTerminalHungUp();
|
|
735
|
+
handleShutdownSignal("SIGHUP");
|
|
736
|
+
}, hasTerminal);
|
|
702
737
|
// The background install starts once Claude Code is up; it outlives this
|
|
703
738
|
// process if the session ends first.
|
|
704
739
|
autoUpdate?.scheduleInstall(undefined, (result) => {
|
|
@@ -718,6 +753,9 @@ async function main() {
|
|
|
718
753
|
void shutdown(1);
|
|
719
754
|
});
|
|
720
755
|
child.on("exit", (code, signal) => {
|
|
756
|
+
// Before anything is written: the hangup may reach Claude Code before ccc.
|
|
757
|
+
if (hasTerminal && childExitMeansHangup(process.platform, code, signal))
|
|
758
|
+
markTerminalHungUp();
|
|
721
759
|
if (code !== 0) {
|
|
722
760
|
diagnostics.record("claude_exit", claudeExitFields(code, signal, claudeStartedAt));
|
|
723
761
|
}
|
|
@@ -856,6 +894,13 @@ function budgetFromEnv(raw) {
|
|
|
856
894
|
}
|
|
857
895
|
return budget;
|
|
858
896
|
}
|
|
897
|
+
/** `CCC_ANTHROPIC_UPSTREAM`: a test-only loopback upstream, or undefined (see cli-args.ts). */
|
|
898
|
+
function upstreamFromEnv(raw) {
|
|
899
|
+
const { value, warning } = anthropicUpstreamFromEnv(raw);
|
|
900
|
+
if (warning)
|
|
901
|
+
console.error(warning);
|
|
902
|
+
return value;
|
|
903
|
+
}
|
|
859
904
|
/** The update line a paused session's banner carries (the normal banner's, see notices.ts). */
|
|
860
905
|
function pausedUpdateLine(autoUpdate) {
|
|
861
906
|
const color = terminalSupportsColor();
|