wave-code 1.3.0 → 1.5.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.
Files changed (63) hide show
  1. package/dist/bundle/wave.mjs +1382 -1131
  2. package/package.json +9 -7
  3. package/src/cli.tsx +14 -22
  4. package/src/commands/update.ts +62 -22
  5. package/src/components/AgentsManager.tsx +3 -3
  6. package/src/components/App.tsx +5 -0
  7. package/src/components/BackgroundTaskManager.tsx +76 -54
  8. package/src/components/BtwDisplay.tsx +71 -15
  9. package/src/components/CompactDisplay.tsx +1 -6
  10. package/src/components/ConfirmationDetails.tsx +34 -13
  11. package/src/components/ConfirmationSelector.tsx +31 -36
  12. package/src/components/DiffDisplay.tsx +1 -1
  13. package/src/components/HooksManager.tsx +3 -3
  14. package/src/components/InputBox.tsx +37 -11
  15. package/src/components/LoginCommand.tsx +16 -35
  16. package/src/components/Markdown.tsx +7 -3
  17. package/src/components/MarketplaceAddForm.tsx +15 -19
  18. package/src/components/MessageBlockItem.tsx +0 -6
  19. package/src/components/RemoteControlView.tsx +175 -0
  20. package/src/components/ScrolledContent.tsx +15 -13
  21. package/src/components/SkillsManager.tsx +3 -3
  22. package/src/components/TaskList.tsx +3 -3
  23. package/src/components/ToolDisplay.tsx +3 -18
  24. package/src/components/WorkflowManager.tsx +150 -136
  25. package/src/components/WorkflowRunDetail.tsx +193 -0
  26. package/src/constants/commands.ts +6 -0
  27. package/src/contexts/useChat.tsx +308 -154
  28. package/src/daemon/commands.ts +31 -22
  29. package/src/daemon-cli.ts +6 -1
  30. package/src/hooks/useInputManager.ts +25 -39
  31. package/src/hooks/useLineScroll.ts +51 -5
  32. package/src/hooks/useRemoteControl.ts +346 -0
  33. package/src/index.ts +35 -0
  34. package/src/managers/inputHandlers.ts +5 -0
  35. package/src/managers/inputReducer.ts +39 -0
  36. package/src/print-cli.ts +5 -0
  37. package/src/reducers/workflowManagerReducer.ts +21 -2
  38. package/src/remote/frameBudget.ts +45 -0
  39. package/src/remote/hostIdentity.ts +128 -0
  40. package/src/remote/messageWindow.ts +46 -0
  41. package/src/remote/notificationCoalescer.ts +192 -0
  42. package/src/remote/relayClient.ts +690 -0
  43. package/src/remote/remoteControlCliHost.ts +420 -0
  44. package/src/remote/remoteControlCommands.ts +197 -0
  45. package/src/remote/remoteControlConfig.ts +353 -0
  46. package/src/remote/remoteControlService.ts +822 -0
  47. package/src/remote/remoteControlSink.ts +78 -0
  48. package/src/remote/remoteNotifications.ts +200 -0
  49. package/src/stdio/agentBridge.ts +874 -106
  50. package/src/stdio/daemonServer.ts +30 -0
  51. package/src/stdio/hostSlashCommands.ts +209 -0
  52. package/src/stdio/jsonRpcConnection.ts +11 -2
  53. package/src/stdio/protocol.ts +14 -115
  54. package/src/stdio/stdioServer.ts +33 -2
  55. package/src/stdio/uiPayload.ts +65 -0
  56. package/src/stdio-cli.ts +11 -2
  57. package/src/types.ts +7 -0
  58. package/src/utils/gitCredentialHelper.ts +106 -0
  59. package/src/utils/logger.ts +5 -2
  60. package/src/utils/rewindCheckpoints.ts +2 -4
  61. package/src/utils/workspaceDiff.ts +620 -0
  62. package/src/utils/worktree.ts +97 -0
  63. package/src/utils/bracketedPaste.ts +0 -170
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Git credential helper installed for repositories cloned from a `wave://clone`
3
+ * deep link (spec: docs/specs/desktop/desktop-deep-link.md「克隆出的仓库长期
4
+ * 自动认证」).
5
+ *
6
+ * What lands in the repository config is *this command*, never the credential:
7
+ *
8
+ * [credential]
9
+ * helper =
10
+ * helper = !exec '/Users/me/.wave/git-credential-wave'
11
+ *
12
+ * The empty first entry resets the helper list inherited from system/global
13
+ * config. Without it a machine-wide store/cache helper (osxkeychain, manager,
14
+ * credential-store) also runs and pins the first credential it sees, so later
15
+ * logins and token refreshes would never be picked up.
16
+ *
17
+ * The helper is a plain `/bin/sh` script rather than a call back into the CLI:
18
+ * git invokes it before *every* authenticated network operation, and booting
19
+ * the Electron-bundled Node runtime for that would add seconds to each push. It
20
+ * only needs the token sitting in `~/.wave/auth.json`, which the CLI keeps
21
+ * current (including background refreshes).
22
+ */
23
+
24
+ import { chmodSync, mkdirSync, writeFileSync } from "fs";
25
+ import * as path from "path";
26
+ import { AuthService } from "wave-agent-sdk";
27
+
28
+ /** Extensionless on purpose: git execs it through the shebang, and MSYS sh
29
+ * resolves a bare path that starts with `#!`. */
30
+ export const GIT_CREDENTIAL_HELPER_FILENAME = "git-credential-wave";
31
+
32
+ export interface InstalledGitCredentialHelper {
33
+ /** Absolute path of the generated script. */
34
+ path: string;
35
+ /** Ready-to-use `credential.helper` value (written into repo config). */
36
+ command: string;
37
+ }
38
+
39
+ /** `<home>/.wave/git-credential-wave` — next to `auth.json`. */
40
+ export function gitCredentialHelperPath(): string {
41
+ return path.join(
42
+ path.dirname(AuthService.getInstance().getAuthPath()),
43
+ GIT_CREDENTIAL_HELPER_FILENAME,
44
+ );
45
+ }
46
+
47
+ /**
48
+ * (Re)write the helper script and return the config value that installs it.
49
+ * Idempotent — safe to call on every deep-link clone.
50
+ */
51
+ export function installGitCredentialHelper(): InstalledGitCredentialHelper {
52
+ const scriptPath = gitCredentialHelperPath();
53
+ mkdirSync(path.dirname(scriptPath), { recursive: true });
54
+ writeFileSync(
55
+ scriptPath,
56
+ renderGitCredentialHelper(AuthService.getInstance().getAuthPath()),
57
+ "utf-8",
58
+ );
59
+ chmodSync(scriptPath, 0o755);
60
+ return { path: scriptPath, command: `!exec ${shellQuote(scriptPath)}` };
61
+ }
62
+
63
+ /** The script body. Exported for tests. */
64
+ export function renderGitCredentialHelper(authFilePath: string): string {
65
+ return `#!/bin/sh
66
+ # Wave git credential helper — generated by CodeWave IDE.
67
+ # Rewritten on every deep-link clone; do not edit by hand.
68
+ #
69
+ # Prints the current Wave SSO token, read fresh from the login store on each
70
+ # request, so logging in (or the CLI refreshing the token) takes effect without
71
+ # touching any repository.
72
+
73
+ AUTH_FILE=${shellQuote(authFilePath)}
74
+
75
+ # Drain git's request: we only look at the capabilities it advertises below, and
76
+ # a helper that exits before reading stdin can get EPIPE'd.
77
+ input=$(cat 2>/dev/null) || input=
78
+
79
+ token=$(sed -n 's/.*"SSO_TOKEN"[[:space:]]*:[[:space:]]*"\\([^"]*\\)".*/\\1/p' "$AUTH_FILE" 2>/dev/null | head -n 1)
80
+
81
+ if [ -z "$token" ]; then
82
+ # Not logged in on this machine. Stop git right here: quit=true skips the
83
+ # remaining helpers *and* the interactive prompt (there is no terminal when
84
+ # the agent runs git), so the operation fails fast instead of hanging.
85
+ echo "quit=true"
86
+ exit 0
87
+ fi
88
+
89
+ case "$input" in
90
+ *capability\\[\\]=authtype*)
91
+ echo "capability[]=authtype"
92
+ echo "authtype=bearer"
93
+ printf 'credential=%s\\n' "$token"
94
+ ;;
95
+ *)
96
+ echo "username=oauth2"
97
+ printf 'password=%s\\n' "$token"
98
+ ;;
99
+ esac
100
+ `;
101
+ }
102
+
103
+ /** Single-quote a value for `sh`, escaping embedded single quotes. */
104
+ export function shellQuote(value: string): string {
105
+ return `'${value.replace(/'/g, `'\\''`)}'`;
106
+ }
@@ -11,7 +11,7 @@
11
11
  import * as fs from "fs";
12
12
  import * as path from "path";
13
13
  import { Chalk } from "chalk";
14
- import { getLastLines } from "wave-agent-sdk";
14
+ import { getLastLines, errorReplacer } from "wave-agent-sdk";
15
15
  import { LOG_FILE } from "./constants.js";
16
16
 
17
17
  const chalk = new Chalk({ level: 3 });
@@ -132,7 +132,10 @@ const formatArg = (arg: unknown): string => {
132
132
  result = arg.stack || arg.message || String(arg);
133
133
  } else if (typeof arg === "object") {
134
134
  try {
135
- result = JSON.stringify(arg);
135
+ // The replacer keeps Errors nested inside a payload ({ error: e }) from
136
+ // serializing to `{}` — the `instanceof` check above only covers args
137
+ // passed bare.
138
+ result = JSON.stringify(arg, errorReplacer);
136
139
  } catch {
137
140
  // If JSON.stringify fails, fallback to String()
138
141
  result = String(arg);
@@ -2,15 +2,13 @@ import type { Message } from "wave-agent-sdk";
2
2
 
3
3
  /**
4
4
  * 判断一条 user 消息能否作为 /rewind 检查点。
5
- * 后台任务通知(task_notification)、hook 注入的消息(source: "hook")
6
- * 都是系统生成、用户不可见的,不能作为回滚点。bash 模式命令消息
5
+ * 后台任务通知(task_notification)与 hook 注入的消息都是系统生成、
6
+ * 用户不可见的(meta),不能作为回滚点。bash 模式命令消息
7
7
  * (`!ls`)是用户真正输入,与 fork skill 命令消息一致,可作为回滚点。
8
8
  * CLI 交互式选择器与 stdio listRewindCheckpoints 共用此判定,避免两处漂移。
9
9
  */
10
10
  export function isUserCheckpointMessage(m: Message): boolean {
11
11
  if (m.role !== "user" || m.isMeta) return false;
12
12
  if (m.blocks.some((b) => b.type === "task_notification")) return false;
13
- if (m.blocks.some((b) => b.type === "text" && b.source === "hook"))
14
- return false;
15
13
  return true;
16
14
  }