@marckrenn/pi-sub-bar 1.0.2 → 1.0.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/CHANGELOG.md +43 -0
- package/README.md +9 -6
- package/index.ts +219 -23
- package/node_modules/@marckrenn/pi-sub-core/CHANGELOG.md +68 -0
- package/node_modules/@marckrenn/pi-sub-core/README.md +178 -0
- package/node_modules/@marckrenn/pi-sub-core/index.ts +395 -0
- package/node_modules/@marckrenn/pi-sub-core/package.json +35 -0
- package/node_modules/@marckrenn/pi-sub-core/src/cache.ts +487 -0
- package/node_modules/@marckrenn/pi-sub-core/src/config.ts +35 -0
- package/node_modules/@marckrenn/pi-sub-core/src/dependencies.ts +37 -0
- package/node_modules/@marckrenn/pi-sub-core/src/errors.ts +71 -0
- package/node_modules/@marckrenn/pi-sub-core/src/paths.ts +55 -0
- package/node_modules/@marckrenn/pi-sub-core/src/provider.ts +66 -0
- package/node_modules/@marckrenn/pi-sub-core/src/providers/detection.ts +51 -0
- package/node_modules/@marckrenn/pi-sub-core/src/providers/impl/anthropic.ts +170 -0
- package/node_modules/@marckrenn/pi-sub-core/src/providers/impl/antigravity.ts +205 -0
- package/node_modules/@marckrenn/pi-sub-core/src/providers/impl/codex.ts +139 -0
- package/node_modules/@marckrenn/pi-sub-core/src/providers/impl/copilot.ts +172 -0
- package/node_modules/@marckrenn/pi-sub-core/src/providers/impl/gemini.ts +121 -0
- package/node_modules/@marckrenn/pi-sub-core/src/providers/impl/kiro.ts +92 -0
- package/node_modules/@marckrenn/pi-sub-core/src/providers/impl/zai.ts +117 -0
- package/node_modules/@marckrenn/pi-sub-core/src/providers/index.ts +5 -0
- package/node_modules/@marckrenn/pi-sub-core/src/providers/metadata.ts +16 -0
- package/node_modules/@marckrenn/pi-sub-core/src/providers/registry.ts +54 -0
- package/node_modules/@marckrenn/pi-sub-core/src/providers/settings.ts +109 -0
- package/node_modules/@marckrenn/pi-sub-core/src/providers/status.ts +25 -0
- package/node_modules/@marckrenn/pi-sub-core/src/settings/behavior.ts +58 -0
- package/node_modules/@marckrenn/pi-sub-core/src/settings/menu.ts +83 -0
- package/node_modules/@marckrenn/pi-sub-core/src/settings/tools.ts +38 -0
- package/node_modules/@marckrenn/pi-sub-core/src/settings/ui.ts +450 -0
- package/node_modules/@marckrenn/pi-sub-core/src/settings-types.ts +95 -0
- package/node_modules/@marckrenn/pi-sub-core/src/settings-ui.ts +1 -0
- package/node_modules/@marckrenn/pi-sub-core/src/settings.ts +137 -0
- package/node_modules/@marckrenn/pi-sub-core/src/status.ts +123 -0
- package/node_modules/@marckrenn/pi-sub-core/src/storage/lock.ts +60 -0
- package/node_modules/@marckrenn/pi-sub-core/src/storage.ts +61 -0
- package/node_modules/@marckrenn/pi-sub-core/src/types.ts +33 -0
- package/node_modules/@marckrenn/pi-sub-core/src/ui/settings-list.ts +290 -0
- package/node_modules/@marckrenn/pi-sub-core/src/usage/controller.ts +235 -0
- package/node_modules/@marckrenn/pi-sub-core/src/usage/fetch.ts +215 -0
- package/node_modules/@marckrenn/pi-sub-core/src/usage/types.ts +5 -0
- package/node_modules/@marckrenn/pi-sub-core/src/utils.ts +122 -0
- package/node_modules/@marckrenn/pi-sub-core/test/all.test.ts +5 -0
- package/node_modules/@marckrenn/pi-sub-core/test/cache.test.ts +96 -0
- package/node_modules/@marckrenn/pi-sub-core/test/controller.test.ts +101 -0
- package/node_modules/@marckrenn/pi-sub-core/test/detection.test.ts +24 -0
- package/node_modules/@marckrenn/pi-sub-core/test/helpers.ts +48 -0
- package/node_modules/@marckrenn/pi-sub-core/test/lock.test.ts +42 -0
- package/node_modules/@marckrenn/pi-sub-core/test/providers.test.ts +222 -0
- package/node_modules/@marckrenn/pi-sub-core/tsconfig.json +5 -0
- package/node_modules/@marckrenn/pi-sub-shared/README.md +58 -0
- package/node_modules/@marckrenn/pi-sub-shared/index.ts +212 -0
- package/node_modules/@marckrenn/pi-sub-shared/package.json +23 -0
- package/package.json +5 -4
- package/src/paths.ts +7 -0
- package/src/settings/display.ts +20 -6
- package/src/settings/menu.ts +17 -11
- package/src/settings/themes.ts +33 -2
- package/src/settings/ui.ts +238 -22
- package/src/settings-types.ts +19 -5
- package/src/settings.ts +30 -18
- package/src/share.ts +24 -5
- package/test/settings.test.ts +12 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,48 @@
|
|
|
1
1
|
# @marckrenn/pi-sub-bar
|
|
2
2
|
|
|
3
|
+
## 1.0.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#28](https://github.com/marckrenn/pi-sub/pull/28) [`2e35657`](https://github.com/marckrenn/pi-sub/commit/2e3565776a98ec133537fe0bacbc099cd4afadbe) Thanks [@marckrenn](https://github.com/marckrenn)! - Default Anthropic “Show Extra Window” provider setting to off.
|
|
8
|
+
|
|
9
|
+
- [#29](https://github.com/marckrenn/pi-sub/pull/29) [`7e6b7a0`](https://github.com/marckrenn/pi-sub/commit/7e6b7a08d69cf1cd456d2add406ec89c5c86f5df) Thanks [@marckrenn](https://github.com/marckrenn)! - Split display padding into left/right settings and migrate legacy paddingX values to both sides.
|
|
10
|
+
|
|
11
|
+
- [#22](https://github.com/marckrenn/pi-sub/pull/22) [`3e5a026`](https://github.com/marckrenn/pi-sub/commit/3e5a026ea3dc113561ff32466a8aa03b91c6d876) Thanks [@marckrenn](https://github.com/marckrenn)! - Store sub-core and sub-bar settings in agent-level JSON files so updates no longer overwrite user configuration. Legacy extension `settings.json` files are migrated into the new files and removed after a successful migration.
|
|
12
|
+
|
|
13
|
+
Manual migration (if you want to do it yourself before updating):
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
cp ~/.pi/agent/extensions/sub-core/settings.json ~/.pi/agent/pi-sub-core-settings.json
|
|
17
|
+
cp ~/.pi/agent/extensions/sub-bar/settings.json ~/.pi/agent/pi-sub-bar-settings.json
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Existing users should move legacy settings from the extension folders to:
|
|
21
|
+
- `~/.pi/agent/pi-sub-core-settings.json`
|
|
22
|
+
- `~/.pi/agent/pi-sub-bar-settings.json`
|
|
23
|
+
|
|
24
|
+
- [#23](https://github.com/marckrenn/pi-sub/pull/23) [`9c324fc`](https://github.com/marckrenn/pi-sub/commit/9c324fc7daae2a874816f600ac1ea422f3799dd2) Thanks [@marckrenn](https://github.com/marckrenn)! - Auto-post theme share strings when saving, add a “Share theme” menu entry, allow share strings without a name when importing, and post raw share strings (without the `/sub-bar:import` prefix).
|
|
25
|
+
|
|
26
|
+
- [#25](https://github.com/marckrenn/pi-sub/pull/25) [`ab97c8f`](https://github.com/marckrenn/pi-sub/commit/ab97c8f13c567c32581bb82fe5b0406b3f2464ca) Thanks [@marckrenn](https://github.com/marckrenn)! - Refine the theme menu ordering/labels and add rename support for saved themes in the Manage & Load flow.
|
|
27
|
+
|
|
28
|
+
- [#27](https://github.com/marckrenn/pi-sub/pull/27) [`549c6fe`](https://github.com/marckrenn/pi-sub/commit/549c6fe3eb57374a54bfc69ad70c91862250a186) Thanks [@marckrenn](https://github.com/marckrenn)! - Move Themes to the root settings menu, rename Display Settings to Adv. Display Settings, and rename “Manage & Load themes” to “Load & Manage themes”.
|
|
29
|
+
|
|
30
|
+
- [#26](https://github.com/marckrenn/pi-sub/pull/26) [`af28d98`](https://github.com/marckrenn/pi-sub/commit/af28d9820f80bc1d045783644afbcc4d7cd114f1) Thanks [@marckrenn](https://github.com/marckrenn)! - Prompt to upload theme share strings as secret GitHub gists and post the gist URL when accepted.
|
|
31
|
+
|
|
32
|
+
- Updated dependencies [[`af0828a`](https://github.com/marckrenn/pi-sub/commit/af0828a8d2e529497a1acff95e388a0a3eabb90e), [`3e5a026`](https://github.com/marckrenn/pi-sub/commit/3e5a026ea3dc113561ff32466a8aa03b91c6d876), [`a6c0d33`](https://github.com/marckrenn/pi-sub/commit/a6c0d33c8d19d2876a4a8a1a0a69302a3c63f5e8), [`7da1e08`](https://github.com/marckrenn/pi-sub/commit/7da1e082e634f4e4dee2560b4d490527d1543ade), [`1f5e451`](https://github.com/marckrenn/pi-sub/commit/1f5e45173b9868b0d6645ae35a084142a0ac56a5), [`35eb185`](https://github.com/marckrenn/pi-sub/commit/35eb18590f369db4cda931b8e11099d0f3ddb4ec)]:
|
|
33
|
+
- @marckrenn/pi-sub-core@1.0.4
|
|
34
|
+
- @marckrenn/pi-sub-shared@1.0.4
|
|
35
|
+
|
|
36
|
+
## 1.0.3
|
|
37
|
+
|
|
38
|
+
### Patch Changes
|
|
39
|
+
|
|
40
|
+
- [`6fa2736`](https://github.com/marckrenn/pi-sub/commit/6fa27363573f34c38a372a6d7b8b74e756716724) Thanks [@marckrenn](https://github.com/marckrenn)! - Update extension tool execute signature order for compatibility with latest Pi API.
|
|
41
|
+
|
|
42
|
+
- Updated dependencies [[`6fa2736`](https://github.com/marckrenn/pi-sub/commit/6fa27363573f34c38a372a6d7b8b74e756716724)]:
|
|
43
|
+
- @marckrenn/pi-sub-core@1.0.3
|
|
44
|
+
- @marckrenn/pi-sub-shared@1.0.3
|
|
45
|
+
|
|
3
46
|
## 1.0.2
|
|
4
47
|
|
|
5
48
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -51,7 +51,7 @@ https://github.com/user-attachments/assets/d61d82f6-afd0-45fc-82f3-69910543aa7a
|
|
|
51
51
|
|
|
52
52
|
## Installation
|
|
53
53
|
|
|
54
|
-
Install via the pi package manager (recommended). `sub-bar` bundles `sub-core`, so you only need to install
|
|
54
|
+
Install via the pi package manager (recommended). `sub-bar` bundles `sub-core`, so you only need to install sub-bar:
|
|
55
55
|
|
|
56
56
|
```bash
|
|
57
57
|
pi install npm:@marckrenn/pi-sub-bar
|
|
@@ -63,6 +63,8 @@ Use `-l` to install into project settings instead of global:
|
|
|
63
63
|
pi install -l npm:@marckrenn/pi-sub-bar
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
+
If you previously installed `sub-core` separately, remove it from `~/.pi/agent/extensions` or `~/.pi/agent/settings.json` to avoid duplicate core instances.
|
|
67
|
+
|
|
66
68
|
Manual install (local development):
|
|
67
69
|
|
|
68
70
|
```bash
|
|
@@ -73,9 +75,9 @@ npm install
|
|
|
73
75
|
ln -s /path/to/pi-sub/packages/sub-bar ~/.pi/agent/extensions/sub-bar
|
|
74
76
|
```
|
|
75
77
|
|
|
76
|
-
|
|
78
|
+
For local development, also ensure sub-core is available (either link it separately or link it into `packages/sub-bar/node_modules`).
|
|
77
79
|
|
|
78
|
-
Alternative (no symlink): add
|
|
80
|
+
Alternative (no symlink): add sub-bar to `~/.pi/agent/settings.json`:
|
|
79
81
|
|
|
80
82
|
```json
|
|
81
83
|
{
|
|
@@ -96,7 +98,7 @@ The extension loads automatically. Use:
|
|
|
96
98
|
- `Ctrl+Alt+R` - Toggle reset timer format (relative vs datetime)
|
|
97
99
|
|
|
98
100
|
**Caching:**
|
|
99
|
-
- Handled by sub-core at
|
|
101
|
+
- Handled by sub-core at `~/.pi/agent/cache/sub-core/cache.json`
|
|
100
102
|
- Cache TTL matches your auto-refresh interval setting
|
|
101
103
|
- Lock file prevents race conditions between multiple pi windows
|
|
102
104
|
|
|
@@ -108,9 +110,9 @@ The extension loads automatically. Use:
|
|
|
108
110
|
|
|
109
111
|
## Settings
|
|
110
112
|
|
|
111
|
-
Display and provider UI settings are
|
|
113
|
+
Display and provider UI settings are stored in `~/.pi/agent/pi-sub-bar-settings.json` (migrated from the legacy extension `settings.json` when present; the legacy file is removed after a successful migration). Core settings are managed by sub-core, and the sub-bar settings menu includes a shortcut that points you to `sub-core:settings` for additional options.
|
|
112
114
|
|
|
113
|
-
**Settings migrations:** settings are merged with defaults on load, but renames/removals are not migrated automatically. When adding new settings or changing schema, update the defaults/merge logic and provide a migration (or instruct users to reset `settings.json`).
|
|
115
|
+
**Settings migrations:** settings are merged with defaults on load, but renames/removals are not migrated automatically. When adding new settings or changing schema, update the defaults/merge logic and provide a migration (or instruct users to reset `pi-sub-bar-settings.json`).
|
|
114
116
|
|
|
115
117
|
### Provider UI Settings
|
|
116
118
|
|
|
@@ -142,6 +144,7 @@ Credentials are loaded by sub-core from:
|
|
|
142
144
|
Pi packages use a `pi` field in `package.json` plus the `pi-package` keyword for discoverability. This repo already declares `pi.extensions`, so you can install via:
|
|
143
145
|
|
|
144
146
|
```bash
|
|
147
|
+
pi install npm:@marckrenn/pi-sub-core
|
|
145
148
|
pi install npm:@marckrenn/pi-sub-bar
|
|
146
149
|
```
|
|
147
150
|
|
package/index.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import type { ExtensionAPI, ExtensionContext, Theme, ThemeColor } from "@mariozechner/pi-coding-agent";
|
|
8
8
|
import { Container, Input, SelectList, Spacer, Text, truncateToWidth, wrapTextWithAnsi, visibleWidth } from "@mariozechner/pi-tui";
|
|
9
9
|
import * as fs from "node:fs";
|
|
10
|
-
import { homedir } from "node:os";
|
|
10
|
+
import { homedir, tmpdir } from "node:os";
|
|
11
11
|
import { join } from "node:path";
|
|
12
12
|
import type { ProviderName, ProviderUsageEntry, SubCoreAllState, SubCoreState, UsageSnapshot } from "./src/types.js";
|
|
13
13
|
import type { Settings, BaseTextColor } from "./src/settings-types.js";
|
|
@@ -128,6 +128,59 @@ export default function createExtension(pi: ExtensionAPI) {
|
|
|
128
128
|
let settingsSnapshot = "";
|
|
129
129
|
let settingsMtimeMs = 0;
|
|
130
130
|
let settingsWatchStarted = false;
|
|
131
|
+
let subCoreBootstrapAttempted = false;
|
|
132
|
+
|
|
133
|
+
async function probeSubCore(timeoutMs = 200): Promise<boolean> {
|
|
134
|
+
return new Promise((resolve) => {
|
|
135
|
+
let resolved = false;
|
|
136
|
+
const timer = setTimeout(() => {
|
|
137
|
+
if (!resolved) {
|
|
138
|
+
resolved = true;
|
|
139
|
+
resolve(false);
|
|
140
|
+
}
|
|
141
|
+
}, timeoutMs);
|
|
142
|
+
|
|
143
|
+
const request: SubCoreRequest = {
|
|
144
|
+
type: "current",
|
|
145
|
+
reply: () => {
|
|
146
|
+
if (resolved) return;
|
|
147
|
+
resolved = true;
|
|
148
|
+
clearTimeout(timer);
|
|
149
|
+
resolve(true);
|
|
150
|
+
},
|
|
151
|
+
};
|
|
152
|
+
pi.events.emit("sub-core:request", request);
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
async function ensureSubCoreLoaded(): Promise<void> {
|
|
157
|
+
if (subCoreBootstrapAttempted) return;
|
|
158
|
+
subCoreBootstrapAttempted = true;
|
|
159
|
+
const hasCore = await probeSubCore();
|
|
160
|
+
if (hasCore) return;
|
|
161
|
+
try {
|
|
162
|
+
const bundledUrl = new URL("./node_modules/@marckrenn/pi-sub-core/index.ts", import.meta.url);
|
|
163
|
+
const module = await import(bundledUrl.toString());
|
|
164
|
+
const createCore = module.default as undefined | ((api: ExtensionAPI) => void | Promise<void>);
|
|
165
|
+
if (typeof createCore === "function") {
|
|
166
|
+
void createCore(pi);
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
} catch {
|
|
170
|
+
// Fall back to package resolution
|
|
171
|
+
}
|
|
172
|
+
try {
|
|
173
|
+
const module = await import("@marckrenn/pi-sub-core");
|
|
174
|
+
const createCore = module.default as undefined | ((api: ExtensionAPI) => void | Promise<void>);
|
|
175
|
+
if (typeof createCore === "function") {
|
|
176
|
+
void createCore(pi);
|
|
177
|
+
}
|
|
178
|
+
} catch (error) {
|
|
179
|
+
console.warn("Failed to auto-load sub-core:", error);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
void ensureSubCoreLoaded();
|
|
131
184
|
|
|
132
185
|
async function promptImportAction(ctx: ExtensionContext): Promise<"save-apply" | "save" | "cancel"> {
|
|
133
186
|
return new Promise((resolve) => {
|
|
@@ -171,7 +224,7 @@ export default function createExtension(pi: ExtensionAPI) {
|
|
|
171
224
|
resolve(undefined);
|
|
172
225
|
};
|
|
173
226
|
const container = new Container();
|
|
174
|
-
container.addChild(new Text(theme.fg("muted", "Share string"), 1, 0));
|
|
227
|
+
container.addChild(new Text(theme.fg("muted", "Paste Theme Share string"), 1, 0));
|
|
175
228
|
container.addChild(new Spacer(1));
|
|
176
229
|
container.addChild(input);
|
|
177
230
|
return {
|
|
@@ -183,6 +236,141 @@ export default function createExtension(pi: ExtensionAPI) {
|
|
|
183
236
|
});
|
|
184
237
|
}
|
|
185
238
|
|
|
239
|
+
async function promptImportName(ctx: ExtensionContext): Promise<string | undefined> {
|
|
240
|
+
while (true) {
|
|
241
|
+
const name = await ctx.ui.input("Theme name", "Theme");
|
|
242
|
+
if (name === undefined) return undefined;
|
|
243
|
+
const trimmed = name.trim();
|
|
244
|
+
if (trimmed) return trimmed;
|
|
245
|
+
ctx.ui.notify("Enter a theme name", "warning");
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
const THEME_GIST_FILE_BASE = "pi-sub-bar Theme";
|
|
250
|
+
const THEME_GIST_STATUS_KEY = "sub-bar:share";
|
|
251
|
+
|
|
252
|
+
function buildThemeGistFileName(name: string): string {
|
|
253
|
+
const trimmed = name.trim();
|
|
254
|
+
if (!trimmed) return THEME_GIST_FILE_BASE;
|
|
255
|
+
const safeName = trimmed.replace(/[\\/:*?"<>|]+/g, "-").trim();
|
|
256
|
+
return safeName ? `${THEME_GIST_FILE_BASE} ${safeName}` : THEME_GIST_FILE_BASE;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
async function createThemeGist(ctx: ExtensionContext, name: string, shareString: string): Promise<string | null> {
|
|
260
|
+
const notify = (message: string, level: "info" | "warning" | "error") => {
|
|
261
|
+
if (ctx.hasUI) {
|
|
262
|
+
ctx.ui.notify(message, level);
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
if (level === "error") {
|
|
266
|
+
console.error(message);
|
|
267
|
+
} else if (level === "warning") {
|
|
268
|
+
console.warn(message);
|
|
269
|
+
} else {
|
|
270
|
+
console.log(message);
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
try {
|
|
275
|
+
const authResult = await pi.exec("gh", ["auth", "status"]);
|
|
276
|
+
if (authResult.code !== 0) {
|
|
277
|
+
notify("GitHub CLI is not logged in. Run 'gh auth login' first.", "error");
|
|
278
|
+
return null;
|
|
279
|
+
}
|
|
280
|
+
} catch {
|
|
281
|
+
notify("GitHub CLI (gh) is not installed. Install it from https://cli.github.com/", "error");
|
|
282
|
+
return null;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
const tempDir = fs.mkdtempSync(join(tmpdir(), "pi-sub-bar-"));
|
|
286
|
+
const fileName = buildThemeGistFileName(name);
|
|
287
|
+
const filePath = join(tempDir, fileName);
|
|
288
|
+
fs.writeFileSync(filePath, shareString, "utf-8");
|
|
289
|
+
|
|
290
|
+
if (ctx.hasUI) {
|
|
291
|
+
ctx.ui.setStatus(THEME_GIST_STATUS_KEY, "Creating gist...");
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
try {
|
|
295
|
+
const result = await pi.exec("gh", ["gist", "create", "--public=false", filePath]);
|
|
296
|
+
if (result.code !== 0) {
|
|
297
|
+
const errorMsg = result.stderr?.trim() || "Unknown error";
|
|
298
|
+
notify(`Failed to create gist: ${errorMsg}`, "error");
|
|
299
|
+
return null;
|
|
300
|
+
}
|
|
301
|
+
const gistUrl = result.stdout?.trim();
|
|
302
|
+
if (!gistUrl) {
|
|
303
|
+
notify("Failed to create gist: empty response", "error");
|
|
304
|
+
return null;
|
|
305
|
+
}
|
|
306
|
+
return gistUrl;
|
|
307
|
+
} catch (error) {
|
|
308
|
+
notify(`Failed to create gist: ${error instanceof Error ? error.message : "Unknown error"}`, "error");
|
|
309
|
+
return null;
|
|
310
|
+
} finally {
|
|
311
|
+
if (ctx.hasUI) {
|
|
312
|
+
ctx.ui.setStatus(THEME_GIST_STATUS_KEY, undefined);
|
|
313
|
+
}
|
|
314
|
+
try {
|
|
315
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
316
|
+
} catch {
|
|
317
|
+
// Ignore cleanup errors
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
async function shareThemeString(
|
|
323
|
+
ctx: ExtensionContext,
|
|
324
|
+
name: string,
|
|
325
|
+
shareString: string,
|
|
326
|
+
mode: "prompt" | "gist" | "string" = "prompt",
|
|
327
|
+
): Promise<void> {
|
|
328
|
+
const trimmedName = name.trim();
|
|
329
|
+
const notify = (message: string, level: "info" | "warning" | "error") => {
|
|
330
|
+
if (ctx.hasUI) {
|
|
331
|
+
ctx.ui.notify(message, level);
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
if (level === "error") {
|
|
335
|
+
console.error(message);
|
|
336
|
+
} else if (level === "warning") {
|
|
337
|
+
console.warn(message);
|
|
338
|
+
} else {
|
|
339
|
+
console.log(message);
|
|
340
|
+
}
|
|
341
|
+
};
|
|
342
|
+
let resolvedMode = mode;
|
|
343
|
+
if (resolvedMode === "prompt") {
|
|
344
|
+
if (!ctx.hasUI) {
|
|
345
|
+
resolvedMode = "string";
|
|
346
|
+
} else {
|
|
347
|
+
const wantsGist = await ctx.ui.confirm("Share Theme", "Upload to a secret GitHub gist?");
|
|
348
|
+
resolvedMode = wantsGist ? "gist" : "string";
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
if (resolvedMode === "gist") {
|
|
353
|
+
const gistUrl = await createThemeGist(ctx, trimmedName, shareString);
|
|
354
|
+
if (gistUrl) {
|
|
355
|
+
pi.sendMessage({
|
|
356
|
+
customType: "sub-bar",
|
|
357
|
+
content: `Theme gist:\n${gistUrl}`,
|
|
358
|
+
display: true,
|
|
359
|
+
});
|
|
360
|
+
notify("Theme gist posted to chat", "info");
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
notify("Posting share string instead.", "warning");
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
pi.sendMessage({
|
|
367
|
+
customType: "sub-bar",
|
|
368
|
+
content: `Theme share string:\n${shareString}`,
|
|
369
|
+
display: true,
|
|
370
|
+
});
|
|
371
|
+
notify("Theme share string posted to chat", "info");
|
|
372
|
+
}
|
|
373
|
+
|
|
186
374
|
function readSettingsFile(): string | undefined {
|
|
187
375
|
try {
|
|
188
376
|
return fs.readFileSync(SETTINGS_PATH, "utf-8");
|
|
@@ -273,8 +461,9 @@ export default function createExtension(pi: ExtensionAPI) {
|
|
|
273
461
|
(_tui: unknown, theme: Theme) => ({
|
|
274
462
|
render(width: number) {
|
|
275
463
|
const safeWidth = Math.max(1, width);
|
|
276
|
-
const
|
|
277
|
-
const
|
|
464
|
+
const paddingLeft = settings.display.paddingLeft ?? 0;
|
|
465
|
+
const paddingRight = settings.display.paddingRight ?? 0;
|
|
466
|
+
const contentWidth = Math.max(1, safeWidth - paddingLeft - paddingRight);
|
|
278
467
|
const showTopDivider = settings.display.showTopDivider ?? false;
|
|
279
468
|
const showBottomDivider = settings.display.showBottomDivider ?? true;
|
|
280
469
|
const dividerChar = settings.display.dividerCharacter ?? "•";
|
|
@@ -315,9 +504,10 @@ export default function createExtension(pi: ExtensionAPI) {
|
|
|
315
504
|
lines = [trimmed];
|
|
316
505
|
}
|
|
317
506
|
|
|
318
|
-
if (
|
|
319
|
-
const
|
|
320
|
-
|
|
507
|
+
if (paddingLeft > 0 || paddingRight > 0) {
|
|
508
|
+
const leftPad = " ".repeat(paddingLeft);
|
|
509
|
+
const rightPad = " ".repeat(paddingRight);
|
|
510
|
+
lines = lines.map((line) => `${leftPad}${line}${rightPad}`);
|
|
321
511
|
}
|
|
322
512
|
|
|
323
513
|
if (showTopDivider) {
|
|
@@ -593,20 +783,14 @@ export default function createExtension(pi: ExtensionAPI) {
|
|
|
593
783
|
onDisplayThemeApplied: (name, options) => {
|
|
594
784
|
const content = options?.source === "manual"
|
|
595
785
|
? `sub-bar Theme ${name} loaded`
|
|
596
|
-
: `sub-bar Theme ${name} loaded / applied / saved. Restore settings in /sub-bar:settings ->
|
|
786
|
+
: `sub-bar Theme ${name} loaded / applied / saved. Restore settings in /sub-bar:settings -> Themes -> Load & Manage themes`;
|
|
597
787
|
pi.sendMessage({
|
|
598
788
|
customType: "sub-bar",
|
|
599
789
|
content,
|
|
600
790
|
display: true,
|
|
601
791
|
});
|
|
602
792
|
},
|
|
603
|
-
onDisplayThemeShared: (
|
|
604
|
-
pi.sendMessage({
|
|
605
|
-
customType: "sub-bar",
|
|
606
|
-
content: `Theme share string:\n/sub-bar:import ${shareString}`,
|
|
607
|
-
display: true,
|
|
608
|
-
});
|
|
609
|
-
},
|
|
793
|
+
onDisplayThemeShared: (name, shareString, mode) => shareThemeString(ctx, name, shareString, mode ?? "prompt"),
|
|
610
794
|
});
|
|
611
795
|
settings = newSettings;
|
|
612
796
|
void ensurePinnedEntries(settings.pinnedProvider ?? null);
|
|
@@ -642,35 +826,47 @@ export default function createExtension(pi: ExtensionAPI) {
|
|
|
642
826
|
}
|
|
643
827
|
|
|
644
828
|
const action = await promptImportAction(ctx);
|
|
645
|
-
|
|
829
|
+
let resolvedName = decoded.name;
|
|
830
|
+
if ((action === "save-apply" || action === "save") && !decoded.hasName) {
|
|
831
|
+
const providedName = await promptImportName(ctx);
|
|
832
|
+
if (!providedName) {
|
|
833
|
+
settings.display = { ...backup };
|
|
834
|
+
if (lastContext) {
|
|
835
|
+
renderUsageWidget(lastContext, currentUsage);
|
|
836
|
+
}
|
|
837
|
+
return;
|
|
838
|
+
}
|
|
839
|
+
resolvedName = providedName;
|
|
840
|
+
}
|
|
841
|
+
const notifyImported = (name: string) => {
|
|
646
842
|
const message = decoded.isNewerVersion
|
|
647
|
-
? `Imported ${
|
|
648
|
-
: `Imported ${
|
|
843
|
+
? `Imported ${name} (newer version, some fields may be ignored)`
|
|
844
|
+
: `Imported ${name}`;
|
|
649
845
|
ctx.ui.notify(message, decoded.isNewerVersion ? "warning" : "info");
|
|
650
846
|
};
|
|
651
847
|
|
|
652
848
|
if (action === "save-apply") {
|
|
653
849
|
settings.displayUserTheme = { ...backup };
|
|
654
|
-
settings = upsertDisplayTheme(settings,
|
|
850
|
+
settings = upsertDisplayTheme(settings, resolvedName, decoded.display, "imported");
|
|
655
851
|
settings.display = { ...decoded.display };
|
|
656
852
|
saveSettings(settings);
|
|
657
853
|
if (lastContext) {
|
|
658
854
|
renderUsageWidget(lastContext, currentUsage);
|
|
659
855
|
}
|
|
660
|
-
notifyImported();
|
|
856
|
+
notifyImported(resolvedName);
|
|
661
857
|
pi.sendMessage({
|
|
662
858
|
customType: "sub-bar",
|
|
663
|
-
content: `sub-bar Theme ${
|
|
859
|
+
content: `sub-bar Theme ${resolvedName} loaded`,
|
|
664
860
|
display: true,
|
|
665
861
|
});
|
|
666
862
|
return;
|
|
667
863
|
}
|
|
668
864
|
|
|
669
865
|
if (action === "save") {
|
|
670
|
-
settings = upsertDisplayTheme(settings,
|
|
866
|
+
settings = upsertDisplayTheme(settings, resolvedName, decoded.display, "imported");
|
|
671
867
|
settings.display = { ...backup };
|
|
672
868
|
saveSettings(settings);
|
|
673
|
-
notifyImported();
|
|
869
|
+
notifyImported(resolvedName);
|
|
674
870
|
if (lastContext) {
|
|
675
871
|
renderUsageWidget(lastContext, currentUsage);
|
|
676
872
|
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# @marckrenn/pi-sub-core
|
|
2
|
+
|
|
3
|
+
## 1.0.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#30](https://github.com/marckrenn/pi-sub/pull/30) [`af0828a`](https://github.com/marckrenn/pi-sub/commit/af0828a8d2e529497a1acff95e388a0a3eabb90e) Thanks [@marckrenn](https://github.com/marckrenn)! - Store the shared cache and lock files in the agent directory so all sub-core instances share a single cache.
|
|
8
|
+
|
|
9
|
+
- [#22](https://github.com/marckrenn/pi-sub/pull/22) [`3e5a026`](https://github.com/marckrenn/pi-sub/commit/3e5a026ea3dc113561ff32466a8aa03b91c6d876) Thanks [@marckrenn](https://github.com/marckrenn)! - Store sub-core and sub-bar settings in agent-level JSON files so updates no longer overwrite user configuration. Legacy extension `settings.json` files are migrated into the new files and removed after a successful migration.
|
|
10
|
+
|
|
11
|
+
Manual migration (if you want to do it yourself before updating):
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
cp ~/.pi/agent/extensions/sub-core/settings.json ~/.pi/agent/pi-sub-core-settings.json
|
|
15
|
+
cp ~/.pi/agent/extensions/sub-bar/settings.json ~/.pi/agent/pi-sub-bar-settings.json
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Existing users should move legacy settings from the extension folders to:
|
|
19
|
+
- `~/.pi/agent/pi-sub-core-settings.json`
|
|
20
|
+
- `~/.pi/agent/pi-sub-bar-settings.json`
|
|
21
|
+
|
|
22
|
+
- [`a6c0d33`](https://github.com/marckrenn/pi-sub/commit/a6c0d33c8d19d2876a4a8a1a0a69302a3c63f5e8) Thanks [@marckrenn](https://github.com/marckrenn)! - Move the shared cache/lock files under `~/.pi/agent/cache/sub-core` so all clients share a single cache directory.
|
|
23
|
+
|
|
24
|
+
- [`7da1e08`](https://github.com/marckrenn/pi-sub/commit/7da1e082e634f4e4dee2560b4d490527d1543ade) Thanks [@marckrenn](https://github.com/marckrenn)! - Add a minimum refresh interval setting to cap refresh frequency even when refresh is triggered every turn.
|
|
25
|
+
|
|
26
|
+
- [`1f5e451`](https://github.com/marckrenn/pi-sub/commit/1f5e45173b9868b0d6645ae35a084142a0ac56a5) Thanks [@marckrenn](https://github.com/marckrenn)! - Gate tool registration behind `tools.usageTool` and `tools.allUsageTool` (default off) in sub-core settings.
|
|
27
|
+
|
|
28
|
+
- [`35eb185`](https://github.com/marckrenn/pi-sub/commit/35eb18590f369db4cda931b8e11099d0f3ddb4ec) Thanks [@marckrenn](https://github.com/marckrenn)! - Add usage tool aliases `get_current_usage` and `get_all_usage`.
|
|
29
|
+
|
|
30
|
+
- Updated dependencies [[`7da1e08`](https://github.com/marckrenn/pi-sub/commit/7da1e082e634f4e4dee2560b4d490527d1543ade)]:
|
|
31
|
+
- @marckrenn/pi-sub-shared@1.0.4
|
|
32
|
+
|
|
33
|
+
## 1.0.3
|
|
34
|
+
|
|
35
|
+
### Patch Changes
|
|
36
|
+
|
|
37
|
+
- [`6fa2736`](https://github.com/marckrenn/pi-sub/commit/6fa27363573f34c38a372a6d7b8b74e756716724) Thanks [@marckrenn](https://github.com/marckrenn)! - Update extension tool execute signature order for compatibility with latest Pi API.
|
|
38
|
+
|
|
39
|
+
- Updated dependencies [[`6fa2736`](https://github.com/marckrenn/pi-sub/commit/6fa27363573f34c38a372a6d7b8b74e756716724)]:
|
|
40
|
+
- @marckrenn/pi-sub-shared@1.0.3
|
|
41
|
+
|
|
42
|
+
## 1.0.2
|
|
43
|
+
|
|
44
|
+
### Patch Changes
|
|
45
|
+
|
|
46
|
+
- [#3](https://github.com/marckrenn/pi-sub/pull/3) [`4ceb5ad`](https://github.com/marckrenn/pi-sub/commit/4ceb5ad133166237652d197ba9296ad1589a813c) Thanks [@marckrenn](https://github.com/marckrenn)! - Bundle sub-core with sub-bar, refresh Antigravity quotas + settings, and update UI copy/controls.
|
|
47
|
+
|
|
48
|
+
- Updated dependencies [[`4ceb5ad`](https://github.com/marckrenn/pi-sub/commit/4ceb5ad133166237652d197ba9296ad1589a813c)]:
|
|
49
|
+
- @marckrenn/pi-sub-shared@1.0.2
|
|
50
|
+
|
|
51
|
+
## 1.0.1
|
|
52
|
+
|
|
53
|
+
### Patch Changes
|
|
54
|
+
|
|
55
|
+
- Align repo version with npm publish.
|
|
56
|
+
- Updated dependencies:
|
|
57
|
+
- @marckrenn/pi-sub-shared@1.0.1
|
|
58
|
+
|
|
59
|
+
## 1.0.0
|
|
60
|
+
|
|
61
|
+
### Major Changes
|
|
62
|
+
|
|
63
|
+
- [`9bedd80`](https://github.com/marckrenn/pi-sub/commit/9bedd80b0037b723e70f0376019fff59a617e7cb) Thanks [@marckrenn](https://github.com/marckrenn)! - Initial 1.0.0 release.
|
|
64
|
+
|
|
65
|
+
### Patch Changes
|
|
66
|
+
|
|
67
|
+
- Updated dependencies [[`9bedd80`](https://github.com/marckrenn/pi-sub/commit/9bedd80b0037b723e70f0376019fff59a617e7cb)]:
|
|
68
|
+
- @marckrenn/pi-sub-shared@1.0.0
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# sub-core
|
|
2
|
+
|
|
3
|
+
Shared usage data core for pi extensions. Sub-core owns fetching, caching, provider selection, and emits usage updates via `pi.events` for the wider `sub-*` ecosystem (UI and non-UI clients).
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
- Fetches usage + status data from providers
|
|
8
|
+
- Deduplicates requests via shared cache/lock
|
|
9
|
+
- Emits updates for display-focused extensions (e.g. `sub-bar`) and non-UI tooling extensions
|
|
10
|
+
- Supports Antigravity usage via auth.json (`google-antigravity`)
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
Install via the pi package manager (recommended):
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pi install npm:@marckrenn/pi-sub-core
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Use `-l` to install into project settings instead of global:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pi install -l npm:@marckrenn/pi-sub-core
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
For a UI, also install a display extension like `sub-bar` from the same repo (see the root README for the full setup).
|
|
27
|
+
|
|
28
|
+
Manual install (local development):
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
git clone https://github.com/marckrenn/pi-sub.git
|
|
32
|
+
ln -s /path/to/pi-sub/packages/sub-core ~/.pi/agent/extensions/sub-core
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Alternative (no symlink): add it to `~/.pi/agent/settings.json`:
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
{
|
|
39
|
+
"extensions": ["/path/to/pi-sub/packages/sub-core/index.ts"]
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Tool Access
|
|
44
|
+
|
|
45
|
+
Tool registration is gated by `tools` in `~/.pi/agent/pi-sub-core-settings.json`.
|
|
46
|
+
By default, both tools are **off**. To enable them, set:
|
|
47
|
+
|
|
48
|
+
```json
|
|
49
|
+
{
|
|
50
|
+
"tools": {
|
|
51
|
+
"usageTool": true,
|
|
52
|
+
"allUsageTool": true
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Then run `/reload` (tool registration only happens on load). You can also toggle these in `/sub-core:settings` → Tool Settings.
|
|
58
|
+
|
|
59
|
+
When enabled, `sub-core` registers tools to expose usage snapshots to Pi:
|
|
60
|
+
|
|
61
|
+
- `sub_get_usage` / `get_current_usage` – refreshes usage (forced by default) and returns `{ provider, usage }`.
|
|
62
|
+
- `sub_get_all_usage` / `get_all_usage` – refreshes and returns all enabled provider entries (auto-enabled providers require credentials).
|
|
63
|
+
|
|
64
|
+
## Settings
|
|
65
|
+
|
|
66
|
+
Use `sub-core:settings` to configure shared provider settings plus **Usage Refresh Settings** and **Status Refresh Settings**. Provider enablement supports `auto` (default), `on`, and `off` — `auto` enables a provider only when credentials are detected.
|
|
67
|
+
|
|
68
|
+
Usage refresh controls cache/usage updates, while status refresh controls incident polling (you can keep status on a slower interval). The Minimum Refresh Interval caps how often refresh triggers can fetch new data even if you refresh every turn.
|
|
69
|
+
|
|
70
|
+
Antigravity usage requires an OAuth token in `~/.pi/agent/auth.json` under the `google-antigravity` key.
|
|
71
|
+
|
|
72
|
+
Anthropic extra usage formatting is controlled in Provider Settings (currency symbol + decimal separator).
|
|
73
|
+
|
|
74
|
+
Settings are stored in `~/.pi/agent/pi-sub-core-settings.json` (migrated from the legacy extension `settings.json` when present; the legacy file is removed after a successful migration).
|
|
75
|
+
|
|
76
|
+
**Settings migrations:** settings are merged with defaults on load, but renames/removals are not migrated automatically. When adding new settings or changing schema, update the defaults/merge logic and provide a migration (or instruct users to reset `pi-sub-core-settings.json`).
|
|
77
|
+
|
|
78
|
+
## Cache
|
|
79
|
+
|
|
80
|
+
Sub-core stores a shared cache and lock file:
|
|
81
|
+
|
|
82
|
+
- `~/.pi/agent/cache/sub-core/cache.json`
|
|
83
|
+
- `~/.pi/agent/cache/sub-core/cache.lock`
|
|
84
|
+
|
|
85
|
+
Legacy cache files next to the extension entry or in the agent root are migrated to the cache directory and removed on first run.
|
|
86
|
+
|
|
87
|
+
## Security notes
|
|
88
|
+
|
|
89
|
+
- Keep `~/.pi/agent/auth.json` readable only by your user (e.g. `chmod 600 ~/.pi/agent/auth.json`).
|
|
90
|
+
- Avoid logging token-bearing headers or auth config when troubleshooting provider calls.
|
|
91
|
+
|
|
92
|
+
## Provider comparison
|
|
93
|
+
|
|
94
|
+
| Provider | Usage Data | Status Page | Notes |
|
|
95
|
+
|----------|-----------|-------------|-------|
|
|
96
|
+
| Anthropic (Claude) | 5h/Week windows, extra usage | ✅ | Extra usage on/off state |
|
|
97
|
+
| GitHub Copilot | Monthly quota, requests | ✅ | Request multiplier support |
|
|
98
|
+
| Google Gemini | Pro/Flash quotas | ✅ | Aggregated by model family |
|
|
99
|
+
| Antigravity | Model quotas | ✅ | Sandbox Cloud Code Assist quotas (tested) |
|
|
100
|
+
| OpenAI Codex | Primary/secondary windows | ✅ | Credits not yet supported (PRs welcome!) |
|
|
101
|
+
| AWS Kiro | Credits | - | Credits not yet supported (PRs welcome!) |
|
|
102
|
+
| z.ai | Tokens/monthly limits | - | API quota limits |
|
|
103
|
+
|
|
104
|
+
## Development
|
|
105
|
+
|
|
106
|
+
### Packaging notes (pi install compatibility)
|
|
107
|
+
|
|
108
|
+
Pi packages use a `pi` field in `package.json` plus the `pi-package` keyword for discoverability. This repo already declares `pi.extensions`, so you can install via:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
pi install npm:@marckrenn/pi-sub-core
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Manual paths/symlinks still work for local development as documented above.
|
|
115
|
+
|
|
116
|
+
### Tested providers
|
|
117
|
+
|
|
118
|
+
Tested so far: Anthropic (Claude), OpenAI Codex, GitHub Copilot. Other providers are implemented but not yet verified in production.
|
|
119
|
+
|
|
120
|
+
### Adding a Provider
|
|
121
|
+
|
|
122
|
+
You need to update both **sub-core** (fetch layer) and **sub-bar** (display layer).
|
|
123
|
+
|
|
124
|
+
### Feature placement (core vs UI)
|
|
125
|
+
|
|
126
|
+
- **sub-core**: fetching, caching, provider detection/selection, status polling, tools/events, and shared settings.
|
|
127
|
+
- **sub-bar**: formatting, widget layout, UI-only toggles, and display-specific behavior.
|
|
128
|
+
- **sub-shared**: shared types/constants for anything referenced by both layers.
|
|
129
|
+
|
|
130
|
+
See the root README “Developer guide” for the decision checklist and examples.
|
|
131
|
+
|
|
132
|
+
#### sub-core (fetch + status)
|
|
133
|
+
1. Add provider name to `src/types.ts` (`PROVIDERS`, `ProviderName`).
|
|
134
|
+
2. Implement fetcher in `src/providers/impl/<provider>.ts`.
|
|
135
|
+
3. Register provider in `src/providers/registry.ts`.
|
|
136
|
+
4. Add detection + status config in `src/providers/metadata.ts`.
|
|
137
|
+
5. Add provider settings defaults in `src/settings-types.ts`.
|
|
138
|
+
|
|
139
|
+
#### sub-bar (display + UI)
|
|
140
|
+
1. Add provider name to `src/types.ts`.
|
|
141
|
+
2. Add display rules + labels in `src/providers/metadata.ts`.
|
|
142
|
+
3. Add window visibility in `src/providers/windows.ts`.
|
|
143
|
+
4. Add extras in `src/providers/extras.ts` (if needed).
|
|
144
|
+
5. Add settings UI + defaults in `src/providers/settings.ts` and `src/settings-types.ts`.
|
|
145
|
+
|
|
146
|
+
### Events (public contract)
|
|
147
|
+
|
|
148
|
+
Sub-core uses `pi.events` as an in-process pub/sub bus. Any `sub-*` extension can subscribe to updates (UI or headless). Sub-core is the source of truth for provider selection and refresh behavior; clients observe state and optionally request changes.
|
|
149
|
+
|
|
150
|
+
#### Broadcasts
|
|
151
|
+
- `sub-core:ready` → `{ state, settings }` (first load)
|
|
152
|
+
- `sub-core:update-current` → `{ state }` (cache hit or fresh fetch)
|
|
153
|
+
- `sub-core:update-all` → `{ state }` (cached entries + current provider)
|
|
154
|
+
- `sub-core:settings:updated` → `{ settings }`
|
|
155
|
+
|
|
156
|
+
`update-current` state is `{ provider, usage }`.
|
|
157
|
+
`update-all` state is `{ provider, entries }`, where entries are cached provider snapshots.
|
|
158
|
+
|
|
159
|
+
#### Requests (pull current state)
|
|
160
|
+
- `sub-core:request` → `{ reply, includeSettings? }`
|
|
161
|
+
- `sub-core:request` → `{ type: "entries", reply, force? }` (bulk usage entries)
|
|
162
|
+
|
|
163
|
+
The `reply` callback receives `{ state }` or `{ entries }` immediately if available.
|
|
164
|
+
|
|
165
|
+
#### Actions (mutate core state)
|
|
166
|
+
- `sub-core:settings:patch` → `{ patch }` (updates refresh interval/provider settings and persists)
|
|
167
|
+
- `sub-core:action` → `{ type: "refresh" | "cycleProvider", force? }`
|
|
168
|
+
|
|
169
|
+
After an action, sub-core emits `sub-core:update-current` with the new state.
|
|
170
|
+
|
|
171
|
+
## Credits
|
|
172
|
+
|
|
173
|
+
- Hannes Januschka ([barts](https://github.com/hjanuschka/shitty-extensions?tab=readme-ov-file#usage-barts), [@hjanuschka](https://x.com/hjanuschka))
|
|
174
|
+
- Peter Steinberger ([CodexBar](https://github.com/steipete/CodexBar), [@steipete](https://x.com/steipete))
|
|
175
|
+
|
|
176
|
+
## Status
|
|
177
|
+
|
|
178
|
+
Active. Used by `sub-bar` for display.
|