@pantheon.ai/agents 0.0.15 → 0.0.17
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/index.js +718 -227
- package/package.json +3 -1
package/dist/index.js
CHANGED
|
@@ -16,6 +16,7 @@ import { Http2ServerRequest } from "http2";
|
|
|
16
16
|
import { Readable } from "stream";
|
|
17
17
|
import blessed from "reblessed";
|
|
18
18
|
import { inspect } from "node:util";
|
|
19
|
+
import { parse } from "shell-quote";
|
|
19
20
|
|
|
20
21
|
//#region ../../node_modules/dotenv/package.json
|
|
21
22
|
var require_package = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
@@ -394,7 +395,7 @@ var require_cli_options = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
394
395
|
|
|
395
396
|
//#endregion
|
|
396
397
|
//#region package.json
|
|
397
|
-
var version$1 = "0.0.
|
|
398
|
+
var version$1 = "0.0.17";
|
|
398
399
|
|
|
399
400
|
//#endregion
|
|
400
401
|
//#region src/schemas/task-list.ts
|
|
@@ -2344,7 +2345,7 @@ const _parse$1 = (_Err) => (schema, value, _ctx, _params) => {
|
|
|
2344
2345
|
}
|
|
2345
2346
|
return result.value;
|
|
2346
2347
|
};
|
|
2347
|
-
const parse$
|
|
2348
|
+
const parse$2 = /* @__PURE__ */ _parse$1($ZodRealError);
|
|
2348
2349
|
const _parseAsync = (_Err) => async (schema, value, _ctx, params) => {
|
|
2349
2350
|
const ctx = _ctx ? Object.assign(_ctx, { async: true }) : { async: true };
|
|
2350
2351
|
let result = schema._zod.run({
|
|
@@ -5521,7 +5522,7 @@ const ZodRealError = $constructor("ZodError", initializer, { Parent: Error });
|
|
|
5521
5522
|
|
|
5522
5523
|
//#endregion
|
|
5523
5524
|
//#region ../../node_modules/zod/v4/classic/parse.js
|
|
5524
|
-
const parse = /* @__PURE__ */ _parse$1(ZodRealError);
|
|
5525
|
+
const parse$1 = /* @__PURE__ */ _parse$1(ZodRealError);
|
|
5525
5526
|
const parseAsync = /* @__PURE__ */ _parseAsync(ZodRealError);
|
|
5526
5527
|
const safeParse$1 = /* @__PURE__ */ _safeParse(ZodRealError);
|
|
5527
5528
|
const safeParseAsync$1 = /* @__PURE__ */ _safeParseAsync(ZodRealError);
|
|
@@ -5560,7 +5561,7 @@ const ZodType$1 = /* @__PURE__ */ $constructor("ZodType", (inst, def) => {
|
|
|
5560
5561
|
reg.add(inst, meta);
|
|
5561
5562
|
return inst;
|
|
5562
5563
|
});
|
|
5563
|
-
inst.parse = (data, params) => parse(inst, data, params, { callee: inst.parse });
|
|
5564
|
+
inst.parse = (data, params) => parse$1(inst, data, params, { callee: inst.parse });
|
|
5564
5565
|
inst.safeParse = (data, params) => safeParse$1(inst, data, params);
|
|
5565
5566
|
inst.parseAsync = async (data, params) => parseAsync(inst, data, params, { callee: inst.parseAsync });
|
|
5566
5567
|
inst.safeParseAsync = async (data, params) => safeParseAsync$1(inst, data, params);
|
|
@@ -17342,32 +17343,40 @@ async function consumeOpaqueSseStream(options) {
|
|
|
17342
17343
|
};
|
|
17343
17344
|
}
|
|
17344
17345
|
var WatchStepAggregator = class {
|
|
17345
|
-
maxLeadingTextChars;
|
|
17346
|
-
maxLeadingReasoningChars;
|
|
17347
17346
|
maxLogLines;
|
|
17348
17347
|
maxWarnings;
|
|
17349
|
-
leadingText = "";
|
|
17350
|
-
leadingReasoning = "";
|
|
17351
17348
|
toolActions = /* @__PURE__ */ new Map();
|
|
17349
|
+
timeline = [];
|
|
17352
17350
|
logLines = [];
|
|
17351
|
+
todoItems = [];
|
|
17353
17352
|
warnings = [];
|
|
17353
|
+
warningItems = [];
|
|
17354
17354
|
unknownEventCount = 0;
|
|
17355
17355
|
orderCounter = 0;
|
|
17356
17356
|
constructor(options = {}) {
|
|
17357
|
-
this.maxLeadingTextChars = options.maxLeadingTextChars ?? 800;
|
|
17358
|
-
this.maxLeadingReasoningChars = options.maxLeadingReasoningChars ?? 800;
|
|
17359
17357
|
this.maxLogLines = options.maxLogLines ?? 200;
|
|
17360
17358
|
this.maxWarnings = options.maxWarnings ?? 50;
|
|
17361
17359
|
}
|
|
17362
17360
|
pushLog(line) {
|
|
17363
17361
|
if (!line) return;
|
|
17364
17362
|
this.logLines.push(line);
|
|
17365
|
-
if (this.logLines.length > this.maxLogLines) this.logLines.splice(0, this.logLines.length - this.maxLogLines);
|
|
17363
|
+
if (Number.isFinite(this.maxLogLines) && this.maxLogLines > 0 && this.logLines.length > this.maxLogLines) this.logLines.splice(0, this.logLines.length - this.maxLogLines);
|
|
17366
17364
|
}
|
|
17367
17365
|
pushWarning(message) {
|
|
17368
17366
|
if (!message) return;
|
|
17367
|
+
const order = this.orderCounter++;
|
|
17369
17368
|
this.warnings.push(message);
|
|
17369
|
+
this.warningItems.push({
|
|
17370
|
+
message,
|
|
17371
|
+
order
|
|
17372
|
+
});
|
|
17373
|
+
this.timeline.push({
|
|
17374
|
+
kind: "warning",
|
|
17375
|
+
message,
|
|
17376
|
+
order
|
|
17377
|
+
});
|
|
17370
17378
|
if (this.warnings.length > this.maxWarnings) this.warnings.splice(0, this.warnings.length - this.maxWarnings);
|
|
17379
|
+
if (this.warningItems.length > this.maxWarnings) this.warningItems.splice(0, this.warningItems.length - this.maxWarnings);
|
|
17371
17380
|
}
|
|
17372
17381
|
pushCommandExecutionOutput(output) {
|
|
17373
17382
|
const out = output;
|
|
@@ -17377,6 +17386,31 @@ var WatchStepAggregator = class {
|
|
|
17377
17386
|
if (trimmed) trimmed.split("\n").forEach((line) => this.pushLog(line));
|
|
17378
17387
|
if (exitCode != null && exitCode !== 0) this.pushLog(`exit_code=${exitCode}`);
|
|
17379
17388
|
}
|
|
17389
|
+
setTodoItems(items) {
|
|
17390
|
+
if (!Array.isArray(items)) return;
|
|
17391
|
+
const normalized = [];
|
|
17392
|
+
for (const item of items) {
|
|
17393
|
+
if (typeof item !== "object" || item === null) continue;
|
|
17394
|
+
const text = typeof item.text === "string" ? item.text : "";
|
|
17395
|
+
const completed = Boolean(item.completed);
|
|
17396
|
+
if (!text) continue;
|
|
17397
|
+
normalized.push({
|
|
17398
|
+
text,
|
|
17399
|
+
completed
|
|
17400
|
+
});
|
|
17401
|
+
}
|
|
17402
|
+
this.todoItems = normalized;
|
|
17403
|
+
}
|
|
17404
|
+
pushTimelineText(kind, delta) {
|
|
17405
|
+
if (!delta) return this.orderCounter;
|
|
17406
|
+
const order = this.orderCounter++;
|
|
17407
|
+
this.timeline.push({
|
|
17408
|
+
kind,
|
|
17409
|
+
order,
|
|
17410
|
+
text: delta
|
|
17411
|
+
});
|
|
17412
|
+
return order;
|
|
17413
|
+
}
|
|
17380
17414
|
getOrCreateToolAction(toolCallId) {
|
|
17381
17415
|
const existing = this.toolActions.get(toolCallId);
|
|
17382
17416
|
if (existing) return existing;
|
|
@@ -17386,6 +17420,11 @@ var WatchStepAggregator = class {
|
|
|
17386
17420
|
_order: this.orderCounter++
|
|
17387
17421
|
};
|
|
17388
17422
|
this.toolActions.set(toolCallId, created);
|
|
17423
|
+
this.timeline.push({
|
|
17424
|
+
kind: "tool",
|
|
17425
|
+
order: created._order,
|
|
17426
|
+
toolCallId
|
|
17427
|
+
});
|
|
17389
17428
|
return created;
|
|
17390
17429
|
}
|
|
17391
17430
|
pushUiChunk(chunk) {
|
|
@@ -17396,19 +17435,13 @@ var WatchStepAggregator = class {
|
|
|
17396
17435
|
case "text-delta": {
|
|
17397
17436
|
const delta = typeof chunk.delta === "string" ? chunk.delta : "";
|
|
17398
17437
|
if (!delta) return;
|
|
17399
|
-
|
|
17400
|
-
const remaining = this.maxLeadingTextChars - this.leadingText.length;
|
|
17401
|
-
this.leadingText += delta.slice(0, remaining);
|
|
17402
|
-
}
|
|
17438
|
+
this.pushTimelineText("message", delta);
|
|
17403
17439
|
return;
|
|
17404
17440
|
}
|
|
17405
17441
|
case "reasoning-delta": {
|
|
17406
17442
|
const delta = typeof chunk.delta === "string" ? chunk.delta : "";
|
|
17407
17443
|
if (!delta) return;
|
|
17408
|
-
|
|
17409
|
-
const remaining = this.maxLeadingReasoningChars - this.leadingReasoning.length;
|
|
17410
|
-
this.leadingReasoning += delta.slice(0, remaining);
|
|
17411
|
-
}
|
|
17444
|
+
this.pushTimelineText("reasoning", delta);
|
|
17412
17445
|
return;
|
|
17413
17446
|
}
|
|
17414
17447
|
case "tool-input-start": {
|
|
@@ -17476,6 +17509,11 @@ var WatchStepAggregator = class {
|
|
|
17476
17509
|
this.pushLog(`! unknown: ${reason}`);
|
|
17477
17510
|
return;
|
|
17478
17511
|
}
|
|
17512
|
+
case "data-agent-event": {
|
|
17513
|
+
const data = chunk.data;
|
|
17514
|
+
if (data?.kind === "codex.todo_list") this.setTodoItems(data.items);
|
|
17515
|
+
return;
|
|
17516
|
+
}
|
|
17479
17517
|
default: return;
|
|
17480
17518
|
}
|
|
17481
17519
|
}
|
|
@@ -17483,13 +17521,16 @@ var WatchStepAggregator = class {
|
|
|
17483
17521
|
chunks.forEach((chunk) => this.pushUiChunk(chunk));
|
|
17484
17522
|
}
|
|
17485
17523
|
snapshot() {
|
|
17486
|
-
const actions = Array.from(this.toolActions.values()).sort((a, b) => a._order - b._order).map(({ _order: _unused, ...rest }) => rest);
|
|
17487
17524
|
return {
|
|
17488
|
-
|
|
17489
|
-
|
|
17490
|
-
|
|
17525
|
+
toolActions: Array.from(this.toolActions.values()).sort((a, b) => a._order - b._order).map(({ _order, ...rest }) => ({
|
|
17526
|
+
...rest,
|
|
17527
|
+
order: _order
|
|
17528
|
+
})),
|
|
17529
|
+
timeline: this.timeline.map((item) => ({ ...item })),
|
|
17491
17530
|
logLines: [...this.logLines],
|
|
17531
|
+
todoItems: this.todoItems.map((item) => ({ ...item })),
|
|
17492
17532
|
warnings: [...this.warnings],
|
|
17533
|
+
warningItems: this.warningItems.map((item) => ({ ...item })),
|
|
17493
17534
|
unknownEventCount: this.unknownEventCount
|
|
17494
17535
|
};
|
|
17495
17536
|
}
|
|
@@ -18099,11 +18140,11 @@ function createLlmExplainCommand(version) {
|
|
|
18099
18140
|
projectId: task.project_id,
|
|
18100
18141
|
branchId: task.branch_id
|
|
18101
18142
|
});
|
|
18102
|
-
if (!branch.branch
|
|
18143
|
+
if (!branch.branch?.latest_snap?.event_stream_id) {
|
|
18103
18144
|
console.error(`Branch ${task.branch_id} has no latest snap.`);
|
|
18104
18145
|
process$1.exit(1);
|
|
18105
18146
|
}
|
|
18106
|
-
const stream = await getRawStream(branch.branch
|
|
18147
|
+
const stream = await getRawStream(branch.branch?.latest_snap.event_stream_id);
|
|
18107
18148
|
const text = await llmExplain(task.task, stream, {
|
|
18108
18149
|
timeout: 3e3,
|
|
18109
18150
|
characters
|
|
@@ -21138,7 +21179,7 @@ const ZodMiniType = /* @__PURE__ */ $constructor("ZodMiniType", (inst, def) => {
|
|
|
21138
21179
|
$ZodType.init(inst, def);
|
|
21139
21180
|
inst.def = def;
|
|
21140
21181
|
inst.type = def.type;
|
|
21141
|
-
inst.parse = (data, params) => parse$
|
|
21182
|
+
inst.parse = (data, params) => parse$2(inst, data, params, { callee: inst.parse });
|
|
21142
21183
|
inst.safeParse = (data, params) => safeParse$2(inst, data, params);
|
|
21143
21184
|
inst.parseAsync = async (data, params) => parseAsync$1(inst, data, params, { callee: inst.parseAsync });
|
|
21144
21185
|
inst.safeParseAsync = async (data, params) => safeParseAsync$2(inst, data, params);
|
|
@@ -31886,6 +31927,52 @@ function createClaudeCodeNormalizer(options = {}) {
|
|
|
31886
31927
|
});
|
|
31887
31928
|
return out;
|
|
31888
31929
|
}
|
|
31930
|
+
function formatToolResultOutput(content, toolUseResult) {
|
|
31931
|
+
if (toolUseResult == null) return content ?? null;
|
|
31932
|
+
if (content == null) return toolUseResult;
|
|
31933
|
+
if (typeof content === "string" && content.length === 0) return toolUseResult;
|
|
31934
|
+
return {
|
|
31935
|
+
content,
|
|
31936
|
+
tool_use_result: toolUseResult
|
|
31937
|
+
};
|
|
31938
|
+
}
|
|
31939
|
+
function getToolResultErrorText(content, toolUseResult) {
|
|
31940
|
+
if (typeof content === "string" && content.trim().length > 0) return content;
|
|
31941
|
+
if (isRecord(toolUseResult) && typeof toolUseResult.stderr === "string") {
|
|
31942
|
+
const stderr = toolUseResult.stderr.trim();
|
|
31943
|
+
if (stderr.length > 0) return stderr;
|
|
31944
|
+
}
|
|
31945
|
+
try {
|
|
31946
|
+
if (toolUseResult != null) return JSON.stringify(toolUseResult);
|
|
31947
|
+
} catch {}
|
|
31948
|
+
return "Tool execution failed";
|
|
31949
|
+
}
|
|
31950
|
+
function handleUserMessage(message, toolUseResult) {
|
|
31951
|
+
const blocks = Array.isArray(message.content) ? message.content : [];
|
|
31952
|
+
const out = [];
|
|
31953
|
+
blocks.forEach((block, index) => {
|
|
31954
|
+
if (!isRecord(block) || block.type !== "tool_result") return;
|
|
31955
|
+
const toolCallId = typeof block.tool_use_id === "string" ? block.tool_use_id : `claude-tool-result-${index}`;
|
|
31956
|
+
const content = block.content;
|
|
31957
|
+
const interrupted = isRecord(toolUseResult) && toolUseResult.interrupted === true;
|
|
31958
|
+
if (block.is_error === true || interrupted) {
|
|
31959
|
+
out.push({
|
|
31960
|
+
type: "tool-output-error",
|
|
31961
|
+
toolCallId,
|
|
31962
|
+
errorText: getToolResultErrorText(content, toolUseResult),
|
|
31963
|
+
dynamic: true
|
|
31964
|
+
});
|
|
31965
|
+
return;
|
|
31966
|
+
}
|
|
31967
|
+
out.push({
|
|
31968
|
+
type: "tool-output-available",
|
|
31969
|
+
toolCallId,
|
|
31970
|
+
output: formatToolResultOutput(content, toolUseResult),
|
|
31971
|
+
dynamic: true
|
|
31972
|
+
});
|
|
31973
|
+
});
|
|
31974
|
+
return out;
|
|
31975
|
+
}
|
|
31889
31976
|
function push(chunk) {
|
|
31890
31977
|
const parsed = topLevelSchema.safeParse(chunk);
|
|
31891
31978
|
if (!parsed.success) return {
|
|
@@ -31917,7 +32004,6 @@ function createClaudeCodeNormalizer(options = {}) {
|
|
|
31917
32004
|
};
|
|
31918
32005
|
}
|
|
31919
32006
|
case "stream_event": {
|
|
31920
|
-
sawStreamEvents = true;
|
|
31921
32007
|
const event = streamEventSchema.safeParse(msg.event);
|
|
31922
32008
|
if (!event.success) return {
|
|
31923
32009
|
recognized: false,
|
|
@@ -31939,6 +32025,17 @@ function createClaudeCodeNormalizer(options = {}) {
|
|
|
31939
32025
|
chunks: handleAssistantMessage(message)
|
|
31940
32026
|
};
|
|
31941
32027
|
}
|
|
32028
|
+
case "user": {
|
|
32029
|
+
const message = msg.message;
|
|
32030
|
+
if (!isRecord(message)) return {
|
|
32031
|
+
recognized: false,
|
|
32032
|
+
chunks: []
|
|
32033
|
+
};
|
|
32034
|
+
return {
|
|
32035
|
+
recognized: true,
|
|
32036
|
+
chunks: handleUserMessage(message, msg.tool_use_result)
|
|
32037
|
+
};
|
|
32038
|
+
}
|
|
31942
32039
|
case "result": return {
|
|
31943
32040
|
recognized: true,
|
|
31944
32041
|
chunks: maybeMeta({
|
|
@@ -32085,36 +32182,150 @@ function tryExtractBashCommand(command) {
|
|
|
32085
32182
|
}
|
|
32086
32183
|
return rest.trim();
|
|
32087
32184
|
}
|
|
32088
|
-
function
|
|
32185
|
+
function normalizeCommand(command) {
|
|
32089
32186
|
const trimmed = command.trim();
|
|
32090
32187
|
return tryExtractBashCommand(trimmed)?.trim() || trimmed;
|
|
32091
32188
|
}
|
|
32092
|
-
function
|
|
32093
|
-
|
|
32094
|
-
|
|
32095
|
-
|
|
32096
|
-
const
|
|
32097
|
-
|
|
32098
|
-
return
|
|
32189
|
+
function splitCommandLines(command) {
|
|
32190
|
+
return command.replaceAll("\r\n", "\n").split("\n").map((line) => line.trim()).filter(Boolean);
|
|
32191
|
+
}
|
|
32192
|
+
function stripCommentPrefix(line) {
|
|
32193
|
+
const trimmed = line.trim();
|
|
32194
|
+
if (trimmed.startsWith("//")) return trimmed.slice(2).trimStart();
|
|
32195
|
+
return trimmed;
|
|
32196
|
+
}
|
|
32197
|
+
function commandBasename(value) {
|
|
32198
|
+
const lastSlash = value.lastIndexOf("/");
|
|
32199
|
+
return lastSlash === -1 ? value : value.slice(lastSlash + 1);
|
|
32200
|
+
}
|
|
32201
|
+
function parseShellEntries(line) {
|
|
32202
|
+
try {
|
|
32203
|
+
return parse(line);
|
|
32204
|
+
} catch {
|
|
32205
|
+
return;
|
|
32206
|
+
}
|
|
32207
|
+
}
|
|
32208
|
+
function takeMainTokens(entries) {
|
|
32209
|
+
const stopSet = new Set([
|
|
32210
|
+
"|",
|
|
32211
|
+
"||",
|
|
32212
|
+
"&&",
|
|
32213
|
+
";",
|
|
32214
|
+
"|&",
|
|
32215
|
+
";;",
|
|
32216
|
+
"&",
|
|
32217
|
+
"(",
|
|
32218
|
+
")",
|
|
32219
|
+
"<",
|
|
32220
|
+
">",
|
|
32221
|
+
">>",
|
|
32222
|
+
">&",
|
|
32223
|
+
"<("
|
|
32224
|
+
]);
|
|
32225
|
+
const out = [];
|
|
32226
|
+
for (const entry of entries) {
|
|
32227
|
+
if (typeof entry === "string") {
|
|
32228
|
+
out.push(entry);
|
|
32229
|
+
continue;
|
|
32230
|
+
}
|
|
32231
|
+
if ("op" in entry) {
|
|
32232
|
+
if (stopSet.has(entry.op)) break;
|
|
32233
|
+
continue;
|
|
32234
|
+
}
|
|
32235
|
+
if ("comment" in entry) break;
|
|
32236
|
+
}
|
|
32237
|
+
return out;
|
|
32238
|
+
}
|
|
32239
|
+
function pickLastNonOptionArg(tokens) {
|
|
32240
|
+
const values = tokens.filter((token) => !token.startsWith("-"));
|
|
32241
|
+
return values.length > 0 ? values[values.length - 1] : void 0;
|
|
32242
|
+
}
|
|
32243
|
+
function parseExploredItem(line) {
|
|
32244
|
+
const entries = parseShellEntries(normalizeCommand(line));
|
|
32245
|
+
if (!entries) return void 0;
|
|
32246
|
+
const tokens = takeMainTokens(entries);
|
|
32247
|
+
if (tokens.length === 0) return void 0;
|
|
32248
|
+
const command = commandBasename(tokens[0] ?? "");
|
|
32249
|
+
if (command === "rg") {
|
|
32250
|
+
const args = tokens.slice(1);
|
|
32251
|
+
if (args.includes("--files")) return {
|
|
32252
|
+
kind: "list",
|
|
32253
|
+
target: pickLastNonOptionArg(args)
|
|
32254
|
+
};
|
|
32255
|
+
const firstValueIndex = args.findIndex((token) => !token.startsWith("-"));
|
|
32256
|
+
if (firstValueIndex === -1) return void 0;
|
|
32257
|
+
const terms = args[firstValueIndex];
|
|
32258
|
+
const file = args[firstValueIndex + 1];
|
|
32259
|
+
if (!terms || !file) return void 0;
|
|
32260
|
+
return {
|
|
32261
|
+
kind: "search",
|
|
32262
|
+
terms,
|
|
32263
|
+
file
|
|
32264
|
+
};
|
|
32265
|
+
}
|
|
32266
|
+
if (command === "ls") return {
|
|
32267
|
+
kind: "list",
|
|
32268
|
+
target: pickLastNonOptionArg(tokens.slice(1))
|
|
32269
|
+
};
|
|
32270
|
+
if (command === "sed" || command === "nl" || command === "cat") {
|
|
32271
|
+
if (tokens.length < 2) return void 0;
|
|
32272
|
+
const file = tokens[tokens.length - 1];
|
|
32273
|
+
if (!file || file.startsWith("-")) return void 0;
|
|
32274
|
+
return {
|
|
32275
|
+
kind: "read",
|
|
32276
|
+
file
|
|
32277
|
+
};
|
|
32278
|
+
}
|
|
32279
|
+
}
|
|
32280
|
+
function parseExploredItemsFromCommand(command) {
|
|
32281
|
+
const rawLines = splitCommandLines(normalizeCommand(command));
|
|
32282
|
+
const items = [];
|
|
32283
|
+
for (const rawLine of rawLines) {
|
|
32284
|
+
const line = stripCommentPrefix(rawLine);
|
|
32285
|
+
if (!line) continue;
|
|
32286
|
+
const item = parseExploredItem(normalizeCommand(line));
|
|
32287
|
+
if (!item) return void 0;
|
|
32288
|
+
items.push(item);
|
|
32289
|
+
}
|
|
32290
|
+
if (items.length === 0) return void 0;
|
|
32291
|
+
return items;
|
|
32292
|
+
}
|
|
32293
|
+
function formatExploredItemsLines(items) {
|
|
32294
|
+
const lines = ["Explored"];
|
|
32295
|
+
for (const item of items) {
|
|
32296
|
+
if (item.kind === "read") {
|
|
32297
|
+
lines.push(`Read ${item.file}`);
|
|
32298
|
+
continue;
|
|
32299
|
+
}
|
|
32300
|
+
if (item.kind === "list") {
|
|
32301
|
+
lines.push(item.target ? `List ${item.target}` : "List");
|
|
32302
|
+
continue;
|
|
32303
|
+
}
|
|
32304
|
+
lines.push(`Search ${item.terms} in ${item.file}`);
|
|
32305
|
+
}
|
|
32306
|
+
return lines;
|
|
32307
|
+
}
|
|
32308
|
+
function getExploredCommandLines(command) {
|
|
32309
|
+
const explored = parseExploredItemsFromCommand(command);
|
|
32310
|
+
if (!explored) return void 0;
|
|
32311
|
+
return formatExploredItemsLines(explored);
|
|
32312
|
+
}
|
|
32313
|
+
function isExploredCommandExecution(command) {
|
|
32314
|
+
return parseExploredItemsFromCommand(command) != null;
|
|
32315
|
+
}
|
|
32316
|
+
function formatCommandExecutionDisplayCommand(command) {
|
|
32317
|
+
const exploredLines = getExploredCommandLines(command);
|
|
32318
|
+
if (exploredLines) return exploredLines.join("\n");
|
|
32319
|
+
return normalizeCommand(command);
|
|
32099
32320
|
}
|
|
32100
32321
|
|
|
32101
32322
|
//#endregion
|
|
32102
32323
|
//#region src/cli/commands/watch.ts
|
|
32103
32324
|
const PANTHEON_BASE_URL = "https://pantheon-ai.tidb.ai";
|
|
32104
|
-
|
|
32105
|
-
|
|
32106
|
-
|
|
32107
|
-
|
|
32108
|
-
function parseScreenGrid(value) {
|
|
32109
|
-
const match = value.trim().toLowerCase().match(/^(\d+)x(\d+)$/);
|
|
32110
|
-
if (!match) throw new InvalidArgumentError("screen must be <cols>x<rows>, e.g. 3x1 or 5x4");
|
|
32111
|
-
const cols = Number(match[1]);
|
|
32112
|
-
const rows = Number(match[2]);
|
|
32113
|
-
if (!Number.isInteger(cols) || !Number.isInteger(rows) || cols <= 0 || rows <= 0) throw new InvalidArgumentError("screen requires positive integer cols/rows, e.g. 3x1");
|
|
32114
|
-
return {
|
|
32115
|
-
cols,
|
|
32116
|
-
rows
|
|
32117
|
-
};
|
|
32325
|
+
function parseListWidth(value) {
|
|
32326
|
+
const width = Number(value);
|
|
32327
|
+
if (!Number.isInteger(width) || width <= 0) throw new InvalidArgumentError("list-width requires a positive integer, e.g. 32");
|
|
32328
|
+
return width;
|
|
32118
32329
|
}
|
|
32119
32330
|
function ensureEnvOrExit(keys) {
|
|
32120
32331
|
const missing = keys.filter((key) => !process.env[key]);
|
|
@@ -32122,33 +32333,6 @@ function ensureEnvOrExit(keys) {
|
|
|
32122
32333
|
for (const key of missing) console.error(`${key} environment variable is not set.`);
|
|
32123
32334
|
process.exit(1);
|
|
32124
32335
|
}
|
|
32125
|
-
function formatDurationMs(ms) {
|
|
32126
|
-
const seconds = Math.max(0, Math.floor(ms / 1e3));
|
|
32127
|
-
const minutes = Math.floor(seconds / 60);
|
|
32128
|
-
const hours = Math.floor(minutes / 60);
|
|
32129
|
-
if (hours > 0) return `${hours}h ${minutes % 60}m ${seconds % 60}s`;
|
|
32130
|
-
if (minutes > 0) return `${minutes}m ${seconds % 60}s`;
|
|
32131
|
-
return `${seconds}s`;
|
|
32132
|
-
}
|
|
32133
|
-
function getTaskStartTime(task) {
|
|
32134
|
-
switch (task.status) {
|
|
32135
|
-
case "pending": return task.queued_at;
|
|
32136
|
-
case "running": return task.started_at;
|
|
32137
|
-
case "completed":
|
|
32138
|
-
case "failed": return task.started_at ?? task.queued_at;
|
|
32139
|
-
case "cancelled": return task.queued_at;
|
|
32140
|
-
}
|
|
32141
|
-
}
|
|
32142
|
-
function getTaskElapsedMs(task, now = /* @__PURE__ */ new Date()) {
|
|
32143
|
-
const start = getTaskStartTime(task);
|
|
32144
|
-
if (!start) return 0;
|
|
32145
|
-
switch (task.status) {
|
|
32146
|
-
case "completed": return task.ended_at.getTime() - start.getTime();
|
|
32147
|
-
case "failed": return (task.ended_at ?? now).getTime() - start.getTime();
|
|
32148
|
-
case "cancelled": return task.cancelled_at.getTime() - start.getTime();
|
|
32149
|
-
default: return now.getTime() - start.getTime();
|
|
32150
|
-
}
|
|
32151
|
-
}
|
|
32152
32336
|
function toStreamSourceFromExecuteAgent(executeAgent) {
|
|
32153
32337
|
if (!executeAgent) return void 0;
|
|
32154
32338
|
const normalized = executeAgent.toLowerCase();
|
|
@@ -32296,42 +32480,36 @@ function yellow(text, enabled) {
|
|
|
32296
32480
|
function cyan(text, enabled) {
|
|
32297
32481
|
return sgrWrap(text, ANSI.cyan, enabled);
|
|
32298
32482
|
}
|
|
32483
|
+
function dimGray(text, enabled) {
|
|
32484
|
+
return sgrWrap(text, `${ANSI.dim}${ANSI.gray}`, enabled);
|
|
32485
|
+
}
|
|
32299
32486
|
function kv(label, value, style) {
|
|
32300
32487
|
return `${dim(`${label}:`, style)} ${value}`;
|
|
32301
32488
|
}
|
|
32302
|
-
function
|
|
32303
|
-
|
|
32304
|
-
|
|
32305
|
-
|
|
32306
|
-
case "failed": return red(status, style);
|
|
32307
|
-
case "pending": return cyan(status, style);
|
|
32308
|
-
case "cancelled": return gray(status, style);
|
|
32309
|
-
}
|
|
32489
|
+
function getCommandExecutionDisplayCommand(tool) {
|
|
32490
|
+
const raw = getCommandExecutionRawCommand(tool);
|
|
32491
|
+
if (!raw) return void 0;
|
|
32492
|
+
return formatCommandExecutionDisplayCommand(raw) || void 0;
|
|
32310
32493
|
}
|
|
32311
|
-
function
|
|
32312
|
-
|
|
32313
|
-
|
|
32314
|
-
|
|
32315
|
-
|
|
32316
|
-
case "running":
|
|
32317
|
-
case "pending": return yellow(status, style);
|
|
32318
|
-
case "manifesting":
|
|
32319
|
-
case "ready_for_manifest": return cyan(status, style);
|
|
32320
|
-
default: return gray(status, style);
|
|
32321
|
-
}
|
|
32494
|
+
function colorizeCommandProgram(display, style) {
|
|
32495
|
+
const match = display.match(/^(\s*)(\S+)([\s\S]*)$/);
|
|
32496
|
+
if (!match) return display;
|
|
32497
|
+
const [, leading, program, rest] = match;
|
|
32498
|
+
return `${leading}${cyan(program ?? "", style)}${rest ?? ""}`;
|
|
32322
32499
|
}
|
|
32323
|
-
function
|
|
32500
|
+
function getCommandExecutionRawCommand(tool) {
|
|
32324
32501
|
const title = typeof tool.title === "string" ? tool.title : "";
|
|
32325
32502
|
const inputCommand = typeof tool.input?.command === "string" ? tool.input.command : "";
|
|
32326
|
-
|
|
32327
|
-
if (!raw) return void 0;
|
|
32328
|
-
return formatCommandExecutionDisplayCommand(raw) || void 0;
|
|
32503
|
+
return title || inputCommand || void 0;
|
|
32329
32504
|
}
|
|
32330
32505
|
function formatToolLabel(tool, style) {
|
|
32331
32506
|
const name = tool.toolName ?? "<tool>";
|
|
32332
32507
|
if (name === "command_execution") {
|
|
32508
|
+
const rawCommand = getCommandExecutionRawCommand(tool);
|
|
32509
|
+
const exploredLines = rawCommand ? getExploredCommandLines(rawCommand) : void 0;
|
|
32510
|
+
if (exploredLines && exploredLines.length > 1) return cyan(exploredLines[0] ?? "Explored", style);
|
|
32333
32511
|
const display = getCommandExecutionDisplayCommand(tool) ?? "(unknown command)";
|
|
32334
|
-
return `${bold("$", style)} ${
|
|
32512
|
+
return `${bold("$", style)} ${colorizeCommandProgram(display, style)}`;
|
|
32335
32513
|
}
|
|
32336
32514
|
const renderedName = bold(name, style);
|
|
32337
32515
|
if (!tool.title) return renderedName;
|
|
@@ -32346,45 +32524,56 @@ function formatToolSummaryLine(tool, style) {
|
|
|
32346
32524
|
default: return `${yellow("…", style)} ${label} (${id})`;
|
|
32347
32525
|
}
|
|
32348
32526
|
}
|
|
32349
|
-
function
|
|
32350
|
-
|
|
32527
|
+
function getToolStatus(value) {
|
|
32528
|
+
if (value === "completed" || value === "failed") return value;
|
|
32529
|
+
return "in_progress";
|
|
32351
32530
|
}
|
|
32352
|
-
function
|
|
32353
|
-
const
|
|
32354
|
-
if (
|
|
32355
|
-
if (
|
|
32356
|
-
|
|
32357
|
-
|
|
32358
|
-
|
|
32359
|
-
|
|
32360
|
-
|
|
32361
|
-
|
|
32362
|
-
|
|
32363
|
-
|
|
32364
|
-
|
|
32365
|
-
|
|
32366
|
-
|
|
32367
|
-
|
|
32368
|
-
|
|
32369
|
-
|
|
32370
|
-
|
|
32371
|
-
|
|
32372
|
-
|
|
32373
|
-
|
|
32374
|
-
|
|
32531
|
+
function combineToolStatuses(statuses) {
|
|
32532
|
+
const normalized = statuses.map((status) => getToolStatus(status));
|
|
32533
|
+
if (normalized.some((status) => status === "failed")) return "failed";
|
|
32534
|
+
if (normalized.some((status) => status === "in_progress")) return "in_progress";
|
|
32535
|
+
return "completed";
|
|
32536
|
+
}
|
|
32537
|
+
function formatToolStatusIcon(status, style) {
|
|
32538
|
+
switch (getToolStatus(status)) {
|
|
32539
|
+
case "completed": return green("✓", style);
|
|
32540
|
+
case "failed": return red("✗", style);
|
|
32541
|
+
default: return yellow("…", style);
|
|
32542
|
+
}
|
|
32543
|
+
}
|
|
32544
|
+
function getExploredSubCommandLines(tool) {
|
|
32545
|
+
if (tool.toolName !== "command_execution") return void 0;
|
|
32546
|
+
const rawCommand = getCommandExecutionRawCommand(tool);
|
|
32547
|
+
if (!rawCommand) return void 0;
|
|
32548
|
+
const exploredLines = getExploredCommandLines(rawCommand);
|
|
32549
|
+
if (!exploredLines || exploredLines.length <= 1) return void 0;
|
|
32550
|
+
return exploredLines.slice(1);
|
|
32551
|
+
}
|
|
32552
|
+
function formatExploredSubCommandLine(line, style) {
|
|
32553
|
+
if (line.startsWith("Search ")) {
|
|
32554
|
+
const payload = line.slice(7);
|
|
32555
|
+
const at = payload.lastIndexOf(" in ");
|
|
32556
|
+
if (at !== -1) {
|
|
32557
|
+
const terms = payload.slice(0, at);
|
|
32558
|
+
const file = payload.slice(at + 4);
|
|
32559
|
+
return `${cyan("Search", style)} ${terms} ${dimGray("in", style)} ${file}`;
|
|
32375
32560
|
}
|
|
32376
|
-
|
|
32377
|
-
current = "";
|
|
32378
|
-
if (word.length <= width) current = word;
|
|
32379
|
-
else pushLongWord(word);
|
|
32561
|
+
return `${cyan("Search", style)} ${payload}`;
|
|
32380
32562
|
}
|
|
32381
|
-
if (
|
|
32382
|
-
return
|
|
32563
|
+
if (line.startsWith("Read ")) return `${cyan("Read", style)} ${line.slice(5)}`;
|
|
32564
|
+
if (line === "List") return cyan("List", style);
|
|
32565
|
+
if (line.startsWith("List ")) return `${cyan("List", style)} ${line.slice(5)}`;
|
|
32566
|
+
return line;
|
|
32567
|
+
}
|
|
32568
|
+
function toDisplayLines(text) {
|
|
32569
|
+
return text.replaceAll("\r\n", "\n").split("\n");
|
|
32383
32570
|
}
|
|
32384
|
-
function
|
|
32385
|
-
|
|
32386
|
-
if (
|
|
32387
|
-
|
|
32571
|
+
function wrapRawLineToWidth(line, width) {
|
|
32572
|
+
if (width <= 0) return [line];
|
|
32573
|
+
if (line.length === 0) return [""];
|
|
32574
|
+
const out = [];
|
|
32575
|
+
for (let i = 0; i < line.length; i += width) out.push(line.slice(i, i + width));
|
|
32576
|
+
return out;
|
|
32388
32577
|
}
|
|
32389
32578
|
function trimLinesWithEllipsis(lines, maxLines) {
|
|
32390
32579
|
if (maxLines <= 0) return [];
|
|
@@ -32395,14 +32584,34 @@ function trimLinesWithEllipsis(lines, maxLines) {
|
|
|
32395
32584
|
kept[lastIndex] = last ? `${last}…` : "…";
|
|
32396
32585
|
return kept;
|
|
32397
32586
|
}
|
|
32587
|
+
function trimCommandOutputTopBottom(lines) {
|
|
32588
|
+
if (lines.length <= 4) return lines;
|
|
32589
|
+
const hidden = lines.length - 4;
|
|
32590
|
+
return [
|
|
32591
|
+
lines[0],
|
|
32592
|
+
lines[1],
|
|
32593
|
+
`… +${hidden} lines`,
|
|
32594
|
+
lines[lines.length - 2],
|
|
32595
|
+
lines[lines.length - 1]
|
|
32596
|
+
];
|
|
32597
|
+
}
|
|
32398
32598
|
function formatToolResultPreviewLines(tool, options) {
|
|
32399
32599
|
if (tool.status === "in_progress") return [];
|
|
32400
32600
|
if (options.maxLines <= 0) return [];
|
|
32401
|
-
if (tool.
|
|
32601
|
+
if (tool.toolName === "command_execution") {
|
|
32602
|
+
const rawCommand = getCommandExecutionRawCommand(tool);
|
|
32603
|
+
if (rawCommand && isExploredCommandExecution(rawCommand)) return [];
|
|
32604
|
+
}
|
|
32605
|
+
if (tool.status === "failed") {
|
|
32606
|
+
const lines = toDisplayLines(tool.errorText ?? "(no error text)");
|
|
32607
|
+
return trimLinesWithEllipsis(tool.toolName === "command_execution" ? trimCommandOutputTopBottom(lines) : lines, options.maxLines);
|
|
32608
|
+
}
|
|
32402
32609
|
if (tool.output == null) return ["(none)"];
|
|
32403
32610
|
if (tool.toolName === "command_execution") {
|
|
32404
32611
|
const output = tool.output;
|
|
32405
|
-
|
|
32612
|
+
const allLines = toDisplayLines((typeof output?.aggregated_output === "string" ? output.aggregated_output : "").trimEnd());
|
|
32613
|
+
if (!allLines.some((line) => line.length > 0)) return ["(none)"];
|
|
32614
|
+
return trimLinesWithEllipsis(trimCommandOutputTopBottom(allLines), options.maxLines);
|
|
32406
32615
|
}
|
|
32407
32616
|
return trimLinesWithEllipsis(toDisplayLines(inspect(tool.output, {
|
|
32408
32617
|
depth: 6,
|
|
@@ -32442,8 +32651,59 @@ function clip(value, maxVisible) {
|
|
|
32442
32651
|
const sliced = sliceSgrByVisibleWidth(value, maxVisible - 1);
|
|
32443
32652
|
return `${sliced}…${sliced.includes("\x1B[") ? ANSI.reset : ""}`;
|
|
32444
32653
|
}
|
|
32654
|
+
const TODO_PREVIEW_MAX_ITEMS = 3;
|
|
32655
|
+
const TODO_PREVIEW_MAX_PENDING = 2;
|
|
32656
|
+
function selectTodoPreviewItems(todoItems, options) {
|
|
32657
|
+
const selected = [];
|
|
32658
|
+
let pendingCount = 0;
|
|
32659
|
+
for (let index = todoItems.length - 1; index >= 0; index--) {
|
|
32660
|
+
const item = todoItems[index];
|
|
32661
|
+
if (selected.length >= options.maxItems) break;
|
|
32662
|
+
if (!item.completed && pendingCount >= options.maxPending) continue;
|
|
32663
|
+
selected.push({
|
|
32664
|
+
ordinal: index + 1,
|
|
32665
|
+
item
|
|
32666
|
+
});
|
|
32667
|
+
if (!item.completed) pendingCount += 1;
|
|
32668
|
+
}
|
|
32669
|
+
selected.reverse();
|
|
32670
|
+
return selected;
|
|
32671
|
+
}
|
|
32672
|
+
function wrapTodoItemLine(entry, widthHint) {
|
|
32673
|
+
const { ordinal, item } = entry;
|
|
32674
|
+
const normalizedText = item.text.trim().replaceAll(/\s+/g, " ") || "(empty)";
|
|
32675
|
+
const prefix = `${ordinal}. ${item.completed ? "[x]" : "[ ]"} `;
|
|
32676
|
+
return wrapRawLineToWidth(normalizedText, Math.max(1, widthHint - prefix.length)).map((chunk, chunkIndex) => chunkIndex === 0 ? `${prefix}${chunk}` : `${" ".repeat(prefix.length)}${chunk}`);
|
|
32677
|
+
}
|
|
32678
|
+
function trimLinesToHeight(lines, maxLines, style) {
|
|
32679
|
+
if (maxLines <= 0) return [];
|
|
32680
|
+
if (lines.length <= maxLines) return lines;
|
|
32681
|
+
if (maxLines === 1) return [dimGray(`… +${lines.length} more lines`, style)];
|
|
32682
|
+
const kept = lines.slice(0, maxLines - 1);
|
|
32683
|
+
const hidden = lines.length - kept.length;
|
|
32684
|
+
kept.push(dimGray(`… +${hidden} more lines`, style));
|
|
32685
|
+
return kept;
|
|
32686
|
+
}
|
|
32687
|
+
function formatTodoPanelLines(options) {
|
|
32688
|
+
if (options.todoItems.length === 0) return [];
|
|
32689
|
+
const selectedEntries = options.fullView ? options.todoItems.map((item, index) => ({
|
|
32690
|
+
ordinal: index + 1,
|
|
32691
|
+
item
|
|
32692
|
+
})) : selectTodoPreviewItems(options.todoItems, {
|
|
32693
|
+
maxItems: TODO_PREVIEW_MAX_ITEMS,
|
|
32694
|
+
maxPending: TODO_PREVIEW_MAX_PENDING
|
|
32695
|
+
});
|
|
32696
|
+
const lines = [bold("todos", options.style)];
|
|
32697
|
+
selectedEntries.forEach((entry) => lines.push(...wrapTodoItemLine(entry, Math.max(1, options.widthHint))));
|
|
32698
|
+
if (!options.fullView && selectedEntries.length < options.todoItems.length) {
|
|
32699
|
+
const hidden = options.todoItems.length - selectedEntries.length;
|
|
32700
|
+
lines.push(dimGray(`… +${hidden} more todos (t for full)`, options.style));
|
|
32701
|
+
}
|
|
32702
|
+
lines.push(dimGray("─".repeat(Math.max(1, options.widthHint)), options.style));
|
|
32703
|
+
return lines;
|
|
32704
|
+
}
|
|
32445
32705
|
function createWatchCommand(version) {
|
|
32446
|
-
return createCommand("watch").version(version).description("Inspect task progress via live stream data (internal tooling).").option("--tasks <ids>", "Comma-separated task IDs to watch.", parseCommaList, []).option("--agents <names>", "Comma-separated agent names to watch.", parseCommaList, []).option("--
|
|
32706
|
+
return createCommand("watch").version(version).description("Inspect task progress via live stream data (internal tooling).").option("--tasks <ids>", "Comma-separated task IDs to watch.", parseCommaList, []).option("--agents <names>", "Comma-separated agent names to watch.", parseCommaList, []).option("--list-width <cols>", "Left task-list width in columns (default: 32).", parseListWidth, 32).action(async function() {
|
|
32447
32707
|
ensureEnvOrExit(["PANTHEON_API_KEY", "DATABASE_URL"]);
|
|
32448
32708
|
const options = this.opts();
|
|
32449
32709
|
if (options.tasks.length > 0 && options.agents.length > 0) {
|
|
@@ -32471,9 +32731,20 @@ function createWatchCommand(version) {
|
|
|
32471
32731
|
process.on("SIGINT", onSigInt);
|
|
32472
32732
|
const runtime = targets.map((target) => ({
|
|
32473
32733
|
target,
|
|
32474
|
-
aggregator: new WatchStepAggregator({ maxLogLines:
|
|
32734
|
+
aggregator: new WatchStepAggregator({ maxLogLines: Number.POSITIVE_INFINITY }),
|
|
32475
32735
|
streamDone: false
|
|
32476
32736
|
}));
|
|
32737
|
+
const logViewportByTaskId = /* @__PURE__ */ new Map();
|
|
32738
|
+
function getLogViewport(taskId) {
|
|
32739
|
+
const existing = logViewportByTaskId.get(taskId);
|
|
32740
|
+
if (existing) return existing;
|
|
32741
|
+
const created = {
|
|
32742
|
+
autoFollow: true,
|
|
32743
|
+
scrollOffset: 0
|
|
32744
|
+
};
|
|
32745
|
+
logViewportByTaskId.set(taskId, created);
|
|
32746
|
+
return created;
|
|
32747
|
+
}
|
|
32477
32748
|
async function startStream(rt, streamId) {
|
|
32478
32749
|
rt.streamAbort?.abort();
|
|
32479
32750
|
rt.streamAbort = new AbortController();
|
|
@@ -32509,7 +32780,7 @@ function createWatchCommand(version) {
|
|
|
32509
32780
|
normalizer = createAgentStreamNormalizer({
|
|
32510
32781
|
source: rt.source,
|
|
32511
32782
|
emitStartChunk: false,
|
|
32512
|
-
includeMetaEvents:
|
|
32783
|
+
includeMetaEvents: true,
|
|
32513
32784
|
unknownChunkPolicy: "emit"
|
|
32514
32785
|
});
|
|
32515
32786
|
}
|
|
@@ -32544,7 +32815,10 @@ function createWatchCommand(version) {
|
|
|
32544
32815
|
const nextStreamId = branch.latest_snap?.event_stream_id ?? void 0;
|
|
32545
32816
|
if (nextStreamId && nextStreamId !== rt.streamId) {
|
|
32546
32817
|
rt.streamId = nextStreamId;
|
|
32547
|
-
rt.aggregator = new WatchStepAggregator({ maxLogLines:
|
|
32818
|
+
rt.aggregator = new WatchStepAggregator({ maxLogLines: Number.POSITIVE_INFINITY });
|
|
32819
|
+
const viewport = getLogViewport(rt.target.task.id);
|
|
32820
|
+
viewport.autoFollow = true;
|
|
32821
|
+
viewport.scrollOffset = 0;
|
|
32548
32822
|
await startStream(rt, nextStreamId);
|
|
32549
32823
|
}
|
|
32550
32824
|
} catch (error) {
|
|
@@ -32557,7 +32831,7 @@ function createWatchCommand(version) {
|
|
|
32557
32831
|
title: "pantheon-agents watch"
|
|
32558
32832
|
});
|
|
32559
32833
|
screen.key(["q", "C-c"], () => abortController.abort());
|
|
32560
|
-
const
|
|
32834
|
+
const globalFooter = blessed.box({
|
|
32561
32835
|
parent: screen,
|
|
32562
32836
|
bottom: 0,
|
|
32563
32837
|
left: 0,
|
|
@@ -32567,108 +32841,325 @@ function createWatchCommand(version) {
|
|
|
32567
32841
|
content: "Ctrl+C to exit • q to quit",
|
|
32568
32842
|
style: { fg: "gray" }
|
|
32569
32843
|
});
|
|
32570
|
-
const
|
|
32844
|
+
const taskListPane = blessed.list({
|
|
32571
32845
|
parent: screen,
|
|
32572
32846
|
top: 0,
|
|
32573
32847
|
left: 0,
|
|
32574
32848
|
height: "100%-1",
|
|
32575
|
-
width:
|
|
32849
|
+
width: options.listWidth,
|
|
32850
|
+
border: "line",
|
|
32851
|
+
tags: false,
|
|
32852
|
+
wrap: false,
|
|
32853
|
+
keys: false,
|
|
32854
|
+
vi: false,
|
|
32855
|
+
mouse: false,
|
|
32856
|
+
style: {
|
|
32857
|
+
border: { fg: "cyan" },
|
|
32858
|
+
selected: {
|
|
32859
|
+
fg: "black",
|
|
32860
|
+
bg: "cyan"
|
|
32861
|
+
},
|
|
32862
|
+
item: { fg: "white" }
|
|
32863
|
+
}
|
|
32864
|
+
});
|
|
32865
|
+
const rightPane = blessed.box({
|
|
32866
|
+
parent: screen,
|
|
32867
|
+
top: 0,
|
|
32868
|
+
left: options.listWidth,
|
|
32869
|
+
height: "100%-1",
|
|
32870
|
+
width: `100%-${options.listWidth}`,
|
|
32576
32871
|
border: "line",
|
|
32577
32872
|
tags: false,
|
|
32578
|
-
scrollable: false,
|
|
32579
32873
|
wrap: false,
|
|
32580
32874
|
style: { border: { fg: "gray" } }
|
|
32581
|
-
})
|
|
32875
|
+
});
|
|
32876
|
+
const rightHeader = blessed.box({
|
|
32877
|
+
parent: rightPane,
|
|
32878
|
+
top: 0,
|
|
32879
|
+
left: 1,
|
|
32880
|
+
height: 2,
|
|
32881
|
+
width: "100%-2",
|
|
32882
|
+
tags: false,
|
|
32883
|
+
wrap: false
|
|
32884
|
+
});
|
|
32885
|
+
const rightBody = blessed.box({
|
|
32886
|
+
parent: rightPane,
|
|
32887
|
+
top: 2,
|
|
32888
|
+
left: 1,
|
|
32889
|
+
width: "100%-2",
|
|
32890
|
+
height: 1,
|
|
32891
|
+
tags: false,
|
|
32892
|
+
wrap: false,
|
|
32893
|
+
scrollable: false
|
|
32894
|
+
});
|
|
32895
|
+
const rightFooter = blessed.box({
|
|
32896
|
+
parent: rightPane,
|
|
32897
|
+
left: 1,
|
|
32898
|
+
height: 1,
|
|
32899
|
+
width: "100%-2",
|
|
32900
|
+
tags: false,
|
|
32901
|
+
wrap: false,
|
|
32902
|
+
style: { fg: "gray" }
|
|
32903
|
+
});
|
|
32582
32904
|
let lastGlobalError;
|
|
32583
|
-
|
|
32584
|
-
|
|
32585
|
-
|
|
32586
|
-
|
|
32587
|
-
|
|
32588
|
-
|
|
32589
|
-
|
|
32590
|
-
|
|
32591
|
-
|
|
32592
|
-
|
|
32593
|
-
|
|
32594
|
-
|
|
32595
|
-
|
|
32596
|
-
|
|
32597
|
-
|
|
32905
|
+
let selectedIndex = 0;
|
|
32906
|
+
let focus = "list";
|
|
32907
|
+
let showFullTodoList = false;
|
|
32908
|
+
function normalizeTaskText(taskText) {
|
|
32909
|
+
return taskText.trim().replaceAll(/\s+/g, " ");
|
|
32910
|
+
}
|
|
32911
|
+
function getSelectedRuntimeTask() {
|
|
32912
|
+
if (selectedIndex < 0) selectedIndex = 0;
|
|
32913
|
+
if (selectedIndex >= runtime.length) selectedIndex = runtime.length - 1;
|
|
32914
|
+
return runtime[selectedIndex];
|
|
32915
|
+
}
|
|
32916
|
+
function getFormattedLogLines(rt, options) {
|
|
32917
|
+
const step = rt.aggregator.snapshot();
|
|
32918
|
+
const blocks = [];
|
|
32919
|
+
const reasoningWrapWidth = Math.max(1, options.widthHint);
|
|
32920
|
+
const messageWrapWidth = Math.max(1, options.widthHint);
|
|
32921
|
+
const toolById = new Map(step.toolActions.map((tool) => [tool.toolCallId, tool]));
|
|
32922
|
+
function pushBlock(order, lines) {
|
|
32923
|
+
if (lines.length === 0) return;
|
|
32924
|
+
blocks.push({
|
|
32925
|
+
order: order ?? Number.MAX_SAFE_INTEGER,
|
|
32926
|
+
lines
|
|
32927
|
+
});
|
|
32928
|
+
}
|
|
32929
|
+
for (let timelineIndex = 0; timelineIndex < step.timeline.length; timelineIndex++) {
|
|
32930
|
+
const entry = step.timeline[timelineIndex];
|
|
32931
|
+
if (entry.kind === "reasoning") {
|
|
32932
|
+
const reasoningBlock = [];
|
|
32933
|
+
const hasTrailingLineFeed = entry.text.endsWith("\n");
|
|
32934
|
+
const rawReasoningLines = toDisplayLines(entry.text);
|
|
32935
|
+
for (const rawLine of rawReasoningLines) wrapRawLineToWidth(rawLine, reasoningWrapWidth).forEach((chunk) => reasoningBlock.push(gray(chunk, options.style)));
|
|
32936
|
+
if (!hasTrailingLineFeed) reasoningBlock.push("");
|
|
32937
|
+
pushBlock(entry.order, reasoningBlock);
|
|
32598
32938
|
continue;
|
|
32599
32939
|
}
|
|
32600
|
-
|
|
32601
|
-
|
|
32602
|
-
|
|
32603
|
-
|
|
32604
|
-
|
|
32605
|
-
|
|
32606
|
-
|
|
32607
|
-
|
|
32608
|
-
|
|
32609
|
-
|
|
32610
|
-
|
|
32940
|
+
if (entry.kind === "message") {
|
|
32941
|
+
const messageBlock = [];
|
|
32942
|
+
const rawMessageLines = toDisplayLines(entry.text);
|
|
32943
|
+
for (const rawLine of rawMessageLines) wrapRawLineToWidth(rawLine, messageWrapWidth).forEach((chunk) => messageBlock.push(chunk));
|
|
32944
|
+
pushBlock(entry.order, messageBlock);
|
|
32945
|
+
continue;
|
|
32946
|
+
}
|
|
32947
|
+
if (entry.kind === "warning") {
|
|
32948
|
+
pushBlock(entry.order, [kv("warning", yellow(entry.message, options.style), options.style)]);
|
|
32949
|
+
continue;
|
|
32950
|
+
}
|
|
32951
|
+
const tool = toolById.get(entry.toolCallId);
|
|
32952
|
+
if (!tool) continue;
|
|
32953
|
+
const exploredSubLines = getExploredSubCommandLines(tool);
|
|
32954
|
+
if (exploredSubLines != null) {
|
|
32955
|
+
const groupedTools = [tool];
|
|
32956
|
+
const groupedSubLines = [...exploredSubLines];
|
|
32957
|
+
let lookahead = timelineIndex + 1;
|
|
32958
|
+
while (lookahead < step.timeline.length) {
|
|
32959
|
+
const next = step.timeline[lookahead];
|
|
32960
|
+
if (next.kind !== "tool") break;
|
|
32961
|
+
const nextTool = toolById.get(next.toolCallId);
|
|
32962
|
+
if (!nextTool) break;
|
|
32963
|
+
const nextSubLines = getExploredSubCommandLines(nextTool);
|
|
32964
|
+
if (nextSubLines == null) break;
|
|
32965
|
+
groupedTools.push(nextTool);
|
|
32966
|
+
groupedSubLines.push(...nextSubLines);
|
|
32967
|
+
lookahead += 1;
|
|
32968
|
+
}
|
|
32969
|
+
const groupedBlock = [` ${[
|
|
32970
|
+
formatToolStatusIcon(combineToolStatuses(groupedTools.map((groupedTool) => groupedTool.status)), options.style),
|
|
32971
|
+
cyan("Explored", options.style),
|
|
32972
|
+
groupedTools.length > 1 ? gray(`x${groupedTools.length}`, options.style) : void 0
|
|
32973
|
+
].filter(Boolean).join(" ")}`];
|
|
32974
|
+
groupedSubLines.forEach((subLine, subIndex) => groupedBlock.push(subIndex === 0 ? ` ${dimGray("└", options.style)} ${formatExploredSubCommandLine(subLine, options.style)}` : ` ${formatExploredSubCommandLine(subLine, options.style)}`));
|
|
32975
|
+
pushBlock(entry.order, groupedBlock);
|
|
32976
|
+
timelineIndex = lookahead - 1;
|
|
32977
|
+
continue;
|
|
32978
|
+
}
|
|
32979
|
+
const toolBlock = [];
|
|
32980
|
+
toDisplayLines(formatToolSummaryLine(tool, options.style)).forEach((line, index) => toolBlock.push(index === 0 ? ` ${line}` : ` ${line}`));
|
|
32981
|
+
if (tool.toolName === "command_execution") formatToolResultPreviewLines(tool, {
|
|
32982
|
+
maxLines: Number.MAX_SAFE_INTEGER,
|
|
32983
|
+
widthHint: Math.max(20, options.widthHint - 10),
|
|
32984
|
+
style: options.style
|
|
32985
|
+
}).forEach((line, index) => toolBlock.push(index === 0 ? ` ${dimGray("└", options.style)} ${dimGray(line, options.style)}` : ` ${dimGray(line, options.style)}`));
|
|
32986
|
+
pushBlock(entry.order, toolBlock);
|
|
32611
32987
|
}
|
|
32612
|
-
|
|
32613
|
-
|
|
32614
|
-
|
|
32615
|
-
|
|
32988
|
+
if (rt.lastError) pushBlock(void 0, [kv("error", red(rt.lastError, options.style), options.style)]);
|
|
32989
|
+
blocks.sort((a, b) => a.order - b.order);
|
|
32990
|
+
const lines = [];
|
|
32991
|
+
for (const block of blocks) {
|
|
32992
|
+
if (lines.length > 0 && lines[lines.length - 1] !== "") lines.push("");
|
|
32993
|
+
lines.push(...block.lines);
|
|
32994
|
+
}
|
|
32995
|
+
if (lines.length === 0) lines.push(gray("(waiting for formatted stream output)", options.style));
|
|
32996
|
+
return lines;
|
|
32997
|
+
}
|
|
32998
|
+
function moveTaskSelection(delta) {
|
|
32999
|
+
if (runtime.length === 0) return;
|
|
33000
|
+
selectedIndex = Math.max(0, Math.min(runtime.length - 1, selectedIndex + delta));
|
|
33001
|
+
}
|
|
33002
|
+
function scrollSelectedLog(delta) {
|
|
33003
|
+
const selected = getSelectedRuntimeTask();
|
|
33004
|
+
const viewport = getLogViewport(selected.target.task.id);
|
|
33005
|
+
const bodyHeight = typeof rightBody.height === "number" ? rightBody.height : 0;
|
|
33006
|
+
if (bodyHeight <= 0) return;
|
|
33007
|
+
const bodyWidth = typeof rightBody.width === "number" ? rightBody.width : 80;
|
|
33008
|
+
const lines = getFormattedLogLines(selected, {
|
|
33009
|
+
style: useAnsiStyles(),
|
|
33010
|
+
widthHint: Math.max(20, bodyWidth)
|
|
33011
|
+
});
|
|
33012
|
+
const maxOffset = Math.max(0, lines.length - bodyHeight);
|
|
33013
|
+
viewport.autoFollow = false;
|
|
33014
|
+
viewport.scrollOffset = Math.max(0, Math.min(maxOffset, viewport.scrollOffset + delta));
|
|
33015
|
+
}
|
|
33016
|
+
function scrollSelectedLogToTop() {
|
|
33017
|
+
const viewport = getLogViewport(getSelectedRuntimeTask().target.task.id);
|
|
33018
|
+
viewport.autoFollow = false;
|
|
33019
|
+
viewport.scrollOffset = 0;
|
|
33020
|
+
}
|
|
33021
|
+
function scrollSelectedLogToBottom() {
|
|
33022
|
+
const selected = getSelectedRuntimeTask();
|
|
33023
|
+
const viewport = getLogViewport(selected.target.task.id);
|
|
33024
|
+
const bodyHeight = typeof rightBody.height === "number" ? rightBody.height : 0;
|
|
33025
|
+
if (bodyHeight <= 0) return;
|
|
33026
|
+
const bodyWidth = typeof rightBody.width === "number" ? rightBody.width : 80;
|
|
33027
|
+
const lines = getFormattedLogLines(selected, {
|
|
33028
|
+
style: useAnsiStyles(),
|
|
33029
|
+
widthHint: Math.max(20, bodyWidth)
|
|
33030
|
+
});
|
|
33031
|
+
const maxOffset = Math.max(0, lines.length - bodyHeight);
|
|
33032
|
+
viewport.autoFollow = false;
|
|
33033
|
+
viewport.scrollOffset = maxOffset;
|
|
33034
|
+
}
|
|
33035
|
+
function getHalfScreenScrollStep() {
|
|
33036
|
+
const bodyHeight = typeof rightBody.height === "number" ? rightBody.height : 0;
|
|
33037
|
+
return Math.max(1, Math.floor(bodyHeight / 2));
|
|
32616
33038
|
}
|
|
33039
|
+
function resumeAutoFollowForSelectedLog() {
|
|
33040
|
+
const viewport = getLogViewport(getSelectedRuntimeTask().target.task.id);
|
|
33041
|
+
viewport.autoFollow = true;
|
|
33042
|
+
}
|
|
33043
|
+
screen.key(["left"], () => {
|
|
33044
|
+
focus = "list";
|
|
33045
|
+
});
|
|
33046
|
+
screen.key(["right"], () => {
|
|
33047
|
+
focus = "log";
|
|
33048
|
+
});
|
|
33049
|
+
screen.key(["up"], () => {
|
|
33050
|
+
if (focus === "list") moveTaskSelection(-1);
|
|
33051
|
+
else scrollSelectedLog(-getHalfScreenScrollStep());
|
|
33052
|
+
});
|
|
33053
|
+
screen.key(["down"], () => {
|
|
33054
|
+
if (focus === "list") moveTaskSelection(1);
|
|
33055
|
+
else scrollSelectedLog(getHalfScreenScrollStep());
|
|
33056
|
+
});
|
|
33057
|
+
screen.key(["g", "home"], () => {
|
|
33058
|
+
if (focus !== "log") return;
|
|
33059
|
+
scrollSelectedLogToTop();
|
|
33060
|
+
});
|
|
33061
|
+
screen.key([
|
|
33062
|
+
"G",
|
|
33063
|
+
"S-g",
|
|
33064
|
+
"end"
|
|
33065
|
+
], () => {
|
|
33066
|
+
if (focus !== "log") return;
|
|
33067
|
+
scrollSelectedLogToBottom();
|
|
33068
|
+
});
|
|
33069
|
+
screen.key(["f"], () => {
|
|
33070
|
+
resumeAutoFollowForSelectedLog();
|
|
33071
|
+
});
|
|
33072
|
+
screen.key(["t"], () => {
|
|
33073
|
+
showFullTodoList = !showFullTodoList;
|
|
33074
|
+
});
|
|
32617
33075
|
const renderTimer = setInterval(() => {
|
|
32618
33076
|
const style = useAnsiStyles();
|
|
32619
33077
|
const columns = Math.max(40, screen.width ?? 120);
|
|
32620
|
-
const
|
|
32621
|
-
const
|
|
32622
|
-
|
|
32623
|
-
|
|
32624
|
-
|
|
32625
|
-
|
|
32626
|
-
|
|
32627
|
-
|
|
32628
|
-
|
|
32629
|
-
|
|
32630
|
-
|
|
32631
|
-
|
|
32632
|
-
|
|
32633
|
-
|
|
32634
|
-
|
|
32635
|
-
|
|
32636
|
-
|
|
32637
|
-
|
|
32638
|
-
|
|
32639
|
-
|
|
32640
|
-
|
|
32641
|
-
|
|
32642
|
-
|
|
32643
|
-
|
|
32644
|
-
|
|
32645
|
-
|
|
32646
|
-
|
|
32647
|
-
|
|
32648
|
-
|
|
32649
|
-
|
|
32650
|
-
|
|
32651
|
-
|
|
32652
|
-
|
|
32653
|
-
|
|
32654
|
-
|
|
32655
|
-
|
|
32656
|
-
|
|
32657
|
-
|
|
32658
|
-
|
|
32659
|
-
|
|
32660
|
-
|
|
32661
|
-
|
|
32662
|
-
|
|
32663
|
-
|
|
32664
|
-
|
|
32665
|
-
|
|
32666
|
-
|
|
32667
|
-
|
|
32668
|
-
|
|
32669
|
-
|
|
32670
|
-
pane.setContent(baseLines.map((line) => clip(line, paneInnerWidth)).join("\n"));
|
|
33078
|
+
const rows = Math.max(8, screen.height ?? 24);
|
|
33079
|
+
const contentHeight = Math.max(1, rows - 1);
|
|
33080
|
+
const minListWidth = 12;
|
|
33081
|
+
const maxListWidth = Math.max(minListWidth, columns - 24);
|
|
33082
|
+
const listWidth = Math.min(Math.max(minListWidth, options.listWidth), maxListWidth);
|
|
33083
|
+
const rightPaneWidth = Math.max(1, columns - listWidth);
|
|
33084
|
+
taskListPane.top = 0;
|
|
33085
|
+
taskListPane.left = 0;
|
|
33086
|
+
taskListPane.width = listWidth;
|
|
33087
|
+
taskListPane.height = contentHeight;
|
|
33088
|
+
taskListPane.setLabel(" Tasks ");
|
|
33089
|
+
taskListPane.style.border = { fg: focus === "list" ? "cyan" : "gray" };
|
|
33090
|
+
rightPane.top = 0;
|
|
33091
|
+
rightPane.left = listWidth;
|
|
33092
|
+
rightPane.width = rightPaneWidth;
|
|
33093
|
+
rightPane.height = contentHeight;
|
|
33094
|
+
rightPane.style.border = { fg: focus === "log" ? "cyan" : "gray" };
|
|
33095
|
+
const selected = getSelectedRuntimeTask();
|
|
33096
|
+
const selectedTaskId = selected.target.task.id;
|
|
33097
|
+
const viewport = getLogViewport(selectedTaskId);
|
|
33098
|
+
const snapshot = selected.aggregator.snapshot();
|
|
33099
|
+
const paneInnerWidth = Math.max(1, rightPaneWidth - 2);
|
|
33100
|
+
const paneInnerHeight = Math.max(1, contentHeight - 2);
|
|
33101
|
+
const headerHeight = Math.min(2, paneInnerHeight);
|
|
33102
|
+
const maxRightFooterHeight = Math.max(0, paneInnerHeight - headerHeight);
|
|
33103
|
+
const visibleTodoPanelLines = trimLinesToHeight(formatTodoPanelLines({
|
|
33104
|
+
todoItems: snapshot.todoItems,
|
|
33105
|
+
fullView: showFullTodoList,
|
|
33106
|
+
widthHint: paneInnerWidth,
|
|
33107
|
+
style
|
|
33108
|
+
}), maxRightFooterHeight, style);
|
|
33109
|
+
const rightFooterHeight = visibleTodoPanelLines.length;
|
|
33110
|
+
const bodyHeight = Math.max(0, paneInnerHeight - headerHeight - rightFooterHeight);
|
|
33111
|
+
const listInnerWidth = Math.max(1, listWidth - 2);
|
|
33112
|
+
const taskListItems = runtime.map((rt) => clip(`${rt.target.agent}: ${normalizeTaskText(rt.target.task.task)}`, listInnerWidth));
|
|
33113
|
+
taskListPane.setItems(taskListItems);
|
|
33114
|
+
taskListPane.select(selectedIndex);
|
|
33115
|
+
rightPane.setLabel(` ${selected.target.agent} `);
|
|
33116
|
+
rightHeader.top = 0;
|
|
33117
|
+
rightHeader.left = 1;
|
|
33118
|
+
rightHeader.width = paneInnerWidth;
|
|
33119
|
+
rightHeader.height = headerHeight;
|
|
33120
|
+
rightHeader.show();
|
|
33121
|
+
const latestSnapId = selected.branch?.latest_snap_id ?? "(none)";
|
|
33122
|
+
const streamId = selected.streamId ?? selected.branch?.latest_snap?.event_stream_id ?? "(none)";
|
|
33123
|
+
const headerLines = [clip(`project id: ${selected.target.task.project_id} • task id: ${selected.target.task.id} • latest snap id: ${latestSnapId}`, paneInnerWidth), clip(`stream id: ${streamId}`, paneInnerWidth)];
|
|
33124
|
+
rightHeader.setContent(headerLines.slice(0, headerHeight).join("\n"));
|
|
33125
|
+
const formattedLogLines = getFormattedLogLines(selected, {
|
|
33126
|
+
style,
|
|
33127
|
+
widthHint: paneInnerWidth
|
|
32671
33128
|
});
|
|
33129
|
+
const maxOffset = Math.max(0, formattedLogLines.length - bodyHeight);
|
|
33130
|
+
if (viewport.autoFollow) viewport.scrollOffset = maxOffset;
|
|
33131
|
+
else viewport.scrollOffset = Math.max(0, Math.min(maxOffset, viewport.scrollOffset));
|
|
33132
|
+
rightBody.top = headerHeight + rightFooterHeight;
|
|
33133
|
+
rightBody.left = 1;
|
|
33134
|
+
rightBody.width = paneInnerWidth;
|
|
33135
|
+
rightBody.height = bodyHeight;
|
|
33136
|
+
if (bodyHeight <= 0) rightBody.hide();
|
|
33137
|
+
else {
|
|
33138
|
+
const visibleLines = formattedLogLines.slice(viewport.scrollOffset, viewport.scrollOffset + bodyHeight);
|
|
33139
|
+
rightBody.setContent(visibleLines.map((line) => clip(line, paneInnerWidth)).join("\n"));
|
|
33140
|
+
rightBody.show();
|
|
33141
|
+
}
|
|
33142
|
+
rightFooter.top = headerHeight;
|
|
33143
|
+
rightFooter.left = 1;
|
|
33144
|
+
rightFooter.width = paneInnerWidth;
|
|
33145
|
+
rightFooter.height = rightFooterHeight;
|
|
33146
|
+
if (rightFooterHeight <= 0) rightFooter.hide();
|
|
33147
|
+
else {
|
|
33148
|
+
rightFooter.setContent(visibleTodoPanelLines.map((line) => clip(line, paneInnerWidth)).join("\n"));
|
|
33149
|
+
rightFooter.show();
|
|
33150
|
+
}
|
|
33151
|
+
const footerParts = [
|
|
33152
|
+
"Ctrl+C to exit",
|
|
33153
|
+
"q to quit",
|
|
33154
|
+
"←/→ focus",
|
|
33155
|
+
focus === "list" ? "↑/↓ select task" : "↑/↓ half-page",
|
|
33156
|
+
"g/G top/bottom",
|
|
33157
|
+
"f resume auto-scroll",
|
|
33158
|
+
showFullTodoList ? "t todo preview" : "t todo full"
|
|
33159
|
+
];
|
|
33160
|
+
if (!viewport.autoFollow) footerParts.push("auto-scroll paused");
|
|
33161
|
+
if (lastGlobalError) footerParts.push(`error: ${clip(lastGlobalError, 40)}`);
|
|
33162
|
+
globalFooter.setContent(footerParts.join(" • "));
|
|
32672
33163
|
screen.render();
|
|
32673
33164
|
}, 300);
|
|
32674
33165
|
let pollTimer;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pantheon.ai/agents",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.17",
|
|
5
5
|
"bin": {
|
|
6
6
|
"pantheon-agents": "dist/index.js"
|
|
7
7
|
},
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
22
22
|
"@openrouter/ai-sdk-provider": "^2.2.3",
|
|
23
23
|
"@types/express": "^5.0.6",
|
|
24
|
+
"@types/shell-quote": "^1.7.5",
|
|
24
25
|
"commander": "^14.0.3",
|
|
25
26
|
"dotenv": "^17.2.4",
|
|
26
27
|
"expand-tilde": "^2.0.2",
|
|
@@ -31,6 +32,7 @@
|
|
|
31
32
|
"pino-pretty": "^13.1.3",
|
|
32
33
|
"pino-roll": "^4.0.0",
|
|
33
34
|
"reblessed": "^0.2.1",
|
|
35
|
+
"shell-quote": "^1.8.3",
|
|
34
36
|
"smol-toml": "^1.6.0",
|
|
35
37
|
"zod": "^4.3.6"
|
|
36
38
|
},
|