@xfey/tutti 0.1.95 → 0.1.96
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.
|
@@ -48,7 +48,9 @@ function failedResultCanRetry(row, result) {
|
|
|
48
48
|
}
|
|
49
49
|
export function materializeTaskRetryRun(db, input) {
|
|
50
50
|
return withHostStoreTransaction(db, (tx) => {
|
|
51
|
-
const taskRow = tx
|
|
51
|
+
const taskRow = tx
|
|
52
|
+
.prepare("SELECT * FROM tasks WHERE id = ?")
|
|
53
|
+
.get(input.task_id);
|
|
52
54
|
if (taskRow === undefined) {
|
|
53
55
|
return { disposition: { kind: "task_not_failed" } };
|
|
54
56
|
}
|
|
@@ -18,6 +18,7 @@ export declare class Phase5ControlPlane {
|
|
|
18
18
|
private readonly runLifecycle;
|
|
19
19
|
private readonly now;
|
|
20
20
|
private readonly scratchpadAutoRefreshScheduler;
|
|
21
|
+
private pendingWorklistCompletionContextSyncTimer;
|
|
21
22
|
private readonly pendingReferenceSummaryPaths;
|
|
22
23
|
private readonly referenceSummaryWaiters;
|
|
23
24
|
private pendingAllReferenceSummaries;
|
|
@@ -67,7 +68,9 @@ export declare class Phase5ControlPlane {
|
|
|
67
68
|
private tryRunTaskArrivalScheduler;
|
|
68
69
|
private maybeScheduleAfterRunCompletion;
|
|
69
70
|
private worklistCompletionContextSyncTrigger;
|
|
70
|
-
private
|
|
71
|
+
private scheduleContextSyncAfterWorklistCompletion;
|
|
72
|
+
private attemptContextSyncAfterWorklistCompletion;
|
|
73
|
+
private cancelPendingWorklistCompletionContextSync;
|
|
71
74
|
private startTaskCompileContinuation;
|
|
72
75
|
private startTaskBoundFollowUpCheck;
|
|
73
76
|
private publishProcedureTransition;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { readActiveTaskCompileContext, readWorklistProjection, } from "../collaboration-state/index.js";
|
|
1
|
+
import { readActiveTaskCompileContext, readScratchpadSourceState, readWorklistProjection, } from "../collaboration-state/index.js";
|
|
2
2
|
import { ProcedureEngine } from "../procedure-engine/index.js";
|
|
3
3
|
import { RunEngine } from "../run-engine/index.js";
|
|
4
|
-
import { WorkspaceOpsError, readReferenceSummaryTargets
|
|
4
|
+
import { WorkspaceOpsError, readReferenceSummaryTargets } from "../workspace-ops/index.js";
|
|
5
5
|
import { publishProcedureTransition as publishProcedureTransitionEvent, publishRunResultRecorded as publishRunResultRecordedEvent, publishRunTransition as publishRunTransitionEvent, publishTaskRunStarted as publishTaskRunStartedEvent, } from "./event-publishers.js";
|
|
6
6
|
import { startContextSyncAnalysisProcedure } from "./context-sync.js";
|
|
7
7
|
import { refreshProjectBriefProjection, } from "./project-brief-refresh.js";
|
|
@@ -19,6 +19,7 @@ import { startControlPlaneRunForTask } from "./run-start.js";
|
|
|
19
19
|
import { retryControlPlaneTask } from "./run-retry.js";
|
|
20
20
|
import { runSendClarificationRoundMessage, runSubmitClarificationRound, } from "./clarification-commands.js";
|
|
21
21
|
import { emitTaskCompletedResultMessage, emitTaskFailedResultMessage, } from "./worklist-terminal-feedback.js";
|
|
22
|
+
const WORKLIST_COMPLETION_CONTEXT_SYNC_GRACE_MS = 30_000;
|
|
22
23
|
export class Phase5ControlPlane {
|
|
23
24
|
engine;
|
|
24
25
|
runEngine;
|
|
@@ -33,6 +34,7 @@ export class Phase5ControlPlane {
|
|
|
33
34
|
runLifecycle;
|
|
34
35
|
now;
|
|
35
36
|
scratchpadAutoRefreshScheduler;
|
|
37
|
+
pendingWorklistCompletionContextSyncTimer = null;
|
|
36
38
|
pendingReferenceSummaryPaths = new Set();
|
|
37
39
|
referenceSummaryWaiters = new Map();
|
|
38
40
|
pendingAllReferenceSummaries = false;
|
|
@@ -112,6 +114,7 @@ export class Phase5ControlPlane {
|
|
|
112
114
|
});
|
|
113
115
|
}
|
|
114
116
|
startScratchpadRefresh(options = {}) {
|
|
117
|
+
this.cancelPendingWorklistCompletionContextSync();
|
|
115
118
|
return startControlPlaneScratchpadRefresh({
|
|
116
119
|
engine: this.engine,
|
|
117
120
|
store: this.store,
|
|
@@ -128,6 +131,7 @@ export class Phase5ControlPlane {
|
|
|
128
131
|
if (!shouldUseMessageAsScratchpadSource(message)) {
|
|
129
132
|
return;
|
|
130
133
|
}
|
|
134
|
+
this.cancelPendingWorklistCompletionContextSync();
|
|
131
135
|
this.scratchpadAutoRefreshScheduler.notifySourceChanged();
|
|
132
136
|
}
|
|
133
137
|
refreshProjectBrief(options) {
|
|
@@ -148,6 +152,7 @@ export class Phase5ControlPlane {
|
|
|
148
152
|
}
|
|
149
153
|
this.closing = true;
|
|
150
154
|
this.scratchpadAutoRefreshScheduler.dispose();
|
|
155
|
+
this.cancelPendingWorklistCompletionContextSync();
|
|
151
156
|
this.pendingAllReferenceSummaries = false;
|
|
152
157
|
this.pendingReferenceSummaryPaths.clear();
|
|
153
158
|
}
|
|
@@ -171,6 +176,7 @@ export class Phase5ControlPlane {
|
|
|
171
176
|
}
|
|
172
177
|
}
|
|
173
178
|
startTaskCompile(payload) {
|
|
179
|
+
this.cancelPendingWorklistCompletionContextSync();
|
|
174
180
|
const activeRun = this.readActiveRun();
|
|
175
181
|
if (activeRun !== null) {
|
|
176
182
|
return {
|
|
@@ -211,6 +217,9 @@ export class Phase5ControlPlane {
|
|
|
211
217
|
});
|
|
212
218
|
}
|
|
213
219
|
startContextSyncAnalysis(trigger = { kind: "manual" }) {
|
|
220
|
+
if (trigger.kind === "manual") {
|
|
221
|
+
this.cancelPendingWorklistCompletionContextSync();
|
|
222
|
+
}
|
|
214
223
|
return startContextSyncAnalysisProcedure({
|
|
215
224
|
engine: this.engine,
|
|
216
225
|
store: this.store,
|
|
@@ -366,6 +375,7 @@ export class Phase5ControlPlane {
|
|
|
366
375
|
publishRunResultRecorded: (recorded) => this.publishRunResultRecorded(recorded),
|
|
367
376
|
});
|
|
368
377
|
if (result.kind === "accepted") {
|
|
378
|
+
this.cancelPendingWorklistCompletionContextSync();
|
|
369
379
|
this.runLifecycle?.started();
|
|
370
380
|
}
|
|
371
381
|
return result;
|
|
@@ -497,7 +507,7 @@ export class Phase5ControlPlane {
|
|
|
497
507
|
if (this.tryRunTaskArrivalScheduler()) {
|
|
498
508
|
return;
|
|
499
509
|
}
|
|
500
|
-
this.
|
|
510
|
+
this.scheduleContextSyncAfterWorklistCompletion();
|
|
501
511
|
}
|
|
502
512
|
worklistCompletionContextSyncTrigger() {
|
|
503
513
|
const worklist = readWorklistProjection(this.store.db);
|
|
@@ -511,16 +521,46 @@ export class Phase5ControlPlane {
|
|
|
511
521
|
module_count: worklist.modules.length,
|
|
512
522
|
};
|
|
513
523
|
}
|
|
514
|
-
|
|
515
|
-
if (this.closing
|
|
524
|
+
scheduleContextSyncAfterWorklistCompletion() {
|
|
525
|
+
if (this.closing ||
|
|
526
|
+
!this.store.db.open ||
|
|
527
|
+
this.pendingWorklistCompletionContextSyncTimer !== null) {
|
|
528
|
+
return;
|
|
529
|
+
}
|
|
530
|
+
const sourceState = readScratchpadSourceState(this.store.db);
|
|
531
|
+
if (this.worklistCompletionContextSyncTrigger() === undefined ||
|
|
532
|
+
sourceState.dirty_since !== undefined ||
|
|
533
|
+
sourceState.in_flight !== undefined ||
|
|
534
|
+
this.readSchedulerBlocker() !== null) {
|
|
535
|
+
return;
|
|
536
|
+
}
|
|
537
|
+
this.pendingWorklistCompletionContextSyncTimer = setTimeout(() => {
|
|
538
|
+
this.attemptContextSyncAfterWorklistCompletion();
|
|
539
|
+
}, WORKLIST_COMPLETION_CONTEXT_SYNC_GRACE_MS);
|
|
540
|
+
this.pendingWorklistCompletionContextSyncTimer.unref?.();
|
|
541
|
+
}
|
|
542
|
+
attemptContextSyncAfterWorklistCompletion() {
|
|
543
|
+
this.pendingWorklistCompletionContextSyncTimer = null;
|
|
544
|
+
if (this.closing || !this.store.db.open) {
|
|
516
545
|
return;
|
|
517
546
|
}
|
|
518
547
|
const trigger = this.worklistCompletionContextSyncTrigger();
|
|
519
|
-
|
|
548
|
+
const sourceState = readScratchpadSourceState(this.store.db);
|
|
549
|
+
if (trigger === undefined ||
|
|
550
|
+
sourceState.dirty_since !== undefined ||
|
|
551
|
+
sourceState.in_flight !== undefined ||
|
|
552
|
+
this.readSchedulerBlocker() !== null) {
|
|
520
553
|
return;
|
|
521
554
|
}
|
|
522
555
|
void this.startContextSyncAnalysis(trigger);
|
|
523
556
|
}
|
|
557
|
+
cancelPendingWorklistCompletionContextSync() {
|
|
558
|
+
if (this.pendingWorklistCompletionContextSyncTimer === null) {
|
|
559
|
+
return;
|
|
560
|
+
}
|
|
561
|
+
clearTimeout(this.pendingWorklistCompletionContextSyncTimer);
|
|
562
|
+
this.pendingWorklistCompletionContextSyncTimer = null;
|
|
563
|
+
}
|
|
524
564
|
startTaskCompileContinuation(owner, roundId) {
|
|
525
565
|
let tasksAdded = false;
|
|
526
566
|
return startControlPlaneTaskCompileContinuation({
|
|
@@ -570,6 +610,9 @@ export class Phase5ControlPlane {
|
|
|
570
610
|
});
|
|
571
611
|
}
|
|
572
612
|
publishProcedureTransition(state) {
|
|
613
|
+
if (state.transition_kind === "started" && state.activity.lane === "foreground") {
|
|
614
|
+
this.cancelPendingWorklistCompletionContextSync();
|
|
615
|
+
}
|
|
573
616
|
this.logProcedureTransition(state);
|
|
574
617
|
publishProcedureTransitionEvent({
|
|
575
618
|
events: this.events,
|
|
@@ -596,6 +639,11 @@ export class Phase5ControlPlane {
|
|
|
596
639
|
}
|
|
597
640
|
if (!this.closing) {
|
|
598
641
|
this.schedulePendingReferenceSummaryRefresh();
|
|
642
|
+
if (state.activity.status === "finished" &&
|
|
643
|
+
(state.activity.workflow_kind === "scratchpad_refresh" ||
|
|
644
|
+
state.activity.workflow_kind === "reference_summary_refresh")) {
|
|
645
|
+
this.scheduleContextSyncAfterWorklistCompletion();
|
|
646
|
+
}
|
|
599
647
|
}
|
|
600
648
|
}
|
|
601
649
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { createMainChatAgentMessage, markScratchpadRefreshSucceeded,
|
|
2
|
-
import { mainChatInvalidates, scratchpadRefreshInvalidates
|
|
1
|
+
import { createMainChatAgentMessage, markScratchpadRefreshSucceeded, upsertScratchpadProjection, } from "../collaboration-state/index.js";
|
|
2
|
+
import { mainChatInvalidates, scratchpadRefreshInvalidates } from "./invalidations.js";
|
|
3
3
|
export function applyScratchpadRefreshOutput(input) {
|
|
4
4
|
if (input.output.decision === "needs_human") {
|
|
5
5
|
const message = createMainChatAgentMessage(input.store.db, {
|
|
@@ -7,7 +7,7 @@ export function applyScratchpadRefreshOutput(input) {
|
|
|
7
7
|
refs: {
|
|
8
8
|
workflow_ref: input.workflowRef,
|
|
9
9
|
activity_ref: input.activityRef,
|
|
10
|
-
scratchpad_source: "
|
|
10
|
+
scratchpad_source: "exclude",
|
|
11
11
|
},
|
|
12
12
|
now: input.now,
|
|
13
13
|
});
|
|
@@ -20,7 +20,6 @@ export function applyScratchpadRefreshOutput(input) {
|
|
|
20
20
|
...input.cursorUpdate,
|
|
21
21
|
now: input.now,
|
|
22
22
|
});
|
|
23
|
-
markScratchpadSourceDirty(input.store.db, { now: input.now });
|
|
24
23
|
return {
|
|
25
24
|
kind: "needs_human",
|
|
26
25
|
summary: input.output.request_payload.summary,
|
|
@@ -291,11 +291,9 @@ export function acquireCodexTaskSessionLock(session) {
|
|
|
291
291
|
throw error;
|
|
292
292
|
}
|
|
293
293
|
const lockValue = readJson(lockPath);
|
|
294
|
-
const ownerPid = isRecord(lockValue) && typeof lockValue.owner_pid === "number"
|
|
295
|
-
? lockValue.owner_pid
|
|
296
|
-
: null;
|
|
294
|
+
const ownerPid = isRecord(lockValue) && typeof lockValue.owner_pid === "number" ? lockValue.owner_pid : null;
|
|
297
295
|
if (ownerPid !== null && isProcessAlive(ownerPid)) {
|
|
298
|
-
throw new Error("Codex task session already has an active turn owner.");
|
|
296
|
+
throw new Error("Codex task session already has an active turn owner.", { cause: error });
|
|
299
297
|
}
|
|
300
298
|
unlinkSync(lockPath);
|
|
301
299
|
}
|