@kw-yeh/vibeflow 4.0.1 → 4.0.3
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/README.md +118 -99
- package/dist/postinstall.mjs +57 -0
- package/dist/vibeflow.mjs +11 -6
- package/dist/web/404/index.html +1 -1
- package/dist/web/404.html +1 -1
- package/dist/web/home/index.html +1 -1
- package/package.json +4 -1
- /package/dist/web/_next/static/{-9MMnQDtlhk8JcEq6dTBS → 0iT_99y5BhZs3U_2l_mSN}/_buildManifest.js +0 -0
- /package/dist/web/_next/static/{-9MMnQDtlhk8JcEq6dTBS → 0iT_99y5BhZs3U_2l_mSN}/_ssgManifest.js +0 -0
package/README.md
CHANGED
|
@@ -1,146 +1,165 @@
|
|
|
1
1
|
# VibeFlow
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**讓多個 coding agent 同時開工的本機看板。**
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
每張卡片是一個任務。卡片一開始,VibeFlow 就幫它開一條獨立的 Git 分支與 worktree,在裡面啟動 Claude Code 或 Codex,並把即時終端機放在卡片旁邊。好幾張卡可以同時跑,彼此不會改到同一份檔案,你的專案資料夾本身也不會被切換分支。
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
* **儲存**: core 自有的 JSON store(`packages/core/src/json-store.ts`,沿用舊版桌面 App 的 electron-store 檔案,舊看板會直接接上)
|
|
7
|
+
```bash
|
|
8
|
+
npm i -g @kw-yeh/vibeflow@latest
|
|
9
|
+
vibeflow
|
|
10
|
+
```
|
|
12
11
|
|
|
13
|
-
|
|
12
|
+
一切都在你的電腦上執行:不需要另外註冊帳號,看板與程式碼都留在本機。
|
|
14
13
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## 它能幫你做什麼
|
|
17
|
+
|
|
18
|
+
- **一卡一分支一 worktree**:建卡時自動建立分支與 worktree、複製 `.env` 等被忽略的檔案,相依套件也在背景複製好,worktree 建好就能直接跑。
|
|
19
|
+
- **看板式管理多個 agent**:Backlog → In Progress → Done。把卡片拖進 In Progress,agent 就在它的 worktree 裡開始工作。
|
|
20
|
+
- **即時終端機**:每張卡都有自己的互動式終端機,agent 要你確認時直接在畫面上回答。
|
|
21
|
+
- **關掉也不會中斷**:裝了 tmux 時,agent 跑在背景 session 裡;關掉瀏覽器甚至 VibeFlow 本身,任務都會繼續,重新開啟就接回來。
|
|
22
|
+
- **看得到 agent 做了什麼**:每張卡有 diff 檢視、artifacts,以及一份會保留下來的決策紀錄(agent 做了哪些決定、為什麼)。
|
|
23
|
+
- **選你要的 agent**:Claude Code 或 Codex,每張卡可以各自指定 model、推理強度(effort)與 Auto Mode(是否免確認執行)。
|
|
24
|
+
- **Web UI 與終端機 UI 共用同一個看板**:習慣瀏覽器用 Web UI,習慣終端機用 `vibeflow tui`。
|
|
25
|
+
- **也能用指令操作**:`vibeflow task create` 不開 UI 直接建卡;agent 自己也能在看板上建立後續的卡片。
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## 快速開始
|
|
21
30
|
|
|
22
|
-
|
|
31
|
+
### 1. 先準備好這些
|
|
32
|
+
|
|
33
|
+
| 需要 | 說明 |
|
|
34
|
+
|---|---|
|
|
35
|
+
| **Node.js 22+** | [nodejs.org](https://nodejs.org) |
|
|
36
|
+
| **Git 2.30+** | 要操作的專案必須是 Git repository |
|
|
37
|
+
| **Claude Code 或 Codex CLI,且已登入** | 至少一個。Claude Code:`npm install -g @anthropic-ai/claude-code`(或 `curl -fsSL https://claude.ai/install.sh \| bash`),裝完執行一次 `claude` 完成登入 |
|
|
38
|
+
| tmux(建議) | macOS:`brew install tmux`。沒有也能用,只是關掉 VibeFlow 時 agent 會一起結束 |
|
|
39
|
+
| Git Bash(僅 Windows) | 隨 [Git for Windows](https://git-scm.com/download/win) 安裝 |
|
|
40
|
+
|
|
41
|
+
### 2. 安裝並啟動
|
|
23
42
|
|
|
24
43
|
```bash
|
|
25
|
-
|
|
26
|
-
vibeflow
|
|
27
|
-
vibeflow status # host、執行中的 session、看板摘要
|
|
28
|
-
vibeflow stop <id> | --all # 停止 agent session
|
|
29
|
-
vibeflow shutdown # 停止 host(tmux 裡的 agent 會繼續執行)
|
|
30
|
-
vibeflow open <path> # 把專案資料夾加入最近使用清單,再開啟 Web UI
|
|
31
|
-
vibeflow doctor # 檢查前置需求,並列出修正指令
|
|
32
|
-
vibeflow task create … # 不開 UI 直接建卡(vibeflow task --help)
|
|
44
|
+
npm i -g @kw-yeh/vibeflow@latest
|
|
45
|
+
vibeflow
|
|
33
46
|
```
|
|
34
47
|
|
|
35
|
-
|
|
48
|
+
VibeFlow 會在本機啟動,並自動用瀏覽器開啟看板。第一次啟動時如果偵測到缺了什麼,會直接告訴你該怎麼補。
|
|
36
49
|
|
|
37
|
-
|
|
50
|
+
### 3. 開第一張卡
|
|
38
51
|
|
|
39
|
-
|
|
52
|
+
1. 按側邊欄的 **+**,或 Backlog 欄的 **新建任務**。
|
|
53
|
+
2. 選一個專案資料夾(必須是 Git repo),選要從哪條分支開始。
|
|
54
|
+
3. 寫下標題與你要 agent 做的事,選 agent,按建立。
|
|
55
|
+
4. 把卡片拖到 **In Progress**,agent 就開始工作;點開卡片就能看到它的即時終端機。
|
|
56
|
+
5. 做完之後在卡片上檢查 diff;要留下的變更請讓 agent commit、push 或開 PR。
|
|
57
|
+
6. 把卡片移到 **Done**:VibeFlow 會刪掉這張卡的 worktree 與本地分支。**尚未 commit 的變更會一起消失**,移動前會再跟你確認一次。
|
|
40
58
|
|
|
41
|
-
|
|
42
|
-
2. **Git 2.30 以上**,且要操作的專案必須是 Git repository。若要使用「Approve & Push」,推送認證(SSH key 或 credential helper)需事先設定好。
|
|
43
|
-
3. **tmux**(建議;macOS 用 `brew install tmux`)。沒有時會自動改用 node-pty,並在 `vibeflow doctor` 裡提示。
|
|
44
|
-
4. **claude 或 codex CLI 至少一個,已登入**:
|
|
45
|
-
```bash
|
|
46
|
-
npm install -g @anthropic-ai/claude-code # 或官方 installer:curl -fsSL https://claude.ai/install.sh | bash
|
|
47
|
-
```
|
|
48
|
-
5. **Windows**:需要 Git for Windows 的 Git Bash(agent 的啟動指令是 POSIX sh)。
|
|
59
|
+
有問題時先跑:
|
|
49
60
|
|
|
50
|
-
|
|
61
|
+
```bash
|
|
62
|
+
vibeflow doctor
|
|
63
|
+
```
|
|
51
64
|
|
|
52
|
-
|
|
65
|
+
它會逐項檢查 Node、Git、tmux、終端機模組與 agent CLI,並列出修正指令。
|
|
53
66
|
|
|
54
|
-
|
|
67
|
+
---
|
|
55
68
|
|
|
56
|
-
|
|
57
|
-
- 必須帶每次啟動時產生的 token 才能進入。`vibeflow` 開啟的網址會帶上 token,載入後換成 HttpOnly、SameSite=Strict 的 cookie,並從網址列移除。
|
|
58
|
-
- WebSocket 握手會同時檢查 cookie 與 `Origin`,其他網頁無法從你的瀏覽器連進來。
|
|
59
|
-
- `Host` 標頭必須是 loopback,用來防範 DNS rebinding。
|
|
60
|
-
- 鎖檔權限為 0600。
|
|
61
|
-
- API 只接受 core 認得的 task id,不接受任意路徑或指令。
|
|
69
|
+
## 安裝方式
|
|
62
70
|
|
|
63
|
-
|
|
71
|
+
| 方式 | 指令 | 適合 |
|
|
72
|
+
|---|---|---|
|
|
73
|
+
| **全域安裝(建議)** | `npm i -g @kw-yeh/vibeflow@latest`,之後執行 `vibeflow` | 大多數人 |
|
|
74
|
+
| 免安裝試用 | `npx @kw-yeh/vibeflow` | 只想先看看、不想安裝 |
|
|
75
|
+
| 從原始碼一鍵啟動 | clone 後雙擊 `start.command`(macOS/Linux)或 `start.cmd`(Windows) | 想用最新的 `main`,或要改程式 |
|
|
64
76
|
|
|
65
|
-
|
|
77
|
+
三種方式讀寫的是同一份看板,可以隨時換。
|
|
66
78
|
|
|
67
|
-
|
|
68
|
-
2. `npm pack` 後以全域安裝方式驗證能啟動,再執行 `npm publish --provenance`(需要 `NPM_TOKEN` secret)。
|
|
79
|
+
之後要更新到最新版,再執行一次同一行安裝指令即可:
|
|
69
80
|
|
|
70
81
|
```bash
|
|
71
|
-
|
|
72
|
-
# 2. 上 tag 並推送
|
|
73
|
-
git tag v4.0.0
|
|
74
|
-
git push origin v4.0.0
|
|
82
|
+
npm i -g @kw-yeh/vibeflow@latest
|
|
75
83
|
```
|
|
76
84
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
## 📂 專案資料結構與 Worktree 隔離設計
|
|
85
|
+
### 安裝時出現 `EACCES: permission denied`
|
|
80
86
|
|
|
81
|
-
|
|
87
|
+
代表 npm 的全域目錄屬於系統管理員(從 nodejs.org 下載安裝檔裝 Node 時常見)。建議不要用 `sudo`,改成讓全域套件裝在你自己的家目錄:
|
|
82
88
|
|
|
89
|
+
```bash
|
|
90
|
+
mkdir -p ~/.npm-global
|
|
91
|
+
npm config set prefix ~/.npm-global
|
|
92
|
+
echo 'export PATH="$HOME/.npm-global/bin:$PATH"' >> ~/.zshrc
|
|
93
|
+
source ~/.zshrc
|
|
94
|
+
npm i -g @kw-yeh/vibeflow@latest
|
|
83
95
|
```
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
96
|
+
|
|
97
|
+
用 Homebrew(`brew install node`)或 [nvm](https://github.com/nvm-sh/nvm) 裝的 Node 本來就不需要 `sudo`。已經用 `sudo` 裝好也能正常使用;若 `vibeflow doctor` 回報終端機模組沒有執行權限,照它列出的 `sudo chmod +x …` 指令執行一次即可。
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## 常用指令
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
vibeflow # 啟動(或連到已在執行的)VibeFlow,開啟 Web UI
|
|
105
|
+
vibeflow tui # 終端機介面,和 Web UI 操作同一個看板
|
|
106
|
+
vibeflow status # 目前的 host、執行中的 session、看板摘要
|
|
107
|
+
vibeflow stop <id> | --all # 停止某張卡(或全部)的 agent
|
|
108
|
+
vibeflow shutdown # 關閉 VibeFlow(tmux 裡的 agent 會繼續執行)
|
|
109
|
+
vibeflow open <path> # 把專案資料夾加進最近使用清單並開啟 Web UI
|
|
110
|
+
vibeflow doctor # 檢查前置需求
|
|
111
|
+
vibeflow task create … # 不開 UI 直接建卡,選項見 vibeflow task --help
|
|
90
112
|
```
|
|
91
113
|
|
|
92
|
-
|
|
114
|
+
沒有全域安裝、改用 `npx` 時,把 `vibeflow` 換成 `npx @kw-yeh/vibeflow`。
|
|
93
115
|
|
|
94
|
-
|
|
116
|
+
---
|
|
95
117
|
|
|
96
|
-
|
|
97
|
-
* **分支策略**: 若有 Remote,彈窗讓使用者選擇基準分支(Base Branch)。
|
|
98
|
-
* **背景準備**:
|
|
99
|
-
1. 自動將 `.vibeflow/` 寫入 `.gitignore`。
|
|
100
|
-
2. 執行 `git worktree add -b vf-[id] .vibeflow/vf-[id] origin/[選定分支]`。
|
|
101
|
-
3. 執行 `git push -u origin vf-[id]` 將工作分支同步至雲端。
|
|
118
|
+
## 運作方式
|
|
102
119
|
|
|
103
|
-
|
|
120
|
+
**檔案放在哪裡**
|
|
104
121
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
* **多工並行**: 支援同時啟動多張卡片,每張卡片擁有獨立的 PTY 進程與 Worktree 環境,互不干擾。
|
|
122
|
+
- 每張卡的 worktree 建在「工作站資料夾」底下:`<工作站>/<專案名>/<分支名>`。工作站預設是 `~/Desktop`,可在 **設定** 裡改。
|
|
123
|
+
- 你的專案資料夾本身不會被切換分支,也不會多出 worktree。
|
|
124
|
+
- 專案有 remote 時,新分支會在建卡時 push 到 origin;有設 CI 的話可能會被觸發。
|
|
125
|
+
- 看板資料存在 `~/Library/Application Support/vibeflow/`(macOS)、`%APPDATA%\vibeflow\`(Windows)或 `~/.config/vibeflow/`(Linux)。
|
|
110
126
|
|
|
111
|
-
|
|
127
|
+
**同一台電腦只有一個 VibeFlow**
|
|
112
128
|
|
|
113
|
-
|
|
114
|
-
* **一鍵合併**: 使用者點擊 Approve 後,App 在 Worktree 執行 `git commit` 與 `git push`。
|
|
115
|
-
* **自動清理**: 卡片移至 `Done` 後,App 自動執行 `git worktree remove`,徹底刪除 `.vibeflow/` 下的暫存資料夾,保持硬碟整潔。
|
|
129
|
+
再次執行 `vibeflow` 或 `vibeflow tui` 時,會連到已在執行的那一個,不會開出第二份。
|
|
116
130
|
|
|
117
|
-
|
|
131
|
+
**本機伺服器的安全性**
|
|
118
132
|
|
|
119
|
-
|
|
133
|
+
VibeFlow 的本機伺服器能啟動 agent、寫入終端機,因此:
|
|
120
134
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
135
|
+
- 只綁定 `127.0.0.1`/`::1`,使用隨機 port。
|
|
136
|
+
- 每次啟動產生一組 token,網址帶上它才能進入;載入後換成 HttpOnly、SameSite=Strict 的 cookie,並從網址列移除。
|
|
137
|
+
- WebSocket 連線同時檢查 cookie 與 `Origin`,`Host` 必須是 loopback,其他網頁無法從你的瀏覽器連進來。
|
|
138
|
+
- API 只接受 VibeFlow 認得的卡片 id,不接受任意路徑或指令。
|
|
124
139
|
|
|
125
|
-
|
|
140
|
+
---
|
|
126
141
|
|
|
127
|
-
|
|
128
|
-
* [x] 實作自動建立 Worktree 與分支推送的後端邏輯。
|
|
129
|
-
* [x] 確保 `.vibeflow/` 資料夾被正確忽略。
|
|
142
|
+
## 參與開發
|
|
130
143
|
|
|
131
|
-
|
|
144
|
+
```bash
|
|
145
|
+
git clone https://github.com/KW-Yeh/VibeFlow.git
|
|
146
|
+
cd VibeFlow
|
|
147
|
+
./start.command # 或:npm install && npm start
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
架構、慣例、測試指令與完成標準都在 [AGENTS.md](AGENTS.md)。
|
|
132
151
|
|
|
133
|
-
|
|
134
|
-
* [x] 前端整合 `xterm.js`,達成雙向串流(輸出顯示 + 鍵盤輸入)。
|
|
135
|
-
* [x] 實作多卡片並行的 PTY 進程管理。
|
|
152
|
+
### 發佈新版本(Maintainers)
|
|
136
153
|
|
|
137
|
-
|
|
154
|
+
推送 `v*` tag 會觸發 [CI](.github/workflows/release.yml):在 Ubuntu、macOS、Windows 上跑 typecheck、測試、端對端測試與 `vibeflow doctor`,打包後實際安裝驗證,再以 npm Trusted Publishing(OIDC,不需要 token)發佈 `@kw-yeh/vibeflow`。
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
npm version <x.y.z> -m "chore: release v%s"
|
|
158
|
+
git push origin main --follow-tags
|
|
159
|
+
```
|
|
138
160
|
|
|
139
|
-
|
|
140
|
-
* [x] 實作 Approve 後的自動提交與 Worktree 清理機制。
|
|
161
|
+
本地驗證打包:`npm run build:npm && npm pack ./dist-npm`。
|
|
141
162
|
|
|
142
|
-
##
|
|
163
|
+
## License
|
|
143
164
|
|
|
144
|
-
|
|
145
|
-
2. **互動處理**: 確保 `xterm.js` 的輸入能即時傳回 PTY,這對於 Claude Code 的互動式提問(Type A)至關重要。
|
|
146
|
-
3. **環境變數**: core 呼叫 `claude` 時需手動注入使用者的 `PATH`(`packages/core/src/env.ts`),否則會找不到指令。
|
|
165
|
+
[MIT](LICENSE)
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { createRequire as __vfCreateRequire } from 'node:module';
|
|
2
|
+
const require = __vfCreateRequire(import.meta.url);
|
|
3
|
+
|
|
4
|
+
// packages/core/src/pty-helper.ts
|
|
5
|
+
import fs from "fs";
|
|
6
|
+
import path from "path";
|
|
7
|
+
import { createRequire } from "module";
|
|
8
|
+
function nodePtyRoot() {
|
|
9
|
+
try {
|
|
10
|
+
return path.dirname(createRequire(import.meta.url).resolve("node-pty/package.json"));
|
|
11
|
+
} catch {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
function ensurePtySpawnHelper(root = nodePtyRoot()) {
|
|
16
|
+
if (process.platform === "win32" || !root) return [];
|
|
17
|
+
const candidates = [
|
|
18
|
+
path.join(root, "build", "Release", "spawn-helper"),
|
|
19
|
+
path.join(root, "prebuilds", `${process.platform}-${process.arch}`, "spawn-helper")
|
|
20
|
+
];
|
|
21
|
+
const failures = [];
|
|
22
|
+
for (const file of candidates) {
|
|
23
|
+
let stat;
|
|
24
|
+
try {
|
|
25
|
+
stat = fs.statSync(file);
|
|
26
|
+
} catch {
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
try {
|
|
30
|
+
fs.accessSync(file, fs.constants.X_OK);
|
|
31
|
+
continue;
|
|
32
|
+
} catch {
|
|
33
|
+
}
|
|
34
|
+
try {
|
|
35
|
+
fs.chmodSync(file, stat.mode & 4095 | 73);
|
|
36
|
+
} catch (err) {
|
|
37
|
+
const uid = process.getuid?.();
|
|
38
|
+
failures.push({ path: file, error: err.message, ownedByOther: uid !== void 0 && stat.uid !== uid });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return failures;
|
|
42
|
+
}
|
|
43
|
+
function spawnHelperFixCommand(failures) {
|
|
44
|
+
const sudo = failures.some((f) => f.ownedByOther) ? "sudo " : "";
|
|
45
|
+
return `${sudo}chmod +x ${failures.map((f) => `"${f.path}"`).join(" ")}`;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// packages/cli/src/postinstall.ts
|
|
49
|
+
try {
|
|
50
|
+
const failures = ensurePtySpawnHelper();
|
|
51
|
+
if (failures.length > 0) {
|
|
52
|
+
console.warn(`[vibeflow] node-pty spawn-helper \u7121\u6CD5\u8A2D\u70BA\u53EF\u57F7\u884C\uFF0C\u7D42\u7AEF\u6A5F\u6703\u7121\u6CD5\u555F\u52D5\u3002\u8ACB\u57F7\u884C\uFF1A
|
|
53
|
+
${spawnHelperFixCommand(failures)}`);
|
|
54
|
+
}
|
|
55
|
+
} catch (err) {
|
|
56
|
+
console.warn(`[vibeflow] postinstall \u7565\u904E\uFF1A${err.message}`);
|
|
57
|
+
}
|
package/dist/vibeflow.mjs
CHANGED
|
@@ -1899,9 +1899,9 @@ function ensurePtySpawnHelper(root = nodePtyRoot()) {
|
|
|
1899
1899
|
];
|
|
1900
1900
|
const failures = [];
|
|
1901
1901
|
for (const file of candidates) {
|
|
1902
|
-
let
|
|
1902
|
+
let stat;
|
|
1903
1903
|
try {
|
|
1904
|
-
|
|
1904
|
+
stat = fs4.statSync(file);
|
|
1905
1905
|
} catch {
|
|
1906
1906
|
continue;
|
|
1907
1907
|
}
|
|
@@ -1911,13 +1911,18 @@ function ensurePtySpawnHelper(root = nodePtyRoot()) {
|
|
|
1911
1911
|
} catch {
|
|
1912
1912
|
}
|
|
1913
1913
|
try {
|
|
1914
|
-
fs4.chmodSync(file, mode & 4095 | 73);
|
|
1914
|
+
fs4.chmodSync(file, stat.mode & 4095 | 73);
|
|
1915
1915
|
} catch (err) {
|
|
1916
|
-
|
|
1916
|
+
const uid = process.getuid?.();
|
|
1917
|
+
failures.push({ path: file, error: err.message, ownedByOther: uid !== void 0 && stat.uid !== uid });
|
|
1917
1918
|
}
|
|
1918
1919
|
}
|
|
1919
1920
|
return failures;
|
|
1920
1921
|
}
|
|
1922
|
+
function spawnHelperFixCommand(failures) {
|
|
1923
|
+
const sudo = failures.some((f) => f.ownedByOther) ? "sudo " : "";
|
|
1924
|
+
return `${sudo}chmod +x ${failures.map((f) => `"${f.path}"`).join(" ")}`;
|
|
1925
|
+
}
|
|
1921
1926
|
|
|
1922
1927
|
// packages/cli/src/task-command.ts
|
|
1923
1928
|
import { parseArgs } from "node:util";
|
|
@@ -5641,8 +5646,8 @@ async function checkNodePty() {
|
|
|
5641
5646
|
id: "node-pty",
|
|
5642
5647
|
name: "node-pty",
|
|
5643
5648
|
level: "fail",
|
|
5644
|
-
detail: `spawn-helper \u6C92\u6709\u57F7\u884C\u6B0A\u9650\uFF1A${unrepaired[0].error}`,
|
|
5645
|
-
fix: unrepaired
|
|
5649
|
+
detail: unrepaired.some((f) => f.ownedByOther) ? "spawn-helper \u6C92\u6709\u57F7\u884C\u6B0A\u9650\uFF0C\u800C\u4E14\u6A94\u6848\u5C6C\u65BC\u5176\u4ED6\u4F7F\u7528\u8005\uFF08\u901A\u5E38\u662F\u7528 sudo \u5168\u57DF\u5B89\u88DD\uFF09\uFF0CVibeFlow \u7121\u6CD5\u81EA\u884C\u4FEE\u6B63" : `spawn-helper \u6C92\u6709\u57F7\u884C\u6B0A\u9650\uFF1A${unrepaired[0].error}`,
|
|
5650
|
+
fix: spawnHelperFixCommand(unrepaired)
|
|
5646
5651
|
};
|
|
5647
5652
|
}
|
|
5648
5653
|
try {
|
package/dist/web/404/index.html
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
<!DOCTYPE html><html><head><meta charSet="utf-8" data-next-head=""/><meta name="viewport" content="width=device-width" data-next-head=""/><link rel="icon" href="/favicon.ico" sizes="any" data-next-head=""/><link rel="icon" href="/logo.svg" type="image/svg+xml" data-next-head=""/><link rel="apple-touch-icon" href="/apple-touch-icon.png" data-next-head=""/><title data-next-head="">404: This page could not be found</title><link rel="preload" href="/_next/static/css/edcc6abb24dfd492.css" as="style"/><link rel="stylesheet" href="/_next/static/css/edcc6abb24dfd492.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" noModule="" src="/_next/static/chunks/polyfills-42372ed130431b0a.js"></script><script src="/_next/static/chunks/webpack-c8aa5df0425f6b7b.js" defer=""></script><script src="/_next/static/chunks/framework-b92a367cf1ad4bf7.js" defer=""></script><script src="/_next/static/chunks/main-ec7fd4c371d06729.js" defer=""></script><script src="/_next/static/chunks/pages/_app-320afeed07d86516.js" defer=""></script><script src="/_next/static/chunks/pages/_error-8f65b0f8749f42d2.js" defer=""></script><script src="/_next/static
|
|
1
|
+
<!DOCTYPE html><html><head><meta charSet="utf-8" data-next-head=""/><meta name="viewport" content="width=device-width" data-next-head=""/><link rel="icon" href="/favicon.ico" sizes="any" data-next-head=""/><link rel="icon" href="/logo.svg" type="image/svg+xml" data-next-head=""/><link rel="apple-touch-icon" href="/apple-touch-icon.png" data-next-head=""/><title data-next-head="">404: This page could not be found</title><link rel="preload" href="/_next/static/css/edcc6abb24dfd492.css" as="style"/><link rel="stylesheet" href="/_next/static/css/edcc6abb24dfd492.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" noModule="" src="/_next/static/chunks/polyfills-42372ed130431b0a.js"></script><script src="/_next/static/chunks/webpack-c8aa5df0425f6b7b.js" defer=""></script><script src="/_next/static/chunks/framework-b92a367cf1ad4bf7.js" defer=""></script><script src="/_next/static/chunks/main-ec7fd4c371d06729.js" defer=""></script><script src="/_next/static/chunks/pages/_app-320afeed07d86516.js" defer=""></script><script src="/_next/static/chunks/pages/_error-8f65b0f8749f42d2.js" defer=""></script><script src="/_next/static/0iT_99y5BhZs3U_2l_mSN/_buildManifest.js" defer=""></script><script src="/_next/static/0iT_99y5BhZs3U_2l_mSN/_ssgManifest.js" defer=""></script></head><body><div id="__next"><div style="font-family:system-ui,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div style="line-height:48px"><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding-right:23px;font-size:24px;font-weight:500;vertical-align:top">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:28px">This page could not be found<!-- -->.</h2></div></div></div></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{"statusCode":404}},"page":"/_error","query":{},"buildId":"0iT_99y5BhZs3U_2l_mSN","nextExport":true,"isFallback":false,"gip":true,"scriptLoader":[]}</script></body></html>
|
package/dist/web/404.html
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
<!DOCTYPE html><html><head><meta charSet="utf-8" data-next-head=""/><meta name="viewport" content="width=device-width" data-next-head=""/><link rel="icon" href="/favicon.ico" sizes="any" data-next-head=""/><link rel="icon" href="/logo.svg" type="image/svg+xml" data-next-head=""/><link rel="apple-touch-icon" href="/apple-touch-icon.png" data-next-head=""/><title data-next-head="">404: This page could not be found</title><link rel="preload" href="/_next/static/css/edcc6abb24dfd492.css" as="style"/><link rel="stylesheet" href="/_next/static/css/edcc6abb24dfd492.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" noModule="" src="/_next/static/chunks/polyfills-42372ed130431b0a.js"></script><script src="/_next/static/chunks/webpack-c8aa5df0425f6b7b.js" defer=""></script><script src="/_next/static/chunks/framework-b92a367cf1ad4bf7.js" defer=""></script><script src="/_next/static/chunks/main-ec7fd4c371d06729.js" defer=""></script><script src="/_next/static/chunks/pages/_app-320afeed07d86516.js" defer=""></script><script src="/_next/static/chunks/pages/_error-8f65b0f8749f42d2.js" defer=""></script><script src="/_next/static
|
|
1
|
+
<!DOCTYPE html><html><head><meta charSet="utf-8" data-next-head=""/><meta name="viewport" content="width=device-width" data-next-head=""/><link rel="icon" href="/favicon.ico" sizes="any" data-next-head=""/><link rel="icon" href="/logo.svg" type="image/svg+xml" data-next-head=""/><link rel="apple-touch-icon" href="/apple-touch-icon.png" data-next-head=""/><title data-next-head="">404: This page could not be found</title><link rel="preload" href="/_next/static/css/edcc6abb24dfd492.css" as="style"/><link rel="stylesheet" href="/_next/static/css/edcc6abb24dfd492.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" noModule="" src="/_next/static/chunks/polyfills-42372ed130431b0a.js"></script><script src="/_next/static/chunks/webpack-c8aa5df0425f6b7b.js" defer=""></script><script src="/_next/static/chunks/framework-b92a367cf1ad4bf7.js" defer=""></script><script src="/_next/static/chunks/main-ec7fd4c371d06729.js" defer=""></script><script src="/_next/static/chunks/pages/_app-320afeed07d86516.js" defer=""></script><script src="/_next/static/chunks/pages/_error-8f65b0f8749f42d2.js" defer=""></script><script src="/_next/static/0iT_99y5BhZs3U_2l_mSN/_buildManifest.js" defer=""></script><script src="/_next/static/0iT_99y5BhZs3U_2l_mSN/_ssgManifest.js" defer=""></script></head><body><div id="__next"><div style="font-family:system-ui,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div style="line-height:48px"><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding-right:23px;font-size:24px;font-weight:500;vertical-align:top">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:28px">This page could not be found<!-- -->.</h2></div></div></div></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{"statusCode":404}},"page":"/_error","query":{},"buildId":"0iT_99y5BhZs3U_2l_mSN","nextExport":true,"isFallback":false,"gip":true,"scriptLoader":[]}</script></body></html>
|
package/dist/web/home/index.html
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
<!DOCTYPE html><html><head><meta charSet="utf-8" data-next-head=""/><meta name="viewport" content="width=device-width" data-next-head=""/><link rel="icon" href="/favicon.ico" sizes="any" data-next-head=""/><link rel="icon" href="/logo.svg" type="image/svg+xml" data-next-head=""/><link rel="apple-touch-icon" href="/apple-touch-icon.png" data-next-head=""/><title data-next-head="">VibeFlow</title><link rel="preload" href="/_next/static/css/edcc6abb24dfd492.css" as="style"/><link rel="stylesheet" href="/_next/static/css/edcc6abb24dfd492.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" noModule="" src="/_next/static/chunks/polyfills-42372ed130431b0a.js"></script><script src="/_next/static/chunks/webpack-c8aa5df0425f6b7b.js" defer=""></script><script src="/_next/static/chunks/framework-b92a367cf1ad4bf7.js" defer=""></script><script src="/_next/static/chunks/main-ec7fd4c371d06729.js" defer=""></script><script src="/_next/static/chunks/pages/_app-320afeed07d86516.js" defer=""></script><script src="/_next/static/chunks/4270-6c9c75303137e3a5.js" defer=""></script><script src="/_next/static/chunks/pages/home-efefddd4b88b018d.js" defer=""></script><script src="/_next/static
|
|
1
|
+
<!DOCTYPE html><html><head><meta charSet="utf-8" data-next-head=""/><meta name="viewport" content="width=device-width" data-next-head=""/><link rel="icon" href="/favicon.ico" sizes="any" data-next-head=""/><link rel="icon" href="/logo.svg" type="image/svg+xml" data-next-head=""/><link rel="apple-touch-icon" href="/apple-touch-icon.png" data-next-head=""/><title data-next-head="">VibeFlow</title><link rel="preload" href="/_next/static/css/edcc6abb24dfd492.css" as="style"/><link rel="stylesheet" href="/_next/static/css/edcc6abb24dfd492.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" noModule="" src="/_next/static/chunks/polyfills-42372ed130431b0a.js"></script><script src="/_next/static/chunks/webpack-c8aa5df0425f6b7b.js" defer=""></script><script src="/_next/static/chunks/framework-b92a367cf1ad4bf7.js" defer=""></script><script src="/_next/static/chunks/main-ec7fd4c371d06729.js" defer=""></script><script src="/_next/static/chunks/pages/_app-320afeed07d86516.js" defer=""></script><script src="/_next/static/chunks/4270-6c9c75303137e3a5.js" defer=""></script><script src="/_next/static/chunks/pages/home-efefddd4b88b018d.js" defer=""></script><script src="/_next/static/0iT_99y5BhZs3U_2l_mSN/_buildManifest.js" defer=""></script><script src="/_next/static/0iT_99y5BhZs3U_2l_mSN/_ssgManifest.js" defer=""></script></head><body><div id="__next"><div class="bg-background text-foreground"><div class="flex min-h-screen items-center justify-center bg-background text-base text-muted-foreground">載入中…</div></div></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/home","query":{},"buildId":"0iT_99y5BhZs3U_2l_mSN","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kw-yeh/vibeflow",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.3",
|
|
4
4
|
"description": "Intent-driven local kanban for coding agents: git worktree per card, Web UI and TUI.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "KW-Yeh",
|
|
@@ -8,6 +8,9 @@
|
|
|
8
8
|
"bin": {
|
|
9
9
|
"vibeflow": "dist/vibeflow.mjs"
|
|
10
10
|
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"postinstall": "node dist/postinstall.mjs"
|
|
13
|
+
},
|
|
11
14
|
"files": [
|
|
12
15
|
"dist",
|
|
13
16
|
"README.md",
|
/package/dist/web/_next/static/{-9MMnQDtlhk8JcEq6dTBS → 0iT_99y5BhZs3U_2l_mSN}/_buildManifest.js
RENAMED
|
File without changes
|
/package/dist/web/_next/static/{-9MMnQDtlhk8JcEq6dTBS → 0iT_99y5BhZs3U_2l_mSN}/_ssgManifest.js
RENAMED
|
File without changes
|