@bubblebrain-ai/bubble 0.0.58 → 0.0.60

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.
Files changed (177) hide show
  1. package/README.md +56 -6
  2. package/dist/agent/child-runner.js +5 -1
  3. package/dist/agent/internal-reminder-sanitizer.d.ts +1 -1
  4. package/dist/agent/internal-reminder-sanitizer.js +7 -1
  5. package/dist/agent/profiles.js +4 -4
  6. package/dist/agent/routing-catalog.d.ts +19 -1
  7. package/dist/agent/routing-catalog.js +32 -13
  8. package/dist/agent/subagent/runtime.d.ts +28 -0
  9. package/dist/agent/subagent/runtime.js +34 -30
  10. package/dist/agent/subagent-control.d.ts +7 -0
  11. package/dist/agent/subagent-control.js +2 -0
  12. package/dist/agent/subagent-lifecycle-reminder.js +2 -1
  13. package/dist/agent/subagent-wait-guidance.d.ts +2 -0
  14. package/dist/agent/subagent-wait-guidance.js +8 -0
  15. package/dist/agent/subtask-policy.js +4 -4
  16. package/dist/agent.d.ts +20 -11
  17. package/dist/agent.js +200 -117
  18. package/dist/anthropic-thinking.d.ts +4 -0
  19. package/dist/anthropic-thinking.js +11 -0
  20. package/dist/approval/controller.d.ts +20 -6
  21. package/dist/approval/controller.js +67 -8
  22. package/dist/approval/protected-paths.d.ts +1 -0
  23. package/dist/approval/protected-paths.js +35 -0
  24. package/dist/approval/session-cache.d.ts +12 -26
  25. package/dist/approval/session-cache.js +20 -50
  26. package/dist/approval/types.d.ts +27 -1
  27. package/dist/cli.d.ts +5 -0
  28. package/dist/cli.js +25 -2
  29. package/dist/config.d.ts +3 -0
  30. package/dist/config.js +7 -0
  31. package/dist/context/checkpoint.d.ts +18 -0
  32. package/dist/context/checkpoint.js +117 -0
  33. package/dist/context/compact-llm.js +7 -0
  34. package/dist/context/compact.d.ts +8 -0
  35. package/dist/context/compact.js +40 -7
  36. package/dist/context/llm-compactor.d.ts +36 -2
  37. package/dist/context/llm-compactor.js +227 -44
  38. package/dist/context/session-write-lock.d.ts +20 -0
  39. package/dist/context/session-write-lock.js +162 -0
  40. package/dist/context/tool-images.d.ts +3 -0
  41. package/dist/context/tool-images.js +35 -0
  42. package/dist/context/usage.js +22 -5
  43. package/dist/feishu/agent-host/run-driver.js +56 -9
  44. package/dist/lsp/service.d.ts +13 -1
  45. package/dist/lsp/service.js +163 -43
  46. package/dist/main.js +82 -16
  47. package/dist/mcp/config.d.ts +4 -0
  48. package/dist/mcp/config.js +17 -0
  49. package/dist/mcp/manager.d.ts +13 -1
  50. package/dist/mcp/manager.js +32 -1
  51. package/dist/mcp/transports.js +11 -0
  52. package/dist/memory/db.d.ts +1 -0
  53. package/dist/memory/db.js +20 -4
  54. package/dist/memory/phase1.js +122 -16
  55. package/dist/memory/prompts.js +3 -0
  56. package/dist/model-catalog.js +19 -3
  57. package/dist/model-config.d.ts +1 -0
  58. package/dist/model-config.js +5 -5
  59. package/dist/model-pricing.js +26 -9
  60. package/dist/network/provider-transport-log.d.ts +12 -0
  61. package/dist/network/provider-transport-log.js +32 -0
  62. package/dist/network/provider-transport.js +6 -1
  63. package/dist/network/retry.d.ts +1 -1
  64. package/dist/network/retry.js +1 -1
  65. package/dist/oauth/grok.d.ts +1 -0
  66. package/dist/oauth/grok.js +20 -16
  67. package/dist/oauth/openai-codex.d.ts +1 -0
  68. package/dist/oauth/openai-codex.js +29 -25
  69. package/dist/oauth/refresh-control.d.ts +12 -0
  70. package/dist/oauth/refresh-control.js +42 -0
  71. package/dist/oauth/storage.d.ts +55 -1
  72. package/dist/oauth/storage.js +281 -16
  73. package/dist/permissions/rule.d.ts +6 -3
  74. package/dist/permissions/rule.js +71 -12
  75. package/dist/permissions/settings.d.ts +28 -1
  76. package/dist/permissions/settings.js +93 -3
  77. package/dist/permissions/shell-command.d.ts +36 -0
  78. package/dist/permissions/shell-command.js +226 -0
  79. package/dist/permissions/trust-prompt.d.ts +10 -0
  80. package/dist/permissions/trust-prompt.js +34 -0
  81. package/dist/permissions/trust.d.ts +26 -0
  82. package/dist/permissions/trust.js +113 -0
  83. package/dist/prompt/compose.d.ts +3 -0
  84. package/dist/prompt/compose.js +24 -7
  85. package/dist/prompt/environment.js +2 -2
  86. package/dist/prompt/reminders.js +1 -1
  87. package/dist/prompt/runtime.js +1 -1
  88. package/dist/provider-anthropic.d.ts +6 -2
  89. package/dist/provider-anthropic.js +98 -18
  90. package/dist/provider-error-record.d.ts +9 -0
  91. package/dist/provider-error-record.js +42 -14
  92. package/dist/provider-grok.js +5 -1
  93. package/dist/provider-openai-codex.d.ts +8 -0
  94. package/dist/provider-openai-codex.js +107 -24
  95. package/dist/provider-registry.d.ts +45 -2
  96. package/dist/provider-registry.js +300 -88
  97. package/dist/provider-transform.js +8 -0
  98. package/dist/provider-zen-errors.d.ts +9 -0
  99. package/dist/provider-zen-errors.js +36 -0
  100. package/dist/provider.js +36 -5
  101. package/dist/sdk/index.d.ts +69 -8
  102. package/dist/sdk/index.js +252 -39
  103. package/dist/sdk/replay-event-log.d.ts +7 -0
  104. package/dist/sdk/replay-event-log.js +66 -16
  105. package/dist/session-context-fence.d.ts +16 -0
  106. package/dist/session-context-fence.js +26 -0
  107. package/dist/session-log.d.ts +11 -2
  108. package/dist/session-log.js +187 -39
  109. package/dist/session-types.d.ts +5 -1
  110. package/dist/session.d.ts +39 -7
  111. package/dist/session.js +341 -93
  112. package/dist/skills/format.d.ts +31 -1
  113. package/dist/skills/format.js +45 -24
  114. package/dist/slash-commands/commands.d.ts +3 -0
  115. package/dist/slash-commands/commands.js +29 -14
  116. package/dist/system-prompt.d.ts +3 -1
  117. package/dist/tasks/manager.d.ts +7 -0
  118. package/dist/tasks/manager.js +97 -18
  119. package/dist/tools/agent-lifecycle.js +11 -7
  120. package/dist/tools/child-tools.d.ts +1 -1
  121. package/dist/tools/child-tools.js +4 -4
  122. package/dist/tools/edit-apply.d.ts +0 -3
  123. package/dist/tools/edit-apply.js +45 -249
  124. package/dist/tools/edit.js +3 -3
  125. package/dist/tools/exit-plan-mode.d.ts +5 -0
  126. package/dist/tools/exit-plan-mode.js +3 -2
  127. package/dist/tools/file-state.d.ts +4 -0
  128. package/dist/tools/file-state.js +12 -3
  129. package/dist/tools/grep.js +20 -1
  130. package/dist/tools/index.d.ts +1 -1
  131. package/dist/tools/index.js +3 -3
  132. package/dist/tools/ls.d.ts +3 -0
  133. package/dist/tools/ls.js +85 -0
  134. package/dist/tools/path-utils.d.ts +6 -0
  135. package/dist/tools/path-utils.js +38 -1
  136. package/dist/tools/sensitive-paths.d.ts +8 -0
  137. package/dist/tools/sensitive-paths.js +85 -3
  138. package/dist/tools/skill.d.ts +2 -0
  139. package/dist/tools/skill.js +34 -2
  140. package/dist/tools/task-tools.js +11 -7
  141. package/dist/tui/app.js +22 -12
  142. package/dist/tui/components/approval-dialog.d.ts +5 -5
  143. package/dist/tui/components/approval-dialog.js +16 -51
  144. package/dist/tui/components/skills-panel.d.ts +4 -0
  145. package/dist/tui/components/skills-panel.js +15 -1
  146. package/dist/tui/components/streaming-message.js +7 -2
  147. package/dist/tui/components/tasks-pane.d.ts +38 -0
  148. package/dist/tui/components/tasks-pane.js +182 -32
  149. package/dist/tui/components/transcript.d.ts +11 -4
  150. package/dist/tui/components/transcript.js +158 -71
  151. package/dist/tui/composer-autocomplete.d.ts +17 -2
  152. package/dist/tui/composer-autocomplete.js +79 -2
  153. package/dist/tui/controller/controller.d.ts +9 -4
  154. package/dist/tui/controller/controller.js +87 -95
  155. package/dist/tui/controller/goal-runtime-controller.js +1 -1
  156. package/dist/tui/controller/session-transition.js +1 -1
  157. package/dist/tui/model/subagent-view.d.ts +11 -19
  158. package/dist/tui/model/subagent-view.js +56 -85
  159. package/dist/tui/model/task-lifecycle.d.ts +57 -0
  160. package/dist/tui/model/task-lifecycle.js +124 -0
  161. package/dist/tui/model/trace-groups.js +10 -9
  162. package/dist/tui/trace-groups.js +10 -9
  163. package/dist/types.d.ts +20 -0
  164. package/dist/variant/variant-resolver.js +2 -0
  165. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui-alt-screen.d.ts +1 -0
  166. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui-alt-screen.d.ts.map +1 -1
  167. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui-alt-screen.js +6 -0
  168. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui-alt-screen.js.map +1 -1
  169. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui.d.ts +2 -0
  170. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui.d.ts.map +1 -1
  171. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui.js +8 -4
  172. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui.js.map +1 -1
  173. package/package.json +11 -3
  174. package/dist/prompt/skills.d.ts +0 -2
  175. package/dist/prompt/skills.js +0 -4
  176. package/dist/tools/glob.d.ts +0 -5
  177. package/dist/tools/glob.js +0 -199
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Background task lifecycle projection for the transcript.
3
+ *
4
+ * A `bash run_in_background` call settles as soon as the process is spawned,
5
+ * leaving a "Task started" row in the trace. When the task later finishes,
6
+ * its terminal state (completed / failed / killed, exit code, duration,
7
+ * output tail) is landed on that same launch row by task id, so the reader
8
+ * sees the outcome where the command was issued rather than as a detached
9
+ * row appended after the assistant's answer.
10
+ *
11
+ * A synthetic terminal row is only produced when no launch row exists (the
12
+ * transcript was cleared, or the task was started outside this transcript).
13
+ */
14
+ import type { BackgroundTaskInfo } from "../../tasks/manager.js";
15
+ import { type DisplayMessage, type DisplayToolCall } from "./display-history.js";
16
+ /**
17
+ * Occurrence for a restored terminal marker whose task_started marker is not
18
+ * in the retained log (the task was launched before a conversation_clear).
19
+ * It must never land on a later launch that happens to reuse the task id.
20
+ */
21
+ export declare const UNMATCHED_LAUNCH = -1;
22
+ export interface TaskLifecycleTerminal {
23
+ task: BackgroundTaskInfo;
24
+ output?: string;
25
+ /**
26
+ * Which launch of this task id the terminal state belongs to (0-based, in
27
+ * transcript order), or UNMATCHED_LAUNCH. Task ids restart at task_0001 in
28
+ * every process, so a resumed session can hold several launches sharing
29
+ * one id; persisted markers carry their launch order. Omitted for live
30
+ * completions, which always belong to the newest launch not settled yet.
31
+ */
32
+ occurrence?: number;
33
+ }
34
+ /** Returns a copy of `tool` carrying the task's terminal state. */
35
+ export declare function applyTaskLifecycleToTool(tool: DisplayToolCall, task: BackgroundTaskInfo, output?: string): DisplayToolCall;
36
+ /**
37
+ * Lands the terminal state on a launch row that is still in the streaming
38
+ * accumulator. Mutates in place because the accumulator's parts share the
39
+ * same tool objects. A row whose tool_end has not arrived yet is skipped:
40
+ * the reducer would overwrite the merge when the result lands.
41
+ */
42
+ export declare function mergeTaskLifecycleIntoLiveTools(tools: DisplayToolCall[], task: BackgroundTaskInfo, output?: string): boolean;
43
+ /**
44
+ * Lands the terminal state on exactly one committed launch row: the given
45
+ * launch occurrence, or (for live completions) the newest one still open.
46
+ */
47
+ export declare function applyTaskLifecycleToMessages(messages: DisplayMessage[], task: BackgroundTaskInfo, output?: string, occurrence?: number): {
48
+ messages: DisplayMessage[];
49
+ merged: boolean;
50
+ };
51
+ /** Detached terminal row for a task whose launch row is not in the transcript. */
52
+ export declare function taskLifecycleDisplayMessage(task: BackgroundTaskInfo, output?: string): DisplayMessage;
53
+ /**
54
+ * Lands every terminal state on its launch row; tasks without one get a
55
+ * detached row appended in the given order.
56
+ */
57
+ export declare function landTaskLifecycles(messages: DisplayMessage[], terminals: TaskLifecycleTerminal[]): DisplayMessage[];
@@ -0,0 +1,124 @@
1
+ import { nextDisplayMessageKey } from "./display-history.js";
2
+ import { mapTranscriptTools } from "./subagent-view.js";
3
+ /**
4
+ * Occurrence for a restored terminal marker whose task_started marker is not
5
+ * in the retained log (the task was launched before a conversation_clear).
6
+ * It must never land on a later launch that happens to reuse the task id.
7
+ */
8
+ export const UNMATCHED_LAUNCH = -1;
9
+ function isLaunchRowFor(tool, taskId) {
10
+ return tool.metadata?.background === true && tool.metadata?.taskId === taskId;
11
+ }
12
+ function hasLanded(tool) {
13
+ return tool.metadata?.taskLifecycle !== undefined;
14
+ }
15
+ /** Launch rows for a task id in transcript order, one entry per tool call. */
16
+ function launchRowsFor(messages, taskId) {
17
+ const seen = new Set();
18
+ const rows = [];
19
+ for (const message of messages) {
20
+ const tools = message.toolCalls
21
+ ?? message.parts?.flatMap((part) => (part.type === "tools" ? part.toolCalls : []))
22
+ ?? [];
23
+ for (const tool of tools) {
24
+ if (!isLaunchRowFor(tool, taskId) || seen.has(tool.id))
25
+ continue;
26
+ seen.add(tool.id);
27
+ rows.push(tool);
28
+ }
29
+ }
30
+ return rows;
31
+ }
32
+ /** The launch row a terminal state should land on, or undefined. */
33
+ function targetLaunchRow(messages, taskId, occurrence) {
34
+ const rows = launchRowsFor(messages, taskId);
35
+ if (occurrence !== undefined)
36
+ return occurrence >= 0 ? rows[occurrence] : undefined;
37
+ for (let index = rows.length - 1; index >= 0; index -= 1) {
38
+ if (!hasLanded(rows[index]))
39
+ return rows[index];
40
+ }
41
+ return undefined;
42
+ }
43
+ function displayStatus(task) {
44
+ return task.status === "killed" ? "cancelled" : task.status === "failed" ? "failed" : "completed";
45
+ }
46
+ /** Returns a copy of `tool` carrying the task's terminal state. */
47
+ export function applyTaskLifecycleToTool(tool, task, output) {
48
+ return {
49
+ ...tool,
50
+ status: displayStatus(task),
51
+ isError: task.status === "failed",
52
+ result: output?.trim() ? output : tool.result,
53
+ startedAt: task.startedAt ?? tool.startedAt,
54
+ metadata: {
55
+ ...tool.metadata,
56
+ kind: "shell",
57
+ background: true,
58
+ taskId: task.id,
59
+ taskLifecycle: task.status,
60
+ exitCode: task.exitCode ?? null,
61
+ endedAt: task.endedAt,
62
+ outputLines: task.outputLines,
63
+ },
64
+ };
65
+ }
66
+ /**
67
+ * Lands the terminal state on a launch row that is still in the streaming
68
+ * accumulator. Mutates in place because the accumulator's parts share the
69
+ * same tool objects. A row whose tool_end has not arrived yet is skipped:
70
+ * the reducer would overwrite the merge when the result lands.
71
+ */
72
+ export function mergeTaskLifecycleIntoLiveTools(tools, task, output) {
73
+ const tool = [...tools].reverse().find((candidate) => isLaunchRowFor(candidate, task.id) && !hasLanded(candidate));
74
+ if (!tool || tool.status === "running")
75
+ return false;
76
+ Object.assign(tool, applyTaskLifecycleToTool(tool, task, output));
77
+ return true;
78
+ }
79
+ /**
80
+ * Lands the terminal state on exactly one committed launch row: the given
81
+ * launch occurrence, or (for live completions) the newest one still open.
82
+ */
83
+ export function applyTaskLifecycleToMessages(messages, task, output, occurrence) {
84
+ const target = targetLaunchRow(messages, task.id, occurrence);
85
+ if (!target)
86
+ return { messages, merged: false };
87
+ const next = mapTranscriptTools(messages, (tool) => tool.id === target.id ? applyTaskLifecycleToTool(tool, task, output) : tool);
88
+ return { messages: next, merged: next !== messages };
89
+ }
90
+ /** Detached terminal row for a task whose launch row is not in the transcript. */
91
+ export function taskLifecycleDisplayMessage(task, output) {
92
+ const tool = applyTaskLifecycleToTool({
93
+ id: `task-lifecycle:${task.id}:${task.endedAt ?? Date.now()}`,
94
+ name: "bash",
95
+ args: {
96
+ command: task.command,
97
+ ...(task.description ? { description: task.description } : {}),
98
+ },
99
+ startedAt: task.startedAt,
100
+ }, task, output);
101
+ return {
102
+ key: nextDisplayMessageKey("task"),
103
+ role: "assistant",
104
+ content: "",
105
+ toolCalls: [tool],
106
+ parts: [{ type: "tools", toolCalls: [tool] }],
107
+ };
108
+ }
109
+ /**
110
+ * Lands every terminal state on its launch row; tasks without one get a
111
+ * detached row appended in the given order.
112
+ */
113
+ export function landTaskLifecycles(messages, terminals) {
114
+ let next = messages;
115
+ const detached = [];
116
+ for (const { task, output, occurrence } of terminals) {
117
+ const landed = applyTaskLifecycleToMessages(next, task, output, occurrence);
118
+ if (landed.merged)
119
+ next = landed.messages;
120
+ else
121
+ detached.push(taskLifecycleDisplayMessage(task, output));
122
+ }
123
+ return detached.length > 0 ? [...next, ...detached] : next;
124
+ }
@@ -121,9 +121,10 @@ function classifyTool(toolCall) {
121
121
  }
