@vm0/cli 9.244.7 → 9.245.0
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/{agent-2TIFNP32.js → agent-VZXA6XR3.js} +6 -5
- package/{agent-2TIFNP32.js.map → agent-VZXA6XR3.js.map} +1 -1
- package/{banking-UR7XJI3L.js → banking-QOV2GZE6.js} +4 -3
- package/{banking-UR7XJI3L.js.map → banking-QOV2GZE6.js.map} +1 -1
- package/{chat-5N4C3FDV.js → chat-7PONFLUP.js} +5 -4
- package/{chat-5N4C3FDV.js.map → chat-7PONFLUP.js.map} +1 -1
- package/{chunk-NR6ANGRK.js → chunk-5XVBOER3.js} +74 -506
- package/chunk-5XVBOER3.js.map +1 -0
- package/{chunk-E32I3TNQ.js → chunk-6P7XBY46.js} +845 -1217
- package/chunk-6P7XBY46.js.map +1 -0
- package/{chunk-7KSTVBNN.js → chunk-ARENVRJY.js} +4 -4
- package/{chunk-M6GLCPCJ.js → chunk-DE4HMRSU.js} +3 -3
- package/{chunk-STMJYQTH.js → chunk-FVYB5CBP.js} +2 -2
- package/chunk-HOIDOML4.js +678 -0
- package/chunk-HOIDOML4.js.map +1 -0
- package/{chunk-BIJC6U3G.js → chunk-VN4PPSXU.js} +2 -2
- package/{chunk-26BGLMA3.js → chunk-XYZN3XWH.js} +3 -665
- package/chunk-XYZN3XWH.js.map +1 -0
- package/{chunk-JWDLLCI3.js → chunk-YSVL5RAP.js} +2 -2
- package/{chunk-QCG2H3VD.js → chunk-ZXCF4ARW.js} +2 -2
- package/{computer-use-3WUKJYHK.js → computer-use-Y54YFGNC.js} +4 -3
- package/{computer-use-3WUKJYHK.js.map → computer-use-Y54YFGNC.js.map} +1 -1
- package/{connector-PDEOFNTE.js → connector-2PAPMRZG.js} +7 -6
- package/{connector-PDEOFNTE.js.map → connector-2PAPMRZG.js.map} +1 -1
- package/{credit-ET4RS32X.js → credit-PX6354BA.js} +5 -4
- package/{credit-ET4RS32X.js.map → credit-PX6354BA.js.map} +1 -1
- package/{developer-support-3DJEJT2A.js → developer-support-R5K6XKFG.js} +4 -3
- package/{developer-support-3DJEJT2A.js.map → developer-support-R5K6XKFG.js.map} +1 -1
- package/{doctor-F7OWYXXH.js → doctor-JNHZPFHW.js} +4 -3
- package/{doctor-F7OWYXXH.js.map → doctor-JNHZPFHW.js.map} +1 -1
- package/{generate-4GKWSL6P.js → generate-TY4LZA3R.js} +10 -8
- package/{generate-4GKWSL6P.js.map → generate-TY4LZA3R.js.map} +1 -1
- package/{github-S5HFK2IC.js → github-UHTFPDZJ.js} +4 -3
- package/{github-S5HFK2IC.js.map → github-UHTFPDZJ.js.map} +1 -1
- package/{goal-ISJWIT2Q.js → goal-CKBOG76D.js} +4 -3
- package/{goal-ISJWIT2Q.js.map → goal-CKBOG76D.js.map} +1 -1
- package/{host-T52XQ2SZ.js → host-HAVFML26.js} +28 -7
- package/host-HAVFML26.js.map +1 -0
- package/index.js +4 -715
- package/index.js.map +1 -1
- package/{logs-D4IL5OLR.js → logs-OXZZHIMA.js} +13 -14
- package/logs-OXZZHIMA.js.map +1 -0
- package/{mail-JXO3GW72.js → mail-QCU47LFX.js} +6 -5
- package/{mail-JXO3GW72.js.map → mail-QCU47LFX.js.map} +1 -1
- package/{maps-T3YFBRLP.js → maps-F3YPBNGC.js} +4 -3
- package/{maps-T3YFBRLP.js.map → maps-F3YPBNGC.js.map} +1 -1
- package/{model-GJRTV6E5.js → model-5CYADUCZ.js} +5 -4
- package/{model-GJRTV6E5.js.map → model-5CYADUCZ.js.map} +1 -1
- package/{model-provider-T4VN4HNU.js → model-provider-676BK2JF.js} +5 -4
- package/{model-provider-T4VN4HNU.js.map → model-provider-676BK2JF.js.map} +1 -1
- package/{org-GNNU77Y5.js → org-M637OTRU.js} +4 -3
- package/{org-GNNU77Y5.js.map → org-M637OTRU.js.map} +1 -1
- package/package.json +1 -1
- package/{phone-EQ4R2GBO.js → phone-WBFLXP4V.js} +4 -3
- package/{phone-EQ4R2GBO.js.map → phone-WBFLXP4V.js.map} +1 -1
- package/{preference-3FHEQPKG.js → preference-5AVRP7UU.js} +4 -3
- package/{preference-3FHEQPKG.js.map → preference-5AVRP7UU.js.map} +1 -1
- package/{resource-EOO2VATC.js → resource-N6ADJPCL.js} +4 -3
- package/{resource-EOO2VATC.js.map → resource-N6ADJPCL.js.map} +1 -1
- package/{scrape-TZCFJY6X.js → scrape-XIJ5J6LW.js} +4 -3
- package/{scrape-TZCFJY6X.js.map → scrape-XIJ5J6LW.js.map} +1 -1
- package/{search-RXP4DMUC.js → search-V2PWSYSL.js} +9 -10
- package/search-V2PWSYSL.js.map +1 -0
- package/{secret-S4ZCVY2X.js → secret-JLGGOPTX.js} +4 -3
- package/{secret-S4ZCVY2X.js.map → secret-JLGGOPTX.js.map} +1 -1
- package/{slack-7YJFUJE6.js → slack-QNQY6TVX.js} +4 -3
- package/{slack-7YJFUJE6.js.map → slack-QNQY6TVX.js.map} +1 -1
- package/{teams-45MMUROF.js → teams-QZZG5ERQ.js} +4 -3
- package/{teams-45MMUROF.js.map → teams-QZZG5ERQ.js.map} +1 -1
- package/{telegram-7ZCSI24W.js → telegram-JEQYIW2X.js} +4 -3
- package/{telegram-7ZCSI24W.js.map → telegram-JEQYIW2X.js.map} +1 -1
- package/{variable-O33TDP4J.js → variable-LDKUIYU7.js} +4 -3
- package/{variable-O33TDP4J.js.map → variable-LDKUIYU7.js.map} +1 -1
- package/{video-D5LSABFJ.js → video-D3AUHQL2.js} +6 -4
- package/{video-D5LSABFJ.js.map → video-D3AUHQL2.js.map} +1 -1
- package/{web-JW7AH2UT.js → web-MUTRFMMA.js} +7 -5
- package/{web-JW7AH2UT.js.map → web-MUTRFMMA.js.map} +1 -1
- package/{web-search-MHFQFZS6.js → web-search-KBLKNBIF.js} +4 -3
- package/{web-search-MHFQFZS6.js.map → web-search-KBLKNBIF.js.map} +1 -1
- package/{whoami-5DJLOQUZ.js → whoami-POJMF7BB.js} +6 -5
- package/{whoami-5DJLOQUZ.js.map → whoami-POJMF7BB.js.map} +1 -1
- package/{workflow-TXG3RBJR.js → workflow-GXTNSIWC.js} +4 -3
- package/{workflow-TXG3RBJR.js.map → workflow-GXTNSIWC.js.map} +1 -1
- package/zero.js +35 -35
- package/chunk-26BGLMA3.js.map +0 -1
- package/chunk-5QJVQEHO.js +0 -240
- package/chunk-5QJVQEHO.js.map +0 -1
- package/chunk-E32I3TNQ.js.map +0 -1
- package/chunk-NR6ANGRK.js.map +0 -1
- package/chunk-ZUSDQG2O.js +0 -50
- package/chunk-ZUSDQG2O.js.map +0 -1
- package/host-T52XQ2SZ.js.map +0 -1
- package/logs-D4IL5OLR.js.map +0 -1
- package/search-RXP4DMUC.js.map +0 -1
- /package/{chunk-7KSTVBNN.js.map → chunk-ARENVRJY.js.map} +0 -0
- /package/{chunk-M6GLCPCJ.js.map → chunk-DE4HMRSU.js.map} +0 -0
- /package/{chunk-STMJYQTH.js.map → chunk-FVYB5CBP.js.map} +0 -0
- /package/{chunk-BIJC6U3G.js.map → chunk-VN4PPSXU.js.map} +0 -0
- /package/{chunk-JWDLLCI3.js.map → chunk-YSVL5RAP.js.map} +0 -0
- /package/{chunk-QCG2H3VD.js.map → chunk-ZXCF4ARW.js.map} +0 -0
package/chunk-5QJVQEHO.js
DELETED
|
@@ -1,240 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { createRequire as __createRequire } from "node:module";
|
|
3
|
-
const require = __createRequire(import.meta.url);
|
|
4
|
-
import {
|
|
5
|
-
EventRenderer,
|
|
6
|
-
EventStreamNormalizer,
|
|
7
|
-
formatIsoTimestamp,
|
|
8
|
-
isSupportedFramework,
|
|
9
|
-
isUUID,
|
|
10
|
-
parseTime
|
|
11
|
-
} from "./chunk-E32I3TNQ.js";
|
|
12
|
-
import {
|
|
13
|
-
searchZeroLogs
|
|
14
|
-
} from "./chunk-NR6ANGRK.js";
|
|
15
|
-
import {
|
|
16
|
-
source_default,
|
|
17
|
-
withErrorHandler
|
|
18
|
-
} from "./chunk-26BGLMA3.js";
|
|
19
|
-
import {
|
|
20
|
-
Command
|
|
21
|
-
} from "./chunk-B3W2RUBP.js";
|
|
22
|
-
import {
|
|
23
|
-
init_esm_shims
|
|
24
|
-
} from "./chunk-DIRAZ3YX.js";
|
|
25
|
-
|
|
26
|
-
// src/lib/utils/log-pagination.ts
|
|
27
|
-
init_esm_shims();
|
|
28
|
-
function parsePositiveLogCount(value, optionName) {
|
|
29
|
-
const trimmed = value.trim();
|
|
30
|
-
if (!/^0*[1-9]\d*$/.test(trimmed)) {
|
|
31
|
-
throw new Error(`Option ${optionName} must be a positive integer`);
|
|
32
|
-
}
|
|
33
|
-
const count = Number(trimmed);
|
|
34
|
-
if (!Number.isSafeInteger(count)) {
|
|
35
|
-
throw new Error(`Option ${optionName} must be a positive integer`);
|
|
36
|
-
}
|
|
37
|
-
return count;
|
|
38
|
-
}
|
|
39
|
-
function parseBoundedLogCount(value, optionName, min, max) {
|
|
40
|
-
const trimmed = value.trim();
|
|
41
|
-
if (!/^\d+$/.test(trimmed)) {
|
|
42
|
-
throw new Error(`${optionName} must be between ${min} and ${max}`);
|
|
43
|
-
}
|
|
44
|
-
const count = Number(trimmed);
|
|
45
|
-
if (!Number.isSafeInteger(count) || count < min || count > max) {
|
|
46
|
-
throw new Error(`${optionName} must be between ${min} and ${max}`);
|
|
47
|
-
}
|
|
48
|
-
return count;
|
|
49
|
-
}
|
|
50
|
-
async function collectLogItems(options) {
|
|
51
|
-
const collected = [];
|
|
52
|
-
const seenCursors = /* @__PURE__ */ new Set();
|
|
53
|
-
let cursor;
|
|
54
|
-
while (true) {
|
|
55
|
-
const requestLimit = options.targetCount === "all" ? options.pageLimit : Math.min(options.pageLimit, options.targetCount - collected.length);
|
|
56
|
-
const page = await options.fetchPage({
|
|
57
|
-
sinceTime: options.sinceTime,
|
|
58
|
-
cursor,
|
|
59
|
-
limit: requestLimit,
|
|
60
|
-
order: options.order
|
|
61
|
-
});
|
|
62
|
-
collected.push(...page.items);
|
|
63
|
-
if (options.targetCount !== "all" && collected.length >= options.targetCount) {
|
|
64
|
-
break;
|
|
65
|
-
}
|
|
66
|
-
const nextCursor = page.nextCursor ?? null;
|
|
67
|
-
if (!page.hasMore || !nextCursor || seenCursors.has(nextCursor)) {
|
|
68
|
-
break;
|
|
69
|
-
}
|
|
70
|
-
seenCursors.add(nextCursor);
|
|
71
|
-
cursor = nextCursor;
|
|
72
|
-
}
|
|
73
|
-
const entries = options.targetCount === "all" ? collected : collected.slice(0, options.targetCount);
|
|
74
|
-
return options.order === "desc" ? entries.reverse() : entries;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// src/lib/utils/search-query.ts
|
|
78
|
-
init_esm_shims();
|
|
79
|
-
function parseSearchQuery(value, label) {
|
|
80
|
-
const trimmed = value.trim();
|
|
81
|
-
if (!trimmed) {
|
|
82
|
-
throw new Error(`${label} cannot be empty.`);
|
|
83
|
-
}
|
|
84
|
-
return trimmed;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// src/commands/zero/logs/search.ts
|
|
88
|
-
init_esm_shims();
|
|
89
|
-
var SEVEN_DAYS_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
90
|
-
function supportedSearchFramework(framework) {
|
|
91
|
-
const normalized = framework ?? void 0;
|
|
92
|
-
return isSupportedFramework(normalized) ? normalized : void 0;
|
|
93
|
-
}
|
|
94
|
-
function renderSearchEvent(event, framework, renderer, normalizer) {
|
|
95
|
-
const parsedEvents = normalizer.process(
|
|
96
|
-
event.eventData,
|
|
97
|
-
supportedSearchFramework(framework),
|
|
98
|
-
new Date(event.createdAt)
|
|
99
|
-
);
|
|
100
|
-
for (const parsed of parsedEvents) {
|
|
101
|
-
renderer.render(parsed);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
function flushSearchRenderer(renderer, normalizer) {
|
|
105
|
-
for (const parsed of normalizer.flush()) {
|
|
106
|
-
renderer.render(parsed);
|
|
107
|
-
}
|
|
108
|
-
renderer.flush();
|
|
109
|
-
}
|
|
110
|
-
function formatRunHeader(runId, agentName, timestamp) {
|
|
111
|
-
const time = formatIsoTimestamp(timestamp);
|
|
112
|
-
return `\u2500\u2500 Run ${runId} (${agentName}, ${time}) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`;
|
|
113
|
-
}
|
|
114
|
-
function parseContextOptions(options) {
|
|
115
|
-
const contextN = options.context !== void 0 ? parseBoundedLogCount(options.context, "--context", 0, 10) : 0;
|
|
116
|
-
const before = options.beforeContext !== void 0 ? parseBoundedLogCount(options.beforeContext, "--before-context", 0, 10) : contextN;
|
|
117
|
-
const after = options.afterContext !== void 0 ? parseBoundedLogCount(options.afterContext, "--after-context", 0, 10) : contextN;
|
|
118
|
-
return { before, after };
|
|
119
|
-
}
|
|
120
|
-
function parseLimit(value) {
|
|
121
|
-
if (value === void 0) return void 0;
|
|
122
|
-
return parseBoundedLogCount(value, "--limit", 1, 50);
|
|
123
|
-
}
|
|
124
|
-
function renderResults(response) {
|
|
125
|
-
const grouped = /* @__PURE__ */ new Map();
|
|
126
|
-
for (const result of response.results) {
|
|
127
|
-
const existing = grouped.get(result.runId);
|
|
128
|
-
if (existing) {
|
|
129
|
-
existing.results.push(result);
|
|
130
|
-
} else {
|
|
131
|
-
grouped.set(result.runId, {
|
|
132
|
-
agentName: result.agentName,
|
|
133
|
-
results: [result]
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
let isFirstGroup = true;
|
|
138
|
-
for (const [runId, group] of grouped) {
|
|
139
|
-
if (!isFirstGroup) {
|
|
140
|
-
console.log();
|
|
141
|
-
}
|
|
142
|
-
isFirstGroup = false;
|
|
143
|
-
const firstTimestamp = group.results[0].matchedEvent.createdAt;
|
|
144
|
-
console.log(
|
|
145
|
-
source_default.bold(formatRunHeader(runId, group.agentName, firstTimestamp))
|
|
146
|
-
);
|
|
147
|
-
for (const result of group.results) {
|
|
148
|
-
const renderer = new EventRenderer({
|
|
149
|
-
showTimestamp: true,
|
|
150
|
-
verbose: false
|
|
151
|
-
});
|
|
152
|
-
const normalizer = new EventStreamNormalizer();
|
|
153
|
-
for (const event of result.contextBefore) {
|
|
154
|
-
renderSearchEvent(event, result.framework, renderer, normalizer);
|
|
155
|
-
}
|
|
156
|
-
renderSearchEvent(
|
|
157
|
-
result.matchedEvent,
|
|
158
|
-
result.framework,
|
|
159
|
-
renderer,
|
|
160
|
-
normalizer
|
|
161
|
-
);
|
|
162
|
-
for (const event of result.contextAfter) {
|
|
163
|
-
renderSearchEvent(event, result.framework, renderer, normalizer);
|
|
164
|
-
}
|
|
165
|
-
flushSearchRenderer(renderer, normalizer);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
if (response.hasMore) {
|
|
169
|
-
console.log();
|
|
170
|
-
console.log(
|
|
171
|
-
source_default.dim(
|
|
172
|
-
` Showing first ${response.results.length} matches. Use --limit to see more.`
|
|
173
|
-
)
|
|
174
|
-
);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
async function runLogsSearch(keyword, options) {
|
|
178
|
-
const searchKeyword = parseSearchQuery(keyword, "Keyword");
|
|
179
|
-
const { before, after } = parseContextOptions(options);
|
|
180
|
-
if (options.agentId !== void 0 && !isUUID(options.agentId)) {
|
|
181
|
-
console.error(
|
|
182
|
-
source_default.red(`\u2717 Invalid agent ID "${options.agentId}" \u2014 expected a UUID`)
|
|
183
|
-
);
|
|
184
|
-
console.error(source_default.dim(" Run: zero logs list to find agent IDs"));
|
|
185
|
-
process.exit(1);
|
|
186
|
-
}
|
|
187
|
-
if (options.run !== void 0 && !isUUID(options.run)) {
|
|
188
|
-
console.error(
|
|
189
|
-
source_default.red(`\u2717 Invalid run ID "${options.run}" \u2014 expected a UUID`)
|
|
190
|
-
);
|
|
191
|
-
console.error(source_default.dim(" Run: zero logs list to find run IDs"));
|
|
192
|
-
process.exit(1);
|
|
193
|
-
}
|
|
194
|
-
const since = options.since !== void 0 ? parseTime(options.since) : Date.now() - SEVEN_DAYS_MS;
|
|
195
|
-
const limit = parseLimit(options.limit);
|
|
196
|
-
const response = await searchZeroLogs({
|
|
197
|
-
keyword: searchKeyword,
|
|
198
|
-
agentId: options.agentId,
|
|
199
|
-
runId: options.run,
|
|
200
|
-
since,
|
|
201
|
-
limit,
|
|
202
|
-
before,
|
|
203
|
-
after
|
|
204
|
-
});
|
|
205
|
-
if (response.results.length === 0) {
|
|
206
|
-
console.log(source_default.dim("No matches found"));
|
|
207
|
-
console.log(
|
|
208
|
-
source_default.dim(
|
|
209
|
-
" Try a broader search with --since 30d or a different keyword"
|
|
210
|
-
)
|
|
211
|
-
);
|
|
212
|
-
return;
|
|
213
|
-
}
|
|
214
|
-
renderResults(response);
|
|
215
|
-
}
|
|
216
|
-
var searchCommand = new Command().name("search").description("Search agent events across runs").argument("<keyword>", "Search keyword").option("-A, --after-context <n>", "Show n events after each match").option("-B, --before-context <n>", "Show n events before each match").option("-C, --context <n>", "Show n events before and after each match").option("--agent <id>", "Filter by Zero agent ID").option("--run <id>", "Filter by specific run ID").option("--since <time>", "Search logs since (default: 7d)").option("--limit <n>", "Maximum number of matches (default: 20)").addHelpText(
|
|
217
|
-
"after",
|
|
218
|
-
`
|
|
219
|
-
Examples:
|
|
220
|
-
zero logs search "error"
|
|
221
|
-
zero logs search "timeout" --agent 123e4567-e89b-12d3-a456-426614174000 -C 2
|
|
222
|
-
zero logs search "failed" --since 30d --limit 50`
|
|
223
|
-
).action(
|
|
224
|
-
withErrorHandler(
|
|
225
|
-
async (keyword, options) => {
|
|
226
|
-
const { agent, ...searchOptions } = options;
|
|
227
|
-
await runLogsSearch(keyword, { ...searchOptions, agentId: agent });
|
|
228
|
-
}
|
|
229
|
-
)
|
|
230
|
-
);
|
|
231
|
-
|
|
232
|
-
export {
|
|
233
|
-
parsePositiveLogCount,
|
|
234
|
-
parseBoundedLogCount,
|
|
235
|
-
collectLogItems,
|
|
236
|
-
parseSearchQuery,
|
|
237
|
-
runLogsSearch,
|
|
238
|
-
searchCommand
|
|
239
|
-
};
|
|
240
|
-
//# sourceMappingURL=chunk-5QJVQEHO.js.map
|
package/chunk-5QJVQEHO.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/utils/log-pagination.ts","../src/lib/utils/search-query.ts","../src/commands/zero/logs/search.ts"],"sourcesContent":["type LogOrder = \"asc\" | \"desc\";\n\ninterface CursorLogPageRequest {\n readonly sinceTime?: number;\n readonly cursor?: string;\n readonly limit: number;\n readonly order: LogOrder;\n}\n\ninterface CursorLogPage<T> {\n readonly items: readonly T[];\n readonly hasMore: boolean;\n readonly nextCursor?: string | null;\n}\n\ninterface CollectLogItemsOptions<T> {\n readonly fetchPage: (\n request: CursorLogPageRequest,\n ) => Promise<CursorLogPage<T>>;\n readonly sinceTime?: number;\n readonly targetCount: number | \"all\";\n readonly order: LogOrder;\n readonly pageLimit: number;\n}\n\nexport function parsePositiveLogCount(\n value: string,\n optionName: string,\n): number {\n const trimmed = value.trim();\n if (!/^0*[1-9]\\d*$/.test(trimmed)) {\n throw new Error(`Option ${optionName} must be a positive integer`);\n }\n\n const count = Number(trimmed);\n if (!Number.isSafeInteger(count)) {\n throw new Error(`Option ${optionName} must be a positive integer`);\n }\n\n return count;\n}\n\nexport function parseBoundedLogCount(\n value: string,\n optionName: string,\n min: number,\n max: number,\n): number {\n const trimmed = value.trim();\n if (!/^\\d+$/.test(trimmed)) {\n throw new Error(`${optionName} must be between ${min} and ${max}`);\n }\n\n const count = Number(trimmed);\n if (!Number.isSafeInteger(count) || count < min || count > max) {\n throw new Error(`${optionName} must be between ${min} and ${max}`);\n }\n\n return count;\n}\n\nexport async function collectLogItems<T>(\n options: CollectLogItemsOptions<T>,\n): Promise<T[]> {\n const collected: T[] = [];\n const seenCursors = new Set<string>();\n let cursor: string | undefined;\n\n while (true) {\n const requestLimit =\n options.targetCount === \"all\"\n ? options.pageLimit\n : Math.min(options.pageLimit, options.targetCount - collected.length);\n\n const page = await options.fetchPage({\n sinceTime: options.sinceTime,\n cursor,\n limit: requestLimit,\n order: options.order,\n });\n\n collected.push(...page.items);\n\n if (\n options.targetCount !== \"all\" &&\n collected.length >= options.targetCount\n ) {\n break;\n }\n\n const nextCursor = page.nextCursor ?? null;\n if (!page.hasMore || !nextCursor || seenCursors.has(nextCursor)) {\n break;\n }\n\n seenCursors.add(nextCursor);\n cursor = nextCursor;\n }\n\n const entries =\n options.targetCount === \"all\"\n ? collected\n : collected.slice(0, options.targetCount);\n\n return options.order === \"desc\" ? entries.reverse() : entries;\n}\n","export function parseSearchQuery(value: string, label: string): string {\n const trimmed = value.trim();\n if (!trimmed) {\n throw new Error(`${label} cannot be empty.`);\n }\n return trimmed;\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport {\n searchZeroLogs,\n type RunEvent,\n type LogsSearchResponse,\n} from \"../../../lib/api\";\nimport { parseTime } from \"../../../lib/utils/time-parser\";\nimport { formatIsoTimestamp } from \"../../../lib/utils/time-format\";\nimport { EventRenderer } from \"../../../lib/events/event-renderer\";\nimport { EventStreamNormalizer } from \"../../../lib/events/event-stream-normalizer\";\nimport { withErrorHandler } from \"../../../lib/command\";\nimport { isUUID } from \"../../run/shared\";\nimport { parseBoundedLogCount } from \"../../../lib/utils/log-pagination\";\nimport { parseSearchQuery } from \"../../../lib/utils/search-query\";\nimport { isSupportedFramework } from \"@vm0/core/frameworks\";\n\nconst SEVEN_DAYS_MS = 7 * 24 * 60 * 60 * 1000;\n\nexport interface LogsSearchCliOptions {\n afterContext?: string;\n beforeContext?: string;\n context?: string;\n agentId?: string;\n run?: string;\n since?: string;\n limit?: string;\n}\n\ninterface LogsSearchCommandOptions extends Omit<\n LogsSearchCliOptions,\n \"agentId\"\n> {\n agent?: string;\n}\n\nfunction supportedSearchFramework(\n framework: string | null | undefined,\n): string | undefined {\n const normalized = framework ?? undefined;\n return isSupportedFramework(normalized) ? normalized : undefined;\n}\n\nfunction renderSearchEvent(\n event: RunEvent,\n framework: string | null | undefined,\n renderer: EventRenderer,\n normalizer: EventStreamNormalizer,\n): void {\n const parsedEvents = normalizer.process(\n event.eventData,\n supportedSearchFramework(framework),\n new Date(event.createdAt),\n );\n for (const parsed of parsedEvents) {\n renderer.render(parsed);\n }\n}\n\nfunction flushSearchRenderer(\n renderer: EventRenderer,\n normalizer: EventStreamNormalizer,\n): void {\n for (const parsed of normalizer.flush()) {\n renderer.render(parsed);\n }\n renderer.flush();\n}\n\nfunction formatRunHeader(\n runId: string,\n agentName: string,\n timestamp: string,\n): string {\n const time = formatIsoTimestamp(timestamp);\n return `── Run ${runId} (${agentName}, ${time}) ──────────`;\n}\n\nfunction parseContextOptions(options: LogsSearchCliOptions): {\n before: number;\n after: number;\n} {\n const contextN =\n options.context !== undefined\n ? parseBoundedLogCount(options.context, \"--context\", 0, 10)\n : 0;\n const before =\n options.beforeContext !== undefined\n ? parseBoundedLogCount(options.beforeContext, \"--before-context\", 0, 10)\n : contextN;\n const after =\n options.afterContext !== undefined\n ? parseBoundedLogCount(options.afterContext, \"--after-context\", 0, 10)\n : contextN;\n\n return { before, after };\n}\n\nfunction parseLimit(value: string | undefined): number | undefined {\n if (value === undefined) return undefined;\n return parseBoundedLogCount(value, \"--limit\", 1, 50);\n}\n\nfunction renderResults(response: LogsSearchResponse): void {\n const grouped = new Map<\n string,\n { agentName: string; results: LogsSearchResponse[\"results\"] }\n >();\n for (const result of response.results) {\n const existing = grouped.get(result.runId);\n if (existing) {\n existing.results.push(result);\n } else {\n grouped.set(result.runId, {\n agentName: result.agentName,\n results: [result],\n });\n }\n }\n\n let isFirstGroup = true;\n for (const [runId, group] of grouped) {\n if (!isFirstGroup) {\n console.log();\n }\n isFirstGroup = false;\n\n const firstTimestamp = group.results[0]!.matchedEvent.createdAt;\n console.log(\n chalk.bold(formatRunHeader(runId, group.agentName, firstTimestamp)),\n );\n\n for (const result of group.results) {\n const renderer = new EventRenderer({\n showTimestamp: true,\n verbose: false,\n });\n const normalizer = new EventStreamNormalizer();\n\n for (const event of result.contextBefore) {\n renderSearchEvent(event, result.framework, renderer, normalizer);\n }\n renderSearchEvent(\n result.matchedEvent,\n result.framework,\n renderer,\n normalizer,\n );\n for (const event of result.contextAfter) {\n renderSearchEvent(event, result.framework, renderer, normalizer);\n }\n flushSearchRenderer(renderer, normalizer);\n }\n }\n\n if (response.hasMore) {\n console.log();\n console.log(\n chalk.dim(\n ` Showing first ${response.results.length} matches. Use --limit to see more.`,\n ),\n );\n }\n}\n\nexport async function runLogsSearch(\n keyword: string,\n options: LogsSearchCliOptions,\n): Promise<void> {\n const searchKeyword = parseSearchQuery(keyword, \"Keyword\");\n const { before, after } = parseContextOptions(options);\n\n if (options.agentId !== undefined && !isUUID(options.agentId)) {\n console.error(\n chalk.red(`✗ Invalid agent ID \"${options.agentId}\" — expected a UUID`),\n );\n console.error(chalk.dim(\" Run: zero logs list to find agent IDs\"));\n process.exit(1);\n }\n\n if (options.run !== undefined && !isUUID(options.run)) {\n console.error(\n chalk.red(`✗ Invalid run ID \"${options.run}\" — expected a UUID`),\n );\n console.error(chalk.dim(\" Run: zero logs list to find run IDs\"));\n process.exit(1);\n }\n\n const since =\n options.since !== undefined\n ? parseTime(options.since)\n : Date.now() - SEVEN_DAYS_MS;\n const limit = parseLimit(options.limit);\n\n const response = await searchZeroLogs({\n keyword: searchKeyword,\n agentId: options.agentId,\n runId: options.run,\n since,\n limit,\n before,\n after,\n });\n\n if (response.results.length === 0) {\n console.log(chalk.dim(\"No matches found\"));\n console.log(\n chalk.dim(\n \" Try a broader search with --since 30d or a different keyword\",\n ),\n );\n return;\n }\n\n renderResults(response);\n}\n\nexport const searchCommand = new Command()\n .name(\"search\")\n .description(\"Search agent events across runs\")\n .argument(\"<keyword>\", \"Search keyword\")\n .option(\"-A, --after-context <n>\", \"Show n events after each match\")\n .option(\"-B, --before-context <n>\", \"Show n events before each match\")\n .option(\"-C, --context <n>\", \"Show n events before and after each match\")\n .option(\"--agent <id>\", \"Filter by Zero agent ID\")\n .option(\"--run <id>\", \"Filter by specific run ID\")\n .option(\"--since <time>\", \"Search logs since (default: 7d)\")\n .option(\"--limit <n>\", \"Maximum number of matches (default: 20)\")\n .addHelpText(\n \"after\",\n `\nExamples:\n zero logs search \"error\"\n zero logs search \"timeout\" --agent 123e4567-e89b-12d3-a456-426614174000 -C 2\n zero logs search \"failed\" --since 30d --limit 50`,\n )\n .action(\n withErrorHandler(\n async (keyword: string, options: LogsSearchCommandOptions) => {\n const { agent, ...searchOptions } = options;\n await runLogsSearch(keyword, { ...searchOptions, agentId: agent });\n },\n ),\n );\n"],"mappings":"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","names":[]}
|