perstack 0.0.54 → 0.0.56
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/bin/cli.js +1340 -1881
- package/dist/bin/cli.js.map +1 -1
- package/package.json +8 -6
package/dist/bin/cli.js
CHANGED
|
@@ -4,22 +4,24 @@ import { writeFile, mkdir, readFile } from 'fs/promises';
|
|
|
4
4
|
import * as path10 from 'path';
|
|
5
5
|
import path10__default from 'path';
|
|
6
6
|
import { createApiClient } from '@perstack/api-client';
|
|
7
|
-
import { registerAdapter, parseWithFriendlyError, runCommandInputSchema, startCommandInputSchema, defaultMaxRetries, defaultTimeout, defaultPerstackApiBaseUrl, checkpointSchema, jobSchema, runSettingSchema, BaseAdapter, createRuntimeInitEvent, createEmptyUsage, createStartRunEvent, createCompleteRunEvent, getFilteredEnv,
|
|
7
|
+
import { registerAdapter, parseWithFriendlyError, runCommandInputSchema, validateEventFilter, createFilteredEventListener, startCommandInputSchema, defaultMaxRetries, defaultTimeout, defaultPerstackApiBaseUrl, checkpointSchema, jobSchema, runSettingSchema, BaseAdapter, createRuntimeInitEvent, createEmptyUsage, createStartRunEvent, createCompleteRunEvent, getFilteredEnv, createCallToolsEvent, createResolveToolResultsEvent, createRuntimeEvent, perstackConfigSchema, expertSchema, isAdapterAvailable as isAdapterAvailable$1, getRegisteredRuntimes as getRegisteredRuntimes$1, getAdapter as getAdapter$1 } from '@perstack/core';
|
|
8
8
|
import { collectToolDefinitionsForExpert } from '@perstack/runtime';
|
|
9
9
|
import TOML from 'smol-toml';
|
|
10
10
|
import dotenv from 'dotenv';
|
|
11
11
|
import * as fs from 'fs';
|
|
12
12
|
import { existsSync, readdirSync, readFileSync, statSync } from 'fs';
|
|
13
|
-
import { render, useApp,
|
|
14
|
-
import { createContext, useState, useEffect, useCallback,
|
|
13
|
+
import { render, useApp, useInput, Box, Text } from 'ink';
|
|
14
|
+
import { createContext, useMemo, useReducer, useState, useEffect, useCallback, useRef, useContext } from 'react';
|
|
15
|
+
import { useTextInput, SelectableList, useListNavigation } from '@perstack/tui-components';
|
|
15
16
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
17
|
+
import { useRun } from '@perstack/react';
|
|
16
18
|
import { spawn, execSync } from 'child_process';
|
|
17
19
|
import * as os from 'os';
|
|
18
20
|
|
|
19
21
|
// package.json
|
|
20
22
|
var package_default = {
|
|
21
23
|
name: "perstack",
|
|
22
|
-
version: "0.0.
|
|
24
|
+
version: "0.0.56",
|
|
23
25
|
description: "PerStack CLI"};
|
|
24
26
|
function getEnv(envPath) {
|
|
25
27
|
const env = Object.fromEntries(
|
|
@@ -350,16 +352,6 @@ async function defaultStoreEvent(event) {
|
|
|
350
352
|
await mkdir(runDir, { recursive: true });
|
|
351
353
|
await writeFile(eventPath, JSON.stringify(event));
|
|
352
354
|
}
|
|
353
|
-
function getEventsByRun(jobId, runId) {
|
|
354
|
-
const runDir = defaultGetRunDir(jobId, runId);
|
|
355
|
-
if (!existsSync(runDir)) {
|
|
356
|
-
return [];
|
|
357
|
-
}
|
|
358
|
-
return readdirSync(runDir).filter((file) => file.startsWith("event-")).map((file) => {
|
|
359
|
-
const [_, timestamp, stepNumber, type] = file.split(".")[0].split("-");
|
|
360
|
-
return { timestamp: Number(timestamp), stepNumber: Number(stepNumber), type };
|
|
361
|
-
}).sort((a, b) => a.stepNumber - b.stepNumber);
|
|
362
|
-
}
|
|
363
355
|
function getEventContents(jobId, runId, maxStepNumber) {
|
|
364
356
|
const runDir = defaultGetRunDir(jobId, runId);
|
|
365
357
|
if (!existsSync(runDir)) {
|
|
@@ -650,8 +642,8 @@ function createStorageAdapter(storage, basePath) {
|
|
|
650
642
|
|
|
651
643
|
// src/lib/log/filter.ts
|
|
652
644
|
var ERROR_EVENT_TYPES = /* @__PURE__ */ new Set(["stopRunByError", "retry"]);
|
|
653
|
-
var TOOL_EVENT_TYPES = /* @__PURE__ */ new Set(["callTools", "resolveToolResults", "
|
|
654
|
-
var DELEGATION_EVENT_TYPES = /* @__PURE__ */ new Set(["
|
|
645
|
+
var TOOL_EVENT_TYPES = /* @__PURE__ */ new Set(["callTools", "resolveToolResults", "stopRunByInteractiveTool"]);
|
|
646
|
+
var DELEGATION_EVENT_TYPES = /* @__PURE__ */ new Set(["stopRunByDelegate"]);
|
|
655
647
|
function parseStepFilter(step) {
|
|
656
648
|
const trimmed = step.trim();
|
|
657
649
|
const rangeMatch = trimmed.match(/^(\d+)-(\d+)$/);
|
|
@@ -867,8 +859,8 @@ function addContextEvents(allEvents, matchedEvents, contextSize) {
|
|
|
867
859
|
|
|
868
860
|
// src/lib/log/formatter.ts
|
|
869
861
|
var ERROR_EVENT_TYPES2 = /* @__PURE__ */ new Set(["stopRunByError", "retry"]);
|
|
870
|
-
var TOOL_EVENT_TYPES2 = /* @__PURE__ */ new Set(["callTools", "resolveToolResults", "
|
|
871
|
-
var DELEGATION_EVENT_TYPES2 = /* @__PURE__ */ new Set(["
|
|
862
|
+
var TOOL_EVENT_TYPES2 = /* @__PURE__ */ new Set(["callTools", "resolveToolResults", "stopRunByInteractiveTool"]);
|
|
863
|
+
var DELEGATION_EVENT_TYPES2 = /* @__PURE__ */ new Set(["stopRunByDelegate"]);
|
|
872
864
|
function createSummary(events) {
|
|
873
865
|
if (events.length === 0) {
|
|
874
866
|
return {
|
|
@@ -1048,11 +1040,10 @@ function formatEvent(event, verbose) {
|
|
|
1048
1040
|
lines.push(` Message: ${errorEvent.error.message}`);
|
|
1049
1041
|
lines.push(` Retryable: ${errorEvent.error.isRetryable}`);
|
|
1050
1042
|
}
|
|
1051
|
-
if (event.type === "
|
|
1043
|
+
if (event.type === "stopRunByDelegate" && "checkpoint" in event) {
|
|
1052
1044
|
const delegateEvent = event;
|
|
1053
|
-
for (const
|
|
1054
|
-
|
|
1055
|
-
lines.push(` Delegate to: ${expertKey}`);
|
|
1045
|
+
for (const d of delegateEvent.checkpoint.delegateTo ?? []) {
|
|
1046
|
+
lines.push(` Delegate to: ${d.expert.key}`);
|
|
1056
1047
|
}
|
|
1057
1048
|
}
|
|
1058
1049
|
if (event.type === "completeRun" && "text" in event) {
|
|
@@ -1363,7 +1354,6 @@ var summarizeOutput = (lines, maxLines) => {
|
|
|
1363
1354
|
// src/tui/constants.ts
|
|
1364
1355
|
var UI_CONSTANTS = {
|
|
1365
1356
|
MAX_VISIBLE_LIST_ITEMS: 25,
|
|
1366
|
-
MAX_EVENTS: 1e3,
|
|
1367
1357
|
TRUNCATE_TEXT_MEDIUM: 80,
|
|
1368
1358
|
TRUNCATE_TEXT_DEFAULT: 100};
|
|
1369
1359
|
var RENDER_CONSTANTS = {
|
|
@@ -1372,7 +1362,6 @@ var RENDER_CONSTANTS = {
|
|
|
1372
1362
|
LIST_DIR_MAX_ITEMS: 4
|
|
1373
1363
|
};
|
|
1374
1364
|
var INDICATOR = {
|
|
1375
|
-
CHEVRON_RIGHT: ">",
|
|
1376
1365
|
BULLET: "\u25CF",
|
|
1377
1366
|
TREE: "\u2514",
|
|
1378
1367
|
ELLIPSIS: "..."
|
|
@@ -1413,654 +1402,149 @@ var KEY_HINTS = {
|
|
|
1413
1402
|
CTRL_QUIT: `${KEY_BINDINGS.CTRL_QUIT}:Quit`,
|
|
1414
1403
|
CONFIRM: `${KEY_BINDINGS.SELECT}:Confirm`
|
|
1415
1404
|
};
|
|
1416
|
-
var
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
} =
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
}, [configuredExperts, recentExperts]);
|
|
1435
|
-
const handleExpertSelect = useCallback(
|
|
1436
|
-
(expertKey) => {
|
|
1437
|
-
setExpertName(expertKey);
|
|
1438
|
-
const needsQuery = needsQueryInput || inputState.type === "browsingExperts";
|
|
1439
|
-
dispatch({ type: "SELECT_EXPERT", expertKey, needsQuery });
|
|
1440
|
-
if (!needsQuery) {
|
|
1441
|
-
markAsStarted();
|
|
1442
|
-
onComplete(expertKey, "");
|
|
1443
|
-
}
|
|
1444
|
-
},
|
|
1445
|
-
[needsQueryInput, inputState.type, dispatch, setExpertName, onComplete, markAsStarted]
|
|
1446
|
-
);
|
|
1447
|
-
return { allExperts, handleExpertSelect };
|
|
1448
|
-
};
|
|
1449
|
-
|
|
1450
|
-
// src/tui/utils/error-handling.ts
|
|
1451
|
-
var createErrorHandler = (onError) => (error, context) => {
|
|
1452
|
-
const err = error instanceof Error ? error : new Error(`${context}: ${String(error)}`);
|
|
1453
|
-
onError?.(err);
|
|
1454
|
-
};
|
|
1455
|
-
|
|
1456
|
-
// src/tui/hooks/core/use-error-handler.ts
|
|
1457
|
-
var useErrorHandler = (onError) => {
|
|
1458
|
-
return useMemo(() => createErrorHandler(onError), [onError]);
|
|
1459
|
-
};
|
|
1460
|
-
|
|
1461
|
-
// src/tui/hooks/actions/use-history-actions.ts
|
|
1462
|
-
var useHistoryActions = (options) => {
|
|
1463
|
-
const {
|
|
1464
|
-
allExperts,
|
|
1465
|
-
historyJobs,
|
|
1466
|
-
onLoadCheckpoints,
|
|
1467
|
-
onLoadEvents,
|
|
1468
|
-
onResumeFromCheckpoint,
|
|
1469
|
-
onLoadHistoricalEvents,
|
|
1470
|
-
setHistoricalEvents,
|
|
1471
|
-
setCurrentStep,
|
|
1472
|
-
setContextWindowUsage,
|
|
1473
|
-
dispatch,
|
|
1474
|
-
setExpertName,
|
|
1475
|
-
onError
|
|
1476
|
-
} = options;
|
|
1477
|
-
const [selectedJob, setSelectedJob] = useState(null);
|
|
1478
|
-
const handleError = useErrorHandler(onError);
|
|
1479
|
-
const handleJobSelect = useCallback(
|
|
1480
|
-
async (job) => {
|
|
1481
|
-
try {
|
|
1482
|
-
setSelectedJob(job);
|
|
1483
|
-
setExpertName(job.expertKey);
|
|
1484
|
-
if (onLoadCheckpoints) {
|
|
1485
|
-
const checkpoints = await onLoadCheckpoints(job);
|
|
1486
|
-
dispatch({ type: "SELECT_JOB", job, checkpoints });
|
|
1487
|
-
}
|
|
1488
|
-
} catch (error) {
|
|
1489
|
-
handleError(error, "Failed to load checkpoints");
|
|
1490
|
-
}
|
|
1491
|
-
},
|
|
1492
|
-
[onLoadCheckpoints, dispatch, setExpertName, handleError]
|
|
1493
|
-
);
|
|
1494
|
-
const handleJobResume = useCallback(
|
|
1495
|
-
async (job) => {
|
|
1496
|
-
try {
|
|
1497
|
-
setSelectedJob(job);
|
|
1498
|
-
setExpertName(job.expertKey);
|
|
1499
|
-
if (onLoadCheckpoints && onResumeFromCheckpoint) {
|
|
1500
|
-
const checkpoints = await onLoadCheckpoints(job);
|
|
1501
|
-
const latestCheckpoint = checkpoints[0];
|
|
1502
|
-
if (latestCheckpoint) {
|
|
1503
|
-
if (onLoadHistoricalEvents) {
|
|
1504
|
-
const events = await onLoadHistoricalEvents(latestCheckpoint);
|
|
1505
|
-
setHistoricalEvents(events);
|
|
1506
|
-
}
|
|
1507
|
-
setCurrentStep(latestCheckpoint.stepNumber);
|
|
1508
|
-
setContextWindowUsage(latestCheckpoint.contextWindowUsage);
|
|
1509
|
-
dispatch({ type: "RESUME_CHECKPOINT", expertKey: job.expertKey });
|
|
1510
|
-
onResumeFromCheckpoint(latestCheckpoint);
|
|
1511
|
-
}
|
|
1512
|
-
}
|
|
1513
|
-
} catch (error) {
|
|
1514
|
-
handleError(error, "Failed to resume job");
|
|
1515
|
-
}
|
|
1516
|
-
},
|
|
1517
|
-
[
|
|
1518
|
-
onLoadCheckpoints,
|
|
1519
|
-
onResumeFromCheckpoint,
|
|
1520
|
-
onLoadHistoricalEvents,
|
|
1521
|
-
setHistoricalEvents,
|
|
1522
|
-
setCurrentStep,
|
|
1523
|
-
setContextWindowUsage,
|
|
1524
|
-
dispatch,
|
|
1525
|
-
setExpertName,
|
|
1526
|
-
handleError
|
|
1527
|
-
]
|
|
1528
|
-
);
|
|
1529
|
-
const handleCheckpointSelect = useCallback(
|
|
1530
|
-
async (checkpoint) => {
|
|
1531
|
-
try {
|
|
1532
|
-
if (selectedJob && onLoadEvents) {
|
|
1533
|
-
const eventsData = await onLoadEvents(selectedJob, checkpoint);
|
|
1534
|
-
dispatch({ type: "SELECT_CHECKPOINT", job: selectedJob, checkpoint, events: eventsData });
|
|
1535
|
-
}
|
|
1536
|
-
} catch (error) {
|
|
1537
|
-
handleError(error, "Failed to load events");
|
|
1538
|
-
}
|
|
1539
|
-
},
|
|
1540
|
-
[selectedJob, onLoadEvents, dispatch, handleError]
|
|
1541
|
-
);
|
|
1542
|
-
const handleCheckpointResume = useCallback(
|
|
1543
|
-
async (checkpoint) => {
|
|
1544
|
-
if (onResumeFromCheckpoint) {
|
|
1545
|
-
if (onLoadHistoricalEvents) {
|
|
1546
|
-
const events = await onLoadHistoricalEvents(checkpoint);
|
|
1547
|
-
setHistoricalEvents(events);
|
|
1548
|
-
}
|
|
1549
|
-
setCurrentStep(checkpoint.stepNumber);
|
|
1550
|
-
setContextWindowUsage(checkpoint.contextWindowUsage);
|
|
1551
|
-
dispatch({ type: "RESUME_CHECKPOINT", expertKey: selectedJob?.expertKey || "" });
|
|
1552
|
-
onResumeFromCheckpoint(checkpoint);
|
|
1553
|
-
}
|
|
1554
|
-
},
|
|
1555
|
-
[
|
|
1556
|
-
onResumeFromCheckpoint,
|
|
1557
|
-
onLoadHistoricalEvents,
|
|
1558
|
-
setHistoricalEvents,
|
|
1559
|
-
setCurrentStep,
|
|
1560
|
-
setContextWindowUsage,
|
|
1561
|
-
dispatch,
|
|
1562
|
-
selectedJob?.expertKey
|
|
1563
|
-
]
|
|
1564
|
-
);
|
|
1565
|
-
const handleBackFromEvents = useCallback(async () => {
|
|
1566
|
-
try {
|
|
1567
|
-
if (selectedJob && onLoadCheckpoints) {
|
|
1568
|
-
const checkpoints = await onLoadCheckpoints(selectedJob);
|
|
1569
|
-
dispatch({ type: "GO_BACK_FROM_EVENTS", job: selectedJob, checkpoints });
|
|
1570
|
-
}
|
|
1571
|
-
} catch (error) {
|
|
1572
|
-
handleError(error, "Failed to go back from events");
|
|
1573
|
-
}
|
|
1574
|
-
}, [selectedJob, onLoadCheckpoints, dispatch, handleError]);
|
|
1575
|
-
const handleBackFromCheckpoints = useCallback(() => {
|
|
1576
|
-
if (historyJobs) {
|
|
1577
|
-
setSelectedJob(null);
|
|
1578
|
-
dispatch({ type: "GO_BACK_FROM_CHECKPOINTS", historyJobs });
|
|
1579
|
-
}
|
|
1580
|
-
}, [historyJobs, dispatch]);
|
|
1581
|
-
const handleEventSelect = useCallback(
|
|
1582
|
-
(state, event) => {
|
|
1583
|
-
dispatch({
|
|
1584
|
-
type: "SELECT_EVENT",
|
|
1585
|
-
checkpoint: state.checkpoint,
|
|
1586
|
-
events: state.events,
|
|
1587
|
-
selectedEvent: event
|
|
1588
|
-
});
|
|
1589
|
-
},
|
|
1590
|
-
[dispatch]
|
|
1591
|
-
);
|
|
1592
|
-
const handleBackFromEventDetail = useCallback(
|
|
1593
|
-
(state) => {
|
|
1594
|
-
dispatch({
|
|
1595
|
-
type: "GO_BACK_FROM_EVENT_DETAIL",
|
|
1596
|
-
checkpoint: state.checkpoint,
|
|
1597
|
-
events: state.events
|
|
1598
|
-
});
|
|
1599
|
-
},
|
|
1600
|
-
[dispatch]
|
|
1601
|
-
);
|
|
1602
|
-
const handleBack = useCallback(
|
|
1603
|
-
(currentState) => {
|
|
1604
|
-
switch (currentState.type) {
|
|
1605
|
-
case "browsingEventDetail":
|
|
1606
|
-
handleBackFromEventDetail(currentState);
|
|
1607
|
-
break;
|
|
1608
|
-
case "browsingEvents":
|
|
1609
|
-
handleBackFromEvents();
|
|
1610
|
-
break;
|
|
1611
|
-
case "browsingCheckpoints":
|
|
1612
|
-
handleBackFromCheckpoints();
|
|
1613
|
-
break;
|
|
1614
|
-
}
|
|
1615
|
-
},
|
|
1616
|
-
[handleBackFromEventDetail, handleBackFromEvents, handleBackFromCheckpoints]
|
|
1617
|
-
);
|
|
1618
|
-
const handleSwitchToExperts = useCallback(() => {
|
|
1619
|
-
dispatch({ type: "BROWSE_EXPERTS", experts: allExperts });
|
|
1620
|
-
}, [dispatch, allExperts]);
|
|
1621
|
-
const handleSwitchToHistory = useCallback(() => {
|
|
1622
|
-
if (historyJobs) {
|
|
1623
|
-
dispatch({ type: "BROWSE_HISTORY", jobs: historyJobs });
|
|
1624
|
-
}
|
|
1625
|
-
}, [dispatch, historyJobs]);
|
|
1626
|
-
return {
|
|
1627
|
-
selectedJob,
|
|
1628
|
-
handleJobSelect,
|
|
1629
|
-
handleJobResume,
|
|
1630
|
-
handleCheckpointSelect,
|
|
1631
|
-
handleCheckpointResume,
|
|
1632
|
-
handleEventSelect,
|
|
1633
|
-
handleBack,
|
|
1634
|
-
handleSwitchToExperts,
|
|
1635
|
-
handleSwitchToHistory
|
|
1636
|
-
};
|
|
1637
|
-
};
|
|
1638
|
-
var useLatestRef = (value) => {
|
|
1639
|
-
const ref = useRef(value);
|
|
1640
|
-
useInsertionEffect(() => {
|
|
1641
|
-
ref.current = value;
|
|
1405
|
+
var ListBrowser = ({
|
|
1406
|
+
title,
|
|
1407
|
+
items,
|
|
1408
|
+
renderItem,
|
|
1409
|
+
onSelect,
|
|
1410
|
+
emptyMessage = "No items found",
|
|
1411
|
+
extraKeyHandler,
|
|
1412
|
+
onBack,
|
|
1413
|
+
maxItems = UI_CONSTANTS.MAX_VISIBLE_LIST_ITEMS
|
|
1414
|
+
}) => {
|
|
1415
|
+
const { selectedIndex, handleNavigation } = useListNavigation({
|
|
1416
|
+
items,
|
|
1417
|
+
onSelect,
|
|
1418
|
+
onBack
|
|
1419
|
+
});
|
|
1420
|
+
useInput((inputChar, key) => {
|
|
1421
|
+
if (extraKeyHandler?.(inputChar, key, items[selectedIndex])) return;
|
|
1422
|
+
handleNavigation(inputChar, key);
|
|
1642
1423
|
});
|
|
1643
|
-
|
|
1424
|
+
const { scrollOffset, displayItems } = useMemo(() => {
|
|
1425
|
+
const offset = Math.max(0, Math.min(selectedIndex - maxItems + 1, items.length - maxItems));
|
|
1426
|
+
return {
|
|
1427
|
+
scrollOffset: offset,
|
|
1428
|
+
displayItems: items.slice(offset, offset + maxItems)
|
|
1429
|
+
};
|
|
1430
|
+
}, [items, selectedIndex, maxItems]);
|
|
1431
|
+
const hasMoreAbove = scrollOffset > 0;
|
|
1432
|
+
const hasMoreBelow = scrollOffset + maxItems < items.length;
|
|
1433
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
1434
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
1435
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: title }),
|
|
1436
|
+
items.length > maxItems && /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
|
|
1437
|
+
" ",
|
|
1438
|
+
"(",
|
|
1439
|
+
selectedIndex + 1,
|
|
1440
|
+
"/",
|
|
1441
|
+
items.length,
|
|
1442
|
+
")"
|
|
1443
|
+
] })
|
|
1444
|
+
] }),
|
|
1445
|
+
hasMoreAbove && /* @__PURE__ */ jsx(Text, { color: "gray", children: INDICATOR.ELLIPSIS }),
|
|
1446
|
+
/* @__PURE__ */ jsx(Box, { flexDirection: "column", children: displayItems.length === 0 ? /* @__PURE__ */ jsx(Text, { color: "gray", children: emptyMessage }) : displayItems.map((item, index) => {
|
|
1447
|
+
const actualIndex = scrollOffset + index;
|
|
1448
|
+
return renderItem(item, actualIndex === selectedIndex, actualIndex);
|
|
1449
|
+
}) }),
|
|
1450
|
+
hasMoreBelow && /* @__PURE__ */ jsx(Text, { color: "gray", children: INDICATOR.ELLIPSIS })
|
|
1451
|
+
] });
|
|
1644
1452
|
};
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
stepStoreAddEvent(event);
|
|
1665
|
-
const result = handleEvent(event);
|
|
1666
|
-
if (result?.initialized) {
|
|
1667
|
-
dispatch({ type: "INITIALIZE_RUNTIME" });
|
|
1668
|
-
} else if (result?.completed && onContinueRef.current) {
|
|
1669
|
-
dispatch({ type: "END_RUN", expertName: expertNameRef.current || "", reason: "completed" });
|
|
1670
|
-
} else if (result?.stopped && onContinueRef.current) {
|
|
1671
|
-
dispatch({ type: "END_RUN", expertName: expertNameRef.current || "", reason: "stopped" });
|
|
1672
|
-
}
|
|
1673
|
-
});
|
|
1674
|
-
}, [onReady, stepStoreAddEvent, handleEvent, dispatch, onContinueRef, expertNameRef]);
|
|
1675
|
-
const handleQuerySubmit = useCallback(
|
|
1676
|
-
(query) => {
|
|
1677
|
-
setQuery(query);
|
|
1678
|
-
dispatch({ type: "START_RUN" });
|
|
1679
|
-
if (hasStarted && onContinue) {
|
|
1680
|
-
onContinue(query);
|
|
1681
|
-
} else {
|
|
1682
|
-
markAsStarted();
|
|
1683
|
-
onComplete(expertName || "", query);
|
|
1453
|
+
var BrowsingCheckpointsInput = ({
|
|
1454
|
+
job,
|
|
1455
|
+
checkpoints,
|
|
1456
|
+
onCheckpointSelect,
|
|
1457
|
+
onCheckpointResume,
|
|
1458
|
+
onBack,
|
|
1459
|
+
showEventsHint = true
|
|
1460
|
+
}) => /* @__PURE__ */ jsx(
|
|
1461
|
+
ListBrowser,
|
|
1462
|
+
{
|
|
1463
|
+
title: `Checkpoints for ${job.expertKey} ${KEY_HINTS.NAVIGATE} ${KEY_HINTS.RESUME} ${showEventsHint ? KEY_HINTS.EVENTS : ""} ${KEY_HINTS.BACK}`.trim(),
|
|
1464
|
+
items: checkpoints,
|
|
1465
|
+
onSelect: onCheckpointResume,
|
|
1466
|
+
onBack,
|
|
1467
|
+
emptyMessage: "No checkpoints found",
|
|
1468
|
+
extraKeyHandler: (char, _key, selected) => {
|
|
1469
|
+
if (char === "e" && selected) {
|
|
1470
|
+
onCheckpointSelect(selected);
|
|
1471
|
+
return true;
|
|
1684
1472
|
}
|
|
1473
|
+
return false;
|
|
1685
1474
|
},
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
"startRunResult",
|
|
1695
|
-
"streamRunResult"
|
|
1696
|
-
]);
|
|
1697
|
-
var isToolCallsEvent = (event) => "type" in event && event.type === "callTools" && "toolCalls" in event;
|
|
1698
|
-
var isToolCallEvent = (event) => "type" in event && (event.type === "callInteractiveTool" || event.type === "callDelegate") && "toolCall" in event;
|
|
1699
|
-
var isToolResultsEvent = (event) => "type" in event && event.type === "resolveToolResults" && "toolResults" in event;
|
|
1700
|
-
var isToolResultEvent = (event) => "type" in event && TOOL_RESULT_EVENT_TYPES.has(event.type) && "toolResult" in event;
|
|
1701
|
-
var checkIsSuccess = (result) => {
|
|
1702
|
-
const textPart = result.find((r) => r.type === "textPart");
|
|
1703
|
-
if (!textPart || typeof textPart.text !== "string") return true;
|
|
1704
|
-
const text = textPart.text.toLowerCase();
|
|
1705
|
-
return !text.startsWith("error") && !text.includes("failed");
|
|
1706
|
-
};
|
|
1707
|
-
var extractQuery = (event) => {
|
|
1708
|
-
const userMessage = event.inputMessages.find((m) => m.type === "userMessage");
|
|
1709
|
-
if (userMessage?.type !== "userMessage") return void 0;
|
|
1710
|
-
return userMessage.contents.find((c) => c.type === "textPart")?.text;
|
|
1711
|
-
};
|
|
1712
|
-
var formatRuntimeName = (runtime) => {
|
|
1713
|
-
if (runtime === "claude-code") return "Claude Code";
|
|
1714
|
-
if (runtime === "local") return "Local";
|
|
1715
|
-
return runtime.charAt(0).toUpperCase() + runtime.slice(1);
|
|
1716
|
-
};
|
|
1717
|
-
var processEventToLogs = (state, event, addLog) => {
|
|
1718
|
-
if (!("runId" in event)) return;
|
|
1719
|
-
const runId = event.runId;
|
|
1720
|
-
if (event.type === "dockerBuildProgress") {
|
|
1721
|
-
const buildEvent = event;
|
|
1722
|
-
addLog({
|
|
1723
|
-
id: `docker-build-${event.id}`,
|
|
1724
|
-
type: "docker-build",
|
|
1725
|
-
stage: buildEvent.stage,
|
|
1726
|
-
service: buildEvent.service,
|
|
1727
|
-
message: buildEvent.message,
|
|
1728
|
-
progress: buildEvent.progress
|
|
1729
|
-
});
|
|
1730
|
-
return;
|
|
1731
|
-
}
|
|
1732
|
-
if (event.type === "dockerContainerStatus") {
|
|
1733
|
-
const containerEvent = event;
|
|
1734
|
-
addLog({
|
|
1735
|
-
id: `docker-container-${event.id}`,
|
|
1736
|
-
type: "docker-container",
|
|
1737
|
-
status: containerEvent.status,
|
|
1738
|
-
service: containerEvent.service,
|
|
1739
|
-
message: containerEvent.message
|
|
1740
|
-
});
|
|
1741
|
-
return;
|
|
1742
|
-
}
|
|
1743
|
-
if (event.type === "proxyAccess") {
|
|
1744
|
-
const proxyEvent = event;
|
|
1745
|
-
addLog({
|
|
1746
|
-
id: `proxy-access-${event.id}`,
|
|
1747
|
-
type: "proxy-access",
|
|
1748
|
-
action: proxyEvent.action,
|
|
1749
|
-
domain: proxyEvent.domain,
|
|
1750
|
-
port: proxyEvent.port,
|
|
1751
|
-
reason: proxyEvent.reason
|
|
1752
|
-
});
|
|
1753
|
-
return;
|
|
1754
|
-
}
|
|
1755
|
-
if (event.type === "completeReasoning") {
|
|
1756
|
-
const reasoningEvent = event;
|
|
1757
|
-
addLog({
|
|
1758
|
-
id: `completeReasoning-${event.id}`,
|
|
1759
|
-
type: "completeReasoning",
|
|
1760
|
-
text: reasoningEvent.text
|
|
1761
|
-
});
|
|
1762
|
-
state.isReasoningStreaming = false;
|
|
1763
|
-
state.streamingReasoning = void 0;
|
|
1764
|
-
return;
|
|
1765
|
-
}
|
|
1766
|
-
if (event.type === "retry") {
|
|
1767
|
-
const retryEvent = event;
|
|
1768
|
-
addLog({
|
|
1769
|
-
id: `retry-${event.id}`,
|
|
1770
|
-
type: "retry",
|
|
1771
|
-
reason: retryEvent.reason
|
|
1772
|
-
});
|
|
1773
|
-
state.streamingText = void 0;
|
|
1774
|
-
state.streamingReasoning = void 0;
|
|
1775
|
-
return;
|
|
1776
|
-
}
|
|
1777
|
-
if (event.type === "initializeRuntime") {
|
|
1778
|
-
if (!state.rootRunId) {
|
|
1779
|
-
state.rootRunId = runId;
|
|
1780
|
-
} else if (runId !== state.rootRunId) {
|
|
1781
|
-
const expertName = event.expertName ?? "unknown";
|
|
1782
|
-
const runtime = formatRuntimeName(
|
|
1783
|
-
event.runtime ?? event.model?.split(":")[0] ?? "unknown"
|
|
1784
|
-
);
|
|
1785
|
-
const version = event.runtimeVersion ?? "unknown";
|
|
1786
|
-
const query = event.query;
|
|
1787
|
-
state.pendingDelegations.set(runId, { expertName, runtime, version, query });
|
|
1788
|
-
addLog({
|
|
1789
|
-
id: `delegation-started-${runId}`,
|
|
1790
|
-
type: "delegation-started",
|
|
1791
|
-
expertName,
|
|
1792
|
-
runtime,
|
|
1793
|
-
version,
|
|
1794
|
-
query
|
|
1795
|
-
});
|
|
1796
|
-
}
|
|
1797
|
-
return;
|
|
1798
|
-
}
|
|
1799
|
-
const isDelegation = state.rootRunId && runId !== state.rootRunId;
|
|
1800
|
-
if (event.type === "streamingText" && "text" in event) {
|
|
1801
|
-
if (!isDelegation) {
|
|
1802
|
-
state.streamingText = event.text;
|
|
1803
|
-
}
|
|
1804
|
-
return;
|
|
1805
|
-
}
|
|
1806
|
-
if (event.type === "completeRun") {
|
|
1807
|
-
if (isDelegation) {
|
|
1808
|
-
const pending = state.pendingDelegations.get(runId);
|
|
1809
|
-
if (pending) {
|
|
1810
|
-
addLog({
|
|
1811
|
-
id: `delegation-completed-${runId}`,
|
|
1812
|
-
type: "delegation-completed",
|
|
1813
|
-
expertName: pending.expertName,
|
|
1814
|
-
runtime: pending.runtime,
|
|
1815
|
-
version: pending.version,
|
|
1816
|
-
result: event.text
|
|
1817
|
-
});
|
|
1818
|
-
state.pendingDelegations.delete(runId);
|
|
1819
|
-
}
|
|
1820
|
-
} else if (!state.completionLogged) {
|
|
1821
|
-
const text = event.text || state.streamingText;
|
|
1822
|
-
if (text) {
|
|
1823
|
-
addLog({ id: `completion-${runId}`, type: "completion", text });
|
|
1824
|
-
}
|
|
1825
|
-
state.completionLogged = true;
|
|
1826
|
-
state.isComplete = true;
|
|
1827
|
-
state.streamingText = void 0;
|
|
1828
|
-
state.streamingReasoning = void 0;
|
|
1829
|
-
}
|
|
1830
|
-
return;
|
|
1475
|
+
renderItem: (cp, isSelected) => /* @__PURE__ */ jsxs(Text, { color: isSelected ? "cyan" : "gray", children: [
|
|
1476
|
+
isSelected ? ">" : " ",
|
|
1477
|
+
" Step ",
|
|
1478
|
+
cp.stepNumber,
|
|
1479
|
+
" (",
|
|
1480
|
+
cp.id,
|
|
1481
|
+
")"
|
|
1482
|
+
] }, cp.id)
|
|
1831
1483
|
}
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
errorName: errorEvent.error.name,
|
|
1838
|
-
message: errorEvent.error.message,
|
|
1839
|
-
statusCode: errorEvent.error.statusCode
|
|
1840
|
-
});
|
|
1841
|
-
state.isComplete = true;
|
|
1842
|
-
state.streamingText = void 0;
|
|
1843
|
-
state.streamingReasoning = void 0;
|
|
1844
|
-
return;
|
|
1845
|
-
}
|
|
1846
|
-
if (isDelegation) return;
|
|
1847
|
-
if (event.type === "startRun") {
|
|
1848
|
-
const query = extractQuery(event);
|
|
1849
|
-
if (query) {
|
|
1850
|
-
if (state.completionLogged) {
|
|
1851
|
-
state.completionLogged = false;
|
|
1852
|
-
state.isComplete = false;
|
|
1853
|
-
state.queryLogged = false;
|
|
1854
|
-
}
|
|
1855
|
-
if (!state.queryLogged) {
|
|
1856
|
-
addLog({ id: `query-${runId}`, type: "query", text: query });
|
|
1857
|
-
state.queryLogged = true;
|
|
1858
|
-
}
|
|
1859
|
-
}
|
|
1860
|
-
} else if (isToolCallsEvent(event)) {
|
|
1861
|
-
for (const toolCall of event.toolCalls) {
|
|
1862
|
-
if (!state.tools.has(toolCall.id)) {
|
|
1863
|
-
state.tools.set(toolCall.id, {
|
|
1864
|
-
id: toolCall.id,
|
|
1865
|
-
toolName: toolCall.toolName,
|
|
1866
|
-
args: toolCall.args,
|
|
1867
|
-
logged: false
|
|
1868
|
-
});
|
|
1869
|
-
}
|
|
1870
|
-
}
|
|
1871
|
-
} else if (isToolCallEvent(event)) {
|
|
1872
|
-
const { toolCall } = event;
|
|
1873
|
-
if (!state.tools.has(toolCall.id)) {
|
|
1874
|
-
state.tools.set(toolCall.id, {
|
|
1875
|
-
id: toolCall.id,
|
|
1876
|
-
toolName: toolCall.toolName,
|
|
1877
|
-
args: toolCall.args,
|
|
1878
|
-
logged: false
|
|
1879
|
-
});
|
|
1880
|
-
}
|
|
1881
|
-
} else if (isToolResultsEvent(event)) {
|
|
1882
|
-
for (const toolResult of event.toolResults) {
|
|
1883
|
-
const tool = state.tools.get(toolResult.id);
|
|
1884
|
-
if (tool && !tool.logged && Array.isArray(toolResult.result)) {
|
|
1885
|
-
tool.result = toolResult.result;
|
|
1886
|
-
tool.isSuccess = checkIsSuccess(toolResult.result);
|
|
1887
|
-
addLog({
|
|
1888
|
-
id: `tool-${tool.id}`,
|
|
1889
|
-
type: "tool",
|
|
1890
|
-
toolName: tool.toolName,
|
|
1891
|
-
args: tool.args,
|
|
1892
|
-
result: tool.result,
|
|
1893
|
-
isSuccess: tool.isSuccess
|
|
1894
|
-
});
|
|
1895
|
-
tool.logged = true;
|
|
1896
|
-
}
|
|
1897
|
-
}
|
|
1898
|
-
} else if (isToolResultEvent(event)) {
|
|
1899
|
-
const { toolResult } = event;
|
|
1900
|
-
const tool = state.tools.get(toolResult.id);
|
|
1901
|
-
if (tool && !tool.logged && Array.isArray(toolResult.result)) {
|
|
1902
|
-
tool.result = toolResult.result;
|
|
1903
|
-
tool.isSuccess = checkIsSuccess(toolResult.result);
|
|
1904
|
-
addLog({
|
|
1905
|
-
id: `tool-${tool.id}`,
|
|
1906
|
-
type: "tool",
|
|
1907
|
-
toolName: tool.toolName,
|
|
1908
|
-
args: tool.args,
|
|
1909
|
-
result: tool.result,
|
|
1910
|
-
isSuccess: tool.isSuccess
|
|
1911
|
-
});
|
|
1912
|
-
tool.logged = true;
|
|
1484
|
+
);
|
|
1485
|
+
var BrowsingEventDetailInput = ({ event, onBack }) => {
|
|
1486
|
+
useInput((input, key) => {
|
|
1487
|
+
if (input === "b" || key.escape) {
|
|
1488
|
+
onBack();
|
|
1913
1489
|
}
|
|
1914
|
-
}
|
|
1915
|
-
};
|
|
1916
|
-
var useEventStore = () => {
|
|
1917
|
-
const [events, setEvents] = useState([]);
|
|
1918
|
-
const [logs, setLogs] = useState([]);
|
|
1919
|
-
const [streamingText, setStreamingText] = useState();
|
|
1920
|
-
const [streamingReasoning, setStreamingReasoning] = useState();
|
|
1921
|
-
const [isComplete, setIsComplete] = useState(false);
|
|
1922
|
-
const stateRef = useRef({
|
|
1923
|
-
tools: /* @__PURE__ */ new Map(),
|
|
1924
|
-
pendingDelegations: /* @__PURE__ */ new Map(),
|
|
1925
|
-
queryLogged: false,
|
|
1926
|
-
completionLogged: false,
|
|
1927
|
-
isComplete: false
|
|
1928
1490
|
});
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
}
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
}
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
}
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
}
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
}, []);
|
|
1961
|
-
const setHistoricalEvents = useCallback((historicalEvents) => {
|
|
1962
|
-
needsRebuildRef.current = true;
|
|
1963
|
-
setEvents(
|
|
1964
|
-
historicalEvents.length > UI_CONSTANTS.MAX_EVENTS ? historicalEvents.slice(-1e3) : historicalEvents
|
|
1965
|
-
);
|
|
1966
|
-
}, []);
|
|
1967
|
-
useEffect(() => {
|
|
1968
|
-
if (needsRebuildRef.current) {
|
|
1969
|
-
stateRef.current = {
|
|
1970
|
-
tools: /* @__PURE__ */ new Map(),
|
|
1971
|
-
pendingDelegations: /* @__PURE__ */ new Map(),
|
|
1972
|
-
queryLogged: false,
|
|
1973
|
-
completionLogged: false,
|
|
1974
|
-
isComplete: false
|
|
1975
|
-
};
|
|
1976
|
-
setLogs([]);
|
|
1977
|
-
processedCountRef.current = 0;
|
|
1978
|
-
needsRebuildRef.current = false;
|
|
1979
|
-
}
|
|
1980
|
-
const newEvents = events.slice(processedCountRef.current);
|
|
1981
|
-
const newLogs = [];
|
|
1982
|
-
const addLog = (entry) => newLogs.push(entry);
|
|
1983
|
-
for (const event of newEvents) {
|
|
1984
|
-
processEventToLogs(stateRef.current, event, addLog);
|
|
1985
|
-
}
|
|
1986
|
-
processedCountRef.current = events.length;
|
|
1987
|
-
if (newLogs.length > 0) {
|
|
1988
|
-
setLogs((prev) => [...prev, ...newLogs]);
|
|
1989
|
-
}
|
|
1990
|
-
setStreamingText(stateRef.current.streamingText);
|
|
1991
|
-
setStreamingReasoning(stateRef.current.streamingReasoning);
|
|
1992
|
-
setIsComplete(stateRef.current.isComplete);
|
|
1993
|
-
}, [events]);
|
|
1994
|
-
return {
|
|
1995
|
-
logs,
|
|
1996
|
-
streamingText,
|
|
1997
|
-
streamingReasoning,
|
|
1998
|
-
isComplete,
|
|
1999
|
-
eventCount: events.length,
|
|
2000
|
-
addEvent,
|
|
2001
|
-
setHistoricalEvents
|
|
2002
|
-
};
|
|
1491
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 1, children: [
|
|
1492
|
+
/* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
|
|
1493
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: "Event Detail" }),
|
|
1494
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
1495
|
+
" ",
|
|
1496
|
+
KEY_HINTS.BACK
|
|
1497
|
+
] })
|
|
1498
|
+
] }),
|
|
1499
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginLeft: 2, children: [
|
|
1500
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
1501
|
+
/* @__PURE__ */ jsx(Text, { color: "gray", children: "Type: " }),
|
|
1502
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: event.type })
|
|
1503
|
+
] }),
|
|
1504
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
1505
|
+
/* @__PURE__ */ jsx(Text, { color: "gray", children: "Step: " }),
|
|
1506
|
+
/* @__PURE__ */ jsx(Text, { children: event.stepNumber })
|
|
1507
|
+
] }),
|
|
1508
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
1509
|
+
/* @__PURE__ */ jsx(Text, { color: "gray", children: "Timestamp: " }),
|
|
1510
|
+
/* @__PURE__ */ jsx(Text, { children: formatTimestamp2(event.timestamp) })
|
|
1511
|
+
] }),
|
|
1512
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
1513
|
+
/* @__PURE__ */ jsx(Text, { color: "gray", children: "ID: " }),
|
|
1514
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: event.id })
|
|
1515
|
+
] }),
|
|
1516
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
1517
|
+
/* @__PURE__ */ jsx(Text, { color: "gray", children: "Run ID: " }),
|
|
1518
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: event.runId })
|
|
1519
|
+
] })
|
|
1520
|
+
] })
|
|
1521
|
+
] });
|
|
2003
1522
|
};
|
|
2004
|
-
var
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
};
|
|
2028
|
-
case "RESUME_CHECKPOINT":
|
|
2029
|
-
return { type: "enteringQuery", expertName: action.expertKey };
|
|
2030
|
-
case "GO_BACK_FROM_EVENTS":
|
|
2031
|
-
return { type: "browsingCheckpoints", job: action.job, checkpoints: action.checkpoints };
|
|
2032
|
-
case "GO_BACK_FROM_CHECKPOINTS":
|
|
2033
|
-
return { type: "browsingHistory", jobs: action.historyJobs };
|
|
2034
|
-
case "SELECT_EVENT":
|
|
2035
|
-
return {
|
|
2036
|
-
type: "browsingEventDetail",
|
|
2037
|
-
checkpoint: action.checkpoint,
|
|
2038
|
-
events: action.events,
|
|
2039
|
-
selectedEvent: action.selectedEvent
|
|
2040
|
-
};
|
|
2041
|
-
case "GO_BACK_FROM_EVENT_DETAIL":
|
|
2042
|
-
return {
|
|
2043
|
-
type: "browsingEvents",
|
|
2044
|
-
checkpoint: action.checkpoint,
|
|
2045
|
-
events: action.events
|
|
2046
|
-
};
|
|
2047
|
-
default:
|
|
2048
|
-
return assertNever(action);
|
|
2049
|
-
}
|
|
2050
|
-
};
|
|
2051
|
-
var getInitialState = (options) => {
|
|
2052
|
-
if (options.showHistory && options.historyJobs) {
|
|
2053
|
-
return { type: "browsingHistory", jobs: options.historyJobs };
|
|
2054
|
-
}
|
|
2055
|
-
if (options.needsQueryInput) {
|
|
2056
|
-
return { type: "enteringQuery", expertName: options.initialExpertName || "" };
|
|
1523
|
+
var BrowsingEventsInput = ({
|
|
1524
|
+
checkpoint,
|
|
1525
|
+
events,
|
|
1526
|
+
onEventSelect,
|
|
1527
|
+
onBack
|
|
1528
|
+
}) => /* @__PURE__ */ jsx(
|
|
1529
|
+
ListBrowser,
|
|
1530
|
+
{
|
|
1531
|
+
title: `Events for Step ${checkpoint.stepNumber} ${KEY_HINTS.NAVIGATE} ${KEY_HINTS.SELECT} ${KEY_HINTS.BACK}`,
|
|
1532
|
+
items: events,
|
|
1533
|
+
onSelect: onEventSelect,
|
|
1534
|
+
onBack,
|
|
1535
|
+
emptyMessage: "No events found",
|
|
1536
|
+
renderItem: (ev, isSelected) => /* @__PURE__ */ jsxs(Text, { color: isSelected ? "cyan" : "gray", children: [
|
|
1537
|
+
isSelected ? ">" : " ",
|
|
1538
|
+
" [",
|
|
1539
|
+
ev.type,
|
|
1540
|
+
"] Step ",
|
|
1541
|
+
ev.stepNumber,
|
|
1542
|
+
" (",
|
|
1543
|
+
formatTimestamp2(ev.timestamp),
|
|
1544
|
+
")"
|
|
1545
|
+
] }, ev.id)
|
|
2057
1546
|
}
|
|
2058
|
-
|
|
2059
|
-
};
|
|
2060
|
-
var useInputState = (options) => {
|
|
2061
|
-
const [state, dispatch] = useReducer(inputReducer, options, getInitialState);
|
|
2062
|
-
return { state, dispatch };
|
|
2063
|
-
};
|
|
1547
|
+
);
|
|
2064
1548
|
var useRuntimeInfo = (options) => {
|
|
2065
1549
|
const [runtimeInfo, setRuntimeInfo] = useState({
|
|
2066
1550
|
status: "initializing",
|
|
@@ -2126,13 +1610,6 @@ var useRuntimeInfo = (options) => {
|
|
|
2126
1610
|
}));
|
|
2127
1611
|
return null;
|
|
2128
1612
|
}
|
|
2129
|
-
if (event.type === "streamingText") {
|
|
2130
|
-
setRuntimeInfo((prev) => ({
|
|
2131
|
-
...prev,
|
|
2132
|
-
streamingText: (prev.streamingText ?? "") + event.text
|
|
2133
|
-
}));
|
|
2134
|
-
return null;
|
|
2135
|
-
}
|
|
2136
1613
|
if ("stepNumber" in event) {
|
|
2137
1614
|
const isComplete = event.type === "completeRun";
|
|
2138
1615
|
const isStopped = STOP_EVENT_TYPES.includes(event.type);
|
|
@@ -2170,72 +1647,6 @@ var useRuntimeInfo = (options) => {
|
|
|
2170
1647
|
setContextWindowUsage
|
|
2171
1648
|
};
|
|
2172
1649
|
};
|
|
2173
|
-
var useTextInput = (options) => {
|
|
2174
|
-
const [input, setInput] = useState("");
|
|
2175
|
-
const inputRef = useLatestRef(input);
|
|
2176
|
-
const onSubmitRef = useLatestRef(options.onSubmit);
|
|
2177
|
-
const onCancelRef = useLatestRef(options.onCancel);
|
|
2178
|
-
const handleInput = useCallback(
|
|
2179
|
-
(inputChar, key) => {
|
|
2180
|
-
if (key.escape) {
|
|
2181
|
-
setInput("");
|
|
2182
|
-
onCancelRef.current?.();
|
|
2183
|
-
return;
|
|
2184
|
-
}
|
|
2185
|
-
if (key.return && inputRef.current.trim()) {
|
|
2186
|
-
onSubmitRef.current(inputRef.current.trim());
|
|
2187
|
-
setInput("");
|
|
2188
|
-
return;
|
|
2189
|
-
}
|
|
2190
|
-
if (key.backspace || key.delete) {
|
|
2191
|
-
setInput((prev) => prev.slice(0, -1));
|
|
2192
|
-
return;
|
|
2193
|
-
}
|
|
2194
|
-
if (!key.ctrl && !key.meta && inputChar) {
|
|
2195
|
-
setInput((prev) => prev + inputChar);
|
|
2196
|
-
}
|
|
2197
|
-
},
|
|
2198
|
-
[inputRef, onSubmitRef, onCancelRef]
|
|
2199
|
-
);
|
|
2200
|
-
const reset = useCallback(() => {
|
|
2201
|
-
setInput("");
|
|
2202
|
-
}, []);
|
|
2203
|
-
return { input, handleInput, reset };
|
|
2204
|
-
};
|
|
2205
|
-
var useListNavigation = (options) => {
|
|
2206
|
-
const { items, onSelect, onBack } = options;
|
|
2207
|
-
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
2208
|
-
useEffect(() => {
|
|
2209
|
-
if (selectedIndex >= items.length && items.length > 0) {
|
|
2210
|
-
setSelectedIndex(items.length - 1);
|
|
2211
|
-
}
|
|
2212
|
-
}, [items.length, selectedIndex]);
|
|
2213
|
-
const handleNavigation = useCallback(
|
|
2214
|
-
(inputChar, key) => {
|
|
2215
|
-
if (key.upArrow && items.length > 0) {
|
|
2216
|
-
setSelectedIndex((prev) => Math.max(0, prev - 1));
|
|
2217
|
-
return true;
|
|
2218
|
-
}
|
|
2219
|
-
if (key.downArrow && items.length > 0) {
|
|
2220
|
-
setSelectedIndex((prev) => Math.min(items.length - 1, prev + 1));
|
|
2221
|
-
return true;
|
|
2222
|
-
}
|
|
2223
|
-
if (key.return && items[selectedIndex]) {
|
|
2224
|
-
onSelect?.(items[selectedIndex]);
|
|
2225
|
-
return true;
|
|
2226
|
-
}
|
|
2227
|
-
if ((key.escape || inputChar === "b") && onBack) {
|
|
2228
|
-
onBack();
|
|
2229
|
-
return true;
|
|
2230
|
-
}
|
|
2231
|
-
return false;
|
|
2232
|
-
},
|
|
2233
|
-
[items, selectedIndex, onSelect, onBack]
|
|
2234
|
-
);
|
|
2235
|
-
return { selectedIndex, handleNavigation };
|
|
2236
|
-
};
|
|
2237
|
-
|
|
2238
|
-
// src/tui/hooks/ui/use-expert-selector.ts
|
|
2239
1650
|
var useExpertSelector = (options) => {
|
|
2240
1651
|
const { experts, onExpertSelect, extraKeyHandler } = options;
|
|
2241
1652
|
const [inputMode, setInputMode] = useState(false);
|
|
@@ -2272,321 +1683,162 @@ var useExpertSelector = (options) => {
|
|
|
2272
1683
|
handleKeyInput
|
|
2273
1684
|
};
|
|
2274
1685
|
};
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
}
|
|
2302
|
-
const
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
}
|
|
2320
|
-
|
|
2321
|
-
if (
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
onEventSelect: history.handleEventSelect,
|
|
2363
|
-
onBack: handleBack,
|
|
2364
|
-
onSwitchToExperts: history.handleSwitchToExperts,
|
|
2365
|
-
onSwitchToHistory: history.handleSwitchToHistory
|
|
2366
|
-
}),
|
|
2367
|
-
[
|
|
2368
|
-
handleExpertSelect,
|
|
2369
|
-
handleQuerySubmit,
|
|
2370
|
-
history.handleJobSelect,
|
|
2371
|
-
history.handleJobResume,
|
|
2372
|
-
history.handleCheckpointSelect,
|
|
2373
|
-
history.handleCheckpointResume,
|
|
2374
|
-
history.handleEventSelect,
|
|
2375
|
-
handleBack,
|
|
2376
|
-
history.handleSwitchToExperts,
|
|
2377
|
-
history.handleSwitchToHistory
|
|
2378
|
-
]
|
|
2379
|
-
);
|
|
1686
|
+
function isBaseStep(step) {
|
|
1687
|
+
if (typeof step !== "object" || step === null) return false;
|
|
1688
|
+
const stepType = step.type;
|
|
1689
|
+
return stepType === "selectExpert" || stepType === "loadingVersions" || stepType === "selectVersion" || stepType === "error";
|
|
1690
|
+
}
|
|
1691
|
+
function useExpertVersionWizard({
|
|
1692
|
+
experts,
|
|
1693
|
+
onFetchVersions,
|
|
1694
|
+
customStepFromVersion
|
|
1695
|
+
}) {
|
|
1696
|
+
const [step, setStep] = useState({ type: "selectExpert" });
|
|
1697
|
+
const handleExpertSelect = async (expertName) => {
|
|
1698
|
+
setStep({ type: "loadingVersions", expertName });
|
|
1699
|
+
try {
|
|
1700
|
+
const versions = await onFetchVersions(expertName);
|
|
1701
|
+
if (versions.length === 0) {
|
|
1702
|
+
setStep({ type: "error", message: `No versions found for ${expertName}` });
|
|
1703
|
+
return;
|
|
1704
|
+
}
|
|
1705
|
+
setStep({ type: "selectVersion", expertName, versions });
|
|
1706
|
+
} catch (error) {
|
|
1707
|
+
setStep({
|
|
1708
|
+
type: "error",
|
|
1709
|
+
message: error instanceof Error ? error.message : "Failed to fetch versions"
|
|
1710
|
+
});
|
|
1711
|
+
}
|
|
1712
|
+
};
|
|
1713
|
+
const handleVersionSelect = (version) => {
|
|
1714
|
+
const customStep = customStepFromVersion(version);
|
|
1715
|
+
setStep(customStep);
|
|
1716
|
+
};
|
|
1717
|
+
const handleBack = (customBackHandler) => {
|
|
1718
|
+
if (isBaseStep(step)) {
|
|
1719
|
+
switch (step.type) {
|
|
1720
|
+
case "selectVersion":
|
|
1721
|
+
setStep({ type: "selectExpert" });
|
|
1722
|
+
break;
|
|
1723
|
+
case "error":
|
|
1724
|
+
setStep({ type: "selectExpert" });
|
|
1725
|
+
break;
|
|
1726
|
+
}
|
|
1727
|
+
} else if (customBackHandler) {
|
|
1728
|
+
customBackHandler(step);
|
|
1729
|
+
}
|
|
1730
|
+
};
|
|
1731
|
+
const renderBaseStep = (options) => {
|
|
1732
|
+
if (!isBaseStep(step)) {
|
|
1733
|
+
return null;
|
|
1734
|
+
}
|
|
1735
|
+
switch (step.type) {
|
|
1736
|
+
case "selectExpert":
|
|
1737
|
+
return /* @__PURE__ */ jsx(
|
|
1738
|
+
WizardExpertSelector,
|
|
1739
|
+
{
|
|
1740
|
+
title: options?.title ?? "Select an Expert:",
|
|
1741
|
+
experts,
|
|
1742
|
+
onSelect: handleExpertSelect
|
|
1743
|
+
}
|
|
1744
|
+
);
|
|
1745
|
+
case "loadingVersions":
|
|
1746
|
+
return /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { children: [
|
|
1747
|
+
"Loading versions for ",
|
|
1748
|
+
step.expertName,
|
|
1749
|
+
"..."
|
|
1750
|
+
] }) });
|
|
1751
|
+
case "selectVersion":
|
|
1752
|
+
return /* @__PURE__ */ jsx(
|
|
1753
|
+
VersionSelector,
|
|
1754
|
+
{
|
|
1755
|
+
expertName: step.expertName,
|
|
1756
|
+
versions: step.versions,
|
|
1757
|
+
onSelect: handleVersionSelect,
|
|
1758
|
+
onBack: handleBack,
|
|
1759
|
+
title: options?.versionSelectorTitle
|
|
1760
|
+
}
|
|
1761
|
+
);
|
|
1762
|
+
case "error":
|
|
1763
|
+
return /* @__PURE__ */ jsx(ErrorStep, { message: step.message, onBack: handleBack });
|
|
1764
|
+
default:
|
|
1765
|
+
return null;
|
|
1766
|
+
}
|
|
1767
|
+
};
|
|
1768
|
+
const handlers = {
|
|
1769
|
+
handleExpertSelect,
|
|
1770
|
+
handleVersionSelect,
|
|
1771
|
+
handleBack
|
|
1772
|
+
};
|
|
2380
1773
|
return {
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
1774
|
+
step,
|
|
1775
|
+
setStep,
|
|
1776
|
+
handlers,
|
|
1777
|
+
renderBaseStep,
|
|
1778
|
+
isBaseStep: isBaseStep(step)
|
|
2385
1779
|
};
|
|
1780
|
+
}
|
|
1781
|
+
var ExpertList = ({
|
|
1782
|
+
experts,
|
|
1783
|
+
selectedIndex,
|
|
1784
|
+
showSource = false,
|
|
1785
|
+
inline = false,
|
|
1786
|
+
maxItems
|
|
1787
|
+
}) => {
|
|
1788
|
+
const displayExperts = maxItems ? experts.slice(0, maxItems) : experts;
|
|
1789
|
+
if (displayExperts.length === 0) {
|
|
1790
|
+
return /* @__PURE__ */ jsx(Text, { color: "gray", children: "No experts found." });
|
|
1791
|
+
}
|
|
1792
|
+
const items = displayExperts.map((expert, index) => /* @__PURE__ */ jsxs(Text, { color: index === selectedIndex ? "cyan" : "gray", children: [
|
|
1793
|
+
index === selectedIndex ? ">" : " ",
|
|
1794
|
+
" ",
|
|
1795
|
+
showSource ? expert.key : expert.name,
|
|
1796
|
+
showSource && expert.source && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1797
|
+
" ",
|
|
1798
|
+
/* @__PURE__ */ jsxs(Text, { color: expert.source === "configured" ? "green" : "yellow", children: [
|
|
1799
|
+
"[",
|
|
1800
|
+
expert.source === "configured" ? "config" : "recent",
|
|
1801
|
+
"]"
|
|
1802
|
+
] })
|
|
1803
|
+
] }),
|
|
1804
|
+
inline ? " " : ""
|
|
1805
|
+
] }, expert.key));
|
|
1806
|
+
return inline ? /* @__PURE__ */ jsx(Box, { children: items }) : /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: items });
|
|
2386
1807
|
};
|
|
2387
|
-
var
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
maxItems = UI_CONSTANTS.MAX_VISIBLE_LIST_ITEMS
|
|
1808
|
+
var ExpertSelectorBase = ({
|
|
1809
|
+
experts,
|
|
1810
|
+
hint,
|
|
1811
|
+
onExpertSelect,
|
|
1812
|
+
showSource = false,
|
|
1813
|
+
inline = false,
|
|
1814
|
+
maxItems = UI_CONSTANTS.MAX_VISIBLE_LIST_ITEMS,
|
|
1815
|
+
extraKeyHandler
|
|
2396
1816
|
}) => {
|
|
2397
|
-
const { selectedIndex,
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
});
|
|
2402
|
-
useInput((inputChar, key) => {
|
|
2403
|
-
if (extraKeyHandler?.(inputChar, key, items[selectedIndex])) return;
|
|
2404
|
-
handleNavigation(inputChar, key);
|
|
1817
|
+
const { inputMode, input, selectedIndex, handleKeyInput } = useExpertSelector({
|
|
1818
|
+
experts,
|
|
1819
|
+
onExpertSelect,
|
|
1820
|
+
extraKeyHandler
|
|
2405
1821
|
});
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
"(",
|
|
2421
|
-
selectedIndex + 1,
|
|
2422
|
-
"/",
|
|
2423
|
-
items.length,
|
|
2424
|
-
")"
|
|
2425
|
-
] })
|
|
1822
|
+
useInput(handleKeyInput);
|
|
1823
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: inline ? "row" : "column", children: [
|
|
1824
|
+
!inputMode && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
1825
|
+
/* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Text, { color: "cyan", children: hint }) }),
|
|
1826
|
+
/* @__PURE__ */ jsx(
|
|
1827
|
+
ExpertList,
|
|
1828
|
+
{
|
|
1829
|
+
experts,
|
|
1830
|
+
selectedIndex,
|
|
1831
|
+
showSource,
|
|
1832
|
+
inline,
|
|
1833
|
+
maxItems
|
|
1834
|
+
}
|
|
1835
|
+
)
|
|
2426
1836
|
] }),
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
hasMoreBelow && /* @__PURE__ */ jsx(Text, { color: "gray", children: INDICATOR.ELLIPSIS })
|
|
2433
|
-
] });
|
|
2434
|
-
};
|
|
2435
|
-
var BrowsingCheckpointsInput = ({
|
|
2436
|
-
job,
|
|
2437
|
-
checkpoints,
|
|
2438
|
-
onCheckpointSelect,
|
|
2439
|
-
onCheckpointResume,
|
|
2440
|
-
onBack
|
|
2441
|
-
}) => /* @__PURE__ */ jsx(
|
|
2442
|
-
ListBrowser,
|
|
2443
|
-
{
|
|
2444
|
-
title: `Checkpoints for ${job.expertKey} ${KEY_HINTS.NAVIGATE} ${KEY_HINTS.RESUME} ${KEY_HINTS.EVENTS} ${KEY_HINTS.BACK}`,
|
|
2445
|
-
items: checkpoints,
|
|
2446
|
-
onSelect: onCheckpointResume,
|
|
2447
|
-
onBack,
|
|
2448
|
-
emptyMessage: "No checkpoints found",
|
|
2449
|
-
extraKeyHandler: (char, _key, selected) => {
|
|
2450
|
-
if (char === "e" && selected) {
|
|
2451
|
-
onCheckpointSelect(selected);
|
|
2452
|
-
return true;
|
|
2453
|
-
}
|
|
2454
|
-
return false;
|
|
2455
|
-
},
|
|
2456
|
-
renderItem: (cp, isSelected) => /* @__PURE__ */ jsxs(Text, { color: isSelected ? "cyan" : "gray", children: [
|
|
2457
|
-
isSelected ? ">" : " ",
|
|
2458
|
-
" Step ",
|
|
2459
|
-
cp.stepNumber,
|
|
2460
|
-
" (",
|
|
2461
|
-
cp.id,
|
|
2462
|
-
")"
|
|
2463
|
-
] }, cp.id)
|
|
2464
|
-
}
|
|
2465
|
-
);
|
|
2466
|
-
var BrowsingEventDetailInput = ({ event, onBack }) => {
|
|
2467
|
-
useInput((input, key) => {
|
|
2468
|
-
if (input === "b" || key.escape) {
|
|
2469
|
-
onBack();
|
|
2470
|
-
}
|
|
2471
|
-
});
|
|
2472
|
-
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 1, children: [
|
|
2473
|
-
/* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
|
|
2474
|
-
/* @__PURE__ */ jsx(Text, { bold: true, children: "Event Detail" }),
|
|
2475
|
-
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2476
|
-
" ",
|
|
2477
|
-
KEY_HINTS.BACK
|
|
2478
|
-
] })
|
|
2479
|
-
] }),
|
|
2480
|
-
/* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginLeft: 2, children: [
|
|
2481
|
-
/* @__PURE__ */ jsxs(Text, { children: [
|
|
2482
|
-
/* @__PURE__ */ jsx(Text, { color: "gray", children: "Type: " }),
|
|
2483
|
-
/* @__PURE__ */ jsx(Text, { color: "cyan", children: event.type })
|
|
2484
|
-
] }),
|
|
2485
|
-
/* @__PURE__ */ jsxs(Text, { children: [
|
|
2486
|
-
/* @__PURE__ */ jsx(Text, { color: "gray", children: "Step: " }),
|
|
2487
|
-
/* @__PURE__ */ jsx(Text, { children: event.stepNumber })
|
|
2488
|
-
] }),
|
|
2489
|
-
/* @__PURE__ */ jsxs(Text, { children: [
|
|
2490
|
-
/* @__PURE__ */ jsx(Text, { color: "gray", children: "Timestamp: " }),
|
|
2491
|
-
/* @__PURE__ */ jsx(Text, { children: formatTimestamp2(event.timestamp) })
|
|
2492
|
-
] }),
|
|
2493
|
-
/* @__PURE__ */ jsxs(Text, { children: [
|
|
2494
|
-
/* @__PURE__ */ jsx(Text, { color: "gray", children: "ID: " }),
|
|
2495
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: event.id })
|
|
2496
|
-
] }),
|
|
2497
|
-
/* @__PURE__ */ jsxs(Text, { children: [
|
|
2498
|
-
/* @__PURE__ */ jsx(Text, { color: "gray", children: "Run ID: " }),
|
|
2499
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: event.runId })
|
|
2500
|
-
] })
|
|
2501
|
-
] })
|
|
2502
|
-
] });
|
|
2503
|
-
};
|
|
2504
|
-
var BrowsingEventsInput = ({
|
|
2505
|
-
checkpoint,
|
|
2506
|
-
events,
|
|
2507
|
-
onEventSelect,
|
|
2508
|
-
onBack
|
|
2509
|
-
}) => /* @__PURE__ */ jsx(
|
|
2510
|
-
ListBrowser,
|
|
2511
|
-
{
|
|
2512
|
-
title: `Events for Step ${checkpoint.stepNumber} ${KEY_HINTS.NAVIGATE} ${KEY_HINTS.SELECT} ${KEY_HINTS.BACK}`,
|
|
2513
|
-
items: events,
|
|
2514
|
-
onSelect: onEventSelect,
|
|
2515
|
-
onBack,
|
|
2516
|
-
emptyMessage: "No events found",
|
|
2517
|
-
renderItem: (ev, isSelected) => /* @__PURE__ */ jsxs(Text, { color: isSelected ? "cyan" : "gray", children: [
|
|
2518
|
-
isSelected ? ">" : " ",
|
|
2519
|
-
" [",
|
|
2520
|
-
ev.type,
|
|
2521
|
-
"] Step ",
|
|
2522
|
-
ev.stepNumber,
|
|
2523
|
-
" (",
|
|
2524
|
-
formatTimestamp2(ev.timestamp),
|
|
2525
|
-
")"
|
|
2526
|
-
] }, ev.id)
|
|
2527
|
-
}
|
|
2528
|
-
);
|
|
2529
|
-
var ExpertList = ({
|
|
2530
|
-
experts,
|
|
2531
|
-
selectedIndex,
|
|
2532
|
-
showSource = false,
|
|
2533
|
-
inline = false,
|
|
2534
|
-
maxItems
|
|
2535
|
-
}) => {
|
|
2536
|
-
const displayExperts = maxItems ? experts.slice(0, maxItems) : experts;
|
|
2537
|
-
if (displayExperts.length === 0) {
|
|
2538
|
-
return /* @__PURE__ */ jsx(Text, { color: "gray", children: "No experts found." });
|
|
2539
|
-
}
|
|
2540
|
-
const items = displayExperts.map((expert, index) => /* @__PURE__ */ jsxs(Text, { color: index === selectedIndex ? "cyan" : "gray", children: [
|
|
2541
|
-
index === selectedIndex ? ">" : " ",
|
|
2542
|
-
" ",
|
|
2543
|
-
showSource ? expert.key : expert.name,
|
|
2544
|
-
showSource && expert.source && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2545
|
-
" ",
|
|
2546
|
-
/* @__PURE__ */ jsxs(Text, { color: expert.source === "configured" ? "green" : "yellow", children: [
|
|
2547
|
-
"[",
|
|
2548
|
-
expert.source === "configured" ? "config" : "recent",
|
|
2549
|
-
"]"
|
|
2550
|
-
] })
|
|
2551
|
-
] }),
|
|
2552
|
-
inline ? " " : ""
|
|
2553
|
-
] }, expert.key));
|
|
2554
|
-
return inline ? /* @__PURE__ */ jsx(Box, { children: items }) : /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: items });
|
|
2555
|
-
};
|
|
2556
|
-
var ExpertSelectorBase = ({
|
|
2557
|
-
experts,
|
|
2558
|
-
hint,
|
|
2559
|
-
onExpertSelect,
|
|
2560
|
-
showSource = false,
|
|
2561
|
-
inline = false,
|
|
2562
|
-
maxItems = UI_CONSTANTS.MAX_VISIBLE_LIST_ITEMS,
|
|
2563
|
-
extraKeyHandler
|
|
2564
|
-
}) => {
|
|
2565
|
-
const { inputMode, input, selectedIndex, handleKeyInput } = useExpertSelector({
|
|
2566
|
-
experts,
|
|
2567
|
-
onExpertSelect,
|
|
2568
|
-
extraKeyHandler
|
|
2569
|
-
});
|
|
2570
|
-
useInput(handleKeyInput);
|
|
2571
|
-
return /* @__PURE__ */ jsxs(Box, { flexDirection: inline ? "row" : "column", children: [
|
|
2572
|
-
!inputMode && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
2573
|
-
/* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Text, { color: "cyan", children: hint }) }),
|
|
2574
|
-
/* @__PURE__ */ jsx(
|
|
2575
|
-
ExpertList,
|
|
2576
|
-
{
|
|
2577
|
-
experts,
|
|
2578
|
-
selectedIndex,
|
|
2579
|
-
showSource,
|
|
2580
|
-
inline,
|
|
2581
|
-
maxItems
|
|
2582
|
-
}
|
|
2583
|
-
)
|
|
2584
|
-
] }),
|
|
2585
|
-
inputMode && /* @__PURE__ */ jsxs(Box, { children: [
|
|
2586
|
-
/* @__PURE__ */ jsx(Text, { color: "gray", children: "Expert: " }),
|
|
2587
|
-
/* @__PURE__ */ jsx(Text, { color: "white", children: input }),
|
|
2588
|
-
/* @__PURE__ */ jsx(Text, { color: "cyan", children: "_" })
|
|
2589
|
-
] })
|
|
1837
|
+
inputMode && /* @__PURE__ */ jsxs(Box, { children: [
|
|
1838
|
+
/* @__PURE__ */ jsx(Text, { color: "gray", children: "Expert: " }),
|
|
1839
|
+
/* @__PURE__ */ jsx(Text, { color: "white", children: input }),
|
|
1840
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: "_" })
|
|
1841
|
+
] })
|
|
2590
1842
|
] });
|
|
2591
1843
|
};
|
|
2592
1844
|
var BrowsingExpertsInput = ({
|
|
@@ -2654,7 +1906,7 @@ var BrowsingHistoryInput = ({
|
|
|
2654
1906
|
] }, job.jobId)
|
|
2655
1907
|
}
|
|
2656
1908
|
);
|
|
2657
|
-
var BrowserRouter = ({ inputState }) => {
|
|
1909
|
+
var BrowserRouter = ({ inputState, showEventsHint = true }) => {
|
|
2658
1910
|
const ctx = useInputAreaContext();
|
|
2659
1911
|
const handleEventSelect = useCallback(
|
|
2660
1912
|
(event) => {
|
|
@@ -2692,7 +1944,8 @@ var BrowserRouter = ({ inputState }) => {
|
|
|
2692
1944
|
checkpoints: inputState.checkpoints,
|
|
2693
1945
|
onCheckpointSelect: ctx.onCheckpointSelect,
|
|
2694
1946
|
onCheckpointResume: ctx.onCheckpointResume,
|
|
2695
|
-
onBack: ctx.onBack
|
|
1947
|
+
onBack: ctx.onBack,
|
|
1948
|
+
showEventsHint
|
|
2696
1949
|
}
|
|
2697
1950
|
);
|
|
2698
1951
|
case "browsingEvents":
|
|
@@ -2711,256 +1964,180 @@ var BrowserRouter = ({ inputState }) => {
|
|
|
2711
1964
|
return assertNever(inputState);
|
|
2712
1965
|
}
|
|
2713
1966
|
};
|
|
2714
|
-
|
|
2715
|
-
|
|
1967
|
+
var ActionRowSimple = ({
|
|
1968
|
+
indicatorColor,
|
|
1969
|
+
text,
|
|
1970
|
+
textDimColor = false
|
|
1971
|
+
}) => /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: /* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
|
|
1972
|
+
/* @__PURE__ */ jsx(Box, { paddingRight: 1, children: /* @__PURE__ */ jsx(Text, { color: indicatorColor, children: INDICATOR.BULLET }) }),
|
|
1973
|
+
/* @__PURE__ */ jsx(Text, { color: "white", dimColor: textDimColor, children: text })
|
|
1974
|
+
] }) });
|
|
1975
|
+
var ActionRow = ({ indicatorColor, label, summary, children }) => /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
1976
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
1977
|
+
/* @__PURE__ */ jsx(Text, { color: indicatorColor, children: INDICATOR.BULLET }),
|
|
1978
|
+
/* @__PURE__ */ jsx(Text, { color: "white", children: label }),
|
|
1979
|
+
summary && /* @__PURE__ */ jsx(Text, { color: "white", dimColor: true, children: summary })
|
|
1980
|
+
] }),
|
|
1981
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
|
|
1982
|
+
/* @__PURE__ */ jsx(Box, { paddingRight: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: INDICATOR.TREE }) }),
|
|
1983
|
+
children
|
|
1984
|
+
] })
|
|
1985
|
+
] });
|
|
1986
|
+
var CheckpointActionRow = ({ action }) => {
|
|
1987
|
+
if (action.type === "parallelGroup") {
|
|
1988
|
+
return renderParallelGroup(action);
|
|
1989
|
+
}
|
|
1990
|
+
const actionElement = renderAction(action);
|
|
1991
|
+
if (!actionElement) return null;
|
|
2716
1992
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
message
|
|
2720
|
-
] }),
|
|
2721
|
-
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Press any key to go back" }) })
|
|
1993
|
+
action.reasoning && renderReasoning(action.reasoning),
|
|
1994
|
+
actionElement
|
|
2722
1995
|
] });
|
|
2723
|
-
}
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
}
|
|
2731
|
-
const { input, handleInput } = useTextInput({
|
|
2732
|
-
onSubmit: onQuerySubmit ?? (() => {
|
|
1996
|
+
};
|
|
1997
|
+
function renderParallelGroup(group) {
|
|
1998
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
1999
|
+
group.reasoning && renderReasoning(group.reasoning),
|
|
2000
|
+
group.activities.map((activity, index) => {
|
|
2001
|
+
const actionElement = renderAction(activity);
|
|
2002
|
+
if (!actionElement) return null;
|
|
2003
|
+
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: actionElement }, activity.id || `${activity.type}-${index}`);
|
|
2733
2004
|
})
|
|
2734
|
-
});
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
const skills = info.activeSkills.length > 0 ? info.activeSkills.join(", ") : "";
|
|
2738
|
-
const step = info.currentStep !== void 0 ? String(info.currentStep) : "";
|
|
2739
|
-
const usagePercent = (info.contextWindowUsage * 100).toFixed(1);
|
|
2740
|
-
return /* @__PURE__ */ jsxs(
|
|
2741
|
-
Box,
|
|
2742
|
-
{
|
|
2743
|
-
flexDirection: "column",
|
|
2744
|
-
borderStyle: "single",
|
|
2745
|
-
borderColor: "gray",
|
|
2746
|
-
borderTop: true,
|
|
2747
|
-
borderBottom: false,
|
|
2748
|
-
borderLeft: false,
|
|
2749
|
-
borderRight: false,
|
|
2750
|
-
children: [
|
|
2751
|
-
/* @__PURE__ */ jsxs(Text, { children: [
|
|
2752
|
-
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: info.runtime === "local" ? "Local" : info.runtime === "claude-code" ? "Claude Code" : (info.runtime ?? "docker").charAt(0).toUpperCase() + (info.runtime ?? "docker").slice(1) }),
|
|
2753
|
-
info.runtime === "docker" || !info.runtime ? /* @__PURE__ */ jsxs(Text, { color: info.dockerState === "building" ? "yellow" : "gray", children: [
|
|
2754
|
-
" ",
|
|
2755
|
-
"(",
|
|
2756
|
-
info.dockerState ?? "initializing",
|
|
2757
|
-
")"
|
|
2758
|
-
] }) : info.runtimeVersion && /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
|
|
2759
|
-
" ",
|
|
2760
|
-
"(",
|
|
2761
|
-
info.runtime === "local" ? `v${info.runtimeVersion}` : info.runtimeVersion,
|
|
2762
|
-
")"
|
|
2763
|
-
] })
|
|
2764
|
-
] }),
|
|
2765
|
-
/* @__PURE__ */ jsxs(Text, { children: [
|
|
2766
|
-
/* @__PURE__ */ jsx(Text, { color: "gray", children: "Expert: " }),
|
|
2767
|
-
/* @__PURE__ */ jsx(Text, { color: "white", children: displayExpertName }),
|
|
2768
|
-
/* @__PURE__ */ jsx(Text, { color: "gray", children: " / Skills: " }),
|
|
2769
|
-
/* @__PURE__ */ jsx(Text, { color: "green", children: skills })
|
|
2770
|
-
] }),
|
|
2771
|
-
/* @__PURE__ */ jsxs(Text, { children: [
|
|
2772
|
-
/* @__PURE__ */ jsx(Text, { color: "gray", children: "Status: " }),
|
|
2773
|
-
/* @__PURE__ */ jsx(
|
|
2774
|
-
Text,
|
|
2775
|
-
{
|
|
2776
|
-
color: info.status === "running" ? "green" : info.status === "completed" ? "cyan" : "yellow",
|
|
2777
|
-
children: info.status
|
|
2778
|
-
}
|
|
2779
|
-
),
|
|
2780
|
-
/* @__PURE__ */ jsx(Text, { color: "gray", children: " / Step: " }),
|
|
2781
|
-
/* @__PURE__ */ jsx(Text, { color: "white", children: step }),
|
|
2782
|
-
/* @__PURE__ */ jsx(Text, { color: "gray", children: " / Events: " }),
|
|
2783
|
-
/* @__PURE__ */ jsx(Text, { color: "white", children: eventCount }),
|
|
2784
|
-
/* @__PURE__ */ jsx(Text, { color: "gray", children: " / Usage: " }),
|
|
2785
|
-
/* @__PURE__ */ jsxs(Text, { color: "white", children: [
|
|
2786
|
-
usagePercent,
|
|
2787
|
-
"%"
|
|
2788
|
-
] })
|
|
2789
|
-
] }),
|
|
2790
|
-
/* @__PURE__ */ jsxs(Text, { children: [
|
|
2791
|
-
/* @__PURE__ */ jsx(Text, { color: "gray", children: "Model: " }),
|
|
2792
|
-
/* @__PURE__ */ jsx(Text, { color: "white", children: info.model })
|
|
2793
|
-
] }),
|
|
2794
|
-
/* @__PURE__ */ jsxs(Box, { children: [
|
|
2795
|
-
/* @__PURE__ */ jsx(Text, { color: "gray", children: "Query: " }),
|
|
2796
|
-
isEditing ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2797
|
-
/* @__PURE__ */ jsx(Text, { color: "white", children: input }),
|
|
2798
|
-
/* @__PURE__ */ jsx(Text, { color: "cyan", children: "_" })
|
|
2799
|
-
] }) : /* @__PURE__ */ jsx(Text, { color: "white", children: info.query })
|
|
2800
|
-
] })
|
|
2801
|
-
]
|
|
2802
|
-
}
|
|
2803
|
-
);
|
|
2804
|
-
};
|
|
2805
|
-
var QueryRow = ({ text }) => /* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
|
|
2806
|
-
/* @__PURE__ */ jsx(Box, { paddingRight: 1, children: /* @__PURE__ */ jsx(Text, { color: "cyan", children: INDICATOR.CHEVRON_RIGHT }) }),
|
|
2807
|
-
/* @__PURE__ */ jsx(Text, { color: "cyan", children: text })
|
|
2808
|
-
] });
|
|
2809
|
-
var CompletionRow = ({ text }) => /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
2810
|
-
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
2811
|
-
/* @__PURE__ */ jsx(Text, { color: "white", children: INDICATOR.BULLET }),
|
|
2812
|
-
/* @__PURE__ */ jsx(Text, { color: "white", children: "Run Results" })
|
|
2813
|
-
] }),
|
|
2814
|
-
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
|
|
2815
|
-
/* @__PURE__ */ jsx(Box, { paddingRight: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: INDICATOR.TREE }) }),
|
|
2816
|
-
/* @__PURE__ */ jsx(Text, { color: "white", children: text })
|
|
2817
|
-
] })
|
|
2818
|
-
] });
|
|
2819
|
-
var ErrorRow = ({ errorName, message, statusCode }) => /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
2820
|
-
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
2821
|
-
/* @__PURE__ */ jsx(Text, { color: "red", children: INDICATOR.BULLET }),
|
|
2822
|
-
/* @__PURE__ */ jsxs(Text, { color: "red", bold: true, children: [
|
|
2823
|
-
"Error: ",
|
|
2824
|
-
errorName,
|
|
2825
|
-
statusCode ? ` (${statusCode})` : ""
|
|
2826
|
-
] })
|
|
2827
|
-
] }),
|
|
2828
|
-
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
|
|
2829
|
-
/* @__PURE__ */ jsx(Box, { paddingRight: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: INDICATOR.TREE }) }),
|
|
2830
|
-
/* @__PURE__ */ jsx(Text, { color: "red", children: message })
|
|
2831
|
-
] })
|
|
2832
|
-
] });
|
|
2833
|
-
var ActionRowSimple = ({
|
|
2834
|
-
indicatorColor,
|
|
2835
|
-
text,
|
|
2836
|
-
textDimColor = false
|
|
2837
|
-
}) => /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: /* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
|
|
2838
|
-
/* @__PURE__ */ jsx(Box, { paddingRight: 1, children: /* @__PURE__ */ jsx(Text, { color: indicatorColor, children: INDICATOR.BULLET }) }),
|
|
2839
|
-
/* @__PURE__ */ jsx(Text, { color: "white", dimColor: textDimColor, children: text })
|
|
2840
|
-
] }) });
|
|
2841
|
-
var ActionRow = ({ indicatorColor, label, summary, children }) => /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
2842
|
-
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
2843
|
-
/* @__PURE__ */ jsx(Text, { color: indicatorColor, children: INDICATOR.BULLET }),
|
|
2844
|
-
/* @__PURE__ */ jsx(Text, { color: "white", children: label }),
|
|
2845
|
-
summary && /* @__PURE__ */ jsx(Text, { color: "white", dimColor: true, children: summary })
|
|
2846
|
-
] }),
|
|
2847
|
-
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
|
|
2848
|
-
/* @__PURE__ */ jsx(Box, { paddingRight: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: INDICATOR.TREE }) }),
|
|
2849
|
-
children
|
|
2850
|
-
] })
|
|
2851
|
-
] });
|
|
2852
|
-
var getResultText = (result) => {
|
|
2853
|
-
if (!result) return "";
|
|
2854
|
-
return result.find((r) => r.type === "textPart")?.text ?? "";
|
|
2855
|
-
};
|
|
2856
|
-
var getString = (args, key) => {
|
|
2857
|
-
const value = args[key];
|
|
2858
|
-
return typeof value === "string" ? value : "";
|
|
2859
|
-
};
|
|
2860
|
-
var getStringArray = (args, key) => {
|
|
2861
|
-
const value = args[key];
|
|
2862
|
-
return Array.isArray(value) ? value : [];
|
|
2863
|
-
};
|
|
2864
|
-
var getNumberArray = (args, key) => {
|
|
2865
|
-
const value = args[key];
|
|
2866
|
-
return Array.isArray(value) ? value : [];
|
|
2867
|
-
};
|
|
2868
|
-
var renderThink = (args) => {
|
|
2869
|
-
const thought = getString(args, "thought");
|
|
2870
|
-
return /* @__PURE__ */ jsx(ActionRowSimple, { indicatorColor: "white", text: thought, textDimColor: true });
|
|
2871
|
-
};
|
|
2872
|
-
var renderCompleteReasoning = (text) => {
|
|
2873
|
-
const label = "Reasoning";
|
|
2005
|
+
] });
|
|
2006
|
+
}
|
|
2007
|
+
function renderReasoning(text) {
|
|
2874
2008
|
const lines = text.split("\n");
|
|
2875
|
-
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: "white", label, children: /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: lines.map((line, idx) => /* @__PURE__ */ jsx(Text, { dimColor: true, wrap: "wrap", children: line }, `reasoning-${idx}`)) }) });
|
|
2876
|
-
}
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2009
|
+
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: "white", label: "Reasoning", children: /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: lines.map((line, idx) => /* @__PURE__ */ jsx(Text, { dimColor: true, wrap: "wrap", children: line }, `reasoning-${idx}`)) }) });
|
|
2010
|
+
}
|
|
2011
|
+
function renderAction(action) {
|
|
2012
|
+
const color = action.type === "error" || "error" in action && action.error ? "red" : "green";
|
|
2013
|
+
switch (action.type) {
|
|
2014
|
+
case "query":
|
|
2015
|
+
return renderQuery(action.text, action.runId);
|
|
2016
|
+
case "retry":
|
|
2017
|
+
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: "yellow", label: "Retry", children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: action.message || action.error }) });
|
|
2018
|
+
case "complete":
|
|
2019
|
+
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: "green", label: "Run Results", children: /* @__PURE__ */ jsx(Text, { children: action.text }) });
|
|
2020
|
+
case "attemptCompletion": {
|
|
2021
|
+
if (action.error) {
|
|
2022
|
+
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: "red", label: "Completion Failed", children: /* @__PURE__ */ jsx(Text, { color: "red", children: action.error }) });
|
|
2023
|
+
}
|
|
2024
|
+
const remaining = action.remainingTodos?.filter((t) => !t.completed) ?? [];
|
|
2025
|
+
if (remaining.length > 0) {
|
|
2026
|
+
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: "yellow", label: "Completion Blocked", children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2027
|
+
remaining.length,
|
|
2028
|
+
" remaining task",
|
|
2029
|
+
remaining.length > 1 ? "s" : ""
|
|
2030
|
+
] }) });
|
|
2031
|
+
}
|
|
2032
|
+
return /* @__PURE__ */ jsx(ActionRowSimple, { indicatorColor: "green", text: "Completion Accepted" });
|
|
2033
|
+
}
|
|
2034
|
+
case "todo":
|
|
2035
|
+
return renderTodo(action, color);
|
|
2036
|
+
case "clearTodo":
|
|
2037
|
+
return /* @__PURE__ */ jsx(ActionRowSimple, { indicatorColor: color, text: "Todo Cleared" });
|
|
2038
|
+
case "readTextFile":
|
|
2039
|
+
return renderReadTextFile(action, color);
|
|
2040
|
+
case "writeTextFile":
|
|
2041
|
+
return renderWriteTextFile(action, color);
|
|
2042
|
+
case "editTextFile":
|
|
2043
|
+
return renderEditTextFile(action, color);
|
|
2044
|
+
case "appendTextFile":
|
|
2045
|
+
return renderAppendTextFile(action, color);
|
|
2046
|
+
case "deleteFile":
|
|
2047
|
+
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: color, label: "Delete", summary: shortenPath(action.path), children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Removed" }) });
|
|
2048
|
+
case "deleteDirectory":
|
|
2049
|
+
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: color, label: "Delete Dir", summary: shortenPath(action.path), children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2050
|
+
"Removed",
|
|
2051
|
+
action.recursive ? " (recursive)" : ""
|
|
2052
|
+
] }) });
|
|
2053
|
+
case "moveFile":
|
|
2054
|
+
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: color, label: "Move", summary: shortenPath(action.source), children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2055
|
+
"\u2192 ",
|
|
2056
|
+
shortenPath(action.destination, 30)
|
|
2057
|
+
] }) });
|
|
2058
|
+
case "createDirectory":
|
|
2059
|
+
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: color, label: "Mkdir", summary: shortenPath(action.path), children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Created" }) });
|
|
2060
|
+
case "listDirectory":
|
|
2061
|
+
return renderListDirectory(action, color);
|
|
2062
|
+
case "getFileInfo":
|
|
2063
|
+
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: color, label: "Info", summary: shortenPath(action.path), children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Fetched" }) });
|
|
2064
|
+
case "readPdfFile":
|
|
2065
|
+
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: color, label: "PDF", summary: shortenPath(action.path), children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Read" }) });
|
|
2066
|
+
case "readImageFile":
|
|
2067
|
+
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: color, label: "Image", summary: shortenPath(action.path), children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Read" }) });
|
|
2068
|
+
case "exec":
|
|
2069
|
+
return renderExec(action, color);
|
|
2070
|
+
case "delegate":
|
|
2071
|
+
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: "yellow", label: action.delegateExpertKey, children: /* @__PURE__ */ jsx(
|
|
2072
|
+
Text,
|
|
2073
|
+
{
|
|
2074
|
+
dimColor: true,
|
|
2075
|
+
children: `{"query":"${truncateText(action.query, UI_CONSTANTS.TRUNCATE_TEXT_MEDIUM)}"}`
|
|
2076
|
+
}
|
|
2077
|
+
) });
|
|
2078
|
+
case "delegationComplete":
|
|
2079
|
+
return /* @__PURE__ */ jsx(
|
|
2080
|
+
ActionRowSimple,
|
|
2081
|
+
{
|
|
2082
|
+
indicatorColor: "green",
|
|
2083
|
+
text: `Delegation Complete (${action.count} delegate${action.count > 1 ? "s" : ""} returned)`
|
|
2084
|
+
}
|
|
2085
|
+
);
|
|
2086
|
+
case "interactiveTool":
|
|
2087
|
+
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: "yellow", label: `Interactive: ${action.toolName}`, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: truncateText(JSON.stringify(action.args), UI_CONSTANTS.TRUNCATE_TEXT_MEDIUM) }) });
|
|
2088
|
+
case "generalTool":
|
|
2089
|
+
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: color, label: action.toolName, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: truncateText(JSON.stringify(action.args), UI_CONSTANTS.TRUNCATE_TEXT_MEDIUM) }) });
|
|
2090
|
+
case "error":
|
|
2091
|
+
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: "red", label: action.errorName ?? "Error", children: /* @__PURE__ */ jsx(Text, { color: "red", children: action.error ?? "Unknown error" }) });
|
|
2092
|
+
default: {
|
|
2093
|
+
return null;
|
|
2094
|
+
}
|
|
2887
2095
|
}
|
|
2888
|
-
}
|
|
2889
|
-
|
|
2890
|
-
const newTodos =
|
|
2891
|
-
const
|
|
2892
|
-
|
|
2893
|
-
if (
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2096
|
+
}
|
|
2097
|
+
function renderTodo(action, color) {
|
|
2098
|
+
const { newTodos, completedTodos, todos } = action;
|
|
2099
|
+
const hasNewTodos = newTodos && newTodos.length > 0;
|
|
2100
|
+
const hasCompletedTodos = completedTodos && completedTodos.length > 0;
|
|
2101
|
+
if (!hasNewTodos && !hasCompletedTodos) {
|
|
2102
|
+
return /* @__PURE__ */ jsx(ActionRowSimple, { indicatorColor: color, text: "Todo No changes" });
|
|
2103
|
+
}
|
|
2104
|
+
const labelParts = [];
|
|
2105
|
+
if (hasNewTodos) {
|
|
2106
|
+
labelParts.push(`Added ${newTodos.length} task${newTodos.length > 1 ? "s" : ""}`);
|
|
2107
|
+
}
|
|
2108
|
+
if (hasCompletedTodos) {
|
|
2109
|
+
labelParts.push(
|
|
2110
|
+
`Completed ${completedTodos.length} task${completedTodos.length > 1 ? "s" : ""}`
|
|
2111
|
+
);
|
|
2112
|
+
}
|
|
2113
|
+
const label = `Todo ${labelParts.join(", ")}`;
|
|
2114
|
+
const completedTitles = hasCompletedTodos ? completedTodos.map((id) => todos.find((t) => t.id === id)?.title).filter((t) => t !== void 0) : [];
|
|
2115
|
+
if (!hasNewTodos && completedTitles.length === 0) {
|
|
2116
|
+
return /* @__PURE__ */ jsx(ActionRowSimple, { indicatorColor: color, text: label });
|
|
2117
|
+
}
|
|
2118
|
+
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: color, label, children: /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
2119
|
+
hasNewTodos && newTodos.slice(0, RENDER_CONSTANTS.NEW_TODO_MAX_PREVIEW).map((todo, idx) => /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2120
|
+
"\u25CB ",
|
|
2121
|
+
todo
|
|
2122
|
+
] }, `todo-${idx}`)),
|
|
2123
|
+
hasNewTodos && newTodos.length > RENDER_CONSTANTS.NEW_TODO_MAX_PREVIEW && /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2124
|
+
"... +",
|
|
2125
|
+
newTodos.length - RENDER_CONSTANTS.NEW_TODO_MAX_PREVIEW,
|
|
2126
|
+
" more"
|
|
2127
|
+
] }),
|
|
2128
|
+
completedTitles.slice(0, RENDER_CONSTANTS.NEW_TODO_MAX_PREVIEW).map((title, idx) => /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2919
2129
|
"\u2713 ",
|
|
2920
2130
|
title
|
|
2921
2131
|
] }, `completed-${idx}`)),
|
|
2922
|
-
|
|
2923
|
-
"... +",
|
|
2924
|
-
remaining,
|
|
2925
|
-
" more"
|
|
2926
|
-
] })
|
|
2927
|
-
] }) });
|
|
2928
|
-
};
|
|
2929
|
-
var renderExec = (args, result, color) => {
|
|
2930
|
-
const command = getString(args, "command");
|
|
2931
|
-
const cmdArgs = getStringArray(args, "args");
|
|
2932
|
-
const cwd = getString(args, "cwd");
|
|
2933
|
-
const cwdPart = cwd ? ` ${shortenPath(cwd, 40)}` : "";
|
|
2934
|
-
const cmdLine = truncateText(
|
|
2935
|
-
`${command} ${cmdArgs.join(" ")}${cwdPart}`,
|
|
2936
|
-
UI_CONSTANTS.TRUNCATE_TEXT_DEFAULT
|
|
2937
|
-
);
|
|
2938
|
-
const text = getResultText(result);
|
|
2939
|
-
const { visible, remaining } = summarizeOutput(
|
|
2940
|
-
text.split("\n"),
|
|
2941
|
-
RENDER_CONSTANTS.EXEC_OUTPUT_MAX_LINES
|
|
2942
|
-
);
|
|
2943
|
-
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: color, label: `Bash ${cmdLine}`, children: /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
2944
|
-
visible.map((line, idx) => /* @__PURE__ */ jsx(Text, { dimColor: true, children: truncateText(line, UI_CONSTANTS.TRUNCATE_TEXT_DEFAULT) }, `out-${idx}`)),
|
|
2945
|
-
remaining > 0 && /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2132
|
+
completedTitles.length > RENDER_CONSTANTS.NEW_TODO_MAX_PREVIEW && /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2946
2133
|
"... +",
|
|
2947
|
-
|
|
2134
|
+
completedTitles.length - RENDER_CONSTANTS.NEW_TODO_MAX_PREVIEW,
|
|
2948
2135
|
" more"
|
|
2949
2136
|
] })
|
|
2950
2137
|
] }) });
|
|
2951
|
-
}
|
|
2952
|
-
|
|
2953
|
-
const
|
|
2954
|
-
if (!text) return { content: "" };
|
|
2955
|
-
try {
|
|
2956
|
-
return JSON.parse(text);
|
|
2957
|
-
} catch {
|
|
2958
|
-
return { content: "" };
|
|
2959
|
-
}
|
|
2960
|
-
};
|
|
2961
|
-
var renderReadTextFile = (args, result, color) => {
|
|
2962
|
-
const path11 = getString(args, "path");
|
|
2963
|
-
const { content, from, to } = parseReadTextFileResult(result);
|
|
2138
|
+
}
|
|
2139
|
+
function renderReadTextFile(action, color) {
|
|
2140
|
+
const { path: path11, content, from, to } = action;
|
|
2964
2141
|
const lineRange = from !== void 0 && to !== void 0 ? `#${from}-${to}` : "";
|
|
2965
2142
|
const lines = content?.split("\n") ?? [];
|
|
2966
2143
|
return /* @__PURE__ */ jsx(
|
|
@@ -2972,20 +2149,17 @@ var renderReadTextFile = (args, result, color) => {
|
|
|
2972
2149
|
children: /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: lines.map((line, idx) => /* @__PURE__ */ jsx(Box, { flexDirection: "row", gap: 1, children: /* @__PURE__ */ jsx(Text, { color: "white", dimColor: true, children: line }) }, `read-${idx}`)) })
|
|
2973
2150
|
}
|
|
2974
2151
|
);
|
|
2975
|
-
}
|
|
2976
|
-
|
|
2977
|
-
const path11 =
|
|
2978
|
-
const text = getString(args, "text");
|
|
2152
|
+
}
|
|
2153
|
+
function renderWriteTextFile(action, color) {
|
|
2154
|
+
const { path: path11, text } = action;
|
|
2979
2155
|
const lines = text.split("\n");
|
|
2980
2156
|
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: color, label: "Write Text File", summary: shortenPath(path11), children: /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: lines.map((line, idx) => /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
2981
2157
|
/* @__PURE__ */ jsx(Text, { color: "green", dimColor: true, children: "+" }),
|
|
2982
2158
|
/* @__PURE__ */ jsx(Text, { color: "white", dimColor: true, children: line })
|
|
2983
2159
|
] }, `write-${idx}`)) }) });
|
|
2984
|
-
}
|
|
2985
|
-
|
|
2986
|
-
const path11 =
|
|
2987
|
-
const oldText = getString(args, "oldText");
|
|
2988
|
-
const newText = getString(args, "newText");
|
|
2160
|
+
}
|
|
2161
|
+
function renderEditTextFile(action, color) {
|
|
2162
|
+
const { path: path11, oldText, newText } = action;
|
|
2989
2163
|
const oldLines = oldText.split("\n");
|
|
2990
2164
|
const newLines = newText.split("\n");
|
|
2991
2165
|
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: color, label: "Edit Text File", summary: shortenPath(path11), children: /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
@@ -2998,23 +2172,19 @@ var renderEditTextFile = (args, color) => {
|
|
|
2998
2172
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: line })
|
|
2999
2173
|
] }, `new-${idx}`))
|
|
3000
2174
|
] }) });
|
|
3001
|
-
}
|
|
3002
|
-
|
|
3003
|
-
const path11 =
|
|
3004
|
-
const text = getString(args, "text");
|
|
2175
|
+
}
|
|
2176
|
+
function renderAppendTextFile(action, color) {
|
|
2177
|
+
const { path: path11, text } = action;
|
|
3005
2178
|
const lines = text.split("\n");
|
|
3006
2179
|
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: color, label: "Append Text File", summary: shortenPath(path11), children: /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: lines.map((line, idx) => /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
3007
2180
|
/* @__PURE__ */ jsx(Text, { color: "green", dimColor: true, children: "+" }),
|
|
3008
2181
|
/* @__PURE__ */ jsx(Text, { color: "white", dimColor: true, children: line })
|
|
3009
2182
|
] }, `append-${idx}`)) }) });
|
|
3010
|
-
}
|
|
3011
|
-
|
|
3012
|
-
const path11 =
|
|
3013
|
-
const
|
|
3014
|
-
const { visible, remaining } = summarizeOutput(
|
|
3015
|
-
text.split("\n"),
|
|
3016
|
-
RENDER_CONSTANTS.LIST_DIR_MAX_ITEMS
|
|
3017
|
-
);
|
|
2183
|
+
}
|
|
2184
|
+
function renderListDirectory(action, color) {
|
|
2185
|
+
const { path: path11, items } = action;
|
|
2186
|
+
const itemLines = items?.map((item) => `${item.type === "directory" ? "\u{1F4C1}" : "\u{1F4C4}"} ${item.name}`) ?? [];
|
|
2187
|
+
const { visible, remaining } = summarizeOutput(itemLines, RENDER_CONSTANTS.LIST_DIR_MAX_ITEMS);
|
|
3018
2188
|
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: color, label: "List", summary: shortenPath(path11), children: /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
3019
2189
|
visible.map((line, idx) => /* @__PURE__ */ jsx(Text, { dimColor: true, children: truncateText(line, UI_CONSTANTS.TRUNCATE_TEXT_DEFAULT) }, `dir-${idx}`)),
|
|
3020
2190
|
remaining > 0 && /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
@@ -3023,159 +2193,160 @@ var renderListDirectory = (args, result, color) => {
|
|
|
3023
2193
|
" more"
|
|
3024
2194
|
] })
|
|
3025
2195
|
] }) });
|
|
3026
|
-
}
|
|
3027
|
-
|
|
3028
|
-
const
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
};
|
|
3047
|
-
var renderReadPdfFile = (args, color) => {
|
|
3048
|
-
const path11 = getString(args, "path");
|
|
3049
|
-
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: color, label: "PDF", summary: shortenPath(path11), children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Read" }) });
|
|
3050
|
-
};
|
|
3051
|
-
var renderReadImageFile = (args, color) => {
|
|
3052
|
-
const path11 = getString(args, "path");
|
|
3053
|
-
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: color, label: "Image", summary: shortenPath(path11), children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Read" }) });
|
|
3054
|
-
};
|
|
3055
|
-
var renderTestUrl = (args, color) => {
|
|
3056
|
-
const urls = getStringArray(args, "urls");
|
|
3057
|
-
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: color, label: "TestURL", children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
3058
|
-
urls.length,
|
|
3059
|
-
" URL(s)"
|
|
3060
|
-
] }) });
|
|
3061
|
-
};
|
|
3062
|
-
var renderDefault = (toolName, args, color) => /* @__PURE__ */ jsx(ActionRow, { indicatorColor: color, label: toolName, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: truncateText(JSON.stringify(args), UI_CONSTANTS.TRUNCATE_TEXT_MEDIUM) }) });
|
|
3063
|
-
var renderDelegationStarted = (expertName, runtime, version, query) => {
|
|
3064
|
-
const label = `Delegation Started (${expertName}, ${runtime}, v${version})`;
|
|
3065
|
-
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: "yellow", label, children: query && /* @__PURE__ */ jsx(Text, { dimColor: true, children: truncateText(query, UI_CONSTANTS.TRUNCATE_TEXT_MEDIUM) }) });
|
|
3066
|
-
};
|
|
3067
|
-
var renderDelegationCompleted = (expertName, runtime, version, result) => {
|
|
3068
|
-
const label = `Delegation Completed (${expertName}, ${runtime}, v${version})`;
|
|
3069
|
-
const trimmedResult = result?.trim();
|
|
3070
|
-
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: "green", label, children: trimmedResult && /* @__PURE__ */ jsx(Text, { dimColor: true, children: truncateText(trimmedResult, UI_CONSTANTS.TRUNCATE_TEXT_MEDIUM) }) });
|
|
3071
|
-
};
|
|
3072
|
-
var renderDockerBuild = (stage, service, message) => {
|
|
3073
|
-
const stageColors = {
|
|
3074
|
-
pulling: "yellow",
|
|
3075
|
-
building: "yellow",
|
|
3076
|
-
complete: "green",
|
|
3077
|
-
error: "red"
|
|
3078
|
-
};
|
|
3079
|
-
const color = stageColors[stage] ?? "yellow";
|
|
3080
|
-
const stageLabel = stage.charAt(0).toUpperCase() + stage.slice(1);
|
|
3081
|
-
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: color, label: `Docker Build [${service}] ${stageLabel}`, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: truncateText(message, UI_CONSTANTS.TRUNCATE_TEXT_DEFAULT) }) });
|
|
3082
|
-
};
|
|
3083
|
-
var renderDockerContainer = (status, service, message) => {
|
|
3084
|
-
const statusColors = {
|
|
3085
|
-
starting: "yellow",
|
|
3086
|
-
running: "green",
|
|
3087
|
-
healthy: "green",
|
|
3088
|
-
unhealthy: "red",
|
|
3089
|
-
stopped: "white",
|
|
3090
|
-
error: "red"
|
|
3091
|
-
};
|
|
3092
|
-
const color = statusColors[status] ?? "white";
|
|
3093
|
-
const statusLabel = status.charAt(0).toUpperCase() + status.slice(1);
|
|
3094
|
-
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: color, label: `Docker [${service}] ${statusLabel}`, children: message && /* @__PURE__ */ jsx(Text, { dimColor: true, children: truncateText(message, UI_CONSTANTS.TRUNCATE_TEXT_DEFAULT) }) });
|
|
3095
|
-
};
|
|
3096
|
-
var renderProxyAccess = (action, domain, port, reason) => {
|
|
3097
|
-
const isAllowed = action === "allowed";
|
|
3098
|
-
const color = isAllowed ? "green" : "red";
|
|
3099
|
-
const icon = isAllowed ? "\u2713" : "\u2717";
|
|
3100
|
-
const detail = reason ? `${domain}:${port} (${reason})` : `${domain}:${port}`;
|
|
3101
|
-
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: color, label: "Proxy", children: /* @__PURE__ */ jsxs(Text, { color, children: [
|
|
3102
|
-
icon,
|
|
3103
|
-
" ",
|
|
3104
|
-
detail
|
|
2196
|
+
}
|
|
2197
|
+
function renderExec(action, color) {
|
|
2198
|
+
const { command, args, cwd, output } = action;
|
|
2199
|
+
const cwdPart = cwd ? ` ${shortenPath(cwd, 40)}` : "";
|
|
2200
|
+
const cmdLine = truncateText(
|
|
2201
|
+
`${command} ${args.join(" ")}${cwdPart}`,
|
|
2202
|
+
UI_CONSTANTS.TRUNCATE_TEXT_DEFAULT
|
|
2203
|
+
);
|
|
2204
|
+
const outputLines = output?.split("\n") ?? [];
|
|
2205
|
+
const { visible, remaining } = summarizeOutput(
|
|
2206
|
+
outputLines,
|
|
2207
|
+
RENDER_CONSTANTS.EXEC_OUTPUT_MAX_LINES
|
|
2208
|
+
);
|
|
2209
|
+
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: color, label: `Bash ${cmdLine}`, children: /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
2210
|
+
visible.map((line, idx) => /* @__PURE__ */ jsx(Text, { dimColor: true, children: truncateText(line, UI_CONSTANTS.TRUNCATE_TEXT_DEFAULT) }, `out-${idx}`)),
|
|
2211
|
+
remaining > 0 && /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2212
|
+
"... +",
|
|
2213
|
+
remaining,
|
|
2214
|
+
" more"
|
|
2215
|
+
] })
|
|
3105
2216
|
] }) });
|
|
2217
|
+
}
|
|
2218
|
+
function renderQuery(text, runId) {
|
|
2219
|
+
const lines = text.split("\n");
|
|
2220
|
+
const shortRunId = runId.slice(0, 8);
|
|
2221
|
+
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: "cyan", label: "Query", summary: `(${shortRunId})`, children: /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: lines.map((line, idx) => /* @__PURE__ */ jsx(Text, { dimColor: true, wrap: "wrap", children: line }, `query-${idx}`)) }) });
|
|
2222
|
+
}
|
|
2223
|
+
function ErrorStep({ message, onBack }) {
|
|
2224
|
+
useInput(() => onBack());
|
|
2225
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
2226
|
+
/* @__PURE__ */ jsxs(Text, { color: "red", children: [
|
|
2227
|
+
"Error: ",
|
|
2228
|
+
message
|
|
2229
|
+
] }),
|
|
2230
|
+
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Press any key to go back" }) })
|
|
2231
|
+
] });
|
|
2232
|
+
}
|
|
2233
|
+
var RunSetting = ({
|
|
2234
|
+
info,
|
|
2235
|
+
eventCount,
|
|
2236
|
+
isEditing,
|
|
2237
|
+
expertName,
|
|
2238
|
+
onQuerySubmit
|
|
2239
|
+
}) => {
|
|
2240
|
+
const { input, handleInput } = useTextInput({
|
|
2241
|
+
onSubmit: onQuerySubmit ?? (() => {
|
|
2242
|
+
})
|
|
2243
|
+
});
|
|
2244
|
+
useInput(handleInput, { isActive: isEditing });
|
|
2245
|
+
const displayExpertName = expertName ?? info.expertName;
|
|
2246
|
+
const skills = info.activeSkills.length > 0 ? info.activeSkills.join(", ") : "";
|
|
2247
|
+
const step = info.currentStep !== void 0 ? String(info.currentStep) : "";
|
|
2248
|
+
const usagePercent = (info.contextWindowUsage * 100).toFixed(1);
|
|
2249
|
+
return /* @__PURE__ */ jsxs(
|
|
2250
|
+
Box,
|
|
2251
|
+
{
|
|
2252
|
+
flexDirection: "column",
|
|
2253
|
+
borderStyle: "single",
|
|
2254
|
+
borderColor: "gray",
|
|
2255
|
+
borderTop: true,
|
|
2256
|
+
borderBottom: false,
|
|
2257
|
+
borderLeft: false,
|
|
2258
|
+
borderRight: false,
|
|
2259
|
+
children: [
|
|
2260
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
2261
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: info.runtime === "local" ? "Local" : info.runtime === "claude-code" ? "Claude Code" : (info.runtime ?? "docker").charAt(0).toUpperCase() + (info.runtime ?? "docker").slice(1) }),
|
|
2262
|
+
info.runtime === "docker" || !info.runtime ? /* @__PURE__ */ jsxs(Text, { color: info.dockerState === "building" ? "yellow" : "gray", children: [
|
|
2263
|
+
" ",
|
|
2264
|
+
"(",
|
|
2265
|
+
info.dockerState ?? "initializing",
|
|
2266
|
+
")"
|
|
2267
|
+
] }) : info.runtimeVersion && /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
|
|
2268
|
+
" ",
|
|
2269
|
+
"(",
|
|
2270
|
+
info.runtime === "local" ? `v${info.runtimeVersion}` : info.runtimeVersion,
|
|
2271
|
+
")"
|
|
2272
|
+
] })
|
|
2273
|
+
] }),
|
|
2274
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
2275
|
+
/* @__PURE__ */ jsx(Text, { color: "gray", children: "Expert: " }),
|
|
2276
|
+
/* @__PURE__ */ jsx(Text, { color: "white", children: displayExpertName }),
|
|
2277
|
+
/* @__PURE__ */ jsx(Text, { color: "gray", children: " / Skills: " }),
|
|
2278
|
+
/* @__PURE__ */ jsx(Text, { color: "green", children: skills })
|
|
2279
|
+
] }),
|
|
2280
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
2281
|
+
/* @__PURE__ */ jsx(Text, { color: "gray", children: "Status: " }),
|
|
2282
|
+
/* @__PURE__ */ jsx(
|
|
2283
|
+
Text,
|
|
2284
|
+
{
|
|
2285
|
+
color: info.status === "running" ? "green" : info.status === "completed" ? "cyan" : "yellow",
|
|
2286
|
+
children: info.status
|
|
2287
|
+
}
|
|
2288
|
+
),
|
|
2289
|
+
/* @__PURE__ */ jsx(Text, { color: "gray", children: " / Step: " }),
|
|
2290
|
+
/* @__PURE__ */ jsx(Text, { color: "white", children: step }),
|
|
2291
|
+
/* @__PURE__ */ jsx(Text, { color: "gray", children: " / Events: " }),
|
|
2292
|
+
/* @__PURE__ */ jsx(Text, { color: "white", children: eventCount }),
|
|
2293
|
+
/* @__PURE__ */ jsx(Text, { color: "gray", children: " / Usage: " }),
|
|
2294
|
+
/* @__PURE__ */ jsxs(Text, { color: "white", children: [
|
|
2295
|
+
usagePercent,
|
|
2296
|
+
"%"
|
|
2297
|
+
] })
|
|
2298
|
+
] }),
|
|
2299
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
2300
|
+
/* @__PURE__ */ jsx(Text, { color: "gray", children: "Model: " }),
|
|
2301
|
+
/* @__PURE__ */ jsx(Text, { color: "white", children: info.model })
|
|
2302
|
+
] }),
|
|
2303
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
2304
|
+
/* @__PURE__ */ jsx(Text, { color: "gray", children: "Query: " }),
|
|
2305
|
+
isEditing ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2306
|
+
/* @__PURE__ */ jsx(Text, { color: "white", children: input }),
|
|
2307
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: "_" })
|
|
2308
|
+
] }) : /* @__PURE__ */ jsx(Text, { color: "white", children: info.query })
|
|
2309
|
+
] })
|
|
2310
|
+
]
|
|
2311
|
+
}
|
|
2312
|
+
);
|
|
3106
2313
|
};
|
|
3107
|
-
var
|
|
3108
|
-
const
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
return renderAttemptCompletion();
|
|
3114
|
-
case "todo":
|
|
3115
|
-
return renderTodo(args, result);
|
|
3116
|
-
case "exec":
|
|
3117
|
-
return renderExec(args, result, color);
|
|
3118
|
-
case "readTextFile":
|
|
3119
|
-
return renderReadTextFile(args, result, color);
|
|
3120
|
-
case "writeTextFile":
|
|
3121
|
-
return renderWriteTextFile(args, color);
|
|
3122
|
-
case "editTextFile":
|
|
3123
|
-
return renderEditTextFile(args, color);
|
|
3124
|
-
case "appendTextFile":
|
|
3125
|
-
return renderAppendTextFile(args, color);
|
|
3126
|
-
case "listDirectory":
|
|
3127
|
-
return renderListDirectory(args, result, color);
|
|
3128
|
-
case "deleteFile":
|
|
3129
|
-
return renderDeleteFile(args, color);
|
|
3130
|
-
case "moveFile":
|
|
3131
|
-
return renderMoveFile(args, color);
|
|
3132
|
-
case "createDirectory":
|
|
3133
|
-
return renderCreateDirectory(args, color);
|
|
3134
|
-
case "getFileInfo":
|
|
3135
|
-
return renderGetFileInfo(args, color);
|
|
3136
|
-
case "readPdfFile":
|
|
3137
|
-
return renderReadPdfFile(args, color);
|
|
3138
|
-
case "readImageFile":
|
|
3139
|
-
return renderReadImageFile(args, color);
|
|
3140
|
-
case "testUrl":
|
|
3141
|
-
return renderTestUrl(args, color);
|
|
3142
|
-
default:
|
|
3143
|
-
return renderDefault(toolName, args, color);
|
|
3144
|
-
}
|
|
2314
|
+
var StreamingDisplay = ({ streaming }) => {
|
|
2315
|
+
const activeRuns = Object.entries(streaming.runs).filter(
|
|
2316
|
+
([, run]) => run.isReasoningActive || run.isRunResultActive
|
|
2317
|
+
);
|
|
2318
|
+
if (activeRuns.length === 0) return null;
|
|
2319
|
+
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginY: 1, children: activeRuns.map(([runId, run]) => /* @__PURE__ */ jsx(StreamingRunSection, { run }, runId)) });
|
|
3145
2320
|
};
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
);
|
|
3173
|
-
case "completeReasoning":
|
|
3174
|
-
return /* @__PURE__ */ jsx(Box, { children: renderCompleteReasoning(entry.text) });
|
|
3175
|
-
case "retry":
|
|
3176
|
-
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: "yellow", label: "Retry", children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: entry.reason }) });
|
|
2321
|
+
function StreamingRunSection({ run }) {
|
|
2322
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
2323
|
+
run.isReasoningActive && run.reasoning !== void 0 && /* @__PURE__ */ jsx(StreamingReasoning, { expertKey: run.expertKey, text: run.reasoning }),
|
|
2324
|
+
run.isRunResultActive && run.runResult !== void 0 && /* @__PURE__ */ jsx(StreamingRunResult, { expertKey: run.expertKey, text: run.runResult })
|
|
2325
|
+
] });
|
|
2326
|
+
}
|
|
2327
|
+
function StreamingReasoning({
|
|
2328
|
+
expertKey,
|
|
2329
|
+
text
|
|
2330
|
+
}) {
|
|
2331
|
+
const lines = text.split("\n");
|
|
2332
|
+
const label = `[${formatExpertKey(expertKey)}] Reasoning...`;
|
|
2333
|
+
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: "cyan", label, children: /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: lines.map((line, idx) => /* @__PURE__ */ jsx(Text, { dimColor: true, wrap: "wrap", children: line }, `streaming-reasoning-${idx}`)) }) });
|
|
2334
|
+
}
|
|
2335
|
+
function StreamingRunResult({
|
|
2336
|
+
expertKey,
|
|
2337
|
+
text
|
|
2338
|
+
}) {
|
|
2339
|
+
const lines = text.split("\n");
|
|
2340
|
+
const label = `[${formatExpertKey(expertKey)}] Generating...`;
|
|
2341
|
+
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: "green", label, children: /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: lines.map((line, idx) => /* @__PURE__ */ jsx(Text, { wrap: "wrap", children: line }, `streaming-run-result-${idx}`)) }) });
|
|
2342
|
+
}
|
|
2343
|
+
function formatExpertKey(expertKey) {
|
|
2344
|
+
const atIndex = expertKey.lastIndexOf("@");
|
|
2345
|
+
if (atIndex > 0) {
|
|
2346
|
+
return expertKey.substring(0, atIndex);
|
|
3177
2347
|
}
|
|
3178
|
-
|
|
2348
|
+
return expertKey;
|
|
2349
|
+
}
|
|
3179
2350
|
|
|
3180
2351
|
// src/tui/utils/status-color.ts
|
|
3181
2352
|
var getStatusColor = (status) => {
|
|
@@ -3236,6 +2407,10 @@ function VersionSelector({
|
|
|
3236
2407
|
function WizardExpertSelector({ title, experts, onSelect }) {
|
|
3237
2408
|
const { exit } = useApp();
|
|
3238
2409
|
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
2410
|
+
const expertItems = experts.map((expert) => ({
|
|
2411
|
+
key: expert.name,
|
|
2412
|
+
expert
|
|
2413
|
+
}));
|
|
3239
2414
|
useInput((input, key) => {
|
|
3240
2415
|
if (key.upArrow) {
|
|
3241
2416
|
setSelectedIndex((prev) => prev > 0 ? prev - 1 : experts.length - 1);
|
|
@@ -3252,17 +2427,291 @@ function WizardExpertSelector({ title, experts, onSelect }) {
|
|
|
3252
2427
|
});
|
|
3253
2428
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
3254
2429
|
/* @__PURE__ */ jsx(Text, { bold: true, children: title }),
|
|
3255
|
-
/* @__PURE__ */ jsx(Box, { flexDirection: "column", marginTop: 1, children:
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
2430
|
+
/* @__PURE__ */ jsx(Box, { flexDirection: "column", marginTop: 1, children: /* @__PURE__ */ jsx(
|
|
2431
|
+
SelectableList,
|
|
2432
|
+
{
|
|
2433
|
+
items: expertItems,
|
|
2434
|
+
selectedIndex,
|
|
2435
|
+
renderItem: (item, isSelected) => /* @__PURE__ */ jsxs(Text, { color: isSelected ? "cyan" : void 0, children: [
|
|
2436
|
+
isSelected ? "\u276F " : " ",
|
|
2437
|
+
item.expert.name,
|
|
2438
|
+
item.expert.description && /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2439
|
+
" - ",
|
|
2440
|
+
item.expert.description
|
|
2441
|
+
] })
|
|
2442
|
+
] })
|
|
2443
|
+
}
|
|
2444
|
+
) }),
|
|
3263
2445
|
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191\u2193 navigate \xB7 enter select \xB7 q quit" }) })
|
|
3264
2446
|
] });
|
|
3265
2447
|
}
|
|
2448
|
+
function getActivityKey(activityOrGroup, index) {
|
|
2449
|
+
return activityOrGroup.id || `activity-${index}`;
|
|
2450
|
+
}
|
|
2451
|
+
var RunBox = ({ node, isRoot }) => {
|
|
2452
|
+
if (isRoot) {
|
|
2453
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
2454
|
+
node.activities.map((activity, index) => /* @__PURE__ */ jsx(CheckpointActionRow, { action: activity }, getActivityKey(activity, index))),
|
|
2455
|
+
node.children.map((child) => /* @__PURE__ */ jsx(RunBox, { node: child, isRoot: false }, child.runId))
|
|
2456
|
+
] });
|
|
2457
|
+
}
|
|
2458
|
+
const shortRunId = node.runId.slice(0, 8);
|
|
2459
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "gray", marginLeft: 1, children: [
|
|
2460
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, bold: true, children: [
|
|
2461
|
+
"[",
|
|
2462
|
+
node.expertKey,
|
|
2463
|
+
"] ",
|
|
2464
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2465
|
+
"(",
|
|
2466
|
+
shortRunId,
|
|
2467
|
+
")"
|
|
2468
|
+
] })
|
|
2469
|
+
] }),
|
|
2470
|
+
node.activities.map((activity, index) => /* @__PURE__ */ jsx(CheckpointActionRow, { action: activity }, getActivityKey(activity, index))),
|
|
2471
|
+
node.children.map((child) => /* @__PURE__ */ jsx(RunBox, { node: child, isRoot: false }, child.runId))
|
|
2472
|
+
] });
|
|
2473
|
+
};
|
|
2474
|
+
function getActivityProps(activityOrGroup) {
|
|
2475
|
+
if (activityOrGroup.type === "parallelGroup") {
|
|
2476
|
+
const group = activityOrGroup;
|
|
2477
|
+
const firstActivity = group.activities[0];
|
|
2478
|
+
return {
|
|
2479
|
+
runId: group.runId,
|
|
2480
|
+
expertKey: group.expertKey,
|
|
2481
|
+
delegatedBy: firstActivity?.delegatedBy
|
|
2482
|
+
};
|
|
2483
|
+
}
|
|
2484
|
+
return activityOrGroup;
|
|
2485
|
+
}
|
|
2486
|
+
var ActivityLogPanel = ({ activities }) => {
|
|
2487
|
+
const rootNodes = useMemo(() => {
|
|
2488
|
+
const nodeMap = /* @__PURE__ */ new Map();
|
|
2489
|
+
const roots = [];
|
|
2490
|
+
const orphanChildren = /* @__PURE__ */ new Map();
|
|
2491
|
+
for (const activityOrGroup of activities) {
|
|
2492
|
+
const { runId, expertKey, delegatedBy } = getActivityProps(activityOrGroup);
|
|
2493
|
+
let node = nodeMap.get(runId);
|
|
2494
|
+
if (!node) {
|
|
2495
|
+
node = {
|
|
2496
|
+
runId,
|
|
2497
|
+
expertKey,
|
|
2498
|
+
activities: [],
|
|
2499
|
+
children: []
|
|
2500
|
+
};
|
|
2501
|
+
nodeMap.set(runId, node);
|
|
2502
|
+
const waitingChildren = orphanChildren.get(runId);
|
|
2503
|
+
if (waitingChildren) {
|
|
2504
|
+
for (const child of waitingChildren) {
|
|
2505
|
+
node.children.push(child);
|
|
2506
|
+
const rootIndex = roots.indexOf(child);
|
|
2507
|
+
if (rootIndex !== -1) {
|
|
2508
|
+
roots.splice(rootIndex, 1);
|
|
2509
|
+
}
|
|
2510
|
+
}
|
|
2511
|
+
orphanChildren.delete(runId);
|
|
2512
|
+
}
|
|
2513
|
+
if (delegatedBy) {
|
|
2514
|
+
const parentNode = nodeMap.get(delegatedBy.runId);
|
|
2515
|
+
if (parentNode) {
|
|
2516
|
+
parentNode.children.push(node);
|
|
2517
|
+
} else {
|
|
2518
|
+
const orphans = orphanChildren.get(delegatedBy.runId) ?? [];
|
|
2519
|
+
orphans.push(node);
|
|
2520
|
+
orphanChildren.set(delegatedBy.runId, orphans);
|
|
2521
|
+
roots.push(node);
|
|
2522
|
+
}
|
|
2523
|
+
} else {
|
|
2524
|
+
roots.push(node);
|
|
2525
|
+
}
|
|
2526
|
+
}
|
|
2527
|
+
node.activities.push(activityOrGroup);
|
|
2528
|
+
}
|
|
2529
|
+
return roots;
|
|
2530
|
+
}, [activities]);
|
|
2531
|
+
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: rootNodes.map((node) => /* @__PURE__ */ jsx(RunBox, { node, isRoot: true }, node.runId)) });
|
|
2532
|
+
};
|
|
2533
|
+
var ContinueInputPanel = ({
|
|
2534
|
+
isActive,
|
|
2535
|
+
runStatus,
|
|
2536
|
+
onSubmit
|
|
2537
|
+
}) => {
|
|
2538
|
+
const { input, handleInput } = useTextInput({
|
|
2539
|
+
onSubmit: (newQuery) => {
|
|
2540
|
+
if (isActive && newQuery.trim()) {
|
|
2541
|
+
onSubmit(newQuery.trim());
|
|
2542
|
+
}
|
|
2543
|
+
}
|
|
2544
|
+
});
|
|
2545
|
+
useInput(handleInput, { isActive });
|
|
2546
|
+
if (runStatus === "running") {
|
|
2547
|
+
return null;
|
|
2548
|
+
}
|
|
2549
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "gray", children: [
|
|
2550
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
2551
|
+
/* @__PURE__ */ jsx(Text, { color: runStatus === "completed" ? "green" : "yellow", bold: true, children: runStatus === "completed" ? "Completed" : "Stopped" }),
|
|
2552
|
+
/* @__PURE__ */ jsx(Text, { color: "gray", children: " - Enter a follow-up query or wait to exit" })
|
|
2553
|
+
] }),
|
|
2554
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
2555
|
+
/* @__PURE__ */ jsx(Text, { color: "gray", children: "Continue: " }),
|
|
2556
|
+
/* @__PURE__ */ jsx(Text, { children: input }),
|
|
2557
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: "_" })
|
|
2558
|
+
] })
|
|
2559
|
+
] });
|
|
2560
|
+
};
|
|
2561
|
+
var StatusPanel = ({
|
|
2562
|
+
runtimeInfo,
|
|
2563
|
+
eventCount,
|
|
2564
|
+
runStatus
|
|
2565
|
+
}) => {
|
|
2566
|
+
if (runStatus !== "running") {
|
|
2567
|
+
return null;
|
|
2568
|
+
}
|
|
2569
|
+
return /* @__PURE__ */ jsx(RunSetting, { info: runtimeInfo, eventCount, isEditing: false });
|
|
2570
|
+
};
|
|
2571
|
+
var useExecutionState = (options) => {
|
|
2572
|
+
const { expertKey, query, config, continueTimeoutMs, historicalEvents, onReady, onComplete } = options;
|
|
2573
|
+
const { exit } = useApp();
|
|
2574
|
+
const runState = useRun();
|
|
2575
|
+
const { runtimeInfo, handleEvent, setQuery } = useRuntimeInfo({
|
|
2576
|
+
initialExpertName: expertKey,
|
|
2577
|
+
initialConfig: config
|
|
2578
|
+
});
|
|
2579
|
+
const [runStatus, setRunStatus] = useState("running");
|
|
2580
|
+
const [isAcceptingContinue, setIsAcceptingContinue] = useState(false);
|
|
2581
|
+
const timeoutRef = useRef(null);
|
|
2582
|
+
const clearTimeoutIfExists = useCallback(() => {
|
|
2583
|
+
if (timeoutRef.current) {
|
|
2584
|
+
clearTimeout(timeoutRef.current);
|
|
2585
|
+
timeoutRef.current = null;
|
|
2586
|
+
}
|
|
2587
|
+
}, []);
|
|
2588
|
+
const startExitTimeout = useCallback(() => {
|
|
2589
|
+
clearTimeoutIfExists();
|
|
2590
|
+
timeoutRef.current = setTimeout(() => {
|
|
2591
|
+
onComplete({ nextQuery: null });
|
|
2592
|
+
exit();
|
|
2593
|
+
}, continueTimeoutMs);
|
|
2594
|
+
}, [clearTimeoutIfExists, continueTimeoutMs, onComplete, exit]);
|
|
2595
|
+
useEffect(() => {
|
|
2596
|
+
setQuery(query);
|
|
2597
|
+
}, [query, setQuery]);
|
|
2598
|
+
useEffect(() => {
|
|
2599
|
+
if (historicalEvents && historicalEvents.length > 0) {
|
|
2600
|
+
runState.appendHistoricalEvents(historicalEvents);
|
|
2601
|
+
}
|
|
2602
|
+
}, [historicalEvents, runState.appendHistoricalEvents]);
|
|
2603
|
+
useEffect(() => {
|
|
2604
|
+
onReady((event) => {
|
|
2605
|
+
runState.addEvent(event);
|
|
2606
|
+
const result = handleEvent(event);
|
|
2607
|
+
if (result?.completed) {
|
|
2608
|
+
setRunStatus("completed");
|
|
2609
|
+
setIsAcceptingContinue(true);
|
|
2610
|
+
startExitTimeout();
|
|
2611
|
+
} else if (result?.stopped) {
|
|
2612
|
+
setRunStatus("stopped");
|
|
2613
|
+
setIsAcceptingContinue(true);
|
|
2614
|
+
startExitTimeout();
|
|
2615
|
+
}
|
|
2616
|
+
});
|
|
2617
|
+
}, [onReady, runState.addEvent, handleEvent, startExitTimeout]);
|
|
2618
|
+
useEffect(() => {
|
|
2619
|
+
return () => {
|
|
2620
|
+
clearTimeoutIfExists();
|
|
2621
|
+
};
|
|
2622
|
+
}, [clearTimeoutIfExists]);
|
|
2623
|
+
const handleContinueSubmit = useCallback(
|
|
2624
|
+
(newQuery) => {
|
|
2625
|
+
if (isAcceptingContinue && newQuery.trim()) {
|
|
2626
|
+
clearTimeoutIfExists();
|
|
2627
|
+
onComplete({ nextQuery: newQuery.trim() });
|
|
2628
|
+
exit();
|
|
2629
|
+
}
|
|
2630
|
+
},
|
|
2631
|
+
[isAcceptingContinue, clearTimeoutIfExists, onComplete, exit]
|
|
2632
|
+
);
|
|
2633
|
+
return {
|
|
2634
|
+
activities: runState.activities,
|
|
2635
|
+
streaming: runState.streaming,
|
|
2636
|
+
eventCount: runState.eventCount,
|
|
2637
|
+
runtimeInfo,
|
|
2638
|
+
runStatus,
|
|
2639
|
+
isAcceptingContinue,
|
|
2640
|
+
handleContinueSubmit,
|
|
2641
|
+
clearTimeout: clearTimeoutIfExists
|
|
2642
|
+
};
|
|
2643
|
+
};
|
|
2644
|
+
var ExecutionApp = (props) => {
|
|
2645
|
+
const { expertKey, query, config, continueTimeoutMs, historicalEvents, onReady, onComplete } = props;
|
|
2646
|
+
const { exit } = useApp();
|
|
2647
|
+
const state = useExecutionState({
|
|
2648
|
+
expertKey,
|
|
2649
|
+
query,
|
|
2650
|
+
config,
|
|
2651
|
+
continueTimeoutMs,
|
|
2652
|
+
historicalEvents,
|
|
2653
|
+
onReady,
|
|
2654
|
+
onComplete
|
|
2655
|
+
});
|
|
2656
|
+
useInput((input, key) => {
|
|
2657
|
+
if (key.ctrl && input === "c") {
|
|
2658
|
+
state.clearTimeout();
|
|
2659
|
+
exit();
|
|
2660
|
+
}
|
|
2661
|
+
});
|
|
2662
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
2663
|
+
/* @__PURE__ */ jsx(ActivityLogPanel, { activities: state.activities }),
|
|
2664
|
+
/* @__PURE__ */ jsx(StreamingDisplay, { streaming: state.streaming }),
|
|
2665
|
+
/* @__PURE__ */ jsx(
|
|
2666
|
+
StatusPanel,
|
|
2667
|
+
{
|
|
2668
|
+
runtimeInfo: state.runtimeInfo,
|
|
2669
|
+
eventCount: state.eventCount,
|
|
2670
|
+
runStatus: state.runStatus
|
|
2671
|
+
}
|
|
2672
|
+
),
|
|
2673
|
+
/* @__PURE__ */ jsx(
|
|
2674
|
+
ContinueInputPanel,
|
|
2675
|
+
{
|
|
2676
|
+
isActive: state.isAcceptingContinue,
|
|
2677
|
+
runStatus: state.runStatus,
|
|
2678
|
+
onSubmit: state.handleContinueSubmit
|
|
2679
|
+
}
|
|
2680
|
+
)
|
|
2681
|
+
] });
|
|
2682
|
+
};
|
|
2683
|
+
function renderExecution(params) {
|
|
2684
|
+
const eventQueue = new EventQueue();
|
|
2685
|
+
const result = new Promise((resolve2, reject) => {
|
|
2686
|
+
let resolved = false;
|
|
2687
|
+
const { waitUntilExit } = render(
|
|
2688
|
+
/* @__PURE__ */ jsx(
|
|
2689
|
+
ExecutionApp,
|
|
2690
|
+
{
|
|
2691
|
+
...params,
|
|
2692
|
+
onReady: (handler) => {
|
|
2693
|
+
eventQueue.setHandler(handler);
|
|
2694
|
+
},
|
|
2695
|
+
onComplete: (result2) => {
|
|
2696
|
+
resolved = true;
|
|
2697
|
+
resolve2(result2);
|
|
2698
|
+
}
|
|
2699
|
+
}
|
|
2700
|
+
)
|
|
2701
|
+
);
|
|
2702
|
+
waitUntilExit().then(() => {
|
|
2703
|
+
if (!resolved) {
|
|
2704
|
+
reject(new Error("Execution cancelled"));
|
|
2705
|
+
}
|
|
2706
|
+
}).catch(reject);
|
|
2707
|
+
});
|
|
2708
|
+
return {
|
|
2709
|
+
result,
|
|
2710
|
+
eventListener: (event) => {
|
|
2711
|
+
eventQueue.emit(event);
|
|
2712
|
+
}
|
|
2713
|
+
};
|
|
2714
|
+
}
|
|
3266
2715
|
function PublishApp({ experts, onSelect }) {
|
|
3267
2716
|
const { exit } = useApp();
|
|
3268
2717
|
const handleSelect = (name) => {
|
|
@@ -3297,93 +2746,210 @@ async function renderPublish(options) {
|
|
|
3297
2746
|
});
|
|
3298
2747
|
});
|
|
3299
2748
|
}
|
|
3300
|
-
var
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
2749
|
+
var selectionReducer = (_state, action) => {
|
|
2750
|
+
switch (action.type) {
|
|
2751
|
+
case "BROWSE_HISTORY":
|
|
2752
|
+
return { type: "browsingHistory", jobs: action.jobs };
|
|
2753
|
+
case "BROWSE_EXPERTS":
|
|
2754
|
+
return { type: "browsingExperts", experts: action.experts };
|
|
2755
|
+
case "SELECT_EXPERT":
|
|
2756
|
+
return { type: "enteringQuery", expertKey: action.expertKey };
|
|
2757
|
+
case "SELECT_JOB":
|
|
2758
|
+
return { type: "browsingCheckpoints", job: action.job, checkpoints: action.checkpoints };
|
|
2759
|
+
case "GO_BACK_FROM_CHECKPOINTS":
|
|
2760
|
+
return { type: "browsingHistory", jobs: action.jobs };
|
|
2761
|
+
default:
|
|
2762
|
+
return assertNever(action);
|
|
2763
|
+
}
|
|
2764
|
+
};
|
|
2765
|
+
var SelectionApp = (props) => {
|
|
2766
|
+
const {
|
|
2767
|
+
showHistory,
|
|
2768
|
+
initialExpertKey,
|
|
2769
|
+
initialQuery,
|
|
2770
|
+
initialCheckpoint,
|
|
2771
|
+
configuredExperts,
|
|
2772
|
+
recentExperts,
|
|
2773
|
+
historyJobs,
|
|
2774
|
+
onLoadCheckpoints,
|
|
2775
|
+
onComplete
|
|
2776
|
+
} = props;
|
|
2777
|
+
const { exit } = useApp();
|
|
2778
|
+
const allExperts = useMemo(() => {
|
|
2779
|
+
const configured = configuredExperts.map((e) => ({ ...e, source: "configured" }));
|
|
2780
|
+
const recent = recentExperts.filter((e) => !configured.some((c) => c.key === e.key)).map((e) => ({ ...e, source: "recent" }));
|
|
2781
|
+
return [...configured, ...recent];
|
|
2782
|
+
}, [configuredExperts, recentExperts]);
|
|
2783
|
+
const getInitialState = () => {
|
|
2784
|
+
if (initialExpertKey && !initialQuery) {
|
|
2785
|
+
return { type: "enteringQuery", expertKey: initialExpertKey };
|
|
2786
|
+
}
|
|
2787
|
+
if (showHistory && historyJobs.length > 0) {
|
|
2788
|
+
return { type: "browsingHistory", jobs: historyJobs };
|
|
2789
|
+
}
|
|
2790
|
+
return { type: "browsingExperts", experts: allExperts };
|
|
2791
|
+
};
|
|
2792
|
+
const [state, dispatch] = useReducer(selectionReducer, void 0, getInitialState);
|
|
2793
|
+
const [selectedCheckpoint, setSelectedCheckpoint] = useState(
|
|
2794
|
+
initialCheckpoint
|
|
2795
|
+
);
|
|
2796
|
+
useEffect(() => {
|
|
2797
|
+
if (initialExpertKey && initialQuery) {
|
|
2798
|
+
onComplete({
|
|
2799
|
+
expertKey: initialExpertKey,
|
|
2800
|
+
query: initialQuery,
|
|
2801
|
+
checkpoint: initialCheckpoint
|
|
2802
|
+
});
|
|
2803
|
+
exit();
|
|
2804
|
+
}
|
|
2805
|
+
}, [initialExpertKey, initialQuery, initialCheckpoint, onComplete, exit]);
|
|
2806
|
+
const { input: queryInput, handleInput: handleQueryInput } = useTextInput({
|
|
2807
|
+
onSubmit: (query) => {
|
|
2808
|
+
if (state.type === "enteringQuery" && query.trim()) {
|
|
2809
|
+
onComplete({
|
|
2810
|
+
expertKey: state.expertKey,
|
|
2811
|
+
query: query.trim(),
|
|
2812
|
+
checkpoint: selectedCheckpoint
|
|
2813
|
+
});
|
|
2814
|
+
exit();
|
|
2815
|
+
}
|
|
2816
|
+
}
|
|
2817
|
+
});
|
|
2818
|
+
useInput(handleQueryInput, { isActive: state.type === "enteringQuery" });
|
|
2819
|
+
const handleExpertSelect = useCallback((expertKey) => {
|
|
2820
|
+
dispatch({ type: "SELECT_EXPERT", expertKey });
|
|
2821
|
+
}, []);
|
|
2822
|
+
const handleJobSelect = useCallback(
|
|
2823
|
+
async (job) => {
|
|
2824
|
+
try {
|
|
2825
|
+
const checkpoints = await onLoadCheckpoints(job);
|
|
2826
|
+
dispatch({ type: "SELECT_JOB", job, checkpoints });
|
|
2827
|
+
} catch {
|
|
2828
|
+
dispatch({ type: "SELECT_JOB", job, checkpoints: [] });
|
|
2829
|
+
}
|
|
2830
|
+
},
|
|
2831
|
+
[onLoadCheckpoints]
|
|
2832
|
+
);
|
|
2833
|
+
const handleJobResume = useCallback(
|
|
2834
|
+
async (job) => {
|
|
2835
|
+
try {
|
|
2836
|
+
const checkpoints = await onLoadCheckpoints(job);
|
|
2837
|
+
const latestCheckpoint = checkpoints[0];
|
|
2838
|
+
if (latestCheckpoint) {
|
|
2839
|
+
setSelectedCheckpoint(latestCheckpoint);
|
|
2840
|
+
}
|
|
2841
|
+
dispatch({ type: "SELECT_EXPERT", expertKey: job.expertKey });
|
|
2842
|
+
} catch {
|
|
2843
|
+
dispatch({ type: "SELECT_EXPERT", expertKey: job.expertKey });
|
|
2844
|
+
}
|
|
2845
|
+
},
|
|
2846
|
+
[onLoadCheckpoints]
|
|
2847
|
+
);
|
|
2848
|
+
const handleCheckpointResume = useCallback(
|
|
2849
|
+
(checkpoint) => {
|
|
2850
|
+
setSelectedCheckpoint(checkpoint);
|
|
2851
|
+
if (state.type === "browsingCheckpoints") {
|
|
2852
|
+
dispatch({ type: "SELECT_EXPERT", expertKey: state.job.expertKey });
|
|
2853
|
+
}
|
|
2854
|
+
},
|
|
2855
|
+
[state]
|
|
2856
|
+
);
|
|
2857
|
+
const handleBack = useCallback(() => {
|
|
2858
|
+
if (state.type === "browsingCheckpoints") {
|
|
2859
|
+
dispatch({ type: "GO_BACK_FROM_CHECKPOINTS", jobs: historyJobs });
|
|
2860
|
+
}
|
|
2861
|
+
}, [state, historyJobs]);
|
|
2862
|
+
const handleSwitchToExperts = useCallback(() => {
|
|
2863
|
+
dispatch({ type: "BROWSE_EXPERTS", experts: allExperts });
|
|
2864
|
+
}, [allExperts]);
|
|
2865
|
+
const handleSwitchToHistory = useCallback(() => {
|
|
2866
|
+
dispatch({ type: "BROWSE_HISTORY", jobs: historyJobs });
|
|
2867
|
+
}, [historyJobs]);
|
|
2868
|
+
useInput((input, key) => {
|
|
2869
|
+
if (key.ctrl && input === "c") {
|
|
2870
|
+
exit();
|
|
2871
|
+
}
|
|
2872
|
+
});
|
|
2873
|
+
const contextValue = useMemo(
|
|
2874
|
+
() => ({
|
|
2875
|
+
onExpertSelect: handleExpertSelect,
|
|
2876
|
+
onQuerySubmit: () => {
|
|
2877
|
+
},
|
|
2878
|
+
// Not used in browser
|
|
2879
|
+
onJobSelect: handleJobSelect,
|
|
2880
|
+
onJobResume: handleJobResume,
|
|
2881
|
+
onCheckpointSelect: () => {
|
|
2882
|
+
},
|
|
2883
|
+
// Not used in selection (no event browsing)
|
|
2884
|
+
onCheckpointResume: handleCheckpointResume,
|
|
2885
|
+
onEventSelect: () => {
|
|
2886
|
+
},
|
|
2887
|
+
// Not used in selection
|
|
2888
|
+
onBack: handleBack,
|
|
2889
|
+
onSwitchToExperts: handleSwitchToExperts,
|
|
2890
|
+
onSwitchToHistory: handleSwitchToHistory
|
|
2891
|
+
}),
|
|
2892
|
+
[
|
|
2893
|
+
handleExpertSelect,
|
|
2894
|
+
handleJobSelect,
|
|
2895
|
+
handleJobResume,
|
|
2896
|
+
handleCheckpointResume,
|
|
2897
|
+
handleBack,
|
|
2898
|
+
handleSwitchToExperts,
|
|
2899
|
+
handleSwitchToHistory
|
|
2900
|
+
]
|
|
2901
|
+
);
|
|
2902
|
+
if (initialExpertKey && initialQuery) {
|
|
2903
|
+
return null;
|
|
2904
|
+
}
|
|
2905
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
2906
|
+
/* @__PURE__ */ jsx(InputAreaProvider, { value: contextValue, children: (state.type === "browsingHistory" || state.type === "browsingExperts" || state.type === "browsingCheckpoints") && /* @__PURE__ */ jsx(
|
|
3322
2907
|
BrowserRouter,
|
|
3323
2908
|
{
|
|
3324
|
-
inputState
|
|
2909
|
+
inputState: state,
|
|
2910
|
+
showEventsHint: false
|
|
3325
2911
|
}
|
|
3326
2912
|
) }),
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
2913
|
+
state.type === "enteringQuery" && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "gray", children: [
|
|
2914
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
2915
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "Expert:" }),
|
|
2916
|
+
" ",
|
|
2917
|
+
/* @__PURE__ */ jsx(Text, { children: state.expertKey }),
|
|
2918
|
+
selectedCheckpoint && /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
|
|
2919
|
+
" (resuming from step ",
|
|
2920
|
+
selectedCheckpoint.stepNumber,
|
|
2921
|
+
")"
|
|
2922
|
+
] })
|
|
2923
|
+
] }),
|
|
2924
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
2925
|
+
/* @__PURE__ */ jsx(Text, { color: "gray", children: "Query: " }),
|
|
2926
|
+
/* @__PURE__ */ jsx(Text, { children: queryInput }),
|
|
2927
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: "_" })
|
|
2928
|
+
] }),
|
|
2929
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Press Enter to start" })
|
|
2930
|
+
] })
|
|
3337
2931
|
] });
|
|
3338
2932
|
};
|
|
3339
|
-
|
|
3340
|
-
const eventQueue = new EventQueue();
|
|
3341
|
-
return {
|
|
3342
|
-
setHandler: (fn) => eventQueue.setHandler(fn),
|
|
3343
|
-
emit: (event) => eventQueue.emit(event)
|
|
3344
|
-
};
|
|
3345
|
-
};
|
|
3346
|
-
async function renderStart(options) {
|
|
2933
|
+
async function renderSelection(params) {
|
|
3347
2934
|
return new Promise((resolve2, reject) => {
|
|
3348
|
-
const emitter = createEventEmitter();
|
|
3349
2935
|
let resolved = false;
|
|
3350
2936
|
const { waitUntilExit } = render(
|
|
3351
2937
|
/* @__PURE__ */ jsx(
|
|
3352
|
-
|
|
2938
|
+
SelectionApp,
|
|
3353
2939
|
{
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
initialExpertName: options.initialExpertName,
|
|
3357
|
-
initialQuery: options.initialQuery,
|
|
3358
|
-
initialConfig: options.initialConfig,
|
|
3359
|
-
configuredExperts: options.configuredExperts,
|
|
3360
|
-
recentExperts: options.recentExperts,
|
|
3361
|
-
historyJobs: options.historyJobs,
|
|
3362
|
-
onComplete: (expertKey, query) => {
|
|
2940
|
+
...params,
|
|
2941
|
+
onComplete: (result) => {
|
|
3363
2942
|
resolved = true;
|
|
3364
|
-
resolve2(
|
|
3365
|
-
|
|
3366
|
-
query,
|
|
3367
|
-
eventListener: emitter.emit
|
|
3368
|
-
});
|
|
3369
|
-
},
|
|
3370
|
-
onContinue: options.onContinue,
|
|
3371
|
-
onResumeFromCheckpoint: options.onResumeFromCheckpoint,
|
|
3372
|
-
onLoadCheckpoints: options.onLoadCheckpoints,
|
|
3373
|
-
onLoadEvents: options.onLoadEvents,
|
|
3374
|
-
onLoadHistoricalEvents: options.onLoadHistoricalEvents,
|
|
3375
|
-
onReady: emitter.setHandler
|
|
2943
|
+
resolve2(result);
|
|
2944
|
+
}
|
|
3376
2945
|
}
|
|
3377
2946
|
)
|
|
3378
2947
|
);
|
|
3379
2948
|
waitUntilExit().then(() => {
|
|
3380
2949
|
if (!resolved) {
|
|
3381
|
-
reject(new Error("
|
|
2950
|
+
reject(new Error("Selection cancelled"));
|
|
3382
2951
|
}
|
|
3383
|
-
}).catch(
|
|
3384
|
-
options.onError?.(error);
|
|
3385
|
-
reject(error);
|
|
3386
|
-
});
|
|
2952
|
+
}).catch(reject);
|
|
3387
2953
|
});
|
|
3388
2954
|
}
|
|
3389
2955
|
function getAvailableStatusTransitions(currentStatus) {
|
|
@@ -3509,30 +3075,15 @@ function ConfirmStep({
|
|
|
3509
3075
|
}
|
|
3510
3076
|
function StatusApp({ experts, onFetchVersions, onComplete, onCancel }) {
|
|
3511
3077
|
const { exit } = useApp();
|
|
3512
|
-
const
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
const versions = await onFetchVersions(expertName);
|
|
3517
|
-
if (versions.length === 0) {
|
|
3518
|
-
setStep({ type: "error", message: `No versions found for ${expertName}` });
|
|
3519
|
-
return;
|
|
3520
|
-
}
|
|
3521
|
-
setStep({ type: "selectVersion", expertName, versions });
|
|
3522
|
-
} catch (error) {
|
|
3523
|
-
setStep({
|
|
3524
|
-
type: "error",
|
|
3525
|
-
message: error instanceof Error ? error.message : "Failed to fetch versions"
|
|
3526
|
-
});
|
|
3527
|
-
}
|
|
3528
|
-
};
|
|
3529
|
-
const handleVersionSelect = (version) => {
|
|
3530
|
-
setStep({
|
|
3078
|
+
const { step, setStep, handlers, renderBaseStep, isBaseStep: isBaseStep2 } = useExpertVersionWizard({
|
|
3079
|
+
experts,
|
|
3080
|
+
onFetchVersions,
|
|
3081
|
+
customStepFromVersion: (version) => ({
|
|
3531
3082
|
type: "selectStatus",
|
|
3532
3083
|
expertKey: version.key,
|
|
3533
3084
|
currentStatus: version.status
|
|
3534
|
-
})
|
|
3535
|
-
};
|
|
3085
|
+
})
|
|
3086
|
+
});
|
|
3536
3087
|
const handleStatusSelect = (status) => {
|
|
3537
3088
|
if (step.type === "selectStatus") {
|
|
3538
3089
|
setStep({
|
|
@@ -3552,81 +3103,54 @@ function StatusApp({ experts, onFetchVersions, onComplete, onCancel }) {
|
|
|
3552
3103
|
exit();
|
|
3553
3104
|
}
|
|
3554
3105
|
};
|
|
3555
|
-
const
|
|
3556
|
-
switch (
|
|
3557
|
-
case "selectVersion":
|
|
3558
|
-
setStep({ type: "selectExpert" });
|
|
3559
|
-
break;
|
|
3106
|
+
const handleCustomBack = (currentStep) => {
|
|
3107
|
+
switch (currentStep.type) {
|
|
3560
3108
|
case "selectStatus":
|
|
3561
3109
|
setStep({ type: "selectExpert" });
|
|
3562
3110
|
break;
|
|
3563
3111
|
case "confirm":
|
|
3564
3112
|
setStep({
|
|
3565
3113
|
type: "selectStatus",
|
|
3566
|
-
expertKey:
|
|
3567
|
-
currentStatus:
|
|
3114
|
+
expertKey: currentStep.expertKey,
|
|
3115
|
+
currentStatus: currentStep.currentStatus
|
|
3568
3116
|
});
|
|
3569
3117
|
break;
|
|
3570
|
-
case "error":
|
|
3571
|
-
setStep({ type: "selectExpert" });
|
|
3572
|
-
break;
|
|
3573
3118
|
default:
|
|
3574
3119
|
onCancel();
|
|
3575
3120
|
exit();
|
|
3576
3121
|
}
|
|
3577
3122
|
};
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
{
|
|
3608
|
-
expertKey: step.expertKey,
|
|
3609
|
-
currentStatus: step.currentStatus,
|
|
3610
|
-
onSelect: handleStatusSelect,
|
|
3611
|
-
onBack: handleBack
|
|
3612
|
-
}
|
|
3613
|
-
);
|
|
3614
|
-
case "confirm":
|
|
3615
|
-
return /* @__PURE__ */ jsx(
|
|
3616
|
-
ConfirmStep,
|
|
3617
|
-
{
|
|
3618
|
-
expertKey: step.expertKey,
|
|
3619
|
-
status: step.status,
|
|
3620
|
-
currentStatus: step.currentStatus,
|
|
3621
|
-
onConfirm: handleConfirm,
|
|
3622
|
-
onBack: handleBack
|
|
3623
|
-
}
|
|
3624
|
-
);
|
|
3625
|
-
case "error":
|
|
3626
|
-
return /* @__PURE__ */ jsx(ErrorStep, { message: step.message, onBack: handleBack });
|
|
3627
|
-
default:
|
|
3628
|
-
return null;
|
|
3123
|
+
const baseStepRender = renderBaseStep({ title: "Select an Expert to change status:" });
|
|
3124
|
+
if (baseStepRender) {
|
|
3125
|
+
return baseStepRender;
|
|
3126
|
+
}
|
|
3127
|
+
if (!isBaseStep2) {
|
|
3128
|
+
const customStep = step;
|
|
3129
|
+
switch (customStep.type) {
|
|
3130
|
+
case "selectStatus":
|
|
3131
|
+
return /* @__PURE__ */ jsx(
|
|
3132
|
+
StatusSelector,
|
|
3133
|
+
{
|
|
3134
|
+
expertKey: customStep.expertKey,
|
|
3135
|
+
currentStatus: customStep.currentStatus,
|
|
3136
|
+
onSelect: handleStatusSelect,
|
|
3137
|
+
onBack: () => handlers.handleBack(handleCustomBack)
|
|
3138
|
+
}
|
|
3139
|
+
);
|
|
3140
|
+
case "confirm":
|
|
3141
|
+
return /* @__PURE__ */ jsx(
|
|
3142
|
+
ConfirmStep,
|
|
3143
|
+
{
|
|
3144
|
+
expertKey: customStep.expertKey,
|
|
3145
|
+
status: customStep.status,
|
|
3146
|
+
currentStatus: customStep.currentStatus,
|
|
3147
|
+
onConfirm: handleConfirm,
|
|
3148
|
+
onBack: () => handlers.handleBack(handleCustomBack)
|
|
3149
|
+
}
|
|
3150
|
+
);
|
|
3151
|
+
}
|
|
3629
3152
|
}
|
|
3153
|
+
return null;
|
|
3630
3154
|
}
|
|
3631
3155
|
async function renderStatus(options) {
|
|
3632
3156
|
return new Promise((resolve2) => {
|
|
@@ -3776,30 +3300,15 @@ function ConfirmStep2({
|
|
|
3776
3300
|
}
|
|
3777
3301
|
function TagApp({ experts, onFetchVersions, onComplete, onCancel }) {
|
|
3778
3302
|
const { exit } = useApp();
|
|
3779
|
-
const
|
|
3780
|
-
|
|
3781
|
-
|
|
3782
|
-
|
|
3783
|
-
const versions = await onFetchVersions(expertName);
|
|
3784
|
-
if (versions.length === 0) {
|
|
3785
|
-
setStep({ type: "error", message: `No versions found for ${expertName}` });
|
|
3786
|
-
return;
|
|
3787
|
-
}
|
|
3788
|
-
setStep({ type: "selectVersion", expertName, versions });
|
|
3789
|
-
} catch (error) {
|
|
3790
|
-
setStep({
|
|
3791
|
-
type: "error",
|
|
3792
|
-
message: error instanceof Error ? error.message : "Failed to fetch versions"
|
|
3793
|
-
});
|
|
3794
|
-
}
|
|
3795
|
-
};
|
|
3796
|
-
const handleVersionSelect = (version) => {
|
|
3797
|
-
setStep({
|
|
3303
|
+
const { step, setStep, handlers, renderBaseStep, isBaseStep: isBaseStep2 } = useExpertVersionWizard({
|
|
3304
|
+
experts,
|
|
3305
|
+
onFetchVersions,
|
|
3306
|
+
customStepFromVersion: (version) => ({
|
|
3798
3307
|
type: "inputTags",
|
|
3799
3308
|
expertKey: version.key,
|
|
3800
3309
|
currentTags: version.tags
|
|
3801
|
-
})
|
|
3802
|
-
};
|
|
3310
|
+
})
|
|
3311
|
+
});
|
|
3803
3312
|
const handleTagsSubmit = (tags) => {
|
|
3804
3313
|
if (step.type === "inputTags") {
|
|
3805
3314
|
setStep({
|
|
@@ -3819,81 +3328,54 @@ function TagApp({ experts, onFetchVersions, onComplete, onCancel }) {
|
|
|
3819
3328
|
exit();
|
|
3820
3329
|
}
|
|
3821
3330
|
};
|
|
3822
|
-
const
|
|
3823
|
-
switch (
|
|
3824
|
-
case "selectVersion":
|
|
3825
|
-
setStep({ type: "selectExpert" });
|
|
3826
|
-
break;
|
|
3331
|
+
const handleCustomBack = (currentStep) => {
|
|
3332
|
+
switch (currentStep.type) {
|
|
3827
3333
|
case "inputTags":
|
|
3828
3334
|
setStep({ type: "selectExpert" });
|
|
3829
3335
|
break;
|
|
3830
3336
|
case "confirm":
|
|
3831
3337
|
setStep({
|
|
3832
3338
|
type: "inputTags",
|
|
3833
|
-
expertKey:
|
|
3834
|
-
currentTags:
|
|
3339
|
+
expertKey: currentStep.expertKey,
|
|
3340
|
+
currentTags: currentStep.currentTags
|
|
3835
3341
|
});
|
|
3836
3342
|
break;
|
|
3837
|
-
case "error":
|
|
3838
|
-
setStep({ type: "selectExpert" });
|
|
3839
|
-
break;
|
|
3840
3343
|
default:
|
|
3841
3344
|
onCancel();
|
|
3842
3345
|
exit();
|
|
3843
3346
|
}
|
|
3844
3347
|
};
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
|
|
3853
|
-
|
|
3854
|
-
|
|
3855
|
-
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
|
|
3859
|
-
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
{
|
|
3875
|
-
expertKey: step.expertKey,
|
|
3876
|
-
currentTags: step.currentTags,
|
|
3877
|
-
onSubmit: handleTagsSubmit,
|
|
3878
|
-
onBack: handleBack
|
|
3879
|
-
}
|
|
3880
|
-
);
|
|
3881
|
-
case "confirm":
|
|
3882
|
-
return /* @__PURE__ */ jsx(
|
|
3883
|
-
ConfirmStep2,
|
|
3884
|
-
{
|
|
3885
|
-
expertKey: step.expertKey,
|
|
3886
|
-
tags: step.tags,
|
|
3887
|
-
currentTags: step.currentTags,
|
|
3888
|
-
onConfirm: handleConfirm,
|
|
3889
|
-
onBack: handleBack
|
|
3890
|
-
}
|
|
3891
|
-
);
|
|
3892
|
-
case "error":
|
|
3893
|
-
return /* @__PURE__ */ jsx(ErrorStep, { message: step.message, onBack: handleBack });
|
|
3894
|
-
default:
|
|
3895
|
-
return null;
|
|
3348
|
+
const baseStepRender = renderBaseStep({ title: "Select an Expert to tag:" });
|
|
3349
|
+
if (baseStepRender) {
|
|
3350
|
+
return baseStepRender;
|
|
3351
|
+
}
|
|
3352
|
+
if (!isBaseStep2) {
|
|
3353
|
+
const customStep = step;
|
|
3354
|
+
switch (customStep.type) {
|
|
3355
|
+
case "inputTags":
|
|
3356
|
+
return /* @__PURE__ */ jsx(
|
|
3357
|
+
TagInput,
|
|
3358
|
+
{
|
|
3359
|
+
expertKey: customStep.expertKey,
|
|
3360
|
+
currentTags: customStep.currentTags,
|
|
3361
|
+
onSubmit: handleTagsSubmit,
|
|
3362
|
+
onBack: () => handlers.handleBack(handleCustomBack)
|
|
3363
|
+
}
|
|
3364
|
+
);
|
|
3365
|
+
case "confirm":
|
|
3366
|
+
return /* @__PURE__ */ jsx(
|
|
3367
|
+
ConfirmStep2,
|
|
3368
|
+
{
|
|
3369
|
+
expertKey: customStep.expertKey,
|
|
3370
|
+
tags: customStep.tags,
|
|
3371
|
+
currentTags: customStep.currentTags,
|
|
3372
|
+
onConfirm: handleConfirm,
|
|
3373
|
+
onBack: () => handlers.handleBack(handleCustomBack)
|
|
3374
|
+
}
|
|
3375
|
+
);
|
|
3376
|
+
}
|
|
3896
3377
|
}
|
|
3378
|
+
return null;
|
|
3897
3379
|
}
|
|
3898
3380
|
async function renderTag(options) {
|
|
3899
3381
|
return new Promise((resolve2) => {
|
|
@@ -3984,94 +3466,50 @@ function UnpublishApp({
|
|
|
3984
3466
|
onCancel
|
|
3985
3467
|
}) {
|
|
3986
3468
|
const { exit } = useApp();
|
|
3987
|
-
const
|
|
3988
|
-
|
|
3989
|
-
|
|
3990
|
-
|
|
3991
|
-
const versions = await onFetchVersions(expertName);
|
|
3992
|
-
if (versions.length === 0) {
|
|
3993
|
-
setStep({ type: "error", message: `No versions found for ${expertName}` });
|
|
3994
|
-
return;
|
|
3995
|
-
}
|
|
3996
|
-
setStep({ type: "selectVersion", expertName, versions });
|
|
3997
|
-
} catch (error) {
|
|
3998
|
-
setStep({
|
|
3999
|
-
type: "error",
|
|
4000
|
-
message: error instanceof Error ? error.message : "Failed to fetch versions"
|
|
4001
|
-
});
|
|
4002
|
-
}
|
|
4003
|
-
};
|
|
4004
|
-
const handleVersionSelect = (version) => {
|
|
4005
|
-
setStep({
|
|
3469
|
+
const { step, setStep, handlers, renderBaseStep, isBaseStep: isBaseStep2 } = useExpertVersionWizard({
|
|
3470
|
+
experts,
|
|
3471
|
+
onFetchVersions,
|
|
3472
|
+
customStepFromVersion: (version) => ({
|
|
4006
3473
|
type: "confirm",
|
|
4007
3474
|
expertKey: version.key,
|
|
4008
3475
|
version: version.version
|
|
4009
|
-
})
|
|
4010
|
-
};
|
|
3476
|
+
})
|
|
3477
|
+
});
|
|
4011
3478
|
const handleConfirm = () => {
|
|
4012
3479
|
if (step.type === "confirm") {
|
|
4013
3480
|
onComplete({ expertKey: step.expertKey });
|
|
4014
3481
|
exit();
|
|
4015
3482
|
}
|
|
4016
3483
|
};
|
|
4017
|
-
const
|
|
4018
|
-
switch (
|
|
4019
|
-
case "selectVersion":
|
|
4020
|
-
setStep({ type: "selectExpert" });
|
|
4021
|
-
break;
|
|
3484
|
+
const handleCustomBack = (currentStep) => {
|
|
3485
|
+
switch (currentStep.type) {
|
|
4022
3486
|
case "confirm":
|
|
4023
3487
|
setStep({ type: "selectExpert" });
|
|
4024
3488
|
break;
|
|
4025
|
-
case "error":
|
|
4026
|
-
setStep({ type: "selectExpert" });
|
|
4027
|
-
break;
|
|
4028
3489
|
default:
|
|
4029
3490
|
onCancel();
|
|
4030
3491
|
exit();
|
|
4031
3492
|
}
|
|
4032
3493
|
};
|
|
4033
|
-
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
return /* @__PURE__ */ jsx(
|
|
4051
|
-
VersionSelector,
|
|
4052
|
-
{
|
|
4053
|
-
expertName: step.expertName,
|
|
4054
|
-
versions: step.versions,
|
|
4055
|
-
onSelect: handleVersionSelect,
|
|
4056
|
-
onBack: handleBack,
|
|
4057
|
-
title: `Select a version of ${step.expertName} to unpublish:`
|
|
4058
|
-
}
|
|
4059
|
-
);
|
|
4060
|
-
case "confirm":
|
|
4061
|
-
return /* @__PURE__ */ jsx(
|
|
4062
|
-
ConfirmStep3,
|
|
4063
|
-
{
|
|
4064
|
-
expertKey: step.expertKey,
|
|
4065
|
-
version: step.version,
|
|
4066
|
-
onConfirm: handleConfirm,
|
|
4067
|
-
onBack: handleBack
|
|
4068
|
-
}
|
|
4069
|
-
);
|
|
4070
|
-
case "error":
|
|
4071
|
-
return /* @__PURE__ */ jsx(ErrorStep, { message: step.message, onBack: handleBack });
|
|
4072
|
-
default:
|
|
4073
|
-
return null;
|
|
3494
|
+
const baseStepRender = renderBaseStep({
|
|
3495
|
+
title: "Select an Expert to unpublish:",
|
|
3496
|
+
versionSelectorTitle: `Select a version to unpublish:`
|
|
3497
|
+
});
|
|
3498
|
+
if (baseStepRender) {
|
|
3499
|
+
return baseStepRender;
|
|
3500
|
+
}
|
|
3501
|
+
if (!isBaseStep2 && step.type === "confirm") {
|
|
3502
|
+
return /* @__PURE__ */ jsx(
|
|
3503
|
+
ConfirmStep3,
|
|
3504
|
+
{
|
|
3505
|
+
expertKey: step.expertKey,
|
|
3506
|
+
version: step.version,
|
|
3507
|
+
onConfirm: handleConfirm,
|
|
3508
|
+
onBack: () => handlers.handleBack(handleCustomBack)
|
|
3509
|
+
}
|
|
3510
|
+
);
|
|
4074
3511
|
}
|
|
3512
|
+
return null;
|
|
4075
3513
|
}
|
|
4076
3514
|
async function renderUnpublish(options) {
|
|
4077
3515
|
return new Promise((resolve2) => {
|
|
@@ -4337,6 +3775,9 @@ function getMostRecentRun() {
|
|
|
4337
3775
|
}
|
|
4338
3776
|
return runs[0];
|
|
4339
3777
|
}
|
|
3778
|
+
function getRunsByJobId(jobId) {
|
|
3779
|
+
return getAllRuns2().filter((r) => r.jobId === jobId);
|
|
3780
|
+
}
|
|
4340
3781
|
function getCheckpointsByJobId2(jobId) {
|
|
4341
3782
|
return getCheckpointsByJobId(jobId);
|
|
4342
3783
|
}
|
|
@@ -4379,18 +3820,18 @@ function getCheckpointsWithDetails(jobId) {
|
|
|
4379
3820
|
contextWindowUsage: cp.contextWindowUsage ?? 0
|
|
4380
3821
|
})).sort((a, b) => b.stepNumber - a.stepNumber);
|
|
4381
3822
|
}
|
|
4382
|
-
function getEventsWithDetails(jobId, runId, stepNumber) {
|
|
4383
|
-
return getEventsByRun(jobId, runId).map((e) => ({
|
|
4384
|
-
id: `${e.timestamp}-${e.stepNumber}-${e.type}`,
|
|
4385
|
-
runId,
|
|
4386
|
-
stepNumber: e.stepNumber,
|
|
4387
|
-
type: e.type,
|
|
4388
|
-
timestamp: e.timestamp
|
|
4389
|
-
})).filter((event) => stepNumber === void 0 || event.stepNumber === stepNumber).sort((a, b) => a.timestamp - b.timestamp);
|
|
4390
|
-
}
|
|
4391
3823
|
function getEventContents2(jobId, runId, maxStepNumber) {
|
|
4392
3824
|
return getEventContents(jobId, runId, maxStepNumber);
|
|
4393
3825
|
}
|
|
3826
|
+
function getAllEventContentsForJob(jobId, maxStepNumber) {
|
|
3827
|
+
const runs = getRunsByJobId(jobId);
|
|
3828
|
+
const allEvents = [];
|
|
3829
|
+
for (const run of runs) {
|
|
3830
|
+
const events = getEventContents(jobId, run.runId, maxStepNumber);
|
|
3831
|
+
allEvents.push(...events);
|
|
3832
|
+
}
|
|
3833
|
+
return allEvents.sort((a, b) => a.timestamp - b.timestamp);
|
|
3834
|
+
}
|
|
4394
3835
|
|
|
4395
3836
|
// src/lib/context.ts
|
|
4396
3837
|
var defaultProvider = "anthropic";
|
|
@@ -4402,11 +3843,11 @@ async function resolveRunContext(input) {
|
|
|
4402
3843
|
if (!input.continueJob) {
|
|
4403
3844
|
throw new Error("--resume-from requires --continue-job");
|
|
4404
3845
|
}
|
|
4405
|
-
checkpoint =
|
|
3846
|
+
checkpoint = getCheckpointById(input.continueJob, input.resumeFrom);
|
|
4406
3847
|
} else if (input.continueJob) {
|
|
4407
|
-
checkpoint =
|
|
3848
|
+
checkpoint = getMostRecentCheckpoint(input.continueJob);
|
|
4408
3849
|
} else if (input.continue) {
|
|
4409
|
-
checkpoint =
|
|
3850
|
+
checkpoint = getMostRecentCheckpoint();
|
|
4410
3851
|
}
|
|
4411
3852
|
if ((input.continue || input.continueJob || input.resumeFrom) && !checkpoint) {
|
|
4412
3853
|
throw new Error("No checkpoint found");
|
|
@@ -6357,9 +5798,6 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
|
|
|
6357
5798
|
const text = content.text?.trim();
|
|
6358
5799
|
if (text && text !== state.lastStreamingText) {
|
|
6359
5800
|
state.lastStreamingText = text;
|
|
6360
|
-
const event = createStreamingTextEvent(jobId, runId, text);
|
|
6361
|
-
state.events.push(event);
|
|
6362
|
-
eventListener?.(event);
|
|
6363
5801
|
}
|
|
6364
5802
|
} else if (content.type === "tool_use") {
|
|
6365
5803
|
const toolCall = {
|
|
@@ -6433,11 +5871,7 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
|
|
|
6433
5871
|
} else if (parsed.type === "content_block_delta" && parsed.delta) {
|
|
6434
5872
|
const delta = parsed.delta;
|
|
6435
5873
|
const text = delta.text?.trim();
|
|
6436
|
-
if (delta.type === "text_delta" && text)
|
|
6437
|
-
const event = createStreamingTextEvent(jobId, runId, text);
|
|
6438
|
-
state.events.push(event);
|
|
6439
|
-
eventListener?.(event);
|
|
6440
|
-
}
|
|
5874
|
+
if (delta.type === "text_delta" && text) ;
|
|
6441
5875
|
}
|
|
6442
5876
|
}
|
|
6443
5877
|
};
|
|
@@ -6646,9 +6080,6 @@ ${query}`;
|
|
|
6646
6080
|
const text = content.text?.trim();
|
|
6647
6081
|
if (content.type === "text" && text && text !== state.lastStreamingText) {
|
|
6648
6082
|
state.lastStreamingText = text;
|
|
6649
|
-
const event = createStreamingTextEvent(jobId, runId, text);
|
|
6650
|
-
state.events.push(event);
|
|
6651
|
-
eventListener?.(event);
|
|
6652
6083
|
}
|
|
6653
6084
|
}
|
|
6654
6085
|
}
|
|
@@ -7040,10 +6471,16 @@ function validateWorkspacePath(path11) {
|
|
|
7040
6471
|
}
|
|
7041
6472
|
}
|
|
7042
6473
|
function generateComposeFile(options) {
|
|
7043
|
-
const { proxyEnabled, networkName, envKeys, workspacePath } = options;
|
|
6474
|
+
const { proxyEnabled, networkName, envKeys, workspacePath, additionalVolumes } = options;
|
|
7044
6475
|
if (workspacePath) {
|
|
7045
6476
|
validateWorkspacePath(workspacePath);
|
|
7046
6477
|
}
|
|
6478
|
+
for (const volume of additionalVolumes ?? []) {
|
|
6479
|
+
const hostPath = volume.split(":")[0];
|
|
6480
|
+
if (hostPath) {
|
|
6481
|
+
validateWorkspacePath(hostPath);
|
|
6482
|
+
}
|
|
6483
|
+
}
|
|
7047
6484
|
const internalNetworkName = `${networkName}-internal`;
|
|
7048
6485
|
const lines = [];
|
|
7049
6486
|
lines.push("services:");
|
|
@@ -7066,9 +6503,15 @@ function generateComposeFile(options) {
|
|
|
7066
6503
|
lines.push(` - ${key}`);
|
|
7067
6504
|
}
|
|
7068
6505
|
}
|
|
7069
|
-
|
|
6506
|
+
const hasVolumes = workspacePath || additionalVolumes && additionalVolumes.length > 0;
|
|
6507
|
+
if (hasVolumes) {
|
|
7070
6508
|
lines.push(" volumes:");
|
|
7071
|
-
|
|
6509
|
+
if (workspacePath) {
|
|
6510
|
+
lines.push(` - ${workspacePath}:/workspace:rw`);
|
|
6511
|
+
}
|
|
6512
|
+
for (const volume of additionalVolumes ?? []) {
|
|
6513
|
+
lines.push(` - ${volume}`);
|
|
6514
|
+
}
|
|
7072
6515
|
}
|
|
7073
6516
|
lines.push(" stdin_open: true");
|
|
7074
6517
|
lines.push(" tty: true");
|
|
@@ -7119,7 +6562,12 @@ function generateComposeFile(options) {
|
|
|
7119
6562
|
return lines.join("\n");
|
|
7120
6563
|
}
|
|
7121
6564
|
function generateBuildContext(config, expertKey, options) {
|
|
7122
|
-
const { workspacePath, verbose, additionalEnvKeys } = typeof options === "string" || options === void 0 ? {
|
|
6565
|
+
const { workspacePath, verbose, additionalEnvKeys, additionalVolumes } = typeof options === "string" || options === void 0 ? {
|
|
6566
|
+
workspacePath: options,
|
|
6567
|
+
verbose: false,
|
|
6568
|
+
additionalEnvKeys: [],
|
|
6569
|
+
additionalVolumes: []
|
|
6570
|
+
} : { additionalEnvKeys: [], additionalVolumes: [], ...options };
|
|
7123
6571
|
const allowedDomains = collectAllowedDomains(config, expertKey);
|
|
7124
6572
|
const hasAllowlist = allowedDomains.length > 0;
|
|
7125
6573
|
const dockerfile = generateDockerfile(config, expertKey, { proxyEnabled: hasAllowlist });
|
|
@@ -7143,7 +6591,8 @@ function generateBuildContext(config, expertKey, options) {
|
|
|
7143
6591
|
proxyEnabled: hasAllowlist,
|
|
7144
6592
|
networkName: "perstack-net",
|
|
7145
6593
|
envKeys: allEnvKeys,
|
|
7146
|
-
workspacePath: resolvedWorkspacePath
|
|
6594
|
+
workspacePath: resolvedWorkspacePath,
|
|
6595
|
+
additionalVolumes
|
|
7147
6596
|
});
|
|
7148
6597
|
return {
|
|
7149
6598
|
dockerfile,
|
|
@@ -7437,7 +6886,7 @@ var DockerAdapter = class extends BaseAdapter {
|
|
|
7437
6886
|
return { instruction: expert.instruction };
|
|
7438
6887
|
}
|
|
7439
6888
|
async run(params) {
|
|
7440
|
-
const { setting, config, eventListener, workspace, additionalEnvKeys } = params;
|
|
6889
|
+
const { setting, config, eventListener, workspace, additionalEnvKeys, additionalVolumes } = params;
|
|
7441
6890
|
if (!config) {
|
|
7442
6891
|
throw new Error("DockerAdapter requires config in AdapterRunParams");
|
|
7443
6892
|
}
|
|
@@ -7452,7 +6901,8 @@ var DockerAdapter = class extends BaseAdapter {
|
|
|
7452
6901
|
expertKey,
|
|
7453
6902
|
resolvedWorkspace,
|
|
7454
6903
|
setting.verbose,
|
|
7455
|
-
additionalEnvKeys
|
|
6904
|
+
additionalEnvKeys,
|
|
6905
|
+
additionalVolumes
|
|
7456
6906
|
);
|
|
7457
6907
|
let signalReceived = false;
|
|
7458
6908
|
const signalHandler = async (signal) => {
|
|
@@ -7538,12 +6988,13 @@ var DockerAdapter = class extends BaseAdapter {
|
|
|
7538
6988
|
}
|
|
7539
6989
|
return resolved;
|
|
7540
6990
|
}
|
|
7541
|
-
async prepareBuildContext(config, expertKey, workspace, verbose, additionalEnvKeys) {
|
|
6991
|
+
async prepareBuildContext(config, expertKey, workspace, verbose, additionalEnvKeys, additionalVolumes) {
|
|
7542
6992
|
const buildDir = fs.mkdtempSync(path10.join(os.tmpdir(), "perstack-docker-"));
|
|
7543
6993
|
const context = generateBuildContext(config, expertKey, {
|
|
7544
6994
|
workspacePath: workspace,
|
|
7545
6995
|
verbose,
|
|
7546
|
-
additionalEnvKeys
|
|
6996
|
+
additionalEnvKeys,
|
|
6997
|
+
additionalVolumes
|
|
7547
6998
|
});
|
|
7548
6999
|
fs.writeFileSync(path10.join(buildDir, "Dockerfile"), context.dockerfile);
|
|
7549
7000
|
fs.writeFileSync(path10.join(buildDir, "perstack.toml"), context.configToml);
|
|
@@ -7910,9 +7361,6 @@ ${query}`;
|
|
|
7910
7361
|
state.finalOutput = state.accumulatedText;
|
|
7911
7362
|
if (content !== state.lastStreamingText) {
|
|
7912
7363
|
state.lastStreamingText = content;
|
|
7913
|
-
const event = createStreamingTextEvent(jobId, runId, state.accumulatedText);
|
|
7914
|
-
state.events.push(event);
|
|
7915
|
-
eventListener?.(event);
|
|
7916
7364
|
}
|
|
7917
7365
|
}
|
|
7918
7366
|
} else if (parsed.type === "tool_use") {
|
|
@@ -8004,12 +7452,14 @@ async function dispatchToRuntime(params) {
|
|
|
8004
7452
|
storeEvent,
|
|
8005
7453
|
retrieveCheckpoint,
|
|
8006
7454
|
workspace,
|
|
8007
|
-
additionalEnvKeys
|
|
7455
|
+
additionalEnvKeys,
|
|
7456
|
+
additionalVolumes
|
|
8008
7457
|
} = params;
|
|
8009
7458
|
const setting = {
|
|
8010
7459
|
...params.setting,
|
|
8011
7460
|
jobId: params.setting.jobId ?? createId(),
|
|
8012
|
-
runId:
|
|
7461
|
+
runId: createId()
|
|
7462
|
+
// runId is always generated internally, never from external input
|
|
8013
7463
|
};
|
|
8014
7464
|
if (!isAdapterAvailable(runtime)) {
|
|
8015
7465
|
const available = getRegisteredRuntimes().join(", ");
|
|
@@ -8035,7 +7485,8 @@ See: ${error.helpUrl}`;
|
|
|
8035
7485
|
storeEvent: storeEvent ?? defaultStoreEvent,
|
|
8036
7486
|
retrieveCheckpoint: retrieveCheckpoint ?? defaultRetrieveCheckpoint,
|
|
8037
7487
|
workspace,
|
|
8038
|
-
additionalEnvKeys
|
|
7488
|
+
additionalEnvKeys,
|
|
7489
|
+
additionalVolumes
|
|
8039
7490
|
});
|
|
8040
7491
|
return { checkpoint: result.checkpoint };
|
|
8041
7492
|
}
|
|
@@ -8068,7 +7519,7 @@ var runCommand = new Command().command("run").description("Run Perstack with JSO
|
|
|
8068
7519
|
).option("--max-retries <maxRetries>", "Maximum number of generation retries, default is 5").option(
|
|
8069
7520
|
"--timeout <timeout>",
|
|
8070
7521
|
"Timeout for each generation in milliseconds, default is 60000 (1 minute)"
|
|
8071
|
-
).option("--job-id <jobId>", "Job ID for identifying the job").option(
|
|
7522
|
+
).option("--job-id <jobId>", "Job ID for identifying the job").option(
|
|
8072
7523
|
"--env-path <path>",
|
|
8073
7524
|
"Path to the environment file (can be specified multiple times), default is .env and .env.local",
|
|
8074
7525
|
(value, previous) => previous.concat(value),
|
|
@@ -8081,8 +7532,31 @@ var runCommand = new Command().command("run").description("Run Perstack with JSO
|
|
|
8081
7532
|
).option("--verbose", "Enable verbose logging").option("--continue", "Continue the most recent job with new query").option("--continue-job <jobId>", "Continue the specified job with new query").option(
|
|
8082
7533
|
"--resume-from <checkpointId>",
|
|
8083
7534
|
"Resume from a specific checkpoint (requires --continue or --continue-job)"
|
|
8084
|
-
).option("-i, --interactive-tool-call-result", "Query is interactive tool call result").option("--runtime <runtime>", "Execution runtime (docker, local, cursor, claude-code, gemini)").option("--workspace <workspace>", "Workspace directory for Docker runtime").
|
|
7535
|
+
).option("-i, --interactive-tool-call-result", "Query is interactive tool call result").option("--runtime <runtime>", "Execution runtime (docker, local, cursor, claude-code, gemini)").option("--workspace <workspace>", "Workspace directory for Docker runtime").option(
|
|
7536
|
+
"--volume <volume>",
|
|
7537
|
+
"Additional volume mount for Docker runtime (format: hostPath:containerPath:mode, can be specified multiple times)",
|
|
7538
|
+
(value, previous) => previous.concat(value),
|
|
7539
|
+
[]
|
|
7540
|
+
).option(
|
|
7541
|
+
"--filter <types>",
|
|
7542
|
+
"Filter events by type (comma-separated, e.g., completeRun,stopRunByError)"
|
|
7543
|
+
).action(async (expertKey, query, options) => {
|
|
8085
7544
|
const input = parseWithFriendlyError(runCommandInputSchema, { expertKey, query, options });
|
|
7545
|
+
let eventListener = defaultEventListener;
|
|
7546
|
+
if (input.options.filter && input.options.filter.length > 0) {
|
|
7547
|
+
try {
|
|
7548
|
+
const validatedTypes = validateEventFilter(input.options.filter);
|
|
7549
|
+
const allowedTypes = new Set(validatedTypes);
|
|
7550
|
+
eventListener = createFilteredEventListener(defaultEventListener, allowedTypes);
|
|
7551
|
+
} catch (error) {
|
|
7552
|
+
if (error instanceof Error) {
|
|
7553
|
+
console.error(error.message);
|
|
7554
|
+
} else {
|
|
7555
|
+
console.error(error);
|
|
7556
|
+
}
|
|
7557
|
+
process.exit(1);
|
|
7558
|
+
}
|
|
7559
|
+
}
|
|
8086
7560
|
try {
|
|
8087
7561
|
const { perstackConfig, checkpoint, env, providerConfig, model, experts } = await resolveRunContext({
|
|
8088
7562
|
configPath: input.options.config,
|
|
@@ -8098,7 +7572,6 @@ var runCommand = new Command().command("run").description("Run Perstack with JSO
|
|
|
8098
7572
|
await dispatchToRuntime({
|
|
8099
7573
|
setting: {
|
|
8100
7574
|
jobId: checkpoint?.jobId ?? input.options.jobId,
|
|
8101
|
-
runId: checkpoint?.runId ?? input.options.runId,
|
|
8102
7575
|
expertKey: input.expertKey,
|
|
8103
7576
|
input: input.options.interactiveToolCallResult ? parseInteractiveToolCallResultJson(input.query) ?? (checkpoint ? parseInteractiveToolCallResult(input.query, checkpoint) : { text: input.query }) : { text: input.query },
|
|
8104
7577
|
experts,
|
|
@@ -8118,9 +7591,10 @@ var runCommand = new Command().command("run").description("Run Perstack with JSO
|
|
|
8118
7591
|
checkpoint,
|
|
8119
7592
|
runtime,
|
|
8120
7593
|
config: perstackConfig,
|
|
8121
|
-
eventListener
|
|
7594
|
+
eventListener,
|
|
8122
7595
|
workspace: input.options.workspace,
|
|
8123
|
-
additionalEnvKeys: input.options.env
|
|
7596
|
+
additionalEnvKeys: input.options.env,
|
|
7597
|
+
additionalVolumes: input.options.volume
|
|
8124
7598
|
});
|
|
8125
7599
|
} catch (error) {
|
|
8126
7600
|
if (error instanceof Error) {
|
|
@@ -8141,7 +7615,7 @@ var startCommand = new Command().command("start").description("Start Perstack wi
|
|
|
8141
7615
|
).option("--max-retries <maxRetries>", "Maximum number of generation retries, default is 5").option(
|
|
8142
7616
|
"--timeout <timeout>",
|
|
8143
7617
|
"Timeout for each generation in milliseconds, default is 60000 (1 minute)"
|
|
8144
|
-
).option("--job-id <jobId>", "Job ID for identifying the job").option(
|
|
7618
|
+
).option("--job-id <jobId>", "Job ID for identifying the job").option(
|
|
8145
7619
|
"--env-path <path>",
|
|
8146
7620
|
"Path to the environment file (can be specified multiple times), default is .env and .env.local",
|
|
8147
7621
|
(value, previous) => previous.concat(value),
|
|
@@ -8168,14 +7642,16 @@ var startCommand = new Command().command("start").description("Start Perstack wi
|
|
|
8168
7642
|
expertKey: input.expertKey
|
|
8169
7643
|
});
|
|
8170
7644
|
const runtime = input.options.runtime ?? perstackConfig.runtime ?? "docker";
|
|
8171
|
-
const
|
|
8172
|
-
const
|
|
7645
|
+
const maxSteps = input.options.maxSteps ?? perstackConfig.maxSteps;
|
|
7646
|
+
const maxRetries = input.options.maxRetries ?? perstackConfig.maxRetries ?? defaultMaxRetries;
|
|
7647
|
+
const timeout = input.options.timeout ?? perstackConfig.timeout ?? defaultTimeout;
|
|
8173
7648
|
const configuredExperts = Object.keys(perstackConfig.experts ?? {}).map((key) => ({
|
|
8174
7649
|
key,
|
|
8175
7650
|
name: key
|
|
8176
7651
|
}));
|
|
8177
|
-
const recentExperts =
|
|
8178
|
-
const
|
|
7652
|
+
const recentExperts = getRecentExperts(10);
|
|
7653
|
+
const showHistory = !input.expertKey && !input.query && !checkpoint;
|
|
7654
|
+
const historyJobs = showHistory ? getAllJobs2().map((j) => ({
|
|
8179
7655
|
jobId: j.id,
|
|
8180
7656
|
status: j.status,
|
|
8181
7657
|
expertKey: j.coordinatorExpertKey,
|
|
@@ -8183,75 +7659,65 @@ var startCommand = new Command().command("start").description("Start Perstack wi
|
|
|
8183
7659
|
startedAt: j.startedAt,
|
|
8184
7660
|
finishedAt: j.finishedAt
|
|
8185
7661
|
})) : [];
|
|
8186
|
-
const
|
|
8187
|
-
let resolveContinueQuery = null;
|
|
8188
|
-
const maxSteps = input.options.maxSteps ?? perstackConfig.maxSteps;
|
|
8189
|
-
const maxRetries = input.options.maxRetries ?? perstackConfig.maxRetries ?? defaultMaxRetries;
|
|
8190
|
-
const timeout = input.options.timeout ?? perstackConfig.timeout ?? defaultTimeout;
|
|
8191
|
-
const result = await renderStart({
|
|
7662
|
+
const selection = await renderSelection({
|
|
8192
7663
|
showHistory,
|
|
8193
|
-
|
|
8194
|
-
initialExpertName: input.expertKey,
|
|
7664
|
+
initialExpertKey: input.expertKey,
|
|
8195
7665
|
initialQuery: input.query,
|
|
8196
|
-
|
|
8197
|
-
|
|
8198
|
-
|
|
8199
|
-
|
|
8200
|
-
|
|
8201
|
-
|
|
8202
|
-
|
|
8203
|
-
runtime
|
|
8204
|
-
},
|
|
7666
|
+
initialCheckpoint: checkpoint ? {
|
|
7667
|
+
id: checkpoint.id,
|
|
7668
|
+
jobId: checkpoint.jobId,
|
|
7669
|
+
runId: checkpoint.runId,
|
|
7670
|
+
stepNumber: checkpoint.stepNumber,
|
|
7671
|
+
contextWindowUsage: checkpoint.contextWindowUsage ?? 0
|
|
7672
|
+
} : void 0,
|
|
8205
7673
|
configuredExperts,
|
|
8206
7674
|
recentExperts,
|
|
8207
7675
|
historyJobs,
|
|
8208
|
-
onContinue: (query2) => {
|
|
8209
|
-
if (resolveContinueQuery) {
|
|
8210
|
-
resolveContinueQuery(query2);
|
|
8211
|
-
resolveContinueQuery = null;
|
|
8212
|
-
}
|
|
8213
|
-
},
|
|
8214
|
-
onResumeFromCheckpoint: (cp) => {
|
|
8215
|
-
resumeState.checkpoint = cp;
|
|
8216
|
-
},
|
|
8217
7676
|
onLoadCheckpoints: async (j) => {
|
|
8218
|
-
const checkpoints =
|
|
7677
|
+
const checkpoints = getCheckpointsWithDetails(j.jobId);
|
|
8219
7678
|
return checkpoints.map((cp) => ({ ...cp, jobId: j.jobId }));
|
|
8220
|
-
},
|
|
8221
|
-
onLoadEvents: async (j, cp) => {
|
|
8222
|
-
const events = await getEventsWithDetails(j.jobId, cp.runId, cp.stepNumber);
|
|
8223
|
-
return events.map((e) => ({ ...e, jobId: j.jobId }));
|
|
8224
|
-
},
|
|
8225
|
-
onLoadHistoricalEvents: async (cp) => {
|
|
8226
|
-
return await getEventContents2(cp.jobId, cp.runId, cp.stepNumber);
|
|
8227
7679
|
}
|
|
8228
7680
|
});
|
|
8229
|
-
|
|
8230
|
-
let finalQuery = result.query || input.query;
|
|
8231
|
-
if (!finalExpertKey) {
|
|
7681
|
+
if (!selection.expertKey) {
|
|
8232
7682
|
console.error("Expert key is required");
|
|
8233
7683
|
return;
|
|
8234
7684
|
}
|
|
8235
|
-
|
|
8236
|
-
|
|
8237
|
-
console.error(
|
|
8238
|
-
`Checkpoint expert key ${currentCheckpoint.expert.key} does not match input expert key ${finalExpertKey}`
|
|
8239
|
-
);
|
|
7685
|
+
if (!selection.query && !selection.checkpoint) {
|
|
7686
|
+
console.error("Query is required");
|
|
8240
7687
|
return;
|
|
8241
7688
|
}
|
|
8242
|
-
|
|
8243
|
-
|
|
7689
|
+
let currentCheckpoint = selection.checkpoint ? getCheckpointById(selection.checkpoint.jobId, selection.checkpoint.id) : checkpoint;
|
|
7690
|
+
if (currentCheckpoint && currentCheckpoint.expert.key !== selection.expertKey) {
|
|
7691
|
+
console.error(
|
|
7692
|
+
`Checkpoint expert key ${currentCheckpoint.expert.key} does not match input expert key ${selection.expertKey}`
|
|
7693
|
+
);
|
|
8244
7694
|
return;
|
|
8245
7695
|
}
|
|
7696
|
+
let currentQuery = selection.query;
|
|
8246
7697
|
let currentJobId = currentCheckpoint?.jobId ?? input.options.jobId;
|
|
8247
|
-
let
|
|
8248
|
-
while (
|
|
7698
|
+
let accumulatedEvents = currentCheckpoint ? getAllEventContentsForJob(currentCheckpoint.jobId, currentCheckpoint.stepNumber) : void 0;
|
|
7699
|
+
while (currentQuery !== null) {
|
|
7700
|
+
const historicalEvents = accumulatedEvents;
|
|
7701
|
+
const { result: executionResult, eventListener } = renderExecution({
|
|
7702
|
+
expertKey: selection.expertKey,
|
|
7703
|
+
query: currentQuery,
|
|
7704
|
+
config: {
|
|
7705
|
+
runtimeVersion: getRuntimeVersion(),
|
|
7706
|
+
model,
|
|
7707
|
+
maxSteps,
|
|
7708
|
+
maxRetries,
|
|
7709
|
+
timeout,
|
|
7710
|
+
contextWindowUsage: currentCheckpoint?.contextWindowUsage ?? 0,
|
|
7711
|
+
runtime
|
|
7712
|
+
},
|
|
7713
|
+
continueTimeoutMs: CONTINUE_TIMEOUT_MS,
|
|
7714
|
+
historicalEvents
|
|
7715
|
+
});
|
|
8249
7716
|
const { checkpoint: runResult } = await dispatchToRuntime({
|
|
8250
7717
|
setting: {
|
|
8251
7718
|
jobId: currentJobId,
|
|
8252
|
-
|
|
8253
|
-
|
|
8254
|
-
input: input.options.interactiveToolCallResult && currentCheckpoint ? parseInteractiveToolCallResult(finalQuery || "", currentCheckpoint) : { text: finalQuery },
|
|
7719
|
+
expertKey: selection.expertKey,
|
|
7720
|
+
input: input.options.interactiveToolCallResult && currentCheckpoint ? parseInteractiveToolCallResult(currentQuery, currentCheckpoint) : { text: currentQuery },
|
|
8255
7721
|
experts,
|
|
8256
7722
|
model,
|
|
8257
7723
|
providerConfig,
|
|
@@ -8268,30 +7734,23 @@ var startCommand = new Command().command("start").description("Start Perstack wi
|
|
|
8268
7734
|
checkpoint: currentCheckpoint,
|
|
8269
7735
|
runtime,
|
|
8270
7736
|
config: perstackConfig,
|
|
8271
|
-
eventListener
|
|
7737
|
+
eventListener,
|
|
8272
7738
|
workspace: input.options.workspace,
|
|
8273
7739
|
additionalEnvKeys: input.options.env
|
|
8274
7740
|
});
|
|
8275
|
-
|
|
8276
|
-
|
|
8277
|
-
|
|
8278
|
-
|
|
8279
|
-
|
|
8280
|
-
|
|
8281
|
-
|
|
8282
|
-
|
|
8283
|
-
}, CONTINUE_TIMEOUT_MS);
|
|
8284
|
-
});
|
|
8285
|
-
if (nextQuery) {
|
|
8286
|
-
finalQuery = nextQuery;
|
|
8287
|
-
currentCheckpoint = runResult;
|
|
8288
|
-
currentJobId = runResult.jobId;
|
|
8289
|
-
currentRunId = runResult.runId;
|
|
7741
|
+
const result = await executionResult;
|
|
7742
|
+
if (result.nextQuery && (runResult.status === "completed" || runResult.status === "stoppedByExceededMaxSteps" || runResult.status === "stoppedByError")) {
|
|
7743
|
+
currentQuery = result.nextQuery;
|
|
7744
|
+
currentCheckpoint = runResult;
|
|
7745
|
+
currentJobId = runResult.jobId;
|
|
7746
|
+
const newRunEvents = getEventContents2(runResult.jobId, runResult.runId);
|
|
7747
|
+
if (accumulatedEvents) {
|
|
7748
|
+
accumulatedEvents = [...accumulatedEvents, ...newRunEvents];
|
|
8290
7749
|
} else {
|
|
8291
|
-
|
|
7750
|
+
accumulatedEvents = newRunEvents;
|
|
8292
7751
|
}
|
|
8293
7752
|
} else {
|
|
8294
|
-
|
|
7753
|
+
currentQuery = null;
|
|
8295
7754
|
}
|
|
8296
7755
|
}
|
|
8297
7756
|
} catch (error) {
|