Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@cortexkit/opencode-anthropic-auth

Package Overview
Dependencies
Maintainers
1
Versions
22
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@cortexkit/opencode-anthropic-auth - npm Package Compare versions

Comparing version
1.1.1
to
1.1.2
+190
-19
dist/index.js
import { randomUUID } from 'node:crypto';
import { authorize, buildClaudeQuotaSummary, buildFallbackQuotaSummaries, buildRefreshOperationError, CACHE_1H_COMMAND_NAME, CLAUDE_DUMP_COMMAND_NAME, CLAUDE_FAST_COMMAND_NAME, CLAUDE_QUOTAS_COMMAND_NAME, ClaudeOAuthRefreshError, exchange, executeCache1hCommand, executeDumpCommand, executeFastModeCommand, FallbackAccountManager, fetchOAuthQuotaSnapshot, formatRefreshBackoffMessage, getCache1hMode, getCache1hPersistentMode, getQuotaCheckIntervalMs, getQuotaNextRefreshAt, getRelayConfig, hashRefreshToken, isCache1hEnabled, isCache1hPersistentlyEnabled, isDumpPersistentlyEnabled, isFastModeEnabled, isFastModePersistentlyEnabled, isFastModeSupportedModel, loadAccounts, log, parseCache1hCommandAction, parseDumpCommandAction, parseFastModeCommandAction, quotaSnapshotPassesPolicy, refreshBackoffActive, refreshClaudeOAuthToken, resolveClaudeCodeIdentity, saveAccounts, sendViaRelay, setCache1hPersistentEnabled, setCache1hPersistentMode, setCache1hState, setDumpEnabled, setDumpPersistentEnabled, setFastModeEnabled, setFastModePersistentEnabled, shouldFallbackStatus, } from '@cortexkit/anthropic-auth-core';
import { authorize, buildClaudeQuotaSummary, buildFallbackQuotaSummaries, buildRefreshOperationError, CACHE_1H_COMMAND_NAME, CACHE_KEEP_EXTENDED_TTL_BETA, CacheKeepManager, CLAUDE_CACHE_KEEP_COMMAND_NAME, CLAUDE_DUMP_COMMAND_NAME, CLAUDE_FAST_COMMAND_NAME, CLAUDE_QUOTAS_COMMAND_NAME, ClaudeOAuthRefreshError, exchange, executeCache1hCommand, executeCacheKeepCommand, executeDumpCommand, executeFastModeCommand, FallbackAccountManager, fetchOAuthQuotaSnapshot, formatRefreshBackoffMessage, getCache1hMode, getCache1hPersistentMode, getCacheKeepWindow, getQuotaCheckIntervalMs, getQuotaNextRefreshAt, getRelayConfig, hashRefreshToken, isCache1hEnabled, isCache1hPersistentlyEnabled, isCacheKeepHybridActive, isCacheKeepPersistentlyEnabled, isDumpPersistentlyEnabled, isFastModeEnabled, isFastModePersistentlyEnabled, isFastModeSupportedModel, loadAccounts, log, mergeAnthropicBetas, parseCache1hCommandAction, parseCacheKeepCommandAction, parseDumpCommandAction, parseFastModeCommandAction, quotaSnapshotPassesPolicy, refreshBackoffActive, refreshClaudeOAuthToken, resolveClaudeCodeIdentity, saveAccounts, sendViaRelay, setCache1hPersistentEnabled, setCache1hPersistentMode, setCache1hState, setCacheKeepPersistentEnabled, setCacheKeepPersistentWindow, setDumpEnabled, setDumpPersistentEnabled, setFastModeEnabled, setFastModePersistentEnabled, shouldFallbackStatus, } from '@cortexkit/anthropic-auth-core';
import { resolvePromptContext } from "./prompt-context.js";

@@ -10,2 +10,5 @@ import { addFastModeBetaHeader, createStrippedStream, isInsecure, mergeHeaders, rewriteRequestBody, rewriteUrl, setOAuthHeaders, } from "./transform.js";

