@evandu/super-pi 0.1.148 → 0.1.149
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.
|
@@ -35,5 +35,5 @@
|
|
|
35
35
|
"src/client/types.ts": "7c06189b32890009d28a371a64d9f29161c14a349a5b399d51d1314d38fa27ac",
|
|
36
36
|
"src/client/vite-env.d.ts": "65996936fbb042915f7b74a200fcdde7e410f32a669b1ab9597cfaa4b0faddb5"
|
|
37
37
|
},
|
|
38
|
-
"recordedAt": "2026-11-01T14:
|
|
38
|
+
"recordedAt": "2026-11-01T14:53:57.934Z"
|
|
39
39
|
}
|
|
@@ -110,16 +110,27 @@ export declare class SessionOrchestratorService {
|
|
|
110
110
|
*/
|
|
111
111
|
private readonly lengthContinuations;
|
|
112
112
|
/**
|
|
113
|
-
* THE CHILDREN THAT HAVE ALREADY REPORTED THEIR OWN RESULT TO THEIR PARENT.
|
|
113
|
+
* THE CHILDREN THAT HAVE ALREADY REPORTED THEIR OWN RESULT TO THEIR PARENT, AND WHEN.
|
|
114
114
|
*
|
|
115
115
|
* A child can report explicitly - the `report` action - and that report is the child's own
|
|
116
116
|
* statement of what it did. When the child's turn then ends, the automatic completion report
|
|
117
117
|
* would deliver the same thing a second time, so the automatic path steps aside for a child that
|
|
118
|
-
* is in this
|
|
118
|
+
* is in this map.
|
|
119
119
|
*
|
|
120
120
|
* The entry is added only by a TERMINAL report (`completed` / `failed`), because an interim
|
|
121
121
|
* update is not the child's final word: the task is still running, and the parent will want to
|
|
122
122
|
* hear how it ended.
|
|
123
|
+
*
|
|
124
|
+
* WHY THE MAP HOLDS A TIMESTAMP AND NOT A FLAG. A flag says "this child reported", and that is
|
|
125
|
+
* not the same question as "this child reported ABOUT THE TURN THAT JUST ENDED". A flag stays
|
|
126
|
+
* true for the rest of the child's life, so it silences every automatic report the child ever
|
|
127
|
+
* produces again: the parent gives the same child a second task, the child finishes, and the
|
|
128
|
+
* result is swallowed because of a report the parent received about the FIRST task. The parent
|
|
129
|
+
* waits for a result that was written and never arrives, and nothing in the transcript says why.
|
|
130
|
+
*
|
|
131
|
+
* The timestamp answers the real question: the report was made INSIDE this turn, so it speaks for
|
|
132
|
+
* this turn. A report made before the turn started speaks for an earlier one, and this turn's
|
|
133
|
+
* result is still its own.
|
|
123
134
|
*/
|
|
124
135
|
private readonly reportedChildren;
|
|
125
136
|
constructor(store: Store, conversationService: ConversationService, runService: RunService, ledger: SessionLedger, broadcaster?: EventBroadcaster | undefined, watchdog?: SessionWatchdog);
|
|
@@ -39,18 +39,29 @@ export class SessionOrchestratorService {
|
|
|
39
39
|
*/
|
|
40
40
|
lengthContinuations = new Map();
|
|
41
41
|
/**
|
|
42
|
-
* THE CHILDREN THAT HAVE ALREADY REPORTED THEIR OWN RESULT TO THEIR PARENT.
|
|
42
|
+
* THE CHILDREN THAT HAVE ALREADY REPORTED THEIR OWN RESULT TO THEIR PARENT, AND WHEN.
|
|
43
43
|
*
|
|
44
44
|
* A child can report explicitly - the `report` action - and that report is the child's own
|
|
45
45
|
* statement of what it did. When the child's turn then ends, the automatic completion report
|
|
46
46
|
* would deliver the same thing a second time, so the automatic path steps aside for a child that
|
|
47
|
-
* is in this
|
|
47
|
+
* is in this map.
|
|
48
48
|
*
|
|
49
49
|
* The entry is added only by a TERMINAL report (`completed` / `failed`), because an interim
|
|
50
50
|
* update is not the child's final word: the task is still running, and the parent will want to
|
|
51
51
|
* hear how it ended.
|
|
52
|
+
*
|
|
53
|
+
* WHY THE MAP HOLDS A TIMESTAMP AND NOT A FLAG. A flag says "this child reported", and that is
|
|
54
|
+
* not the same question as "this child reported ABOUT THE TURN THAT JUST ENDED". A flag stays
|
|
55
|
+
* true for the rest of the child's life, so it silences every automatic report the child ever
|
|
56
|
+
* produces again: the parent gives the same child a second task, the child finishes, and the
|
|
57
|
+
* result is swallowed because of a report the parent received about the FIRST task. The parent
|
|
58
|
+
* waits for a result that was written and never arrives, and nothing in the transcript says why.
|
|
59
|
+
*
|
|
60
|
+
* The timestamp answers the real question: the report was made INSIDE this turn, so it speaks for
|
|
61
|
+
* this turn. A report made before the turn started speaks for an earlier one, and this turn's
|
|
62
|
+
* result is still its own.
|
|
52
63
|
*/
|
|
53
|
-
reportedChildren = new
|
|
64
|
+
reportedChildren = new Map();
|
|
54
65
|
constructor(store, conversationService, runService, ledger, broadcaster, watchdog) {
|
|
55
66
|
this.store = store;
|
|
56
67
|
this.conversationService = conversationService;
|
|
@@ -180,6 +191,11 @@ export class SessionOrchestratorService {
|
|
|
180
191
|
// writes the words under the reader's own name - so the child's transcript showed an
|
|
181
192
|
// instruction the reader never typed, wearing the reader's avatar, and a reader who looked at
|
|
182
193
|
// the child session saw their own name on somebody else's order.
|
|
194
|
+
//
|
|
195
|
+
// THE TURN'S START IS RECORDED HERE, because the question "did this child already report THIS
|
|
196
|
+
// turn?" is answered by comparing the report's time against it. A report made inside the turn
|
|
197
|
+
// speaks for the turn; a report made before it speaks for an earlier one.
|
|
198
|
+
const turnStartedAt = Date.now();
|
|
183
199
|
const runPromise = this.runService.enqueueAndRunAsAgent(conversationId, content);
|
|
184
200
|
const completion = (async () => {
|
|
185
201
|
let failure;
|
|
@@ -238,9 +254,13 @@ export class SessionOrchestratorService {
|
|
|
238
254
|
// is what it produced"; the explicit report says "the child is telling its parent something
|
|
239
255
|
// now", and can be called at any point in the task's life.
|
|
240
256
|
const turnEnded = current?.status === "completed" || current?.status === "failed";
|
|
241
|
-
// A CHILD THAT REPORTED ITSELF IS NOT REPORTED TWICE
|
|
242
|
-
// child's own statement of what it did, so the
|
|
243
|
-
|
|
257
|
+
// A CHILD THAT REPORTED ITSELF IS NOT REPORTED TWICE - BUT ONLY FOR THE TURN IT REPORTED.
|
|
258
|
+
// The explicit terminal report is the child's own statement of what it did, so the
|
|
259
|
+
// automatic completion steps aside for it - when the report was made inside THIS turn.
|
|
260
|
+
// A report from an earlier turn says nothing about this one's result, and silencing this
|
|
261
|
+
// one because of that would swallow a result the parent is still waiting for.
|
|
262
|
+
const reportedAt = this.reportedChildren.get(conversationId);
|
|
263
|
+
const alreadyReported = reportedAt !== undefined && reportedAt >= turnStartedAt;
|
|
244
264
|
if (turnEnded && !alreadyReported) {
|
|
245
265
|
await this.runService.enqueueSessionResult({
|
|
246
266
|
conversationId,
|
|
@@ -260,6 +280,16 @@ export class SessionOrchestratorService {
|
|
|
260
280
|
// turn an already-finished child turn into a second failure.
|
|
261
281
|
console.warn(`Super Pi: session result callback failed for ${conversationId}:`, error instanceof Error ? error.message : String(error));
|
|
262
282
|
}
|
|
283
|
+
finally {
|
|
284
|
+
// THE RECORD IS SPENT BY THE TURN IT SPOKE FOR. Whatever it was about, that turn is over.
|
|
285
|
+
//
|
|
286
|
+
// A record left behind would be harmless - the timestamp comparison already keeps it from
|
|
287
|
+
// silencing a later turn - but it would keep saying "this child reported" to every future
|
|
288
|
+
// reader of this code, and the next thing that consults it would have to re-derive the
|
|
289
|
+
// timestamp rule. Dropping it here keeps one rule in one place: a report belongs to the
|
|
290
|
+
// turn that was running when it was made.
|
|
291
|
+
this.reportedChildren.delete(conversationId);
|
|
292
|
+
}
|
|
263
293
|
if (failure !== undefined) {
|
|
264
294
|
console.warn(`Super Pi: dispatch failed for conversation ${conversationId}:`, failure instanceof Error ? failure.message : String(failure));
|
|
265
295
|
this.ledger.update(conversationId, { status: "failed" });
|
|
@@ -391,7 +421,10 @@ export class SessionOrchestratorService {
|
|
|
391
421
|
// does not silence the automatic report: the child is still working, and the parent will want
|
|
392
422
|
// to hear how the task ended.
|
|
393
423
|
if (status === "completed" || status === "failed") {
|
|
394
|
-
|
|
424
|
+
// THE TIME OF THE REPORT IS THE PART THAT MATTERS. It is what tells the completion path
|
|
425
|
+
// whether this report spoke for the turn that is ending or for an earlier one, and it is
|
|
426
|
+
// stamped here - where the report is made - rather than where it is looked up later.
|
|
427
|
+
this.reportedChildren.set(childConversationId, Date.now());
|
|
395
428
|
await this.watchdog.cancel(childConversationId);
|
|
396
429
|
}
|
|
397
430
|
else {
|