wave-code 1.3.0 → 1.4.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 +1275 -895
- package/package.json +4 -2
- package/src/commands/update.ts +62 -22
- package/src/components/BackgroundTaskManager.tsx +76 -54
- package/src/components/ConfirmationDetails.tsx +17 -3
- package/src/components/InputBox.tsx +2 -0
- package/src/components/MessageBlockItem.tsx +0 -6
- package/src/components/WorkflowManager.tsx +38 -138
- package/src/components/WorkflowRunDetail.tsx +193 -0
- package/src/constants/commands.ts +6 -0
- package/src/contexts/useChat.tsx +359 -127
- package/src/daemon/commands.ts +13 -4
- package/src/daemon-cli.ts +6 -1
- package/src/hooks/useInputManager.ts +4 -0
- package/src/hooks/useRemoteControl.ts +324 -0
- package/src/index.ts +35 -0
- package/src/managers/inputHandlers.ts +2 -0
- package/src/managers/inputReducer.ts +1 -0
- package/src/print-cli.ts +5 -0
- package/src/reducers/workflowManagerReducer.ts +21 -2
- package/src/remote/frameBudget.ts +45 -0
- package/src/remote/hostIdentity.ts +128 -0
- package/src/remote/messageWindow.ts +97 -0
- package/src/remote/notificationCoalescer.ts +174 -0
- package/src/remote/relayClient.ts +668 -0
- package/src/remote/remoteControlCliHost.ts +391 -0
- package/src/remote/remoteControlCommands.ts +197 -0
- package/src/remote/remoteControlConfig.ts +334 -0
- package/src/remote/remoteControlService.ts +799 -0
- package/src/remote/remoteControlSink.ts +77 -0
- package/src/remote/remoteNotifications.ts +194 -0
- package/src/stdio/agentBridge.ts +608 -74
- package/src/stdio/daemonServer.ts +30 -0
- package/src/stdio/jsonRpcConnection.ts +11 -2
- package/src/stdio/protocol.ts +14 -115
- package/src/stdio/stdioServer.ts +33 -2
- package/src/stdio-cli.ts +11 -2
- package/src/utils/gitCredentialHelper.ts +106 -0
- package/src/utils/logger.ts +5 -2
- package/src/utils/rewindCheckpoints.ts +2 -4
- package/src/utils/workspaceDiff.ts +620 -0
- package/src/utils/worktree.ts +97 -0
package/src/utils/worktree.ts
CHANGED
|
@@ -407,6 +407,103 @@ export interface WorktreeChanges {
|
|
|
407
407
|
commits: number;
|
|
408
408
|
}
|
|
409
409
|
|
|
410
|
+
/**
|
|
411
|
+
* The linked worktree a directory sits in, derived from the filesystem only.
|
|
412
|
+
* Same field semantics as `createWorktree`'s result, so a caller can hand it
|
|
413
|
+
* straight to `removeWorktree`.
|
|
414
|
+
*/
|
|
415
|
+
export interface DerivedWorktree {
|
|
416
|
+
path: string;
|
|
417
|
+
branch: string;
|
|
418
|
+
repoRoot: string;
|
|
419
|
+
hookBased: boolean;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Work out whether `sessionDir` **is** a linked git worktree — and which one —
|
|
424
|
+
* without running git.
|
|
425
|
+
*
|
|
426
|
+
* Two callers need this and both need it cheap: `listDaemonSessions` embeds the
|
|
427
|
+
* answer in every session row (the remote page decides from it whether deleting
|
|
428
|
+
* a session also deletes a worktree), and `destroy --removeWorktree` needs the
|
|
429
|
+
* path/branch/repoRoot that `removeWorktree` takes. Shelling out per row is not
|
|
430
|
+
* an option — `listDaemonSessions` runs on every reconnect, snapshot and page
|
|
431
|
+
* open, and a synchronous git call in this process freezes every session it
|
|
432
|
+
* serves (see the note at the top of this file). So the whole derivation is
|
|
433
|
+
* plain fs reads:
|
|
434
|
+
*
|
|
435
|
+
* - `.git` a **directory** in `sessionDir` ⇒ it is the main working tree, not a
|
|
436
|
+
* worktree ⇒ `undefined` (removing it would be removing the repository).
|
|
437
|
+
* - `.git` a **file** ⇒ a linked worktree; the file holds `gitdir: <path>`,
|
|
438
|
+
* which is where that worktree's own HEAD lives.
|
|
439
|
+
* - branch = `<gitdir>/HEAD` (`ref: refs/heads/<name>`); a detached HEAD has no
|
|
440
|
+
* branch, which returns `""` — the same thing `git branch --show-current`
|
|
441
|
+
* says, and `removeWorktree` skips a branch it cannot name.
|
|
442
|
+
* - repoRoot = the main repository root, i.e. the directory *above* the common
|
|
443
|
+
* git dir that `<gitdir>/commondir` points at (`<repoRoot>/.git`).
|
|
444
|
+
*
|
|
445
|
+
* `sessionDir` must be the worktree root itself (the directory a session was
|
|
446
|
+
* created in) — a subdirectory of a worktree has no `.git` of its own, and this
|
|
447
|
+
* returns `undefined` for it rather than guessing. Every failure path returns
|
|
448
|
+
* `undefined`: "not a worktree / cannot tell" is a legitimate answer and must
|
|
449
|
+
* never throw into a caller that is only decorating a list.
|
|
450
|
+
*/
|
|
451
|
+
export function deriveWorktreeInfo(
|
|
452
|
+
sessionDir: string,
|
|
453
|
+
): DerivedWorktree | undefined {
|
|
454
|
+
try {
|
|
455
|
+
if (!sessionDir) return undefined;
|
|
456
|
+
const dir = path.resolve(sessionDir);
|
|
457
|
+
const gitEntry = path.join(dir, ".git");
|
|
458
|
+
if (!fs.statSync(gitEntry).isFile()) return undefined;
|
|
459
|
+
|
|
460
|
+
const prefix = "gitdir: ";
|
|
461
|
+
const content = fs.readFileSync(gitEntry, "utf8").trim();
|
|
462
|
+
if (!content.startsWith(prefix)) return undefined;
|
|
463
|
+
const gitDir = path.resolve(dir, content.substring(prefix.length).trim());
|
|
464
|
+
|
|
465
|
+
let branch = "";
|
|
466
|
+
try {
|
|
467
|
+
const head = fs.readFileSync(path.join(gitDir, "HEAD"), "utf8").trim();
|
|
468
|
+
const refPrefix = "ref: refs/heads/";
|
|
469
|
+
if (head.startsWith(refPrefix)) {
|
|
470
|
+
branch = head.substring(refPrefix.length);
|
|
471
|
+
}
|
|
472
|
+
} catch {
|
|
473
|
+
// Detached/unreadable HEAD: no branch to delete, the worktree is still
|
|
474
|
+
// identifiable.
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
let repoRoot = "";
|
|
478
|
+
try {
|
|
479
|
+
const common = fs
|
|
480
|
+
.readFileSync(path.join(gitDir, "commondir"), "utf8")
|
|
481
|
+
.trim();
|
|
482
|
+
const commonDir = path.resolve(gitDir, common);
|
|
483
|
+
repoRoot =
|
|
484
|
+
path.basename(commonDir) === ".git"
|
|
485
|
+
? path.dirname(commonDir)
|
|
486
|
+
: commonDir;
|
|
487
|
+
} catch {
|
|
488
|
+
return undefined;
|
|
489
|
+
}
|
|
490
|
+
if (!repoRoot) return undefined;
|
|
491
|
+
|
|
492
|
+
// Hook-based worktrees are removed by the WorktreeRemove hook, never by
|
|
493
|
+
// `git worktree remove` — mirror createWorktree's own hookBased decision
|
|
494
|
+
// (same test `wave daemon destroy --remove-worktree` uses).
|
|
495
|
+
const config = loadMergedWaveConfig(repoRoot);
|
|
496
|
+
return {
|
|
497
|
+
path: dir,
|
|
498
|
+
branch,
|
|
499
|
+
repoRoot,
|
|
500
|
+
hookBased: hasWorktreeCreateHook(config?.hooks),
|
|
501
|
+
};
|
|
502
|
+
} catch {
|
|
503
|
+
return undefined;
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
|
|
410
507
|
/**
|
|
411
508
|
* Count what deleting a worktree would throw away, so the caller can warn
|
|
412
509
|
* before it happens. Both counts are best-effort: an unknown base branch (never
|