let eventLoopLagMonitorStarted = false;
function perfLoggingEnabled() {
return process.env.OPENCODE_ANTHROPIC_AUTH_PERF === '1';
}
function nowMs() {

@@ -18,4 +21,7 @@ return performance.now();

function startEventLoopLagMonitor() {
if (eventLoopLagMonitorStarted || process.env.NODE_ENV === 'test')
if (eventLoopLagMonitorStarted ||
process.env.NODE_ENV === 'test' ||
!perfLoggingEnabled()) {
return;
}
eventLoopLagMonitorStarted = true;

@@ -45,9 +51,11 @@ const intervalMs = 100;

const current = nowMs();
log('[perf] opencode request stage', {
requestId: trace.requestId,
stage,
deltaMs: roundMs(current - trace.last),
totalMs: roundMs(current - trace.start),
...stageData,
});
if (perfLoggingEnabled()) {
log('[perf] opencode request stage', {
requestId: trace.requestId,
stage,
deltaMs: roundMs(current - trace.last),
totalMs: roundMs(current - trace.start),
...stageData,
});
}
trace.last = current;

@@ -57,13 +65,20 @@ },

const current = nowMs();
log('[perf] opencode request done', {
requestId: trace.requestId,
stage,
deltaMs: roundMs(current - trace.last),
totalMs: roundMs(current - trace.start),
...stageData,
});
if (perfLoggingEnabled()) {
log('[perf] opencode request done', {
requestId: trace.requestId,
stage,
deltaMs: roundMs(current - trace.last),
totalMs: roundMs(current - trace.start),
...stageData,
});
}
trace.last = current;
},
};
log('[perf] opencode request start', { requestId: trace.requestId, ...data });
if (perfLoggingEnabled()) {
log('[perf] opencode request start', {
requestId: trace.requestId,
...data,
});
}
return trace;

@@ -105,2 +120,39 @@ }

fallbackManager.startBackgroundRefresh();
let latestRefreshMainAccessToken = null;
const cacheKeepManager = new CacheKeepManager({
loadStorage: () => loadAccounts(),
prepareHeaders: async (headers, target) => {
if (!latestGetAuth)
return headers;
const auth = await latestGetAuth();
if (auth.type !== 'oauth')
return headers;
if (!auth.access || (auth.expires && auth.expires < Date.now())) {
if (!latestRefreshMainAccessToken)
return headers;
auth.access = await latestRefreshMainAccessToken();
}
if (!auth.access)
return headers;
try {
const parsedBody = JSON.parse(target.bodyText);
const identity = await resolveClaudeCodeIdentity(auth.access, typeof parsedBody.model === 'string' ? parsedBody.model : undefined);
headers.delete('anthropic-beta');
setOAuthHeaders(headers, auth.access, {
body: parsedBody,
identity,
});
headers.set('anthropic-beta', mergeAnthropicBetas(headers.get('anthropic-beta'), [
CACHE_KEEP_EXTENDED_TTL_BETA,
]));
if (parsedBody.speed === 'fast')
addFastModeBetaHeader(headers);
}
catch {
setOAuthHeaders(headers, auth.access);
}
return headers;
},
log,
});
const initialCache1hStorage = await loadAccounts();

@@ -124,2 +176,20 @@ const relayConfig = getRelayConfig(initialCache1hStorage);

}
async function clearStaleMainRefreshError(refreshToken) {
if (!refreshToken)
return;
const storage = await loadAccounts();
const error = storage?.refresh?.mainLastRefreshError;
if (!storage?.refresh || !error?.tokenHash)
return;
const tokenHash = hashRefreshToken(refreshToken);
if (error.tokenHash === tokenHash)
return;
storage.refresh.mainLastRefreshError = undefined;
await saveAccounts(storage);
log('[refresh] opencode main oauth cleared stale backoff after token rotation', {
previousCheckedAt: error.checkedAt,
previousNextRetryAt: error.nextRetryAt,
previousRetryCount: error.retryCount,
});
}
async function buildQuotaCommandSummary() {

@@ -189,2 +259,22 @@ const accounts = [];

}
async function executePersistentCacheKeepCommand(argumentsText) {
const action = parseCacheKeepCommandAction(argumentsText);
let storage = await loadAccounts();
if (action.type === 'window') {
storage = await setCacheKeepPersistentWindow(action.startHour, action.endHour);
}
else if (action.type === 'disable') {
storage = await setCacheKeepPersistentEnabled(false);
}
const window = getCacheKeepWindow(storage);
const stats = cacheKeepManager.stats(window);
return executeCacheKeepCommand({
argumentsText,
enabled: isCacheKeepPersistentlyEnabled(storage),
window,
hybridActive: isCacheKeepHybridActive(storage),
trackedSessions: stats.trackedSessions,
nextPrewarmAt: stats.nextPrewarmAt,
});
}
async function executePersistentDumpCommand(argumentsText) {

@@ -224,2 +314,6 @@ const action = parseDumpCommandAction(argumentsText);

},
[CLAUDE_CACHE_KEEP_COMMAND_NAME]: {
template: CLAUDE_CACHE_KEEP_COMMAND_NAME,
description: 'Keep hybrid Claude cache warm for recently used sessions during a local time window.',
},
[CLAUDE_QUOTAS_COMMAND_NAME]: {

@@ -244,2 +338,6 @@ template: CLAUDE_QUOTAS_COMMAND_NAME,

}
if (input.command === CLAUDE_CACHE_KEEP_COMMAND_NAME) {
await sendIgnoredMessage(ctx, input.sessionID, await executePersistentCacheKeepCommand(input.arguments));
throwHandledSentinel();
}
if (input.command === CLAUDE_QUOTAS_COMMAND_NAME) {

@@ -315,4 +413,20 @@ await sendIgnoredMessage(ctx, input.sessionID, await buildQuotaCommandSummary());

const mainError = storage?.refresh?.mainLastRefreshError;
log('[refresh] opencode main oauth refresh check', {
attempt,
expiresInMs: freshAuth.expires
? freshAuth.expires - Date.now()
: undefined,
hasBackoff: Boolean(mainError),
backoffActive: mainError
? refreshBackoffActive(mainError, freshAuth.refresh, Date.now())
: false,
retryCount: mainError?.retryCount,
nextRetryAt: mainError?.nextRetryAt,
});
if (mainError &&
refreshBackoffActive(mainError, freshAuth.refresh, Date.now())) {
log('[refresh] opencode main oauth refresh skipped backoff', {
nextRetryAt: mainError.nextRetryAt,
retryCount: mainError.retryCount,
});
throw new Error(formatRefreshBackoffMessage(mainError, Date.now()));

@@ -324,2 +438,5 @@ }

refreshTokenHash) {
log('[refresh] opencode main oauth refresh skipped lease', {
leaseUntil: storage.refresh.mainRefreshLeaseUntil,
});
throw new Error('Claude OAuth refresh is already in progress');

@@ -339,2 +456,6 @@ }

