@bubblebrain-ai/bubble 0.0.19 → 0.0.20
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/agent/internal-reminder-sanitizer.d.ts +1 -0
- package/dist/agent/internal-reminder-sanitizer.js +46 -0
- package/dist/agent.d.ts +9 -0
- package/dist/agent.js +305 -17
- package/dist/approval/controller.d.ts +6 -0
- package/dist/approval/controller.js +104 -11
- package/dist/debug-trace.js +4 -0
- package/dist/feishu/agent-host/run-driver.js +28 -0
- package/dist/hooks/config.d.ts +9 -0
- package/dist/hooks/config.js +278 -0
- package/dist/hooks/controller.d.ts +24 -0
- package/dist/hooks/controller.js +254 -0
- package/dist/hooks/index.d.ts +6 -0
- package/dist/hooks/index.js +4 -0
- package/dist/hooks/log.d.ts +14 -0
- package/dist/hooks/log.js +54 -0
- package/dist/hooks/runner.d.ts +5 -0
- package/dist/hooks/runner.js +225 -0
- package/dist/hooks/trust.d.ts +37 -0
- package/dist/hooks/trust.js +143 -0
- package/dist/hooks/types.d.ts +173 -0
- package/dist/hooks/types.js +46 -0
- package/dist/main.js +32 -0
- package/dist/memory/prompts.js +3 -1
- package/dist/model-catalog.js +2 -0
- package/dist/model-pricing.js +8 -0
- package/dist/network/chatgpt-transport.d.ts +0 -1
- package/dist/network/chatgpt-transport.js +40 -121
- package/dist/network/provider-transport.d.ts +32 -0
- package/dist/network/provider-transport.js +265 -0
- package/dist/network/retry.d.ts +29 -0
- package/dist/network/retry.js +88 -0
- package/dist/network/system-proxy.d.ts +18 -0
- package/dist/network/system-proxy.js +175 -0
- package/dist/provider-anthropic.d.ts +1 -0
- package/dist/provider-anthropic.js +127 -52
- package/dist/provider-openai-codex.js +19 -29
- package/dist/session-log.js +3 -3
- package/dist/slash-commands/commands.js +84 -0
- package/dist/slash-commands/types.d.ts +2 -0
- package/dist/tools/edit-apply.js +63 -3
- package/dist/tools/edit.js +4 -4
- package/dist/tui/display-history.d.ts +4 -3
- package/dist/tui/display-history.js +34 -57
- package/dist/tui/display-sanitizer.d.ts +3 -0
- package/dist/tui/display-sanitizer.js +38 -0
- package/dist/tui/paste-placeholder.d.ts +1 -0
- package/dist/tui/paste-placeholder.js +7 -0
- package/dist/tui/run.d.ts +2 -0
- package/dist/tui/run.js +260 -155
- package/dist/tui/trace-groups.js +40 -4
- package/dist/tui/wordmark.d.ts +1 -0
- package/dist/tui/wordmark.js +56 -54
- package/dist/tui-ink/app.js +2 -1
- package/dist/tui-ink/trace-groups.js +40 -4
- package/dist/tui-opentui/app.js +2 -1
- package/dist/tui-opentui/trace-groups.js +40 -4
- package/dist/types.d.ts +27 -0
- package/package.json +1 -1
package/dist/tui/trace-groups.js
CHANGED
|
@@ -133,15 +133,17 @@ function buildTraceGroup(classifier, raw, options) {
|
|
|
133
133
|
}
|
|
134
134
|
}
|
|
135
135
|
function buildListGroup(classifier, raw, options, pending, startedAt, hasError, errorCount) {
|
|
136
|
-
const
|
|
136
|
+
const matchCount = listMatchCount(raw);
|
|
137
|
+
const resultItems = raw.flatMap((tool) => listResultItems(tool, options.homeDir));
|
|
137
138
|
const fallbackItems = raw
|
|
138
139
|
.map((tool) => String(tool.args.pattern ?? tool.args.path ?? "").trim())
|
|
139
140
|
.filter(Boolean)
|
|
140
141
|
.map((item) => formatTracePath(item, options.homeDir));
|
|
141
|
-
const
|
|
142
|
+
const hasResultData = matchCount !== undefined || resultItems.length > 0 || raw.some((tool) => isEmptyListResult(tool.result));
|
|
143
|
+
const sourceItems = hasResultData ? resultItems : fallbackItems;
|
|
142
144
|
const { shown, omitted } = take(sourceItems, options.maxItems);
|
|
143
|
-
const count =
|
|
144
|
-
const noun =
|
|
145
|
+
const count = matchCount ?? (hasResultData ? resultItems.length : sourceItems.length || raw.length);
|
|
146
|
+
const noun = hasResultData ? plural(count, "file", "files") : plural(count, "search", "searches");
|
|
145
147
|
return {
|
|
146
148
|
kind: "list",
|
|
147
149
|
title: classifier.title,
|
|
@@ -158,6 +160,40 @@ function buildListGroup(classifier, raw, options, pending, startedAt, hasError,
|
|
|
158
160
|
startedAt,
|
|
159
161
|
};
|
|
160
162
|
}
|
|
163
|
+
function listResultItems(tool, homeDir) {
|
|
164
|
+
const metadataPaths = Array.isArray(tool.metadata?.paths)
|
|
165
|
+
? tool.metadata.paths.filter((item) => typeof item === "string" && item.trim().length > 0)
|
|
166
|
+
: [];
|
|
167
|
+
if (metadataPaths.length > 0 || typeof tool.metadata?.matches === "number") {
|
|
168
|
+
return metadataPaths.map((line) => formatTracePath(line, homeDir));
|
|
169
|
+
}
|
|
170
|
+
return resultLines(tool.result)
|
|
171
|
+
.filter(isListResultLine)
|
|
172
|
+
.map((line) => formatTracePath(line, homeDir));
|
|
173
|
+
}
|
|
174
|
+
function listMatchCount(raw) {
|
|
175
|
+
let count = 0;
|
|
176
|
+
let sawMetadata = false;
|
|
177
|
+
for (const tool of raw) {
|
|
178
|
+
const matches = tool.metadata?.matches;
|
|
179
|
+
if (typeof matches === "number" && Number.isFinite(matches)) {
|
|
180
|
+
count += Math.max(0, matches);
|
|
181
|
+
sawMetadata = true;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return sawMetadata ? count : undefined;
|
|
185
|
+
}
|
|
186
|
+
function isEmptyListResult(result) {
|
|
187
|
+
if (result === undefined)
|
|
188
|
+
return false;
|
|
189
|
+
const lines = resultLines(result);
|
|
190
|
+
return lines.length > 0 && lines.every((line) => !isListResultLine(line));
|
|
191
|
+
}
|
|
192
|
+
function isListResultLine(line) {
|
|
193
|
+
const normalized = line.trim();
|
|
194
|
+
return !/^No files found\.?$/i.test(normalized)
|
|
195
|
+
&& !/^\[More than \d+ files, output truncated\]$/i.test(normalized);
|
|
196
|
+
}
|
|
161
197
|
function buildPathGroup(classifier, raw, options, pending, startedAt, hasError, errorCount, nounBase) {
|
|
162
198
|
const items = unique(raw
|
|
163
199
|
.map((tool) => formatTracePath(tool.args.path ?? tool.args.file ?? "", options.homeDir))
|
package/dist/tui/wordmark.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export interface BubbleWordmarkLine {
|
|
|
9
9
|
segments?: BubbleWordmarkSegment[];
|
|
10
10
|
}
|
|
11
11
|
export declare const BUBBLE_WORDMARK: BubbleWordmarkLine[];
|
|
12
|
+
export declare const BUBBLE_WORDMARK_LARGE: BubbleWordmarkLine[];
|
|
12
13
|
export declare const BUBBLE_COMPACT_WORDMARK: BubbleWordmarkLine[];
|
|
13
14
|
export declare function bubbleWordmarkLineText(line: BubbleWordmarkLine): string;
|
|
14
15
|
export declare function bubbleWordmarkMaxWidth(lines?: BubbleWordmarkLine[]): number;
|
package/dist/tui/wordmark.js
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
|
+
// Pixel-style glyphs: each cell is a half-block "pixel" (█ ▀ ▄), giving the
|
|
2
|
+
// wordmark an 8-bit look while staying one terminal row per line.
|
|
1
3
|
const LEAD_B = {
|
|
2
4
|
tone: "brand",
|
|
3
5
|
lines: [
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"╰─╯ ",
|
|
6
|
+
"█ ",
|
|
7
|
+
"█ ",
|
|
8
|
+
"█▀█ ",
|
|
9
|
+
"█ █ ",
|
|
10
|
+
"█▄█ ",
|
|
10
11
|
" ",
|
|
11
12
|
],
|
|
12
13
|
};
|
|
13
14
|
const LOWER_B = {
|
|
14
15
|
tone: "ink",
|
|
15
16
|
lines: [
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"╰─╯ ",
|
|
17
|
+
"█ ",
|
|
18
|
+
"█ ",
|
|
19
|
+
"█▀█ ",
|
|
20
|
+
"█ █ ",
|
|
21
|
+
"█▄█ ",
|
|
22
22
|
" ",
|
|
23
23
|
],
|
|
24
24
|
};
|
|
@@ -28,22 +28,20 @@ const GLYPHS = {
|
|
|
28
28
|
lines: [
|
|
29
29
|
" ",
|
|
30
30
|
" ",
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"╰─╯ ",
|
|
31
|
+
"█ █ ",
|
|
32
|
+
"█ █ ",
|
|
33
|
+
"█▄█ ",
|
|
35
34
|
" ",
|
|
36
35
|
],
|
|
37
36
|
},
|
|
38
37
|
l: {
|
|
39
38
|
tone: "ink",
|
|
40
39
|
lines: [
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"╰─ ",
|
|
40
|
+
"█ ",
|
|
41
|
+
"█ ",
|
|
42
|
+
"█ ",
|
|
43
|
+
"█ ",
|
|
44
|
+
"█▄ ",
|
|
47
45
|
" ",
|
|
48
46
|
],
|
|
49
47
|
},
|
|
@@ -52,23 +50,21 @@ const GLYPHS = {
|
|
|
52
50
|
lines: [
|
|
53
51
|
" ",
|
|
54
52
|
" ",
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"╰─╯ ",
|
|
53
|
+
"█▀█ ",
|
|
54
|
+
"█▀▀ ",
|
|
55
|
+
"█▄▄ ",
|
|
59
56
|
" ",
|
|
60
57
|
],
|
|
61
58
|
},
|
|
62
59
|
beta: {
|
|
63
60
|
tone: "brand",
|
|
64
61
|
lines: [
|
|
65
|
-
"
|
|
66
|
-
"
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
"
|
|
71
|
-
"│ ",
|
|
62
|
+
"█▀▀▄ ",
|
|
63
|
+
"█ █ ",
|
|
64
|
+
"█▀▀▄ ",
|
|
65
|
+
"█ █ ",
|
|
66
|
+
"█▄▄▀ ",
|
|
67
|
+
"█ ",
|
|
72
68
|
],
|
|
73
69
|
},
|
|
74
70
|
r: {
|
|
@@ -76,10 +72,9 @@ const GLYPHS = {
|
|
|
76
72
|
lines: [
|
|
77
73
|
" ",
|
|
78
74
|
" ",
|
|
79
|
-
"
|
|
80
|
-
"
|
|
81
|
-
"
|
|
82
|
-
"│ ",
|
|
75
|
+
"█▀▀ ",
|
|
76
|
+
"█ ",
|
|
77
|
+
"█ ",
|
|
83
78
|
" ",
|
|
84
79
|
],
|
|
85
80
|
},
|
|
@@ -88,22 +83,20 @@ const GLYPHS = {
|
|
|
88
83
|
lines: [
|
|
89
84
|
" ",
|
|
90
85
|
" ",
|
|
91
|
-
"
|
|
92
|
-
"
|
|
93
|
-
"
|
|
94
|
-
"│ │ ",
|
|
86
|
+
"▀▀█ ",
|
|
87
|
+
"█▀█ ",
|
|
88
|
+
"█▄█ ",
|
|
95
89
|
" ",
|
|
96
90
|
],
|
|
97
91
|
},
|
|
98
92
|
i: {
|
|
99
93
|
tone: "ink",
|
|
100
94
|
lines: [
|
|
101
|
-
"• ",
|
|
102
95
|
" ",
|
|
103
|
-
"
|
|
104
|
-
"
|
|
105
|
-
"
|
|
106
|
-
"
|
|
96
|
+
"▀ ",
|
|
97
|
+
"█ ",
|
|
98
|
+
"█ ",
|
|
99
|
+
"█ ",
|
|
107
100
|
" ",
|
|
108
101
|
],
|
|
109
102
|
},
|
|
@@ -112,10 +105,9 @@ const GLYPHS = {
|
|
|
112
105
|
lines: [
|
|
113
106
|
" ",
|
|
114
107
|
" ",
|
|
115
|
-
"
|
|
116
|
-
"
|
|
117
|
-
"
|
|
118
|
-
"│ │ ",
|
|
108
|
+
"█▀█ ",
|
|
109
|
+
"█ █ ",
|
|
110
|
+
"█ █ ",
|
|
119
111
|
" ",
|
|
120
112
|
],
|
|
121
113
|
},
|
|
@@ -128,11 +120,10 @@ const GLYPHS = {
|
|
|
128
120
|
" ",
|
|
129
121
|
" ",
|
|
130
122
|
" ",
|
|
131
|
-
" ",
|
|
132
123
|
],
|
|
133
124
|
},
|
|
134
125
|
};
|
|
135
|
-
|
|
126
|
+
const WORDMARK_GLYPHS = [
|
|
136
127
|
LEAD_B,
|
|
137
128
|
GLYPHS.u,
|
|
138
129
|
LOWER_B,
|
|
@@ -145,7 +136,14 @@ export const BUBBLE_WORDMARK = buildWordmark([
|
|
|
145
136
|
GLYPHS.a,
|
|
146
137
|
GLYPHS.i,
|
|
147
138
|
GLYPHS.n,
|
|
148
|
-
]
|
|
139
|
+
];
|
|
140
|
+
export const BUBBLE_WORDMARK = buildWordmark(WORDMARK_GLYPHS);
|
|
141
|
+
// Each pixel doubled horizontally: terminal cells are ~2:1 tall, so 2-char
|
|
142
|
+
// pixels render square and the wordmark reads much larger.
|
|
143
|
+
export const BUBBLE_WORDMARK_LARGE = buildWordmark(WORDMARK_GLYPHS.map((glyph) => ({
|
|
144
|
+
tone: glyph.tone,
|
|
145
|
+
lines: glyph.lines.map((line) => line.split("").map((ch) => ch + ch).join("")),
|
|
146
|
+
})));
|
|
149
147
|
export const BUBBLE_COMPACT_WORDMARK = [
|
|
150
148
|
{
|
|
151
149
|
segments: [
|
|
@@ -175,5 +173,9 @@ export function bubbleWordmarkMaxWidth(lines = BUBBLE_WORDMARK) {
|
|
|
175
173
|
return Math.max(...lines.map((line) => bubbleWordmarkLineText(line).length));
|
|
176
174
|
}
|
|
177
175
|
export function bubbleWordmarkForWidth(width) {
|
|
178
|
-
|
|
176
|
+
if (width >= bubbleWordmarkMaxWidth(BUBBLE_WORDMARK_LARGE) + 4)
|
|
177
|
+
return BUBBLE_WORDMARK_LARGE;
|
|
178
|
+
if (width >= bubbleWordmarkMaxWidth() + 4)
|
|
179
|
+
return BUBBLE_WORDMARK;
|
|
180
|
+
return BUBBLE_COMPACT_WORDMARK;
|
|
179
181
|
}
|
package/dist/tui-ink/app.js
CHANGED
|
@@ -1100,7 +1100,8 @@ export function App({ agent, args, sessionManager, createProvider, registry, ski
|
|
|
1100
1100
|
addMessage("error", `Could not resolve @mention: ${expansion.missing.join(", ")}`);
|
|
1101
1101
|
}
|
|
1102
1102
|
for (const skip of expansion.skipped) {
|
|
1103
|
-
|
|
1103
|
+
if (skip.reason !== "too large")
|
|
1104
|
+
addMessage("error", `Skipped @${skip.path}: ${skip.reason}`);
|
|
1104
1105
|
}
|
|
1105
1106
|
const agentInput = images.length > 0
|
|
1106
1107
|
? [
|
|
@@ -133,15 +133,17 @@ function buildTraceGroup(classifier, raw, options) {
|
|
|
133
133
|
}
|
|
134
134
|
}
|
|
135
135
|
function buildListGroup(classifier, raw, options, pending, startedAt, hasError, errorCount) {
|
|
136
|
-
const
|
|
136
|
+
const matchCount = listMatchCount(raw);
|
|
137
|
+
const resultItems = raw.flatMap((tool) => listResultItems(tool, options.homeDir));
|
|
137
138
|
const fallbackItems = raw
|
|
138
139
|
.map((tool) => String(tool.args.pattern ?? tool.args.path ?? "").trim())
|
|
139
140
|
.filter(Boolean)
|
|
140
141
|
.map((item) => formatTracePath(item, options.homeDir));
|
|
141
|
-
const
|
|
142
|
+
const hasResultData = matchCount !== undefined || resultItems.length > 0 || raw.some((tool) => isEmptyListResult(tool.result));
|
|
143
|
+
const sourceItems = hasResultData ? resultItems : fallbackItems;
|
|
142
144
|
const { shown, omitted } = take(sourceItems, options.maxItems);
|
|
143
|
-
const count =
|
|
144
|
-
const noun =
|
|
145
|
+
const count = matchCount ?? (hasResultData ? resultItems.length : sourceItems.length || raw.length);
|
|
146
|
+
const noun = hasResultData ? plural(count, "file", "files") : plural(count, "search", "searches");
|
|
145
147
|
return {
|
|
146
148
|
kind: "list",
|
|
147
149
|
title: classifier.title,
|
|
@@ -158,6 +160,40 @@ function buildListGroup(classifier, raw, options, pending, startedAt, hasError,
|
|
|
158
160
|
startedAt,
|
|
159
161
|
};
|
|
160
162
|
}
|
|
163
|
+
function listResultItems(tool, homeDir) {
|
|
164
|
+
const metadataPaths = Array.isArray(tool.metadata?.paths)
|
|
165
|
+
? tool.metadata.paths.filter((item) => typeof item === "string" && item.trim().length > 0)
|
|
166
|
+
: [];
|
|
167
|
+
if (metadataPaths.length > 0 || typeof tool.metadata?.matches === "number") {
|
|
168
|
+
return metadataPaths.map((line) => formatTracePath(line, homeDir));
|
|
169
|
+
}
|
|
170
|
+
return resultLines(tool.result)
|
|
171
|
+
.filter(isListResultLine)
|
|
172
|
+
.map((line) => formatTracePath(line, homeDir));
|
|
173
|
+
}
|
|
174
|
+
function listMatchCount(raw) {
|
|
175
|
+
let count = 0;
|
|
176
|
+
let sawMetadata = false;
|
|
177
|
+
for (const tool of raw) {
|
|
178
|
+
const matches = tool.metadata?.matches;
|
|
179
|
+
if (typeof matches === "number" && Number.isFinite(matches)) {
|
|
180
|
+
count += Math.max(0, matches);
|
|
181
|
+
sawMetadata = true;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return sawMetadata ? count : undefined;
|
|
185
|
+
}
|
|
186
|
+
function isEmptyListResult(result) {
|
|
187
|
+
if (result === undefined)
|
|
188
|
+
return false;
|
|
189
|
+
const lines = resultLines(result);
|
|
190
|
+
return lines.length > 0 && lines.every((line) => !isListResultLine(line));
|
|
191
|
+
}
|
|
192
|
+
function isListResultLine(line) {
|
|
193
|
+
const normalized = line.trim();
|
|
194
|
+
return !/^No files found\.?$/i.test(normalized)
|
|
195
|
+
&& !/^\[More than \d+ files, output truncated\]$/i.test(normalized);
|
|
196
|
+
}
|
|
161
197
|
function buildPathGroup(classifier, raw, options, pending, startedAt, hasError, errorCount, nounBase) {
|
|
162
198
|
const items = unique(raw
|
|
163
199
|
.map((tool) => formatTracePath(tool.args.path ?? tool.args.file ?? "", options.homeDir))
|
package/dist/tui-opentui/app.js
CHANGED
|
@@ -1125,7 +1125,8 @@ export function App({ agent, args, sessionManager, createProvider, registry, ski
|
|
|
1125
1125
|
addMessage("error", `Could not resolve @mention: ${expansion.missing.join(", ")}`);
|
|
1126
1126
|
}
|
|
1127
1127
|
for (const skip of expansion.skipped) {
|
|
1128
|
-
|
|
1128
|
+
if (skip.reason !== "too large")
|
|
1129
|
+
addMessage("error", `Skipped @${skip.path}: ${skip.reason}`);
|
|
1129
1130
|
}
|
|
1130
1131
|
const agentInput = images.length > 0
|
|
1131
1132
|
? [
|
|
@@ -133,15 +133,17 @@ function buildTraceGroup(classifier, raw, options) {
|
|
|
133
133
|
}
|
|
134
134
|
}
|
|
135
135
|
function buildListGroup(classifier, raw, options, pending, startedAt, hasError, errorCount) {
|
|
136
|
-
const
|
|
136
|
+
const matchCount = listMatchCount(raw);
|
|
137
|
+
const resultItems = raw.flatMap((tool) => listResultItems(tool, options.homeDir));
|
|
137
138
|
const fallbackItems = raw
|
|
138
139
|
.map((tool) => String(tool.args.pattern ?? tool.args.path ?? "").trim())
|
|
139
140
|
.filter(Boolean)
|
|
140
141
|
.map((item) => formatTracePath(item, options.homeDir));
|
|
141
|
-
const
|
|
142
|
+
const hasResultData = matchCount !== undefined || resultItems.length > 0 || raw.some((tool) => isEmptyListResult(tool.result));
|
|
143
|
+
const sourceItems = hasResultData ? resultItems : fallbackItems;
|
|
142
144
|
const { shown, omitted } = take(sourceItems, options.maxItems);
|
|
143
|
-
const count =
|
|
144
|
-
const noun =
|
|
145
|
+
const count = matchCount ?? (hasResultData ? resultItems.length : sourceItems.length || raw.length);
|
|
146
|
+
const noun = hasResultData ? plural(count, "file", "files") : plural(count, "search", "searches");
|
|
145
147
|
return {
|
|
146
148
|
kind: "list",
|
|
147
149
|
title: classifier.title,
|
|
@@ -158,6 +160,40 @@ function buildListGroup(classifier, raw, options, pending, startedAt, hasError,
|
|
|
158
160
|
startedAt,
|
|
159
161
|
};
|
|
160
162
|
}
|
|
163
|
+
function listResultItems(tool, homeDir) {
|
|
164
|
+
const metadataPaths = Array.isArray(tool.metadata?.paths)
|
|
165
|
+
? tool.metadata.paths.filter((item) => typeof item === "string" && item.trim().length > 0)
|
|
166
|
+
: [];
|
|
167
|
+
if (metadataPaths.length > 0 || typeof tool.metadata?.matches === "number") {
|
|
168
|
+
return metadataPaths.map((line) => formatTracePath(line, homeDir));
|
|
169
|
+
}
|
|
170
|
+
return resultLines(tool.result)
|
|
171
|
+
.filter(isListResultLine)
|
|
172
|
+
.map((line) => formatTracePath(line, homeDir));
|
|
173
|
+
}
|
|
174
|
+
function listMatchCount(raw) {
|
|
175
|
+
let count = 0;
|
|
176
|
+
let sawMetadata = false;
|
|
177
|
+
for (const tool of raw) {
|
|
178
|
+
const matches = tool.metadata?.matches;
|
|
179
|
+
if (typeof matches === "number" && Number.isFinite(matches)) {
|
|
180
|
+
count += Math.max(0, matches);
|
|
181
|
+
sawMetadata = true;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return sawMetadata ? count : undefined;
|
|
185
|
+
}
|
|
186
|
+
function isEmptyListResult(result) {
|
|
187
|
+
if (result === undefined)
|
|
188
|
+
return false;
|
|
189
|
+
const lines = resultLines(result);
|
|
190
|
+
return lines.length > 0 && lines.every((line) => !isListResultLine(line));
|
|
191
|
+
}
|
|
192
|
+
function isListResultLine(line) {
|
|
193
|
+
const normalized = line.trim();
|
|
194
|
+
return !/^No files found\.?$/i.test(normalized)
|
|
195
|
+
&& !/^\[More than \d+ files, output truncated\]$/i.test(normalized);
|
|
196
|
+
}
|
|
161
197
|
function buildPathGroup(classifier, raw, options, pending, startedAt, hasError, errorCount, nounBase) {
|
|
162
198
|
const items = unique(raw
|
|
163
199
|
.map((tool) => formatTracePath(tool.args.path ?? tool.args.file ?? "", options.homeDir))
|
package/dist/types.d.ts
CHANGED
|
@@ -317,6 +317,28 @@ export type AgentEvent = {
|
|
|
317
317
|
} | {
|
|
318
318
|
type: "reasoning_delta";
|
|
319
319
|
content: string;
|
|
320
|
+
} | {
|
|
321
|
+
type: "hook_start";
|
|
322
|
+
eventName: string;
|
|
323
|
+
hookId: string;
|
|
324
|
+
source: string;
|
|
325
|
+
} | {
|
|
326
|
+
type: "hook_end";
|
|
327
|
+
eventName: string;
|
|
328
|
+
hookId: string;
|
|
329
|
+
source: string;
|
|
330
|
+
elapsedMs: number;
|
|
331
|
+
decision: "allow" | "deny";
|
|
332
|
+
reason?: string;
|
|
333
|
+
} | {
|
|
334
|
+
type: "hook_error";
|
|
335
|
+
eventName: string;
|
|
336
|
+
hookId: string;
|
|
337
|
+
source: string;
|
|
338
|
+
elapsedMs?: number;
|
|
339
|
+
decision?: "allow" | "deny";
|
|
340
|
+
reason?: string;
|
|
341
|
+
error: string;
|
|
320
342
|
} | {
|
|
321
343
|
type: "tool_call_start";
|
|
322
344
|
id: string;
|
|
@@ -355,6 +377,11 @@ export type AgentEvent = {
|
|
|
355
377
|
type: "context_recovered";
|
|
356
378
|
droppedMessages: number;
|
|
357
379
|
reason: "overflow";
|
|
380
|
+
} | {
|
|
381
|
+
type: "provider_retry";
|
|
382
|
+
attempt: number;
|
|
383
|
+
maxAttempts: number;
|
|
384
|
+
reason: string;
|
|
358
385
|
} | {
|
|
359
386
|
type: "input_pending_changed";
|
|
360
387
|
pending: number;
|