@xfey/tutti 0.1.88 → 0.1.90
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/providers/openai/app-server/runtime-telemetry.d.ts +2 -1
- package/dist/providers/openai/app-server/runtime-telemetry.js +391 -57
- package/dist/run-pipeline/task-run-invocation.js +1 -0
- package/dist/server-shell/http/routes/project-api/openapi-execution-routes.d.ts +2 -1
- package/dist/server-shell/http/routes/project-api/openapi-workspace-routes.d.ts +2 -1
- package/dist/server-shell/http/routes/project-api/openapi.d.ts +4 -2
- package/dist/server-shell/http/routes/project-api/schemas.d.ts +2 -1
- package/node_modules/@tutti/shared/dist/schemas/api/runtime-events.d.ts +7 -4
- package/node_modules/@tutti/shared/dist/schemas/api/runtime-events.js +6 -0
- package/package.json +1 -1
- package/web/assets/{homepage-motion-scene-ClVDf7l-.js → homepage-motion-scene-i1GMbKQe.js} +1 -1
- package/web/assets/{index-BQhfn207.css → index-Cl_lDhdv.css} +1 -1
- package/web/assets/{index-LxZ6q3jB.js → index-DHn0faN9.js} +3 -3
- package/web/index.html +2 -2
|
@@ -5,7 +5,8 @@ export type CodexAppServerRuntimeTelemetryOptions = {
|
|
|
5
5
|
activityRef: ActivityRef;
|
|
6
6
|
stageId?: string;
|
|
7
7
|
startedAt?: string;
|
|
8
|
-
|
|
8
|
+
workspaceRoot?: string;
|
|
9
|
+
actionMinVisibleMs?: number;
|
|
9
10
|
now?: () => Date;
|
|
10
11
|
onSnapshot?: (snapshot: ExecutionRuntimeSnapshot) => void;
|
|
11
12
|
};
|
|
@@ -1,46 +1,239 @@
|
|
|
1
|
+
import { isAbsolute, relative, resolve } from "node:path";
|
|
2
|
+
import { classifyViewerPath, redactAndTruncateText } from "@tutti/shared/utils";
|
|
1
3
|
import { extractCodexAppServerTokenUsage } from "../token-usage.js";
|
|
2
|
-
const
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
const DEFAULT_ACTION_MIN_VISIBLE_MS = 1_000;
|
|
5
|
+
const MAX_ACTION_DETAIL_LENGTH = 160;
|
|
6
|
+
const MAX_ACTION_PATH_LENGTH = 120;
|
|
7
|
+
function isRecord(value) {
|
|
8
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
9
|
+
}
|
|
10
|
+
function itemFromNotification(notification) {
|
|
11
|
+
if (!isRecord(notification.params) || !isRecord(notification.params.item)) {
|
|
12
|
+
return undefined;
|
|
13
|
+
}
|
|
14
|
+
return notification.params.item;
|
|
15
|
+
}
|
|
16
|
+
function itemId(item) {
|
|
17
|
+
return typeof item.id === "string" && item.id !== "" ? item.id : undefined;
|
|
18
|
+
}
|
|
19
|
+
const CHECK_COMMAND_PATTERN = /(?:^|[\s;&|])(?:(?:npm|pnpm|yarn|bun)\s+(?:(?:run|exec|x)\s+)?(?:test|lint|check|typecheck|build)|(?:npx|pnpm\s+exec|yarn\s+exec|bunx)\s+(?:vitest|jest|eslint|tsc|biome|prettier)|pytest|vitest|jest|cargo\s+(?:test|check|clippy|build)|go\s+test|dotnet\s+(?:test|build)|gradle\w*\s+(?:test|check|build)|make\s+(?:test|check|lint|build)|tsc(?:\s|$)|eslint(?:\s|$)|biome\s+check|ruff\s+check|mypy(?:\s|$)|swift\s+test|xcodebuild(?:\s|$))/iu;
|
|
20
|
+
function boundedDetail(value) {
|
|
21
|
+
const detail = redactAndTruncateText(value.trim().replace(/\s+/gu, " "), MAX_ACTION_DETAIL_LENGTH);
|
|
22
|
+
return detail === "" ? undefined : detail;
|
|
23
|
+
}
|
|
24
|
+
function safeProjectPath(value, workspaceRoot) {
|
|
25
|
+
if (typeof value !== "string" || value.trim() === "") {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
const rawPath = value.trim();
|
|
29
|
+
let candidate = rawPath;
|
|
30
|
+
if (isAbsolute(rawPath)) {
|
|
31
|
+
if (workspaceRoot === undefined) {
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
candidate = relative(resolve(workspaceRoot), resolve(rawPath));
|
|
35
|
+
}
|
|
36
|
+
const classification = classifyViewerPath(candidate);
|
|
37
|
+
if (classification.kind === "rejected" ||
|
|
38
|
+
classification.path_kind === "root" ||
|
|
39
|
+
classification.normalized_path === "") {
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
return redactAndTruncateText(classification.normalized_path, MAX_ACTION_PATH_LENGTH);
|
|
43
|
+
}
|
|
44
|
+
function firstSafePath(records, workspaceRoot, keys = ["path"]) {
|
|
45
|
+
for (const record of records) {
|
|
46
|
+
for (const key of keys) {
|
|
47
|
+
const path = safeProjectPath(record[key], workspaceRoot);
|
|
48
|
+
if (path !== undefined) {
|
|
49
|
+
return path;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
function safeToolName(item) {
|
|
56
|
+
for (const key of ["tool", "toolName", "name"]) {
|
|
57
|
+
const value = item[key];
|
|
58
|
+
if (typeof value === "string" && value.length <= 64 && /^[A-Za-z0-9@._:/-]+$/u.test(value)) {
|
|
59
|
+
return value;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
function commandCheckDetail(commands) {
|
|
65
|
+
const command = commands.join(" ");
|
|
66
|
+
const workspace = /--workspace(?:=|\s+)(@?[A-Za-z0-9._-]+(?:\/[A-Za-z0-9._-]+)?)/iu.exec(command)?.[1];
|
|
67
|
+
const target = workspace === undefined ? "the project" : workspace;
|
|
68
|
+
if (/(?:^|[\s:./_-])(?:test|tests|pytest|vitest|jest)(?:$|[\s:./_-])/iu.test(command)) {
|
|
69
|
+
return {
|
|
70
|
+
detail: workspace === undefined ? "Running project tests" : `Running tests for ${target}`,
|
|
71
|
+
completionDetail: "Reviewing test results",
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
if (/(?:typecheck|\btsc\b|\bmypy\b)/iu.test(command)) {
|
|
75
|
+
return {
|
|
76
|
+
detail: `Checking types for ${target}`,
|
|
77
|
+
completionDetail: "Reviewing type-check results",
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
if (/(?:lint|eslint|biome|prettier|ruff|clippy)/iu.test(command)) {
|
|
81
|
+
return {
|
|
82
|
+
detail: `Checking code quality for ${target}`,
|
|
83
|
+
completionDetail: "Reviewing code-quality results",
|
|
84
|
+
};
|
|
6
85
|
}
|
|
7
|
-
if (
|
|
8
|
-
return
|
|
86
|
+
if (/(?:^|[\s:./_-])build(?:$|[\s:./_-])|xcodebuild/iu.test(command)) {
|
|
87
|
+
return {
|
|
88
|
+
detail: workspace === undefined ? "Building the project" : `Building ${workspace}`,
|
|
89
|
+
completionDetail: "Reviewing the build result",
|
|
90
|
+
};
|
|
9
91
|
}
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
return tokens.join(" ").toLocaleLowerCase();
|
|
92
|
+
return {
|
|
93
|
+
detail: "Running project checks",
|
|
94
|
+
completionDetail: "Reviewing check results",
|
|
95
|
+
};
|
|
15
96
|
}
|
|
16
|
-
function
|
|
97
|
+
function commandActionFromItem(item, workspaceRoot) {
|
|
98
|
+
const commandActions = Array.isArray(item.commandActions)
|
|
99
|
+
? item.commandActions.filter(isRecord)
|
|
100
|
+
: [];
|
|
101
|
+
const commands = [item.command, ...commandActions.map((action) => action.command)].filter((command) => typeof command === "string");
|
|
102
|
+
if (commands.some((command) => CHECK_COMMAND_PATTERN.test(command))) {
|
|
103
|
+
const check = commandCheckDetail(commands);
|
|
104
|
+
return {
|
|
105
|
+
action: "running_checks",
|
|
106
|
+
detail: check.detail,
|
|
107
|
+
completionDetail: check.completionDetail,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
const actionTypes = commandActions
|
|
111
|
+
.map((action) => action.type)
|
|
112
|
+
.filter((type) => typeof type === "string");
|
|
113
|
+
if (actionTypes.some((type) => type === "search" || type === "listFiles")) {
|
|
114
|
+
const path = firstSafePath(commandActions, workspaceRoot, ["path", "name"]);
|
|
115
|
+
return {
|
|
116
|
+
action: "searching_codebase",
|
|
117
|
+
...(path === undefined ? {} : { detail: `Searching in ${path}` }),
|
|
118
|
+
completionDetail: "Reviewing search results",
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
if (actionTypes.includes("read")) {
|
|
122
|
+
const path = firstSafePath(commandActions, workspaceRoot, ["path", "name"]);
|
|
123
|
+
return {
|
|
124
|
+
action: "reading_files",
|
|
125
|
+
...(path === undefined ? {} : { detail: `Reading ${path}` }),
|
|
126
|
+
completionDetail: path === undefined ? "Reviewing project context" : `Reviewing ${path}`,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
action: "running_command",
|
|
131
|
+
completionDetail: "Reviewing command output",
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
function fileChangeSignal(item, workspaceRoot) {
|
|
135
|
+
const changes = Array.isArray(item.changes) ? item.changes.filter(isRecord) : [];
|
|
136
|
+
const path = firstSafePath([item, ...changes], workspaceRoot);
|
|
137
|
+
return {
|
|
138
|
+
action: "editing_files",
|
|
139
|
+
...(path === undefined ? {} : { detail: `Editing ${path}` }),
|
|
140
|
+
completionDetail: path === undefined ? "Reviewing the latest changes" : `Reviewing changes to ${path}`,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
function actionFromItem(item, workspaceRoot) {
|
|
144
|
+
switch (item.type) {
|
|
145
|
+
case "reasoning":
|
|
146
|
+
case "contextCompaction":
|
|
147
|
+
return { action: "analyzing_task" };
|
|
148
|
+
case "plan":
|
|
149
|
+
return { action: "planning" };
|
|
150
|
+
case "commandExecution":
|
|
151
|
+
return commandActionFromItem(item, workspaceRoot);
|
|
152
|
+
case "fileChange":
|
|
153
|
+
return fileChangeSignal(item, workspaceRoot);
|
|
154
|
+
case "imageView": {
|
|
155
|
+
const path = firstSafePath([item], workspaceRoot);
|
|
156
|
+
return {
|
|
157
|
+
action: "reading_files",
|
|
158
|
+
detail: path === undefined ? "Inspecting a project visual" : `Inspecting ${path}`,
|
|
159
|
+
completionDetail: "Reviewing the project visual",
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
case "webSearch":
|
|
163
|
+
return {
|
|
164
|
+
action: "using_tool",
|
|
165
|
+
detail: "Searching the web",
|
|
166
|
+
completionDetail: "Reviewing web search results",
|
|
167
|
+
};
|
|
168
|
+
case "collabAgentToolCall":
|
|
169
|
+
case "subAgentActivity":
|
|
170
|
+
return {
|
|
171
|
+
action: "using_tool",
|
|
172
|
+
detail: "Coordinating a sub-agent",
|
|
173
|
+
completionDetail: "Reviewing the sub-agent result",
|
|
174
|
+
};
|
|
175
|
+
case "imageGeneration":
|
|
176
|
+
return {
|
|
177
|
+
action: "using_tool",
|
|
178
|
+
detail: "Generating an image",
|
|
179
|
+
completionDetail: "Reviewing the generated image",
|
|
180
|
+
};
|
|
181
|
+
case "mcpToolCall":
|
|
182
|
+
case "dynamicToolCall": {
|
|
183
|
+
const tool = safeToolName(item);
|
|
184
|
+
return {
|
|
185
|
+
action: "using_tool",
|
|
186
|
+
...(tool === undefined ? {} : { detail: `Using ${tool}` }),
|
|
187
|
+
completionDetail: "Reviewing tool output",
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
default:
|
|
191
|
+
return undefined;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
function actionFromNotificationMethod(notification, workspaceRoot) {
|
|
17
195
|
const method = notification.method;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
return "using_tool";
|
|
38
|
-
}
|
|
39
|
-
if (combined.includes("reasoning")) {
|
|
40
|
-
return "reading_context";
|
|
196
|
+
if (method === "turn/started" || method.startsWith("item/reasoning/")) {
|
|
197
|
+
return { action: "analyzing_task" };
|
|
198
|
+
}
|
|
199
|
+
if (method === "turn/plan/updated" || method.startsWith("item/plan/")) {
|
|
200
|
+
return { action: "planning" };
|
|
201
|
+
}
|
|
202
|
+
if (method === "turn/diff/updated" || method.startsWith("item/fileChange/")) {
|
|
203
|
+
const params = isRecord(notification.params) ? notification.params : {};
|
|
204
|
+
const rawPaths = params.paths;
|
|
205
|
+
const paths = Array.isArray(rawPaths)
|
|
206
|
+
? rawPaths.map((path) => ({ path }))
|
|
207
|
+
: [];
|
|
208
|
+
return fileChangeSignal({ ...params, changes: paths }, workspaceRoot);
|
|
209
|
+
}
|
|
210
|
+
if (method === "turn/completed") {
|
|
211
|
+
return { action: "preparing_result" };
|
|
212
|
+
}
|
|
213
|
+
if (method.startsWith("item/mcpToolCall/")) {
|
|
214
|
+
return { action: "using_tool", completionDetail: "Reviewing tool output" };
|
|
41
215
|
}
|
|
42
216
|
return undefined;
|
|
43
217
|
}
|
|
218
|
+
function requestKey(value) {
|
|
219
|
+
if (typeof value !== "string" && typeof value !== "number") {
|
|
220
|
+
return undefined;
|
|
221
|
+
}
|
|
222
|
+
return `${typeof value}:${String(value)}`;
|
|
223
|
+
}
|
|
224
|
+
function resolvedRequestKey(notification) {
|
|
225
|
+
if (notification.method !== "serverRequest/resolved" || !isRecord(notification.params)) {
|
|
226
|
+
return undefined;
|
|
227
|
+
}
|
|
228
|
+
return requestKey(notification.params.requestId);
|
|
229
|
+
}
|
|
230
|
+
function isWaitingRequest(request) {
|
|
231
|
+
return (request.method.includes("requestApproval") ||
|
|
232
|
+
request.method === "applyPatchApproval" ||
|
|
233
|
+
request.method === "execCommandApproval" ||
|
|
234
|
+
request.method === "item/tool/requestUserInput" ||
|
|
235
|
+
request.method === "mcpServer/elicitation/request");
|
|
236
|
+
}
|
|
44
237
|
function runtimeTokenUsage(usage) {
|
|
45
238
|
return {
|
|
46
239
|
input_tokens: usage.input_tokens,
|
|
@@ -53,27 +246,51 @@ function runtimeTokenUsage(usage) {
|
|
|
53
246
|
export function createCodexAppServerRuntimeObserver(options) {
|
|
54
247
|
let latest;
|
|
55
248
|
let timer;
|
|
56
|
-
let lastEmittedAt
|
|
57
|
-
|
|
249
|
+
let lastEmittedAt;
|
|
250
|
+
let lastEmittedActionKey;
|
|
251
|
+
let pendingSnapshot;
|
|
252
|
+
let lastCompletedDetail;
|
|
253
|
+
let itemOrder = 0;
|
|
254
|
+
const activeItems = new Map();
|
|
255
|
+
const waitingRequests = new Set();
|
|
256
|
+
const actionMinVisibleMs = Math.max(0, options.actionMinVisibleMs ?? DEFAULT_ACTION_MIN_VISIBLE_MS);
|
|
58
257
|
const now = options.now ?? (() => new Date());
|
|
59
|
-
const
|
|
60
|
-
|
|
258
|
+
const snapshotActionKey = (snapshot) => snapshot?.current_action === undefined
|
|
259
|
+
? undefined
|
|
260
|
+
: `${snapshot.current_action}\u0000${snapshot.current_action_detail ?? ""}`;
|
|
261
|
+
const emit = (snapshot = latest) => {
|
|
262
|
+
if (snapshot === undefined || options.onSnapshot === undefined) {
|
|
61
263
|
return;
|
|
62
264
|
}
|
|
63
265
|
lastEmittedAt = Date.now();
|
|
64
|
-
|
|
266
|
+
lastEmittedActionKey = snapshotActionKey(snapshot);
|
|
267
|
+
options.onSnapshot(snapshot);
|
|
65
268
|
};
|
|
66
|
-
const
|
|
67
|
-
|
|
269
|
+
const publishPendingSnapshot = () => {
|
|
270
|
+
const snapshot = pendingSnapshot;
|
|
271
|
+
pendingSnapshot = undefined;
|
|
272
|
+
emit(snapshot);
|
|
273
|
+
if (latest?.current_action !== undefined &&
|
|
274
|
+
snapshotActionKey(latest) !== lastEmittedActionKey) {
|
|
275
|
+
pendingSnapshot = latest;
|
|
276
|
+
schedulePendingSnapshot();
|
|
277
|
+
}
|
|
278
|
+
};
|
|
279
|
+
const schedulePendingSnapshot = () => {
|
|
280
|
+
if (options.onSnapshot === undefined || pendingSnapshot === undefined) {
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
if (lastEmittedAt === undefined) {
|
|
284
|
+
publishPendingSnapshot();
|
|
68
285
|
return;
|
|
69
286
|
}
|
|
70
287
|
const elapsed = Date.now() - lastEmittedAt;
|
|
71
|
-
if (elapsed >=
|
|
288
|
+
if (elapsed >= actionMinVisibleMs) {
|
|
72
289
|
if (timer !== undefined) {
|
|
73
290
|
clearTimeout(timer);
|
|
74
291
|
timer = undefined;
|
|
75
292
|
}
|
|
76
|
-
|
|
293
|
+
publishPendingSnapshot();
|
|
77
294
|
return;
|
|
78
295
|
}
|
|
79
296
|
if (timer !== undefined) {
|
|
@@ -81,10 +298,29 @@ export function createCodexAppServerRuntimeObserver(options) {
|
|
|
81
298
|
}
|
|
82
299
|
timer = setTimeout(() => {
|
|
83
300
|
timer = undefined;
|
|
84
|
-
|
|
85
|
-
}, Math.max(1,
|
|
301
|
+
publishPendingSnapshot();
|
|
302
|
+
}, Math.max(1, actionMinVisibleMs - elapsed));
|
|
86
303
|
};
|
|
87
|
-
const
|
|
304
|
+
const scheduleActionEmit = (preservePendingAction) => {
|
|
305
|
+
if (options.onSnapshot === undefined || latest?.current_action === undefined) {
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
if (pendingSnapshot !== undefined) {
|
|
309
|
+
if (preservePendingAction) {
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
if (snapshotActionKey(latest) !== lastEmittedActionKey) {
|
|
313
|
+
pendingSnapshot = latest;
|
|
314
|
+
}
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
if (snapshotActionKey(latest) === lastEmittedActionKey) {
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
pendingSnapshot = latest;
|
|
321
|
+
schedulePendingSnapshot();
|
|
322
|
+
};
|
|
323
|
+
const update = (patch, scheduleAction = patch.currentAction !== undefined, preservePendingAction = false) => {
|
|
88
324
|
if (patch.currentAction === undefined && patch.tokenUsage === undefined) {
|
|
89
325
|
return;
|
|
90
326
|
}
|
|
@@ -95,34 +331,132 @@ export function createCodexAppServerRuntimeObserver(options) {
|
|
|
95
331
|
...(options.startedAt === undefined ? {} : { started_at: options.startedAt }),
|
|
96
332
|
...(latest?.token_usage === undefined ? {} : { token_usage: latest.token_usage }),
|
|
97
333
|
...(latest?.current_action === undefined ? {} : { current_action: latest.current_action }),
|
|
334
|
+
...(latest?.current_action_detail === undefined
|
|
335
|
+
? {}
|
|
336
|
+
: { current_action_detail: latest.current_action_detail }),
|
|
98
337
|
updated_at: updatedAt,
|
|
99
338
|
};
|
|
100
339
|
if (patch.tokenUsage !== undefined) {
|
|
101
340
|
latest.token_usage = runtimeTokenUsage(patch.tokenUsage);
|
|
102
341
|
}
|
|
103
342
|
if (patch.currentAction !== undefined) {
|
|
104
|
-
latest.current_action = patch.currentAction;
|
|
343
|
+
latest.current_action = patch.currentAction.action;
|
|
344
|
+
const detail = patch.currentAction.detail === undefined
|
|
345
|
+
? undefined
|
|
346
|
+
: boundedDetail(patch.currentAction.detail);
|
|
347
|
+
if (detail === undefined) {
|
|
348
|
+
delete latest.current_action_detail;
|
|
349
|
+
}
|
|
350
|
+
else {
|
|
351
|
+
latest.current_action_detail = detail;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
if (!scheduleAction && pendingSnapshot !== undefined) {
|
|
355
|
+
pendingSnapshot = latest;
|
|
105
356
|
}
|
|
106
|
-
|
|
357
|
+
if (scheduleAction) {
|
|
358
|
+
scheduleActionEmit(preservePendingAction);
|
|
359
|
+
}
|
|
360
|
+
};
|
|
361
|
+
const currentItemAction = () => {
|
|
362
|
+
let current;
|
|
363
|
+
for (const item of activeItems.values()) {
|
|
364
|
+
if (current === undefined || item.order > current.order) {
|
|
365
|
+
current = item;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
return current;
|
|
369
|
+
};
|
|
370
|
+
const fallbackAction = () => ({
|
|
371
|
+
action: "analyzing_task",
|
|
372
|
+
...(lastCompletedDetail === undefined ? {} : { detail: lastCompletedDetail }),
|
|
373
|
+
});
|
|
374
|
+
const resumeCurrentAction = () => {
|
|
375
|
+
update({
|
|
376
|
+
currentAction: waitingRequests.size > 0
|
|
377
|
+
? { action: "waiting_for_approval" }
|
|
378
|
+
: (currentItemAction() ?? fallbackAction()),
|
|
379
|
+
}, true, true);
|
|
107
380
|
};
|
|
108
381
|
return {
|
|
109
382
|
notification: (notification) => {
|
|
110
383
|
const tokenUsage = extractCodexAppServerTokenUsage([notification]);
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
384
|
+
if (tokenUsage !== undefined) {
|
|
385
|
+
update({ tokenUsage }, false);
|
|
386
|
+
}
|
|
387
|
+
const request = resolvedRequestKey(notification);
|
|
388
|
+
if (request !== undefined) {
|
|
389
|
+
if (waitingRequests.delete(request)) {
|
|
390
|
+
resumeCurrentAction();
|
|
391
|
+
}
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
if (notification.method === "item/started") {
|
|
395
|
+
const item = itemFromNotification(notification);
|
|
396
|
+
const id = item === undefined ? undefined : itemId(item);
|
|
397
|
+
let action = item === undefined ? undefined : actionFromItem(item, options.workspaceRoot);
|
|
398
|
+
if (action?.action === "analyzing_task" &&
|
|
399
|
+
action.detail === undefined &&
|
|
400
|
+
lastCompletedDetail !== undefined) {
|
|
401
|
+
action = { ...action, detail: lastCompletedDetail };
|
|
402
|
+
}
|
|
403
|
+
if (id !== undefined && action !== undefined) {
|
|
404
|
+
itemOrder += 1;
|
|
405
|
+
activeItems.set(id, { ...action, order: itemOrder });
|
|
406
|
+
if (waitingRequests.size === 0) {
|
|
407
|
+
update({ currentAction: action });
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
if (notification.method === "item/completed") {
|
|
413
|
+
const item = itemFromNotification(notification);
|
|
414
|
+
const id = item === undefined ? undefined : itemId(item);
|
|
415
|
+
const completed = id === undefined ? undefined : activeItems.get(id);
|
|
416
|
+
if (id !== undefined && activeItems.delete(id)) {
|
|
417
|
+
if (completed?.completionDetail !== undefined) {
|
|
418
|
+
lastCompletedDetail = completed.completionDetail;
|
|
419
|
+
}
|
|
420
|
+
resumeCurrentAction();
|
|
421
|
+
}
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
let currentAction = actionFromNotificationMethod(notification, options.workspaceRoot);
|
|
425
|
+
const activeAction = currentItemAction();
|
|
426
|
+
if (currentAction !== undefined &&
|
|
427
|
+
currentAction.detail === undefined &&
|
|
428
|
+
activeAction?.action === currentAction.action) {
|
|
429
|
+
currentAction = activeAction;
|
|
430
|
+
}
|
|
431
|
+
if (currentAction?.action === "analyzing_task" &&
|
|
432
|
+
currentAction.detail === undefined &&
|
|
433
|
+
lastCompletedDetail !== undefined) {
|
|
434
|
+
currentAction = { ...currentAction, detail: lastCompletedDetail };
|
|
435
|
+
}
|
|
436
|
+
if (currentAction !== undefined && waitingRequests.size === 0) {
|
|
437
|
+
update({ currentAction });
|
|
438
|
+
}
|
|
116
439
|
},
|
|
117
|
-
serverRequest: () => {
|
|
118
|
-
|
|
440
|
+
serverRequest: (request) => {
|
|
441
|
+
if (!isWaitingRequest(request)) {
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
const key = requestKey(request.id);
|
|
445
|
+
if (key !== undefined) {
|
|
446
|
+
waitingRequests.add(key);
|
|
447
|
+
}
|
|
448
|
+
update({ currentAction: { action: "waiting_for_approval" } });
|
|
119
449
|
},
|
|
120
450
|
flush: () => {
|
|
121
451
|
if (timer !== undefined) {
|
|
122
452
|
clearTimeout(timer);
|
|
123
453
|
timer = undefined;
|
|
124
454
|
}
|
|
125
|
-
|
|
455
|
+
pendingSnapshot = undefined;
|
|
456
|
+
if (latest?.current_action !== undefined &&
|
|
457
|
+
snapshotActionKey(latest) !== lastEmittedActionKey) {
|
|
458
|
+
emit();
|
|
459
|
+
}
|
|
126
460
|
},
|
|
127
461
|
};
|
|
128
462
|
}
|
|
@@ -120,6 +120,7 @@ export async function runWorkspaceWriteTask(options, input) {
|
|
|
120
120
|
runtimeTelemetry: {
|
|
121
121
|
activityRef: input.activity_ref,
|
|
122
122
|
stageId: "provider_task_run",
|
|
123
|
+
workspaceRoot: options.workspaceRoot,
|
|
123
124
|
onSnapshot: (snapshot) => input.on_stage?.({
|
|
124
125
|
stage: "provider_task_run",
|
|
125
126
|
summary: "running Codex task implementation.",
|
|
@@ -202,7 +202,8 @@ export declare const HOST_PROJECT_EXECUTION_OPENAPI_ROUTES: ({
|
|
|
202
202
|
reasoning_output_tokens: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TInteger>;
|
|
203
203
|
total_tokens: import("@sinclair/typebox").TInteger;
|
|
204
204
|
}>>;
|
|
205
|
-
current_action: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"reading_context">, import("@sinclair/typebox").TLiteral<"planning">, import("@sinclair/typebox").TLiteral<"editing_files">, import("@sinclair/typebox").TLiteral<"running_command">, import("@sinclair/typebox").TLiteral<"using_tool">, import("@sinclair/typebox").TLiteral<"waiting_for_approval">, import("@sinclair/typebox").TLiteral<"finalizing">]>>;
|
|
205
|
+
current_action: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"analyzing_task">, import("@sinclair/typebox").TLiteral<"searching_codebase">, import("@sinclair/typebox").TLiteral<"reading_files">, import("@sinclair/typebox").TLiteral<"reading_context">, import("@sinclair/typebox").TLiteral<"planning">, import("@sinclair/typebox").TLiteral<"editing_files">, import("@sinclair/typebox").TLiteral<"running_checks">, import("@sinclair/typebox").TLiteral<"running_command">, import("@sinclair/typebox").TLiteral<"using_tool">, import("@sinclair/typebox").TLiteral<"waiting_for_approval">, import("@sinclair/typebox").TLiteral<"preparing_result">, import("@sinclair/typebox").TLiteral<"finalizing">]>>;
|
|
206
|
+
current_action_detail: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
206
207
|
}>>;
|
|
207
208
|
blocked_by: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{
|
|
208
209
|
kind: import("@sinclair/typebox").TLiteral<"clarification">;
|
|
@@ -1276,7 +1276,8 @@ export declare const HOST_PROJECT_WORKSPACE_OPENAPI_ROUTES: ({
|
|
|
1276
1276
|
reasoning_output_tokens: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TInteger>;
|
|
1277
1277
|
total_tokens: import("@sinclair/typebox").TInteger;
|
|
1278
1278
|
}>>;
|
|
1279
|
-
current_action: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"reading_context">, import("@sinclair/typebox").TLiteral<"planning">, import("@sinclair/typebox").TLiteral<"editing_files">, import("@sinclair/typebox").TLiteral<"running_command">, import("@sinclair/typebox").TLiteral<"using_tool">, import("@sinclair/typebox").TLiteral<"waiting_for_approval">, import("@sinclair/typebox").TLiteral<"finalizing">]>>;
|
|
1279
|
+
current_action: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"analyzing_task">, import("@sinclair/typebox").TLiteral<"searching_codebase">, import("@sinclair/typebox").TLiteral<"reading_files">, import("@sinclair/typebox").TLiteral<"reading_context">, import("@sinclair/typebox").TLiteral<"planning">, import("@sinclair/typebox").TLiteral<"editing_files">, import("@sinclair/typebox").TLiteral<"running_checks">, import("@sinclair/typebox").TLiteral<"running_command">, import("@sinclair/typebox").TLiteral<"using_tool">, import("@sinclair/typebox").TLiteral<"waiting_for_approval">, import("@sinclair/typebox").TLiteral<"preparing_result">, import("@sinclair/typebox").TLiteral<"finalizing">]>>;
|
|
1280
|
+
current_action_detail: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
1280
1281
|
}>>;
|
|
1281
1282
|
blocked_by: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{
|
|
1282
1283
|
kind: import("@sinclair/typebox").TLiteral<"clarification">;
|
|
@@ -831,7 +831,8 @@ export declare const HOST_PROJECT_OPENAPI_ROUTES: ({
|
|
|
831
831
|
reasoning_output_tokens: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TInteger>;
|
|
832
832
|
total_tokens: import("@sinclair/typebox").TInteger;
|
|
833
833
|
}>>;
|
|
834
|
-
current_action: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"reading_context">, import("@sinclair/typebox").TLiteral<"planning">, import("@sinclair/typebox").TLiteral<"editing_files">, import("@sinclair/typebox").TLiteral<"running_command">, import("@sinclair/typebox").TLiteral<"using_tool">, import("@sinclair/typebox").TLiteral<"waiting_for_approval">, import("@sinclair/typebox").TLiteral<"finalizing">]>>;
|
|
834
|
+
current_action: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"analyzing_task">, import("@sinclair/typebox").TLiteral<"searching_codebase">, import("@sinclair/typebox").TLiteral<"reading_files">, import("@sinclair/typebox").TLiteral<"reading_context">, import("@sinclair/typebox").TLiteral<"planning">, import("@sinclair/typebox").TLiteral<"editing_files">, import("@sinclair/typebox").TLiteral<"running_checks">, import("@sinclair/typebox").TLiteral<"running_command">, import("@sinclair/typebox").TLiteral<"using_tool">, import("@sinclair/typebox").TLiteral<"waiting_for_approval">, import("@sinclair/typebox").TLiteral<"preparing_result">, import("@sinclair/typebox").TLiteral<"finalizing">]>>;
|
|
835
|
+
current_action_detail: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
835
836
|
}>>;
|
|
836
837
|
blocked_by: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{
|
|
837
838
|
kind: import("@sinclair/typebox").TLiteral<"clarification">;
|
|
@@ -2550,7 +2551,8 @@ export declare const HOST_PROJECT_OPENAPI_ROUTES: ({
|
|
|
2550
2551
|
reasoning_output_tokens: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TInteger>;
|
|
2551
2552
|
total_tokens: import("@sinclair/typebox").TInteger;
|
|
2552
2553
|
}>>;
|
|
2553
|
-
current_action: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"reading_context">, import("@sinclair/typebox").TLiteral<"planning">, import("@sinclair/typebox").TLiteral<"editing_files">, import("@sinclair/typebox").TLiteral<"running_command">, import("@sinclair/typebox").TLiteral<"using_tool">, import("@sinclair/typebox").TLiteral<"waiting_for_approval">, import("@sinclair/typebox").TLiteral<"finalizing">]>>;
|
|
2554
|
+
current_action: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"analyzing_task">, import("@sinclair/typebox").TLiteral<"searching_codebase">, import("@sinclair/typebox").TLiteral<"reading_files">, import("@sinclair/typebox").TLiteral<"reading_context">, import("@sinclair/typebox").TLiteral<"planning">, import("@sinclair/typebox").TLiteral<"editing_files">, import("@sinclair/typebox").TLiteral<"running_checks">, import("@sinclair/typebox").TLiteral<"running_command">, import("@sinclair/typebox").TLiteral<"using_tool">, import("@sinclair/typebox").TLiteral<"waiting_for_approval">, import("@sinclair/typebox").TLiteral<"preparing_result">, import("@sinclair/typebox").TLiteral<"finalizing">]>>;
|
|
2555
|
+
current_action_detail: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
2554
2556
|
}>>;
|
|
2555
2557
|
blocked_by: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{
|
|
2556
2558
|
kind: import("@sinclair/typebox").TLiteral<"clarification">;
|
|
@@ -1240,7 +1240,8 @@ export declare const BootstrapResponseSchema: {
|
|
|
1240
1240
|
reasoning_output_tokens: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TInteger>;
|
|
1241
1241
|
total_tokens: import("@sinclair/typebox").TInteger;
|
|
1242
1242
|
}>>;
|
|
1243
|
-
current_action: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"reading_context">, import("@sinclair/typebox").TLiteral<"planning">, import("@sinclair/typebox").TLiteral<"editing_files">, import("@sinclair/typebox").TLiteral<"running_command">, import("@sinclair/typebox").TLiteral<"using_tool">, import("@sinclair/typebox").TLiteral<"waiting_for_approval">, import("@sinclair/typebox").TLiteral<"finalizing">]>>;
|
|
1243
|
+
current_action: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"analyzing_task">, import("@sinclair/typebox").TLiteral<"searching_codebase">, import("@sinclair/typebox").TLiteral<"reading_files">, import("@sinclair/typebox").TLiteral<"reading_context">, import("@sinclair/typebox").TLiteral<"planning">, import("@sinclair/typebox").TLiteral<"editing_files">, import("@sinclair/typebox").TLiteral<"running_checks">, import("@sinclair/typebox").TLiteral<"running_command">, import("@sinclair/typebox").TLiteral<"using_tool">, import("@sinclair/typebox").TLiteral<"waiting_for_approval">, import("@sinclair/typebox").TLiteral<"preparing_result">, import("@sinclair/typebox").TLiteral<"finalizing">]>>;
|
|
1244
|
+
current_action_detail: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
1244
1245
|
}>>;
|
|
1245
1246
|
blocked_by: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{
|
|
1246
1247
|
kind: import("@sinclair/typebox").TLiteral<"clarification">;
|