@trevonistrevon/pi-loop 0.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/AGENTS.md ADDED
@@ -0,0 +1,79 @@
1
+ # pi-loop Development Guidelines
2
+
3
+ ## Overview
4
+ `pi-loop` is a pi extension providing cron/event-based agent re-wake loops and background process monitoring. Modeled after Claude Code's `/loop`, `CronCreate`, and `MonitorCreate` tools.
5
+
6
+ ## Stack
7
+ - TypeScript 6.x (strict, ES2022 target, bundler module resolution)
8
+ - `typebox` for tool parameter validation
9
+ - `vitest` for tests
10
+ - `biome` for linting (linter: on, formatter: off)
11
+ - npm packaging as `@trevonistrevon/pi-loop`
12
+
13
+ ## Architecture
14
+ ```
15
+ src/
16
+ ├── index.ts # Extension entry: 6 tools + /loop /loops commands + widget
17
+ ├── types.ts # LoopKind, Trigger spec, LoopEntry, MonitorEntry, LoopConfig
18
+ ├── store.ts # File-backed CRUD (.pi/loops/loops.json) with file locking
19
+ ├── scheduler.ts # Timer-based cron scheduler with jitter + 7-day expiry
20
+ ├── trigger-system.ts # Unified trigger engine: cron timers + pi event subscriptions + hybrid
21
+ ├── monitor-manager.ts # ChildProcess tracking, output buffering, event emission, stop
22
+ ├── loop-parse.ts # Human interval → cron expression, next-fire computation, jitter
23
+ └── ui/
24
+ └── widget.ts # Persistent widget: active loops + monitors
25
+ ```
26
+
27
+ ## Conventions (mirror pi-tasks)
28
+ - No comments unless answering "why", never "what"
29
+ - `debug(...)` helper gated on `PI_LOOP_DEBUG` env var, logs to stderr
30
+ - `textResult(msg)` helper for uniform tool output
31
+ - All tool params use `Type.Object()` with description strings
32
+ - Tool descriptions follow Claude Code format: `## When to Use`, `## When NOT to Use`
33
+ - Cross-extension communication via `pi.events` with `requestId` + reply channels
34
+ - File-backed stores use atomic write (write tmp → rename) + pid-based file locking
35
+ - Widget uses `UICtx.setWidget()` with `render()` callback pattern
36
+ - Tests co-located in `test/`, named `<module>.test.ts`
37
+
38
+ ## File Locking Pattern
39
+ Copy TaskStore from pi-tasks: `O_EXCL` lockfile, stale PID detection, `LOCK_RETRY_MS`/`LOCK_MAX_RETRIES`
40
+
41
+ ## Trigger Types
42
+ Three trigger types, all stored as `LoopEntry.trigger`:
43
+ - `{ type: "cron", schedule: "*/5 * * * *" }` — timer-based
44
+ - `{ type: "event", source: "tool_execution_start", filter?: "regex:..." | '{"key":"value"}' }` — eventbus-based
45
+ - `{ type: "hybrid", cron: "...", event: { source, filter? }, debounceMs: 30000 }` — both with debounce
46
+
47
+ ## Re-wake via System Reminder
48
+ When a loop fires, the scheduler calls `onLoopFire()` which emits `pi.events("loop:fire", ...)`. The extension's listener queues a reminder. On the next `tool_result` event, the reminder is injected as `<system-reminder>` text (mirroring pi-tasks' pattern):
49
+ ```
50
+ <system-reminder>
51
+ Scheduled loop "deploy check" fired. Trigger: schedule: */5 * * * *.
52
+ [loop:abc12345]
53
+ </system-reminder>
54
+ ```
55
+
56
+ ## Monitor Streaming via PI Events
57
+ Monitor stdout/stderr lines are emitted as `pi.events("monitor:output", { monitorId, line, timestamp })`. Tool consumers subscribe to these events. Completion emits `"monitor:done"` / `"monitor:error"`.
58
+
59
+ ## pi-tasks Integration
60
+ When `@tintinweb/pi-tasks` is present, `LoopCreate` with `autoTask: true` fires an RPC to create a task. Communication via `pi.events`:
61
+ - `tasks:rpc:ping` on init → detect pi-tasks presence
62
+ - `tasks:ready` listener → late-binding detection
63
+ - `tasks:rpc:create` → auto-create task when loop fires (if `autoTask: true`)
64
+
65
+ ## /loop Self-Paced Mode
66
+ When no interval is specified in `/loop prompt`, the loop runs in self-paced mode. The agent receives the prompt, acts on it, and uses `LoopCreate`/`LoopUpdate` to schedule the next iteration. The loop fires once, then the agent decides the next interval dynamically (matching Claude Code's dynamic interval behavior).
67
+
68
+ ## Testing
69
+ - `vitest` with `describe`/`it` blocks
70
+ - In-memory stores for unit tests, `tmpdir` for file-backed tests
71
+ - Fake timers (`vi.useFakeTimers`) for scheduler tests
72
+ - Mock pi eventbus for monitor-manager tests
73
+ - `vitest run` in CI, `vitest` for watch mode
74
+
75
+ ## Limits
76
+ - Maximum 25 active loops
77
+ - Maximum 25 running monitors
78
+ - 7-day expiry on recurring loops
79
+ - 5-minute default cron interval for self-paced mode
package/CHANGELOG.md ADDED
@@ -0,0 +1,39 @@
1
+ # Changelog
2
+
3
+ ## [0.1.0] — Initial Release
4
+
5
+ ### Tools
6
+
7
+ - **LoopCreate** — Create scheduled (cron), event-triggered, or hybrid re-wake loops
8
+ - **LoopList** — List all active loops with IDs, triggers, status, and next-fire times
9
+ - **LoopDelete** — Delete or pause a loop by ID
10
+ - **MonitorCreate** — Start a background command that streams output via `monitor:output` pi events
11
+ - **MonitorList** — List monitoring processes and their status
12
+ - **MonitorStop** — Stop a running monitor (SIGTERM → 5s → SIGKILL)
13
+
14
+ ### Commands
15
+
16
+ - **`/loop [interval] [prompt]`** — Interactive TUI loop creation
17
+ - **`/loops`** — View, create, cancel, and configure loops
18
+
19
+ ### Features
20
+
21
+ - Three trigger types: cron (timer), event (eventbus), hybrid (both with debounce)
22
+ - File-backed persistence with pid-based file locking and atomic writes
23
+ - Cron scheduler with per-loop jitter and 7-day expiry
24
+ - Background process monitoring with stdout/stderr streaming
25
+ - Persistent TUI widget showing active loops and monitors
26
+ - System-reminder injection for loop fires (mirrors pi-tasks pattern)
27
+ - Self-paced loop mode for dynamic interval scheduling
28
+ - `@tintinweb/pi-tasks` integration with auto-task creation
29
+
30
+ ### Configuration
31
+
32
+ - `PI_LOOP` env var for store path override / disable
33
+ - `PI_LOOP_SCOPE` env var for `memory` | `session` | `project`
34
+ - `PI_LOOP_DEBUG` env var for debug logging
35
+
36
+ ### Limits
37
+
38
+ - Maximum 25 active loops
39
+ - Maximum 25 running monitors
@@ -0,0 +1,69 @@
1
+ # Contributing to @trevonistrevon/pi-loop
2
+
3
+ Thanks for contributing! This document covers local dev setup, conventions, and workflow.
4
+
5
+ ## Getting Started
6
+
7
+ ```bash
8
+ git clone https://github.com/trevonistrevon/pi-loop.git
9
+ cd pi-loop
10
+ npm install
11
+ ```
12
+
13
+ ## Scripts
14
+
15
+ | Command | Description |
16
+ |---|---|
17
+ | `npm run typecheck` | TypeScript type checking (`tsc --noEmit`) |
18
+ | `npm run lint` | Lint with Biome |
19
+ | `npm run lint:fix` | Auto-fix lint issues |
20
+ | `npm test` | Run tests (`vitest run`) |
21
+ | `npm run test:watch` | Watch mode |
22
+ | `npm run build` | Compile TypeScript |
23
+
24
+ ## Architecture
25
+
26
+ See `AGENTS.md` for the full architecture overview. Key modules:
27
+
28
+ - **`src/index.ts`** — Extension entry: registers 6 tools + `/loop` `/loops` commands + widget lifecycle
29
+ - **`src/types.ts`** — Core types: `LoopEntry`, `MonitorEntry`, `Trigger` variants
30
+ - **`src/store.ts`** — File-backed CRUD with pid-based file locking (atomic write → rename)
31
+ - **`src/scheduler.ts`** — Timer-based cron scheduler with per-loop jitter and 7-day expiry
32
+ - **`src/trigger-system.ts`** — Unified engine: cron timers + pi event subscriptions + hybrid debounce
33
+ - **`src/monitor-manager.ts`** — `ChildProcess` wrapper: stdout/stderr streaming as pi events
34
+ - **`src/loop-parse.ts`** — Human interval parsing (`5m` → cron), cron matching, next-fire computation
35
+ - **`src/ui/widget.ts`** — TUI widget rendering active loops + monitors above the editor
36
+
37
+ ## Conventions
38
+
39
+ - **TypeScript 6.x** strict mode, ES2022 target, bundler module resolution
40
+ - **No comments unless answering "why"** — never "what"
41
+ - **`debug(...)`** helper gated on `PI_LOOP_DEBUG` env var, logs to stderr
42
+ - **`textResult(msg)`** helper for uniform tool output strings
43
+ - **Tool params** use `Type.Object()` with description strings from `typebox`
44
+ - **File-backed stores** use atomic write (write tmp → rename) + pid-based file locking
45
+
46
+ ## Testing
47
+
48
+ Tests are co-located in `test/` as `<module>.test.ts`. The suite uses:
49
+
50
+ - **vitest** with `describe`/`it`
51
+ - In-memory stores for unit tests
52
+ - `tmpdir` for file-backed store tests
53
+ - `vi.useFakeTimers()` for scheduler tests
54
+ - Mocked pi eventbus for monitor-manager tests
55
+
56
+ ```bash
57
+ npm test # Run once
58
+ npm run test:watch # Watch mode
59
+ ```
60
+
61
+ ## Pull Request Workflow
62
+
63
+ 1. Fork, branch, implement
64
+ 2. Ensure `npm run typecheck`, `npm run lint`, and `npm test` all pass
65
+ 3. Open PR against `main`
66
+
67
+ ## License
68
+
69
+ By contributing, you agree that your contributions will be licensed under the MIT License.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 trevonistrevon
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,82 @@
1
+ <p align="center">
2
+ <h1 align="center">@trevonistrevon/pi-loop</h1>
3
+ <h6 align="center">Cron and event loops for the pi coding agent. Background monitors, scheduled re-wakes, pi-tasks integration.</h6>
4
+ </p>
5
+
6
+ ## Install
7
+
8
+ ```bash
9
+ pi install @trevonistrevon/pi-loop
10
+ ```
11
+
12
+ ## Quick start
13
+
14
+ ```
15
+ LoopCreate trigger="5m" prompt="Check if the build passed"
16
+ LoopCreate trigger="tool_execution_start" prompt="Log the tool being used" triggerType="event"
17
+ LoopList
18
+ LoopDelete id="1"
19
+ ```
20
+
21
+ ```
22
+ MonitorCreate command="tail -n0 -f build.log" description="Watch build"
23
+ MonitorList
24
+ MonitorStop monitorId="1"
25
+ ```
26
+
27
+ ## Commands
28
+
29
+ `/loop [interval] [prompt]` — interactive loop creation.
30
+
31
+ ```
32
+ /loop # menu
33
+ /loop 5m check the deploy # 5-minute cron loop
34
+ ```
35
+
36
+ ## Tools
37
+
38
+ | Tool | What it does |
39
+ |---|---|
40
+ | `LoopCreate` | Schedule a prompt on a cron timer, a pi event, or both with debounce |
41
+ | `LoopList` | Show active loops with IDs, triggers, and next-fire times |
42
+ | `LoopDelete` | Delete or pause a loop |
43
+ | `MonitorCreate` | Run a background command, stream output as `monitor:output` events |
44
+ | `MonitorList` | Show monitors with status, uptime, and output line count |
45
+ | `MonitorStop` | Stop a monitor (SIGTERM → 5s → SIGKILL) |
46
+
47
+ Trigger types: `cron` (`5m`, `1h`, `0 9 * * 1-5`), `event` (any pi event source), or `hybrid` (both, debounced).
48
+
49
+ ## pi-tasks
50
+
51
+ Works with [@tintinweb/pi-tasks](https://github.com/tintinweb/pi-tasks). Pass `autoTask: true` on `LoopCreate` and each loop fire auto-creates a tracked task. Detection happens over pi's event bus — no manual wiring.
52
+
53
+ ## Widget
54
+
55
+ Active loops and monitors show in a persistent TUI widget above the editor.
56
+
57
+ ## Configuration
58
+
59
+ | Variable | Effect | Default |
60
+ |---|---|---|
61
+ | `PI_LOOP` | Store path. `off` to disable, absolute or project-relative path | `.pi/loops/loops.json` |
62
+ | `PI_LOOP_SCOPE` | `memory` (ephemeral), `session` (per-session file), `project` (shared) | `session` |
63
+ | `PI_LOOP_DEBUG` | Debug logging to stderr | unset |
64
+
65
+ ## Limits
66
+
67
+ 25 active loops, 25 running monitors. Recurring loops expire after 7 days.
68
+
69
+ ## Development
70
+
71
+ ```bash
72
+ npm run typecheck
73
+ npm run lint
74
+ npm test
75
+ npm run build
76
+ ```
77
+
78
+ See [CONTRIBUTING.md](./CONTRIBUTING.md).
79
+
80
+ ## License
81
+
82
+ MIT — [LICENSE](./LICENSE)
@@ -0,0 +1,17 @@
1
+ /**
2
+ * @trevonistrevon/pi-loop — A pi extension providing cron/event-based agent re-wake loops and background process monitoring.
3
+ *
4
+ * Tools:
5
+ * LoopCreate — Create a scheduled or event-triggered re-wake loop
6
+ * LoopList — List all active loops with status and next-fire times
7
+ * LoopDelete — Delete or pause a loop by ID
8
+ * MonitorCreate — Start a background command that streams output via pi events
9
+ * MonitorList — List running monitors
10
+ * MonitorStop — Stop a running monitor
11
+ *
12
+ * Commands:
13
+ * /loop — Schedule a re-wake loop: /loop [interval] [prompt]
14
+ * /loops — Interactive menu: view, create, cancel, settings
15
+ */
16
+ import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
17
+ export default function (pi: ExtensionAPI): void;