pi-spark 0.21.0 → 0.21.1
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/README.md +1 -1
- package/docs/reverse-engineering-fireworks-credits.md +1 -1
- package/package.json +1 -1
- package/src/features/credits/manager.ts +4 -3
- package/src/features/credits/providers/openai-codex.ts +4 -3
- package/src/features/presets/manager.ts +7 -3
- package/src/utils/auth.ts +11 -0
- package/assets/screencast-write.mp4 +0 -0
package/README.md
CHANGED
|
@@ -80,7 +80,7 @@ pi-spark names the session automatically after the first completed turn, so it's
|
|
|
80
80
|
|
|
81
81
|
Long, streaming `write` tool calls keep their latest lines visible instead of pinning the preview to the beginning. The omitted-line count appears above the preview, while `ctrl+o` still expands the full content.
|
|
82
82
|
|
|
83
|
-
https://
|
|
83
|
+
https://github.com/user-attachments/assets/b7bb77c1-c188-46a2-aba9-6487bdf58fa0
|
|
84
84
|
|
|
85
85
|
## Configuration
|
|
86
86
|
|
|
@@ -89,7 +89,7 @@ The amount is `units + nanos / 1e9` (the standard `google.type.Money` encoding),
|
|
|
89
89
|
The provider lives in [`src/features/credits/providers/fireworks.ts`](../src/features/credits/providers/fireworks.ts) and follows the same `CreditsProvider` contract as the HTTP-based providers; only the transport differs.
|
|
90
90
|
|
|
91
91
|
- **Transport.** A single, reused `@grpc/grpc-js` client dials `gateway.fireworks.ai:443` over TLS. The service is declared in [`fireworks.proto`](../src/features/credits/providers/fireworks.proto) — the minimal slice needed, loaded at runtime with `@grpc/proto-loader`. The `.proto` is resolved relative to the module via `import.meta.url`, so it ships and loads from the package directory.
|
|
92
|
-
- **Auth.** Each call sends `x-api-key: <key>` in gRPC metadata. The
|
|
92
|
+
- **Auth.** Each call sends `x-api-key: <key>` in gRPC metadata. The manager resolves provider authentication through Pi's `modelRegistry.getProviderAuth("fireworks")`. For Fireworks, Pi returns the API key sourced from `FIREWORKS_API_KEY`.
|
|
93
93
|
- **Account resolution.** `ListAccounts` is called once and the resolved `accounts/<id>` is cached per API key, so steady-state refreshes are a single `GetBalance` round trip.
|
|
94
94
|
- **Cancellation.** The shared `AbortSignal` cancels the in-flight gRPC call, and a defensive deadline bounds each request.
|
|
95
95
|
- **Result.** `Money` is converted to a dollar amount and returned as `{ type: "balance", remaining }`, which the status line renders like any other balance provider.
|
package/package.json
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getAuthToken } from "../../utils/auth";
|
|
1
2
|
import { findProvider } from "./providers";
|
|
2
3
|
import { renderCredits, renderError } from "./status";
|
|
3
4
|
|
|
@@ -47,14 +48,14 @@ export class CreditsManager {
|
|
|
47
48
|
|
|
48
49
|
private async fetch(ctx: ExtensionContext, provider: CreditsProvider, signal: AbortSignal): Promise<void> {
|
|
49
50
|
try {
|
|
50
|
-
const
|
|
51
|
+
const token = await getAuthToken(ctx.modelRegistry, provider.id);
|
|
51
52
|
if (signal.aborted) return;
|
|
52
|
-
if (!
|
|
53
|
+
if (!token) {
|
|
53
54
|
ctx.ui.setStatus(STATUS_KEY, undefined);
|
|
54
55
|
return;
|
|
55
56
|
}
|
|
56
57
|
|
|
57
|
-
const credits = await provider.fetch(
|
|
58
|
+
const credits = await provider.fetch(token, signal);
|
|
58
59
|
|
|
59
60
|
// The active model may have changed while the request was in flight.
|
|
60
61
|
if (ctx.model?.provider !== provider.id) return;
|
|
@@ -3,6 +3,7 @@ import { readStoredCredential } from "@earendil-works/pi-coding-agent";
|
|
|
3
3
|
import prettyMilliseconds from "pretty-ms";
|
|
4
4
|
|
|
5
5
|
import { confirmCodexReset, formatAvailableResets, showCodexResetLoader, showCodexResetSelector } from "./openai-codex-panel";
|
|
6
|
+
import { getAuthToken } from "../../../utils/auth";
|
|
6
7
|
import { toNumber } from "../../../utils/format";
|
|
7
8
|
import { http, withAuth } from "../../../utils/http";
|
|
8
9
|
|
|
@@ -51,10 +52,10 @@ interface ConsumeResetResponse {
|
|
|
51
52
|
}
|
|
52
53
|
|
|
53
54
|
async function runCodexReset(ctx: ExtensionContext, refresh: RefreshCredits): Promise<void> {
|
|
54
|
-
const
|
|
55
|
-
if (!
|
|
55
|
+
const token = await getAuthToken(ctx.modelRegistry, PROVIDER);
|
|
56
|
+
if (!token) return;
|
|
56
57
|
|
|
57
|
-
const client = createClient(
|
|
58
|
+
const client = createClient(token);
|
|
58
59
|
|
|
59
60
|
const credit = await showCodexResetSelector(ctx, async (signal) => {
|
|
60
61
|
const [usage, details] = await Promise.all([fetchUsage(client, signal), fetchResetCredits(client, signal)]);
|
|
@@ -80,10 +80,14 @@ export class PresetManager {
|
|
|
80
80
|
const currentIndex = currentKey ? this.keys.indexOf(currentKey) : -1;
|
|
81
81
|
const step = direction === "forward" ? 1 : -1;
|
|
82
82
|
const nextIndex = currentIndex === -1 ? direction === "forward" ? 0 : this.keys.length - 1 : (currentIndex + step + this.keys.length) % this.keys.length;
|
|
83
|
-
const nextKey = this.keys[nextIndex];
|
|
84
|
-
if (!nextKey) return;
|
|
85
83
|
|
|
86
|
-
|
|
84
|
+
for (let offset = 0; offset < this.keys.length; offset++) {
|
|
85
|
+
const candidateIndex = (nextIndex + step * offset + this.keys.length) % this.keys.length;
|
|
86
|
+
const candidateKey = this.keys[candidateIndex];
|
|
87
|
+
if (!candidateKey) continue;
|
|
88
|
+
|
|
89
|
+
if (await this.apply(candidateKey, ctx)) return;
|
|
90
|
+
}
|
|
87
91
|
}
|
|
88
92
|
|
|
89
93
|
describe(key: string): string {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ProviderId } from "@earendil-works/pi-ai";
|
|
2
|
+
import type { ModelRegistry } from "@earendil-works/pi-coding-agent";
|
|
3
|
+
|
|
4
|
+
export async function getAuthToken(modelRegistry: ModelRegistry, provider: ProviderId): Promise<string | undefined> {
|
|
5
|
+
const providerAuth = await modelRegistry.getProviderAuth(provider);
|
|
6
|
+
|
|
7
|
+
const authorization = Object.entries(providerAuth?.auth.headers ?? {}).find(([name]) => name.toLowerCase() === "authorization")?.[1];
|
|
8
|
+
const bearerToken = authorization?.match(/^Bearer\s+(.+)$/i)?.[1];
|
|
9
|
+
|
|
10
|
+
return providerAuth?.auth.apiKey ?? bearerToken;
|
|
11
|
+
}
|
|
Binary file
|