@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.
@@ -5,7 +5,8 @@ export type CodexAppServerRuntimeTelemetryOptions = {
5
5
  activityRef: ActivityRef;
6
6
  stageId?: string;
7
7
  startedAt?: string;
8
- throttleMs?: number;
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 DEFAULT_THROTTLE_MS = 5_000;
3
- function searchText(value) {
4
- if (typeof value === "string") {
5
- return value.toLocaleLowerCase();
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 (typeof value !== "object" || value === null) {
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
- const record = value;
11
- const tokens = ["type", "kind", "name", "status", "method", "state"]
12
- .map((key) => record[key])
13
- .filter((entry) => typeof entry === "string");
14
- return tokens.join(" ").toLocaleLowerCase();
92
+ return {
93
+ detail: "Running project checks",
94
+ completionDetail: "Reviewing check results",
95
+ };
15
96
  }
16
- function actionFromNotification(notification) {
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
- const paramsText = searchText(notification.params);
19
- const combined = `${method} ${paramsText}`.toLocaleLowerCase();
20
- if (combined.includes("commandexecution") || combined.includes("command_execution")) {
21
- return "running_command";
22
- }
23
- if (method === "turn/diff/updated" ||
24
- combined.includes("filechange") ||
25
- combined.includes("file_change")) {
26
- return "editing_files";
27
- }
28
- if (method === "turn/plan/updated" || combined.includes("plan")) {
29
- return "planning";
30
- }
31
- if (combined.includes("mcptoolcall") ||
32
- combined.includes("mcp_tool_call") ||
33
- combined.includes("dynamictoolcall") ||
34
- combined.includes("dynamic_tool_call") ||
35
- combined.includes("websearch") ||
36
- combined.includes("web_search")) {
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 = 0;
57
- const throttleMs = options.throttleMs ?? DEFAULT_THROTTLE_MS;
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 emit = () => {
60
- if (latest === undefined || options.onSnapshot === undefined) {
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
- options.onSnapshot(latest);
266
+ lastEmittedActionKey = snapshotActionKey(snapshot);
267
+ options.onSnapshot(snapshot);
65
268
  };
66
- const scheduleEmit = () => {
67
- if (options.onSnapshot === undefined) {
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 >= throttleMs) {
288
+ if (elapsed >= actionMinVisibleMs) {
72
289
  if (timer !== undefined) {
73
290
  clearTimeout(timer);
74
291
  timer = undefined;
75
292
  }
76
- emit();
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
- emit();
85
- }, Math.max(1, throttleMs - elapsed));
301
+ publishPendingSnapshot();
302
+ }, Math.max(1, actionMinVisibleMs - elapsed));
86
303
  };
87
- const update = (patch) => {
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
- scheduleEmit();
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
- const currentAction = actionFromNotification(notification);
112
- update({
113
- ...(tokenUsage === undefined ? {} : { tokenUsage }),
114
- ...(currentAction === undefined ? {} : { currentAction }),
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
- update({ currentAction: "waiting_for_approval" });
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
- emit();
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">;