@trevonistrevon/pi-loop 0.5.8 → 0.6.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/.release-please-manifest.json +3 -0
- package/AGENTS.md +52 -12
- package/CHANGELOG.md +59 -0
- package/CONTRIBUTING.md +13 -3
- package/Dockerfile +17 -0
- package/README.md +47 -0
- package/coverage/coverage-final.json +35 -31
- package/coverage/index.html +64 -49
- package/coverage/src/api.ts.html +193 -0
- package/coverage/src/commands/index.html +32 -32
- package/coverage/src/commands/loop-command.ts.html +170 -170
- package/coverage/src/commands/tasks-command.ts.html +135 -135
- package/coverage/src/coordinator.ts.html +26 -26
- package/coverage/src/index.html +61 -106
- package/coverage/src/index.ts.html +280 -94
- package/coverage/src/loop-parse.ts.html +90 -57
- package/coverage/src/loop-reducer.ts.html +25 -25
- package/coverage/src/monitor-completion-coordinator.ts.html +1 -1
- package/coverage/src/monitor-manager.ts.html +95 -71
- package/coverage/src/monitor-reducer.ts.html +15 -15
- package/coverage/src/notification-reducer.ts.html +7 -7
- package/coverage/src/reducer-backed-store.ts.html +57 -57
- package/coverage/src/rpc/channels.ts.html +376 -0
- package/coverage/src/rpc/cross-extension-rpc.ts.html +541 -0
- package/coverage/src/rpc/index.html +131 -0
- package/coverage/src/runtime/index.html +89 -29
- package/coverage/src/{goal-coordinator.ts.html → runtime/loop-events.ts.html} +79 -73
- package/coverage/src/runtime/monitor-ondone-runtime.ts.html +5 -5
- package/coverage/src/runtime/native-task-rpc.ts.html +502 -0
- package/coverage/src/runtime/notification-runtime.ts.html +14 -14
- package/coverage/src/runtime/scope.ts.html +17 -17
- package/coverage/src/runtime/session-runtime.ts.html +40 -40
- package/coverage/src/runtime/task-backlog-runtime.ts.html +66 -24
- package/coverage/src/runtime/task-events.ts.html +208 -0
- package/coverage/src/runtime/task-mutations.ts.html +394 -0
- package/coverage/src/runtime/task-rpc.ts.html +106 -118
- package/coverage/src/scheduler.ts.html +12 -12
- package/coverage/src/store.ts.html +20 -20
- package/coverage/src/task-backlog-coordinator.ts.html +8 -8
- package/coverage/src/task-reducer.ts.html +42 -42
- package/coverage/src/task-store.ts.html +49 -49
- package/coverage/src/tools/index.html +39 -24
- package/coverage/src/tools/loop-tools.ts.html +12 -21
- package/coverage/src/tools/monitor-tools.ts.html +12 -21
- package/coverage/src/tools/native-task-tools.ts.html +52 -94
- package/coverage/src/tools/tool-result.ts.html +97 -0
- package/coverage/src/trigger-system.ts.html +12 -12
- package/coverage/src/ui/index.html +1 -1
- package/coverage/src/ui/widget.ts.html +23 -23
- package/dist/api.d.ts +11 -0
- package/dist/api.js +10 -0
- package/dist/commands/loop-command.js +2 -2
- package/dist/commands/tasks-command.js +3 -3
- package/dist/coordinator.d.ts +1 -1
- package/dist/index.js +80 -20
- package/dist/loop-parse.js +14 -5
- package/dist/monitor-manager.d.ts +4 -1
- package/dist/monitor-manager.js +5 -3
- package/dist/reducer-backed-store.d.ts +1 -1
- package/dist/reducer-backed-store.js +1 -1
- package/dist/rpc/channels.d.ts +73 -0
- package/dist/rpc/channels.js +30 -0
- package/dist/rpc/cross-extension-rpc.d.ts +59 -0
- package/dist/rpc/cross-extension-rpc.js +117 -0
- package/dist/runtime/loop-events.d.ts +26 -0
- package/dist/runtime/loop-events.js +26 -0
- package/dist/runtime/native-task-rpc.d.ts +22 -0
- package/dist/runtime/native-task-rpc.js +50 -0
- package/dist/runtime/task-backlog-runtime.d.ts +3 -0
- package/dist/runtime/task-backlog-runtime.js +4 -1
- package/dist/runtime/task-mutations.d.ts +39 -0
- package/dist/runtime/task-mutations.js +68 -0
- package/dist/runtime/task-rpc.d.ts +4 -0
- package/dist/runtime/task-rpc.js +40 -58
- package/dist/scheduler.js +1 -1
- package/dist/tools/loop-tools.js +1 -3
- package/dist/tools/monitor-tools.js +1 -3
- package/dist/tools/native-task-tools.d.ts +2 -6
- package/dist/tools/native-task-tools.js +25 -55
- package/dist/tools/tool-result.d.ts +8 -0
- package/dist/tools/tool-result.js +4 -0
- package/docker-compose.yml +12 -0
- package/docs/architecture/state-machine-migration.md +0 -44
- package/docs/architecture/state-machine-reducer-event-model.md +2 -3
- package/package.json +6 -1
- package/release-please-config.json +9 -0
- package/src/api.ts +36 -0
- package/src/commands/loop-command.ts +2 -2
- package/src/commands/tasks-command.ts +3 -3
- package/src/coordinator.ts +1 -1
- package/src/index.ts +84 -22
- package/src/loop-parse.ts +18 -7
- package/src/monitor-manager.ts +11 -3
- package/src/reducer-backed-store.ts +3 -3
- package/src/rpc/channels.ts +97 -0
- package/src/rpc/cross-extension-rpc.ts +152 -0
- package/src/runtime/loop-events.ts +60 -0
- package/src/runtime/native-task-rpc.ts +139 -0
- package/src/runtime/task-backlog-runtime.ts +14 -0
- package/src/runtime/task-mutations.ts +103 -0
- package/src/runtime/task-rpc.ts +48 -54
- package/src/scheduler.ts +1 -1
- package/src/tools/loop-tools.ts +1 -4
- package/src/tools/monitor-tools.ts +1 -4
- package/src/tools/native-task-tools.ts +31 -52
- package/src/tools/tool-result.ts +4 -0
- package/src/trigger-system.ts +4 -4
- package/vitest.config.ts +11 -7
- package/coverage/src/goal-reducer.ts.html +0 -982
- package/coverage/src/goal-store.ts.html +0 -742
- package/coverage/src/goal-verifier.ts.html +0 -808
- package/dist/goal-coordinator.d.ts +0 -22
- package/dist/goal-coordinator.js +0 -28
- package/dist/goal-reducer.d.ts +0 -98
- package/dist/goal-reducer.js +0 -190
- package/dist/goal-store.d.ts +0 -22
- package/dist/goal-store.js +0 -188
- package/dist/goal-types.d.ts +0 -82
- package/dist/goal-types.js +0 -1
- package/dist/goal-verifier.d.ts +0 -20
- package/dist/goal-verifier.js +0 -198
- package/docs/architecture/goal-state-schema.md +0 -505
- package/src/goal-coordinator.ts +0 -58
- package/src/goal-reducer.ts +0 -299
- package/src/goal-store.ts +0 -219
- package/src/goal-types.ts +0 -104
- package/src/goal-verifier.ts +0 -241
package/AGENTS.md
CHANGED
|
@@ -13,17 +13,60 @@
|
|
|
13
13
|
## Architecture
|
|
14
14
|
```
|
|
15
15
|
src/
|
|
16
|
-
├── index.ts
|
|
17
|
-
├──
|
|
18
|
-
├──
|
|
19
|
-
├──
|
|
20
|
-
├──
|
|
21
|
-
├──
|
|
22
|
-
├──
|
|
16
|
+
├── index.ts # Extension entry: tool/command registration, session wiring, native task fallback timer
|
|
17
|
+
├── api.ts # Public subpath (@trevonistrevon/pi-loop/api): RPC channels/DTOs, TaskStore, scope resolvers
|
|
18
|
+
├── types.ts # LoopKind, Trigger spec, LoopEntry, MonitorEntry, LoopConfig
|
|
19
|
+
├── task-types.ts # TaskEntry, TaskStatus, TaskStoreData
|
|
20
|
+
├── store.ts # File-backed CRUD (.pi/loops/loops.json) with file locking
|
|
21
|
+
├── task-store.ts # File-backed CRUD for native fallback tasks (.pi/tasks/tasks.json)
|
|
22
|
+
├── reducer-backed-store.ts # Shared atomic-write + pid-lock persistence layer for reducer-driven stores
|
|
23
|
+
├── coordinator.ts # ReducerSource/ReducerEvent/ReducerEffect plumbing shared by *-reducer/*-coordinator modules
|
|
24
|
+
├── loop-reducer.ts # Pure loop state transitions, incl. maxFires/expiry checks
|
|
25
|
+
├── monitor-reducer.ts # Pure monitor state transitions
|
|
26
|
+
├── notification-reducer.ts # Pure pending-notification state transitions
|
|
27
|
+
├── task-reducer.ts # Pure native task state transitions
|
|
28
|
+
├── monitor-completion-coordinator.ts # Reduces monitor "onDone" completion into a fire effect
|
|
29
|
+
├── task-backlog-coordinator.ts # Reduces pending-task counts into auto-create/auto-clean effects
|
|
30
|
+
├── scheduler.ts # Timer-based cron scheduler with jitter + 7-day expiry
|
|
31
|
+
├── trigger-system.ts # Unified trigger engine: cron timers + pi event subscriptions + hybrid
|
|
32
|
+
├── monitor-manager.ts # ChildProcess tracking, output buffering, event emission, stop
|
|
33
|
+
├── loop-parse.ts # Human interval → cron expression, next-fire computation, jitter
|
|
34
|
+
├── rpc/ # VENDORED — canonical copy shared verbatim with pi-orca; see "Cross-extension RPC" below
|
|
35
|
+
│ ├── channels.ts # TASKS_RPC/SUBAGENTS_RPC/TASK_EVENTS channel constants + wire DTOs
|
|
36
|
+
│ └── cross-extension-rpc.ts # rpcCall (client), rpcProbe (detection), handleRpc (server), PROTOCOL_VERSION, RpcError
|
|
37
|
+
├── runtime/ # Extension-init-time wiring, one module per concern
|
|
38
|
+
│ ├── loop-events.ts # Auto-delete payload types for backlog-drained loops
|
|
39
|
+
│ ├── monitor-ondone-runtime.ts # Coordinator wiring for MonitorCreate's onDone → loop fire
|
|
40
|
+
│ ├── native-task-rpc.ts # tasks:rpc:* server: ping/pending/create/clean/update over the native TaskStore
|
|
41
|
+
│ ├── notification-runtime.ts # Pending-notification buffering + idle-driven delivery
|
|
42
|
+
│ ├── scope.ts # PI_LOOP_SCOPE → loop/task store path resolution
|
|
43
|
+
│ ├── session-runtime.ts # Session-switch hooks, store (re)binding
|
|
44
|
+
│ ├── task-backlog-runtime.ts # Auto-create/auto-clean backlog worker evaluation
|
|
45
|
+
│ ├── task-events.ts # emitNativeTaskEvent: tasks:created/started/completed/reopened/updated/deleted
|
|
46
|
+
│ ├── task-mutations.ts # Shared mutation service: mutate → emit event → widget → backlog, used by RPC server and tools
|
|
47
|
+
│ └── task-rpc.ts # Client bridge: probes pi-tasks, falls back to native TaskStore for autoTask/pending/clean
|
|
48
|
+
├── tools/ # Tool implementations
|
|
49
|
+
│ ├── loop-tools.ts # LoopCreate/LoopList/LoopDelete
|
|
50
|
+
│ ├── monitor-tools.ts # MonitorCreate/MonitorList/MonitorStop
|
|
51
|
+
│ ├── native-task-tools.ts # TaskCreate/TaskList/TaskUpdate/TaskDelete (fallback only)
|
|
52
|
+
│ └── tool-result.ts # textResult() helper
|
|
53
|
+
├── commands/
|
|
54
|
+
│ ├── loop-command.ts # /loop interactive loop creation
|
|
55
|
+
│ └── tasks-command.ts # /tasks native task viewer/manager
|
|
23
56
|
└── ui/
|
|
24
|
-
└── widget.ts
|
|
57
|
+
└── widget.ts # Persistent widget: active loops + monitors + task summary
|
|
25
58
|
```
|
|
26
59
|
|
|
60
|
+
## Cross-extension RPC
|
|
61
|
+
`src/rpc/` is a **vendored** module: the canonical copy is maintained here and copied verbatim into the sibling `pi-orca` repo. If you edit `channels.ts` or `cross-extension-rpc.ts`, copy the change to `pi-orca` and bump the `VENDOR_REV` comment at the top of both files in both repos — the two copies must never drift.
|
|
62
|
+
|
|
63
|
+
The wire contract is request/reply over `pi.events`: a caller emits `{ requestId, ...params }` on a channel (e.g. `tasks:rpc:create`), the server replies on `<channel>:reply:<requestId>` with an envelope, `{success:true,data}` or `{success:false,error}`. `rpcCall` resolves/rejects that promise, `rpcProbe` swallows the rejection into `undefined` for presence detection, `handleRpc` is the server-side helper that turns a handler function into a channel subscription with automatic envelope wrapping. `PROTOCOL_VERSION` (currently `2`) is returned in ping replies so callers can gate on server capability.
|
|
64
|
+
|
|
65
|
+
`pi-loop`'s native tasks RPC server (`src/runtime/native-task-rpc.ts`) registers at extension init — not behind the native-tool-registration fallback timer — so early cross-extension calls never race it. It stands down (silent no-op via `isEnabled`) once an external `pi-tasks` is detected.
|
|
66
|
+
|
|
67
|
+
## Public API surface
|
|
68
|
+
External consumers must import `@trevonistrevon/pi-loop/api` (`src/api.ts`), never a deep `src/...` path. The package `exports` map in `package.json` enforces this — deep imports fail to resolve. `src/api.ts` re-exports the RPC channel constants/DTOs, `rpcCall`/`rpcProbe`/`handleRpc`/`RpcError`/`PROTOCOL_VERSION`, `TaskStore`, `TaskEntry`/`TaskStatus`, `resolveLoopStorePath`/`resolveTaskStorePath`, and `NATIVE_TASKS_PROVIDER`. Anything not re-exported there is internal and may change without notice.
|
|
69
|
+
|
|
27
70
|
## Conventions (mirror pi-tasks)
|
|
28
71
|
- No comments unless answering "why", never "what"
|
|
29
72
|
- `debug(...)` helper gated on `PI_LOOP_DEBUG` env var, logs to stderr
|
|
@@ -61,10 +104,7 @@ All loops are idle-driven. Cron and hybrid loops track their next fire time but
|
|
|
61
104
|
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"`.
|
|
62
105
|
|
|
63
106
|
## pi-tasks Integration
|
|
64
|
-
|
|
65
|
-
- `tasks:rpc:ping` on init → detect pi-tasks presence
|
|
66
|
-
- `tasks:ready` listener → late-binding detection
|
|
67
|
-
- `tasks:rpc:create` → auto-create task when loop fires (if `autoTask: true`)
|
|
107
|
+
`pi-loop` probes for `@tintinweb/pi-tasks` at init via `tasks:rpc:ping` (see "Cross-extension RPC" above) and again on a `tasks:ready` listener for late binding. When an external provider answers, `LoopCreate` with `autoTask: true` calls `tasks:rpc:create` to create a tracked task on fire. When no external provider answers, `pi-loop`'s own native RPC server (`src/runtime/native-task-rpc.ts`) serves all five verbs — `ping`/`pending`/`create`/`clean`/`update` — against the native `TaskStore`, and `autoTask: true` creates a native task directly instead of over RPC.
|
|
68
108
|
|
|
69
109
|
## /loop Self-Paced Mode
|
|
70
110
|
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).
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,64 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.6.0](https://github.com/trvon/pi-loop/compare/pi-loop-v0.5.8...pi-loop-v0.6.0) (2026-07-02)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### ⚠ BREAKING CHANGES
|
|
7
|
+
|
|
8
|
+
* package exports map blocks deep src/ imports — consumers must use @trevonistrevon/pi-loop/api. tasks:updated now reports previousStatus at edit time, not pre-transition.
|
|
9
|
+
|
|
10
|
+
### Features
|
|
11
|
+
|
|
12
|
+
* add maxFires for self-limiting loops, event-driven prompt steering ([52b50f0](https://github.com/trvon/pi-loop/commit/52b50f0d2b8c0b1df6aa74b09a8561807b549fe6))
|
|
13
|
+
* add native task fallback and compact task tracker ([6b5b6ff](https://github.com/trvon/pi-loop/commit/6b5b6fff53cc7810242e4f9081fe6d21b318c654))
|
|
14
|
+
* add task decomposition guidance to TaskCreate prompt ([4c51e72](https://github.com/trvon/pi-loop/commit/4c51e72a7317e1433cdb5bed6cfc9dfa521b5bfb))
|
|
15
|
+
* add tasks:rpc:clean RPC for sweeping done tasks ([73812ed](https://github.com/trvon/pi-loop/commit/73812ed4c3efeb08e97908e6de6435f65c768440))
|
|
16
|
+
* auto-create task worker loop at backlog threshold ([430663a](https://github.com/trvon/pi-loop/commit/430663a8042560688e08bd08129ea57b190ccecc))
|
|
17
|
+
* canonical rpc module + init-time task server ([7335eff](https://github.com/trvon/pi-loop/commit/7335eff6440452178ae9db3cb22a49098ad3953d))
|
|
18
|
+
* generalize task backlog loop cleanup ([9132948](https://github.com/trvon/pi-loop/commit/9132948dc9e22cda32adf6e8c5e13a7203f9c864))
|
|
19
|
+
* goal prompt and loading refinements ([b31df23](https://github.com/trvon/pi-loop/commit/b31df23c240f0bde7fb69fb8ea702429576276c7))
|
|
20
|
+
* prune completed tasks after successful git commit ([cba120b](https://github.com/trvon/pi-loop/commit/cba120be3a7fcdf71b7f7649b414577412d26a94))
|
|
21
|
+
* refining monitor interface ([66a6007](https://github.com/trvon/pi-loop/commit/66a60077093f40c258efeeb971f6f8db74e24f83))
|
|
22
|
+
* show worker-loop hint when pending tasks reach 5+ ([74dbf2c](https://github.com/trvon/pi-loop/commit/74dbf2cbf7f55a4206762eee3731798527537ab5))
|
|
23
|
+
* skip loop fires when autoTask loop has no pending tasks ([f2feb07](https://github.com/trvon/pi-loop/commit/f2feb079d5b520ed4c4dd0dc85d5b385efc45c45))
|
|
24
|
+
* **tasks:** add native rpc update and backlog signals ([31d06f6](https://github.com/trvon/pi-loop/commit/31d06f61fce1333c359f0d38def7406474144f8b))
|
|
25
|
+
* **tasks:** emit native task events with previousStatus tracking ([61b49ea](https://github.com/trvon/pi-loop/commit/61b49ea5703597b02754998269edfdc5b2018ebb))
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
### Bug Fixes
|
|
29
|
+
|
|
30
|
+
* add trigger validation, readOnly flag, and edge-case tests ([91baa07](https://github.com/trvon/pi-loop/commit/91baa07884bc20d760c7a3642c3ec462997fc0d3))
|
|
31
|
+
* auto-delete worker loop when task backlog clears ([502fa10](https://github.com/trvon/pi-loop/commit/502fa106b8862c06648e6be373e5980d2af18f6f))
|
|
32
|
+
* auto-expire monitor:done loops, buffer output, show completed monitors ([a3ec5de](https://github.com/trvon/pi-loop/commit/a3ec5de5847d67bddee9c572079b559b03e35f3f))
|
|
33
|
+
* deduplicate loop follow-up messages to prevent flood ([1613511](https://github.com/trvon/pi-loop/commit/1613511a2453d346edb59919beed2bdb18c05f63))
|
|
34
|
+
* delete done loops/monitors immediately instead of marking expired ([43f5220](https://github.com/trvon/pi-loop/commit/43f5220a3e6d807234e4bdb7611e44c0fa7468ec))
|
|
35
|
+
* delete event maxFires loops immediately ([12335e7](https://github.com/trvon/pi-loop/commit/12335e75dcf8d17a2c887966cae180d2b2f848da))
|
|
36
|
+
* deliver monitor onDone wakes without event dependency ([79d6a8b](https://github.com/trvon/pi-loop/commit/79d6a8b925aa98e8de0ea1b12addd5e0d2db0c47))
|
|
37
|
+
* derive jitter ceiling from cron step, delete expired event loops ([6d13935](https://github.com/trvon/pi-loop/commit/6d13935e79d2367072bec027d5ef2cb430eff44a))
|
|
38
|
+
* flush buffered worker wakes on agent end ([7a7dedf](https://github.com/trvon/pi-loop/commit/7a7dedf3ec7f16eb63edbfaf93e5dae9ed7a8f25))
|
|
39
|
+
* harden TaskUpdate prompt to prevent taskId alias errors ([5dfefd9](https://github.com/trvon/pi-loop/commit/5dfefd96bb08c29d192de472c6224ac434394b6f))
|
|
40
|
+
* **injection:** use before_agent_start message, not tool_result ([99a6317](https://github.com/trvon/pi-loop/commit/99a6317aabde8ce9d4f9e0c3065f42b6c6111259))
|
|
41
|
+
* loop trigger fix ([619f32c](https://github.com/trvon/pi-loop/commit/619f32c48134d9cc1376a89a62a7c8d729321143))
|
|
42
|
+
* **monitor:** make MonitorManager spawn-injectable, fix CI test timeouts ([f277646](https://github.com/trvon/pi-loop/commit/f277646b95369b43508fbbc8cc7eef5e37580781))
|
|
43
|
+
* **monitor:** prune stopped/timed-out monitors ([a46f6e8](https://github.com/trvon/pi-loop/commit/a46f6e8f2b99fa39bd11ff22d1a34999e1ac4434))
|
|
44
|
+
* only dedup recurring loop fires, always deliver one-shot events ([352e50e](https://github.com/trvon/pi-loop/commit/352e50e1de14ecd8d884b18a8e72572270ca90e9))
|
|
45
|
+
* **persist:** expire event loops on session start, clean stale monitors ([7f0876d](https://github.com/trvon/pi-loop/commit/7f0876d821e93e663f43ec2d5351bc9a37223b4b))
|
|
46
|
+
* recommend 5m default interval in LoopCreate task-continuation prompt ([1af3bcd](https://github.com/trvon/pi-loop/commit/1af3bcd35a2782f9fc333559d293c665db76c234))
|
|
47
|
+
* release please fix ([16e2304](https://github.com/trvon/pi-loop/commit/16e2304ea3112664c12c65b4e098e04d390f93f0))
|
|
48
|
+
* **reminders:** make loop reminder directive, not informational ([e21174d](https://github.com/trvon/pi-loop/commit/e21174df3d1d9403684e094f5763db33ed9cb732))
|
|
49
|
+
* repair native task fallback compilation ([a8cef04](https://github.com/trvon/pi-loop/commit/a8cef04eabd8a8af404d27ffa756266ee6a188ec))
|
|
50
|
+
* **runtime:** unref retention timer, swallow heartbeat pump errors ([602816b](https://github.com/trvon/pi-loop/commit/602816b3abb06859a0268c02119cc753de03decb))
|
|
51
|
+
* scope native task files by session, prevent cross-session leakage ([0436710](https://github.com/trvon/pi-loop/commit/04367102414dd56f7668e1522b91c6f089490979))
|
|
52
|
+
* **tasks:** gate late native RPC probes ([c97f4ad](https://github.com/trvon/pi-loop/commit/c97f4ad6800c00b9858c1a8e640f13e699e0c26a))
|
|
53
|
+
* **tasks:** guard native fallback registration ([7d3b74a](https://github.com/trvon/pi-loop/commit/7d3b74abfa637bbe370ae232b8067e7bc5205ea1))
|
|
54
|
+
* **trigger:** auto-expire non-recurring event loops ([178f9fd](https://github.com/trvon/pi-loop/commit/178f9fd6a6548a04307f3ed83935068a235c24d3))
|
|
55
|
+
* use pi.hasPendingMessages() instead of bespoke tracking Set ([dab60d4](https://github.com/trvon/pi-loop/commit/dab60d46340fab04ae74b80044ad03b6b0ca9fe8))
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
### Performance Improvements
|
|
59
|
+
|
|
60
|
+
* **test:** replace real 6.1s waits with fake-timer advance in onDone tests ([c713ad3](https://github.com/trvon/pi-loop/commit/c713ad36f958d53e75c4c7d7fd723c06ee420543))
|
|
61
|
+
|
|
3
62
|
## [0.1.2]
|
|
4
63
|
|
|
5
64
|
- Added `onDone` parameter to `MonitorCreate` — auto-creates a completion loop so the agent is notified when a background process finishes, no polling needed
|
package/CONTRIBUTING.md
CHANGED
|
@@ -19,19 +19,22 @@ npm install
|
|
|
19
19
|
| `npm run lint:fix` | Auto-fix lint issues |
|
|
20
20
|
| `npm test` | Run tests (`vitest run`) |
|
|
21
21
|
| `npm run test:watch` | Watch mode |
|
|
22
|
+
| `npm run test:coverage` | Run tests with coverage (used in CI) |
|
|
23
|
+
| `npm run test:e2e` | Run `test/e2e/reminder-injection.sh` (self-skips without a local llama server) |
|
|
22
24
|
| `npm run build` | Compile TypeScript |
|
|
23
25
|
|
|
24
26
|
## Architecture
|
|
25
27
|
|
|
26
|
-
See `AGENTS.md` for the full architecture overview. Key modules:
|
|
28
|
+
See `AGENTS.md` for the full architecture overview and directory tree, including `src/rpc/` (vendored cross-extension RPC) and `src/api.ts` (public `@trevonistrevon/pi-loop/api` subpath — the only supported import path for external consumers). Key modules:
|
|
27
29
|
|
|
28
|
-
- **`src/index.ts`** — Extension entry: registers
|
|
30
|
+
- **`src/index.ts`** — Extension entry: registers tools, `/loop` `/tasks` commands, widget lifecycle, cross-extension RPC server
|
|
29
31
|
- **`src/types.ts`** — Core types: `LoopEntry`, `MonitorEntry`, `Trigger` variants
|
|
30
32
|
- **`src/store.ts`** — File-backed CRUD with pid-based file locking (atomic write → rename)
|
|
31
33
|
- **`src/scheduler.ts`** — Timer-based cron scheduler with per-loop jitter and 7-day expiry
|
|
32
34
|
- **`src/trigger-system.ts`** — Unified engine: cron timers + pi event subscriptions + hybrid debounce
|
|
33
35
|
- **`src/monitor-manager.ts`** — `ChildProcess` wrapper: stdout/stderr streaming as pi events
|
|
34
36
|
- **`src/loop-parse.ts`** — Human interval parsing (`5m` → cron), cron matching, next-fire computation
|
|
37
|
+
- **`src/runtime/native-task-rpc.ts`** — `tasks:rpc:*` server for the native fallback task store
|
|
35
38
|
- **`src/ui/widget.ts`** — TUI widget rendering active loops + monitors above the editor
|
|
36
39
|
|
|
37
40
|
## Conventions
|
|
@@ -58,12 +61,19 @@ npm test # Run once
|
|
|
58
61
|
npm run test:watch # Watch mode
|
|
59
62
|
```
|
|
60
63
|
|
|
64
|
+
### Manual fixtures (not run in CI)
|
|
65
|
+
|
|
66
|
+
- `benchmarks/experiment-sim.js` — synthetic monitor fixture: prints periodic `iteration N/M, loss=...` lines and handles `SIGTERM` with a checkpoint message. Used to manually exercise `MonitorCreate` streaming, `onDone`, and stop handling. Run with `node benchmarks/experiment-sim.js`. Not wired into CI by design — it's a fixture, not an assertion.
|
|
67
|
+
- `test/e2e/reminder-injection.sh` (`npm run test:e2e`) — drives a real `pi` session against a local llama server to validate loop/reminder injection end to end. Requires a model server reachable at `localhost:2276`; the script checks for it and self-skips (exit 0) when absent. Never runs in CI — there is no llama server in the CI environment.
|
|
68
|
+
|
|
61
69
|
## Pull Request Workflow
|
|
62
70
|
|
|
63
71
|
1. Fork, branch, implement
|
|
64
|
-
2. Ensure `npm run
|
|
72
|
+
2. Ensure `npm run lint`, `npm run typecheck`, and `npm run test:coverage` all pass, then `npm run build`
|
|
65
73
|
3. Open PR against `main`
|
|
66
74
|
|
|
75
|
+
CI (`.github/workflows/ci.yml`) runs the same validation in this order on Node 20.x and 22.x: `lint` → `typecheck` → `test:coverage` → `build`.
|
|
76
|
+
|
|
67
77
|
## License
|
|
68
78
|
|
|
69
79
|
By contributing, you agree that your contributions will be licensed under the MIT License.
|
package/Dockerfile
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
FROM node:22-alpine AS base
|
|
2
|
+
WORKDIR /app
|
|
3
|
+
COPY package.json package-lock.json ./
|
|
4
|
+
RUN npm ci
|
|
5
|
+
COPY . .
|
|
6
|
+
|
|
7
|
+
FROM node:20-alpine AS node20
|
|
8
|
+
WORKDIR /app
|
|
9
|
+
COPY package.json package-lock.json ./
|
|
10
|
+
RUN npm ci
|
|
11
|
+
COPY . .
|
|
12
|
+
|
|
13
|
+
FROM node:22-alpine AS node22
|
|
14
|
+
WORKDIR /app
|
|
15
|
+
COPY package.json package-lock.json ./
|
|
16
|
+
RUN npm ci
|
|
17
|
+
COPY . .
|
package/README.md
CHANGED
|
@@ -81,9 +81,56 @@ If `pi-tasks` does not respond during startup detection, `pi-loop` registers a n
|
|
|
81
81
|
- `TaskCreate`, `TaskList`, `TaskUpdate`, `TaskDelete`
|
|
82
82
|
- `/tasks` interactive viewer
|
|
83
83
|
- compact status-line task tracking
|
|
84
|
+
- native task RPC replies on `tasks:rpc:ping`, `tasks:rpc:create`, `tasks:rpc:pending`, `tasks:rpc:clean`, and `tasks:rpc:update`
|
|
84
85
|
|
|
85
86
|
This fallback is session-sticky: `pi-loop` decides once at startup whether `pi-tasks` or native tasks own task management for that session.
|
|
86
87
|
|
|
88
|
+
### Task and backlog events
|
|
89
|
+
|
|
90
|
+
`pi-loop` emits native task lifecycle events that other extensions can consume directly:
|
|
91
|
+
|
|
92
|
+
- `tasks:created`
|
|
93
|
+
- `tasks:started`
|
|
94
|
+
- `tasks:completed`
|
|
95
|
+
- `tasks:reopened`
|
|
96
|
+
- `tasks:updated`
|
|
97
|
+
- `tasks:deleted`
|
|
98
|
+
|
|
99
|
+
Payloads carry `previousStatus`. Transition events (`tasks:started` /
|
|
100
|
+
`tasks:completed` / `tasks:reopened`) report the status before the transition;
|
|
101
|
+
`tasks:updated` (a details edit) reports the status current at edit time — so a
|
|
102
|
+
combined status+details update never fabricates a second transition. (Changed
|
|
103
|
+
in 0.6.0: the tool path previously reused the pre-transition status.)
|
|
104
|
+
- `tasks:backlog_empty` — emitted when a task-backlog worker observes zero pending tasks and is about to auto-delete
|
|
105
|
+
- `loops:autodeleted` — emitted for each loop that `pi-loop` auto-deletes, including backlog workers removed because the task queue drained
|
|
106
|
+
|
|
107
|
+
### Cross-extension task RPC
|
|
108
|
+
|
|
109
|
+
Other extensions can create and manage native tasks without importing `pi-loop` internals. `pi-loop` answers `ping` over `pi.events` from extension init; the other verbs unlock once the pi-tasks detection probe settles (a few seconds at most, immediate when no provider replies race it). The whole server stands down (silent no-op) once an external `pi-tasks` is detected:
|
|
110
|
+
|
|
111
|
+
| Channel | Request | Reply |
|
|
112
|
+
|---|---|---|
|
|
113
|
+
| `tasks:rpc:ping` | `{}` | `{ version, provider }` |
|
|
114
|
+
| `tasks:rpc:pending` | `{}` | `{ pending }` |
|
|
115
|
+
| `tasks:rpc:create` | `{ subject, description, metadata? }` | `{ id, task }` |
|
|
116
|
+
| `tasks:rpc:clean` | `{}` | `{ pruned }` |
|
|
117
|
+
| `tasks:rpc:update` | `{ id, status?, subject?, description? }` | `{ task }` |
|
|
118
|
+
|
|
119
|
+
Every request/reply pair follows the same contract: emit `{ requestId, ...params }` on the channel, receive an envelope on `<channel>:reply:<requestId>` — `{ success: true, data }` or `{ success: false, error }`.
|
|
120
|
+
|
|
121
|
+
`@trevonistrevon/pi-loop/api` exports typed channel constants and a client helper so consumers don't hand-roll the envelope:
|
|
122
|
+
|
|
123
|
+
```ts
|
|
124
|
+
import { TASKS_RPC, rpcCall } from "@trevonistrevon/pi-loop/api";
|
|
125
|
+
|
|
126
|
+
const { id, task } = await rpcCall(pi.events, TASKS_RPC.create, {
|
|
127
|
+
subject: "Fix deploy polling",
|
|
128
|
+
description: "Switch deploy check to event-driven loop",
|
|
129
|
+
});
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
`rpcCall` rejects on failure or timeout instead of returning a sentinel; wrap it in `try/catch` if you want fallback behavior. Import only from `@trevonistrevon/pi-loop/api` — the package's `exports` map blocks deep `src/` imports.
|
|
133
|
+
|
|
87
134
|
## Status line
|
|
88
135
|
|
|
89
136
|
`pi-loop` keeps a compact persistent status line in the TUI.
|