@matthewfl/pi-contemplator 0.0.2 → 0.0.3
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/package.json +1 -1
- package/src/agents/contemplator/agent.ts +22 -11
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@matthewfl/pi-contemplator",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "A Pi extension that keeps long-running agentic sessions on track with background memory, contemplation, and structural review.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -143,7 +143,8 @@ export class Contemplator {
|
|
|
143
143
|
private resumedReviewIds = new Set<string>();
|
|
144
144
|
private reviewerSessions = new Map<string, ReviewerSession>();
|
|
145
145
|
private deliveredProbeIds = new Set<string>();
|
|
146
|
-
|
|
146
|
+
/** Probe ids passed to pi.sendMessage by this live extension runtime. */
|
|
147
|
+
private queuedProbeIds = new Set<string>();
|
|
147
148
|
private sessionGeneration = 0;
|
|
148
149
|
private latestCtx: MemoryUpdateCtx | undefined;
|
|
149
150
|
private turnsSinceRun = 0;
|
|
@@ -153,12 +154,19 @@ export class Contemplator {
|
|
|
153
154
|
|
|
154
155
|
register(): void {
|
|
155
156
|
this.runtime.setMemoryUpdateListener((ctx) => this.withDebugContext(ctx, () => this.observeTurn(ctx)));
|
|
156
|
-
|
|
157
|
+
this.pi.on("session_start", (event: any, ctx: ExtensionContext) => {
|
|
157
158
|
this.sessionGeneration++;
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
159
|
+
// AgentSession preserves its steering queue across extension reloads. An
|
|
160
|
+
// undelivered tracking entry therefore still has a live queued message;
|
|
161
|
+
// restoring it here would enqueue the same probe a second time.
|
|
162
|
+
const reload = event?.reason === "reload";
|
|
163
|
+
this.restore(ctx, true, reload, reload);
|
|
164
|
+
});
|
|
165
|
+
this.pi.on("session_tree", (_event: any, ctx: ExtensionContext) => {
|
|
166
|
+
this.sessionGeneration++;
|
|
167
|
+
// Pending steering messages remain queued while navigating the tree.
|
|
168
|
+
this.restore(ctx, true, true);
|
|
169
|
+
});
|
|
162
170
|
this.pi.on("session_shutdown", () => {
|
|
163
171
|
this.sessionGeneration++;
|
|
164
172
|
this.history = [];
|
|
@@ -172,7 +180,7 @@ export class Contemplator {
|
|
|
172
180
|
this.resumedReviewIds.clear();
|
|
173
181
|
this.reviewerSessions.clear();
|
|
174
182
|
this.deliveredProbeIds.clear();
|
|
175
|
-
this.
|
|
183
|
+
this.queuedProbeIds.clear();
|
|
176
184
|
this.latestCtx = undefined;
|
|
177
185
|
this.turnsSinceRun = 0;
|
|
178
186
|
this.restoredTipId = undefined;
|
|
@@ -220,7 +228,7 @@ export class Contemplator {
|
|
|
220
228
|
}, fn);
|
|
221
229
|
}
|
|
222
230
|
|
|
223
|
-
private restore(ctx: MemoryUpdateCtx, resetTracking = false): void {
|
|
231
|
+
private restore(ctx: MemoryUpdateCtx, resetTracking = false, retainQueuedIds = false, skipUndeliveredRestore = false): void {
|
|
224
232
|
this.latestCtx = ctx;
|
|
225
233
|
const entries = ctx.sessionManager.getBranch() as Entry[];
|
|
226
234
|
const tipId = entries.at(-1)?.id;
|
|
@@ -229,7 +237,7 @@ export class Contemplator {
|
|
|
229
237
|
this.history = [];
|
|
230
238
|
if (resetTracking) {
|
|
231
239
|
this.deliveredProbeIds.clear();
|
|
232
|
-
this.
|
|
240
|
+
if (!retainQueuedIds) this.queuedProbeIds.clear();
|
|
233
241
|
this.inFlightReviewIds.clear();
|
|
234
242
|
this.resolvingReviewIds.clear();
|
|
235
243
|
this.resumedReviewIds.clear();
|
|
@@ -312,8 +320,7 @@ export class Contemplator {
|
|
|
312
320
|
}
|
|
313
321
|
this.restoredTipId = tipId;
|
|
314
322
|
for (const [probeId, question] of undeliveredSuggestions) {
|
|
315
|
-
if (queuedProbeIds.has(probeId) || this.
|
|
316
|
-
this.requeuedProbeIds.add(probeId);
|
|
323
|
+
if (skipUndeliveredRestore || queuedProbeIds.has(probeId) || this.queuedProbeIds.has(probeId)) continue;
|
|
317
324
|
this.queueProbe(ctx, question, "restore", probeId);
|
|
318
325
|
}
|
|
319
326
|
if (resetTracking) void this.resumePendingReviews(ctx);
|
|
@@ -571,6 +578,10 @@ export class Contemplator {
|
|
|
571
578
|
display: false,
|
|
572
579
|
details: { version: 1, question, source, probeId },
|
|
573
580
|
}, { deliverAs: "steer", triggerTurn: false });
|
|
581
|
+
// sendMessage queues synchronously. Mark every source (not only restore)
|
|
582
|
+
// before a later turn_end can rebuild state from the still-undelivered
|
|
583
|
+
// tracking entry and enqueue this probe again.
|
|
584
|
+
this.queuedProbeIds.add(probeId);
|
|
574
585
|
this.pi.appendEntry(CONTEMPLATOR_SUGGESTION, { version: 1, suggestion: question, delivered: false, source, probeId });
|
|
575
586
|
this.markTipPersisted(ctx);
|
|
576
587
|
debugLog("contemplator.suggestion_queued", {
|