@monotykamary/pi-better-grok 0.3.2 → 0.3.4
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 +2 -2
- package/index.ts +16 -0
- package/package.json +5 -5
- package/src/config.ts +3 -0
- package/src/xai-models.ts +162 -0
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# pi-better-grok
|
|
2
2
|
|
|
3
|
-
Better Grok/xAI for [pi](https://pi.dev) — mirrors the [pi-better-openai](https://github.com/monotykamary/pi-better-openai) UX for SuperGrok subscribers: fast mode, subscription usage in the footer, footer polish, and a settings picker.
|
|
3
|
+
Better Grok/xAI for [pi](https://pi.dev) — mirrors the [pi-better-openai](https://github.com/monotykamary/pi-better-openai) UX for SuperGrok subscribers: fast mode, subscription usage in the footer, footer polish, and a settings picker. Until pi-core ships it, Grok 4.7 is layered onto the existing `xai` (and sibling Grok) providers as a custom model.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -51,7 +51,7 @@ JSON config at `~/.pi/agent/extensions/pi-better-grok.json` (global) or `<projec
|
|
|
51
51
|
```json
|
|
52
52
|
{
|
|
53
53
|
"persistState": true,
|
|
54
|
-
"supportedModels": ["xai/grok-4.6", "xai/grok-4.5"],
|
|
54
|
+
"supportedModels": ["xai/grok-4.7", "xai/grok-4.6", "xai/grok-4.5"],
|
|
55
55
|
"fast": { "effort": "low" },
|
|
56
56
|
"usage": {
|
|
57
57
|
"enabled": true,
|
package/index.ts
CHANGED
|
@@ -73,6 +73,7 @@ import {
|
|
|
73
73
|
} from "./src/grok-auth.ts";
|
|
74
74
|
import { currentModelKey, FastController, modelList, supportsFast } from "./src/fast-controller.ts";
|
|
75
75
|
import { isGrokSubscriptionModel, UsageController } from "./src/usage-controller.ts";
|
|
76
|
+
import { registerGrok47OnProviders } from "./src/xai-models.ts";
|
|
76
77
|
import { sep } from "node:path";
|
|
77
78
|
|
|
78
79
|
// pi-core's getSettingsListTheme pulls the host module graph into this
|
|
@@ -731,7 +732,22 @@ export default function betterGrok(pi: ExtensionAPI): void {
|
|
|
731
732
|
setStatusWidget(ctx, statusWidgetParts(fast, usage));
|
|
732
733
|
}
|
|
733
734
|
|
|
735
|
+
const ensureGrok47 = (ctx: ExtensionContext): void => {
|
|
736
|
+
if (typeof pi.registerProvider !== "function") return;
|
|
737
|
+
const getAll = ctx.modelRegistry?.getAll;
|
|
738
|
+
if (typeof getAll !== "function") return;
|
|
739
|
+
try {
|
|
740
|
+
registerGrok47OnProviders(
|
|
741
|
+
(name, config) => pi.registerProvider(name, config),
|
|
742
|
+
getAll.call(ctx.modelRegistry),
|
|
743
|
+
);
|
|
744
|
+
} catch {
|
|
745
|
+
// Catalog registration must not break session startup.
|
|
746
|
+
}
|
|
747
|
+
};
|
|
748
|
+
|
|
734
749
|
pi.on("session_start", (_event, ctx) => {
|
|
750
|
+
ensureGrok47(ctx);
|
|
735
751
|
invalidateContextUsage();
|
|
736
752
|
invalidateSessionName();
|
|
737
753
|
multiproviderRefreshCtx = ctx;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@monotykamary/pi-better-grok",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.4",
|
|
4
4
|
"description": "Improve Grok/xAI in pi with fast mode, subscription usage stats, banked reset redemption, multiprovider pools, footer polish, and settings — mirroring pi-better-openai.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"footer",
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
"typecheck": "tsc --noEmit"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
|
-
"@earendil-works/pi-coding-agent": "0.
|
|
50
|
-
"@earendil-works/pi-tui": "0.
|
|
49
|
+
"@earendil-works/pi-coding-agent": "0.86.0",
|
|
50
|
+
"@earendil-works/pi-tui": "0.86.0",
|
|
51
51
|
"@types/node": "~22.19.0",
|
|
52
52
|
"oxfmt": "^0.47.0",
|
|
53
53
|
"oxlint": "^1.62.0",
|
|
@@ -59,8 +59,8 @@
|
|
|
59
59
|
"@earendil-works/pi-tui": "*"
|
|
60
60
|
},
|
|
61
61
|
"overrides": {
|
|
62
|
-
"@earendil-works/pi-agent-core": "0.
|
|
63
|
-
"@earendil-works/pi-ai": "0.
|
|
62
|
+
"@earendil-works/pi-agent-core": "0.86.0",
|
|
63
|
+
"@earendil-works/pi-ai": "0.86.0",
|
|
64
64
|
"brace-expansion": "5.0.9",
|
|
65
65
|
"nanoid": "3.3.18",
|
|
66
66
|
"postcss": "8.5.25",
|
package/src/config.ts
CHANGED
|
@@ -8,10 +8,13 @@ export const FOOTER_MODES = ["replace", "status", "off"] as const;
|
|
|
8
8
|
export const FAST_EFFORTS = ["low", "medium", "high"] as const;
|
|
9
9
|
|
|
10
10
|
export const DEFAULT_SUPPORTED_MODELS = [
|
|
11
|
+
"xai/grok-4.7",
|
|
11
12
|
"xai/grok-4.6",
|
|
12
13
|
"xai/grok-4.5",
|
|
14
|
+
"xai-oauth/grok-4.7",
|
|
13
15
|
"xai-oauth/grok-4.6",
|
|
14
16
|
"xai-oauth/grok-4.5",
|
|
17
|
+
"grok-build/grok-4.7",
|
|
15
18
|
"grok-build/grok-4.6",
|
|
16
19
|
"grok-build/grok-4.5",
|
|
17
20
|
] as const;
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import type { ProviderModelConfig } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
|
|
3
|
+
export const GROK_47_ID = "grok-4.7";
|
|
4
|
+
export const GROK_47_NAME = "Grok 4.7";
|
|
5
|
+
|
|
6
|
+
/** Providers that share Grok model ids and should pick up 4.7 until pi-core ships it. */
|
|
7
|
+
export const GROK_CUSTOM_MODEL_PROVIDERS = ["xai", "xai-oauth", "xai-auth", "grok-build"] as const;
|
|
8
|
+
|
|
9
|
+
const GROK_47_LONG_CONTEXT_TIER = {
|
|
10
|
+
inputTokensAbove: 200_000,
|
|
11
|
+
input: 4,
|
|
12
|
+
output: 12,
|
|
13
|
+
cacheRead: 1,
|
|
14
|
+
cacheWrite: 0,
|
|
15
|
+
} as const;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Native xAI Grok 4.7, cloned from pi-core's grok-4.6 catalog plus the public
|
|
19
|
+
* 4.7 card: 500k context, $2/$6 per 1M, cache read $0.50, 2x rates above 200k,
|
|
20
|
+
* reasoning efforts low/medium/high/xhigh. Used only when a sibling template exists.
|
|
21
|
+
*/
|
|
22
|
+
export const GROK_47_FALLBACK: ProviderModelConfig = {
|
|
23
|
+
id: GROK_47_ID,
|
|
24
|
+
name: GROK_47_NAME,
|
|
25
|
+
api: "openai-responses",
|
|
26
|
+
baseUrl: "https://api.x.ai/v1",
|
|
27
|
+
reasoning: true,
|
|
28
|
+
thinkingLevelMap: {
|
|
29
|
+
off: null,
|
|
30
|
+
minimal: null,
|
|
31
|
+
low: "low",
|
|
32
|
+
medium: "medium",
|
|
33
|
+
high: "high",
|
|
34
|
+
xhigh: "xhigh",
|
|
35
|
+
max: null,
|
|
36
|
+
},
|
|
37
|
+
input: ["text", "image"],
|
|
38
|
+
cost: {
|
|
39
|
+
input: 2,
|
|
40
|
+
output: 6,
|
|
41
|
+
cacheRead: 0.5,
|
|
42
|
+
cacheWrite: 0,
|
|
43
|
+
tiers: [{ ...GROK_47_LONG_CONTEXT_TIER }],
|
|
44
|
+
},
|
|
45
|
+
contextWindow: 500_000,
|
|
46
|
+
maxTokens: 500_000,
|
|
47
|
+
compat: { supportsLongCacheRetention: false },
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/** Structural catalog slice; avoids a hard pi-ai import from this package. */
|
|
51
|
+
export type CatalogModel = {
|
|
52
|
+
id: string;
|
|
53
|
+
name: string;
|
|
54
|
+
api?: ProviderModelConfig["api"];
|
|
55
|
+
provider: string;
|
|
56
|
+
baseUrl?: string;
|
|
57
|
+
reasoning: boolean;
|
|
58
|
+
thinkingLevelMap?: ProviderModelConfig["thinkingLevelMap"];
|
|
59
|
+
input: ProviderModelConfig["input"];
|
|
60
|
+
cost: ProviderModelConfig["cost"];
|
|
61
|
+
promptCache?: ProviderModelConfig["promptCache"];
|
|
62
|
+
contextWindow: number;
|
|
63
|
+
maxTokens: number;
|
|
64
|
+
headers?: Record<string, string>;
|
|
65
|
+
compat?: ProviderModelConfig["compat"];
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export function catalogModelToProviderConfig(model: CatalogModel): ProviderModelConfig {
|
|
69
|
+
return {
|
|
70
|
+
id: model.id,
|
|
71
|
+
name: model.name,
|
|
72
|
+
api: model.api,
|
|
73
|
+
baseUrl: model.baseUrl,
|
|
74
|
+
reasoning: model.reasoning,
|
|
75
|
+
thinkingLevelMap: model.thinkingLevelMap,
|
|
76
|
+
input: model.input,
|
|
77
|
+
cost: model.cost,
|
|
78
|
+
promptCache: model.promptCache,
|
|
79
|
+
contextWindow: model.contextWindow,
|
|
80
|
+
maxTokens: model.maxTokens,
|
|
81
|
+
headers: model.headers,
|
|
82
|
+
compat: model.compat,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function grok47FromTemplate(template: CatalogModel | undefined): ProviderModelConfig {
|
|
87
|
+
if (!template) {
|
|
88
|
+
return {
|
|
89
|
+
...GROK_47_FALLBACK,
|
|
90
|
+
cost: { ...GROK_47_FALLBACK.cost, tiers: [{ ...GROK_47_LONG_CONTEXT_TIER }] },
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
const thinkingLevelMap = {
|
|
94
|
+
...template.thinkingLevelMap,
|
|
95
|
+
low: "low",
|
|
96
|
+
medium: "medium",
|
|
97
|
+
high: "high",
|
|
98
|
+
xhigh: "xhigh",
|
|
99
|
+
};
|
|
100
|
+
return {
|
|
101
|
+
...catalogModelToProviderConfig(template),
|
|
102
|
+
id: GROK_47_ID,
|
|
103
|
+
name: GROK_47_NAME,
|
|
104
|
+
reasoning: true,
|
|
105
|
+
input: ["text", "image"],
|
|
106
|
+
contextWindow: Math.max(template.contextWindow, 500_000),
|
|
107
|
+
maxTokens: Math.max(template.maxTokens, 500_000),
|
|
108
|
+
thinkingLevelMap,
|
|
109
|
+
cost: {
|
|
110
|
+
...template.cost,
|
|
111
|
+
input: 2,
|
|
112
|
+
output: 6,
|
|
113
|
+
cacheRead: template.cost.cacheRead || 0.5,
|
|
114
|
+
cacheWrite: template.cost.cacheWrite ?? 0,
|
|
115
|
+
tiers: template.cost.tiers ?? [{ ...GROK_47_LONG_CONTEXT_TIER }],
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Extension registerProvider models replace that provider's catalog.
|
|
122
|
+
* Return the existing models plus grok-4.7, or undefined when 4.7 is already present
|
|
123
|
+
* or the provider has nothing to layer onto.
|
|
124
|
+
*/
|
|
125
|
+
export function upsertGrok47(existing: readonly CatalogModel[]): ProviderModelConfig[] | undefined {
|
|
126
|
+
if (existing.length === 0) return undefined;
|
|
127
|
+
if (existing.some((model) => model.id === GROK_47_ID)) return undefined;
|
|
128
|
+
const template =
|
|
129
|
+
existing.find((model) => model.id === "grok-4.6") ??
|
|
130
|
+
existing.find((model) => model.id === "grok-4.5") ??
|
|
131
|
+
existing[0];
|
|
132
|
+
return [...existing.map(catalogModelToProviderConfig), grok47FromTemplate(template)];
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export type Grok47Registration = { provider: string; models: ProviderModelConfig[] };
|
|
136
|
+
|
|
137
|
+
export function grok47Registrations(all: readonly CatalogModel[]): Grok47Registration[] {
|
|
138
|
+
const byProvider = new Map<string, CatalogModel[]>();
|
|
139
|
+
for (const model of all) {
|
|
140
|
+
const list = byProvider.get(model.provider) ?? [];
|
|
141
|
+
list.push(model);
|
|
142
|
+
byProvider.set(model.provider, list);
|
|
143
|
+
}
|
|
144
|
+
const registrations: Grok47Registration[] = [];
|
|
145
|
+
for (const provider of GROK_CUSTOM_MODEL_PROVIDERS) {
|
|
146
|
+
const models = upsertGrok47(byProvider.get(provider) ?? []);
|
|
147
|
+
if (models) registrations.push({ provider, models });
|
|
148
|
+
}
|
|
149
|
+
return registrations;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export function registerGrok47OnProviders(
|
|
153
|
+
registerProvider: (name: string, config: { models: ProviderModelConfig[] }) => void,
|
|
154
|
+
all: readonly CatalogModel[],
|
|
155
|
+
): string[] {
|
|
156
|
+
const registered: string[] = [];
|
|
157
|
+
for (const entry of grok47Registrations(all)) {
|
|
158
|
+
registerProvider(entry.provider, { models: entry.models });
|
|
159
|
+
registered.push(entry.provider);
|
|
160
|
+
}
|
|
161
|
+
return registered;
|
|
162
|
+
}
|