@eiei114/pi-sub-core 1.5.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/CHANGELOG.md +190 -0
- package/README.md +178 -0
- package/index.ts +540 -0
- package/package.json +35 -0
- package/src/cache.ts +546 -0
- package/src/config.ts +35 -0
- package/src/dependencies.ts +37 -0
- package/src/errors.ts +71 -0
- package/src/paths.ts +55 -0
- package/src/provider.ts +66 -0
- package/src/providers/detection.ts +51 -0
- package/src/providers/impl/anthropic.ts +174 -0
- package/src/providers/impl/antigravity.ts +226 -0
- package/src/providers/impl/codex.ts +186 -0
- package/src/providers/impl/copilot.ts +176 -0
- package/src/providers/impl/gemini.ts +130 -0
- package/src/providers/impl/kiro.ts +92 -0
- package/src/providers/impl/zai.ts +120 -0
- package/src/providers/index.ts +5 -0
- package/src/providers/metadata.ts +16 -0
- package/src/providers/registry.ts +54 -0
- package/src/providers/settings.ts +109 -0
- package/src/providers/status.ts +25 -0
- package/src/settings/behavior.ts +58 -0
- package/src/settings/menu.ts +83 -0
- package/src/settings/tools.ts +38 -0
- package/src/settings/ui.ts +450 -0
- package/src/settings-types.ts +95 -0
- package/src/settings-ui.ts +1 -0
- package/src/settings.ts +137 -0
- package/src/status.ts +245 -0
- package/src/storage/lock.ts +150 -0
- package/src/storage.ts +61 -0
- package/src/types.ts +33 -0
- package/src/ui/keybindings.ts +92 -0
- package/src/ui/settings-list.ts +290 -0
- package/src/usage/controller.ts +250 -0
- package/src/usage/fetch.ts +215 -0
- package/src/usage/types.ts +5 -0
- package/src/utils.ts +158 -0
- package/test/all.test.ts +9 -0
- package/test/cache.test.ts +157 -0
- package/test/controller.test.ts +101 -0
- package/test/detection.test.ts +24 -0
- package/test/extension.test.ts +233 -0
- package/test/helpers.ts +48 -0
- package/test/keybindings.test.ts +59 -0
- package/test/lock.test.ts +49 -0
- package/test/prioritize.test.ts +81 -0
- package/test/providers.test.ts +385 -0
- package/test/status.test.ts +70 -0
- package/tsconfig.json +5 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider metadata shared across the core.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export {
|
|
6
|
+
PROVIDERS,
|
|
7
|
+
PROVIDER_METADATA,
|
|
8
|
+
PROVIDER_DISPLAY_NAMES,
|
|
9
|
+
} from "@eiei114/pi-sub-shared";
|
|
10
|
+
|
|
11
|
+
export type {
|
|
12
|
+
ProviderName,
|
|
13
|
+
ProviderMetadata,
|
|
14
|
+
ProviderStatusConfig,
|
|
15
|
+
ProviderDetectionConfig,
|
|
16
|
+
} from "@eiei114/pi-sub-shared";
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider registry - exports all providers
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export { AnthropicProvider } from "./impl/anthropic.js";
|
|
6
|
+
export { CopilotProvider } from "./impl/copilot.js";
|
|
7
|
+
export { GeminiProvider } from "./impl/gemini.js";
|
|
8
|
+
export { AntigravityProvider } from "./impl/antigravity.js";
|
|
9
|
+
export { CodexProvider } from "./impl/codex.js";
|
|
10
|
+
export { KiroProvider } from "./impl/kiro.js";
|
|
11
|
+
export { ZaiProvider } from "./impl/zai.js";
|
|
12
|
+
|
|
13
|
+
import type { Dependencies, ProviderName } from "../types.js";
|
|
14
|
+
import type { UsageProvider } from "../provider.js";
|
|
15
|
+
import { PROVIDERS } from "./metadata.js";
|
|
16
|
+
import { AnthropicProvider } from "./impl/anthropic.js";
|
|
17
|
+
import { CopilotProvider } from "./impl/copilot.js";
|
|
18
|
+
import { GeminiProvider } from "./impl/gemini.js";
|
|
19
|
+
import { AntigravityProvider } from "./impl/antigravity.js";
|
|
20
|
+
import { CodexProvider } from "./impl/codex.js";
|
|
21
|
+
import { KiroProvider } from "./impl/kiro.js";
|
|
22
|
+
import { ZaiProvider } from "./impl/zai.js";
|
|
23
|
+
|
|
24
|
+
const PROVIDER_FACTORIES: Record<ProviderName, () => UsageProvider> = {
|
|
25
|
+
anthropic: () => new AnthropicProvider(),
|
|
26
|
+
copilot: () => new CopilotProvider(),
|
|
27
|
+
gemini: () => new GeminiProvider(),
|
|
28
|
+
antigravity: () => new AntigravityProvider(),
|
|
29
|
+
codex: () => new CodexProvider(),
|
|
30
|
+
kiro: () => new KiroProvider(),
|
|
31
|
+
zai: () => new ZaiProvider(),
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Create a provider instance by name
|
|
36
|
+
*/
|
|
37
|
+
export function createProvider(name: ProviderName): UsageProvider {
|
|
38
|
+
return PROVIDER_FACTORIES[name]();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Get all provider instances
|
|
43
|
+
*/
|
|
44
|
+
export function getAllProviders(): UsageProvider[] {
|
|
45
|
+
return PROVIDERS.map((name) => PROVIDER_FACTORIES[name]());
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function hasProviderCredentials(name: ProviderName, deps: Dependencies): boolean {
|
|
49
|
+
const provider = createProvider(name);
|
|
50
|
+
if (provider.hasCredentials) {
|
|
51
|
+
return provider.hasCredentials(deps);
|
|
52
|
+
}
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider-specific settings helpers.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { SettingItem } from "@mariozechner/pi-tui";
|
|
6
|
+
import type { ProviderName } from "../types.js";
|
|
7
|
+
import type { Settings, CoreProviderSettings } from "../settings-types.js";
|
|
8
|
+
import { CUSTOM_OPTION } from "../ui/settings-list.js";
|
|
9
|
+
|
|
10
|
+
function buildBaseProviderItems(ps: CoreProviderSettings): SettingItem[] {
|
|
11
|
+
const enabledValue = ps.enabled === "auto" ? "auto" : ps.enabled === true || ps.enabled === "on" ? "on" : "off";
|
|
12
|
+
return [
|
|
13
|
+
{
|
|
14
|
+
id: "enabled",
|
|
15
|
+
label: "Enabled",
|
|
16
|
+
currentValue: enabledValue,
|
|
17
|
+
values: ["auto", "on", "off"],
|
|
18
|
+
description: "Auto enables if credentials are detected.",
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
id: "fetchStatus",
|
|
22
|
+
label: "Fetch Status",
|
|
23
|
+
currentValue: ps.fetchStatus ? "on" : "off",
|
|
24
|
+
values: ["on", "off"],
|
|
25
|
+
description: "Fetch status page indicator for this provider.",
|
|
26
|
+
},
|
|
27
|
+
];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function resolveEnabledValue(value: string): CoreProviderSettings["enabled"] {
|
|
31
|
+
if (value === "auto") return "auto";
|
|
32
|
+
return value === "on";
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function applyBaseProviderSetting(ps: CoreProviderSettings, id: string, value: string): boolean {
|
|
36
|
+
switch (id) {
|
|
37
|
+
case "enabled":
|
|
38
|
+
ps.enabled = resolveEnabledValue(value);
|
|
39
|
+
return true;
|
|
40
|
+
case "fetchStatus":
|
|
41
|
+
ps.fetchStatus = value === "on";
|
|
42
|
+
return true;
|
|
43
|
+
default:
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Build settings items for a specific provider.
|
|
50
|
+
*/
|
|
51
|
+
export function buildProviderSettingsItems(settings: Settings, provider: ProviderName): SettingItem[] {
|
|
52
|
+
const ps = settings.providers[provider];
|
|
53
|
+
const items = buildBaseProviderItems(ps);
|
|
54
|
+
|
|
55
|
+
if (provider === "anthropic") {
|
|
56
|
+
const currencySymbol = ps.extraUsageCurrencySymbol?.trim();
|
|
57
|
+
items.push(
|
|
58
|
+
{
|
|
59
|
+
id: "extraUsageCurrencySymbol",
|
|
60
|
+
label: "Extra Usage Currency Symbol",
|
|
61
|
+
currentValue: currencySymbol ? currencySymbol : "none",
|
|
62
|
+
values: ["none", CUSTOM_OPTION],
|
|
63
|
+
description: "Prefix symbol for Extra usage amounts.",
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
id: "extraUsageDecimalSeparator",
|
|
67
|
+
label: "Extra Usage Decimal Separator",
|
|
68
|
+
currentValue: ps.extraUsageDecimalSeparator === "," ? "," : ".",
|
|
69
|
+
values: [".", ","],
|
|
70
|
+
description: "Decimal separator for Extra usage amounts.",
|
|
71
|
+
},
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return items;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Apply a provider settings change in-place.
|
|
80
|
+
*/
|
|
81
|
+
export function applyProviderSettingsChange(
|
|
82
|
+
settings: Settings,
|
|
83
|
+
provider: ProviderName,
|
|
84
|
+
id: string,
|
|
85
|
+
value: string
|
|
86
|
+
): Settings {
|
|
87
|
+
const ps = settings.providers[provider];
|
|
88
|
+
if (applyBaseProviderSetting(ps, id, value)) {
|
|
89
|
+
return settings;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
switch (id) {
|
|
93
|
+
case "extraUsageCurrencySymbol":
|
|
94
|
+
if (value === CUSTOM_OPTION) {
|
|
95
|
+
return settings;
|
|
96
|
+
}
|
|
97
|
+
if (value === "none") {
|
|
98
|
+
delete ps.extraUsageCurrencySymbol;
|
|
99
|
+
return settings;
|
|
100
|
+
}
|
|
101
|
+
ps.extraUsageCurrencySymbol = value;
|
|
102
|
+
return settings;
|
|
103
|
+
case "extraUsageDecimalSeparator":
|
|
104
|
+
ps.extraUsageDecimalSeparator = value === "," ? "," : ".";
|
|
105
|
+
return settings;
|
|
106
|
+
default:
|
|
107
|
+
return settings;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider status handling helpers.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { Dependencies, ProviderName, ProviderStatus } from "../types.js";
|
|
6
|
+
import { fetchProviderStatus } from "../status.js";
|
|
7
|
+
import { PROVIDER_METADATA } from "./metadata.js";
|
|
8
|
+
|
|
9
|
+
export function providerHasStatus(
|
|
10
|
+
provider: ProviderName,
|
|
11
|
+
providerInstance?: { fetchStatus?: (deps: Dependencies) => Promise<ProviderStatus> }
|
|
12
|
+
): boolean {
|
|
13
|
+
return Boolean(providerInstance?.fetchStatus) || Boolean(PROVIDER_METADATA[provider]?.status);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export async function fetchProviderStatusWithFallback(
|
|
17
|
+
provider: ProviderName,
|
|
18
|
+
providerInstance: { fetchStatus?: (deps: Dependencies) => Promise<ProviderStatus> },
|
|
19
|
+
deps: Dependencies
|
|
20
|
+
): Promise<ProviderStatus> {
|
|
21
|
+
if (providerInstance.fetchStatus) {
|
|
22
|
+
return providerInstance.fetchStatus(deps);
|
|
23
|
+
}
|
|
24
|
+
return fetchProviderStatus(provider, deps);
|
|
25
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Behavior settings UI helpers.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { SettingItem } from "@mariozechner/pi-tui";
|
|
6
|
+
import type { BehaviorSettings } from "../settings-types.js";
|
|
7
|
+
import { CUSTOM_OPTION } from "../ui/settings-list.js";
|
|
8
|
+
|
|
9
|
+
export function buildRefreshItems(settings: BehaviorSettings): SettingItem[] {
|
|
10
|
+
return [
|
|
11
|
+
{
|
|
12
|
+
id: "refreshInterval",
|
|
13
|
+
label: "Auto-refresh Interval",
|
|
14
|
+
currentValue: settings.refreshInterval === 0 ? "off" : `${settings.refreshInterval}s`,
|
|
15
|
+
values: ["off", "15s", "30s", "60s", "120s", "300s", CUSTOM_OPTION],
|
|
16
|
+
description: "How often to refresh automatically.",
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
id: "minRefreshInterval",
|
|
20
|
+
label: "Minimum Refresh Interval",
|
|
21
|
+
currentValue: settings.minRefreshInterval === 0 ? "off" : `${settings.minRefreshInterval}s`,
|
|
22
|
+
values: ["off", "5s", "10s", "15s", "30s", "60s", "120s", CUSTOM_OPTION],
|
|
23
|
+
description: "Cap refreshes even when triggered each turn.",
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
id: "refreshOnTurnStart",
|
|
27
|
+
label: "Refresh on Turn Start",
|
|
28
|
+
currentValue: settings.refreshOnTurnStart ? "on" : "off",
|
|
29
|
+
values: ["on", "off"],
|
|
30
|
+
description: "Refresh when a new turn starts.",
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
id: "refreshOnToolResult",
|
|
34
|
+
label: "Refresh on Tool Result",
|
|
35
|
+
currentValue: settings.refreshOnToolResult ? "on" : "off",
|
|
36
|
+
values: ["on", "off"],
|
|
37
|
+
description: "Refresh after tool executions.",
|
|
38
|
+
},
|
|
39
|
+
];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function applyRefreshChange(settings: BehaviorSettings, id: string, value: string): BehaviorSettings {
|
|
43
|
+
switch (id) {
|
|
44
|
+
case "refreshInterval":
|
|
45
|
+
settings.refreshInterval = value === "off" ? 0 : parseInt(value, 10);
|
|
46
|
+
break;
|
|
47
|
+
case "minRefreshInterval":
|
|
48
|
+
settings.minRefreshInterval = value === "off" ? 0 : parseInt(value, 10);
|
|
49
|
+
break;
|
|
50
|
+
case "refreshOnTurnStart":
|
|
51
|
+
settings.refreshOnTurnStart = value === "on";
|
|
52
|
+
break;
|
|
53
|
+
case "refreshOnToolResult":
|
|
54
|
+
settings.refreshOnToolResult = value === "on";
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
return settings;
|
|
58
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Settings menu item builders.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { SelectItem } from "@mariozechner/pi-tui";
|
|
6
|
+
import type { Settings } from "../settings-types.js";
|
|
7
|
+
import type { ProviderName } from "../types.js";
|
|
8
|
+
import { PROVIDER_DISPLAY_NAMES } from "../providers/metadata.js";
|
|
9
|
+
|
|
10
|
+
export type TooltipSelectItem = SelectItem & { tooltip?: string };
|
|
11
|
+
|
|
12
|
+
export function buildMainMenuItems(settings: Settings): TooltipSelectItem[] {
|
|
13
|
+
const enabledCount = Object.values(settings.providers).filter((p) => p.enabled !== "off" && p.enabled !== false).length;
|
|
14
|
+
const totalCount = Object.keys(settings.providers).length;
|
|
15
|
+
const toolEnabledCount = [settings.tools.usageTool, settings.tools.allUsageTool].filter(Boolean).length;
|
|
16
|
+
const toolTotalCount = 2;
|
|
17
|
+
|
|
18
|
+
return [
|
|
19
|
+
{
|
|
20
|
+
value: "providers",
|
|
21
|
+
label: "Provider Settings",
|
|
22
|
+
description: `${enabledCount}/${totalCount} enabled`,
|
|
23
|
+
tooltip: "Enable providers, toggle status fetch, and adjust provider settings.",
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
value: "behavior",
|
|
27
|
+
label: "Usage Refresh Settings",
|
|
28
|
+
description: `refresh ${settings.behavior.refreshInterval}s`,
|
|
29
|
+
tooltip: "Control usage refresh interval and triggers.",
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
value: "status-refresh",
|
|
33
|
+
label: "Status Refresh Settings",
|
|
34
|
+
description: `refresh ${settings.statusRefresh.refreshInterval}s`,
|
|
35
|
+
tooltip: "Control status refresh interval and triggers.",
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
value: "tools",
|
|
39
|
+
label: "Tool Settings",
|
|
40
|
+
description: `${toolEnabledCount}/${toolTotalCount} enabled`,
|
|
41
|
+
tooltip: "Enable sub-core tools (requires /reload to take effect).",
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
value: "provider-order",
|
|
45
|
+
label: "Provider Order",
|
|
46
|
+
description: settings.providerOrder.slice(0, 3).join(", ") + "...",
|
|
47
|
+
tooltip: "Reorder providers for cycling and auto-selection.",
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
value: "reset",
|
|
51
|
+
label: "Reset to Defaults",
|
|
52
|
+
description: "restore all settings",
|
|
53
|
+
tooltip: "Restore all sub-core settings to defaults.",
|
|
54
|
+
},
|
|
55
|
+
];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function buildProviderListItems(settings: Settings): TooltipSelectItem[] {
|
|
59
|
+
return settings.providerOrder.map((provider) => {
|
|
60
|
+
const ps = settings.providers[provider];
|
|
61
|
+
const enabledValue = ps.enabled === "auto" ? "auto" : ps.enabled === true || ps.enabled === "on" ? "on" : "off";
|
|
62
|
+
const statusIcon = ps.fetchStatus ? ", status fetch on" : "";
|
|
63
|
+
return {
|
|
64
|
+
value: `provider-${provider}`,
|
|
65
|
+
label: PROVIDER_DISPLAY_NAMES[provider],
|
|
66
|
+
description: `enabled ${enabledValue}${statusIcon}`,
|
|
67
|
+
tooltip: `Enable ${PROVIDER_DISPLAY_NAMES[provider]} and configure status fetching.`,
|
|
68
|
+
};
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function buildProviderOrderItems(settings: Settings): TooltipSelectItem[] {
|
|
73
|
+
const activeProviders = settings.providerOrder.filter((provider) => {
|
|
74
|
+
const enabled = settings.providers[provider].enabled;
|
|
75
|
+
return enabled !== "off" && enabled !== false;
|
|
76
|
+
});
|
|
77
|
+
return activeProviders.map((provider, index) => ({
|
|
78
|
+
value: provider,
|
|
79
|
+
label: `${index + 1}. ${PROVIDER_DISPLAY_NAMES[provider]}`,
|
|
80
|
+
tooltip: "Reorder enabled providers (Space to toggle move mode).",
|
|
81
|
+
}));
|
|
82
|
+
}
|
|
83
|
+
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool settings UI helpers.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { SettingItem } from "@mariozechner/pi-tui";
|
|
6
|
+
import type { Settings, ToolSettings } from "../settings-types.js";
|
|
7
|
+
|
|
8
|
+
export function buildToolItems(settings: ToolSettings): SettingItem[] {
|
|
9
|
+
return [
|
|
10
|
+
{
|
|
11
|
+
id: "usageTool",
|
|
12
|
+
label: "Usage Tool",
|
|
13
|
+
currentValue: settings.usageTool ? "on" : "off",
|
|
14
|
+
values: ["on", "off"],
|
|
15
|
+
description: "Expose sub_get_usage/get_current_usage (requires /reload).",
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
id: "allUsageTool",
|
|
19
|
+
label: "All Usage Tool",
|
|
20
|
+
currentValue: settings.allUsageTool ? "on" : "off",
|
|
21
|
+
values: ["on", "off"],
|
|
22
|
+
description: "Expose sub_get_all_usage/get_all_usage (requires /reload).",
|
|
23
|
+
},
|
|
24
|
+
];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function applyToolChange(settings: Settings, id: string, value: string): Settings {
|
|
28
|
+
const enabled = value === "on";
|
|
29
|
+
switch (id) {
|
|
30
|
+
case "usageTool":
|
|
31
|
+
settings.tools.usageTool = enabled;
|
|
32
|
+
break;
|
|
33
|
+
case "allUsageTool":
|
|
34
|
+
settings.tools.allUsageTool = enabled;
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
return settings;
|
|
38
|
+
}
|