wave-code 1.0.10 → 1.1.1
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/bin/wave-code.js +8 -2
- package/dist/bundle/wave.mjs +3231 -0
- package/package.json +24 -25
- package/src/cli.tsx +6 -1
- package/src/commands/update.ts +2 -7
- package/src/components/App.tsx +3 -7
- package/src/components/BtwDisplay.tsx +10 -1
- package/src/components/ChatInterface.tsx +21 -52
- package/src/components/ConfirmationDetails.tsx +144 -37
- package/src/components/DiffDisplay.tsx +335 -301
- package/src/components/InputBox.tsx +17 -2
- package/src/components/LoadingIndicator.tsx +16 -2
- package/src/components/MessageBlockItem.tsx +2 -4
- package/src/components/MessageList.tsx +75 -14
- package/src/components/ReasoningDisplay.tsx +2 -4
- package/src/components/SessionSelector.tsx +82 -11
- package/src/components/SkillsManager.tsx +312 -0
- package/src/components/StatusCommand.tsx +2 -9
- package/src/components/ToolDisplay.tsx +2 -4
- package/src/constants/commands.ts +6 -0
- package/src/contexts/useChat.tsx +245 -301
- package/src/daemon/commands.ts +57 -27
- package/src/daemon/jsonRpcClient.ts +1 -1
- package/src/daemon/socketClient.ts +2 -2
- package/src/hooks/useInputManager.ts +7 -1
- package/src/index.ts +57 -10
- package/src/managers/inputHandlers.ts +2 -0
- package/src/managers/inputReducer.ts +195 -104
- package/src/print-cli.ts +25 -17
- package/src/reducers/selectorReducer.ts +10 -0
- package/src/reducers/skillsManagerReducer.ts +91 -0
- package/src/session-selector-cli.tsx +269 -28
- package/src/stdio/agentBridge.ts +30 -21
- package/src/stdio/daemonServer.ts +3 -1
- package/src/stdio/protocol.ts +2 -0
- package/src/utils/clipboard.ts +21 -0
- package/src/utils/highlightUtils.ts +46 -1
- package/src/utils/readPackageJson.ts +29 -0
- package/src/utils/streamingText.ts +11 -0
- package/src/utils/worktree.ts +191 -43
- package/dist/cli.d.ts +0 -6
- package/dist/cli.js +0 -53
- package/dist/commands/plugin/disable.d.ts +0 -5
- package/dist/commands/plugin/disable.js +0 -15
- package/dist/commands/plugin/enable.d.ts +0 -5
- package/dist/commands/plugin/enable.js +0 -15
- package/dist/commands/plugin/install.d.ts +0 -5
- package/dist/commands/plugin/install.js +0 -21
- package/dist/commands/plugin/list.d.ts +0 -1
- package/dist/commands/plugin/list.js +0 -31
- package/dist/commands/plugin/marketplace.d.ts +0 -10
- package/dist/commands/plugin/marketplace.js +0 -90
- package/dist/commands/plugin/uninstall.d.ts +0 -3
- package/dist/commands/plugin/uninstall.js +0 -16
- package/dist/commands/plugin/update.d.ts +0 -3
- package/dist/commands/plugin/update.js +0 -15
- package/dist/commands/update.d.ts +0 -1
- package/dist/commands/update.js +0 -97
- package/dist/components/AgentsManager.d.ts +0 -7
- package/dist/components/AgentsManager.js +0 -109
- package/dist/components/App.d.ts +0 -9
- package/dist/components/App.js +0 -76
- package/dist/components/BackgroundTaskManager.d.ts +0 -5
- package/dist/components/BackgroundTaskManager.js +0 -99
- package/dist/components/BangDisplay.d.ts +0 -8
- package/dist/components/BangDisplay.js +0 -17
- package/dist/components/BtwDisplay.d.ts +0 -7
- package/dist/components/BtwDisplay.js +0 -19
- package/dist/components/ChatInterface.d.ts +0 -2
- package/dist/components/ChatInterface.js +0 -61
- package/dist/components/CommandSelector.d.ts +0 -10
- package/dist/components/CommandSelector.js +0 -66
- package/dist/components/CompactDisplay.d.ts +0 -8
- package/dist/components/CompactDisplay.js +0 -13
- package/dist/components/ConfirmationDetails.d.ts +0 -9
- package/dist/components/ConfirmationDetails.js +0 -45
- package/dist/components/ConfirmationSelector.d.ts +0 -13
- package/dist/components/ConfirmationSelector.js +0 -127
- package/dist/components/DiffDisplay.d.ts +0 -8
- package/dist/components/DiffDisplay.js +0 -201
- package/dist/components/DiscoverView.d.ts +0 -2
- package/dist/components/DiscoverView.js +0 -37
- package/dist/components/FileSelector.d.ts +0 -11
- package/dist/components/FileSelector.js +0 -50
- package/dist/components/HelpView.d.ts +0 -7
- package/dist/components/HelpView.js +0 -74
- package/dist/components/HistorySearch.d.ts +0 -8
- package/dist/components/HistorySearch.js +0 -66
- package/dist/components/InputBox.d.ts +0 -24
- package/dist/components/InputBox.js +0 -149
- package/dist/components/InstalledView.d.ts +0 -2
- package/dist/components/InstalledView.js +0 -45
- package/dist/components/LoadingIndicator.d.ts +0 -10
- package/dist/components/LoadingIndicator.js +0 -6
- package/dist/components/LoginCommand.d.ts +0 -5
- package/dist/components/LoginCommand.js +0 -153
- package/dist/components/Markdown.d.ts +0 -5
- package/dist/components/Markdown.js +0 -127
- package/dist/components/MarketplaceAddForm.d.ts +0 -2
- package/dist/components/MarketplaceAddForm.js +0 -55
- package/dist/components/MarketplaceDetail.d.ts +0 -2
- package/dist/components/MarketplaceDetail.js +0 -74
- package/dist/components/MarketplaceList.d.ts +0 -8
- package/dist/components/MarketplaceList.js +0 -17
- package/dist/components/MarketplaceView.d.ts +0 -2
- package/dist/components/MarketplaceView.js +0 -41
- package/dist/components/McpManager.d.ts +0 -9
- package/dist/components/McpManager.js +0 -88
- package/dist/components/MessageBlockItem.d.ts +0 -8
- package/dist/components/MessageBlockItem.js +0 -15
- package/dist/components/MessageList.d.ts +0 -10
- package/dist/components/MessageList.js +0 -80
- package/dist/components/ModelSelector.d.ts +0 -8
- package/dist/components/ModelSelector.js +0 -45
- package/dist/components/Notifications.d.ts +0 -7
- package/dist/components/Notifications.js +0 -9
- package/dist/components/PlanDisplay.d.ts +0 -7
- package/dist/components/PlanDisplay.js +0 -6
- package/dist/components/PluginDetail.d.ts +0 -2
- package/dist/components/PluginDetail.js +0 -87
- package/dist/components/PluginList.d.ts +0 -13
- package/dist/components/PluginList.js +0 -15
- package/dist/components/PluginManagerShell.d.ts +0 -6
- package/dist/components/PluginManagerShell.js +0 -92
- package/dist/components/PluginManagerTypes.d.ts +0 -35
- package/dist/components/PluginManagerTypes.js +0 -1
- package/dist/components/QueuedMessageList.d.ts +0 -2
- package/dist/components/QueuedMessageList.js +0 -18
- package/dist/components/ReasoningDisplay.d.ts +0 -8
- package/dist/components/ReasoningDisplay.js +0 -13
- package/dist/components/RewindCommand.d.ts +0 -12
- package/dist/components/RewindCommand.js +0 -78
- package/dist/components/SessionSelector.d.ts +0 -12
- package/dist/components/SessionSelector.js +0 -47
- package/dist/components/StatusCommand.d.ts +0 -5
- package/dist/components/StatusCommand.js +0 -28
- package/dist/components/StatusLine.d.ts +0 -6
- package/dist/components/StatusLine.js +0 -9
- package/dist/components/TaskList.d.ts +0 -5
- package/dist/components/TaskList.js +0 -197
- package/dist/components/TaskNotificationMessage.d.ts +0 -5
- package/dist/components/TaskNotificationMessage.js +0 -12
- package/dist/components/ToolDisplay.d.ts +0 -9
- package/dist/components/ToolDisplay.js +0 -55
- package/dist/components/WorkflowManager.d.ts +0 -5
- package/dist/components/WorkflowManager.js +0 -102
- package/dist/components/WorktreeExitPrompt.d.ts +0 -12
- package/dist/components/WorktreeExitPrompt.js +0 -35
- package/dist/constants/commands.d.ts +0 -2
- package/dist/constants/commands.js +0 -92
- package/dist/contexts/PluginManagerContext.d.ts +0 -3
- package/dist/contexts/PluginManagerContext.js +0 -9
- package/dist/contexts/useAppConfig.d.ts +0 -10
- package/dist/contexts/useAppConfig.js +0 -13
- package/dist/contexts/useChat.d.ts +0 -101
- package/dist/contexts/useChat.js +0 -993
- package/dist/contracts/status.d.ts +0 -7
- package/dist/contracts/status.js +0 -1
- package/dist/daemon/commands.d.ts +0 -49
- package/dist/daemon/commands.js +0 -341
- package/dist/daemon/jsonRpcClient.d.ts +0 -38
- package/dist/daemon/jsonRpcClient.js +0 -129
- package/dist/daemon/socketClient.d.ts +0 -13
- package/dist/daemon/socketClient.js +0 -26
- package/dist/daemon-cli.d.ts +0 -10
- package/dist/daemon-cli.js +0 -15
- package/dist/hooks/useInputManager.d.ts +0 -75
- package/dist/hooks/useInputManager.js +0 -583
- package/dist/hooks/usePluginManager.d.ts +0 -4
- package/dist/hooks/usePluginManager.js +0 -265
- package/dist/hooks/useTasks.d.ts +0 -1
- package/dist/hooks/useTasks.js +0 -5
- package/dist/index.d.ts +0 -4
- package/dist/index.js +0 -447
- package/dist/managers/inputHandlers.d.ts +0 -30
- package/dist/managers/inputHandlers.js +0 -625
- package/dist/managers/inputReducer.d.ts +0 -271
- package/dist/managers/inputReducer.js +0 -1121
- package/dist/plugin-manager-cli.d.ts +0 -5
- package/dist/plugin-manager-cli.js +0 -12
- package/dist/print-cli.d.ts +0 -10
- package/dist/print-cli.js +0 -209
- package/dist/reducers/agentsManagerReducer.d.ts +0 -26
- package/dist/reducers/agentsManagerReducer.js +0 -54
- package/dist/reducers/backgroundTaskManagerReducer.d.ts +0 -62
- package/dist/reducers/backgroundTaskManagerReducer.js +0 -106
- package/dist/reducers/confirmationReducer.d.ts +0 -37
- package/dist/reducers/confirmationReducer.js +0 -193
- package/dist/reducers/helpSelectorReducer.d.ts +0 -25
- package/dist/reducers/helpSelectorReducer.js +0 -52
- package/dist/reducers/marketplaceAddFormReducer.d.ts +0 -24
- package/dist/reducers/marketplaceAddFormReducer.js +0 -58
- package/dist/reducers/mcpManagerReducer.d.ts +0 -37
- package/dist/reducers/mcpManagerReducer.js +0 -74
- package/dist/reducers/pluginDetailReducer.d.ts +0 -32
- package/dist/reducers/pluginDetailReducer.js +0 -70
- package/dist/reducers/questionReducer.d.ts +0 -82
- package/dist/reducers/questionReducer.js +0 -375
- package/dist/reducers/rewindSelectorReducer.d.ts +0 -21
- package/dist/reducers/rewindSelectorReducer.js +0 -37
- package/dist/reducers/selectorReducer.d.ts +0 -23
- package/dist/reducers/selectorReducer.js +0 -42
- package/dist/reducers/workflowManagerReducer.d.ts +0 -40
- package/dist/reducers/workflowManagerReducer.js +0 -100
- package/dist/session-selector-cli.d.ts +0 -3
- package/dist/session-selector-cli.js +0 -25
- package/dist/stdio/agentBridge.d.ts +0 -139
- package/dist/stdio/agentBridge.js +0 -999
- package/dist/stdio/daemonServer.d.ts +0 -67
- package/dist/stdio/daemonServer.js +0 -191
- package/dist/stdio/index.d.ts +0 -5
- package/dist/stdio/index.js +0 -5
- package/dist/stdio/jsonRpcConnection.d.ts +0 -39
- package/dist/stdio/jsonRpcConnection.js +0 -135
- package/dist/stdio/protocol.d.ts +0 -41
- package/dist/stdio/protocol.js +0 -26
- package/dist/stdio/stdioServer.d.ts +0 -36
- package/dist/stdio/stdioServer.js +0 -51
- package/dist/stdio-cli.d.ts +0 -8
- package/dist/stdio-cli.js +0 -15
- package/dist/types.d.ts +0 -20
- package/dist/types.js +0 -1
- package/dist/utils/bracketedPaste.d.ts +0 -39
- package/dist/utils/bracketedPaste.js +0 -122
- package/dist/utils/clipboard.d.ts +0 -21
- package/dist/utils/clipboard.js +0 -347
- package/dist/utils/constants.d.ts +0 -16
- package/dist/utils/constants.js +0 -18
- package/dist/utils/highlightUtils.d.ts +0 -1
- package/dist/utils/highlightUtils.js +0 -93
- package/dist/utils/inputUtils.d.ts +0 -17
- package/dist/utils/inputUtils.js +0 -67
- package/dist/utils/logger.d.ts +0 -71
- package/dist/utils/logger.js +0 -259
- package/dist/utils/markdownTable.d.ts +0 -34
- package/dist/utils/markdownTable.js +0 -302
- package/dist/utils/rewindCheckpoints.d.ts +0 -8
- package/dist/utils/rewindCheckpoints.js +0 -17
- package/dist/utils/throttle.d.ts +0 -14
- package/dist/utils/throttle.js +0 -55
- package/dist/utils/toolParameterTransforms.d.ts +0 -18
- package/dist/utils/toolParameterTransforms.js +0 -73
- package/dist/utils/usageSummary.d.ts +0 -28
- package/dist/utils/usageSummary.js +0 -121
- package/dist/utils/version.d.ts +0 -1
- package/dist/utils/version.js +0 -4
- package/dist/utils/worktree.d.ts +0 -35
- package/dist/utils/worktree.js +0 -219
package/dist/commands/update.js
DELETED
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import { spawnSync } from "child_process";
|
|
2
|
-
import { readFileSync } from "fs";
|
|
3
|
-
import path from "path";
|
|
4
|
-
import { fileURLToPath } from "url";
|
|
5
|
-
import https from "https";
|
|
6
|
-
import chalk from "chalk";
|
|
7
|
-
import { isUpdateAvailable } from "../utils/version.js";
|
|
8
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
9
|
-
const packageJsonPath = path.resolve(__dirname, "../../package.json");
|
|
10
|
-
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
11
|
-
const currentVersion = packageJson.version;
|
|
12
|
-
async function getLatestVersion() {
|
|
13
|
-
return new Promise((resolve, reject) => {
|
|
14
|
-
https
|
|
15
|
-
.get("https://registry.npmjs.org/wave-code/latest", (res) => {
|
|
16
|
-
let data = "";
|
|
17
|
-
res.on("data", (chunk) => {
|
|
18
|
-
data += chunk;
|
|
19
|
-
});
|
|
20
|
-
res.on("end", () => {
|
|
21
|
-
try {
|
|
22
|
-
const json = JSON.parse(data);
|
|
23
|
-
resolve(json.version);
|
|
24
|
-
}
|
|
25
|
-
catch {
|
|
26
|
-
reject(new Error("Failed to parse npm registry response"));
|
|
27
|
-
}
|
|
28
|
-
});
|
|
29
|
-
})
|
|
30
|
-
.on("error", (err) => {
|
|
31
|
-
reject(err);
|
|
32
|
-
});
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
function detectPackageManager() {
|
|
36
|
-
// Check if wave-code is installed globally with pnpm
|
|
37
|
-
const pnpmList = spawnSync("pnpm", ["list", "-g", "wave-code"], {
|
|
38
|
-
encoding: "utf-8",
|
|
39
|
-
});
|
|
40
|
-
if (pnpmList.status === 0 && pnpmList.stdout?.includes("wave-code")) {
|
|
41
|
-
return "pnpm";
|
|
42
|
-
}
|
|
43
|
-
// Check if wave-code is installed globally with yarn
|
|
44
|
-
const yarnList = spawnSync("yarn", ["global", "list"], { encoding: "utf-8" });
|
|
45
|
-
if (yarnList.status === 0 && yarnList.stdout?.includes("wave-code")) {
|
|
46
|
-
return "yarn";
|
|
47
|
-
}
|
|
48
|
-
// Default to npm
|
|
49
|
-
return "npm";
|
|
50
|
-
}
|
|
51
|
-
export async function updateCommand() {
|
|
52
|
-
console.log(chalk.blue(`Checking for updates...`));
|
|
53
|
-
console.log(chalk.dim(`Current version: ${currentVersion}`));
|
|
54
|
-
try {
|
|
55
|
-
const latestVersion = await getLatestVersion();
|
|
56
|
-
console.log(chalk.dim(`Latest version: ${latestVersion}`));
|
|
57
|
-
if (!isUpdateAvailable(currentVersion, latestVersion)) {
|
|
58
|
-
console.log(chalk.green("WAVE Code is already up to date!"));
|
|
59
|
-
process.exit(0);
|
|
60
|
-
}
|
|
61
|
-
console.log(chalk.yellow(`A new version of WAVE Code is available: ${latestVersion}`));
|
|
62
|
-
const packageManager = detectPackageManager();
|
|
63
|
-
let updateCmd;
|
|
64
|
-
let args;
|
|
65
|
-
if (packageManager === "pnpm") {
|
|
66
|
-
updateCmd = "pnpm";
|
|
67
|
-
args = ["add", "-g", "wave-code@latest"];
|
|
68
|
-
}
|
|
69
|
-
else if (packageManager === "yarn") {
|
|
70
|
-
updateCmd = "yarn";
|
|
71
|
-
args = ["global", "add", "wave-code@latest"];
|
|
72
|
-
}
|
|
73
|
-
else {
|
|
74
|
-
updateCmd = "npm";
|
|
75
|
-
args = ["install", "-g", "wave-code@latest"];
|
|
76
|
-
}
|
|
77
|
-
console.log(chalk.blue(`Updating WAVE Code using ${packageManager}...`));
|
|
78
|
-
console.log(chalk.dim(`Running: ${updateCmd} ${args.join(" ")}`));
|
|
79
|
-
const result = spawnSync(updateCmd, args, { stdio: "inherit" });
|
|
80
|
-
if (result.status === 0) {
|
|
81
|
-
console.log(chalk.green("WAVE Code updated successfully!"));
|
|
82
|
-
process.exit(0);
|
|
83
|
-
}
|
|
84
|
-
else {
|
|
85
|
-
console.log(chalk.red("Failed to update WAVE Code."));
|
|
86
|
-
console.log(chalk.yellow(`Please try running the update command manually: ${updateCmd} ${args.join(" ")}`));
|
|
87
|
-
if (process.platform !== "win32") {
|
|
88
|
-
console.log(chalk.yellow("You might need to run it with sudo if you encounter permission issues."));
|
|
89
|
-
}
|
|
90
|
-
process.exit(1);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
catch (error) {
|
|
94
|
-
console.error(chalk.red("Error checking for updates:"), error);
|
|
95
|
-
process.exit(1);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import type { SubagentConfiguration } from "wave-agent-sdk";
|
|
3
|
-
export interface AgentsManagerProps {
|
|
4
|
-
onCancel: () => void;
|
|
5
|
-
agentDefinitions: SubagentConfiguration[];
|
|
6
|
-
}
|
|
7
|
-
export declare const AgentsManager: React.FC<AgentsManagerProps>;
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useEffect, useMemo, useReducer } from "react";
|
|
3
|
-
import { Box, Text, useInput, useStdout } from "ink";
|
|
4
|
-
import { Markdown } from "./Markdown.js";
|
|
5
|
-
import { agentsManagerReducer, } from "../reducers/agentsManagerReducer.js";
|
|
6
|
-
const SCOPE_LABELS = {
|
|
7
|
-
builtin: "Built-in agents",
|
|
8
|
-
user: "User agents",
|
|
9
|
-
project: "Project agents",
|
|
10
|
-
plugin: "Plugin agents",
|
|
11
|
-
};
|
|
12
|
-
const SCOPE_ORDER = [
|
|
13
|
-
"builtin",
|
|
14
|
-
"user",
|
|
15
|
-
"project",
|
|
16
|
-
"plugin",
|
|
17
|
-
];
|
|
18
|
-
const initialState = {
|
|
19
|
-
selectedIndex: 0,
|
|
20
|
-
viewMode: "list",
|
|
21
|
-
pendingEffect: null,
|
|
22
|
-
};
|
|
23
|
-
export const AgentsManager = ({ onCancel, agentDefinitions, }) => {
|
|
24
|
-
const [state, dispatch] = useReducer(agentsManagerReducer, initialState);
|
|
25
|
-
const { stdout } = useStdout();
|
|
26
|
-
// Handle pending effects
|
|
27
|
-
useEffect(() => {
|
|
28
|
-
if (!state.pendingEffect)
|
|
29
|
-
return;
|
|
30
|
-
const effect = state.pendingEffect;
|
|
31
|
-
dispatch({ type: "CLEAR_PENDING_EFFECT" });
|
|
32
|
-
if (effect.type === "CANCEL") {
|
|
33
|
-
onCancel();
|
|
34
|
-
}
|
|
35
|
-
}, [state.pendingEffect, onCancel]);
|
|
36
|
-
// Flatten definitions (grouped by scope) into one navigable list. Headers
|
|
37
|
-
// and the empty-state line are non-selectable.
|
|
38
|
-
const entries = useMemo(() => {
|
|
39
|
-
const result = [];
|
|
40
|
-
let selectableCount = 0;
|
|
41
|
-
result.push({ kind: "header", label: "AGENTS", selectableIndex: -1 });
|
|
42
|
-
let definitionCount = 0;
|
|
43
|
-
for (const scope of SCOPE_ORDER) {
|
|
44
|
-
const defs = agentDefinitions
|
|
45
|
-
.filter((d) => d.scope === scope)
|
|
46
|
-
.sort((a, b) => a.name.localeCompare(b.name));
|
|
47
|
-
if (defs.length === 0)
|
|
48
|
-
continue;
|
|
49
|
-
result.push({
|
|
50
|
-
kind: "header",
|
|
51
|
-
label: SCOPE_LABELS[scope],
|
|
52
|
-
scope,
|
|
53
|
-
selectableIndex: -1,
|
|
54
|
-
});
|
|
55
|
-
for (const def of defs) {
|
|
56
|
-
result.push({
|
|
57
|
-
kind: "definition",
|
|
58
|
-
label: def.name,
|
|
59
|
-
model: def.model,
|
|
60
|
-
sub: def.description,
|
|
61
|
-
scope: def.scope,
|
|
62
|
-
selectableIndex: selectableCount++,
|
|
63
|
-
definition: def,
|
|
64
|
-
});
|
|
65
|
-
definitionCount++;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
if (definitionCount === 0) {
|
|
69
|
-
result.push({
|
|
70
|
-
kind: "empty",
|
|
71
|
-
label: "No agents available",
|
|
72
|
-
selectableIndex: -1,
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
return result;
|
|
76
|
-
}, [agentDefinitions]);
|
|
77
|
-
const itemCount = entries.filter((e) => e.selectableIndex >= 0).length;
|
|
78
|
-
// Window slice: center the selected item within the visible area, clamping
|
|
79
|
-
// to the terminal's available rows (reusable pattern from
|
|
80
|
-
// BackgroundTaskManager).
|
|
81
|
-
const availableRows = stdout?.rows ?? 24;
|
|
82
|
-
const maxVisible = Math.max(3, Math.min(15, availableRows - 12));
|
|
83
|
-
const selectedFlatIndex = entries.findIndex((e) => e.selectableIndex === state.selectedIndex);
|
|
84
|
-
const startIndex = Math.max(0, Math.min(selectedFlatIndex - Math.floor(maxVisible / 2), Math.max(0, entries.length - maxVisible)));
|
|
85
|
-
const visibleEntries = entries.slice(startIndex, startIndex + maxVisible);
|
|
86
|
-
useInput((input, key) => {
|
|
87
|
-
dispatch({ type: "HANDLE_KEY", input, key, itemCount });
|
|
88
|
-
});
|
|
89
|
-
const selectedEntry = entries.find((e) => e.selectableIndex === state.selectedIndex);
|
|
90
|
-
// Detail view — body renders fully expanded with no height limit, no
|
|
91
|
-
// clipping and no scrolling (aligned with Claude Code's AgentDetail).
|
|
92
|
-
if (state.viewMode === "detail" && selectedEntry) {
|
|
93
|
-
const def = selectedEntry.definition;
|
|
94
|
-
return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "cyan", borderBottom: false, borderLeft: false, borderRight: false, paddingTop: 1, gap: 1, children: [_jsx(Box, { children: _jsxs(Text, { color: "cyan", bold: true, children: ["Agent: ", selectedEntry.label] }) }), _jsxs(Box, { flexDirection: "column", gap: 1, children: [def?.description && (_jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "Description:" }), " ", def.description] }) })), _jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "Model:" }), " ", def?.model || "default (not explicitly configured)"] }) }), _jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "Scope:" }), " ", def ? SCOPE_LABELS[def.scope] : ""] }) }), def?.tools && def.tools.length > 0 && (_jsx(Box, { children: _jsxs(Text, { wrap: "wrap", children: [_jsx(Text, { color: "blue", children: "Tools:" }), " ", def.tools.join(", ")] }) })), def?.filePath && (_jsx(Box, { children: _jsxs(Text, { wrap: "wrap", children: [_jsx(Text, { color: "blue", children: "File:" }), " ", def.filePath] }) }))] }), def && (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { color: "blue", bold: true, children: "System Prompt:" }), _jsx(Box, { marginLeft: 2, marginRight: 2, children: _jsx(Markdown, { children: def.systemPrompt }) })] })), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Esc or Enter to go back" }) })] }));
|
|
95
|
-
}
|
|
96
|
-
if (itemCount === 0) {
|
|
97
|
-
return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "cyan", borderBottom: false, borderLeft: false, borderRight: false, paddingTop: 1, children: [_jsx(Text, { color: "cyan", bold: true, children: "Agents" }), _jsx(Text, { children: "No agents available" }), _jsx(Text, { dimColor: true, children: "Press Escape to close" })] }));
|
|
98
|
-
}
|
|
99
|
-
return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "cyan", borderBottom: false, borderLeft: false, borderRight: false, paddingTop: 1, gap: 1, children: [_jsx(Box, { children: _jsx(Text, { color: "cyan", bold: true, children: "Agents" }) }), _jsx(Text, { dimColor: true, children: "Select an agent to view details" }), _jsx(Box, { flexDirection: "column", children: visibleEntries.map((entry, index) => {
|
|
100
|
-
const isSelected = entry.selectableIndex === state.selectedIndex;
|
|
101
|
-
if (entry.kind === "header") {
|
|
102
|
-
return (_jsx(Text, { dimColor: true, bold: true, children: entry.label }, `${entry.kind}-${entry.label}-${index}`));
|
|
103
|
-
}
|
|
104
|
-
if (entry.kind === "empty") {
|
|
105
|
-
return (_jsx(Text, { dimColor: true, children: entry.label }, `empty-${index}`));
|
|
106
|
-
}
|
|
107
|
-
return (_jsxs(Text, { color: isSelected ? "black" : "white", backgroundColor: isSelected ? "cyan" : undefined, wrap: "truncate-end", children: [isSelected ? "▶ " : " ", entry.selectableIndex + 1, ". ", entry.label, entry.model ? (_jsxs(Text, { color: isSelected ? "black" : "gray", children: [" ", "\u00B7 ", entry.model] })) : null, entry.sub ? ` · ${entry.sub}` : ""] }, `${entry.kind}-${entry.selectableIndex}`));
|
|
108
|
-
}) }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "\u2191/\u2193 to select \u00B7 Enter to view details \u00B7 Esc to close" }) })] }));
|
|
109
|
-
};
|
package/dist/components/App.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { BaseAppProps } from "../types.js";
|
|
3
|
-
interface AppProps extends BaseAppProps {
|
|
4
|
-
restoreSessionId?: string;
|
|
5
|
-
continueLastSession?: boolean;
|
|
6
|
-
onExit: (shouldRemove: boolean) => void;
|
|
7
|
-
}
|
|
8
|
-
export declare const App: React.FC<AppProps>;
|
|
9
|
-
export {};
|
package/dist/components/App.js
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useState, useEffect, useCallback } from "react";
|
|
3
|
-
import { useInput } from "ink";
|
|
4
|
-
import { ChatInterface } from "./ChatInterface.js";
|
|
5
|
-
import { ChatProvider, useChat } from "../contexts/useChat.js";
|
|
6
|
-
import { AppProvider } from "../contexts/useAppConfig.js";
|
|
7
|
-
import { WorktreeExitPrompt } from "./WorktreeExitPrompt.js";
|
|
8
|
-
import { hasUncommittedChanges, hasNewCommits, getDefaultRemoteBranch, } from "wave-agent-sdk";
|
|
9
|
-
import { btwOverlayActiveRef } from "../managers/inputReducer.js";
|
|
10
|
-
/** Wraps ChatInterface with worktree exit handling, using useChat() for hook access. */
|
|
11
|
-
const ChatWithExitPrompt = ({ worktreeSession, onExit }) => {
|
|
12
|
-
const { triggerWorktreeRemoveHook } = useChat();
|
|
13
|
-
const [isExiting, setIsExiting] = useState(false);
|
|
14
|
-
const [worktreeStatus, setWorktreeStatus] = useState(null);
|
|
15
|
-
const handleSignal = useCallback(async () => {
|
|
16
|
-
const cwd = worktreeSession.path;
|
|
17
|
-
const baseBranch = getDefaultRemoteBranch(cwd);
|
|
18
|
-
const hasChanges = hasUncommittedChanges(cwd);
|
|
19
|
-
const hasCommits = hasNewCommits(cwd, baseBranch);
|
|
20
|
-
if (hasChanges || hasCommits) {
|
|
21
|
-
setWorktreeStatus({
|
|
22
|
-
hasUncommittedChanges: hasChanges,
|
|
23
|
-
hasNewCommits: hasCommits,
|
|
24
|
-
});
|
|
25
|
-
setIsExiting(true);
|
|
26
|
-
}
|
|
27
|
-
else {
|
|
28
|
-
onExit(true);
|
|
29
|
-
}
|
|
30
|
-
}, [worktreeSession, onExit]);
|
|
31
|
-
useInput((input, key) => {
|
|
32
|
-
// While the /btw overlay is up it owns the keys; Ctrl+C must not quit
|
|
33
|
-
if (btwOverlayActiveRef.current)
|
|
34
|
-
return;
|
|
35
|
-
if (input === "c" && key.ctrl) {
|
|
36
|
-
handleSignal();
|
|
37
|
-
}
|
|
38
|
-
});
|
|
39
|
-
useEffect(() => {
|
|
40
|
-
const onSigInt = () => handleSignal();
|
|
41
|
-
const onSigTerm = () => handleSignal();
|
|
42
|
-
process.on("SIGINT", onSigInt);
|
|
43
|
-
process.on("SIGTERM", onSigTerm);
|
|
44
|
-
return () => {
|
|
45
|
-
process.off("SIGINT", onSigInt);
|
|
46
|
-
process.off("SIGTERM", onSigTerm);
|
|
47
|
-
};
|
|
48
|
-
}, [handleSignal]);
|
|
49
|
-
if (isExiting && worktreeStatus) {
|
|
50
|
-
return (_jsx(WorktreeExitPrompt, { name: worktreeSession.name, path: worktreeSession.path, hasUncommittedChanges: worktreeStatus.hasUncommittedChanges, hasNewCommits: worktreeStatus.hasNewCommits, onKeep: () => onExit(false), onRemove: async () => {
|
|
51
|
-
await triggerWorktreeRemoveHook(worktreeSession.path);
|
|
52
|
-
onExit(true);
|
|
53
|
-
}, onCancel: () => setIsExiting(false) }));
|
|
54
|
-
}
|
|
55
|
-
return _jsx(ChatInterface, {});
|
|
56
|
-
};
|
|
57
|
-
const AppWithProviders = ({ bypassPermissions, permissionMode, pluginDirs, additionalDirectories, tools, allowedTools, disallowedTools, worktreeSession, workdir, originalCwd, version, model, mcpServers, onExit, }) => {
|
|
58
|
-
// Handle Ctrl-C for non-worktree sessions (immediate exit)
|
|
59
|
-
// Ink runs terminal in raw mode, so Ctrl+C arrives as useInput event, not SIGINT
|
|
60
|
-
useInput((input, key) => {
|
|
61
|
-
// While the /btw overlay is up it owns the keys; Ctrl+C must not quit
|
|
62
|
-
if (btwOverlayActiveRef.current)
|
|
63
|
-
return;
|
|
64
|
-
if (!worktreeSession && input === "c" && key.ctrl) {
|
|
65
|
-
onExit(false);
|
|
66
|
-
return true;
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
if (worktreeSession) {
|
|
70
|
-
return (_jsx(ChatProvider, { bypassPermissions: bypassPermissions, permissionMode: permissionMode, pluginDirs: pluginDirs, additionalDirectories: additionalDirectories, tools: tools, allowedTools: allowedTools, disallowedTools: disallowedTools, workdir: workdir, worktreeSession: worktreeSession, originalCwd: originalCwd, version: version, model: model, mcpServers: mcpServers, children: _jsx(ChatWithExitPrompt, { worktreeSession: worktreeSession, onExit: onExit }) }));
|
|
71
|
-
}
|
|
72
|
-
return (_jsx(ChatProvider, { bypassPermissions: bypassPermissions, permissionMode: permissionMode, pluginDirs: pluginDirs, additionalDirectories: additionalDirectories, tools: tools, allowedTools: allowedTools, disallowedTools: disallowedTools, workdir: workdir, worktreeSession: worktreeSession, originalCwd: originalCwd, version: version, model: model, mcpServers: mcpServers, children: _jsx(ChatInterface, {}) }));
|
|
73
|
-
};
|
|
74
|
-
export const App = ({ restoreSessionId, continueLastSession, bypassPermissions, permissionMode, pluginDirs, additionalDirectories, tools, allowedTools, disallowedTools, worktreeSession, workdir, originalCwd, version, model, mcpServers, onExit, }) => {
|
|
75
|
-
return (_jsx(AppProvider, { restoreSessionId: restoreSessionId, continueLastSession: continueLastSession, children: _jsx(AppWithProviders, { bypassPermissions: bypassPermissions, permissionMode: permissionMode, pluginDirs: pluginDirs, additionalDirectories: additionalDirectories, tools: tools, allowedTools: allowedTools, disallowedTools: disallowedTools, worktreeSession: worktreeSession, workdir: workdir, originalCwd: originalCwd, version: version, model: model, mcpServers: mcpServers, onExit: onExit }) }));
|
|
76
|
-
};
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useEffect, useReducer } from "react";
|
|
3
|
-
import { Box, Text, useInput } from "ink";
|
|
4
|
-
import { useChat } from "../contexts/useChat.js";
|
|
5
|
-
import { getLastLines } from "wave-agent-sdk";
|
|
6
|
-
import { backgroundTaskManagerReducer, } from "../reducers/backgroundTaskManagerReducer.js";
|
|
7
|
-
export const BackgroundTaskManager = ({ onCancel, }) => {
|
|
8
|
-
const { backgroundTasks, getBackgroundTaskOutput, stopBackgroundTask } = useChat();
|
|
9
|
-
const MAX_VISIBLE_ITEMS = 3;
|
|
10
|
-
const [state, dispatch] = useReducer(backgroundTaskManagerReducer, {
|
|
11
|
-
tasks: [],
|
|
12
|
-
selectedIndex: 0,
|
|
13
|
-
viewMode: "list",
|
|
14
|
-
detailTaskId: null,
|
|
15
|
-
detailOutput: null,
|
|
16
|
-
pendingEffect: null,
|
|
17
|
-
});
|
|
18
|
-
// Handle pending effects
|
|
19
|
-
useEffect(() => {
|
|
20
|
-
if (!state.pendingEffect)
|
|
21
|
-
return;
|
|
22
|
-
const effect = state.pendingEffect;
|
|
23
|
-
dispatch({ type: "CLEAR_PENDING_EFFECT" });
|
|
24
|
-
switch (effect.type) {
|
|
25
|
-
case "CANCEL":
|
|
26
|
-
onCancel();
|
|
27
|
-
break;
|
|
28
|
-
case "STOP_TASK":
|
|
29
|
-
stopBackgroundTask(effect.taskId);
|
|
30
|
-
break;
|
|
31
|
-
}
|
|
32
|
-
}, [state.pendingEffect, onCancel, stopBackgroundTask]);
|
|
33
|
-
const { tasks, selectedIndex, viewMode, detailTaskId, detailOutput } = state;
|
|
34
|
-
// Convert backgroundTasks to local Task format
|
|
35
|
-
useEffect(() => {
|
|
36
|
-
dispatch({
|
|
37
|
-
type: "SET_TASKS",
|
|
38
|
-
tasks: backgroundTasks.map((task) => ({
|
|
39
|
-
id: task.id,
|
|
40
|
-
type: task.type,
|
|
41
|
-
description: task.description,
|
|
42
|
-
status: task.status,
|
|
43
|
-
startTime: task.startTime,
|
|
44
|
-
exitCode: task.exitCode,
|
|
45
|
-
runtime: task.runtime,
|
|
46
|
-
outputPath: task.outputPath,
|
|
47
|
-
})),
|
|
48
|
-
});
|
|
49
|
-
}, [backgroundTasks]);
|
|
50
|
-
// Load detail output for selected task
|
|
51
|
-
useEffect(() => {
|
|
52
|
-
if (viewMode === "detail" && detailTaskId) {
|
|
53
|
-
const output = getBackgroundTaskOutput(detailTaskId);
|
|
54
|
-
dispatch({ type: "SET_DETAIL_OUTPUT", output });
|
|
55
|
-
}
|
|
56
|
-
}, [viewMode, detailTaskId, getBackgroundTaskOutput]);
|
|
57
|
-
const formatDuration = (ms) => {
|
|
58
|
-
if (ms < 1000)
|
|
59
|
-
return `${ms}ms`;
|
|
60
|
-
if (ms < 60000)
|
|
61
|
-
return `${Math.round(ms / 1000)}s`;
|
|
62
|
-
const minutes = Math.floor(ms / 60000);
|
|
63
|
-
const seconds = Math.round((ms % 60000) / 1000);
|
|
64
|
-
return `${minutes}m ${seconds}s`;
|
|
65
|
-
};
|
|
66
|
-
const formatTime = (timestamp) => {
|
|
67
|
-
return new Date(timestamp).toLocaleTimeString();
|
|
68
|
-
};
|
|
69
|
-
// Calculate visible window
|
|
70
|
-
const startIndex = Math.max(0, Math.min(selectedIndex - Math.floor(MAX_VISIBLE_ITEMS / 2), Math.max(0, tasks.length - MAX_VISIBLE_ITEMS)));
|
|
71
|
-
const visibleTasks = tasks.slice(startIndex, startIndex + MAX_VISIBLE_ITEMS);
|
|
72
|
-
useInput((input, key) => {
|
|
73
|
-
dispatch({ type: "HANDLE_KEY", input, key });
|
|
74
|
-
});
|
|
75
|
-
if (viewMode === "detail" && detailTaskId && detailOutput) {
|
|
76
|
-
const task = tasks.find((t) => t.id === detailTaskId);
|
|
77
|
-
if (!task) {
|
|
78
|
-
dispatch({ type: "RESET_DETAIL" });
|
|
79
|
-
return null;
|
|
80
|
-
}
|
|
81
|
-
return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "cyan", borderBottom: false, borderLeft: false, borderRight: false, paddingTop: 1, gap: 1, children: [_jsx(Box, { children: _jsxs(Text, { color: "cyan", bold: true, children: ["Background Task Details: ", task.id] }) }), _jsxs(Box, { flexDirection: "column", gap: 1, children: [_jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "Type:" }), " ", task.type] }) }), task.description && (_jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "Description:" }), " ", task.description] }) })), _jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "Status:" }), " ", task.status, task.exitCode !== undefined && ` (exit code: ${task.exitCode})`] }) }), _jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "Started:" }), " ", formatTime(task.startTime), task.runtime !== undefined && (_jsxs(Text, { children: [" ", "| ", _jsx(Text, { color: "blue", children: "Runtime:" }), " ", formatDuration(task.runtime)] }))] }) }), task.outputPath && (_jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "Log File:" }), " ", task.outputPath] }) }))] }), detailOutput.stdout && (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { color: "green", bold: true, children: "OUTPUT (last 10 lines):" }), _jsx(Box, { borderStyle: "single", borderColor: "green", padding: 1, children: _jsx(Text, { children: getLastLines(detailOutput.stdout, 10) }) })] })), detailOutput.stderr && (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { color: "red", bold: true, children: "ERRORS:" }), _jsx(Box, { borderStyle: "single", borderColor: "red", padding: 1, children: _jsx(Text, { color: "red", children: getLastLines(detailOutput.stderr, 10) }) })] })), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: [task.status === "running" ? "k to stop · " : "", "Esc to go back"] }) })] }));
|
|
82
|
-
}
|
|
83
|
-
if (!backgroundTasks) {
|
|
84
|
-
return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "cyan", borderBottom: false, borderLeft: false, borderRight: false, paddingTop: 1, children: [_jsx(Text, { color: "cyan", bold: true, children: "Background Tasks" }), _jsx(Text, { children: "Background tasks not available" }), _jsx(Text, { dimColor: true, children: "Press Escape to close" })] }));
|
|
85
|
-
}
|
|
86
|
-
if (tasks.length === 0) {
|
|
87
|
-
return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "cyan", borderBottom: false, borderLeft: false, borderRight: false, paddingTop: 1, children: [_jsx(Text, { color: "cyan", bold: true, children: "Background Tasks" }), _jsx(Text, { children: "No background tasks found" }), _jsx(Text, { dimColor: true, children: "Press Escape to close" })] }));
|
|
88
|
-
}
|
|
89
|
-
return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "cyan", borderBottom: false, borderLeft: false, borderRight: false, paddingTop: 1, gap: 1, children: [_jsx(Box, { children: _jsx(Text, { color: "cyan", bold: true, children: "Background Tasks" }) }), _jsx(Text, { dimColor: true, children: "Select a task to view details" }), _jsx(Box, { flexDirection: "column", children: visibleTasks.map((task, index) => {
|
|
90
|
-
const actualIndex = startIndex + index;
|
|
91
|
-
const isSelected = actualIndex === selectedIndex;
|
|
92
|
-
return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { color: isSelected ? "black" : "white", backgroundColor: isSelected ? "cyan" : undefined, children: [isSelected ? "▶ " : " ", actualIndex + 1, ". [", task.id, "] ", task.type, task.description ? `: ${task.description}` : "", _jsxs(Text, { color: task.status === "running"
|
|
93
|
-
? "green"
|
|
94
|
-
: task.status === "completed"
|
|
95
|
-
? "blue"
|
|
96
|
-
: "red", children: [" ", "(", task.status, ")"] })] }), isSelected && (_jsx(Box, { marginLeft: 4, flexDirection: "column", children: _jsxs(Text, { color: "gray", dimColor: true, children: [task.outputPath ? (_jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "Log File:" }), " ", task.outputPath] })) : (`Started: ${formatTime(task.startTime)}`), task.runtime !== undefined &&
|
|
97
|
-
` | Runtime: ${formatDuration(task.runtime)}`, task.exitCode !== undefined && ` | Exit: ${task.exitCode}`] }) }))] }, task.id));
|
|
98
|
-
}) }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: ["\u2191/\u2193 to select \u00B7 Enter to view \u00B7", " ", tasks[selectedIndex]?.status === "running" ? "k to stop · " : "", "Esc to close"] }) })] }));
|
|
99
|
-
};
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Box, Text } from "ink";
|
|
3
|
-
import { getLastLines } from "wave-agent-sdk";
|
|
4
|
-
export const BangDisplay = ({ block, isExpanded = false, }) => {
|
|
5
|
-
const { command, output, stage, exitCode } = block;
|
|
6
|
-
const MAX_LINES = 3; // Set maximum display lines
|
|
7
|
-
const getStatusColor = () => {
|
|
8
|
-
if (stage === "running")
|
|
9
|
-
return "yellow";
|
|
10
|
-
if (exitCode === 0)
|
|
11
|
-
return "green";
|
|
12
|
-
if (exitCode !== null && exitCode !== 0)
|
|
13
|
-
return "red";
|
|
14
|
-
return "gray"; // Unknown state
|
|
15
|
-
};
|
|
16
|
-
return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { children: [_jsx(Text, { color: getStatusColor(), children: "! " }), _jsx(Text, { color: "white", children: command })] }), output && (_jsx(Box, { paddingLeft: 2, overflow: "hidden", children: _jsx(Text, { color: "gray", children: isExpanded ? output : getLastLines(output, MAX_LINES) }) }))] }));
|
|
17
|
-
};
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { Box, Text } from "ink";
|
|
3
|
-
import { Markdown } from "./Markdown.js";
|
|
4
|
-
export const BtwDisplay = ({ btwState }) => {
|
|
5
|
-
// Rendered for a real question (loading or answered) and for the bare
|
|
6
|
-
// `/btw` usage message (question === "", answer set).
|
|
7
|
-
if (!btwState.question && !btwState.answer) {
|
|
8
|
-
return null;
|
|
9
|
-
}
|
|
10
|
-
const answer = btwState.answer ?? "";
|
|
11
|
-
// The SDK surfaces failure as the answer string; classify by prefix so it
|
|
12
|
-
// renders in error color (aligned with Claude Code's error display).
|
|
13
|
-
const isError = !btwState.isLoading &&
|
|
14
|
-
(answer.startsWith("(API error") ||
|
|
15
|
-
answer.startsWith("(The model tried to call") ||
|
|
16
|
-
answer === "No response received");
|
|
17
|
-
return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [btwState.question && (_jsxs(Box, { children: [_jsxs(Text, { color: "warning", bold: true, children: ["/btw", " "] }), _jsx(Text, { dimColor: true, children: btwState.question })] })), _jsx(Box, { marginTop: 1, flexDirection: "column", children: btwState.isLoading ? (_jsx(Text, { color: "gray", children: "\u273B Answering..." })) : isError ? (_jsx(Text, { color: "error", children: answer })) : (_jsx(Markdown, { children: answer })) }), btwState.question && btwState.answer && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Escape to dismiss" }) })), !btwState.question && btwState.answer && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Escape to dismiss" }) }))] }));
|
|
18
|
-
};
|
|
19
|
-
BtwDisplay.displayName = "BtwDisplay";
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useState, useRef, useEffect, useCallback } from "react";
|
|
3
|
-
import { Box, useStdout, measureElement, Static } from "ink";
|
|
4
|
-
import { authService } from "wave-agent-sdk";
|
|
5
|
-
import { MessageList } from "./MessageList.js";
|
|
6
|
-
import { InputBox } from "./InputBox.js";
|
|
7
|
-
import { LoadingIndicator } from "./LoadingIndicator.js";
|
|
8
|
-
import { TaskList } from "./TaskList.js";
|
|
9
|
-
import { QueuedMessageList } from "./QueuedMessageList.js";
|
|
10
|
-
import { ConfirmationDetails } from "./ConfirmationDetails.js";
|
|
11
|
-
import { ConfirmationSelector } from "./ConfirmationSelector.js";
|
|
12
|
-
import { useChat } from "../contexts/useChat.js";
|
|
13
|
-
export const ChatInterface = () => {
|
|
14
|
-
const { messages, isLoading, isCommandRunning, isCompacting, sendMessage, abortMessage, mcpServers, connectMcpServer, disconnectMcpServer, isExpanded, sessionId, latestTotalTokens, maxInputTokens, slashCommands, hasSlashCommand, isConfirmationVisible, hasPendingConfirmations, confirmingTool, handleConfirmationDecision, handleConfirmationCancel, version, workdir, remountKey, forceRemount, getGatewayConfig, } = useChat();
|
|
15
|
-
const displayMessages = messages;
|
|
16
|
-
const [forceStatic, setForceStatic] = useState(false);
|
|
17
|
-
const { stdout } = useStdout();
|
|
18
|
-
const terminalHeight = stdout?.rows ?? 24;
|
|
19
|
-
const chatInterfaceRef = useRef(null);
|
|
20
|
-
// Compute whether the user has any usable auth/direct-API config,
|
|
21
|
-
// so the welcome page can prompt /login when neither is present.
|
|
22
|
-
// An SSO token counts as authenticated even if the access token is stale —
|
|
23
|
-
// it refreshes lazily on the next API call (matching the claude-code CLI).
|
|
24
|
-
const computeAuthState = useCallback(() => {
|
|
25
|
-
if (authService.getSSOToken())
|
|
26
|
-
return true;
|
|
27
|
-
const gateway = getGatewayConfig();
|
|
28
|
-
return Boolean(gateway.apiKey || gateway.baseURL);
|
|
29
|
-
}, [getGatewayConfig]);
|
|
30
|
-
const [hasAuth, setHasAuth] = useState(computeAuthState);
|
|
31
|
-
// Keep the /login hint in sync with auth state changes (login/logout).
|
|
32
|
-
useEffect(() => {
|
|
33
|
-
const unsubscribe = authService.onAuthChange(() => {
|
|
34
|
-
setHasAuth(computeAuthState());
|
|
35
|
-
});
|
|
36
|
-
return unsubscribe;
|
|
37
|
-
}, [computeAuthState]);
|
|
38
|
-
const showLoginHint = !hasAuth;
|
|
39
|
-
// Handle forceStatic mode for overflow and request remount when exiting
|
|
40
|
-
useEffect(() => {
|
|
41
|
-
if (isConfirmationVisible && chatInterfaceRef.current) {
|
|
42
|
-
const { height } = measureElement(chatInterfaceRef.current);
|
|
43
|
-
if (height > terminalHeight) {
|
|
44
|
-
setForceStatic(true);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
else if (forceStatic && !hasPendingConfirmations) {
|
|
48
|
-
setForceStatic(false);
|
|
49
|
-
forceRemount();
|
|
50
|
-
}
|
|
51
|
-
}, [
|
|
52
|
-
isConfirmationVisible,
|
|
53
|
-
terminalHeight,
|
|
54
|
-
forceStatic,
|
|
55
|
-
hasPendingConfirmations,
|
|
56
|
-
forceRemount,
|
|
57
|
-
]);
|
|
58
|
-
if (!sessionId)
|
|
59
|
-
return null;
|
|
60
|
-
return (_jsxs(Box, { ref: chatInterfaceRef, flexDirection: "column", children: [_jsx(MessageList, { messages: displayMessages, isExpanded: isExpanded, version: version, workdir: workdir, forceStatic: forceStatic }, remountKey), !isConfirmationVisible && !isExpanded && (_jsxs(_Fragment, { children: [(isLoading || isCommandRunning || isCompacting) && (_jsx(LoadingIndicator, { isLoading: isLoading, isCommandRunning: isCommandRunning, isCompacting: isCompacting, latestTotalTokens: latestTotalTokens })), _jsx(TaskList, {}), _jsx(QueuedMessageList, {}), _jsx(InputBox, { isLoading: isLoading, isCommandRunning: isCommandRunning, isCompacting: isCompacting, sendMessage: sendMessage, abortMessage: abortMessage, mcpServers: mcpServers, connectMcpServer: connectMcpServer, disconnectMcpServer: disconnectMcpServer, slashCommands: slashCommands, hasSlashCommand: hasSlashCommand, latestTotalTokens: latestTotalTokens, maxInputTokens: maxInputTokens, showLoginHint: showLoginHint })] })), isConfirmationVisible && (_jsxs(_Fragment, { children: [forceStatic ? (_jsx(Static, { items: [{ key: "confirmation-details" }], children: () => (_jsx(ConfirmationDetails, { toolName: confirmingTool.name, toolInput: confirmingTool.input, planContent: confirmingTool.planContent, warning: confirmingTool.warning, isExpanded: isExpanded }, "confirmation-details")) })) : (_jsx(ConfirmationDetails, { toolName: confirmingTool.name, toolInput: confirmingTool.input, planContent: confirmingTool.planContent, warning: confirmingTool.warning, isExpanded: isExpanded })), _jsx(ConfirmationSelector, { toolName: confirmingTool.name, toolInput: confirmingTool.input, suggestedPrefix: confirmingTool.suggestedPrefix, hidePersistentOption: confirmingTool.hidePersistentOption, permissionMode: confirmingTool.permissionMode, isExpanded: isExpanded, onDecision: handleConfirmationDecision, onCancel: handleConfirmationCancel })] }))] }));
|
|
61
|
-
};
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import type { SlashCommand } from "wave-agent-sdk";
|
|
3
|
-
export interface CommandSelectorProps {
|
|
4
|
-
searchQuery: string;
|
|
5
|
-
onSelect: (command: string) => void;
|
|
6
|
-
onInsert?: (command: string) => void;
|
|
7
|
-
onCancel: () => void;
|
|
8
|
-
commands?: SlashCommand[];
|
|
9
|
-
}
|
|
10
|
-
export declare const CommandSelector: React.FC<CommandSelectorProps>;
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useReducer, useEffect, useMemo } from "react";
|
|
3
|
-
import { Box, Text, useInput } from "ink";
|
|
4
|
-
import { AVAILABLE_COMMANDS } from "../constants/commands.js";
|
|
5
|
-
import { selectorReducer, } from "../reducers/selectorReducer.js";
|
|
6
|
-
export const CommandSelector = ({ searchQuery, onSelect, onInsert, onCancel, commands = [], }) => {
|
|
7
|
-
const MAX_VISIBLE_ITEMS = 3;
|
|
8
|
-
const [state, dispatch] = useReducer((selectorReducer), {
|
|
9
|
-
selectedIndex: 0,
|
|
10
|
-
pendingDecision: null,
|
|
11
|
-
items: [],
|
|
12
|
-
});
|
|
13
|
-
const { selectedIndex, pendingDecision, items: filteredCommands } = state;
|
|
14
|
-
// Merge agent commands and local commands, memoized to stabilize useEffect dependencies
|
|
15
|
-
const computedCommands = useMemo(() => {
|
|
16
|
-
const allCommands = [...AVAILABLE_COMMANDS, ...commands];
|
|
17
|
-
return allCommands.filter((command) => !searchQuery ||
|
|
18
|
-
command.id.toLowerCase().includes(searchQuery.toLowerCase()));
|
|
19
|
-
}, [searchQuery, commands]);
|
|
20
|
-
// Sync computed commands into reducer state (SET_ITEMS also resets index)
|
|
21
|
-
useEffect(() => {
|
|
22
|
-
dispatch({ type: "SET_ITEMS", items: computedCommands });
|
|
23
|
-
}, [computedCommands]);
|
|
24
|
-
// Handle decisions from reducer
|
|
25
|
-
useEffect(() => {
|
|
26
|
-
if (!pendingDecision)
|
|
27
|
-
return;
|
|
28
|
-
if (pendingDecision === "select") {
|
|
29
|
-
if (filteredCommands.length > 0 &&
|
|
30
|
-
selectedIndex < filteredCommands.length) {
|
|
31
|
-
onSelect(filteredCommands[selectedIndex].id);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
else if (pendingDecision === "insert" && onInsert) {
|
|
35
|
-
if (filteredCommands.length > 0 &&
|
|
36
|
-
selectedIndex < filteredCommands.length) {
|
|
37
|
-
onInsert(filteredCommands[selectedIndex].id);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
else if (pendingDecision === "cancel") {
|
|
41
|
-
onCancel();
|
|
42
|
-
}
|
|
43
|
-
dispatch({ type: "CLEAR_DECISION" });
|
|
44
|
-
}, [
|
|
45
|
-
pendingDecision,
|
|
46
|
-
selectedIndex,
|
|
47
|
-
filteredCommands,
|
|
48
|
-
onSelect,
|
|
49
|
-
onInsert,
|
|
50
|
-
onCancel,
|
|
51
|
-
]);
|
|
52
|
-
// Calculate visible window
|
|
53
|
-
const startIndex = Math.max(0, Math.min(selectedIndex - Math.floor(MAX_VISIBLE_ITEMS / 2), Math.max(0, filteredCommands.length - MAX_VISIBLE_ITEMS)));
|
|
54
|
-
const visibleCommands = filteredCommands.slice(startIndex, startIndex + MAX_VISIBLE_ITEMS);
|
|
55
|
-
useInput((input, key) => {
|
|
56
|
-
dispatch({ type: "HANDLE_KEY", key, hasInsert: !!onInsert });
|
|
57
|
-
});
|
|
58
|
-
if (filteredCommands.length === 0) {
|
|
59
|
-
return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "yellow", borderBottom: false, borderLeft: false, borderRight: false, children: [_jsxs(Text, { color: "yellow", children: ["No commands found for \"", searchQuery, "\""] }), _jsx(Text, { dimColor: true, children: "Press Escape to cancel" })] }));
|
|
60
|
-
}
|
|
61
|
-
return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "magenta", borderBottom: false, borderLeft: false, borderRight: false, gap: 1, children: [_jsx(Box, { children: _jsxs(Text, { color: "magenta", bold: true, children: ["Command Selector ", searchQuery && `(filtering: "${searchQuery}")`] }) }), _jsx(Box, { flexDirection: "column", children: visibleCommands.map((command, index) => {
|
|
62
|
-
const actualIndex = startIndex + index;
|
|
63
|
-
const isSelected = actualIndex === selectedIndex;
|
|
64
|
-
return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { color: isSelected ? "black" : "white", backgroundColor: isSelected ? "magenta" : undefined, children: [isSelected ? "▶ " : " ", "/", command.id] }), isSelected && (_jsx(Box, { marginLeft: 4, children: _jsx(Text, { color: "gray", dimColor: true, children: command.description }) }))] }, command.id));
|
|
65
|
-
}) }), _jsx(Box, { children: _jsxs(Text, { dimColor: true, children: ["\u2191\u2193 navigate \u2022 Enter execute \u2022 ", onInsert ? "Tab insert • " : "", "Esc cancel"] }) })] }));
|
|
66
|
-
};
|