pi-provider-cursor-ask 0.1.0
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/CHANGELOG.md +9 -0
- package/LICENSE +21 -0
- package/README.md +87 -0
- package/README.zh-CN.md +87 -0
- package/UPSTREAM_CHANGELOG.md +368 -0
- package/UPSTREAM_SOURCE.md +23 -0
- package/dist/index.js +54 -0
- package/package.json +97 -0
- package/src/auth/cli-credentials.ts +275 -0
- package/src/auth/consent.ts +25 -0
- package/src/auth/index.ts +23 -0
- package/src/auth/oauth.ts +282 -0
- package/src/auth/refresh-guard.ts +93 -0
- package/src/client/bridge.ts +673 -0
- package/src/client/cursor-wire.ts +213 -0
- package/src/client/h2-unary.ts +142 -0
- package/src/client/index.ts +18 -0
- package/src/config/index.ts +69 -0
- package/src/diagnostics/diagnostics.ts +116 -0
- package/src/diagnostics/index.ts +1 -0
- package/src/extension/auth.ts +99 -0
- package/src/extension/commands.ts +163 -0
- package/src/extension/compaction-guard.ts +86 -0
- package/src/extension/debug-hooks.ts +359 -0
- package/src/extension/index.ts +8 -0
- package/src/extension/provider.ts +277 -0
- package/src/extension/quota-adapter.ts +175 -0
- package/src/extension/report-dashboard.ts +133 -0
- package/src/identity.ts +16 -0
- package/src/index.ts +186 -0
- package/src/models/ask-catalog.ts +384 -0
- package/src/models/catalog.json +1163 -0
- package/src/models/cost.ts +126 -0
- package/src/models/index.ts +6 -0
- package/src/models/limits.ts +36 -0
- package/src/models/parameterized.ts +416 -0
- package/src/models/processing.ts +313 -0
- package/src/proto/agent_pb.ts +14577 -0
- package/src/stream/bridge-session.ts +215 -0
- package/src/stream/client-transcript.ts +51 -0
- package/src/stream/config.ts +5 -0
- package/src/stream/context-normalize.ts +308 -0
- package/src/stream/context-usage.ts +168 -0
- package/src/stream/debug-log.ts +316 -0
- package/src/stream/drift.ts +122 -0
- package/src/stream/images.ts +201 -0
- package/src/stream/index.ts +68 -0
- package/src/stream/interaction-query.ts +369 -0
- package/src/stream/message-parsing.ts +402 -0
- package/src/stream/model-cache.ts +100 -0
- package/src/stream/model-discovery.ts +242 -0
- package/src/stream/model-routing.ts +100 -0
- package/src/stream/native-core.ts +2121 -0
- package/src/stream/pi-adapter.ts +414 -0
- package/src/stream/protocol.ts +63 -0
- package/src/stream/recovery.ts +494 -0
- package/src/stream/request-build.ts +668 -0
- package/src/stream/root-prompt.ts +184 -0
- package/src/stream/run-journal.ts +474 -0
- package/src/stream/run-usage.ts +107 -0
- package/src/stream/server-messages.ts +777 -0
- package/src/stream/session-state.ts +499 -0
- package/src/stream/stream-writer.ts +211 -0
- package/src/stream/thinking-filter.ts +63 -0
- package/src/stream/tool-schema.ts +185 -0
- package/src/stream/transport-errors.ts +150 -0
- package/src/stream/tuning.ts +250 -0
- package/src/stream/types.ts +330 -0
- package/src/types/enums.ts +103 -0
- package/src/types/index.ts +4 -0
- package/src/usage.ts +262 -0
- package/src/utils/cache-dir.ts +39 -0
- package/src/utils/index.ts +2 -0
- package/src/utils/security.ts +68 -0
- package/src/utils/util.ts +43 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Back-off for Cursor refresh-token exchanges that are known to fail.
|
|
3
|
+
*
|
|
4
|
+
* The Cursor CLI can leave a stale keychain entry behind — in the observed
|
|
5
|
+
* case it writes the *same expired access token* into `cursor-refresh-token`,
|
|
6
|
+
* so `exchange_user_api_key` answers `Invalid User API Key` in ~2.6s. Without
|
|
7
|
+
* a memory of that failure every pi launch re-pays those seconds on the
|
|
8
|
+
* startup path before falling through to a source that works.
|
|
9
|
+
*
|
|
10
|
+
* Failures are keyed by a hash of the refresh token (never the token itself)
|
|
11
|
+
* and persisted so the back-off survives process restarts. A token that starts
|
|
12
|
+
* working again is picked up as soon as the entry expires, and any successful
|
|
13
|
+
* exchange clears the entry immediately.
|
|
14
|
+
*/
|
|
15
|
+
import { createHash } from "node:crypto";
|
|
16
|
+
import { readFileSync, writeFileSync } from "node:fs";
|
|
17
|
+
|
|
18
|
+
import { cacheFilePath } from "../utils/cache-dir.js";
|
|
19
|
+
|
|
20
|
+
/** How long a failed exchange suppresses retries for the same token. */
|
|
21
|
+
export const REFRESH_FAILURE_TTL_MS = 10 * 60 * 1000;
|
|
22
|
+
|
|
23
|
+
const CACHE_FILE = "refresh-failures.json";
|
|
24
|
+
|
|
25
|
+
type FailureMap = Record<string, number>;
|
|
26
|
+
|
|
27
|
+
let failures: FailureMap | undefined;
|
|
28
|
+
|
|
29
|
+
function tokenKey(refreshToken: string): string {
|
|
30
|
+
return createHash("sha256").update(refreshToken).digest("hex").slice(0, 16);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function load(): FailureMap {
|
|
34
|
+
if (failures) return failures;
|
|
35
|
+
failures = {};
|
|
36
|
+
const path = cacheFilePath(CACHE_FILE);
|
|
37
|
+
if (!path) return failures;
|
|
38
|
+
try {
|
|
39
|
+
const parsed: unknown = JSON.parse(readFileSync(path, "utf8"));
|
|
40
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
41
|
+
const now = Date.now();
|
|
42
|
+
for (const [key, expiresAt] of Object.entries(parsed as Record<string, unknown>)) {
|
|
43
|
+
if (typeof expiresAt === "number" && expiresAt > now) failures[key] = expiresAt;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
} catch {
|
|
47
|
+
// Missing or corrupt cache is equivalent to "nothing known to be failing".
|
|
48
|
+
}
|
|
49
|
+
return failures;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function persist(map: FailureMap): void {
|
|
53
|
+
const path = cacheFilePath(CACHE_FILE);
|
|
54
|
+
if (!path) return;
|
|
55
|
+
try {
|
|
56
|
+
writeFileSync(path, JSON.stringify(map), { mode: 0o600 });
|
|
57
|
+
} catch {
|
|
58
|
+
// Best effort: an unwritable cache only costs us the cross-process benefit.
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** True when this refresh token failed recently and should not be retried yet. */
|
|
63
|
+
export function isRefreshKnownBad(refreshToken: string): boolean {
|
|
64
|
+
const map = load();
|
|
65
|
+
const expiresAt = map[tokenKey(refreshToken)];
|
|
66
|
+
if (expiresAt === undefined) return false;
|
|
67
|
+
if (Date.now() >= expiresAt) {
|
|
68
|
+
delete map[tokenKey(refreshToken)];
|
|
69
|
+
persist(map);
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** Record a failed exchange so the next launch skips it. */
|
|
76
|
+
export function markRefreshFailed(refreshToken: string, ttlMs = REFRESH_FAILURE_TTL_MS): void {
|
|
77
|
+
const map = load();
|
|
78
|
+
map[tokenKey(refreshToken)] = Date.now() + ttlMs;
|
|
79
|
+
persist(map);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** Clear a recorded failure after a successful exchange. */
|
|
83
|
+
export function markRefreshSucceeded(refreshToken: string): void {
|
|
84
|
+
const map = load();
|
|
85
|
+
if (map[tokenKey(refreshToken)] === undefined) return;
|
|
86
|
+
delete map[tokenKey(refreshToken)];
|
|
87
|
+
persist(map);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** Test helper: drop in-memory state so the next call re-reads from disk. */
|
|
91
|
+
export function resetRefreshGuardForTests(): void {
|
|
92
|
+
failures = undefined;
|
|
93
|
+
}
|