pi-harness-runtime 0.10.0 → 1.1.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/CHANGELOG.md +22 -0
- package/README.md +122 -0
- package/harness/e2e/minimax-quota-scraper.ts +4 -4
- package/harness/e2e/openai-quota-scraper.ts +13 -8
- package/index.ts +93 -2
- package/package.json +1 -1
- package/packages/a2a-adapter/package.json +1 -1
- package/packages/auth/package.json +1 -1
- package/packages/autonomous-refactor/package.json +1 -1
- package/packages/autonomous-runtime/package.json +1 -1
- package/packages/cache-strategy/package.json +1 -1
- package/packages/capability-registry/package.json +1 -1
- package/packages/checkpoint/package.json +1 -1
- package/packages/cli-plugin-sdk/package.json +1 -1
- package/packages/clipboard/dist/src/copy-sync.d.ts +27 -0
- package/packages/clipboard/dist/src/copy-sync.d.ts.map +1 -0
- package/packages/clipboard/dist/src/copy-sync.js +170 -0
- package/packages/clipboard/dist/src/copy-sync.js.map +1 -0
- package/packages/clipboard/dist/src/gist-relay.d.ts +48 -0
- package/packages/clipboard/dist/src/gist-relay.d.ts.map +1 -0
- package/packages/clipboard/dist/src/gist-relay.js +186 -0
- package/packages/clipboard/dist/src/gist-relay.js.map +1 -0
- package/packages/clipboard/dist/src/github-login.d.ts +16 -0
- package/packages/clipboard/dist/src/github-login.d.ts.map +1 -0
- package/packages/clipboard/dist/src/github-login.js +69 -0
- package/packages/clipboard/dist/src/github-login.js.map +1 -0
- package/packages/clipboard/dist/src/index.d.ts +2 -0
- package/packages/clipboard/dist/src/index.d.ts.map +1 -1
- package/packages/clipboard/dist/src/index.js +2 -1
- package/packages/clipboard/dist/src/index.js.map +1 -1
- package/packages/clipboard/package.json +1 -1
- package/packages/clipboard/src/copy-sync.ts +201 -0
- package/packages/clipboard/src/gist-relay.ts +240 -0
- package/packages/clipboard/src/github-login.ts +107 -0
- package/packages/clipboard/src/index.ts +2 -0
- package/packages/clipboard/test/mojibake.test.mjs +143 -0
- package/packages/code-generation/package.json +1 -1
- package/packages/code-review/package.json +1 -1
- package/packages/codex-adapter/package.json +1 -1
- package/packages/context-compiler/package.json +1 -1
- package/packages/context-discovery/package.json +1 -1
- package/packages/context-manager/package.json +1 -1
- package/packages/cookie-sanitizer/package.json +1 -1
- package/packages/cost-optimizer/package.json +1 -1
- package/packages/dependency-analyzer/package.json +1 -1
- package/packages/django-plugin/package.json +1 -1
- package/packages/doc-generator/package.json +1 -1
- package/packages/evaluation-engine/package.json +1 -1
- package/packages/evaluation-runner/package.json +1 -1
- package/packages/event-bus/package.json +1 -1
- package/packages/event-store/package.json +1 -1
- package/packages/experience-replay/package.json +1 -1
- package/packages/feedback-collector/package.json +1 -1
- package/packages/framework-detector/package.json +1 -1
- package/packages/framework-plugin-sdk/package.json +1 -1
- package/packages/frappe-plugin/package.json +1 -1
- package/packages/generic-web-plugin/package.json +1 -1
- package/packages/health-monitor/package.json +1 -1
- package/packages/intent-analyzer/package.json +1 -1
- package/packages/laravel-plugin/package.json +1 -1
- package/packages/learning-engine/package.json +1 -1
- package/packages/mcp-adapter/package.json +1 -1
- package/packages/memory-engine/package.json +1 -1
- package/packages/model-registry/package.json +1 -1
- package/packages/nextjs-plugin/package.json +1 -1
- package/packages/notification/package.json +1 -1
- package/packages/observability/package.json +1 -1
- package/packages/performance-optimizer/package.json +1 -1
- package/packages/privilege-broker/package.json +1 -1
- package/packages/project-analyzer/package.json +1 -1
- package/packages/projection-engine/package.json +1 -1
- package/packages/prompt-compiler/package.json +1 -1
- package/packages/prompt-versioning/package.json +1 -1
- package/packages/provider-adapter-sdk/package.json +1 -1
- package/packages/provider-router/package.json +1 -1
- package/packages/provider-selector/package.json +1 -1
- package/packages/providers/package.json +1 -1
- package/packages/quota-manager/package.json +1 -1
- package/packages/rate-limiter/package.json +1 -1
- package/packages/react-vite-plugin/package.json +1 -1
- package/packages/release-manager/package.json +1 -1
- package/packages/requirement-compiler/package.json +1 -1
- package/packages/runtime/package.json +1 -1
- package/packages/scheduler/package.json +1 -1
- package/packages/scheduler-adapter/package.json +1 -1
- package/packages/session/package.json +1 -1
- package/packages/session-api/package.json +1 -1
- package/packages/session-export/package.json +1 -1
- package/packages/shared-context/package.json +1 -1
- package/packages/skill-registry/package.json +1 -1
- package/packages/sprint-planner/package.json +1 -1
- package/packages/subscription-engine/package.json +1 -1
- package/packages/task-compiler/package.json +1 -1
- package/packages/test-data-generator/package.json +1 -1
- package/packages/test-generator/package.json +1 -1
- package/packages/todo-bd-sync/package.json +22 -0
- package/packages/todo-bd-sync/src/detector.ts +150 -0
- package/packages/todo-bd-sync/src/extension.ts +101 -0
- package/packages/todo-bd-sync/src/index.ts +401 -0
- package/packages/todo-bd-sync/src/sync.ts +322 -0
- package/packages/todo-bd-sync/src/todo-reminder.ts +418 -0
- package/packages/todo-bd-sync/src/types.ts +137 -0
- package/packages/token-estimation/package.json +1 -1
- package/packages/token-optimizer/package.json +1 -1
- package/packages/tui/package.json +1 -1
- package/packages/types/package.json +1 -1
- package/packages/workflow-events/package.json +1 -1
- package/packages/workspace-scanner/package.json +1 -1
- package/packages/worktree/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
### [0.10.1](https://github.com/ManotLuijiu/pi-harness-runtime/compare/v0.9.24...v0.10.1) (2026-07-31)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* blackboard-coordinated loop controller with early exit ([f3cf3ea](https://github.com/ManotLuijiu/pi-harness-runtime/commit/f3cf3ea479170dd75b7e9a7c3515dde230bb0da7))
|
|
11
|
+
* herdr inter-agent event bus for autonomous code review ([1490cdd](https://github.com/ManotLuijiu/pi-harness-runtime/commit/1490cddec80dac812065c3c681984524ad3194e1))
|
|
12
|
+
* loop controller for write-review cycles with early exit ([95066ce](https://github.com/ManotLuijiu/pi-harness-runtime/commit/95066ce8cb58c55eaa14d69fd826b5aaff680c16))
|
|
13
|
+
* release adapters, stale reminder fix, tests, and bug fixes ([5fe5a26](https://github.com/ManotLuijiu/pi-harness-runtime/commit/5fe5a260e0d9a005965b43e4973cbe04a371b85e))
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### Bug Fixes
|
|
17
|
+
|
|
18
|
+
* **clipboard:** pass UTF-8 bytes directly to xclip via stdin, avoid pipeline corruption ([051ca18](https://github.com/ManotLuijiu/pi-harness-runtime/commit/051ca18fb1deb1169a8a4da16aa9314d2e6ec66d))
|
|
19
|
+
* disable todo-bd auto-reminder (Phase 1 containment) ([e1b16c1](https://github.com/ManotLuijiu/pi-harness-runtime/commit/e1b16c11e34cee8e35ec813081b17dd171671771))
|
|
20
|
+
* herdr-bus refactoring — rename publishers to *Simple variants ([d727591](https://github.com/ManotLuijiu/pi-harness-runtime/commit/d7275913a89deb56a6bcfdb912ea9d17e3a80ce1))
|
|
21
|
+
* import LoopConfig from index.js, remove unused LoopNextAction import ([1100a4e](https://github.com/ManotLuijiu/pi-harness-runtime/commit/1100a4e87433e54416259dfdad41bc5e0def19b3))
|
|
22
|
+
* periodic quota refresh every 15 minutes via setInterval ([f28e700](https://github.com/ManotLuijiu/pi-harness-runtime/commit/f28e7004d089aeada1659f4d55a35461baba76fc))
|
|
23
|
+
* replace all Unicode box-drawing characters with ASCII ([dd4223a](https://github.com/ManotLuijiu/pi-harness-runtime/commit/dd4223abb0e25f746ee09ced05f6b3e40a10eb85))
|
|
24
|
+
* replace Unicode dashes and arrows with ASCII equivalents ([e9027e6](https://github.com/ManotLuijiu/pi-harness-runtime/commit/e9027e689c06fdc1ca2ac4a6365ed6a6a0a384fd))
|
|
25
|
+
* trigger cookie sync on startup so pre-existing cookies aren't ignored ([2914299](https://github.com/ManotLuijiu/pi-harness-runtime/commit/2914299b8caa02acbb06620c7cb8e4870acfa40e))
|
|
26
|
+
|
|
5
27
|
## [0.10.0](https://github.com/ManotLuijiu/pi-harness-runtime/compare/v0.9.24...v0.10.0) (2026-07-30)
|
|
6
28
|
|
|
7
29
|
|
package/README.md
CHANGED
|
@@ -27,6 +27,76 @@ pi install npm:pi-harness-runtime
|
|
|
27
27
|
|
|
28
28
|
Requires Pi v0.37.3+.
|
|
29
29
|
|
|
30
|
+
### Headless Server Setup (herdr clipboard bridge)
|
|
31
|
+
|
|
32
|
+
If running on a **headless server** via herdr SSH, install the clipboard bridge plugin to enable copy/paste between server and local machine:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# 1. Link the plugin (already included in this package)
|
|
36
|
+
cd ~/.config/herdr/plugins
|
|
37
|
+
ln -s ~/.config/herdr/plugins/moocoding.clipboard-bridge moocoding.clipboard-bridge 2>/dev/null || true
|
|
38
|
+
|
|
39
|
+
# 2. Add keybinding to ~/.config/herdr/config.toml
|
|
40
|
+
cat >> ~/.config/herdr/config.toml << 'EOF'
|
|
41
|
+
|
|
42
|
+
[[keys.command]]
|
|
43
|
+
key = "prefix+y"
|
|
44
|
+
type = "plugin_action"
|
|
45
|
+
command = "moocoding.clipboard-bridge.copy"
|
|
46
|
+
description = "Copy selected text via bridge"
|
|
47
|
+
EOF
|
|
48
|
+
|
|
49
|
+
# 3. Reload herdr config
|
|
50
|
+
herdr server reload-config
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### todo-bd-sync (Auto Task Tracker)
|
|
54
|
+
|
|
55
|
+
Automatic two-way sync between rpiv-todo overlay and bd issue tracker.
|
|
56
|
+
|
|
57
|
+
When you use `bd` for issue tracking, this feature automatically syncs tasks.
|
|
58
|
+
|
|
59
|
+
> **Important:** `bd` is **not** implemented or bundled by `pi-harness-runtime`.
|
|
60
|
+
> It is the external **Beads CLI** from the upstream project:
|
|
61
|
+
> `https://github.com/gastownhall/beads`
|
|
62
|
+
>
|
|
63
|
+
> Install it system-wide from upstream, then initialize it in your own project:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# Install beads CLI (system-wide - don't clone this repo into your project)
|
|
67
|
+
curl -fsSL https://raw.githubusercontent.com/gastownhall/beads/main/scripts/install.sh | bash
|
|
68
|
+
|
|
69
|
+
# Initialize in YOUR project
|
|
70
|
+
cd your-project
|
|
71
|
+
bd init
|
|
72
|
+
|
|
73
|
+
# Optional: refresh or install richer instructions for your agent
|
|
74
|
+
bd setup codex # Codex CLI - installs skill, AGENTS.md guidance, and hooks
|
|
75
|
+
bd setup claude # Claude Code - installs hooks/settings
|
|
76
|
+
bd setup factory # Factory.ai Droid - creates/updates AGENTS.md
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
- Install dependencies:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
# Install rpiv-todo overlay
|
|
83
|
+
pi install npm:@juicesharp/rpiv-todo
|
|
84
|
+
|
|
85
|
+
# Verify bd is available from your upstream beads install
|
|
86
|
+
bd --version
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
- Works automatically: Just use prompts with multiple steps, and tasks sync to bd
|
|
90
|
+
- Manual commands:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
/bd-todo-sync # Force sync all mapped tasks
|
|
94
|
+
/bd-todo-status # Show sync status
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
> **Note:** Auto-reminder is **disabled by default** (bug fix for transcript growth).
|
|
98
|
+
> See [docs/todo-bd-sync.md](docs/todo-bd-sync.md) for details.
|
|
99
|
+
|
|
30
100
|
## Usage Commands
|
|
31
101
|
|
|
32
102
|
```bash
|
|
@@ -35,6 +105,8 @@ Requires Pi v0.37.3+.
|
|
|
35
105
|
/usage today # today's usage + 5h window
|
|
36
106
|
/usage week # this week's usage + lifetime totals
|
|
37
107
|
/usage reset # clear provider mirror
|
|
108
|
+
/bd-todo-sync # Force sync all mapped tasks (todo <-> bd)
|
|
109
|
+
/bd-todo-status # Show todo-bd sync status and dependencies
|
|
38
110
|
```
|
|
39
111
|
|
|
40
112
|
## Harness Commands
|
|
@@ -245,6 +317,56 @@ The runtime watches `~/.pi-harness-runtime/cookies/` for cookie files. Drop any
|
|
|
245
317
|
**Override:** set `QUOTA_COOKIE_FILE=/path/to/your/cookies.txt` to bypass the sanitizer
|
|
246
318
|
and read a specific file directly.
|
|
247
319
|
|
|
320
|
+
## herdr Integration (Clipboard Bridge)
|
|
321
|
+
|
|
322
|
+
> **⚠️ This only applies when using herdr.dev**
|
|
323
|
+
>
|
|
324
|
+
> If you're using a normal terminal (iTerm2, Terminal.app, etc.), clipboard works fine — no special setup needed.
|
|
325
|
+
|
|
326
|
+
When running on a **headless server via herdr.dev**, clipboard operations need special setup because:
|
|
327
|
+
|
|
328
|
+
- herdr's `copy_on_select` uses OSC52 which fails in VS Code's integrated terminal PTY
|
|
329
|
+
- UTF-8 box-drawing characters (`┌─┐│└`) get corrupted to garbled text
|
|
330
|
+
- Server-side clipboard tools (`xclip`, `wl-copy`) don't exist
|
|
331
|
+
|
|
332
|
+
### Quick Setup
|
|
333
|
+
|
|
334
|
+
```bash
|
|
335
|
+
# Copy the example config (includes clipboard bridge keybinding)
|
|
336
|
+
cp config.toml.example ~/.config/herdr/config.toml
|
|
337
|
+
|
|
338
|
+
# Reload herdr config
|
|
339
|
+
herdr server reload-config
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
### Usage
|
|
343
|
+
|
|
344
|
+
1. **Select text** with mouse in herdr terminal
|
|
345
|
+
2. Press **`prefix+y`** (prefix is `ctrl+b` by default)
|
|
346
|
+
3. Text is copied via the bridge to your local clipboard
|
|
347
|
+
|
|
348
|
+
### How It Works
|
|
349
|
+
|
|
350
|
+
```
|
|
351
|
+
Select text in herdr
|
|
352
|
+
↓
|
|
353
|
+
Press prefix+y (plugin action)
|
|
354
|
+
↓
|
|
355
|
+
~/.herdr-clipboard (bridge file)
|
|
356
|
+
↓
|
|
357
|
+
SSH reverse tunnel or tmux buffer
|
|
358
|
+
↓
|
|
359
|
+
Your local machine clipboard
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
### Files
|
|
363
|
+
|
|
364
|
+
| File | Purpose |
|
|
365
|
+
|------|---------|
|
|
366
|
+
| `config.toml.example` | Template for `~/.config/herdr/config.toml` |
|
|
367
|
+
| `~/.herdr-clipboard` | Bridge file between herdr and clipboard |
|
|
368
|
+
| `~/.config/herdr/plugins/moocoding.clipboard-bridge/` | herdr plugin |
|
|
369
|
+
|
|
248
370
|
### Other Providers
|
|
249
371
|
|
|
250
372
|
No setup needed. The runtime reads TUI messages and captures quota-exhaustion signals.
|
|
@@ -387,7 +387,8 @@ export class MiniMaxQuotaScraper {
|
|
|
387
387
|
} catch {
|
|
388
388
|
const msg =
|
|
389
389
|
"Playwright not installed. Install with: bun add playwright\nThen install browsers: bunx playwright install chromium";
|
|
390
|
-
if (!this.config.quiet)
|
|
390
|
+
if (!this.config.quiet)
|
|
391
|
+
console.error("[DEBUG MiniMaxQuotaScraper] " + msg);
|
|
391
392
|
throw new Error(msg);
|
|
392
393
|
}
|
|
393
394
|
|
|
@@ -399,8 +400,7 @@ export class MiniMaxQuotaScraper {
|
|
|
399
400
|
|
|
400
401
|
if (cookies.length === 0) {
|
|
401
402
|
const dropHint = join(homedir(), ".pi-harness-runtime", "cookies");
|
|
402
|
-
const msg =
|
|
403
|
-
`No cookies found.
|
|
403
|
+
const msg = `No cookies found.
|
|
404
404
|
Drop your platform.minimax.io cookies (Netscape or EditThisCookie JSON) into:
|
|
405
405
|
${dropHint}
|
|
406
406
|
…or run: bun packages/auth/src/run-minimax-auth.ts auth`;
|
|
@@ -550,7 +550,7 @@ MiniMax Quota Scraper Setup Instructions
|
|
|
550
550
|
3. Use the scraper:
|
|
551
551
|
const scraper = new MiniMaxQuotaScraper();
|
|
552
552
|
const quota = await scraper.scrape();
|
|
553
|
-
console.log("5h usage:", quota.h5UsedPct, "%");
|
|
553
|
+
console.log("[DEBUG MiniMaxQuotaScraper] 5h usage:", quota.h5UsedPct, "%");
|
|
554
554
|
`;
|
|
555
555
|
}
|
|
556
556
|
}
|
|
@@ -205,13 +205,14 @@ export class OpenAIQuotaScraper {
|
|
|
205
205
|
Drop your chatgpt.com cookies (Netscape or EditThisCookie JSON) into:
|
|
206
206
|
${dropHint}
|
|
207
207
|
Then run: bun run packages/cookie-sanitizer/src/sync.ts`;
|
|
208
|
-
if (!this.config.quiet)
|
|
208
|
+
if (!this.config.quiet)
|
|
209
|
+
console.error(`[DEBUG OpenAIQuotaScraper] ${msg}`);
|
|
209
210
|
throw new Error(msg);
|
|
210
211
|
}
|
|
211
212
|
|
|
212
213
|
// Launch browser
|
|
213
214
|
if (!this.config.quiet) {
|
|
214
|
-
console.log("[OpenAIQuotaScraper] Launching browser...");
|
|
215
|
+
console.log("[DEBUG OpenAIQuotaScraper] Launching browser...");
|
|
215
216
|
}
|
|
216
217
|
|
|
217
218
|
const browser = await chromium.launch({
|
|
@@ -259,7 +260,9 @@ Then run: bun run packages/cookie-sanitizer/src/sync.ts`;
|
|
|
259
260
|
try {
|
|
260
261
|
// Navigate to analytics page
|
|
261
262
|
if (!this.config.quiet) {
|
|
262
|
-
console.log(
|
|
263
|
+
console.log(
|
|
264
|
+
"[DEBUG OpenAIQuotaScraper] Navigating to analytics page...",
|
|
265
|
+
);
|
|
263
266
|
}
|
|
264
267
|
|
|
265
268
|
await page.goto(ANALYTICS_URL, {
|
|
@@ -282,14 +285,16 @@ Then run: bun run packages/cookie-sanitizer/src/sync.ts`;
|
|
|
282
285
|
if (currentUrl.includes("login") || currentUrl.includes("auth")) {
|
|
283
286
|
const msg =
|
|
284
287
|
"OpenAI cookies are expired or insufficient. Please re-export cookies from chatgpt.com.";
|
|
285
|
-
if (!this.config.quiet)
|
|
288
|
+
if (!this.config.quiet)
|
|
289
|
+
console.error("[DEBUG OpenAIQuotaScraper] " + msg);
|
|
286
290
|
throw new Error(msg);
|
|
287
291
|
}
|
|
288
292
|
|
|
289
293
|
// Parse the usage data from the captured API response
|
|
290
294
|
if (!usageData) {
|
|
291
295
|
const msg = "Failed to capture usage data from API";
|
|
292
|
-
if (!this.config.quiet)
|
|
296
|
+
if (!this.config.quiet)
|
|
297
|
+
console.error("[DEBUG OpenAIQuotaScraper] " + msg);
|
|
293
298
|
throw new Error(msg);
|
|
294
299
|
}
|
|
295
300
|
|
|
@@ -306,7 +311,7 @@ Then run: bun run packages/cookie-sanitizer/src/sync.ts`;
|
|
|
306
311
|
|
|
307
312
|
if (!this.config.quiet) {
|
|
308
313
|
console.log(
|
|
309
|
-
`[OpenAIQuotaScraper] Weekly usage: ${weeklyUsedPct}%, resets in ${weeklyResetsAt}`,
|
|
314
|
+
`[DEBUG OpenAIQuotaScraper] Weekly usage: ${weeklyUsedPct}%, resets in ${weeklyResetsAt}`,
|
|
310
315
|
);
|
|
311
316
|
}
|
|
312
317
|
|
|
@@ -349,7 +354,7 @@ Then run: bun run packages/cookie-sanitizer/src/sync.ts`;
|
|
|
349
354
|
if (!response.ok) {
|
|
350
355
|
if (!this.config.quiet) {
|
|
351
356
|
console.log(
|
|
352
|
-
`[OpenAIQuotaScraper] Direct API failed: ${response.status}`,
|
|
357
|
+
`[DEBUG OpenAIQuotaScraper] Direct API failed: ${response.status}`,
|
|
353
358
|
);
|
|
354
359
|
}
|
|
355
360
|
return null;
|
|
@@ -374,7 +379,7 @@ Then run: bun run packages/cookie-sanitizer/src/sync.ts`;
|
|
|
374
379
|
} catch (error) {
|
|
375
380
|
if (!this.config.quiet) {
|
|
376
381
|
console.warn(
|
|
377
|
-
"[OpenAIQuotaScraper] Direct API error:",
|
|
382
|
+
"[DEBUG OpenAIQuotaScraper] Direct API error:",
|
|
378
383
|
error instanceof Error ? error.message : String(error),
|
|
379
384
|
);
|
|
380
385
|
}
|
package/index.ts
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
* Runs directly from Bun.
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
+
import { Key } from "@earendil-works/pi-tui";
|
|
16
17
|
import type {
|
|
17
18
|
CompactOptions,
|
|
18
19
|
ExtensionAPI,
|
|
@@ -39,6 +40,8 @@ import {
|
|
|
39
40
|
} from "./packages/quota-manager/src/tui-usage-monitor.ts";
|
|
40
41
|
import { QuotaManager } from "./packages/quota-manager/src/quota-manager.ts";
|
|
41
42
|
import { buildFooterStatusValue } from "./footer-status.ts";
|
|
43
|
+
import { registerGithubLoginCommand } from "./packages/clipboard/src/github-login.js";
|
|
44
|
+
import { registerCopySyncShortcut } from "./packages/clipboard/src/copy-sync.js";
|
|
42
45
|
import {
|
|
43
46
|
MAX_PROACTIVE_COMPACT_FAILURES,
|
|
44
47
|
OUTPUT_LIMIT_RESUME_PROMPT,
|
|
@@ -64,6 +67,17 @@ import {
|
|
|
64
67
|
createBlackboard,
|
|
65
68
|
} from "./harness/blackboard.ts";
|
|
66
69
|
import { scheduleAutoResume, cancelAutoResume } from "./harness/index.js";
|
|
70
|
+
|
|
71
|
+
// --- todo-bd-sync: Two-way sync between rpiv-todo and bd --------------------
|
|
72
|
+
// Lazy import - only loads when packages/todo-bd-sync exists
|
|
73
|
+
async function initTodoBdSync(pi: ExtensionAPI): Promise<void> {
|
|
74
|
+
try {
|
|
75
|
+
const mod = await import("./packages/todo-bd-sync/src/extension.js");
|
|
76
|
+
mod.registerTodoBdSync(pi, { debug: false });
|
|
77
|
+
} catch {
|
|
78
|
+
// todo-bd-sync not available
|
|
79
|
+
}
|
|
80
|
+
}
|
|
67
81
|
import { homedir } from "node:os";
|
|
68
82
|
import { appendFileSync, existsSync, mkdirSync } from "node:fs";
|
|
69
83
|
import { join } from "node:path";
|
|
@@ -211,6 +225,31 @@ export default function (pi: ExtensionAPI) {
|
|
|
211
225
|
const mirrorStore = new MirrorStore();
|
|
212
226
|
ensureHarnessDir();
|
|
213
227
|
|
|
228
|
+
// --- todo-bd-sync: Initialize two-way sync with bd ---------------
|
|
229
|
+
// Start async init but don't await - runs in background
|
|
230
|
+
void initTodoBdSync(pi);
|
|
231
|
+
|
|
232
|
+
// --- Auto-Invoke rpiv-todo via System Prompt ------------------------
|
|
233
|
+
// This makes the todo overlay ALWAYS activate at session start
|
|
234
|
+
const AUTO_TODO_INVOKE_HINT = `
|
|
235
|
+
|
|
236
|
+
You have access to a todo tool that shows a persistent task overlay.
|
|
237
|
+
ALWAYS use it at the START of every session to capture user requirements as tasks.
|
|
238
|
+
When the user gives you a multi-step task:
|
|
239
|
+
1. Immediately create todo items for each step using the todo tool
|
|
240
|
+
2. Keep tasks updated - mark in_progress when working, completed when done
|
|
241
|
+
3. When a task is completed, continue to the next or ask the user
|
|
242
|
+
|
|
243
|
+
The todo overlay persists and helps track progress across your conversation.
|
|
244
|
+
`;
|
|
245
|
+
let firstAgentStart = true;
|
|
246
|
+
pi.on("before_agent_start", async (event) => {
|
|
247
|
+
if (firstAgentStart) {
|
|
248
|
+
event.systemPrompt += AUTO_TODO_INVOKE_HINT;
|
|
249
|
+
firstAgentStart = false;
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
|
|
214
253
|
// --- Auto-track every assistant message ------------------------------
|
|
215
254
|
pi.on("message_end", async (event, ctx) => {
|
|
216
255
|
if (isOutputLimitResumePromptMessage(event.message)) {
|
|
@@ -288,7 +327,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
288
327
|
|
|
289
328
|
// --- Smart quota fetch for OpenAI status -------------------------
|
|
290
329
|
const OPENAI_REFRESH_MIN_INTERVAL_MS = 5 * 60 * 1000; // 5 minutes
|
|
291
|
-
const _openaiQuotaScraper = new OpenAIQuotaScraper();
|
|
330
|
+
const _openaiQuotaScraper = new OpenAIQuotaScraper({ quiet: true });
|
|
292
331
|
let lastOpenAIQuotaFetchAt = 0;
|
|
293
332
|
|
|
294
333
|
// --- Cookie sanitizer integration ------------------------------------
|
|
@@ -343,6 +382,8 @@ export default function (pi: ExtensionAPI) {
|
|
|
343
382
|
}
|
|
344
383
|
});
|
|
345
384
|
|
|
385
|
+
let lastQuotaAutoFetchAt = 0;
|
|
386
|
+
|
|
346
387
|
// Live watcher — sanitises on every change in the drop folder.
|
|
347
388
|
const cookieWatcher = new CookieWatcher({
|
|
348
389
|
dropDir: cookieDropDir,
|
|
@@ -369,6 +410,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
369
410
|
}
|
|
370
411
|
},
|
|
371
412
|
});
|
|
413
|
+
|
|
372
414
|
try {
|
|
373
415
|
cookieWatcher.start();
|
|
374
416
|
// Sync existing drop-folder cookies now (ignoreInitial: true means
|
|
@@ -396,7 +438,6 @@ export default function (pi: ExtensionAPI) {
|
|
|
396
438
|
let footerStatusCtx: {
|
|
397
439
|
ui: { setStatus: (key: string, value: string) => void };
|
|
398
440
|
} | null = null;
|
|
399
|
-
let lastQuotaAutoFetchAt = 0;
|
|
400
441
|
let quotaAutoFetchInFlight = false;
|
|
401
442
|
let proactiveCompactInFlight = false;
|
|
402
443
|
let lastProactiveCompactAt = 0;
|
|
@@ -406,6 +447,49 @@ export default function (pi: ExtensionAPI) {
|
|
|
406
447
|
let pendingOutputLimitResumeAfterCompact = false;
|
|
407
448
|
let pendingOutputLimitResumeAfterSettled = false;
|
|
408
449
|
|
|
450
|
+
// --- Context-usage escalating warning tiers -----------------------------
|
|
451
|
+
// Amber at 75%, red at 85%. No notify above 90% (proactive compact handles it).
|
|
452
|
+
// Per-session dedup: only notify when crossing INTO a new higher tier.
|
|
453
|
+
const TIER_WARNING = 0.75; // amber
|
|
454
|
+
const TIER_ERROR = 0.85; // red
|
|
455
|
+
let lastNotifiedTier: "none" | "warning" | "error" = "none";
|
|
456
|
+
|
|
457
|
+
function maybeNotifyContextUsage(ctx: ExtensionContext): void {
|
|
458
|
+
const usage = ctx.getContextUsage();
|
|
459
|
+
const pct = usage?.percent;
|
|
460
|
+
if (pct === null || pct === undefined) return;
|
|
461
|
+
if (pct >= 0.9) return; // proactive compact handles 90%+
|
|
462
|
+
|
|
463
|
+
const tier: "none" | "warning" | "error" =
|
|
464
|
+
pct >= TIER_ERROR ? "error" : pct >= TIER_WARNING ? "warning" : "none";
|
|
465
|
+
|
|
466
|
+
// Only notify when crossing into a strictly higher tier
|
|
467
|
+
if (tier === "none") {
|
|
468
|
+
lastNotifiedTier = "none";
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
if (
|
|
472
|
+
tier === "warning" &&
|
|
473
|
+
lastNotifiedTier !== "warning" &&
|
|
474
|
+
lastNotifiedTier !== "error"
|
|
475
|
+
) {
|
|
476
|
+
lastNotifiedTier = "warning";
|
|
477
|
+
ctx.ui.notify(
|
|
478
|
+
`Context at ${Math.round(pct * 100)}% — consider condensing`,
|
|
479
|
+
"info",
|
|
480
|
+
);
|
|
481
|
+
return;
|
|
482
|
+
}
|
|
483
|
+
if (tier === "error" && lastNotifiedTier !== "error") {
|
|
484
|
+
lastNotifiedTier = "error";
|
|
485
|
+
ctx.ui.notify(
|
|
486
|
+
`Context at ${Math.round(pct * 100)}% — approaching limit`,
|
|
487
|
+
"warning",
|
|
488
|
+
);
|
|
489
|
+
return;
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
|
|
409
493
|
function writeMirrorRecord(
|
|
410
494
|
provider: ProviderId,
|
|
411
495
|
record: Omit<import("./mirror.js").ProviderMirrorRecord, "provider">,
|
|
@@ -818,6 +902,12 @@ export default function (pi: ExtensionAPI) {
|
|
|
818
902
|
},
|
|
819
903
|
});
|
|
820
904
|
|
|
905
|
+
// --- /github-login — Connect GitHub Gist for clipboard sync ------------
|
|
906
|
+
registerGithubLoginCommand(pi);
|
|
907
|
+
|
|
908
|
+
// --- Ctrl+Shift+C — Copy to clipboard + sync to Gist ------------
|
|
909
|
+
registerCopySyncShortcut(pi, Key);
|
|
910
|
+
|
|
821
911
|
// --- /harness start — Start a new harness job ----------------------
|
|
822
912
|
pi.registerCommand("harness-start", {
|
|
823
913
|
description: "Start a new harness job: /harness start <requirement>",
|
|
@@ -1117,6 +1207,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
1117
1207
|
);
|
|
1118
1208
|
void maybeAutoFetchQuota(ctx.model?.id ?? null);
|
|
1119
1209
|
maybeTriggerProactiveCompact(ctx);
|
|
1210
|
+
maybeNotifyContextUsage(ctx);
|
|
1120
1211
|
});
|
|
1121
1212
|
|
|
1122
1213
|
pi.on("agent_end", () => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-harness/capability-registry",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Capability Registry for pi-harness-runtime — tracks model capabilities and enables capability-based routing",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copy + Sync — Ctrl+Shift+C shortcut for clipboard sync
|
|
3
|
+
*
|
|
4
|
+
* Registers a keyboard shortcut that:
|
|
5
|
+
* 1. Reads selected text from clipboard (Xvfb/X11 on headless server)
|
|
6
|
+
* 2. Writes to bridge file for terminal paste
|
|
7
|
+
* 3. POSTs to GitHub Gist for cross-device sync
|
|
8
|
+
*
|
|
9
|
+
* Only fires on explicit Ctrl+Shift+C — NOT on auto-select/highlight.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Read selected text, write to bridge, sync to Gist.
|
|
13
|
+
* Called by the Ctrl+Shift+C shortcut handler.
|
|
14
|
+
*/
|
|
15
|
+
export declare function copyAndSync(ctx: {
|
|
16
|
+
ui: {
|
|
17
|
+
notify: (msg: string, type?: string) => void;
|
|
18
|
+
};
|
|
19
|
+
}): Promise<void>;
|
|
20
|
+
type AnyPi = any;
|
|
21
|
+
/**
|
|
22
|
+
* Register Ctrl+Shift+C as the copy+sync shortcut.
|
|
23
|
+
* The Key.ctrlShift("c") syntax comes from @earendil-works/pi-tui.
|
|
24
|
+
*/
|
|
25
|
+
export declare function registerCopySyncShortcut(pi: AnyPi, Key: AnyPi): void;
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=copy-sync.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copy-sync.d.ts","sourceRoot":"","sources":["../../src/copy-sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AA6HH;;;GAGG;AACH,wBAAsB,WAAW,CAAC,GAAG,EAAE;IACtC,EAAE,EAAE;QAAE,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE,CAAC;CACrD,GAAG,OAAO,CAAC,IAAI,CAAC,CAoChB;AAKD,KAAK,KAAK,GAAG,GAAG,CAAC;AAEjB;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,GAAG,IAAI,CAapE"}
|