claude-code-infinite 1.0.26 → 1.0.28
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 +44 -16
- package/dist/claude-auth.d.ts +9 -1
- package/dist/claude-auth.d.ts.map +1 -1
- package/dist/claude-auth.js +26 -4
- package/dist/claude-auth.js.map +1 -1
- package/dist/claude-env.d.ts +11 -4
- package/dist/claude-env.d.ts.map +1 -1
- package/dist/claude-env.js +11 -4
- package/dist/claude-env.js.map +1 -1
- package/dist/claude-locate.d.ts +18 -0
- package/dist/claude-locate.d.ts.map +1 -1
- package/dist/claude-locate.js +82 -3
- package/dist/claude-locate.js.map +1 -1
- package/dist/claude-plan-warning.d.ts +55 -0
- package/dist/claude-plan-warning.d.ts.map +1 -0
- package/dist/claude-plan-warning.js +95 -0
- package/dist/claude-plan-warning.js.map +1 -0
- package/dist/cli-args.d.ts +5 -0
- package/dist/cli-args.d.ts.map +1 -1
- package/dist/cli-args.js +9 -0
- package/dist/cli-args.js.map +1 -1
- package/dist/cli-lifecycle.d.ts +5 -0
- package/dist/cli-lifecycle.d.ts.map +1 -1
- package/dist/cli-lifecycle.js +13 -0
- package/dist/cli-lifecycle.js.map +1 -1
- package/dist/cli-main.js +170 -87
- package/dist/cli-main.js.map +1 -1
- package/dist/diagnostics-schema.d.ts +2 -0
- package/dist/diagnostics-schema.d.ts.map +1 -1
- package/dist/diagnostics-schema.js +13 -2
- package/dist/diagnostics-schema.js.map +1 -1
- package/dist/diagnostics.d.ts +8 -3
- package/dist/diagnostics.d.ts.map +1 -1
- package/dist/diagnostics.js +12 -3
- package/dist/diagnostics.js.map +1 -1
- package/dist/hooks.d.ts +8 -0
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +57 -25
- package/dist/hooks.js.map +1 -1
- package/dist/key-page.d.ts +17 -0
- package/dist/key-page.d.ts.map +1 -0
- package/dist/key-page.js +32 -0
- package/dist/key-page.js.map +1 -0
- package/dist/key-status.d.ts +79 -0
- package/dist/key-status.d.ts.map +1 -0
- package/dist/key-status.js +143 -0
- package/dist/key-status.js.map +1 -0
- package/dist/memtree.d.ts +23 -0
- package/dist/memtree.d.ts.map +1 -1
- package/dist/memtree.js +39 -3
- package/dist/memtree.js.map +1 -1
- package/dist/notices.d.ts +5 -0
- package/dist/notices.d.ts.map +1 -1
- package/dist/notices.js +13 -0
- package/dist/notices.js.map +1 -1
- package/dist/paused-session.d.ts +29 -0
- package/dist/paused-session.d.ts.map +1 -0
- package/dist/paused-session.js +148 -0
- package/dist/paused-session.js.map +1 -0
- package/dist/payment-gate.d.ts +44 -13
- package/dist/payment-gate.d.ts.map +1 -1
- package/dist/payment-gate.js +82 -23
- package/dist/payment-gate.js.map +1 -1
- package/dist/payment-link.d.ts +68 -0
- package/dist/payment-link.d.ts.map +1 -0
- package/dist/payment-link.js +123 -0
- package/dist/payment-link.js.map +1 -0
- package/dist/project-trees.d.ts +100 -0
- package/dist/project-trees.d.ts.map +1 -0
- package/dist/project-trees.js +196 -0
- package/dist/project-trees.js.map +1 -0
- package/dist/proxy.d.ts +13 -0
- package/dist/proxy.d.ts.map +1 -1
- package/dist/proxy.js +70 -8
- package/dist/proxy.js.map +1 -1
- package/dist/reqlog.d.ts +2 -0
- package/dist/reqlog.d.ts.map +1 -1
- package/dist/reqlog.js.map +1 -1
- package/package.json +1 -1
package/dist/proxy.js
CHANGED
|
@@ -56,6 +56,7 @@ import { COMPRESSED_NOTICE, compressedTotalsText, DEGRADED_NOTICE, NOT_COMPRESSE
|
|
|
56
56
|
import { NoticeDeliveryQueue, MEMTREE_COMPACT_COMMAND, MEMTREE_HELP_COMMAND, TRAILER_LABEL, LINK_LABEL, linkLines, urlLine, terminalSupportsHyperlinks, isMemtreeViewCommand, sessionCommandArgs, parseNoticeHookInput, } from "./hooks.js";
|
|
57
57
|
import { USAGE_LABEL, USAGE_SIGN_IN_NOTE } from "./usage-link.js";
|
|
58
58
|
import { hyperlink } from "./payment-gate.js";
|
|
59
|
+
import { keyInvalidNoticeText, keyInvalidRefusalMessage } from "./key-status.js";
|
|
59
60
|
import { PaymentNoticeThrottle, pausedCompactionText, pausedRefusalMessage, paymentNoticeText, subscribeUrlFromDetail } from "./payment-notice.js";
|
|
60
61
|
import { MEMTREE_LINKS_MAX_SESSIONS } from "./memtree-links.js";
|
|
61
62
|
import { describeClaudeCodeRequest, inspectMonitorTranscript, knownSideRequestKind, transcriptWarning, isClaudeCodeSideRequest, memtreeClientMeta, sessionTag, } from "./cc-request.js";
|
|
@@ -304,11 +305,15 @@ export function startProxy(opts) {
|
|
|
304
305
|
const shutdownAbort = new AbortController();
|
|
305
306
|
const state = {
|
|
306
307
|
paymentNotice: new PaymentNoticeThrottle(opts.paymentNoticeIntervalMs),
|
|
308
|
+
keyNotice: new PaymentNoticeThrottle(opts.paymentNoticeIntervalMs),
|
|
309
|
+
keyInvalid: () => opts.memtree.keyInvalid,
|
|
310
|
+
keyPageUrl: opts.memtree.keyPageUrl,
|
|
307
311
|
pausedNearWindowWarned: new Set(),
|
|
308
312
|
unpaidDetail: () => opts.memtree.paymentRequiredDetail,
|
|
309
313
|
pausedDetail: () => opts.memtree.pausedDetail,
|
|
310
314
|
usageUrl: opts.memtree.usageDashboardUrl,
|
|
311
315
|
sessionStartNotice: opts.sessionStartNotice,
|
|
316
|
+
projectTrees: opts.projectTrees,
|
|
312
317
|
diagnostics: opts.diagnostics,
|
|
313
318
|
notices: new NoticeDeliveryQueue(),
|
|
314
319
|
mainNoticePending: false,
|
|
@@ -726,17 +731,20 @@ onMainStop) {
|
|
|
726
731
|
recordSessionStart(state, parsed.source);
|
|
727
732
|
noteMainSessionStart(state, parsed.source, parsed.session_id);
|
|
728
733
|
}
|
|
734
|
+
// Earlier trees in this project: asked now, so its wait overlaps the resume's.
|
|
735
|
+
const contextPromise = projectTreesContext(state.projectTrees, parsed);
|
|
729
736
|
// A resume waits briefly for the newest tree; a fresh session has none to wait for.
|
|
730
737
|
if (parsed.agent_id === undefined && parsed.source === "resume") {
|
|
731
738
|
await state.newestTrees?.settle(parsed.session_id);
|
|
732
739
|
}
|
|
733
740
|
const line = joinNoticeLines(resumeLinkLine(state, parsed), resumePaymentNotice(state, parsed), extraSessionStartLine(state.sessionStartNotice, parsed));
|
|
734
|
-
|
|
741
|
+
const context = await contextPromise;
|
|
742
|
+
if (!line && !context) {
|
|
735
743
|
res.writeHead(204);
|
|
736
744
|
res.end();
|
|
737
745
|
return;
|
|
738
746
|
}
|
|
739
|
-
const body = Buffer.from(JSON.stringify(
|
|
747
|
+
const body = Buffer.from(JSON.stringify(sessionStartOutput(line, context)), "utf-8");
|
|
740
748
|
res.writeHead(200, {
|
|
741
749
|
"content-type": "application/json",
|
|
742
750
|
"content-length": String(body.length),
|
|
@@ -1697,6 +1705,13 @@ async function handleMessages(req, res, opts, upstream, state) {
|
|
|
1697
1705
|
// it pending for the next turn.
|
|
1698
1706
|
if (result && sessionId !== undefined)
|
|
1699
1707
|
state.compactNow.delete(sessionId);
|
|
1708
|
+
// A first 402 starts fetching the short checkout link (memtree.ts): give the
|
|
1709
|
+
// paused notice below a moment to show it instead of the long one. Only a turn
|
|
1710
|
+
// that can show the notice waits, and only while that fetch is in flight.
|
|
1711
|
+
if (!result && displayForThisTurn && state.mainPromptGeneration === noticePromptGeneration &&
|
|
1712
|
+
state.paymentNotice.due() && opts.memtree.paymentRequiredDetail !== null) {
|
|
1713
|
+
await opts.memtree.paymentLinkSettled?.(PAYMENT_LINK_NOTICE_WAIT_MS);
|
|
1714
|
+
}
|
|
1700
1715
|
if (downstreamClosedDuringCompression ||
|
|
1701
1716
|
(res.destroyed && !res.writableFinished)) {
|
|
1702
1717
|
releaseUncommittedRouteDecision();
|
|
@@ -1724,7 +1739,15 @@ async function handleMessages(req, res, opts, upstream, state) {
|
|
|
1724
1739
|
const paymentDetail = opts.memtree.paymentRequiredDetail;
|
|
1725
1740
|
const mayQueueNotice = displayForThisTurn && state.mainPromptGeneration === noticePromptGeneration;
|
|
1726
1741
|
const overBudget = reachedBudget(rec.compaction);
|
|
1727
|
-
if (
|
|
1742
|
+
if (state.keyInvalid()) {
|
|
1743
|
+
// A refused key (401/403) says why MemTree is off and how to fix it;
|
|
1744
|
+
// throttled like the payment notice, and quiet in between.
|
|
1745
|
+
if (mayQueueNotice && state.keyNotice.due()) {
|
|
1746
|
+
// A refusal of this very request says the same and withdraws it.
|
|
1747
|
+
pausedNotices.set(rec, state.notices.queueSuffix(keyInvalidNoticeText(state.keyPageUrl), () => state.keyNotice.markShown(), noticePromptId));
|
|
1748
|
+
}
|
|
1749
|
+
}
|
|
1750
|
+
else if (mayQueueNotice && paymentDetail !== null &&
|
|
1728
1751
|
(state.paymentNotice.due() || (overBudget && !nearWindowWarned(state, sessionId)))) {
|
|
1729
1752
|
// A paused refusal of this very request withdraws it (refuseWholeRequest),
|
|
1730
1753
|
// and any later one withdraws its near-window line.
|
|
@@ -1984,11 +2007,39 @@ function extraSessionStartLine(provider, input) {
|
|
|
1984
2007
|
return undefined;
|
|
1985
2008
|
}
|
|
1986
2009
|
}
|
|
2010
|
+
/**
|
|
2011
|
+
* Earlier sessions in this project (project-trees.ts) for a main session's
|
|
2012
|
+
* start: fresh, resumed, cleared or forked, never a compaction. Never throws.
|
|
2013
|
+
*/
|
|
2014
|
+
async function projectTreesContext(hint, input) {
|
|
2015
|
+
if (!hint || input.agent_id !== undefined || input.source === "compact")
|
|
2016
|
+
return undefined;
|
|
2017
|
+
try {
|
|
2018
|
+
return await hint.contextFor(input.session_id);
|
|
2019
|
+
}
|
|
2020
|
+
catch {
|
|
2021
|
+
return undefined;
|
|
2022
|
+
}
|
|
2023
|
+
}
|
|
2024
|
+
/**
|
|
2025
|
+
* The SessionStart hook's answer: the banner line for the user
|
|
2026
|
+
* (`systemMessage`), model context (`additionalContext`), or both.
|
|
2027
|
+
*/
|
|
2028
|
+
export function sessionStartOutput(line, context) {
|
|
2029
|
+
return {
|
|
2030
|
+
...(line ? { systemMessage: line } : {}),
|
|
2031
|
+
...(context
|
|
2032
|
+
? { hookSpecificOutput: { hookEventName: "SessionStart", additionalContext: context } }
|
|
2033
|
+
: {}),
|
|
2034
|
+
};
|
|
2035
|
+
}
|
|
1987
2036
|
function joinNoticeLines(...parts) {
|
|
1988
2037
|
const present = parts.filter((part) => !!part);
|
|
1989
2038
|
return present.length ? present.join("\n") : undefined;
|
|
1990
2039
|
}
|
|
1991
2040
|
export const MEMTREE_COMPACT_MIN_TOKENS = 20_000;
|
|
2041
|
+
/** How long a paused turn waits for the short checkout link before its notice (once). */
|
|
2042
|
+
export const PAYMENT_LINK_NOTICE_WAIT_MS = 1_000;
|
|
1992
2043
|
/** The reply to a ccc slash command, or undefined for an ordinary prompt. */
|
|
1993
2044
|
function sessionCommandReply(state, sessionId, prompt) {
|
|
1994
2045
|
const unpaid = state.unpaidDetail();
|
|
@@ -3554,7 +3605,9 @@ async function recoverToolRouteMiss(args) {
|
|
|
3554
3605
|
// a later turn. An unpaid key (402, possibly set by this very compress)
|
|
3555
3606
|
// or a shutting-down proxy gets no retry.
|
|
3556
3607
|
if (!state.shutdownSignal.aborted &&
|
|
3557
|
-
opts.memtree.paymentRequiredDetail === null
|
|
3608
|
+
opts.memtree.paymentRequiredDetail === null &&
|
|
3609
|
+
!opts.memtree.keyInvalid // a refused key refuses the index too
|
|
3610
|
+
) {
|
|
3558
3611
|
opts.memtree.indexInBackground(hash, msgsForMemtree, modelContextLimit, requestSessionId(req), args.clientMeta, transcriptTimesFor(opts, requestSessionId(req), agentAttributionId(req)));
|
|
3559
3612
|
}
|
|
3560
3613
|
return forwardOriginal();
|
|
@@ -3962,9 +4015,12 @@ async function wholeRequestRefused(sizing, candidate, limits) {
|
|
|
3962
4015
|
}
|
|
3963
4016
|
/** Write the bounded fallback refusal (route-fallback.ts); always false. */
|
|
3964
4017
|
function refuseWholeRequest(args, inputTokens, budgetTokens) {
|
|
3965
|
-
|
|
3966
|
-
const
|
|
3967
|
-
|
|
4018
|
+
// A refused key or a paused one: a retry cannot fix either, so it is final at once.
|
|
4019
|
+
const keyInvalid = args.state.keyInvalid();
|
|
4020
|
+
const unpaid = keyInvalid ? null : args.state.pausedDetail();
|
|
4021
|
+
const failure = keyInvalid ? pausedRefusal(keyInvalidRefusalMessage(args.state.keyPageUrl))
|
|
4022
|
+
: unpaid !== null ? pausedRefusal(pausedRefusalMessage(unpaid))
|
|
4023
|
+
: args.state.fallbackFailures.fail(args.routeKey, { awaitingIndex: args.rec.indexBehind === true });
|
|
3968
4024
|
args.rec.forwardedBytes = 0;
|
|
3969
4025
|
args.rec.approxInputTokens = 0;
|
|
3970
4026
|
args.state.diagnostics?.record("refusal", {
|
|
@@ -3977,8 +4033,9 @@ function refuseWholeRequest(args, inputTokens, budgetTokens) {
|
|
|
3977
4033
|
inputTokens, outputTokens: args.body.max_tokens ?? 0,
|
|
3978
4034
|
outputReservation: bodyOutputReservation(args.body), indexBehind: args.rec.indexBehind === true,
|
|
3979
4035
|
budgetTokens, modelContextLimit: args.modelContextLimit, ...(unpaid !== null ? { paused: true } : {}),
|
|
4036
|
+
...(keyInvalid ? { keyInvalid: true } : {}),
|
|
3980
4037
|
};
|
|
3981
|
-
if (unpaid !== null)
|
|
4038
|
+
if (unpaid !== null || keyInvalid)
|
|
3982
4039
|
cancelPausedNotice(args.state, args.rec);
|
|
3983
4040
|
if (args.res.headersSent || args.res.destroyed)
|
|
3984
4041
|
return false;
|
|
@@ -3987,6 +4044,9 @@ function refuseWholeRequest(args, inputTokens, budgetTokens) {
|
|
|
3987
4044
|
if (unpaid !== null) {
|
|
3988
4045
|
notePausedRefusal(args.state, args.rec, args.routeKey, requestSessionId(args.req));
|
|
3989
4046
|
}
|
|
4047
|
+
// The refusal named the key: it counts as the key notice on the user's screen.
|
|
4048
|
+
if (keyInvalid && args.rec.routeLane === "main")
|
|
4049
|
+
args.state.keyNotice.markShown();
|
|
3990
4050
|
return false;
|
|
3991
4051
|
}
|
|
3992
4052
|
/**
|
|
@@ -4025,6 +4085,8 @@ function cancelPausedNotice(state, rec) {
|
|
|
4025
4085
|
* already queued the paused notice carries the line itself.
|
|
4026
4086
|
*/
|
|
4027
4087
|
function warnPausedNearWindow(state, rec, sessionId) {
|
|
4088
|
+
if (state.keyInvalid())
|
|
4089
|
+
return; // a refused key, not a pause: the key notice says why
|
|
4028
4090
|
const detail = state.unpaidDetail();
|
|
4029
4091
|
// Paid again: a later pause (next month's limit) warns afresh.
|
|
4030
4092
|
if (detail === null)
|