@saccolabs/pi-claude-cli 0.4.4 → 0.4.5
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/index.ts +42 -1
- package/package.json +1 -1
- package/src/provider.ts +14 -0
- package/src/types.ts +20 -1
package/index.ts
CHANGED
|
@@ -22,6 +22,44 @@ process.on("exit", killAllProcesses);
|
|
|
22
22
|
|
|
23
23
|
const PROVIDER_ID = "pi-claude-cli";
|
|
24
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Status key carrying account rate-limit state to the front-end. Neutral
|
|
27
|
+
* (not pidex-specific) because any pi front-end can read it.
|
|
28
|
+
*/
|
|
29
|
+
const RATE_LIMIT_STATUS_KEY = "claude-rate-limit";
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The stream runs deep inside streamSimple, which has no ExtensionContext,
|
|
33
|
+
* so the ctx handed to session_start is kept for its `ui.setStatus`.
|
|
34
|
+
*/
|
|
35
|
+
let uiContext:
|
|
36
|
+
{ ui?: { setStatus?(key: string, text?: string): void } } | undefined;
|
|
37
|
+
/** Last payload pushed — the CLI repeats this event on every turn. */
|
|
38
|
+
let lastRateLimitJson: string | undefined;
|
|
39
|
+
|
|
40
|
+
function publishRateLimit(info: Record<string, unknown>): void {
|
|
41
|
+
const setStatus = uiContext?.ui?.setStatus;
|
|
42
|
+
if (typeof setStatus !== "function") return;
|
|
43
|
+
const payload = JSON.stringify({
|
|
44
|
+
status: info.status,
|
|
45
|
+
resetsAt: info.resetsAt,
|
|
46
|
+
rateLimitType: info.rateLimitType,
|
|
47
|
+
overageStatus: info.overageStatus,
|
|
48
|
+
isUsingOverage: info.isUsingOverage === true,
|
|
49
|
+
observedAt: Math.floor(Date.now() / 1000),
|
|
50
|
+
});
|
|
51
|
+
// Push only on change: the event repeats every turn, and a status that
|
|
52
|
+
// rewrites itself constantly is noise for whatever renders it.
|
|
53
|
+
const withoutObservedAt = payload.replace(/,"observedAt":\d+/, "");
|
|
54
|
+
if (withoutObservedAt === lastRateLimitJson) return;
|
|
55
|
+
lastRateLimitJson = withoutObservedAt;
|
|
56
|
+
try {
|
|
57
|
+
setStatus.call(uiContext!.ui, RATE_LIMIT_STATUS_KEY, payload);
|
|
58
|
+
} catch {
|
|
59
|
+
/* never break a turn over a status push */
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
25
63
|
let mcpConfigPath: string | undefined;
|
|
26
64
|
let mcpConfigResolved = false;
|
|
27
65
|
|
|
@@ -91,7 +129,9 @@ export default function (pi: ExtensionAPI) {
|
|
|
91
129
|
|
|
92
130
|
// Ensure all registered tools are active so pi can execute them.
|
|
93
131
|
// Some tools (find, grep, ls) are registered but not activated by default.
|
|
94
|
-
pi.on("session_start", async () => {
|
|
132
|
+
pi.on("session_start", async (_event: unknown, ctx: unknown) => {
|
|
133
|
+
uiContext = ctx as typeof uiContext;
|
|
134
|
+
lastRateLimitJson = undefined;
|
|
95
135
|
const allTools = pi.getAllTools();
|
|
96
136
|
if (Array.isArray(allTools)) {
|
|
97
137
|
pi.setActiveTools(allTools.map((t: any) => t.name));
|
|
@@ -107,6 +147,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
107
147
|
return streamViaCli(model, context, {
|
|
108
148
|
...options,
|
|
109
149
|
mcpConfigPath: configPath,
|
|
150
|
+
onRateLimit: publishRateLimit,
|
|
110
151
|
});
|
|
111
152
|
};
|
|
112
153
|
|
package/package.json
CHANGED
package/src/provider.ts
CHANGED
|
@@ -55,6 +55,8 @@ const INACTIVITY_TIMEOUT_MS =
|
|
|
55
55
|
type StreamViaCLiOptions = SimpleStreamOptions & {
|
|
56
56
|
cwd?: string;
|
|
57
57
|
mcpConfigPath?: string;
|
|
58
|
+
/** Called with account rate-limit state as the CLI reports it. */
|
|
59
|
+
onRateLimit?: (info: Record<string, unknown>) => void;
|
|
58
60
|
};
|
|
59
61
|
|
|
60
62
|
/**
|
|
@@ -296,6 +298,18 @@ export function streamViaCli(
|
|
|
296
298
|
rl.close();
|
|
297
299
|
return; // Don't process further -- done event already pushed by event bridge
|
|
298
300
|
}
|
|
301
|
+
} else if (msg.type === "rate_limit_event") {
|
|
302
|
+
// Account-level state, not turn content: hand it to the host so a
|
|
303
|
+
// front-end can surface the window and its reset. Never touches
|
|
304
|
+
// the assistant message.
|
|
305
|
+
const info = (msg as any).rate_limit_info;
|
|
306
|
+
if (info && typeof info === "object") {
|
|
307
|
+
try {
|
|
308
|
+
options?.onRateLimit?.(info);
|
|
309
|
+
} catch {
|
|
310
|
+
/* a status push must never break a turn */
|
|
311
|
+
}
|
|
312
|
+
}
|
|
299
313
|
} else if (msg.type === "assistant") {
|
|
300
314
|
// Complete-block envelopes: marker text for CLI-side tools that
|
|
301
315
|
// would otherwise be invisible between cycles.
|
package/src/types.ts
CHANGED
|
@@ -43,6 +43,24 @@ export interface ClaudeAssistantEnvelope {
|
|
|
43
43
|
};
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Emitted when the API reports rate-limit state for the account. Carries the
|
|
48
|
+
* window and its reset, not a utilization percentage — the percentages the
|
|
49
|
+
* Claude Code TUI shows come from `anthropic-ratelimit-unified-*` response
|
|
50
|
+
* headers, which the CLI consumes in-process and does not forward here.
|
|
51
|
+
*/
|
|
52
|
+
export interface ClaudeRateLimitEvent {
|
|
53
|
+
type: "rate_limit_event";
|
|
54
|
+
rate_limit_info?: {
|
|
55
|
+
status?: string;
|
|
56
|
+
resetsAt?: number;
|
|
57
|
+
rateLimitType?: string;
|
|
58
|
+
overageStatus?: string;
|
|
59
|
+
overageDisabledReason?: string;
|
|
60
|
+
isUsingOverage?: boolean;
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
46
64
|
/** Tool results the CLI feeds back between cycles (top-level only). */
|
|
47
65
|
export interface ClaudeUserEnvelope {
|
|
48
66
|
type: "user";
|
|
@@ -81,7 +99,8 @@ export type NdjsonMessage =
|
|
|
81
99
|
| ClaudeSystemMessage
|
|
82
100
|
| ClaudeControlRequest
|
|
83
101
|
| ClaudeAssistantEnvelope
|
|
84
|
-
| ClaudeUserEnvelope
|
|
102
|
+
| ClaudeUserEnvelope
|
|
103
|
+
| ClaudeRateLimitEvent;
|
|
85
104
|
|
|
86
105
|
// Claude API event types (inside stream_event wrapper)
|
|
87
106
|
|