@xfey/tutti 0.1.60 → 0.1.62
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/README.md +2 -2
- package/dist/collaboration-state/clarification-records.d.ts +0 -9
- package/dist/collaboration-state/clarification-records.js +0 -57
- package/dist/collaboration-state/index.d.ts +6 -5
- package/dist/collaboration-state/index.js +5 -4
- package/dist/collaboration-state/messages.d.ts +4 -6
- package/dist/collaboration-state/messages.js +22 -29
- package/dist/collaboration-state/scratchpad-source-state.d.ts +4 -12
- package/dist/collaboration-state/scratchpad-source-state.js +24 -58
- package/dist/collaboration-state/scratchpad.d.ts +1 -2
- package/dist/collaboration-state/scratchpad.js +0 -59
- package/dist/collaboration-state/storage-types.d.ts +25 -5
- package/dist/collaboration-state/task-compile-context.d.ts +40 -0
- package/dist/collaboration-state/task-compile-context.js +273 -0
- package/dist/collaboration-state/types.d.ts +39 -9
- package/dist/control-plane/clarification-commands.d.ts +0 -1
- package/dist/control-plane/clarification-commands.js +0 -1
- package/dist/control-plane/index.js +16 -3
- package/dist/control-plane/project-context-bootstrap.d.ts +4 -4
- package/dist/control-plane/project-context-bootstrap.js +7 -12
- package/dist/control-plane/scratchpad-auto-refresh.js +12 -1
- package/dist/control-plane/scratchpad-refresh-start.js +77 -94
- package/dist/control-plane/scratchpad-refresh.js +3 -1
- package/dist/control-plane/scratchpad-source-messages.d.ts +15 -7
- package/dist/control-plane/scratchpad-source-messages.js +53 -69
- package/dist/control-plane/task-compile-clarification-context.d.ts +9 -0
- package/dist/control-plane/task-compile-clarification-context.js +70 -0
- package/dist/control-plane/task-compile-continuation.js +28 -56
- package/dist/control-plane/task-compile-output.js +50 -14
- package/dist/control-plane/task-compile-start.js +119 -55
- package/dist/control-plane/workflows/openai.d.ts +2 -1
- package/dist/control-plane/workflows/openai.js +13 -27
- package/dist/control-plane/workflows/types.d.ts +27 -17
- package/dist/server-shell/cli/args.d.ts +4 -0
- package/dist/server-shell/cli/args.js +11 -0
- package/dist/server-shell/cli/cli.js +35 -11
- package/dist/server-shell/cli/host-server-runtime.d.ts +2 -0
- package/dist/server-shell/cli/host-server-runtime.js +12 -5
- package/dist/server-shell/cli/local-control-client.d.ts +5 -1
- package/dist/server-shell/cli/local-control-client.js +19 -0
- package/dist/server-shell/desktop-integration/manager.d.ts +2 -0
- package/dist/server-shell/desktop-integration/manager.js +19 -31
- package/dist/server-shell/http/routes/local-control.d.ts +2 -0
- package/dist/server-shell/http/routes/local-control.js +24 -0
- package/dist/server-shell/local-console/invocation-context.js +10 -1
- package/dist/server-shell/local-console/operation-coordinator.d.ts +16 -0
- package/dist/server-shell/local-console/operation-coordinator.js +50 -0
- package/dist/server-shell/local-console/package-update-completion.d.ts +25 -0
- package/dist/server-shell/local-console/package-update-completion.js +91 -0
- package/dist/server-shell/local-console/package-update-hosts.d.ts +17 -0
- package/dist/server-shell/local-console/package-update-hosts.js +92 -0
- package/dist/server-shell/local-console/package-update-lock.d.ts +46 -0
- package/dist/server-shell/local-console/package-update-lock.js +223 -0
- package/dist/server-shell/local-console/package-update-log.d.ts +20 -0
- package/dist/server-shell/local-console/package-update-log.js +75 -0
- package/dist/server-shell/local-console/package-update-process.d.ts +22 -0
- package/dist/server-shell/local-console/package-update-process.js +252 -0
- package/dist/server-shell/local-console/package-update-record.d.ts +53 -0
- package/dist/server-shell/local-console/package-update-record.js +180 -0
- package/dist/server-shell/local-console/package-update-recovery.d.ts +34 -0
- package/dist/server-shell/local-console/package-update-recovery.js +140 -0
- package/dist/server-shell/local-console/package-update-service.d.ts +72 -0
- package/dist/server-shell/local-console/package-update-service.js +400 -0
- package/dist/server-shell/local-console/package-update-worker.d.ts +55 -0
- package/dist/server-shell/local-console/package-update-worker.js +297 -0
- package/dist/server-shell/local-console/project-service.d.ts +2 -0
- package/dist/server-shell/local-console/project-service.js +16 -12
- package/dist/server-shell/local-console/server.d.ts +9 -0
- package/dist/server-shell/local-console/server.js +92 -4
- package/dist/server-shell/package-installation/command.d.ts +36 -0
- package/dist/server-shell/package-installation/command.js +162 -0
- package/dist/server-shell/package-installation/discovery.d.ts +51 -0
- package/dist/server-shell/package-installation/discovery.js +137 -0
- package/dist/server-shell/package-installation/index.d.ts +5 -0
- package/dist/server-shell/package-installation/index.js +5 -0
- package/dist/server-shell/package-installation/installation.d.ts +34 -0
- package/dist/server-shell/package-installation/installation.js +123 -0
- package/dist/server-shell/package-installation/semver.d.ts +9 -0
- package/dist/server-shell/package-installation/semver.js +84 -0
- package/migrations/0014_scratchpad_task_compile_context.sql +147 -0
- package/migrations/README.md +2 -1
- package/package.json +1 -1
- package/prompts/procedures/README.md +3 -3
- package/prompts/procedures/scratchpad-refresh.md +17 -9
- package/prompts/procedures/task-compile.md +6 -3
- package/prompts/prompt-flow-map.md +21 -14
- package/web/assets/{homepage-motion-scene-CY7o4hnR.js → homepage-motion-scene-CRmrkkEH.js} +1 -1
- package/web/assets/{index-B08r3x8o.js → index-C9JrplHV.js} +14 -14
- package/web/assets/{index-DpabiRgp.css → index-IZKcmU_g.css} +1 -1
- package/web/index.html +2 -2
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { applyTaskCompileProposal, openNextTaskCompileClarificationRound, openTaskCompileClarificationRound,
|
|
1
|
+
import { applyTaskCompileProposal, completeTaskCompileContext, materializeClarificationSuccessor, openNextTaskCompileClarificationRound, openTaskCompileClarificationRound, readClarificationRoundProjection, readWorklistProjection, } from "../collaboration-state/index.js";
|
|
2
|
+
import { withHostStoreTransaction } from "../store/index.js";
|
|
2
3
|
import { clarificationInvalidates, taskCompileInvalidates, } from "./invalidations.js";
|
|
3
4
|
import { normalizeTaskCompileProposal } from "./task-proposal.js";
|
|
4
5
|
const EMPTY_INITIAL_WORKLIST_CLARIFICATION = {
|
|
@@ -72,25 +73,45 @@ export function applyTaskCompileProcedureOutput(input) {
|
|
|
72
73
|
}
|
|
73
74
|
const currentWorklist = readWorklistProjection(input.store.db);
|
|
74
75
|
const proposal = normalizeTaskCompileProposal(input.output.proposal);
|
|
75
|
-
if (
|
|
76
|
+
if (input.continueFromRoundId === undefined &&
|
|
77
|
+
proposal.tasks.length === 0 &&
|
|
78
|
+
countWorklistTasks(currentWorklist) === 0) {
|
|
76
79
|
return openTaskCompileNeedsHuman({
|
|
77
80
|
...input,
|
|
78
81
|
requestPayload: EMPTY_INITIAL_WORKLIST_CLARIFICATION,
|
|
79
82
|
});
|
|
80
83
|
}
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
84
|
+
const continuationRound = input.continueFromRoundId === undefined
|
|
85
|
+
? null
|
|
86
|
+
: readClarificationRoundProjection(input.store.db, input.continueFromRoundId);
|
|
87
|
+
const committed = withHostStoreTransaction(input.store.db, (tx) => {
|
|
88
|
+
const applied = applyTaskCompileProposal(tx, {
|
|
89
|
+
workflow_ref: input.workflowRef,
|
|
90
|
+
proposal,
|
|
91
|
+
now: input.now,
|
|
92
|
+
});
|
|
93
|
+
const scratchpad = completeTaskCompileContext(tx, {
|
|
94
|
+
workflow_ref: input.workflowRef,
|
|
95
|
+
activity_ref: input.activityRef,
|
|
96
|
+
now: input.now,
|
|
97
|
+
});
|
|
98
|
+
if (input.continueFromRoundId !== undefined) {
|
|
99
|
+
materializeClarificationSuccessor(tx, {
|
|
100
|
+
round_id: input.continueFromRoundId,
|
|
101
|
+
successor_ref: {
|
|
102
|
+
kind: "proposal_applied",
|
|
103
|
+
workflow_ref: input.workflowRef,
|
|
104
|
+
},
|
|
105
|
+
close_thread: true,
|
|
106
|
+
now: input.now,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
return { applied, scratchpad };
|
|
85
110
|
});
|
|
111
|
+
const { applied } = committed;
|
|
86
112
|
if (applied.changed_task_ids.length > 0) {
|
|
87
113
|
input.onTasksAdded?.();
|
|
88
114
|
}
|
|
89
|
-
const submittedScratchpad = submitScratchpadProjection(input.store.db, {
|
|
90
|
-
workflow_ref: input.workflowRef,
|
|
91
|
-
activity_ref: input.activityRef,
|
|
92
|
-
now: input.now,
|
|
93
|
-
});
|
|
94
115
|
input.events.publish({
|
|
95
116
|
event_type: "worklist.changed",
|
|
96
117
|
payload: {
|
|
@@ -105,21 +126,36 @@ export function applyTaskCompileProcedureOutput(input) {
|
|
|
105
126
|
input.events.publish({
|
|
106
127
|
event_type: "scratchpad.updated",
|
|
107
128
|
payload: {
|
|
108
|
-
scratchpad:
|
|
129
|
+
scratchpad: committed.scratchpad,
|
|
109
130
|
activity_ref: input.activityRef,
|
|
110
131
|
},
|
|
111
132
|
invalidates: taskCompileInvalidates(),
|
|
112
133
|
});
|
|
134
|
+
if (input.continueFromRoundId !== undefined && continuationRound !== null) {
|
|
135
|
+
input.events.publish({
|
|
136
|
+
event_type: "clarification.changed",
|
|
137
|
+
payload: {
|
|
138
|
+
reason: "successor_materialized",
|
|
139
|
+
thread_id: continuationRound.thread_id,
|
|
140
|
+
round_id: input.continueFromRoundId,
|
|
141
|
+
successor_ref: {
|
|
142
|
+
kind: "proposal_applied",
|
|
143
|
+
workflow_ref: input.workflowRef,
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
invalidates: clarificationInvalidates(input.continueFromRoundId, continuationRound.thread_id),
|
|
147
|
+
});
|
|
148
|
+
}
|
|
113
149
|
if (input.continueFromRoundId !== undefined) {
|
|
114
150
|
return {
|
|
115
151
|
kind: "completed",
|
|
116
|
-
summary: "Worklist compiled.",
|
|
152
|
+
summary: proposal.tasks.length === 0 ? "No new task created." : "Worklist compiled.",
|
|
117
153
|
result_anchor: { kind: "workflow", workflow_ref: input.workflowRef },
|
|
118
154
|
};
|
|
119
155
|
}
|
|
120
156
|
return {
|
|
121
157
|
kind: "completed",
|
|
122
|
-
summary: "Worklist compiled.",
|
|
158
|
+
summary: proposal.tasks.length === 0 ? "No new task created." : "Worklist compiled.",
|
|
123
159
|
result_anchor: { kind: "workflow", workflow_ref: input.workflowRef },
|
|
124
160
|
};
|
|
125
161
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createWorkflowInvocationRef, } from "@tutti/shared/ids";
|
|
2
|
-
import { readScratchpadProjection, readWorklistProjection } from "../collaboration-state/index.js";
|
|
2
|
+
import { captureTaskCompileContext, readActiveTaskCompileContext, readScratchpadProjection, readWorklistProjection, rollbackTaskCompileContext, } from "../collaboration-state/index.js";
|
|
3
3
|
import { initializeProjectDocs, readProjectDocsInitializationStatus, } from "../workspace-ops/index.js";
|
|
4
4
|
import { logProcedureExecutionError } from "./procedure-logging.js";
|
|
5
5
|
import { projectBriefShouldRefreshForUpdatedPaths, refreshProjectBriefProjection, } from "./project-brief-refresh.js";
|
|
@@ -7,6 +7,15 @@ import { applyProjectDocsInitializationResult, buildProjectDocsInitializationCon
|
|
|
7
7
|
import { readActiveScratchpadRefreshActivityRef, readControlPlaneScratchpadSourceBatch, runControlPlaneScratchpadRefreshProcedure, } from "./scratchpad-refresh-start.js";
|
|
8
8
|
import { applyTaskCompileProcedureOutput } from "./task-compile-output.js";
|
|
9
9
|
export function startControlPlaneTaskCompile(options) {
|
|
10
|
+
const activeContext = readActiveTaskCompileContext(options.store.db);
|
|
11
|
+
if (activeContext !== null) {
|
|
12
|
+
return {
|
|
13
|
+
disposition: {
|
|
14
|
+
kind: "already_running",
|
|
15
|
+
activity_ref: activeContext.captured_by_activity_ref,
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
}
|
|
10
19
|
const scratchpad = readScratchpadProjection(options.store.db);
|
|
11
20
|
if (options.payload.expected_scratchpad_updated_at !== undefined &&
|
|
12
21
|
options.payload.expected_scratchpad_updated_at !== scratchpad.updated_at) {
|
|
@@ -31,6 +40,7 @@ export function startControlPlaneTaskCompile(options) {
|
|
|
31
40
|
},
|
|
32
41
|
};
|
|
33
42
|
}
|
|
43
|
+
const taskCompileWorkflowRef = createWorkflowInvocationRef();
|
|
34
44
|
const sourceBatch = readControlPlaneScratchpadSourceBatch(options.store);
|
|
35
45
|
if (sourceBatch.source_message_count > 0) {
|
|
36
46
|
const activeScratchpadRefresh = readActiveScratchpadRefreshActivityRef({
|
|
@@ -49,6 +59,7 @@ export function startControlPlaneTaskCompile(options) {
|
|
|
49
59
|
...options,
|
|
50
60
|
runner: runnerResolution.runner,
|
|
51
61
|
sourceBatch,
|
|
62
|
+
taskCompileWorkflowRef,
|
|
52
63
|
});
|
|
53
64
|
}
|
|
54
65
|
if (!scratchpadHasSubmittableContent(scratchpad)) {
|
|
@@ -58,19 +69,23 @@ export function startControlPlaneTaskCompile(options) {
|
|
|
58
69
|
return startProjectContextBootstrapActivity({
|
|
59
70
|
...options,
|
|
60
71
|
runner: runnerResolution.runner,
|
|
72
|
+
taskCompileWorkflowRef,
|
|
61
73
|
});
|
|
62
74
|
}
|
|
63
75
|
return startControlPlaneTaskCompileActivity({
|
|
64
76
|
...options,
|
|
65
77
|
runner: runnerResolution.runner,
|
|
78
|
+
taskCompileWorkflowRef,
|
|
66
79
|
});
|
|
67
80
|
}
|
|
68
81
|
function startControlPlaneTaskCompileActivity(options) {
|
|
82
|
+
const activeContext = readActiveTaskCompileContext(options.store.db, options.taskCompileWorkflowRef);
|
|
69
83
|
const scratchpad = readScratchpadProjection(options.store.db);
|
|
70
|
-
if (
|
|
84
|
+
if (activeContext === null &&
|
|
85
|
+
!scratchpadHasSubmittableContent(scratchpad)) {
|
|
71
86
|
return { disposition: { kind: "scratchpad_empty" } };
|
|
72
87
|
}
|
|
73
|
-
const workflowRef =
|
|
88
|
+
const workflowRef = options.taskCompileWorkflowRef;
|
|
74
89
|
const start = options.engine.startProcedure({
|
|
75
90
|
workflow_ref: workflowRef,
|
|
76
91
|
workflow_kind: "task_compile",
|
|
@@ -201,8 +216,7 @@ function startProjectContextBootstrapActivity(options) {
|
|
|
201
216
|
if (shouldInitializeControlPlaneProjectContext(options)) {
|
|
202
217
|
return;
|
|
203
218
|
}
|
|
204
|
-
|
|
205
|
-
if (!scratchpadHasSubmittableContent(scratchpad)) {
|
|
219
|
+
if (readActiveTaskCompileContext(options.store.db, options.taskCompileWorkflowRef) === null) {
|
|
206
220
|
return;
|
|
207
221
|
}
|
|
208
222
|
void startControlPlaneTaskCompileActivity(options);
|
|
@@ -221,44 +235,59 @@ function startProjectContextBootstrapActivity(options) {
|
|
|
221
235
|
summary: "Project context is unavailable.",
|
|
222
236
|
};
|
|
223
237
|
}
|
|
224
|
-
const
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
projectContext: options.projectContext,
|
|
228
|
-
scratchpad: readScratchpadProjection(options.store.db),
|
|
229
|
-
projectName: options.projectContext.projectName,
|
|
230
|
-
workflowRef,
|
|
238
|
+
const taskCompileContext = readOrCaptureTaskCompileContext({
|
|
239
|
+
store: options.store,
|
|
240
|
+
workflowRef: options.taskCompileWorkflowRef,
|
|
231
241
|
activityRef: context.activity_ref,
|
|
232
|
-
logger: options.logger,
|
|
233
|
-
reportProgress: context.reportProgress,
|
|
234
|
-
now: options.now,
|
|
235
|
-
});
|
|
236
|
-
const initialized = initializeProjectDocs({
|
|
237
|
-
workspaceRoot: options.projectContext.workspaceRoot,
|
|
238
|
-
projectName: options.projectContext.projectName,
|
|
239
|
-
context: initializationContext,
|
|
240
|
-
...(modelDocuments === undefined ? {} : { documents: modelDocuments }),
|
|
241
242
|
now: options.now,
|
|
242
243
|
});
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
projectContext: options.projectContext,
|
|
247
|
-
reason: "project_context_bootstrap",
|
|
244
|
+
try {
|
|
245
|
+
const initializationContext = buildProjectDocsInitializationContext(taskCompileContext.scratchpad_snapshot);
|
|
246
|
+
const modelDocuments = await tryProjectContextBootstrapDocuments({
|
|
248
247
|
runner: options.runner,
|
|
248
|
+
projectContext: options.projectContext,
|
|
249
|
+
scratchpad: taskCompileContext.scratchpad_snapshot,
|
|
250
|
+
projectName: options.projectContext.projectName,
|
|
249
251
|
workflowRef,
|
|
250
252
|
activityRef: context.activity_ref,
|
|
251
253
|
logger: options.logger,
|
|
254
|
+
reportProgress: context.reportProgress,
|
|
255
|
+
now: options.now,
|
|
256
|
+
});
|
|
257
|
+
const initialized = initializeProjectDocs({
|
|
258
|
+
workspaceRoot: options.projectContext.workspaceRoot,
|
|
259
|
+
projectName: options.projectContext.projectName,
|
|
260
|
+
context: initializationContext,
|
|
261
|
+
...(modelDocuments === undefined ? {} : { documents: modelDocuments }),
|
|
262
|
+
now: options.now,
|
|
263
|
+
});
|
|
264
|
+
if (projectBriefShouldRefreshForUpdatedPaths(initialized.created_paths)) {
|
|
265
|
+
await refreshProjectBriefProjection({
|
|
266
|
+
store: options.store,
|
|
267
|
+
projectContext: options.projectContext,
|
|
268
|
+
reason: "project_context_bootstrap",
|
|
269
|
+
runner: options.runner,
|
|
270
|
+
workflowRef,
|
|
271
|
+
activityRef: context.activity_ref,
|
|
272
|
+
logger: options.logger,
|
|
273
|
+
now: options.now,
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
return applyProjectDocsInitializationResult({
|
|
277
|
+
events: options.events,
|
|
278
|
+
logger: options.logger,
|
|
279
|
+
result: initialized,
|
|
280
|
+
workflowRef,
|
|
281
|
+
activityRef: context.activity_ref,
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
catch (error) {
|
|
285
|
+
rollbackTaskCompileContext(options.store.db, {
|
|
286
|
+
workflow_ref: options.taskCompileWorkflowRef,
|
|
252
287
|
now: options.now,
|
|
253
288
|
});
|
|
289
|
+
throw error;
|
|
254
290
|
}
|
|
255
|
-
return applyProjectDocsInitializationResult({
|
|
256
|
-
events: options.events,
|
|
257
|
-
logger: options.logger,
|
|
258
|
-
result: initialized,
|
|
259
|
-
workflowRef,
|
|
260
|
-
activityRef: context.activity_ref,
|
|
261
|
-
});
|
|
262
291
|
},
|
|
263
292
|
});
|
|
264
293
|
if (start.kind === "already_running") {
|
|
@@ -278,33 +307,59 @@ function startProjectContextBootstrapActivity(options) {
|
|
|
278
307
|
};
|
|
279
308
|
}
|
|
280
309
|
export async function runControlPlaneTaskCompileProcedure(options) {
|
|
281
|
-
const
|
|
282
|
-
if (!scratchpadHasSubmittableContent(scratchpad)) {
|
|
283
|
-
return {
|
|
284
|
-
kind: "failed",
|
|
285
|
-
summary: "Scratchpad is empty. Discuss more before running.",
|
|
286
|
-
};
|
|
287
|
-
}
|
|
288
|
-
const output = await options.runner.runTaskCompile({
|
|
289
|
-
workflow_ref: options.workflowRef,
|
|
290
|
-
scratchpad,
|
|
291
|
-
worklist: readWorklistProjection(options.store.db),
|
|
292
|
-
}, {
|
|
293
|
-
workflow_ref: options.workflowRef,
|
|
294
|
-
activity_ref: options.activityRef,
|
|
295
|
-
...(options.reportProgress === undefined
|
|
296
|
-
? {}
|
|
297
|
-
: { reportProgress: options.reportProgress }),
|
|
298
|
-
});
|
|
299
|
-
return applyTaskCompileProcedureOutput({
|
|
310
|
+
const context = readOrCaptureTaskCompileContext({
|
|
300
311
|
store: options.store,
|
|
301
|
-
events: options.events,
|
|
302
|
-
output,
|
|
303
312
|
workflowRef: options.workflowRef,
|
|
304
313
|
activityRef: options.activityRef,
|
|
305
314
|
now: options.now,
|
|
306
|
-
onTasksAdded: options.onTasksAdded,
|
|
307
315
|
});
|
|
316
|
+
if (!scratchpadSnapshotHasSubmittableContent(context.scratchpad_snapshot)) {
|
|
317
|
+
rollbackTaskCompileContext(options.store.db, {
|
|
318
|
+
workflow_ref: options.workflowRef,
|
|
319
|
+
now: options.now,
|
|
320
|
+
});
|
|
321
|
+
return {
|
|
322
|
+
kind: "failed",
|
|
323
|
+
summary: "Scratchpad is empty. Discuss more before running.",
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
try {
|
|
327
|
+
const output = await options.runner.runTaskCompile({
|
|
328
|
+
workflow_ref: options.workflowRef,
|
|
329
|
+
scratchpad: context.scratchpad_snapshot,
|
|
330
|
+
worklist: readWorklistProjection(options.store.db),
|
|
331
|
+
}, {
|
|
332
|
+
workflow_ref: options.workflowRef,
|
|
333
|
+
activity_ref: options.activityRef,
|
|
334
|
+
...(options.reportProgress === undefined
|
|
335
|
+
? {}
|
|
336
|
+
: { reportProgress: options.reportProgress }),
|
|
337
|
+
});
|
|
338
|
+
return applyTaskCompileProcedureOutput({
|
|
339
|
+
store: options.store,
|
|
340
|
+
events: options.events,
|
|
341
|
+
output,
|
|
342
|
+
workflowRef: options.workflowRef,
|
|
343
|
+
activityRef: options.activityRef,
|
|
344
|
+
now: options.now,
|
|
345
|
+
onTasksAdded: options.onTasksAdded,
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
catch (error) {
|
|
349
|
+
rollbackTaskCompileContext(options.store.db, {
|
|
350
|
+
workflow_ref: options.workflowRef,
|
|
351
|
+
now: options.now,
|
|
352
|
+
});
|
|
353
|
+
throw error;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
function readOrCaptureTaskCompileContext(input) {
|
|
357
|
+
return (readActiveTaskCompileContext(input.store.db, input.workflowRef) ??
|
|
358
|
+
captureTaskCompileContext(input.store.db, {
|
|
359
|
+
workflow_ref: input.workflowRef,
|
|
360
|
+
captured_by_activity_ref: input.activityRef,
|
|
361
|
+
now: input.now,
|
|
362
|
+
}));
|
|
308
363
|
}
|
|
309
364
|
function scratchpadHasSubmittableContent(scratchpad) {
|
|
310
365
|
if (scratchpad.state !== "ready") {
|
|
@@ -318,4 +373,13 @@ function scratchpadHasSubmittableContent(scratchpad) {
|
|
|
318
373
|
...scratchpad.task_changes,
|
|
319
374
|
].some((item) => item.trim().length > 0);
|
|
320
375
|
}
|
|
376
|
+
function scratchpadSnapshotHasSubmittableContent(scratchpad) {
|
|
377
|
+
return [
|
|
378
|
+
scratchpad.topic,
|
|
379
|
+
scratchpad.background_summary,
|
|
380
|
+
...scratchpad.current_consensus,
|
|
381
|
+
...scratchpad.open_questions,
|
|
382
|
+
...scratchpad.task_changes,
|
|
383
|
+
].some((item) => item.trim().length > 0);
|
|
384
|
+
}
|
|
321
385
|
//# sourceMappingURL=task-compile-start.js.map
|
|
@@ -2,7 +2,7 @@ import type { ProjectId } from "@tutti/shared/ids";
|
|
|
2
2
|
import type { ProviderUsageRecorder } from "../../provider-usage/index.js";
|
|
3
3
|
import { type OpenAiStructuredOutputClient } from "../../providers/openai/sdk-procedure-runner.js";
|
|
4
4
|
import { type OpenAiProviderConfig } from "../../providers/openai/provider-config.js";
|
|
5
|
-
import type { ProcedureWorkflowRunner, ProcedureWorkflowRunnerResolution } from "./types.js";
|
|
5
|
+
import type { ProcedureWorkflowRunner, ProcedureWorkflowRunnerResolution, TaskCompilePromptInput, TaskCompileWorkflowInput } from "./types.js";
|
|
6
6
|
import type { CodexAppServerAgentContextRuntime } from "../../providers/openai/app-server/skills.js";
|
|
7
7
|
export type OpenAiProcedureWorkflowRunnerOptions = {
|
|
8
8
|
config: OpenAiProviderConfig;
|
|
@@ -30,6 +30,7 @@ export type ProjectOpenAiProcedureWorkflowRunnerOptions = {
|
|
|
30
30
|
agentContext?: CodexAppServerAgentContextRuntime;
|
|
31
31
|
recordUsage?: ProviderUsageRecorder;
|
|
32
32
|
};
|
|
33
|
+
export declare function buildTaskCompilePromptInput(input: TaskCompileWorkflowInput): TaskCompilePromptInput;
|
|
33
34
|
export declare function createOpenAiProcedureWorkflowRunner(options: OpenAiProcedureWorkflowRunnerOptions): ProcedureWorkflowRunner;
|
|
34
35
|
export declare function resolveProjectOpenAiProcedureWorkflowRunner(options: ProjectOpenAiProcedureWorkflowRunnerOptions): ProcedureWorkflowRunnerResolution;
|
|
35
36
|
//# sourceMappingURL=openai.d.ts.map
|
|
@@ -137,7 +137,7 @@ function followUpCheckWorkflowOutput(output) {
|
|
|
137
137
|
summary: output.result.requires_retasking.summary,
|
|
138
138
|
};
|
|
139
139
|
}
|
|
140
|
-
function
|
|
140
|
+
export function buildTaskCompilePromptInput(input) {
|
|
141
141
|
const promptInput = {
|
|
142
142
|
scratchpad: {
|
|
143
143
|
topic: input.scratchpad.topic,
|
|
@@ -160,34 +160,20 @@ function taskCompilePromptInput(input) {
|
|
|
160
160
|
})),
|
|
161
161
|
},
|
|
162
162
|
};
|
|
163
|
-
if (input.
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
.filter((message) => message.message_kind === "user_text" || message.message_kind === "agent_text")
|
|
175
|
-
.map(taskCompileClarificationMessage),
|
|
176
|
-
};
|
|
163
|
+
if (input.clarification_rounds !== undefined) {
|
|
164
|
+
promptInput.clarification_rounds = input.clarification_rounds.map((round) => ({
|
|
165
|
+
request: {
|
|
166
|
+
...(round.request_payload.title === undefined
|
|
167
|
+
? {}
|
|
168
|
+
: { title: round.request_payload.title }),
|
|
169
|
+
summary: round.request_payload.summary,
|
|
170
|
+
request: round.request_payload.request,
|
|
171
|
+
},
|
|
172
|
+
answer_messages: round.answer_messages,
|
|
173
|
+
}));
|
|
177
174
|
}
|
|
178
175
|
return promptInput;
|
|
179
176
|
}
|
|
180
|
-
function taskCompileClarificationMessage(message) {
|
|
181
|
-
const role = message.author.kind === "agent" ? "tutti" : "human";
|
|
182
|
-
const authorDisplayName = message.author.display_name?.trim();
|
|
183
|
-
return {
|
|
184
|
-
role,
|
|
185
|
-
...(role === "human" && authorDisplayName !== undefined && authorDisplayName !== ""
|
|
186
|
-
? { author_display_name: authorDisplayName }
|
|
187
|
-
: {}),
|
|
188
|
-
text: message.body.trim(),
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
177
|
function taskCompileWorkflowOutput(output) {
|
|
192
178
|
if ("clarification_request_payload" in output.result) {
|
|
193
179
|
return {
|
|
@@ -280,7 +266,7 @@ export function createOpenAiProcedureWorkflowRunner(options) {
|
|
|
280
266
|
templateKey: "procedures.task_compile",
|
|
281
267
|
...(options.promptsRoot === undefined ? {} : { promptsRoot: options.promptsRoot }),
|
|
282
268
|
variables: {
|
|
283
|
-
workflow_input_json:
|
|
269
|
+
workflow_input_json: buildTaskCompilePromptInput(input),
|
|
284
270
|
},
|
|
285
271
|
});
|
|
286
272
|
const result = await runCodexAppServerReadOnlyProcedure({
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ExecutionRuntimeSnapshot, MessageProjection, RunResultProjection,
|
|
1
|
+
import type { ExecutionRuntimeSnapshot, MessageProjection, RunResultProjection, TaskDetailProjection, WorklistProjection } from "@tutti/shared/schemas/api";
|
|
2
2
|
import type { ClarificationRequestPayload, TaskContractProjection } from "@tutti/shared/schemas/api";
|
|
3
3
|
import type { ProjectDocKey } from "@tutti/shared/schemas/api";
|
|
4
4
|
import type { ActivityRef, ClarificationRoundRef, ClarificationThreadRef, MessageId, TaskId, TaskModuleId, WorkflowInvocationRef } from "@tutti/shared/ids";
|
|
@@ -6,21 +6,31 @@ import type { RunLineage } from "@tutti/shared/domain";
|
|
|
6
6
|
import type { ProjectBriefSnapshot, ProjectBriefSourceDocument } from "../../project-brief/index.js";
|
|
7
7
|
export type ScratchpadRefreshWorkflowInput = {
|
|
8
8
|
project_brief?: ProjectBriefSnapshot;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
9
|
+
worklist: ScratchpadRefreshWorklistInput;
|
|
10
|
+
active_task_compile?: ScratchpadWorkflowSnapshot;
|
|
11
|
+
messages: ScratchpadRefreshSourceMessageInput[];
|
|
12
|
+
};
|
|
13
|
+
export type ScratchpadWorkflowSnapshot = {
|
|
14
|
+
topic: string;
|
|
15
|
+
background_summary: string;
|
|
16
|
+
current_consensus: string[];
|
|
17
|
+
open_questions: string[];
|
|
18
|
+
task_changes: string[];
|
|
19
|
+
};
|
|
20
|
+
export type ScratchpadRefreshWorklistInput = {
|
|
21
|
+
modules: Array<{
|
|
22
|
+
name: string;
|
|
23
|
+
tasks: Array<{
|
|
24
|
+
title: string;
|
|
25
|
+
summary?: string;
|
|
26
|
+
status: WorklistProjection["modules"][number]["tasks"][number]["status"];
|
|
27
|
+
}>;
|
|
28
|
+
}>;
|
|
18
29
|
};
|
|
19
30
|
export type ScratchpadRefreshSourceMessageInput = {
|
|
20
31
|
role: "human" | "tutti";
|
|
21
32
|
author_display_name?: string;
|
|
22
33
|
text: string;
|
|
23
|
-
ref?: string;
|
|
24
34
|
};
|
|
25
35
|
export type ScratchpadRefreshWorkflowContext = {
|
|
26
36
|
workflow_ref: WorkflowInvocationRef;
|
|
@@ -68,12 +78,12 @@ export type TaskCompileProposalTask = {
|
|
|
68
78
|
};
|
|
69
79
|
export type TaskCompileWorkflowInput = {
|
|
70
80
|
workflow_ref: WorkflowInvocationRef;
|
|
71
|
-
scratchpad:
|
|
81
|
+
scratchpad: ScratchpadWorkflowSnapshot;
|
|
72
82
|
worklist: WorklistProjection;
|
|
73
|
-
|
|
83
|
+
clarification_rounds?: Array<{
|
|
74
84
|
request_payload: ClarificationRequestPayload;
|
|
75
|
-
|
|
76
|
-
}
|
|
85
|
+
answer_messages: TaskCompilePromptClarificationMessage[];
|
|
86
|
+
}>;
|
|
77
87
|
};
|
|
78
88
|
export type TaskCompileWorkflowOutput = {
|
|
79
89
|
decision: "ready";
|
|
@@ -103,14 +113,14 @@ export type TaskCompilePromptInput = {
|
|
|
103
113
|
}>;
|
|
104
114
|
}>;
|
|
105
115
|
};
|
|
106
|
-
|
|
116
|
+
clarification_rounds?: Array<{
|
|
107
117
|
request: {
|
|
108
118
|
title?: string;
|
|
109
119
|
summary: string;
|
|
110
120
|
request: string;
|
|
111
121
|
};
|
|
112
122
|
answer_messages: TaskCompilePromptClarificationMessage[];
|
|
113
|
-
}
|
|
123
|
+
}>;
|
|
114
124
|
};
|
|
115
125
|
export type TaskCompilePromptClarificationMessage = {
|
|
116
126
|
role: "human" | "tutti";
|
|
@@ -138,6 +138,17 @@ export function parseCliArgs(argv, cwd = process.cwd()) {
|
|
|
138
138
|
}
|
|
139
139
|
if (command === "internal") {
|
|
140
140
|
const internalCommand = args.shift();
|
|
141
|
+
if (internalCommand === "package-update-worker" ||
|
|
142
|
+
internalCommand === "package-update-complete") {
|
|
143
|
+
if (args.length > 0) {
|
|
144
|
+
throw new LaunchError("git_bootstrap_failed", `Internal ${internalCommand} does not accept options`, "Internal commands are managed by Tutti.");
|
|
145
|
+
}
|
|
146
|
+
return {
|
|
147
|
+
kind: internalCommand === "package-update-worker"
|
|
148
|
+
? "internal-package-update-worker"
|
|
149
|
+
: "internal-package-update-complete",
|
|
150
|
+
};
|
|
151
|
+
}
|
|
141
152
|
if (internalCommand === "console-run") {
|
|
142
153
|
if (args.length > 0) {
|
|
143
154
|
throw new LaunchError("git_bootstrap_failed", "Internal console-run does not accept options", "Internal commands are managed by Tutti.");
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { dirname, resolve } from "node:path";
|
|
3
|
+
import { resolveTuttiHome } from "../../providers/openai/index.js";
|
|
3
4
|
import { formatCliError, formatCliErrorReason, LaunchError } from "./errors.js";
|
|
4
5
|
import { parseCliArgs, shouldEnsureDesktopIntegrationAutomatically } from "./args.js";
|
|
5
6
|
import { confirmTextFromTty, runBackgroundLaunchCommand, runForegroundLaunchCommand, runInternalHostRunCommand, } from "./launch-command.js";
|
|
@@ -9,6 +10,8 @@ import { runArchiveCommand, runDoctorCommand, runForgetCommand, runInviteCommand
|
|
|
9
10
|
import { readCliVersion } from "./version.js";
|
|
10
11
|
import { ensureDesktopIntegrationAutomatically, parseTuttiDesktopUrl, runDesktopIntegrationCommand, TUTTI_DESKTOP_PROJECTS_URL, TuttiDesktopProtocolError, } from "../desktop-integration/index.js";
|
|
11
12
|
import { ensureLocalConsole, openLocalConsoleBrowser, readLocalConsoleServiceStatus, restartLocalConsoleService, runLocalConsoleProcess, stopLocalConsoleService, } from "../local-console/index.js";
|
|
13
|
+
import { runPackageUpdateCompletionProtocol, runPackageUpdateWorkerProtocol, } from "../local-console/package-update-process.js";
|
|
14
|
+
import { recoverPackageUpdateForConsoleStartup } from "../local-console/package-update-recovery.js";
|
|
12
15
|
const HELP_TEXT = `Usage:
|
|
13
16
|
tutti
|
|
14
17
|
tutti launch [target] [--yes] [--foreground]
|
|
@@ -209,13 +212,30 @@ function ensureDesktopIntegrationForConsole() {
|
|
|
209
212
|
process.stderr.write("Tutti could not update its desktop entry. Run `tutti desktop` for details.\n");
|
|
210
213
|
}
|
|
211
214
|
}
|
|
215
|
+
async function ensureUserLocalConsole(options) {
|
|
216
|
+
const env = process.env;
|
|
217
|
+
const entrypointArgument = process.argv[1];
|
|
218
|
+
if (entrypointArgument !== undefined && entrypointArgument.trim() !== "") {
|
|
219
|
+
const recovery = await recoverPackageUpdateForConsoleStartup({
|
|
220
|
+
tuttiHome: resolveTuttiHome(env.TUTTI_HOME, options.cwd),
|
|
221
|
+
cliEntrypoint: resolve(entrypointArgument),
|
|
222
|
+
cwd: options.cwd,
|
|
223
|
+
env,
|
|
224
|
+
source: options.source,
|
|
225
|
+
});
|
|
226
|
+
if (recovery.status === "completed") {
|
|
227
|
+
return recovery.url;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
return (await ensureLocalConsole({ cwd: options.cwd, env, source: options.source })).url;
|
|
231
|
+
}
|
|
212
232
|
async function runLocalConsoleCommand() {
|
|
213
|
-
const
|
|
214
|
-
if (openLocalConsoleBrowser(
|
|
215
|
-
process.stdout.write(`Tutti is ready at ${
|
|
233
|
+
const url = await ensureUserLocalConsole({ cwd: process.cwd(), source: "terminal" });
|
|
234
|
+
if (openLocalConsoleBrowser(url)) {
|
|
235
|
+
process.stdout.write(`Tutti is ready at ${new URL(url).origin}/console\n`);
|
|
216
236
|
return;
|
|
217
237
|
}
|
|
218
|
-
process.stdout.write(["Open Tutti in a browser:",
|
|
238
|
+
process.stdout.write(["Open Tutti in a browser:", url, ""].join("\n"));
|
|
219
239
|
}
|
|
220
240
|
function desktopResultMessage(result) {
|
|
221
241
|
if (result.status === "installed") {
|
|
@@ -239,9 +259,9 @@ function runDesktopCommand(action) {
|
|
|
239
259
|
return desktopResultMessage(runDesktopIntegrationCommand(action));
|
|
240
260
|
}
|
|
241
261
|
async function runDesktopOpenCommand(value) {
|
|
242
|
-
const
|
|
262
|
+
const desktopUrl = value ?? TUTTI_DESKTOP_PROJECTS_URL;
|
|
243
263
|
try {
|
|
244
|
-
parseTuttiDesktopUrl(
|
|
264
|
+
parseTuttiDesktopUrl(desktopUrl);
|
|
245
265
|
}
|
|
246
266
|
catch (error) {
|
|
247
267
|
if (error instanceof TuttiDesktopProtocolError) {
|
|
@@ -250,11 +270,9 @@ async function runDesktopOpenCommand(value) {
|
|
|
250
270
|
throw error;
|
|
251
271
|
}
|
|
252
272
|
const cliEntrypoint = process.argv[1];
|
|
253
|
-
const
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
});
|
|
257
|
-
if (!openLocalConsoleBrowser(console.url)) {
|
|
273
|
+
const cwd = cliEntrypoint === undefined ? process.cwd() : dirname(resolve(cliEntrypoint));
|
|
274
|
+
const url = await ensureUserLocalConsole({ source: "desktop", cwd });
|
|
275
|
+
if (!openLocalConsoleBrowser(url)) {
|
|
258
276
|
throw new LaunchError("desktop_open_failed", "The Local Console started, but no desktop browser opener is available.", "Run `tutti` from a terminal to print a one-time browser URL.");
|
|
259
277
|
}
|
|
260
278
|
}
|
|
@@ -378,6 +396,12 @@ try {
|
|
|
378
396
|
case "internal-desktop-open":
|
|
379
397
|
await runDesktopOpenCommand(command.url);
|
|
380
398
|
break;
|
|
399
|
+
case "internal-package-update-worker":
|
|
400
|
+
await runPackageUpdateWorkerProtocol();
|
|
401
|
+
break;
|
|
402
|
+
case "internal-package-update-complete":
|
|
403
|
+
await runPackageUpdateCompletionProtocol();
|
|
404
|
+
break;
|
|
381
405
|
case "ps":
|
|
382
406
|
if (command.manage) {
|
|
383
407
|
await runPsManageCommand({ all: command.all });
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { FastifyInstance } from "fastify";
|
|
2
|
+
import type { ExecutionStatusProjection } from "@tutti/shared/schemas/api";
|
|
2
3
|
import { type HostProjectStore } from "../../store/index.js";
|
|
3
4
|
import type { createHostServer } from "../http/create-server.js";
|
|
4
5
|
import type { HostLocalLaunchStatus } from "../http/routes/local-control.js";
|
|
@@ -8,6 +9,7 @@ import type { HostRelayConnectionManager } from "./host-relay-connection-manager
|
|
|
8
9
|
import type { LaunchPreparationResult } from "./launch.js";
|
|
9
10
|
import { type MachineRuntimeEndpointRecord } from "./machine-local.js";
|
|
10
11
|
export declare const HOST_SERVER_VERSION: string;
|
|
12
|
+
export declare function packageUpdateReadinessFromExecutionStatus(execution: Pick<ExecutionStatusProjection, "status" | "active_activity" | "active_activities" | "blocked_by">): "ready" | "busy";
|
|
11
13
|
export type HostServerFactory = typeof createHostServer;
|
|
12
14
|
export type HostServerHandle = {
|
|
13
15
|
app: FastifyInstance;
|