wave-code 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundle/wave.mjs +1049 -584
- package/package.json +4 -3
- package/src/cli.tsx +9 -0
- package/src/commands/plugin/install.ts +6 -7
- package/src/commands/plugin/uninstall.ts +11 -5
- package/src/components/ChatInterface.tsx +1 -0
- package/src/components/ConfirmationDetails.tsx +36 -15
- package/src/components/ConfirmationSelector.tsx +39 -0
- package/src/components/InputBox.tsx +39 -2
- package/src/components/Markdown.tsx +21 -8
- package/src/components/MarketplaceDetail.tsx +10 -27
- package/src/components/MarketplaceView.tsx +17 -3
- package/src/components/Notifications.tsx +7 -0
- package/src/components/PlanView.tsx +22 -17
- package/src/components/PluginManagerShell.tsx +3 -3
- package/src/components/PluginManagerTypes.ts +2 -1
- package/src/components/ResumeCommand.tsx +84 -0
- package/src/components/ScrolledContent.tsx +71 -0
- package/src/components/SessionSelector.tsx +184 -6
- package/src/components/SessionSelectorFlow.tsx +246 -0
- package/src/constants/commands.ts +18 -0
- package/src/contexts/useChat.tsx +158 -28
- package/src/daemon/commands.ts +569 -46
- package/src/daemon-cli.ts +6 -0
- package/src/hooks/useInputManager.ts +16 -0
- package/src/hooks/usePluginManager.ts +104 -78
- package/src/index.ts +62 -8
- package/src/managers/inputHandlers.ts +14 -9
- package/src/managers/inputReducer.ts +29 -9
- package/src/reducers/confirmationReducer.ts +20 -1
- package/src/reducers/selectorReducer.ts +3 -0
- package/src/session-selector-cli.tsx +9 -255
- package/src/stdio/agentBridge.ts +397 -95
- package/src/stdio/protocol.ts +9 -0
- package/src/stdio-cli.ts +6 -0
- package/src/utils/sessionOwnership.ts +62 -0
- package/src/components/PlanDisplay.tsx +0 -18
package/src/stdio/protocol.ts
CHANGED
|
@@ -51,6 +51,8 @@ export type RequestMethod =
|
|
|
51
51
|
| "destroy"
|
|
52
52
|
| "restoreSession"
|
|
53
53
|
| "listSessions"
|
|
54
|
+
| "listAllSessions"
|
|
55
|
+
| "renameSession"
|
|
54
56
|
| "getSessionInfo"
|
|
55
57
|
| "sendMessage"
|
|
56
58
|
| "bang"
|
|
@@ -86,6 +88,10 @@ export type RequestMethod =
|
|
|
86
88
|
| "updateConfig"
|
|
87
89
|
| "getConfiguredModels"
|
|
88
90
|
| "setModel"
|
|
91
|
+
// User preferences (global — read/write user-level ~/.wave/settings.json,
|
|
92
|
+
// 设置页保存路径,见 docs/specs/core/agent-config.md「设置实时重载」)
|
|
93
|
+
| "getUserSettings"
|
|
94
|
+
| "updateUserSettings"
|
|
89
95
|
// Permissions (daemon attach: re-surface pending approvals after reconnect)
|
|
90
96
|
| "listPendingPermissions"
|
|
91
97
|
// Daemon (global — list in-memory session registry, no session required)
|
|
@@ -105,6 +111,8 @@ export type RequestMethod =
|
|
|
105
111
|
| "enablePlugin"
|
|
106
112
|
| "disablePlugin"
|
|
107
113
|
| "updatePlugin"
|
|
114
|
+
| "setPluginScope"
|
|
115
|
+
| "reloadPlugins"
|
|
108
116
|
| "listMarketplaces"
|
|
109
117
|
| "addMarketplace"
|
|
110
118
|
| "removeMarketplace"
|
|
@@ -147,6 +155,7 @@ export type ServerNotificationMethod =
|
|
|
147
155
|
| "compactBlockAdded"
|
|
148
156
|
| "compactionStateChange"
|
|
149
157
|
| "compactionContentUpdate"
|
|
158
|
+
| "planFileUpdated"
|
|
150
159
|
| "backgroundTasksChange"
|
|
151
160
|
| "btwContent"
|
|
152
161
|
| "contextUsage";
|
package/src/stdio-cli.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* the client sends an "initialize" request.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import { ensureRuntimeDeps } from "wave-agent-sdk";
|
|
9
10
|
import { StdioServer } from "./stdio/stdioServer.js";
|
|
10
11
|
import { logger } from "./utils/logger.js";
|
|
11
12
|
|
|
@@ -54,6 +55,11 @@ export function guardStdoutForJsonRpc(): void {
|
|
|
54
55
|
|
|
55
56
|
export async function startStdioCli(): Promise<void> {
|
|
56
57
|
guardStdoutForJsonRpc();
|
|
58
|
+
// Install the on-demand runtime dependencies (image codec + ripgrep) before
|
|
59
|
+
// answering any RPC (see cli.tsx). Blocking here is what closes the race: the
|
|
60
|
+
// host's `initialize` — and with it the webview's initial state — only lands
|
|
61
|
+
// once a pasted image can be handled. Failures are non-fatal.
|
|
62
|
+
await ensureRuntimeDeps();
|
|
57
63
|
// Registered here (stdio mode only): the interactive CLI keeps Node's
|
|
58
64
|
// default behavior so the terminal shows the crash stack directly.
|
|
59
65
|
process.on("uncaughtException", (error) =>
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { existsSync } from "fs";
|
|
2
|
+
import { PathEncoder } from "wave-agent-sdk";
|
|
3
|
+
|
|
4
|
+
/** POSIX single-quote wrapping for use inside a `cd <path> && ...` command. */
|
|
5
|
+
export function quotePath(p: string): string {
|
|
6
|
+
return `'${p.replace(/'/g, `'\\''`)}'`;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type SessionOwnership =
|
|
10
|
+
| { kind: "current" }
|
|
11
|
+
| { kind: "worktree"; resumeWorkdir: string }
|
|
12
|
+
| { kind: "cross-project"; command: string };
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Decide how a selected session relates to the current working directory.
|
|
16
|
+
*
|
|
17
|
+
* Ownership is decided by comparing encoded directory names — the decoded
|
|
18
|
+
* workdir is lossy for paths containing "-", but re-encoding it reproduces the
|
|
19
|
+
* original encoded directory name exactly.
|
|
20
|
+
*
|
|
21
|
+
* - current: session belongs to the current directory → resume in place
|
|
22
|
+
* - worktree: session belongs to a sibling same-repo worktree → resume
|
|
23
|
+
* after chdir into it (skipped when the worktree dir is gone)
|
|
24
|
+
* - cross-project: session belongs to another project → print a cd command
|
|
25
|
+
*/
|
|
26
|
+
export async function resolveSessionOwnership(
|
|
27
|
+
session: { id: string; workdir: string },
|
|
28
|
+
opts: { worktreePaths: string[]; currentWorkdir: string },
|
|
29
|
+
): Promise<SessionOwnership> {
|
|
30
|
+
const encoder = new PathEncoder();
|
|
31
|
+
// encode() resolves the path via realpath and throws ENOENT when the
|
|
32
|
+
// directory no longer exists (e.g. a deleted worktree); fall back to the
|
|
33
|
+
// pure string encodeSync so the picker still works for ghost sessions.
|
|
34
|
+
let sessionEncoded: string;
|
|
35
|
+
try {
|
|
36
|
+
sessionEncoded = await encoder.encode(session.workdir);
|
|
37
|
+
} catch {
|
|
38
|
+
sessionEncoded = encoder.encodeSync(session.workdir);
|
|
39
|
+
}
|
|
40
|
+
const cwdEncoded = await encoder.encode(opts.currentWorkdir);
|
|
41
|
+
|
|
42
|
+
if (sessionEncoded === cwdEncoded) {
|
|
43
|
+
return { kind: "current" };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
for (const wt of opts.worktreePaths) {
|
|
47
|
+
let wtEncoded: string;
|
|
48
|
+
try {
|
|
49
|
+
wtEncoded = await encoder.encode(wt);
|
|
50
|
+
} catch {
|
|
51
|
+
wtEncoded = encoder.encodeSync(wt);
|
|
52
|
+
}
|
|
53
|
+
if (wtEncoded === sessionEncoded && existsSync(wt)) {
|
|
54
|
+
return { kind: "worktree", resumeWorkdir: wt };
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
kind: "cross-project",
|
|
60
|
+
command: `cd ${quotePath(session.workdir)} && wave --restore ${session.id}`,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { Box } from "ink";
|
|
3
|
-
import { Markdown } from "./Markdown.js";
|
|
4
|
-
|
|
5
|
-
interface PlanDisplayProps {
|
|
6
|
-
plan: string;
|
|
7
|
-
isExpanded?: boolean;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export const PlanDisplay: React.FC<PlanDisplayProps> = ({ plan }) => {
|
|
11
|
-
return (
|
|
12
|
-
<Box flexDirection="column" marginTop={1}>
|
|
13
|
-
<Box flexDirection="column">
|
|
14
|
-
<Markdown>{plan}</Markdown>
|
|
15
|
-
</Box>
|
|
16
|
-
</Box>
|
|
17
|
-
);
|
|
18
|
-
};
|