@kw-yeh/vibeflow 4.11.9 → 4.11.12

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/vibeflow.mjs CHANGED
@@ -2373,6 +2373,7 @@ function migrateStore(store) {
2373
2373
  if (!store.has("recentProjects")) {
2374
2374
  store.set("recentProjects", recentProjectsFromBoard(store.get("board")));
2375
2375
  }
2376
+ if (!store.has("terminals")) store.set("terminals", []);
2376
2377
  const settings = store.get("settings");
2377
2378
  if (settings && "agentConnections" in settings) {
2378
2379
  const { agentConnections: _dropped, ...rest } = settings;
@@ -2390,9 +2391,25 @@ function getState() {
2390
2391
  board: store.get("board"),
2391
2392
  // `settings` may be absent in state persisted before this field existed;
2392
2393
  // fall back to defaults so the renderer always receives a value.
2393
- settings: store.get("settings") ?? DEFAULT_SETTINGS
2394
+ settings: store.get("settings") ?? DEFAULT_SETTINGS,
2395
+ terminals: store.get("terminals") ?? []
2394
2396
  };
2395
2397
  }
2398
+ function listTerminals() {
2399
+ return getStore().get("terminals") ?? [];
2400
+ }
2401
+ function saveTerminal(entry) {
2402
+ const current = listTerminals();
2403
+ const index = current.findIndex((t) => t.sessionKey === entry.sessionKey);
2404
+ getStore().set("terminals", index === -1 ? [...current, entry] : current.map((t, i) => i === index ? entry : t));
2405
+ }
2406
+ function removeTerminals(sessionKeys) {
2407
+ const removing = new Set(sessionKeys);
2408
+ const current = listTerminals();
2409
+ if (current.some((t) => removing.has(t.sessionKey))) {
2410
+ getStore().set("terminals", current.filter((t) => !removing.has(t.sessionKey)));
2411
+ }
2412
+ }
2396
2413
  function getSettings() {
2397
2414
  return getStore().get("settings") ?? DEFAULT_SETTINGS;
2398
2415
  }
@@ -2584,6 +2601,8 @@ function createBridge(t) {
2584
2601
  */
2585
2602
  start: (payload) => t.invoke("pty:start", payload),
2586
2603
  startStandalone: (payload) => t.invoke("terminal:start", payload),
2604
+ /** Rename a 終端機-page shell; a blank title is ignored. */
2605
+ renameStandalone: (sessionKey, title) => t.invoke("terminal:rename", { sessionKey, title }),
2587
2606
  /** Join a running session without restarting it. */
2588
2607
  peek: (sessionKey) => t.invoke("pty:peek", sessionKey),
2589
2608
  /** Which session backend runs terminals, and the sessions it has running. */
@@ -6910,6 +6929,7 @@ function createProgressTracker(opts) {
6910
6929
  var InvalidRequestError = class extends Error {
6911
6930
  code = "INVALID_REQUEST";
6912
6931
  };
6932
+ var STANDALONE_KEY = /^terminal_[0-9a-f-]{36}$/;
6913
6933
  function invalid(message) {
6914
6934
  throw new InvalidRequestError(message);
6915
6935
  }
@@ -7018,12 +7038,18 @@ function createCore({ sessions, bus, version, homeDir, ghRunner, githubAuthStatu
7018
7038
  } catch {
7019
7039
  }
7020
7040
  async function teardownSession(key) {
7021
- const standalone = standaloneTerminals.has(key);
7041
+ const standalone = isStandaloneKey(key);
7022
7042
  await sessions.kill(key);
7023
- if (standalone) sessions.discardScrollback?.(key);
7043
+ if (standalone) {
7044
+ sessions.discardScrollback?.(key);
7045
+ removeTerminals([key]);
7046
+ }
7024
7047
  standaloneTerminals.delete(key);
7025
7048
  unwatchSubAgents(key);
7026
7049
  }
7050
+ function isStandaloneKey(key) {
7051
+ return standaloneTerminals.has(key) || listTerminals().some((t) => t.sessionKey === key);
7052
+ }
7027
7053
  async function teardownTask(taskId) {
7028
7054
  const keys = /* @__PURE__ */ new Set([taskId, ...(await sessions.list()).filter((k) => k.startsWith(`${taskId}:`))]);
7029
7055
  await Promise.all(Array.from(keys, (k) => teardownSession(k)));
@@ -7036,7 +7062,7 @@ function createCore({ sessions, bus, version, homeDir, ghRunner, githubAuthStatu
7036
7062
  }
7037
7063
  function requireSessionKey(sessionKey) {
7038
7064
  const key = str(sessionKey, "sessionKey");
7039
- if (standaloneTerminals.has(key)) return key;
7065
+ if (isStandaloneKey(key)) return key;
7040
7066
  requireTask(key.split(":")[0]);
7041
7067
  return key;
7042
7068
  }
@@ -7406,30 +7432,47 @@ function createCore({ sessions, bus, version, homeDir, ghRunner, githubAuthStatu
7406
7432
  "terminal:start": async (payload) => {
7407
7433
  const p = obj(payload, "payload");
7408
7434
  const key = str(p.sessionKey, "sessionKey");
7409
- if (!/^terminal_[0-9a-f-]{36}$/.test(key)) invalid("invalid standalone terminal key");
7435
+ if (!STANDALONE_KEY.test(key)) invalid("invalid standalone terminal key");
7410
7436
  if (Boolean(p.taskId) === Boolean(p.projectPath)) invalid("provide taskId or projectPath");
7437
+ const saved = listTerminals().find((t) => t.sessionKey === key);
7438
+ if (saved && (saved.taskId ? saved.taskId !== p.taskId : saved.projectPath !== p.projectPath)) {
7439
+ invalid("terminal key already belongs to another directory");
7440
+ }
7411
7441
  let cwd;
7442
+ let projectPath;
7412
7443
  if (p.taskId) {
7413
7444
  const requested = requireTask(p.taskId);
7414
7445
  const column = columnOf(requested.id);
7415
7446
  const task = column === "in_progress" && !requested.worktreePath ? await ensureProvisioned(requested) : requested;
7416
7447
  cwd = str(column === "backlog" ? task.projectPath : task.worktreePath ?? task.projectPath, "directory");
7448
+ projectPath = task.projectPath ?? cwd;
7417
7449
  } else {
7418
7450
  cwd = str(p.projectPath, "projectPath");
7451
+ projectPath = cwd;
7419
7452
  }
7420
7453
  if (!path23.isAbsolute(cwd) || !fs19.existsSync(cwd) || !fs19.statSync(cwd).isDirectory()) {
7421
7454
  invalid("terminal directory must be an existing absolute directory");
7422
7455
  }
7423
- const previous = standaloneTerminals.get(key);
7424
- if (previous && previous !== cwd) invalid("terminal key already belongs to another directory");
7425
- const result = await sessions.start(key, {
7426
- cwd,
7427
- cols: typeof p.cols === "number" ? p.cols : void 0,
7428
- rows: typeof p.rows === "number" ? p.rows : void 0
7429
- });
7456
+ const title = (typeof p.title === "string" ? p.title.trim() : "") || saved?.title || path23.basename(projectPath);
7457
+ saveTerminal({ sessionKey: key, title, projectPath, ...p.taskId ? { taskId: p.taskId } : {} });
7430
7458
  standaloneTerminals.set(key, cwd);
7431
7459
  if (!p.taskId) recordRecentProject(getStore(), cwd);
7432
- return result;
7460
+ const cols = typeof p.cols === "number" ? p.cols : void 0;
7461
+ const rows = typeof p.rows === "number" ? p.rows : void 0;
7462
+ if (sessions.kind === "pty" && await sessions.isAlive(key)) {
7463
+ if (cols && rows) sessions.resize(key, cols, rows);
7464
+ return { pid: 0, scrollback: sessions.scrollback(key), attached: true };
7465
+ }
7466
+ return sessions.start(key, { cwd, cols, rows });
7467
+ },
7468
+ "terminal:rename": (payload) => {
7469
+ const p = obj(payload, "payload");
7470
+ const key = str(p.sessionKey, "sessionKey");
7471
+ const saved = listTerminals().find((t) => t.sessionKey === key);
7472
+ if (!saved) invalid("unknown standalone terminal");
7473
+ const title = str(p.title, "title").trim();
7474
+ if (title && title !== saved.title) saveTerminal({ ...saved, title });
7475
+ return getState();
7433
7476
  },
7434
7477
  // Join a session as it is: no restart, for a frontend that attaches
7435
7478
  // after it started (the TUI's terminal view).
@@ -7446,7 +7489,11 @@ function createCore({ sessions, bus, version, homeDir, ghRunner, githubAuthStatu
7446
7489
  if (typeof p.cols !== "number" || typeof p.rows !== "number") invalid("cols/rows must be numbers");
7447
7490
  sessions.resize(requireSessionKey(p.sessionKey), p.cols, p.rows);
7448
7491
  },
7449
- "pty:kill": (sessionKey) => teardownSession(requireSessionKey(sessionKey)),
7492
+ // A pane closed before its listing reached the frontend still names a shell to end.
7493
+ "pty:kill": (sessionKey) => {
7494
+ const key = str(sessionKey, "sessionKey");
7495
+ return teardownSession(STANDALONE_KEY.test(key) ? key : requireSessionKey(key));
7496
+ },
7450
7497
  // History a frontend cannot scroll itself (tmux copy-mode).
7451
7498
  "pty:scrolled": (sessionKey) => sessions.isScrolledBack(requireSessionKey(sessionKey)),
7452
7499
  "pty:scroll-bottom": (sessionKey) => sessions.scrollToBottom(requireSessionKey(sessionKey)),
@@ -7630,6 +7677,7 @@ function createCore({ sessions, bus, version, homeDir, ghRunner, githubAuthStatu
7630
7677
  "vibeflow:deleteTask": async (taskId) => {
7631
7678
  const task = requireTask(taskId);
7632
7679
  await teardownTask(task.id);
7680
+ await Promise.all(listTerminals().filter((t) => t.taskId === task.id).map((t) => teardownSession(t.sessionKey)));
7633
7681
  progress.untrack(task.id);
7634
7682
  cancelChatSend(task.id);
7635
7683
  if (task.workspacePath) {
@@ -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/ac1238c212a3d10f.css" as="style"/><link rel="stylesheet" href="/_next/static/css/ac1238c212a3d10f.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-33344f7100190436.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-33cd991a71572ffc.js" defer=""></script><script src="/_next/static/chunks/pages/_error-8f65b0f8749f42d2.js" defer=""></script><script src="/_next/static/bLScLUyqbuPZ2hYp8Nd3L/_buildManifest.js" defer=""></script><script src="/_next/static/bLScLUyqbuPZ2hYp8Nd3L/_ssgManifest.js" defer=""></script></head><body><div id="__next"><div style="font-family:system-ui,&quot;Segoe UI&quot;,Roboto,Helvetica,Arial,sans-serif,&quot;Apple Color Emoji&quot;,&quot;Segoe UI Emoji&quot;;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":"bLScLUyqbuPZ2hYp8Nd3L","nextExport":true,"isFallback":false,"gip":true,"scriptLoader":[]}</script></body></html>
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/60e89d492b3b3ef3.css" as="style"/><link rel="stylesheet" href="/_next/static/css/60e89d492b3b3ef3.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-33344f7100190436.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-8cf225b59c19ec6a.js" defer=""></script><script src="/_next/static/chunks/pages/_error-8f65b0f8749f42d2.js" defer=""></script><script src="/_next/static/AN8aN7vmfuXjB7DfIABSV/_buildManifest.js" defer=""></script><script src="/_next/static/AN8aN7vmfuXjB7DfIABSV/_ssgManifest.js" defer=""></script></head><body><div id="__next"><div style="font-family:system-ui,&quot;Segoe UI&quot;,Roboto,Helvetica,Arial,sans-serif,&quot;Apple Color Emoji&quot;,&quot;Segoe UI Emoji&quot;;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":"AN8aN7vmfuXjB7DfIABSV","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/ac1238c212a3d10f.css" as="style"/><link rel="stylesheet" href="/_next/static/css/ac1238c212a3d10f.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-33344f7100190436.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-33cd991a71572ffc.js" defer=""></script><script src="/_next/static/chunks/pages/_error-8f65b0f8749f42d2.js" defer=""></script><script src="/_next/static/bLScLUyqbuPZ2hYp8Nd3L/_buildManifest.js" defer=""></script><script src="/_next/static/bLScLUyqbuPZ2hYp8Nd3L/_ssgManifest.js" defer=""></script></head><body><div id="__next"><div style="font-family:system-ui,&quot;Segoe UI&quot;,Roboto,Helvetica,Arial,sans-serif,&quot;Apple Color Emoji&quot;,&quot;Segoe UI Emoji&quot;;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":"bLScLUyqbuPZ2hYp8Nd3L","nextExport":true,"isFallback":false,"gip":true,"scriptLoader":[]}</script></body></html>
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/60e89d492b3b3ef3.css" as="style"/><link rel="stylesheet" href="/_next/static/css/60e89d492b3b3ef3.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-33344f7100190436.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-8cf225b59c19ec6a.js" defer=""></script><script src="/_next/static/chunks/pages/_error-8f65b0f8749f42d2.js" defer=""></script><script src="/_next/static/AN8aN7vmfuXjB7DfIABSV/_buildManifest.js" defer=""></script><script src="/_next/static/AN8aN7vmfuXjB7DfIABSV/_ssgManifest.js" defer=""></script></head><body><div id="__next"><div style="font-family:system-ui,&quot;Segoe UI&quot;,Roboto,Helvetica,Arial,sans-serif,&quot;Apple Color Emoji&quot;,&quot;Segoe UI Emoji&quot;;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":"AN8aN7vmfuXjB7DfIABSV","nextExport":true,"isFallback":false,"gip":true,"scriptLoader":[]}</script></body></html>
@@ -1 +1 @@
1
- self.__BUILD_MANIFEST={__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},__routerFilterStatic:{numItems:0,errorRate:1e-4,numBits:0,numHashes:null,bitArray:[]},__routerFilterDynamic:{numItems:0,errorRate:1e-4,numBits:0,numHashes:null,bitArray:[]},"/_error":["static/chunks/pages/_error-8f65b0f8749f42d2.js"],"/home":["static/chunks/6350-9e5cd43f220aab51.js","static/chunks/pages/home-b6c7635a054e4108.js"],sortedPages:["/_app","/_error","/home"]},self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB();
1
+ self.__BUILD_MANIFEST={__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},__routerFilterStatic:{numItems:0,errorRate:1e-4,numBits:0,numHashes:null,bitArray:[]},__routerFilterDynamic:{numItems:0,errorRate:1e-4,numBits:0,numHashes:null,bitArray:[]},"/_error":["static/chunks/pages/_error-8f65b0f8749f42d2.js"],"/home":["static/chunks/9296-f476f95a89709fef.js","static/chunks/pages/home-8abca1af986a976a.js"],sortedPages:["/_app","/_error","/home"]},self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB();