@juvio15/pi-cliproxyapi-provider 0.1.0 → 0.1.2
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/package.json +1 -1
- package/src/core/catalog.ts +7 -0
- package/src/core/index.ts +15 -4
- package/src/extension/index.ts +10 -5
- package/src/extension/prices.ts +15 -1
- package/src/extension/prompt-cache.ts +2 -2
package/package.json
CHANGED
package/src/core/catalog.ts
CHANGED
|
@@ -368,6 +368,13 @@ export const fetchCatalog = async (
|
|
|
368
368
|
return "models" in payload ? payload.models : payload.data;
|
|
369
369
|
};
|
|
370
370
|
|
|
371
|
+
/**
|
|
372
|
+
* Drops models the latest catalog no longer lists. mergeCatalog keeps them so
|
|
373
|
+
* a session that uses one still resolves, but nobody should pick one anew.
|
|
374
|
+
*/
|
|
375
|
+
export const withoutStale = <T extends object>(models: readonly T[]): T[] =>
|
|
376
|
+
models.filter((model) => !("stale" in model && model.stale === true));
|
|
377
|
+
|
|
371
378
|
export const mergeCatalog = (
|
|
372
379
|
previous: readonly CliproxyModel[],
|
|
373
380
|
fresh: readonly CliproxyModel[],
|
package/src/core/index.ts
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
* matchModelCost(modelId: string, catalog: CostCatalog, fast?: boolean): ModelCost
|
|
14
14
|
* mapCatalog(entries: readonly CatalogModel[], options: MappingOptions): MappedCatalog
|
|
15
15
|
* mergeCatalog(previous: readonly CliproxyModel[], fresh: readonly CliproxyModel[], options?: MergeOptions): CliproxyModel[]
|
|
16
|
+
* withoutStale<T extends object>(models: readonly T[]): T[]
|
|
16
17
|
* wrapCliproxyStreams(streams: ProviderStreams, settings: PayloadSettings): ProviderStreams
|
|
17
18
|
* createCliproxyProvider(options: CliproxyProviderOptions): Provider<CliproxyApi>
|
|
18
19
|
* quotaResetFromError(message: string, now?: number): number | undefined
|
|
@@ -23,13 +24,21 @@
|
|
|
23
24
|
* resetCooldowns(options: ResetCooldownsOptions): Promise<string[]>
|
|
24
25
|
* unavailableModels(usage: readonly ProviderUsage[], exhausted: Readonly<Record<string, number>>, now?: number): Map<string, number>
|
|
25
26
|
*/
|
|
26
|
-
|
|
27
|
-
import {
|
|
28
|
-
|
|
27
|
+
// pi maps only some pi-ai entry points into extensions. compat re-exports the same lazy API factories.
|
|
28
|
+
import {
|
|
29
|
+
anthropicMessagesApi,
|
|
30
|
+
openAICompletionsApi,
|
|
31
|
+
openAIResponsesApi,
|
|
32
|
+
} from "@earendil-works/pi-ai/compat";
|
|
29
33
|
import { createProvider } from "@earendil-works/pi-ai/models";
|
|
30
34
|
import type { Provider } from "@earendil-works/pi-ai/models";
|
|
31
35
|
|
|
32
|
-
import {
|
|
36
|
+
import {
|
|
37
|
+
fetchCatalog,
|
|
38
|
+
mapCatalog,
|
|
39
|
+
mergeCatalog,
|
|
40
|
+
withoutStale,
|
|
41
|
+
} from "./catalog.ts";
|
|
33
42
|
import type { CliproxyApi, CliproxyModel, MappingOptions } from "./catalog.ts";
|
|
34
43
|
import { resolveEndpoints } from "./connection.ts";
|
|
35
44
|
import { fetchCosts } from "./costs.ts";
|
|
@@ -43,6 +52,7 @@ export {
|
|
|
43
52
|
mapCatalog,
|
|
44
53
|
mergeCatalog,
|
|
45
54
|
selectModelApi,
|
|
55
|
+
withoutStale,
|
|
46
56
|
type CatalogFetchOptions,
|
|
47
57
|
type CatalogModel,
|
|
48
58
|
type CliproxyApi,
|
|
@@ -177,6 +187,7 @@ export const createCliproxyProvider = (
|
|
|
177
187
|
staleTtlMs: options.staleTtlMs,
|
|
178
188
|
});
|
|
179
189
|
},
|
|
190
|
+
filterModels: (models) => withoutStale(models),
|
|
180
191
|
id,
|
|
181
192
|
models: options.models ?? [],
|
|
182
193
|
name: options.providerName ?? "CLIProxyAPI",
|
package/src/extension/index.ts
CHANGED
|
@@ -4,7 +4,11 @@ import type {
|
|
|
4
4
|
ExtensionContext,
|
|
5
5
|
} from "@earendil-works/pi-coding-agent";
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
resolveConnectionSources,
|
|
9
|
+
resolveEndpoints,
|
|
10
|
+
withoutStale,
|
|
11
|
+
} from "../core/index.ts";
|
|
8
12
|
import type { CliproxyModel } from "../core/index.ts";
|
|
9
13
|
import { completeFrom } from "./completions.ts";
|
|
10
14
|
import {
|
|
@@ -140,7 +144,7 @@ const registerCatalogCommands = (
|
|
|
140
144
|
const models = controller.getModels();
|
|
141
145
|
const stale = models.filter((model) => model.stale).length;
|
|
142
146
|
ctx.ui.notify(
|
|
143
|
-
`Refreshed ${models.length} CLIProxyAPI models${stale ?
|
|
147
|
+
`Refreshed ${models.length - stale} CLIProxyAPI models${stale ? `. Hid ${stale} that CLIProxyAPI no longer lists` : ""}.`,
|
|
144
148
|
"info"
|
|
145
149
|
);
|
|
146
150
|
} catch (error) {
|
|
@@ -229,7 +233,7 @@ export default async function cliproxyapiProvider(
|
|
|
229
233
|
configured: connection !== null,
|
|
230
234
|
connection: initialConnection,
|
|
231
235
|
fast,
|
|
232
|
-
filterAvailable: (models) => tracker.filter(models),
|
|
236
|
+
filterAvailable: (models) => tracker.filter(withoutStale(models)),
|
|
233
237
|
onModels: (models) => {
|
|
234
238
|
latestModels = models;
|
|
235
239
|
|
|
@@ -370,8 +374,9 @@ export default async function cliproxyapiProvider(
|
|
|
370
374
|
});
|
|
371
375
|
registerWebSearch(pi, {
|
|
372
376
|
agentDir,
|
|
373
|
-
getAvailableModels: () =>
|
|
374
|
-
|
|
377
|
+
getAvailableModels: () =>
|
|
378
|
+
tracker.filter(withoutStale(controller.getModels())),
|
|
379
|
+
getModels: () => withoutStale(controller.getModels()),
|
|
375
380
|
getStandardCost: controller.getStandardCost,
|
|
376
381
|
providerId,
|
|
377
382
|
});
|
package/src/extension/prices.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
|
|
3
|
-
import { ModelCostSchema } from "@earendil-works/pi-ai/providers/model-schema";
|
|
4
3
|
import { Type } from "typebox";
|
|
5
4
|
import type { Static } from "typebox";
|
|
6
5
|
|
|
@@ -22,6 +21,21 @@ const MINUTE_MS = 60_000;
|
|
|
22
21
|
const HOUR_MS = 60 * MINUTE_MS;
|
|
23
22
|
const DAY_MS = 24 * HOUR_MS;
|
|
24
23
|
|
|
24
|
+
const RateFields = {
|
|
25
|
+
cacheRead: Type.Number(),
|
|
26
|
+
cacheWrite: Type.Number(),
|
|
27
|
+
input: Type.Number(),
|
|
28
|
+
output: Type.Number(),
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/** pi-ai's ModelCost. pi does not expose pi-ai's model-schema module to extensions, and typecheck holds this to ModelCost where the file feeds costCatalogFromPrices. */
|
|
32
|
+
const ModelCostSchema = Type.Object({
|
|
33
|
+
...RateFields,
|
|
34
|
+
tiers: Type.Optional(
|
|
35
|
+
Type.Array(Type.Object({ ...RateFields, inputTokensAbove: Type.Number() }))
|
|
36
|
+
),
|
|
37
|
+
});
|
|
38
|
+
|
|
25
39
|
const PricesFileSchema = Type.Object({
|
|
26
40
|
etag: Type.Optional(Type.String()),
|
|
27
41
|
fetchedAt: Type.Number(),
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { ModelPromptCache } from "@earendil-works/pi-ai";
|
|
2
|
-
import {
|
|
2
|
+
import { getBuiltinModels } from "@earendil-works/pi-ai/providers/all";
|
|
3
3
|
|
|
4
4
|
const LIFETIMES = new Map<string, ModelPromptCache | undefined>(
|
|
5
|
-
|
|
5
|
+
getBuiltinModels("anthropic").map((model) => [model.id, model.promptCache])
|
|
6
6
|
);
|
|
7
7
|
|
|
8
8
|
/** pi-ai's own Anthropic lifetimes, matched on the id or its segment after the last "/". */
|