@trevonistrevon/pi-loop 0.5.9 → 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 +1 -1
- package/AGENTS.md +52 -12
- package/CHANGELOG.md +59 -0
- package/CONTRIBUTING.md +13 -3
- package/README.md +47 -0
- package/coverage/coverage-final.json +35 -32
- 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 +129 -129
- package/coverage/src/coordinator.ts.html +26 -26
- package/coverage/src/index.html +61 -106
- package/coverage/src/index.ts.html +224 -86
- package/coverage/src/loop-parse.ts.html +106 -73
- package/coverage/src/loop-reducer.ts.html +21 -21
- 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 +6 -6
- 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 +68 -23
- 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 +22 -22
- package/coverage/src/runtime/scope.ts.html +14 -14
- package/coverage/src/runtime/session-runtime.ts.html +32 -32
- package/coverage/src/runtime/task-backlog-runtime.ts.html +65 -23
- package/coverage/src/runtime/task-events.ts.html +2 -2
- package/coverage/src/runtime/task-mutations.ts.html +394 -0
- package/coverage/src/runtime/task-rpc.ts.html +102 -120
- package/coverage/src/scheduler.ts.html +29 -29
- package/coverage/src/store.ts.html +27 -27
- 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 +57 -120
- 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 +48 -3
- package/dist/loop-parse.js +14 -5
- 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/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/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 +49 -3
- package/src/loop-parse.ts +18 -7
- 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 +7 -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
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import { Type } from "typebox";
|
|
3
3
|
import type { LoopEntry, MonitorEntry, Trigger } from "../types.js";
|
|
4
|
+
import { textResult } from "./tool-result.js";
|
|
4
5
|
|
|
5
6
|
interface MonitorManagerLike {
|
|
6
7
|
list(): MonitorEntry[];
|
|
@@ -26,10 +27,6 @@ export interface MonitorToolsOptions {
|
|
|
26
27
|
handleMonitorDoneLoop: (doneLoop: LoopEntry, monitorId: string) => void;
|
|
27
28
|
}
|
|
28
29
|
|
|
29
|
-
function textResult(msg: string) {
|
|
30
|
-
return { content: [{ type: "text" as const, text: msg }], details: undefined as any };
|
|
31
|
-
}
|
|
32
|
-
|
|
33
30
|
function formatRemaining(ms: number): string {
|
|
34
31
|
if (ms < 60000) return `${Math.round(ms / 1000)}s`;
|
|
35
32
|
if (ms < 3600000) return `${Math.round(ms / 60000)}m`;
|
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import { Type } from "typebox";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
createTask,
|
|
5
|
+
deleteTask,
|
|
6
|
+
type TaskBacklogResult,
|
|
7
|
+
type TaskMutationContext,
|
|
8
|
+
updateTask,
|
|
9
|
+
} from "../runtime/task-mutations.js";
|
|
4
10
|
import { TaskStore } from "../task-store.js";
|
|
11
|
+
import type { TaskStatus } from "../task-types.js";
|
|
12
|
+
import { textResult } from "./tool-result.js";
|
|
5
13
|
|
|
6
|
-
export
|
|
7
|
-
created: boolean;
|
|
8
|
-
entry?: { id: string };
|
|
9
|
-
}
|
|
14
|
+
export type { TaskBacklogResult };
|
|
10
15
|
|
|
11
16
|
export interface NativeTaskToolsOptions {
|
|
12
17
|
pi: ExtensionAPI;
|
|
@@ -15,12 +20,15 @@ export interface NativeTaskToolsOptions {
|
|
|
15
20
|
updateWidget: () => void;
|
|
16
21
|
}
|
|
17
22
|
|
|
18
|
-
function
|
|
19
|
-
return
|
|
23
|
+
function backlogSuffix(backlog: TaskBacklogResult): string {
|
|
24
|
+
return backlog.created && backlog.entry
|
|
25
|
+
? `\nBacklog worker loop #${backlog.entry.id} created`
|
|
26
|
+
: "";
|
|
20
27
|
}
|
|
21
28
|
|
|
22
29
|
export function registerNativeTaskTools(options: NativeTaskToolsOptions): void {
|
|
23
30
|
const { pi, taskStore, evaluateTaskBacklog, updateWidget } = options;
|
|
31
|
+
const mutationCtx: TaskMutationContext = { pi, taskStore, evaluateTaskBacklog, updateWidget };
|
|
24
32
|
|
|
25
33
|
pi.registerTool({
|
|
26
34
|
name: "TaskCreate",
|
|
@@ -47,15 +55,11 @@ Fields:
|
|
|
47
55
|
description: Type.String({ description: "Detailed description of what needs to be done" }),
|
|
48
56
|
}),
|
|
49
57
|
async execute(_toolCallId, params) {
|
|
50
|
-
const entry =
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
const autoLoopMsg = backlog.created && backlog.entry
|
|
56
|
-
? `\nBacklog worker loop #${backlog.entry.id} created`
|
|
57
|
-
: "";
|
|
58
|
-
return Promise.resolve(textResult(`Task #${entry.id} created: ${entry.subject}${autoLoopMsg}`));
|
|
58
|
+
const { entry, backlog } = await createTask(mutationCtx, {
|
|
59
|
+
subject: params.subject,
|
|
60
|
+
description: params.description,
|
|
61
|
+
});
|
|
62
|
+
return textResult(`Task #${entry.id} created: ${entry.subject}${backlogSuffix(backlog)}`);
|
|
59
63
|
},
|
|
60
64
|
});
|
|
61
65
|
|
|
@@ -104,34 +108,15 @@ Parameters: id (required), status, subject, description`,
|
|
|
104
108
|
}),
|
|
105
109
|
async execute(_toolCallId, params) {
|
|
106
110
|
const { id, status, subject, description } = params;
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
} else if (status === "completed") {
|
|
115
|
-
entry = taskStore.complete(id);
|
|
116
|
-
if (entry) emitNativeTaskEvent(pi, "tasks:completed", entry, previousStatus);
|
|
117
|
-
} else if (status === "pending") {
|
|
118
|
-
entry = taskStore.reopen(id);
|
|
119
|
-
if (entry) emitNativeTaskEvent(pi, "tasks:reopened", entry, previousStatus);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
if (!entry) return Promise.resolve(textResult(`Task #${id} not found`));
|
|
123
|
-
if (subject !== undefined || description !== undefined) {
|
|
124
|
-
entry = taskStore.updateDetails(id, { subject, description });
|
|
125
|
-
if (entry) emitNativeTaskEvent(pi, "tasks:updated", entry, previousStatus);
|
|
126
|
-
}
|
|
127
|
-
if (!entry) return Promise.resolve(textResult(`Task #${id} not found`));
|
|
128
|
-
updateWidget();
|
|
129
|
-
const backlog = await evaluateTaskBacklog(taskStore, taskStore.pendingCount());
|
|
111
|
+
const result = await updateTask(mutationCtx, {
|
|
112
|
+
id,
|
|
113
|
+
status: status as TaskStatus | undefined,
|
|
114
|
+
subject,
|
|
115
|
+
description,
|
|
116
|
+
});
|
|
117
|
+
if (!result) return textResult(`Task #${id} not found`);
|
|
130
118
|
const statusMsg = status ? ` → ${status}` : "";
|
|
131
|
-
|
|
132
|
-
? `\nBacklog worker loop #${backlog.entry.id} created`
|
|
133
|
-
: "";
|
|
134
|
-
return Promise.resolve(textResult(`Task #${id} updated${statusMsg}${autoLoopMsg}`));
|
|
119
|
+
return textResult(`Task #${id} updated${statusMsg}${backlogSuffix(result.backlog)}`);
|
|
135
120
|
},
|
|
136
121
|
});
|
|
137
122
|
|
|
@@ -143,15 +128,9 @@ Parameters: id (required), status, subject, description`,
|
|
|
143
128
|
id: Type.String({ description: "Task ID to delete" }),
|
|
144
129
|
}),
|
|
145
130
|
async execute(_toolCallId, params) {
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
if (deleted) {
|
|
150
|
-
if (existing) emitNativeTaskEvent(pi, "tasks:deleted", existing, existing.status);
|
|
151
|
-
await evaluateTaskBacklog(taskStore, taskStore.pendingCount());
|
|
152
|
-
return Promise.resolve(textResult(`Task #${params.id} deleted`));
|
|
153
|
-
}
|
|
154
|
-
return Promise.resolve(textResult(`Task #${params.id} not found`));
|
|
131
|
+
const result = await deleteTask(mutationCtx, params.id);
|
|
132
|
+
if (!result) return textResult(`Task #${params.id} not found`);
|
|
133
|
+
return textResult(`Task #${params.id} deleted`);
|
|
155
134
|
},
|
|
156
135
|
});
|
|
157
136
|
}
|
package/src/trigger-system.ts
CHANGED
|
@@ -58,7 +58,7 @@ export class TriggerSystem {
|
|
|
58
58
|
}
|
|
59
59
|
const subs = this.eventSubscriptions.get(source)!;
|
|
60
60
|
|
|
61
|
-
const unsub = this.pi.events.on(source
|
|
61
|
+
const unsub = this.pi.events.on(source, (data: unknown) => {
|
|
62
62
|
if (entry.trigger.type === "hybrid") {
|
|
63
63
|
this.handleHybridFire(entry, data);
|
|
64
64
|
} else {
|
|
@@ -71,7 +71,7 @@ export class TriggerSystem {
|
|
|
71
71
|
subs.set(entry.id, unsub);
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
private handleHybridFire(entry: LoopEntry, _data:
|
|
74
|
+
private handleHybridFire(entry: LoopEntry, _data: unknown): void {
|
|
75
75
|
const now = Date.now();
|
|
76
76
|
const last = this.lastFireTime.get(entry.id) ?? 0;
|
|
77
77
|
const debounceMs = entry.trigger.type === "hybrid" ? entry.trigger.debounceMs : 0;
|
|
@@ -123,7 +123,7 @@ export class TriggerSystem {
|
|
|
123
123
|
}
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
-
private matchesFilter(data:
|
|
126
|
+
private matchesFilter(data: unknown, filter?: string): boolean {
|
|
127
127
|
if (!filter) return true;
|
|
128
128
|
|
|
129
129
|
if (filter.startsWith("regex:")) {
|
|
@@ -138,7 +138,7 @@ export class TriggerSystem {
|
|
|
138
138
|
try {
|
|
139
139
|
const parsed = JSON.parse(filter);
|
|
140
140
|
for (const [key, value] of Object.entries(parsed)) {
|
|
141
|
-
const dataValue = data?.[key];
|
|
141
|
+
const dataValue = (data as Record<string, unknown> | undefined)?.[key];
|
|
142
142
|
if (dataValue === undefined) return false;
|
|
143
143
|
if (typeof value === "object" && typeof dataValue === "object") {
|
|
144
144
|
if (JSON.stringify(value) !== JSON.stringify(dataValue)) return false;
|
package/vitest.config.ts
CHANGED
|
@@ -15,14 +15,14 @@ export default defineConfig({
|
|
|
15
15
|
include: ["src/**/*.ts"],
|
|
16
16
|
// Type-only modules and test helpers carry no executable logic worth gating.
|
|
17
17
|
exclude: ["src/**/*-types.ts", "src/types.ts"],
|
|
18
|
-
// Floors set just below current actuals (stmts
|
|
19
|
-
// funcs
|
|
20
|
-
//
|
|
18
|
+
// Floors set just below current actuals (stmts 91%, branches 83%,
|
|
19
|
+
// funcs 98%, lines 94%) to catch regressions. Re-anchored after the
|
|
20
|
+
// goal-subsystem removal and the rpc/native-task-rpc/command suites landed.
|
|
21
21
|
thresholds: {
|
|
22
|
-
statements:
|
|
23
|
-
branches:
|
|
24
|
-
functions:
|
|
25
|
-
lines:
|
|
22
|
+
statements: 89,
|
|
23
|
+
branches: 80,
|
|
24
|
+
functions: 96,
|
|
25
|
+
lines: 91,
|
|
26
26
|
},
|
|
27
27
|
},
|
|
28
28
|
},
|