const latestLease = await loadAccounts();
log('[refresh] opencode main oauth refresh lease acquired', {
attempt,
leaseUntil: Date.now() + 2 * 60_000,
});
if (latestLease?.refresh?.mainRefreshLeaseId !== leaseId ||

@@ -345,2 +466,5 @@ latestLease.refresh.mainRefreshLeaseTokenHash !==

}
log('[refresh] opencode main oauth refresh request start', {
attempt,
});
const refreshed = await refreshClaudeOAuthToken({

@@ -371,2 +495,6 @@ refreshToken: freshAuth.refresh,

});
log('[refresh] opencode main oauth refresh succeeded', {
attempt,
expiresInMs: refreshed.expires - Date.now(),
});
return refreshed.access;

@@ -388,2 +516,9 @@ }

}
log('[refresh] opencode main oauth refresh attempt failed', {
attempt,
error: error instanceof Error
? error.message
: String(error),
transient: isNetworkError,
});
const failedRefreshToken = freshAuth?.refresh;

@@ -430,2 +565,3 @@ if (failedRefreshToken &&

}
latestRefreshMainAccessToken = refreshMainAccessToken;
function startMainBackgroundRefresh() {

@@ -444,10 +580,20 @@ if (mainBackgroundRefreshTimer) {

return;
await clearStaleMainRefreshError(latestAuth.refresh);
if (!latestAuth.expires)
return;
if (latestAuth.expires - Date.now() >
mainRefreshBeforeExpiryMs(storage)) {
const expiresInMs = latestAuth.expires - Date.now();
const refreshBeforeMs = mainRefreshBeforeExpiryMs(storage);
if (expiresInMs > refreshBeforeMs) {
return;
}
log('[refresh] opencode main oauth background due', {
expiresInMs,
refreshBeforeMs,
});
if (latestAuth.refresh &&
refreshBackoffActive(storage?.refresh?.mainLastRefreshError, latestAuth.refresh, Date.now())) {
log('[refresh] opencode main oauth background skipped backoff', {
nextRetryAt: storage?.refresh?.mainLastRefreshError?.nextRetryAt,
retryCount: storage?.refresh?.mainLastRefreshError?.retryCount,
});
return;

@@ -627,2 +773,20 @@ }

const rewritten = rewriteUrl(input);
if (route === 'main' &&
typeof body === 'string' &&
!subagentRequest &&
isCache1hEnabled() &&
getCache1hMode() === 'hybrid') {
const storage = await loadAccounts();
const tracked = await cacheKeepManager.track({
sessionId: relayAffinity,
url: rewritten.url?.toString() ?? rewritten.input.toString(),
headers: requestHeaders,
bodyText: body,
storage,
cacheMode: 'hybrid',
});
if (tracked.tracked) {
trace?.mark('cachekeep_track', { session: relayAffinity });
}
}
const directFetch = () => fetch(rewritten.input, {

@@ -767,3 +931,10 @@ ...init,

}
await clearStaleMainRefreshError(auth.refresh);
if (!auth.access || !auth.expires || auth.expires < Date.now()) {
log('[refresh] opencode main oauth refresh required for request', {
hasAccess: Boolean(auth.access),
expiresInMs: auth.expires
? auth.expires - Date.now()
: undefined,
});
const refreshStart = nowMs();

@@ -770,0 +941,0 @@ auth.access = await refreshMainAccessToken();

+4
-1

@@ -66,3 +66,6 @@ function isRecord(value) {

try {
messages = extractMessages(await Promise.resolve(typedClient.session.messages({ path: { id: sessionId } })));
messages = extractMessages(await Promise.resolve(typedClient.session.messages({
path: { id: sessionId },
query: { limit: 100 },
})));
}

@@ -69,0 +72,0 @@ catch {

{
"name": "@cortexkit/opencode-anthropic-auth",
"version": "1.1.1",
"version": "1.1.2",
"type": "module",

@@ -43,4 +43,4 @@ "repository": {

"dependencies": {
"@cortexkit/anthropic-auth-core": "1.1.1"
"@cortexkit/anthropic-auth-core": "1.1.2"
}
}

@@ -22,3 +22,3 @@ # CortexKit Anthropic Auth for OpenCode and Pi

| Sidecar config | `~/.config/opencode/anthropic-auth.json` | `~/.pi/agent/anthropic-auth.json` |
| Commands | `/claude-cache`, `/claude-fast`, `/claude-quota`, `/claude-dump` | `/claude-cache`, `/claude-fast`, `/claude-quota`, `/claude-dump` |
| Commands | `/claude-cache`, `/claude-cachekeep`, `/claude-fast`, `/claude-quota`, `/claude-dump` | `/claude-cache`, `/claude-cachekeep`, `/claude-fast`, `/claude-quota`, `/claude-dump` |
| Fallback accounts, quota routing, relay, dumps, fast mode | Supported | Supported through the same shared core and Pi sidecar |

@@ -31,2 +31,3 @@

- **Persistent Claude cache controls**: manage Anthropic 1-hour prompt caching from `/claude-cache` with explicit, automatic, or hybrid modes.
- **Cache keepalive**: use `/claude-cachekeep HH-HH` to pre-warm hybrid cache anchors for active sessions before the 1-hour TTL expires.
- **Fast mode toggle**: use `/claude-fast on|off` to request Anthropic fast mode for supported Opus models.

@@ -46,3 +47,3 @@ - **Live quota visibility**: use `/claude-quota` to see main and fallback quota state, reset times, and refresh errors.

- Apply quota thresholds before routing to main or fallback accounts.
- Add `/claude-cache`, `/claude-fast`, `/claude-quota`, and `/claude-dump` commands.
- Add `/claude-cache`, `/claude-cachekeep`, `/claude-fast`, `/claude-quota`, and `/claude-dump` commands.
- Optionally relay large requests through a Cloudflare Worker owned by the user.

@@ -178,2 +179,7 @@

},
"cacheKeep": {
"enabled": false,
"startHour": 9,
"endHour": 23
},
"dump": {

@@ -196,3 +202,3 @@ "enabled": false

The `claudeCache` block controls the `/claude-cache` command's persisted mode, and `claudeFast` controls `/claude-fast`. The `main` field identifies OpenCode's primary auth entry; Pi keeps primary OAuth credentials in Pi's own credential store, but uses the same sidecar shape for CortexKit settings and fallback accounts.
The `claudeCache` block controls the `/claude-cache` command's persisted mode, `cacheKeep` controls `/claude-cachekeep`, and `claudeFast` controls `/claude-fast`. The `main` field identifies OpenCode's primary auth entry; Pi keeps primary OAuth credentials in Pi's own credential store, but uses the same sidecar shape for CortexKit settings and fallback accounts.

@@ -283,2 +289,18 @@ ## Fallback accounts

### Cache keepalive
`/claude-cachekeep` keeps recently used hybrid-mode session caches warm while the agent process is running:
```text
/claude-cachekeep
/claude-cachekeep 09-23
/claude-cachekeep off
```
The hour range uses local 24-hour time and is start-inclusive/end-exclusive. `09-23` means cache keepalive may run from 09:00 until 22:59. Overnight windows such as `23-09` are accepted.
Cache keepalive only tracks requests when `/claude-cache` is enabled in `hybrid` mode. For each active session seen that day, the package keeps an in-memory clone of the latest rewritten Anthropic request and sends a non-streaming `max_tokens: 0` pre-warm request about five minutes before the 1-hour cache entry would expire. Nothing is written to disk except the schedule configuration.
Pre-warm requests preserve explicit cache anchors but remove response-only fields that Anthropic rejects with `max_tokens: 0`, such as streaming, enabled thinking, structured output format, and forced/any tool choice. The feature works only while OpenCode or Pi is running and the machine is awake, and cache writes are still billed when the cache entry is no longer warm.
## Claude fast mode

@@ -285,0 +307,0 @@