@trevonistrevon/pi-loop 0.2.6 → 0.2.8
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/dist/index.js +5 -9
- package/package.json +1 -1
- package/src/index.ts +8 -12
package/dist/index.js
CHANGED
|
@@ -121,6 +121,7 @@ export default function (pi) {
|
|
|
121
121
|
trigger: entry.trigger,
|
|
122
122
|
timestamp: Date.now(),
|
|
123
123
|
readOnly: entry.readOnly,
|
|
124
|
+
recurring: entry.recurring,
|
|
124
125
|
});
|
|
125
126
|
}
|
|
126
127
|
// ── Session lifecycle ──
|
|
@@ -179,9 +180,12 @@ export default function (pi) {
|
|
|
179
180
|
showPersistedLoops(isResume);
|
|
180
181
|
});
|
|
181
182
|
// ── Loop fire handler — sends a user message to re-wake the agent ──
|
|
182
|
-
const pendingFollowUps = new Set();
|
|
183
183
|
pi.events.on("loop:fire", (event) => {
|
|
184
184
|
const data = event;
|
|
185
|
+
if (data.recurring && _latestCtx?.hasPendingMessages()) {
|
|
186
|
+
debug(`loop:fire #${data.loopId} — agent has pending messages, skipping recurring fire`);
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
185
189
|
const triggerInfo = typeof data.trigger === "string"
|
|
186
190
|
? data.trigger
|
|
187
191
|
: data.trigger?.type === "cron"
|
|
@@ -190,22 +194,14 @@ export default function (pi) {
|
|
|
190
194
|
? `event: ${data.trigger.source}`
|
|
191
195
|
: `hybrid`;
|
|
192
196
|
const loopId = data.loopId || "?";
|
|
193
|
-
if (pendingFollowUps.has(loopId)) {
|
|
194
|
-
debug(`loop:fire #${loopId} — follow-up already queued, skipping`);
|
|
195
|
-
return;
|
|
196
|
-
}
|
|
197
|
-
pendingFollowUps.add(loopId);
|
|
198
197
|
const prompt = data.prompt || "loop fired";
|
|
199
198
|
const constraint = data.readOnly ? "\n\nREAD-ONLY MODE — use only read tools (Read, TaskList, LoopList, MonitorList, LoopCreate, etc.). No file writes, shell execution, or destructive changes." : "";
|
|
200
199
|
const message = [
|
|
201
200
|
`[pi-loop] Loop #${loopId} fired (${triggerInfo}).${constraint}`,
|
|
202
201
|
prompt,
|
|
203
202
|
].join("\n");
|
|
204
|
-
// deliverAs: "followUp" queues the message when the agent is busy;
|
|
205
|
-
// it delivers after the current turn finishes.
|
|
206
203
|
pi.sendUserMessage(message, { deliverAs: "followUp" });
|
|
207
204
|
});
|
|
208
|
-
pi.on("turn_end", () => { pendingFollowUps.clear(); });
|
|
209
205
|
// ──────────────────────────────────────────────────
|
|
210
206
|
// Tool 1: LoopCreate
|
|
211
207
|
// ──────────────────────────────────────────────────
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -41,6 +41,7 @@ interface LoopFireEvent {
|
|
|
41
41
|
trigger: Trigger | string;
|
|
42
42
|
timestamp: number;
|
|
43
43
|
readOnly?: boolean;
|
|
44
|
+
recurring?: boolean;
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
interface SessionSwitchEvent {
|
|
@@ -136,6 +137,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
136
137
|
trigger: entry.trigger,
|
|
137
138
|
timestamp: Date.now(),
|
|
138
139
|
readOnly: entry.readOnly,
|
|
140
|
+
recurring: entry.recurring,
|
|
139
141
|
});
|
|
140
142
|
}
|
|
141
143
|
|
|
@@ -204,10 +206,14 @@ export default function (pi: ExtensionAPI) {
|
|
|
204
206
|
|
|
205
207
|
// ── Loop fire handler — sends a user message to re-wake the agent ──
|
|
206
208
|
|
|
207
|
-
const pendingFollowUps = new Set<string>();
|
|
208
|
-
|
|
209
209
|
pi.events.on("loop:fire", (event: unknown) => {
|
|
210
210
|
const data = event as LoopFireEvent;
|
|
211
|
+
|
|
212
|
+
if (data.recurring && _latestCtx?.hasPendingMessages()) {
|
|
213
|
+
debug(`loop:fire #${data.loopId} — agent has pending messages, skipping recurring fire`);
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
|
|
211
217
|
const triggerInfo = typeof data.trigger === "string"
|
|
212
218
|
? data.trigger
|
|
213
219
|
: data.trigger?.type === "cron"
|
|
@@ -217,12 +223,6 @@ export default function (pi: ExtensionAPI) {
|
|
|
217
223
|
: `hybrid`;
|
|
218
224
|
|
|
219
225
|
const loopId = data.loopId || "?";
|
|
220
|
-
if (pendingFollowUps.has(loopId)) {
|
|
221
|
-
debug(`loop:fire #${loopId} — follow-up already queued, skipping`);
|
|
222
|
-
return;
|
|
223
|
-
}
|
|
224
|
-
pendingFollowUps.add(loopId);
|
|
225
|
-
|
|
226
226
|
const prompt = data.prompt || "loop fired";
|
|
227
227
|
const constraint = data.readOnly ? "\n\nREAD-ONLY MODE — use only read tools (Read, TaskList, LoopList, MonitorList, LoopCreate, etc.). No file writes, shell execution, or destructive changes." : "";
|
|
228
228
|
const message = [
|
|
@@ -230,13 +230,9 @@ export default function (pi: ExtensionAPI) {
|
|
|
230
230
|
prompt,
|
|
231
231
|
].join("\n");
|
|
232
232
|
|
|
233
|
-
// deliverAs: "followUp" queues the message when the agent is busy;
|
|
234
|
-
// it delivers after the current turn finishes.
|
|
235
233
|
pi.sendUserMessage(message, { deliverAs: "followUp" });
|
|
236
234
|
});
|
|
237
235
|
|
|
238
|
-
pi.on("turn_end", () => { pendingFollowUps.clear(); });
|
|
239
|
-
|
|
240
236
|
// ──────────────────────────────────────────────────
|
|
241
237
|
// Tool 1: LoopCreate
|
|
242
238
|
// ──────────────────────────────────────────────────
|