@juvio15/pi-cliproxyapi-provider 0.0.0-stage → 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/LICENSE +21 -0
- package/package.json +51 -4
- package/src/core/catalog.ts +400 -0
- package/src/core/connection.ts +119 -0
- package/src/core/costs.ts +477 -0
- package/src/core/index.ts +186 -0
- package/src/core/oauth.ts +279 -0
- package/src/core/streams.ts +89 -0
- package/src/core/usage.ts +813 -0
- package/src/extension/completions.ts +20 -0
- package/src/extension/config.ts +314 -0
- package/src/extension/fast.ts +81 -0
- package/src/extension/files.ts +146 -0
- package/src/extension/footer.ts +229 -0
- package/src/extension/index.ts +477 -0
- package/src/extension/oauth.ts +203 -0
- package/src/extension/pause.ts +126 -0
- package/src/extension/prices.ts +191 -0
- package/src/extension/prompt-cache.ts +17 -0
- package/src/extension/provider.ts +386 -0
- package/src/extension/retry.ts +41 -0
- package/src/extension/status.ts +166 -0
- package/src/extension/tps.ts +215 -0
- package/src/extension/usage.ts +609 -0
- package/src/extension/web-search.ts +307 -0
- package/src/web-search/endpoint.ts +21 -0
- package/src/web-search/index.ts +21 -0
- package/src/web-search/model-selector.ts +93 -0
- package/src/web-search/search.ts +571 -0
- package/src/web-search/sse.ts +144 -0
- package/README.md +0 -3
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ExtensionAPI,
|
|
3
|
+
ExtensionContext,
|
|
4
|
+
} from "@earendil-works/pi-coding-agent";
|
|
5
|
+
|
|
6
|
+
import type { PauseController } from "./pause.ts";
|
|
7
|
+
|
|
8
|
+
const STATUS_KEY = "tps";
|
|
9
|
+
const REFRESH_INTERVAL_MS = 1000;
|
|
10
|
+
|
|
11
|
+
const primaryUi = (ctx: ExtensionContext): boolean =>
|
|
12
|
+
ctx.hasUI && ctx.mode === "tui";
|
|
13
|
+
|
|
14
|
+
const formatElapsed = (totalSeconds: number): string => {
|
|
15
|
+
const safe = Math.max(0, Math.floor(totalSeconds));
|
|
16
|
+
|
|
17
|
+
const units = [
|
|
18
|
+
{ suffix: "d", value: Math.floor(safe / 86_400) },
|
|
19
|
+
{ suffix: "h", value: Math.floor((safe % 86_400) / 3600) },
|
|
20
|
+
{ suffix: "m", value: Math.floor((safe % 3600) / 60) },
|
|
21
|
+
{ suffix: "s", value: safe % 60 },
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
const first = units.findIndex(
|
|
25
|
+
(unit, index) => unit.value > 0 || index === units.length - 1
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
return units
|
|
29
|
+
.slice(first)
|
|
30
|
+
.map((unit) => `${unit.value}${unit.suffix}`)
|
|
31
|
+
.join(" ");
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export interface TpsUsage {
|
|
35
|
+
cacheRead: number;
|
|
36
|
+
cacheWrite: number;
|
|
37
|
+
input: number;
|
|
38
|
+
output: number;
|
|
39
|
+
total: number;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const PERCENT = 100;
|
|
43
|
+
const MS_PER_SECOND = 1000;
|
|
44
|
+
|
|
45
|
+
const count = (value: number): string => value.toLocaleString("en-US");
|
|
46
|
+
|
|
47
|
+
const seconds = (ms: number): string => (ms / MS_PER_SECOND).toFixed(1);
|
|
48
|
+
|
|
49
|
+
/** The run summary: output speed over generation time, run length, and cache hit rate. */
|
|
50
|
+
export const formatTpsSummary = (
|
|
51
|
+
usage: TpsUsage,
|
|
52
|
+
generationMs: number,
|
|
53
|
+
wallMs: number
|
|
54
|
+
): string => {
|
|
55
|
+
const tps =
|
|
56
|
+
generationMs > 0
|
|
57
|
+
? (usage.output / (generationMs / MS_PER_SECOND)).toFixed(1)
|
|
58
|
+
: "--";
|
|
59
|
+
|
|
60
|
+
const prompt = usage.input + usage.cacheRead;
|
|
61
|
+
|
|
62
|
+
const cacheHit =
|
|
63
|
+
prompt > 0 ? `${Math.round((usage.cacheRead / prompt) * PERCENT)}%` : "--";
|
|
64
|
+
|
|
65
|
+
return `TPS ${tps} tok/s (${seconds(generationMs)}s generating of ${seconds(wallMs)}s). out ${count(usage.output)}, in ${count(usage.input)}, cache hit ${cacheHit} (r/w ${count(usage.cacheRead)}/${count(usage.cacheWrite)}), total ${count(usage.total)}`;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const emptyUsage = (): TpsUsage => ({
|
|
69
|
+
cacheRead: 0,
|
|
70
|
+
cacheWrite: 0,
|
|
71
|
+
input: 0,
|
|
72
|
+
output: 0,
|
|
73
|
+
total: 0,
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
const isProviderAssistant = (
|
|
77
|
+
message: { role: string; provider?: unknown },
|
|
78
|
+
providerId: string
|
|
79
|
+
): boolean => message.role === "assistant" && message.provider === providerId;
|
|
80
|
+
|
|
81
|
+
export const registerTpsFooter = (
|
|
82
|
+
pi: ExtensionAPI,
|
|
83
|
+
pause: PauseController,
|
|
84
|
+
providerId: string
|
|
85
|
+
): void => {
|
|
86
|
+
let startedAt: number | undefined;
|
|
87
|
+
let pausedAtStart = 0;
|
|
88
|
+
let pauseAtStart = false;
|
|
89
|
+
let timer: ReturnType<typeof setInterval> | undefined;
|
|
90
|
+
let statusContext: ExtensionContext | undefined;
|
|
91
|
+
let usage = emptyUsage();
|
|
92
|
+
let generationMs = 0;
|
|
93
|
+
let generationStartedAt: number | undefined;
|
|
94
|
+
|
|
95
|
+
const clearTimer = (): void => {
|
|
96
|
+
if (timer) {
|
|
97
|
+
clearInterval(timer);
|
|
98
|
+
timer = undefined;
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const elapsed = (): number => {
|
|
103
|
+
if (startedAt === undefined) {
|
|
104
|
+
return 0;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return pauseAtStart
|
|
108
|
+
? pause.getElapsed(startedAt, pausedAtStart)
|
|
109
|
+
: Math.max(0, Date.now() - startedAt);
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const showElapsed = (ctx: ExtensionContext): void => {
|
|
113
|
+
if (primaryUi(ctx)) {
|
|
114
|
+
ctx.ui.setStatus(
|
|
115
|
+
STATUS_KEY,
|
|
116
|
+
ctx.ui.theme.fg("dim", `Elapsed ${formatElapsed(elapsed() / 1000)}`)
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
pi.on("before_agent_start", (_event, ctx) => {
|
|
122
|
+
if (!primaryUi(ctx)) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
statusContext = ctx;
|
|
127
|
+
|
|
128
|
+
if (startedAt !== undefined) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
startedAt = Date.now();
|
|
133
|
+
pauseAtStart = pause.isEnabled();
|
|
134
|
+
pausedAtStart = pause.getPausedDuration(startedAt);
|
|
135
|
+
usage = emptyUsage();
|
|
136
|
+
generationMs = 0;
|
|
137
|
+
generationStartedAt = undefined;
|
|
138
|
+
showElapsed(ctx);
|
|
139
|
+
clearTimer();
|
|
140
|
+
timer = setInterval(() => {
|
|
141
|
+
if (statusContext) {
|
|
142
|
+
showElapsed(statusContext);
|
|
143
|
+
}
|
|
144
|
+
}, REFRESH_INTERVAL_MS);
|
|
145
|
+
timer.unref();
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
pi.on("message_start", (event) => {
|
|
149
|
+
if (
|
|
150
|
+
startedAt !== undefined &&
|
|
151
|
+
isProviderAssistant(event.message, providerId)
|
|
152
|
+
) {
|
|
153
|
+
generationStartedAt = Date.now();
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
pi.on("message_end", (event) => {
|
|
158
|
+
if (
|
|
159
|
+
generationStartedAt === undefined ||
|
|
160
|
+
!isProviderAssistant(event.message, providerId)
|
|
161
|
+
) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
generationMs += Math.max(0, Date.now() - generationStartedAt);
|
|
166
|
+
generationStartedAt = undefined;
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
pi.on("agent_end", (event, ctx) => {
|
|
170
|
+
if (startedAt === undefined || !primaryUi(ctx)) {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
for (const message of event.messages) {
|
|
175
|
+
if (message.role !== "assistant" || message.provider !== providerId) {
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
usage.input += message.usage.input;
|
|
180
|
+
usage.output += message.usage.output;
|
|
181
|
+
usage.cacheRead += message.usage.cacheRead;
|
|
182
|
+
usage.cacheWrite += message.usage.cacheWrite;
|
|
183
|
+
usage.total += message.usage.totalTokens;
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
pi.on("agent_settled", (_event, ctx) => {
|
|
188
|
+
if (startedAt === undefined || !primaryUi(ctx)) {
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const elapsedMs = elapsed();
|
|
193
|
+
showElapsed(ctx);
|
|
194
|
+
startedAt = undefined;
|
|
195
|
+
clearTimer();
|
|
196
|
+
statusContext = ctx;
|
|
197
|
+
|
|
198
|
+
if (elapsedMs <= 0) {
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
ctx.ui.notify(formatTpsSummary(usage, generationMs, elapsedMs), "info");
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
pi.on("session_shutdown", (_event, ctx) => {
|
|
206
|
+
clearTimer();
|
|
207
|
+
|
|
208
|
+
if (primaryUi(ctx)) {
|
|
209
|
+
ctx.ui.setStatus(STATUS_KEY, undefined);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
startedAt = undefined;
|
|
213
|
+
statusContext = undefined;
|
|
214
|
+
});
|
|
215
|
+
};
|