122
122
  }
123
123
  switch (toolCall.name) {
124
+ case "ls":
125
+ return { kind: "list", title: "List Directory", bucketKey: "list:directory", groupable: true };
124
126
  case "glob": {
125
- const pattern = String(toolCall.args.pattern ?? "");
126
- const title = isDirectoryLikeGlob(pattern) ? "List Directory" : "Find Files";
127
+ const title = "Find Files";
127
128
  return {
128
129
  kind: "list",
129
130
  title,
@@ -188,7 +189,9 @@ function buildListGroup(classifier, raw, options, pending, startedAt, hasError,
188
189
  const sourceItems = hasResultData ? resultItems : fallbackItems;
189
190
  const { shown, omitted } = take(sourceItems, options.maxItems);
190
191
  const count = matchCount ?? (hasResultData ? resultItems.length : sourceItems.length || raw.length);
191
- const noun = hasResultData ? plural(count, "file", "files") : plural(count, "search", "searches");
192
+ const noun = hasResultData
193
+ ? classifier.title === "List Directory" ? plural(count, "entry", "entries") : plural(count, "file", "files")
194
+ : plural(count, "search", "searches");
192
195
  return {
193
196
  kind: "list",
194
197
  title: classifier.title,
@@ -209,7 +212,7 @@ function listResultItems(tool, homeDir) {
209
212
  const metadataPaths = Array.isArray(tool.metadata?.paths)
210
213
  ? tool.metadata.paths.filter((item) => typeof item === "string" && item.trim().length > 0)
211
214
  : [];
212
- if (metadataPaths.length > 0) {
215
+ if (Array.isArray(tool.metadata?.paths)) {
213
216
  return metadataPaths.map((line) => formatTracePath(line, homeDir));
214
217
  }
215
218
  return resultLines(tool.result)
@@ -236,7 +239,9 @@ function isEmptyListResult(result) {
236
239
  }
237
240
  function isListResultLine(line) {
238
241
  const normalized = line.trim();
239
- return !/^No files found\.?$/i.test(normalized)
242
+ return !/^\(empty directory\)$/i.test(normalized)
243
+ && !/^\[Output truncated.*\]$/i.test(normalized)
244
+ && !/^No files found\.?$/i.test(normalized)
240
245
  && !/^\[More than \d+ files, output truncated\]$/i.test(normalized);
241
246
  }
242
247
  function buildPathGroup(classifier, raw, options, pending, startedAt, hasError, errorCount, nounBase) {
@@ -450,10 +455,6 @@ function isToolPending(tool) {
450
455
  }
451
456
  return tool.result === undefined;
452
457
  }
453
- function isDirectoryLikeGlob(pattern) {
454
- const normalized = pattern.trim();
455
- return normalized === "" || normalized === "*" || normalized === "**" || normalized === "**/*";
456
- }
457
458
  function resultLines(result) {
458
459
  if (result === undefined)
459
460
  return [];
@@ -114,9 +114,10 @@ function classifyTool(toolCall) {
114
114
  }
115
115
  }
116
116
  switch (toolCall.name) {
117
+ case "ls":
118
+ return { kind: "list", title: "List Directory", bucketKey: "list:directory", groupable: true };
117
119
  case "glob": {
118
- const pattern = String(toolCall.args.pattern ?? "");
119
- const title = isDirectoryLikeGlob(pattern) ? "List Directory" : "Find Files";
120
+ const title = "Find Files";
120
121
  return {
121
122
  kind: "list",
122
123
  title,
@@ -186,7 +187,9 @@ function buildListGroup(classifier, raw, options, pending, startedAt, hasError,
186
187
  const sourceItems = hasResultData ? resultItems : fallbackItems;
187
188
  const { shown, omitted } = take(sourceItems, options.maxItems);
188
189
  const count = matchCount ?? (hasResultData ? resultItems.length : sourceItems.length || raw.length);
189
- const noun = hasResultData ? plural(count, "file", "files") : plural(count, "search", "searches");
190
+ const noun = hasResultData
191
+ ? classifier.title === "List Directory" ? plural(count, "entry", "entries") : plural(count, "file", "files")
192
+ : plural(count, "search", "searches");
190
193
  return {
191
194
  kind: "list",
192
195
  title: classifier.title,
@@ -207,7 +210,7 @@ function listResultItems(tool, homeDir) {
207
210
  const metadataPaths = Array.isArray(tool.metadata?.paths)
208
211
  ? tool.metadata.paths.filter((item) => typeof item === "string" && item.trim().length > 0)
209
212
  : [];
210
- if (metadataPaths.length > 0) {
213
+ if (Array.isArray(tool.metadata?.paths)) {
211
214
  return metadataPaths.map((line) => formatTracePath(line, homeDir));
212
215
  }
213
216
  return resultLines(tool.result)
@@ -234,7 +237,9 @@ function isEmptyListResult(result) {
234
237
  }
235
238
  function isListResultLine(line) {
236
239
  const normalized = line.trim();
237
- return !/^No files found\.?$/i.test(normalized)
240
+ return !/^\(empty directory\)$/i.test(normalized)
241
+ && !/^\[Output truncated.*\]$/i.test(normalized)
242
+ && !/^No files found\.?$/i.test(normalized)
238
243
  && !/^\[More than \d+ files, output truncated\]$/i.test(normalized);
239
244
  }
240
245
  function buildPathGroup(classifier, raw, options, pending, startedAt, hasError, errorCount, nounBase) {
@@ -424,10 +429,6 @@ function isFailedSubagent(subagent) {
424
429
  function isToolPending(tool) {
425
430
  return tool.result === undefined && tool.resultCollapsed !== true;
426
431
  }
427
- function isDirectoryLikeGlob(pattern) {
428
- const normalized = pattern.trim();
429
- return normalized === "" || normalized === "*" || normalized === "**" || normalized === "**/*";
430
- }
431
432
  function resultLines(result) {
432
433
  if (result === undefined)
433
434
  return [];
package/dist/types.d.ts CHANGED
@@ -36,6 +36,8 @@ export interface AssistantProviderMetadata {
36
36
  }
37
37
  export interface UserMessage {
38
38
  role: "user";
39
+ /** Internal image observation; not an authored user prompt. */
40
+ toolObservation?: true;
39
41
  content: string | ContentPart[];
40
42
  /** Local presentation metadata; provider adapters intentionally ignore it. */
41
43
  ui?: {
@@ -147,6 +149,11 @@ export interface ToolResultMetadata {
147
149
  [key: string]: unknown;
148
150
  }
149
151
  export interface ToolResult {
152
+ /** Bounded screenshots, delivered as a model-visible image observation after the tool batch. */
153
+ images?: {
154
+ mimeType: "image/png" | "image/jpeg";
155
+ data: string;
156
+ }[];
150
157
  content: string;
151
158
  isError?: boolean;
152
159
  status?: ToolResultStatus;
@@ -382,6 +389,19 @@ export interface AgentInputController {
382
389
  export type AgentInputRejectedReason = "no_continuation" | "turn_failed" | "turn_cancelled";
383
390
  export type AgentEvent = {
384
391
  type: "turn_start";
392
+ } | {
393
+ type: "context_usage";
394
+ usedTokens: number;
395
+ contextWindow?: number;
396
+ estimated: boolean;
397
+ } | {
398
+ type: "context_compaction";
399
+ status: "started" | "completed" | "failed";
400
+ compactionId?: string;
401
+ persisted?: boolean;
402
+ preTokens: number;
403
+ postTokens?: number;
404
+ contextWindow?: number;
385
405
  } | {
386
406
  type: "text_delta";
387
407
  content: string;
@@ -31,6 +31,8 @@ export function isThinkingOnlyModel(providerId = "", modelId = "") {
31
31
  export function isThinkingToggleModel(providerId = "", modelId = "") {
32
32
  const normalizedProvider = providerId.toLowerCase();
33
33
  const normalizedModel = modelId.toLowerCase();
34
+ if (normalizedProvider === "mimo-token-plan")
35
+ return true;
34
36
  if (normalizedProvider.includes("minimax") || normalizedModel.includes("minimax"))
35
37
  return true;
36
38
  return KIMI_TOGGLE_PROVIDER_IDS.has(normalizedProvider)
@@ -86,6 +86,7 @@ export declare class TuiAltScreen extends TuiBase implements ViewportTUI {
86
86
  protected afterTerminalStop(options: TuiStopOptions): void;
87
87
  private deleteKittyImages;
88
88
  private prepareKittyScreen;
89
+ protected afterTerminalResume(): void;
89
90
  protected resetRenderState(): void;
90
91
  scrollBy(lines: number): void;
91
92
  scrollToTop(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"tui-alt-screen.d.ts","sourceRoot":"","sources":["../../src/tui-alt-screen.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tui-alt-screen.d.ts","sourceRoot":"","sources":["../../src/tui-alt-screen.ts"],"names":[],"mappings":"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"}
@@ -217,6 +217,12 @@ export class TuiAltScreen extends TuiBase {
217
217
  }
218
218
  return { lines, evictedImageDeletion };
219
219
  }
220
+ afterTerminalResume() {
221
+ // The terminal may have lost image bytes while our cached layout and
222
+ // transmission IDs remain valid. Re-upload visible images on this repaint,
223
+ // and offscreen images when they next enter the viewport.
224
+ this.uploadedKittyImages.clear();
225
+ }
220
226
  resetRenderState() {
221
227
  this.previousScreen = [];
222
228
  this.previousScreenWidth = 0;