osdy-pi 1.2.0 → 1.3.0
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 +160 -30
- package/bin/osdy-pi.mjs +29 -6
- package/bin/osdy.mjs +43 -0
- package/extensions/osdy-pi/account-profiles.test.ts +111 -97
- package/extensions/osdy-pi/account-profiles.ts +91 -162
- package/extensions/osdy-pi/animation.test.ts +84 -0
- package/extensions/osdy-pi/animation.ts +17 -8
- package/extensions/osdy-pi/codex-usage-ui.test.ts +1145 -0
- package/extensions/osdy-pi/codex-usage-ui.ts +728 -0
- package/extensions/osdy-pi/codex-usage.test.ts +276 -0
- package/extensions/osdy-pi/codex-usage.ts +276 -0
- package/extensions/osdy-pi/constants.ts +134 -34
- package/extensions/osdy-pi/context-usage-ui.test.ts +168 -0
- package/extensions/osdy-pi/context-usage-ui.ts +60 -0
- package/extensions/osdy-pi/editor-settings.test.ts +121 -23
- package/extensions/osdy-pi/editor-settings.ts +39 -3
- package/extensions/osdy-pi/metrics.test.ts +95 -0
- package/extensions/osdy-pi/metrics.ts +39 -1
- package/extensions/osdy-pi/profile-label.ts +2 -2
- package/extensions/osdy-pi/runtime-helpers.test.ts +220 -1
- package/extensions/osdy-pi/runtime-helpers.ts +42 -19
- package/extensions/osdy-pi/runtime.test.ts +355 -7
- package/extensions/osdy-pi/runtime.ts +344 -66
- package/extensions/osdy-pi/types.ts +26 -1
- package/extensions/osdy-pi/ui.test.ts +128 -0
- package/extensions/osdy-pi/ui.ts +57 -40
- package/package.json +5 -2
- package/scripts/osdy-pi-account-profiles.mjs +521 -76
- package/scripts/osdy-pi-gentle-coexistence.mjs +200 -0
- package/scripts/osdy-pi-profile-setup.mjs +175 -0
- package/themes/osdy-pi-catppuccin-frappe.json +6 -2
- package/themes/osdy-pi-catppuccin-latte.json +6 -2
- package/themes/osdy-pi-catppuccin-macchiato.json +6 -2
- package/themes/osdy-pi-catppuccin-mocha.json +6 -2
- package/themes/osdy-pi-dark.json +6 -2
- package/themes/osdy-pi-dracula.json +6 -2
- package/themes/osdy-pi-kanagawa-dragon.json +6 -2
- package/themes/osdy-pi-kanagawa-lotus.json +6 -2
- package/themes/osdy-pi-kanagawa-wave.json +6 -2
- package/themes/osdy-pi-lucent-orange.json +6 -2
- package/themes/osdy-pi-matrix.json +6 -2
- package/themes/osdy-pi-new.json +6 -2
- package/themes/osdy-pi-sexy.json +6 -2
- package/themes/osdy-pi-tokyo-night.json +6 -2
package/README.md
CHANGED
|
@@ -4,27 +4,114 @@ Osdy Pi gives [Pi](https://github.com/earendil-works/pi) a themed, responsive te
|
|
|
4
4
|
|
|
5
5
|
<img width="1857" height="847" alt="Osdy Pi interface" src="https://github.com/user-attachments/assets/028eeb14-3f43-4f1c-9603-0c55a8d2856d" />
|
|
6
6
|
|
|
7
|
+
## Release highlights
|
|
8
|
+
|
|
9
|
+
| Area | What ships |
|
|
10
|
+
| --- | --- |
|
|
11
|
+
| Message cards | Pi-native, theme-aware user and assistant cards; assistant accents follow the theme and user accents are white. |
|
|
12
|
+
| Header and mascot | A theme-aware `neon` header and selectable `bts` mascot, both responsive and persisted independently. |
|
|
13
|
+
| Accounts | `/osdy-account` switches Codex profiles in place with atomic activation, rollback, bounded auth files, and process-safe locks. |
|
|
14
|
+
| Quota | `/usage` and compact bars emphasize remaining Codex quota at warning (40% or less) and error (15% or less) thresholds. |
|
|
15
|
+
|
|
16
|
+
## Prerequisites
|
|
17
|
+
|
|
18
|
+
- [Pi](https://github.com/earendil-works/pi)
|
|
19
|
+
- Node.js **22.19.0 or later**
|
|
20
|
+
- Git, for Osdy Pi's working-tree and diff features (and for Git-based installs)
|
|
21
|
+
|
|
7
22
|
## Quick start
|
|
8
23
|
|
|
9
|
-
Install from npm:
|
|
24
|
+
1. Install Osdy Pi from npm:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pi install npm:osdy-pi
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Or install directly from GitHub:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pi install git:github.com/OsdyOrtiz/Osdy-Pi
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
2. Start Pi:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pi
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Osdy Pi's own extension and all **14 themes** are bundled with this installation—do not install them separately. Launch through `osdy-pi` (or `npm run pi:dev`) to activate a valid Osdy default account into Pi's shared agent directory before Pi starts. With no default, Pi remains unmanaged; run `/osdy-account` to create a profile and establish a default. On session start, Osdy Pi restores its persisted enabled state when a UI is available and preserves your selected Pi theme. When disabled, it leaves Gentle Shell (or Pi's native UI) untouched.
|
|
43
|
+
|
|
44
|
+
### Optional: isolated `osdy` command
|
|
45
|
+
|
|
46
|
+
Use this path when you want **installed, normal Pi** with Osdy-specific settings and sessions, without changing the official Pi profile. `pi install` loads package resources in Pi; it does not guarantee that package executables are available on your shell's `PATH`. To use the packaged commands, install the CLI separately (or run the scripts directly from a checkout):
|
|
10
47
|
|
|
11
48
|
```bash
|
|
12
|
-
|
|
49
|
+
npm install --global osdy-pi
|
|
50
|
+
osdy-pi setup
|
|
51
|
+
osdy
|
|
13
52
|
```
|
|
14
53
|
|
|
15
|
-
|
|
54
|
+
From an Osdy Pi checkout, `node bin/osdy-pi.mjs setup` or `node bin/osdy.mjs setup` works without a global CLI installation; `node bin/osdy.mjs` launches Pi. `osdy-pi setup` is explicit and repeatable; `osdy` also checks/reconciles the isolated profile before each launch and forwards its arguments to the installed `pi` executable. The default source is `~/.pi/agent`, the isolated destination is `~/.pi/osdy-agent`, and the Osdy source is the package containing the CLI. Set `OSDY_PI_SOURCE_AGENT_DIR`, `OSDY_PI_AGENT_DIR`, or `OSDY_PI_EXTENSION_ROOT` to override them with absolute paths. The setup needs one valid local `gentle-pi` checkout declared as an absolute source in official Pi's package settings; if none or several match, set `GENTLE_PI_EXTENSION_ROOT=/absolute/path/to/gentle-pi` before setup and launch. Missing or invalid Gentle sources fail with an actionable error rather than silently omitting Gentle. No Pi fork, build, or PATH shim is required.
|
|
55
|
+
|
|
56
|
+
**What is isolated?** Official `~/.pi/agent/settings.json` is read but never rewritten by `osdy-pi setup` or `osdy`. Osdy keeps its own settings, selected theme, sessions, crash logs, and command history. Other existing top-level official resources are linked into the isolated profile only when absent—including `auth.json`, so credentials are **shared**, not isolated. Existing isolated files and symlinks are not replaced; the managed isolated settings are reconciled atomically. Named Codex accounts under `/osdy-account` are a separate feature, not this profile separation.
|
|
57
|
+
|
|
58
|
+
**Already have `~/.local/bin/osdy`?** Check `type -a osdy` (or `command -v osdy`) before using the new command: a home-local launcher earlier on `PATH` still wins. Setup does **not** remove or replace it. To try the packaged launcher without changing PATH, use `node "$(npm root -g)/osdy-pi/bin/osdy.mjs" --version` after installing the CLI; `node "$(npm root -g)/osdy-pi/bin/osdy.mjs" setup` runs the same explicit setup. Compare `pi --version` and `osdy --version` once the intended command resolves. Keep the old launcher until you confirm which executable you want; migration/removal is manual.
|
|
59
|
+
|
|
60
|
+
## Optional: complete Osdy Pi suite
|
|
61
|
+
|
|
62
|
+
Add these maintained extensions after installing Osdy Pi. They are optional; each extends Pi independently.
|
|
63
|
+
|
|
64
|
+
| Package | Purpose |
|
|
65
|
+
| --- | --- |
|
|
66
|
+
| `gentle-engram` | Persistent memory shared across sessions, compactions, and MCP agents. |
|
|
67
|
+
| `pi-intercom` | Brokered communication between Pi agents and sessions. |
|
|
68
|
+
| `@juicesharp/rpiv-ask-user-question` | Structured, typed questionnaires when an agent needs clarification. |
|
|
69
|
+
| `pi-web-access` | Web search and URL fetching, plus repository, PDF, YouTube, and local-video analysis. |
|
|
70
|
+
| `pi-lens` | Real-time code feedback through LSP, linters, formatters, type checking, and structural analysis. |
|
|
71
|
+
| `pi-btw` | Parallel side conversations through `/btw`. |
|
|
72
|
+
| `@open-pets/pi` | OpenPets integration for Pi. |
|
|
73
|
+
| `pi-playwright` | Playwright browser-automation skills. |
|
|
74
|
+
| `pi-mcp-adapter` | MCP server and tool adapter for Pi. |
|
|
75
|
+
| `pi-subagents-j0k3r` | Markdown-defined subagents, delegation tools, history, and model profiles. |
|
|
76
|
+
| `@juicesharp/rpiv-todo` | A persistent live todo overlay for the agent. |
|
|
77
|
+
| `gentle-pi` | The Gentle senior-architect harness, with SDD/OpenSpec, subagents, TDD evidence, and skills. |
|
|
78
|
+
|
|
79
|
+
Install the ordinary npm packages once:
|
|
16
80
|
|
|
17
81
|
```bash
|
|
18
|
-
pi install
|
|
82
|
+
pi install npm:gentle-engram
|
|
83
|
+
pi install npm:pi-intercom
|
|
84
|
+
pi install npm:@juicesharp/rpiv-ask-user-question
|
|
85
|
+
pi install npm:pi-web-access
|
|
86
|
+
pi install npm:pi-lens
|
|
87
|
+
pi install npm:pi-btw
|
|
88
|
+
pi install npm:@open-pets/pi
|
|
89
|
+
pi install npm:pi-playwright
|
|
90
|
+
pi install npm:pi-mcp-adapter
|
|
91
|
+
pi install npm:pi-subagents-j0k3r
|
|
92
|
+
pi install npm:@juicesharp/rpiv-todo
|
|
19
93
|
```
|
|
20
94
|
|
|
21
|
-
|
|
95
|
+
`gentle-pi` is deliberately not included in that package-install block: clone and register it through the coexistence setup below, which applies Osdy-specific exclusions instead of adding a duplicate ordinary package entry.
|
|
22
96
|
|
|
23
97
|
```bash
|
|
24
|
-
pi
|
|
98
|
+
git clone https://github.com/Gentleman-Programming/gentle-pi.git
|
|
99
|
+
osdy-pi gentle setup "$(pwd)/gentle-pi"
|
|
25
100
|
```
|
|
26
101
|
|
|
27
|
-
|
|
102
|
+
## Gentle coexistence setup
|
|
103
|
+
|
|
104
|
+
To load a local `gentle-pi` checkout while keeping Osdy Pi's UI authoritative, run:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
osdy-pi gentle setup /absolute/path/to/gentle-pi
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
The command validates that the absolute source is a readable `gentle-pi` package with Gentle's todo and agents extensions before atomically updating `$PI_CODING_AGENT_DIR/settings.json` (or `~/.pi/agent/settings.json`). It registers the local package immediately before the first configured Osdy Pi package entry, so Gentle Shell initializes first, with exclusions only for Gentle's `gentle-todo.ts` and `gentle-agents.ts`, plus `themes: []`. Restart Pi or run `/reload` after setup.
|
|
111
|
+
|
|
112
|
+
Gentle Shell intentionally remains fully active underneath Osdy, including its footer and widgets. While Osdy is enabled, Osdy claims the footer and editor; disabling Osdy restores the editor Gentle Shell provided at session startup. Gentle's changes widget may coexist with Osdy's visual widgets.
|
|
113
|
+
|
|
114
|
+
The exclusions prevent Gentle's todo and agents extensions from competing with the suite. `@juicesharp/rpiv-todo` remains the authoritative todo overlay, `pi-subagents-j0k3r` remains the authoritative subagent system, and `@juicesharp/rpiv-ask-user-question` remains the authoritative structured-question plugin; their package entries are left untouched.
|
|
28
115
|
|
|
29
116
|
## OpenAI account profiles
|
|
30
117
|
|
|
@@ -36,7 +123,7 @@ Osdy Pi can keep multiple ChatGPT Plus/Pro accounts authenticated and let you ch
|
|
|
36
123
|
|
|
37
124
|
| Action | Behavior |
|
|
38
125
|
| --- | --- |
|
|
39
|
-
| **Switch** |
|
|
126
|
+
| **Switch** | Waits for idle, safely replaces Pi's canonical auth with the selected profile, and updates active/default together without restarting Pi. |
|
|
40
127
|
| **Add** | Creates an isolated profile without restarting or changing the default. Select it with **Switch**, then run `/login`. |
|
|
41
128
|
| **Default** | Shows, changes, or clears the profile used by future plain installed `pi` and `npm run pi:dev` launches. It does not switch the current process. |
|
|
42
129
|
| **Rename** | Renames an inactive profile. The default follows the new name when applicable. |
|
|
@@ -71,7 +158,7 @@ osdy-pi account remove personal --confirm personal --replacement work
|
|
|
71
158
|
osdy-pi account default --clear
|
|
72
159
|
```
|
|
73
160
|
|
|
74
|
-
Profile names accept
|
|
161
|
+
Profile names accept ASCII letters, numbers, and hyphens, up to 63 characters, preserving their spelling (for example, `Personal` or `WORK`). Spaces, paths, and the reserved names `default`, `profiles`, and `auth.json` (in any casing) are rejected. Profile identity is case-insensitive, so names that differ only by casing cannot coexist. `account add` opens a profile for login but does not change the default.
|
|
75
162
|
|
|
76
163
|
### See and switch the active account
|
|
77
164
|
|
|
@@ -81,7 +168,7 @@ When Pi was launched through a profile, Osdy Pi shows its profile name in the ed
|
|
|
81
168
|
- **Extended/framed editor:** `personal` replaces the `Osdy-Pi` title.
|
|
82
169
|
- **No managed profile:** the existing model line and `Osdy-Pi` title remain unchanged.
|
|
83
170
|
|
|
84
|
-
`account use <name>`
|
|
171
|
+
`account use <name>` activates the profile in Pi's shared agent directory, saves it as active/default, then starts Pi. Inside Pi, `/osdy-account` waits for active work to finish and swaps the canonical `auth.json` in place; the next request resolves the new account without a spawn, shutdown, session handoff, or restart.
|
|
85
172
|
|
|
86
173
|
To resume a specific session directly from the terminal:
|
|
87
174
|
|
|
@@ -89,7 +176,9 @@ To resume a specific session directly from the terminal:
|
|
|
89
176
|
osdy-pi account use work -- --session /absolute/path/to/session.jsonl
|
|
90
177
|
```
|
|
91
178
|
|
|
92
|
-
> **Privacy:**
|
|
179
|
+
> **Privacy:** each profile keeps a private `auth.json`; Pi runs against its canonical shared `auth.json`. Osdy Pi atomically copies opaque auth files between those private locations only to activate or preserve an account; it never parses, prints, logs, or passes OAuth credentials. Session history, settings, installed packages, and extension resources are shared, so every profile can access that local state. It keeps Pi's canonical `openai-codex` provider and delegates authentication to Pi's built-in `/login` flow.
|
|
180
|
+
|
|
181
|
+
Account switching is serialized in-process and protected by a private cross-process lock. Osdy Pi accepts only bounded regular auth files, refuses symlink-based auth sources, writes replacements with private permissions, and restores the previous canonical auth and account metadata when activation fails. A separate namespace lock protects concurrent profile creation, rename, and removal. Launchers activate the selected auth before starting Pi while continuing to use the shared agent directory; existing managed-directory links from earlier profile layouts are resolved for compatibility.
|
|
93
182
|
|
|
94
183
|
### Rename and permanently remove profiles
|
|
95
184
|
|
|
@@ -104,9 +193,10 @@ Before rename or removal, close this Pi process when it uses the target and **ma
|
|
|
104
193
|
| Area | Included behavior |
|
|
105
194
|
| --- | --- |
|
|
106
195
|
| Themes | 14 built-in themes, including Osdy, Kanagawa, Dracula, Catppuccin, Matrix, and Lucent Orange palettes |
|
|
107
|
-
| Header |
|
|
196
|
+
| Header and mascot | Independently selectable `osdy-theme`/`neon` headers and `current`/`bts` mascots |
|
|
197
|
+
| Messages | Pi-native, theme-aware user and assistant message cards |
|
|
108
198
|
| Input | Responsive auto editor by default, with selectable simple Pi-native or extended framed modes |
|
|
109
|
-
| Status | Custom working spinner, responsive footer metrics,
|
|
199
|
+
| Status | Custom working spinner, responsive footer metrics, dynamic extension statuses, and Codex subscription quota with low-capacity emphasis |
|
|
110
200
|
| Git | Working-tree summary and a centered, filterable diff panel |
|
|
111
201
|
| Audio | Optional event sounds on macOS and Windows |
|
|
112
202
|
|
|
@@ -149,7 +239,16 @@ Or set the theme in Pi's `settings.json`:
|
|
|
149
239
|
|
|
150
240
|
### Header, mascot, and animation
|
|
151
241
|
|
|
152
|
-
|
|
242
|
+
Header and mascot choices are independent:
|
|
243
|
+
|
|
244
|
+
| Element | Choices | Command |
|
|
245
|
+
| --- | --- | --- |
|
|
246
|
+
| Header | `osdy-theme` (default), `neon` | `/osdy-pi header osdy-theme|neon` |
|
|
247
|
+
| Mascot | `current` (default), `bts` | `/osdy-pi mascot current|bts` |
|
|
248
|
+
|
|
249
|
+
Both commands update the UI immediately. Add `status` instead of a choice to inspect the current selection. Choices persist in the global Osdy Pi settings across reloads and sessions. The old top-level style commands and `classic` header aliases are no longer registered.
|
|
250
|
+
|
|
251
|
+
In normal mode, the selected header and mascot render side by side. The Neon header derives its highlights from the active theme rather than using one fixed palette. Each mascot keeps its own tone map while its animated edge glow can resolve through theme colors. Header and mascot scaling remain independent, so any combination follows the same responsive layout rules.
|
|
153
252
|
|
|
154
253
|
Animation is enabled by default with an intro animation. Configure it through `OSDY_PI_ANIMATION`:
|
|
155
254
|
|
|
@@ -167,31 +266,51 @@ Animation is enabled by default with an intro animation. Configure it through `O
|
|
|
167
266
|
| Compact (72+ columns) | Proportionally scaled mascot above a readable header, reduced only when needed | Selected editor mode and Git behavior | Same editor-aware footer behavior as normal/small modes |
|
|
168
267
|
| Small (<72 columns) | Mascot only; art and tone map scale proportionally | Pi native editor for every editor mode; Git summary hidden | Model + styled thinking level, usage, path/branch, then dynamic extension statuses (except Pi Lens) |
|
|
169
268
|
|
|
269
|
+
In the extended framed editor, the active thinking level is rendered in bold in the top-right model metadata so it remains easy to scan.
|
|
270
|
+
|
|
170
271
|
Small and compact modes trim only fully empty mascot-art and tone-map margins before applying one proportional width-and-height scale; mascot width starts near four-fifths of the available width. The header moves below the mascot as soon as side-by-side width would force the mascot into an additional width-limited reduction. Compact headers retain their source art when it fits and reduce proportionally only when a width or row bound requires it. Compact headers and mascots share a bounded terminal-row budget, so the header is omitted rather than collapsed into an unreadable one-row logo when there is not enough vertical space. The small-mode footer places the model and styled bare thinking level above usage, path/branch, and dynamic extension statuses. Pi Lens's footer status is hidden in small mode, but Pi Lens continues running. Usage includes input/output/cache-read/cache-write tokens, cost, and context. Extension statuses are supplied dynamically by Pi/extensions and may include Osdy Pi, MCP, or LSP; they are not hardcoded.
|
|
171
272
|
|
|
172
|
-
The editor mode
|
|
273
|
+
The enabled state, editor mode, working-tree visibility preference, header, and mascot persist globally across Pi reloads and sessions, shared by all projects. They are saved in `$PI_CODING_AGENT_DIR/extensions/osdy-pi/settings.json`, or `~/.pi/agent/extensions/osdy-pi/settings.json` when `PI_CODING_AGENT_DIR` is unset. Existing settings without the new visual fields safely default to `osdy-theme` and `current`; the former `raccoon` mascot value migrates to `bts`. The selected editor mode and working-tree placement are restored when the terminal moves normal → small → normal.
|
|
173
274
|
|
|
174
275
|
## Commands
|
|
175
276
|
|
|
176
277
|
| Group | Command |
|
|
177
278
|
| --- | --- |
|
|
178
279
|
| Main | `/osdy-pi` |
|
|
179
|
-
| Main | `/osdy-pi enable\|disable\|status` |
|
|
280
|
+
| Main | `/osdy-pi enable\|disable\|on\|off\|status` |
|
|
180
281
|
| Accounts | `/osdy-account` |
|
|
181
|
-
| Header | `/osdy-pi osdy-theme\|
|
|
282
|
+
| Header | `/osdy-pi header osdy-theme\|neon\|status` |
|
|
283
|
+
| Mascot | `/osdy-pi mascot current\|bts\|status` |
|
|
182
284
|
| Editor | `/osdy-pi editor auto\|extended\|simple\|on\|off\|toggle\|status` |
|
|
183
285
|
| Working tree | `/osdy-pi working-tree on\|off\|toggle\|status` |
|
|
184
286
|
| Working tree | `/osdy-pi working-tree position top\|bottom\|status` |
|
|
185
287
|
| Audio | `/osdy-pi sound setup` |
|
|
186
288
|
| Diff | `/osdy-pi diff` |
|
|
187
|
-
|
|
|
188
|
-
|
|
289
|
+
| Codex subscription | `/usage` |
|
|
290
|
+
|
|
291
|
+
`/osdy-pi` reports status. `enable` (or `on`) applies the Osdy Pi UI without changing the selected Pi theme; `disable` (or `off`) restores the Gentle Shell or Pi UI captured at session startup while preserving that theme. The enabled state, editor mode, working-tree visibility, and sound configuration persist globally.
|
|
292
|
+
|
|
293
|
+
### Codex subscription usage
|
|
189
294
|
|
|
190
|
-
`/
|
|
295
|
+
Run `/usage` to open the Codex subscription dashboard for the active managed `openai-codex` profile and model. Press `r` to refresh; `esc` or `q` closes it. The dashboard shows these controls at the bottom.
|
|
296
|
+
|
|
297
|
+
The main windows are labeled **Session** and **Weekly** (the API/domain remains primary/secondary). Their remaining-capacity bars are full at 100% remaining and empty at 0%; labels use the active theme's bold accent, Session uses the accent fill, Weekly uses `mdLink`, and empty segments are muted. The remaining percentage stays muted above 40%, changes to the theme's warning color at 40% or less, and changes to its error color at 15% or less. The same thresholds apply in the `/usage` dashboard and compact footer/editor quota bars. A double themed frame, section dividers, and spacing separate the display. Detail cards show each duration and relative, local, and UTC reset times. Plan, availability, credits/reset count, and additional buckets appear only when the service supplies them; absent optional values are omitted.
|
|
298
|
+
|
|
299
|
+
At wide widths, the modal pairs the Session and Weekly detail cards. Below 72 content columns, cards and bars stack and account/model data wraps. The native footer and extended editor also show compact Session/Weekly remaining-capacity bars below model and thinking metadata whenever a current Codex snapshot exists. Wide widths combine those bars; narrow widths stack them. Additional buckets appear only in `/usage`.
|
|
300
|
+
|
|
301
|
+
Usage loads once when the session starts and refreshes when the modal opens or `r` is pressed; it does not poll. A refresh clears the previous snapshot before authentication resolves, and shutdown clears state, so quota data cannot cross account or profile boundaries.
|
|
302
|
+
|
|
303
|
+
> **Privacy:** OAuth is resolved only through Pi's `modelRegistry`. Osdy Pi does not read `auth.json`, persist or log credentials, or display account IDs, tokens, response bodies, or endpoint internals in the UI. Requests use a fixed HTTPS endpoint with bounded timeout, response size, and redirects.
|
|
304
|
+
|
|
305
|
+
## Native message cards
|
|
306
|
+
|
|
307
|
+
Osdy Pi delegates conversation rendering to Pi's native message-card components. It does not install a Markdown transformer or inject card markup into assistant responses. This preserves Pi's own streaming, selection, and Markdown behavior while allowing every bundled Osdy theme to style the native cards.
|
|
308
|
+
|
|
309
|
+
User and assistant cards have separate background, text, and accent tokens. Assistant accents follow each theme's primary accent; user accents are white for a consistent visual distinction. Disabling Osdy Pi continues to restore the underlying Gentle Shell or Pi presentation normally.
|
|
191
310
|
|
|
192
311
|
## Editor and working indicator
|
|
193
312
|
|
|
194
|
-
The default `auto` editor mode preserves the responsive behavior: it uses the framed editor when space permits and Pi's native editor on small terminals. Select `simple` for Pi's native editor at every width, or `extended` to request the framed editor explicitly: `/osdy-pi editor auto|extended|simple`. Small terminals always use Pi's native editor, including when `extended` is selected. The legacy commands remain compatible where feasible: `on` maps to `extended`, `off` maps to `simple`, and `toggle` switches between extended and simple.
|
|
313
|
+
The default `auto` editor mode preserves the responsive behavior: it uses the framed editor when space permits and Pi's native editor on small terminals. Select `simple` for Pi's native editor at every width, or `extended` to request the framed editor explicitly: `/osdy-pi editor auto|extended|simple`. Simple mode actually unmounts the custom editor component rather than hiding it. Small terminals always use Pi's native editor, including when `extended` is selected. The legacy commands remain compatible where feasible: `on` maps to `extended`, `off` maps to `simple`, and `toggle` switches between extended and simple.
|
|
195
314
|
|
|
196
315
|
In auto or extended mode at a non-small width, the framed editor shows the model and thinking level in its title and session usage in its footer. For an account-profile launch, the left title shows the active profile name instead of `Osdy-Pi`. When the native editor is effective (simple mode or any small terminal), the Osdy footer instead shows model, active profile when present, thinking, and usage rows before its path/branch and status rows. It uses the currently active Pi/Osdy theme palette; no separate editor theme selector exists. Usage covers input, output, cache read, cache write when present, cost, and context. If Pi supports autocomplete, the editor uses Pi's native autocomplete rendering while the completion UI is visible.
|
|
197
316
|
|
|
@@ -199,7 +318,7 @@ A custom spinner appears above the editor while work is active. Osdy Pi hides Pi
|
|
|
199
318
|
|
|
200
319
|
## Working tree and diff
|
|
201
320
|
|
|
202
|
-
The working-tree summary is enabled by default. It reads the repository state at session start, including existing changes, and reports staged, unstaged, and untracked counts with total `+/-` changes. It also has clean and unavailable states. After successful `edit`, `write`, `ast_grep_replace`, or `bash` tool execution, it refreshes.
|
|
321
|
+
The working-tree summary is enabled by default. It reads the repository state at session start, including existing changes, and reports staged, unstaged, and untracked counts with total `+/-` changes. It also has clean and unavailable states. `working-tree off` unregisters the widget completely, and a persisted disabled preference leaves it unmounted when the next session starts. `working-tree on` remounts and refreshes it without requiring a restart. After successful `edit`, `write`, `ast_grep_replace`, or `bash` tool execution, it refreshes.
|
|
203
322
|
|
|
204
323
|
Use `working-tree position top` or `bottom` to place the summary above or below the editor. The widget supplies trailing blank space and adds leading separation when it is below the editor or the spinner is active, keeping the surrounding layout readable without promising a fixed number of blank lines in every state.
|
|
205
324
|
|
|
@@ -215,7 +334,7 @@ Use `working-tree position top` or `bottom` to place the summary above or below
|
|
|
215
334
|
|
|
216
335
|
## Audio notifications
|
|
217
336
|
|
|
218
|
-
Osdy Pi can play readable `.mp3` or `.wav` files on macOS and Windows. Other platforms safely skip playback.
|
|
337
|
+
Osdy Pi can play readable `.mp3` or `.wav` files on macOS and Windows. Other platforms safely skip playback. macOS playback requires the system `afplay` command; Windows playback requires `powershell.exe` and the Windows Media Player COM component (`WMPlayer.OCX`).
|
|
219
338
|
|
|
220
339
|
| Event | Current meaning |
|
|
221
340
|
| --- | --- |
|
|
@@ -248,16 +367,22 @@ Precedence is startup flag, then saved global setting, then unconfigured. Empty
|
|
|
248
367
|
|
|
249
368
|
For the normal in-Pi development flow, no global `osdy-pi` link is required:
|
|
250
369
|
|
|
251
|
-
1.
|
|
370
|
+
1. Install the checkout's dependencies:
|
|
371
|
+
|
|
372
|
+
```bash
|
|
373
|
+
npm install
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
2. Start the local extension:
|
|
252
377
|
|
|
253
378
|
```bash
|
|
254
379
|
npm run pi:dev
|
|
255
380
|
```
|
|
256
381
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
382
|
+
3. Inside Pi, run `/osdy-account`.
|
|
383
|
+
4. Choose **Add**, enter a profile name, then choose **Switch** and select it.
|
|
384
|
+
5. Without restarting, run `/login` and choose **ChatGPT Plus/Pro (Codex)**.
|
|
385
|
+
6. From then on, `npm run pi:dev` starts the default profile automatically. Use `/osdy-account` for every profile-management action.
|
|
261
386
|
|
|
262
387
|
The terminal interface remains available for recovery and automated testing:
|
|
263
388
|
|
|
@@ -270,7 +395,7 @@ npm run pi:dev -- account rename personal private
|
|
|
270
395
|
npm run pi:dev -- account remove private --confirm private
|
|
271
396
|
```
|
|
272
397
|
|
|
273
|
-
`npm run pi:dev` launches `pi -e <absolute repository root>` with `PI_CODING_AGENT_DIR=<absolute repository root>/.pi-dev
|
|
398
|
+
`npm run pi:dev` launches `pi -e <absolute repository root>` with `PI_CODING_AGENT_DIR=<absolute repository root>/.pi-dev`. If its `.pi-dev` metadata names a valid profile, it activates that profile's auth before launching Pi and retains `-e <absolute repository root>`. The development `.pi-dev` profile store and the installed Pi profile store are separate. Account commands use this checkout's local launcher, so no global `osdy-pi` link is needed. The development extension root remains loaded after an in-process `/osdy-account` switch. The manual equivalent is:
|
|
274
399
|
|
|
275
400
|
```bash
|
|
276
401
|
PI_CODING_AGENT_DIR="$PWD/.pi-dev" OSDY_PI_DEV_EXTENSION_ROOT="$PWD" pi -e "$PWD"
|
|
@@ -301,15 +426,20 @@ npm run pi:dev
|
|
|
301
426
|
- The Git summary reports unavailable when Git commands cannot read a working tree.
|
|
302
427
|
- Diff patches depend on readable repository files; a file whose patch cannot load shows the reported error in the panel.
|
|
303
428
|
- Audio playback is limited to macOS and Windows and to readable `.mp3`/`.wav` files.
|
|
429
|
+
- `/usage` requires an active `openai-codex` login. Run `/login` and choose **ChatGPT Plus/Pro (Codex)**; run `/reload` after local extension changes.
|
|
430
|
+
- A `401` indicates an expired session, while a `403` means usage is unavailable. Optional backend fields may be absent and simply do not render.
|
|
304
431
|
|
|
305
432
|
## Disable, uninstall, and license
|
|
306
433
|
|
|
307
|
-
|
|
434
|
+
Turn off the custom UI persistently (including across `/reload`):
|
|
308
435
|
|
|
309
436
|
```text
|
|
310
437
|
/osdy-pi disable
|
|
438
|
+
# Alias: /osdy-pi off
|
|
311
439
|
```
|
|
312
440
|
|
|
441
|
+
Restore it with `/osdy-pi enable` or `/osdy-pi on`.
|
|
442
|
+
|
|
313
443
|
To remove the package, use Pi's package-management command for installed packages.
|
|
314
444
|
|
|
315
445
|
MIT
|
package/bin/osdy-pi.mjs
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { spawn } from "node:child_process";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { dirname, join, resolve } from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { setupOsdyProfile } from "../scripts/osdy-pi-profile-setup.mjs";
|
|
7
|
+
import { configureGentleCoexistence } from "../scripts/osdy-pi-gentle-coexistence.mjs";
|
|
3
8
|
import {
|
|
4
9
|
clearDefaultAccount,
|
|
5
10
|
ensureProfileLayout,
|
|
@@ -12,7 +17,7 @@ import {
|
|
|
12
17
|
removeProfile,
|
|
13
18
|
renameProfile,
|
|
14
19
|
setDefaultAccount,
|
|
15
|
-
|
|
20
|
+
switchAccountAuth,
|
|
16
21
|
} from "../scripts/osdy-pi-account-profiles.mjs";
|
|
17
22
|
|
|
18
23
|
function writeStdout(message) {
|
|
@@ -25,7 +30,7 @@ function writeStderr(message) {
|
|
|
25
30
|
|
|
26
31
|
function printUsage() {
|
|
27
32
|
writeStderr(
|
|
28
|
-
"Usage: osdy-pi account list | create <name> | add <name> | rename <old> <new> | remove <name> --confirm <name> [--replacement <other>] | use <name> [-- <pi args...] | default [<name> | --clear]",
|
|
33
|
+
"Usage: osdy-pi setup | gentle setup <absolute-source-path> | account list | create <name> | add <name> | rename <old> <new> | remove <name> --confirm <name> [--replacement <other>] | use <name> [-- <pi args...] | default [<name> | --clear]",
|
|
29
34
|
);
|
|
30
35
|
}
|
|
31
36
|
|
|
@@ -65,13 +70,31 @@ function startPi(plan) {
|
|
|
65
70
|
|
|
66
71
|
try {
|
|
67
72
|
const args = process.argv.slice(2);
|
|
68
|
-
|
|
69
|
-
|
|
73
|
+
if (args[0] === "setup") {
|
|
74
|
+
if (args.length !== 1) throw new Error("Usage: osdy-pi setup");
|
|
75
|
+
const home = homedir();
|
|
76
|
+
const result = await setupOsdyProfile({
|
|
77
|
+
officialDir: process.env.OSDY_PI_SOURCE_AGENT_DIR || join(home, ".pi", "agent"),
|
|
78
|
+
profileDir: process.env.OSDY_PI_AGENT_DIR || join(home, ".pi", "osdy-agent"),
|
|
79
|
+
osdyRoot: process.env.OSDY_PI_EXTENSION_ROOT || resolve(dirname(fileURLToPath(import.meta.url)), ".."),
|
|
80
|
+
gentleRoot: process.env.GENTLE_PI_EXTENSION_ROOT || undefined,
|
|
81
|
+
});
|
|
82
|
+
writeStdout(`Isolated Osdy profile ${result.status}: ${result.profileDir}`);
|
|
83
|
+
} else if (args[0] === "gentle") {
|
|
84
|
+
if (args[1] !== "setup" || args.length !== 3)
|
|
85
|
+
throw new Error("Usage: osdy-pi gentle setup <absolute-source-path>");
|
|
86
|
+
const result = await configureGentleCoexistence(args[2]);
|
|
87
|
+
writeStdout(
|
|
88
|
+
`Gentle coexistence ${result.status}. Restart Pi or run /reload to apply it.`,
|
|
89
|
+
);
|
|
90
|
+
} else if (args.length === 0) {
|
|
91
|
+
const sharedAgentDir = getSharedAgentDir();
|
|
70
92
|
const result = await planDefaultLaunch(sharedAgentDir);
|
|
71
93
|
if (result.defaultAccount.status === "invalid")
|
|
72
94
|
writeStderr("Ignoring invalid Osdy Pi default account metadata.");
|
|
73
95
|
startPi(result.plan);
|
|
74
96
|
} else {
|
|
97
|
+
const sharedAgentDir = getSharedAgentDir();
|
|
75
98
|
const command = parseAccountCommand(args);
|
|
76
99
|
if (command.action === "list") {
|
|
77
100
|
const profiles = await listProfiles(sharedAgentDir);
|
|
@@ -104,6 +127,7 @@ try {
|
|
|
104
127
|
writeStdout(
|
|
105
128
|
"Account profile is ready. In Pi, run /login and select ChatGPT Plus/Pro (Codex).",
|
|
106
129
|
);
|
|
130
|
+
await switchAccountAuth(sharedAgentDir, command.name);
|
|
107
131
|
startPi(planPiLaunch(sharedAgentDir, command.name));
|
|
108
132
|
} else if (command.action === "rename") {
|
|
109
133
|
await renameProfile(sharedAgentDir, command.oldName, command.newName);
|
|
@@ -115,8 +139,7 @@ try {
|
|
|
115
139
|
});
|
|
116
140
|
writeStdout(`Account profile ${command.name} permanently removed.`);
|
|
117
141
|
} else {
|
|
118
|
-
await
|
|
119
|
-
await setDefaultAccount(sharedAgentDir, command.name);
|
|
142
|
+
await switchAccountAuth(sharedAgentDir, command.name);
|
|
120
143
|
startPi(planPiLaunch(sharedAgentDir, command.name, command.piArgs));
|
|
121
144
|
}
|
|
122
145
|
}
|
package/bin/osdy.mjs
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/* global process, console */
|
|
3
|
+
import { spawn } from "node:child_process";
|
|
4
|
+
import { constants as osConstants, homedir } from "node:os";
|
|
5
|
+
import { dirname, join, resolve } from "node:path";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
import { setupOsdyProfile } from "../scripts/osdy-pi-profile-setup.mjs";
|
|
8
|
+
|
|
9
|
+
const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
10
|
+
const home = homedir();
|
|
11
|
+
const officialDir = process.env.OSDY_PI_SOURCE_AGENT_DIR || join(home, ".pi", "agent");
|
|
12
|
+
const profileDir = process.env.OSDY_PI_AGENT_DIR || join(home, ".pi", "osdy-agent");
|
|
13
|
+
const osdyRoot = process.env.OSDY_PI_EXTENSION_ROOT || packageRoot;
|
|
14
|
+
const gentleRoot = process.env.GENTLE_PI_EXTENSION_ROOT || undefined;
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
if (process.argv[2] === "setup" && process.argv.length !== 3)
|
|
18
|
+
throw new Error("Usage: osdy setup");
|
|
19
|
+
const result = await setupOsdyProfile({ officialDir, profileDir, osdyRoot, gentleRoot });
|
|
20
|
+
if (process.argv[2] === "setup") {
|
|
21
|
+
console.log(`Isolated Osdy profile ${result.status}: ${result.profileDir}`);
|
|
22
|
+
} else {
|
|
23
|
+
const child = spawn("pi", process.argv.slice(2), {
|
|
24
|
+
stdio: "inherit",
|
|
25
|
+
env: {
|
|
26
|
+
...process.env,
|
|
27
|
+
PI_CODING_AGENT_DIR: result.profileDir,
|
|
28
|
+
OSDY_PI_DEV_EXTENSION_ROOT: osdyRoot,
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
child.on("error", (error) => {
|
|
32
|
+
console.error(`osdy: Could not launch installed pi from PATH: ${error.message}`);
|
|
33
|
+
process.exitCode = 1;
|
|
34
|
+
});
|
|
35
|
+
child.on("exit", (code, signal) => {
|
|
36
|
+
if (signal) process.exitCode = 128 + (osConstants.signals[signal] ?? 1);
|
|
37
|
+
else process.exitCode = code ?? 1;
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
} catch (error) {
|
|
41
|
+
console.error(`osdy: ${error instanceof Error ? error.message : String(error)}`);
|
|
42
|
+
process.exitCode = 1;
|
|
43
|
+
}
|