@sma1lboy/rove 0.9.108 → 0.9.147
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 +0 -1
- package/dist/cli/chunk-003tvywc.js +3 -0
- package/dist/cli/chunk-0m9j3yap.js +7 -0
- package/dist/cli/chunk-0r8333z3.js +3 -0
- package/dist/cli/chunk-0sm2k04y.js +3 -0
- package/dist/cli/chunk-0vmrteyg.js +3 -0
- package/dist/cli/chunk-0vy8351p.js +18 -0
- package/dist/cli/chunk-13s8rnk5.js +3 -0
- package/dist/cli/chunk-1kktfmtg.js +4 -0
- package/dist/cli/chunk-1rkb0j1j.js +3 -0
- package/dist/cli/chunk-1tx1s5v6.js +2 -0
- package/dist/cli/chunk-20pt9yqh.js +4 -0
- package/dist/cli/chunk-2brn8e1y.js +3 -0
- package/dist/cli/chunk-2fypr41w.js +3 -0
- package/dist/cli/chunk-2jxdzw4r.js +3 -0
- package/dist/cli/chunk-2pqqvse3.js +2 -0
- package/dist/cli/chunk-3bfm4hrs.js +3 -0
- package/dist/cli/chunk-3ry6prwn.js +3 -0
- package/dist/cli/chunk-3ztek08w.js +4 -0
- package/dist/cli/chunk-49s2zc0h.js +8 -0
- package/dist/cli/chunk-4wwx51m5.js +3 -0
- package/dist/cli/chunk-5bn91n19.js +3 -0
- package/dist/cli/chunk-5c3d1y0r.js +2 -0
- package/dist/cli/chunk-5hhvrvgm.js +8 -0
- package/dist/cli/chunk-6dn6h640.js +3 -0
- package/dist/cli/chunk-6frfschk.js +2 -0
- package/dist/cli/chunk-6rkc7efm.js +5 -0
- package/dist/cli/chunk-6xppe9bj.js +3 -0
- package/dist/cli/chunk-6zwg6me2.js +4 -0
- package/dist/cli/chunk-764bsyb0.js +1 -0
- package/dist/cli/chunk-79gqh5p2.js +5 -0
- package/dist/cli/chunk-7nhdvr5v.js +4 -0
- package/dist/cli/chunk-7q67dz4c.js +3 -0
- package/dist/cli/chunk-7ydwn358.js +3 -0
- package/dist/cli/chunk-86j25g7y.js +7 -0
- package/dist/cli/chunk-88qjhytd.js +12 -0
- package/dist/cli/chunk-8arm7k43.js +69 -0
- package/dist/cli/chunk-8ddjfc2v.js +4 -0
- package/dist/cli/chunk-8r1shxz0.js +16 -0
- package/dist/cli/chunk-99devyxr.js +2 -0
- package/dist/cli/chunk-9c1e5z6a.js +3 -0
- package/dist/cli/chunk-9n458sdy.js +2 -0
- package/dist/cli/chunk-aq912vvw.js +3 -0
- package/dist/cli/chunk-arf294te.js +2 -0
- package/dist/cli/chunk-awsawfrm.js +2 -0
- package/dist/cli/chunk-aynx3d2a.js +2 -0
- package/dist/cli/chunk-b99tf0jr.js +3 -0
- package/dist/cli/chunk-bdbgmjt7.js +3 -0
- package/dist/cli/chunk-c6mthex1.js +5 -0
- package/dist/cli/chunk-cb0pgyq1.js +8 -0
- package/dist/cli/chunk-cb2fpajx.js +3 -0
- package/dist/cli/chunk-cehhk94g.js +2 -0
- package/dist/cli/chunk-d4bqay6d.js +9 -0
- package/dist/cli/chunk-dcb59tsn.js +2 -0
- package/dist/cli/chunk-df7qe9y7.js +4 -0
- package/dist/cli/chunk-dkxhmj9k.js +25 -0
- package/dist/cli/chunk-dnb2bmtb.js +3 -0
- package/dist/cli/chunk-dqndd97s.js +7 -0
- package/dist/cli/chunk-dvcb6mk4.js +3 -0
- package/dist/cli/chunk-dw853n4w.js +3 -0
- package/dist/cli/chunk-dwsgeq06.js +15 -0
- package/dist/cli/chunk-e1g9mvww.js +11 -0
- package/dist/cli/chunk-e3ye4kmk.js +2 -0
- package/dist/cli/chunk-ef11h2am.js +3 -0
- package/dist/cli/chunk-ef39ym8f.js +3 -0
- package/dist/cli/chunk-ewdhz3dv.js +2 -0
- package/dist/cli/chunk-f6zsej8e.js +3 -0
- package/dist/cli/chunk-fe34e0w7.js +28 -0
- package/dist/cli/chunk-g1ybdgad.js +25 -0
- package/dist/cli/chunk-gbasmvsc.js +4 -0
- package/dist/cli/chunk-gjf604bb.js +3 -0
- package/dist/cli/chunk-gm3vj0fv.js +5 -0
- package/dist/cli/chunk-grh6dvfv.js +5 -0
- package/dist/cli/chunk-gwcneg6c.js +2 -0
- package/dist/cli/chunk-h5j8b87f.js +2 -0
- package/dist/cli/chunk-h79zfebh.js +7 -0
- package/dist/cli/chunk-h82kzdsn.js +3 -0
- package/dist/cli/chunk-hape5vwj.js +3 -0
- package/dist/cli/chunk-hg5x2wr0.js +3 -0
- package/dist/cli/chunk-hgq2gtxx.js +4 -0
- package/dist/cli/chunk-j4xfsn9g.js +5 -0
- package/dist/cli/chunk-j9g1m4dy.js +2 -0
- package/dist/cli/chunk-jdbfawrm.js +3 -0
- package/dist/cli/chunk-jsss3ze7.js +11 -0
- package/dist/cli/chunk-jvssy49v.js +2 -0
- package/dist/cli/chunk-jvxh93nz.js +3 -0
- package/dist/cli/chunk-jyv82gf0.js +258 -0
- package/dist/cli/chunk-k3ksts6g.js +3 -0
- package/dist/cli/chunk-kdrrw9tm.js +2 -0
- package/dist/cli/chunk-kg11c1py.js +3 -0
- package/dist/cli/chunk-kwe61yx7.js +3 -0
- package/dist/cli/chunk-mb5m7ex7.js +2 -0
- package/dist/cli/chunk-mfqjdpd8.js +2 -0
- package/dist/cli/chunk-mjvq39gf.js +4 -0
- package/dist/cli/chunk-mrwee8sj.js +3 -0
- package/dist/cli/chunk-my20q579.js +3 -0
- package/dist/cli/chunk-myfjt6dw.js +7 -0
- package/dist/cli/chunk-nceh1q3d.js +12 -0
- package/dist/cli/chunk-ncsgawg7.js +2 -0
- package/dist/cli/chunk-nm6adny4.js +4 -0
- package/dist/cli/chunk-np07kccr.js +4 -0
- package/dist/cli/chunk-p56s3ekm.js +3 -0
- package/dist/cli/chunk-p5spmf7e.js +2 -0
- package/dist/cli/chunk-p7kztgsd.js +4 -0
- package/dist/cli/chunk-pdh5w4ht.js +3 -0
- package/dist/cli/chunk-pdj8kqa1.js +74 -0
- package/dist/cli/chunk-psx9tk3x.js +4 -0
- package/dist/cli/chunk-pw6yfj10.js +3 -0
- package/dist/cli/chunk-q6579rbz.js +3 -0
- package/dist/cli/chunk-q7dr9eh6.js +3 -0
- package/dist/cli/chunk-q9x6d0k6.js +3 -0
- package/dist/cli/chunk-qkehg2c1.js +3 -0
- package/dist/cli/chunk-qtke4x42.js +3 -0
- package/dist/cli/chunk-rgcv1wcs.js +4 -0
- package/dist/cli/chunk-rxvbm4vt.js +7 -0
- package/dist/cli/chunk-ryhrw647.js +3 -0
- package/dist/cli/chunk-s76r56rj.js +3 -0
- package/dist/cli/chunk-sdyzxayr.js +3 -0
- package/dist/cli/chunk-svpn3av1.js +3 -0
- package/dist/cli/chunk-v5893dx3.js +2 -0
- package/dist/cli/chunk-vapjtyv9.js +7 -0
- package/dist/cli/chunk-vkch2spv.js +33 -0
- package/dist/cli/chunk-vpzvcxc1.js +3 -0
- package/dist/cli/chunk-vws0j65e.js +4 -0
- package/dist/cli/chunk-vyb5a2rh.js +4 -0
- package/dist/cli/chunk-w298ayjc.js +3 -0
- package/dist/cli/chunk-w48zjgxv.js +9 -0
- package/dist/cli/chunk-w5xy83ze.js +2 -0
- package/dist/cli/chunk-wpgmq5z6.js +106 -0
- package/dist/cli/chunk-wqfp8d9w.js +3 -0
- package/dist/cli/chunk-x760j10f.js +3 -0
- package/dist/cli/chunk-xbc3gcry.js +2 -0
- package/dist/cli/chunk-xy8be792.js +3 -0
- package/dist/cli/chunk-yhcz2d2r.js +34 -0
- package/dist/cli/chunk-yk2ha5yj.js +3 -0
- package/dist/cli/chunk-ykvk2546.js +3 -0
- package/dist/cli/chunk-ympakh8w.js +6 -0
- package/dist/cli/chunk-zb56ck5f.js +3 -0
- package/dist/cli/chunk-zwzkve1e.js +2 -0
- package/dist/cli/chunk-zy6vgjdp.js +19 -0
- package/dist/cli/index.js +15 -845
- package/dist/cli/kobe-run.js +1 -853
- package/dist/cli/kobe.js +6 -6
- package/dist/cli/pty-host-node.mjs +190 -52
- package/dist/cli/rove-run.js +1 -853
- package/dist/cli/rove.js +6 -6
- package/dist/skills/rove/SKILL.md +29 -10
- package/dist/skills/rove/references/api-flags.md +35 -13
- package/dist/web-ui/assets/{ChatTerminal-BshL3M8G.js → harness-CYGJ4uoR.js} +19 -20
- package/dist/web-ui/assets/index-BTJ-X_4s.js +10 -0
- package/dist/web-ui/assets/index-Cs2vPLNB.css +1 -0
- package/dist/web-ui/index.html +2 -9
- package/dist/web-ui/pty-server.mjs +4 -5
- package/package.json +2 -2
- package/dist/web-ui/assets/AppShell-BGRIs5hW.js +0 -5
- package/dist/web-ui/assets/AppShell-HiyATJse.css +0 -1
- package/dist/web-ui/assets/Board-Bt3cwp25.js +0 -1
- package/dist/web-ui/assets/BoardPeek-BKR-tpS2.js +0 -2
- package/dist/web-ui/assets/ChatTranscript-B67_nnd6.js +0 -1
- package/dist/web-ui/assets/ConfirmDialog-kyA624OF.js +0 -1
- package/dist/web-ui/assets/IssueIntakePanel-BMP8Vc3E.js +0 -1
- package/dist/web-ui/assets/IssuePeek-C7afOYax.js +0 -1
- package/dist/web-ui/assets/IssuesPage-DwRaBB-m.js +0 -1
- package/dist/web-ui/assets/SettingsPage-CC1sDI8j.js +0 -2
- package/dist/web-ui/assets/SlideOver-B4sEOPyN.css +0 -1
- package/dist/web-ui/assets/SlideOver-Dq0ifiEm.js +0 -173
- package/dist/web-ui/assets/ViewToggle-mNsDLJp8.js +0 -1
- package/dist/web-ui/assets/WorkspaceTabs-DLzL-Tad.css +0 -1
- package/dist/web-ui/assets/WorkspaceTabs-ifAIZ5Fj.js +0 -3
- package/dist/web-ui/assets/active-task-gVYiAkLv.js +0 -1
- package/dist/web-ui/assets/arrow-left-CavMh90a.js +0 -1
- package/dist/web-ui/assets/board-DoArj55z.js +0 -1
- package/dist/web-ui/assets/chips-CS9PLtWy.js +0 -1
- package/dist/web-ui/assets/createLucideIcon-CuIQtyYV.js +0 -1
- package/dist/web-ui/assets/external-link-Du2dMe8S.js +0 -1
- package/dist/web-ui/assets/external-store-BCBJewGi.js +0 -1
- package/dist/web-ui/assets/harness-ClZMF1wx.js +0 -1
- package/dist/web-ui/assets/index-B4xJZEqf.js +0 -10
- package/dist/web-ui/assets/index-BnjD9Q-3.css +0 -1
- package/dist/web-ui/assets/issues-DwrKXp9c.js +0 -4
- package/dist/web-ui/assets/issues-ISAZBras.js +0 -1
- package/dist/web-ui/assets/lazy-issue-panels-DvXQJhKy.js +0 -6
- package/dist/web-ui/assets/rotate-cw-BXdpzm3v.js +0 -1
- package/dist/web-ui/assets/routes-DEEkL5gG.js +0 -1
- package/dist/web-ui/assets/store-BLM6nh6E.js +0 -2
- package/dist/web-ui/assets/tabs-CMZJhcSB.js +0 -1
- package/dist/web-ui/assets/task._taskId-BCIhg4IQ.js +0 -1
- package/dist/web-ui/assets/terminal-DOp1a9g6.js +0 -1
- package/dist/web-ui/assets/text-match-DW3sD-Rt.js +0 -1
- package/dist/web-ui/assets/time-kviT26Tm.js +0 -1
- package/dist/web-ui/assets/toast-C4yXq6hM.js +0 -1
- package/dist/web-ui/assets/web-transport-Beqz2mQ8.js +0 -1
- package/dist/web-ui/assets/worktrees-BGvJOG2b.js +0 -1
- /package/dist/web-ui/assets/{ChatTerminal-BrP-ENHg.css → harness-BrP-ENHg.css} +0 -0
package/dist/cli/kobe.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{join as
|
|
3
|
-
`)[0]?.trim()??""};function K(W){return W.trim().match(/^v?(\d+\.\d+\.\d+)/)?.[1]??null}function
|
|
4
|
-
`)}function
|
|
5
|
-
`)}function
|
|
6
|
-
`)}function f(W=process.env,b=process.stdin,z=process.stdout){if(W[
|
|
7
|
-
`),1;return
|
|
2
|
+
import{join as z1}from"node:path";import{createInterface as $1}from"node:readline/promises";import{pathToFileURL as J1}from"node:url";import{spawnSync as L}from"node:child_process";import{constants as m,accessSync as u}from"node:fs";import{homedir as l}from"node:os";import{basename as t,delimiter as o,dirname as r,join as Y}from"node:path";import{fileURLToPath as T}from"node:url";var h={$schema:"https://json.schemastore.org/package.json",name:"@sma1lboy/rove",version:"0.9.147",description:"Rove — the agent multiplexer for your terminal. Run coding agents on parallel tasks with isolated worktrees and persistent sessions.",keywords:["terminal","tui","cli","multiplexer","ai-agents","coding-agent","ai-coding-assistant","agentic-ai","parallel-agents","git-worktree","claude-code","codex","llm","developer-tools"],type:"module",packageManager:"bun@1.3.13",bin:{kobe:"dist/cli/kobe.js",rove:"dist/cli/rove.js"},files:["dist/cli","dist/web-ui","dist/skills","dist/*.wav","README.md","LICENSE"],publishConfig:{access:"public"},repository:{type:"git",url:"git+https://github.com/Sma1lboy/rove.git"},homepage:"https://rove.run",bugs:{url:"https://github.com/Sma1lboy/rove/issues"},engines:{bun:">=1.3.11"},scripts:{dev:"ROVE_DEV=1 bun --conditions=browser ./src/cli/rove.ts","dev:kobe":"KOBE_DEV=1 bun --conditions=browser ./src/cli/kobe.ts","dev:mock":"KOBE_DEV=1 bun ./src/tui-react/mock/host.tsx","dev:sandbox":"bun run scripts/dev-sandbox.ts run","dev:sandbox:reset":"bun run scripts/dev-sandbox.ts reset",build:"bun run scripts/build.ts",compile:"bun run scripts/compile.ts",typecheck:"tsc --noEmit","check-i18n":"bun run scripts/check-i18n.ts",test:"bun run test:fast && bun run test:socket","perf:golden":"bun scripts/perf-golden.ts","pty:soak":"bun scripts/pty-soak.ts","test:fast":"vitest run --passWithNoTests --minWorkers=1 --maxWorkers=8","test:socket":"KOBE_INCLUDE_SOCKET=1 vitest run test/daemon --pool forks --minWorkers=1 --maxWorkers=4 --passWithNoTests","test:socket:coverage":"KOBE_INCLUDE_SOCKET=1 KOBE_COVERAGE_DAEMON=1 vitest run test/daemon --coverage --pool forks --minWorkers=1 --maxWorkers=4 --passWithNoTests","test:behavior":"KOBE_INCLUDE_BEHAVIOR=1 vitest run test/behavior --pool forks --minWorkers=1 --maxWorkers=1 --retry=2 --passWithNoTests","test:render":"bun test test/render --coverage --coverage-reporter=text --coverage-reporter=lcov --coverage-dir=coverage-render",coverage:"vitest run --coverage --passWithNoTests",bench:"vitest bench --run",lint:"biome check .",knip:"knip-bun",postinstall:"bun run scripts/check-preview-deps.ts || true",prepublishOnly:"bun run typecheck && bun run build","plugin-sandbox":"bun run scripts/plugin-sandbox.ts"},"//":"biome.json + bunfig.toml live at the monorepo root since they apply repo-wide; bun.lock also lives at root (workspace-shared).",dependencies:{"@ansi-tools/parser":"^1.0.15","@opentui/core":"0.4.3","@opentui/react":"0.4.3","@xterm/addon-serialize":"^0.14.0","@xterm/addon-unicode11":"^0.9.0","@xterm/headless":"^6.0.0","node-pty":"^1.1.0",react:"^19.2.8",ws:"^8.18.0"},devDependencies:{"@biomejs/biome":"1.9.4","@sma1lboy/kobe-daemon":"0.7.18","@tsconfig/bun":"1.0.10","@types/bun":"1.3.14","@types/node":"25.6.2","@types/react":"^19.2.0","@vitest/coverage-v8":"2.1.9",knip:"^6.14.2","react-devtools-core":"^7.0.1",typescript:"5.8.2",vitest:"2.1.9"},trustedDependencies:[]};var U="rove",C="kobe";var V=C;var k=U;var E="ROVE_INVOKED_AS";function x(W=process.env){return W[E]===k?k:V}var F="ROVE_BUN",i="ROVE_NO_BUN_BOOTSTRAP",O="ROVE_SKIP_BUN_CHECK",G=h.engines.bun.match(/\d+\.\d+\.\d+/)?.[0]??"0.0.0",B=(W)=>{try{return u(W,m.X_OK),!0}catch{return!1}},a=(W)=>W==="win32"?"bun.exe":"bun",n=(W)=>{let b=L(W,["--version"],{encoding:"utf8",timeout:5000});if(b.error||b.status!==0)return null;return b.stdout?.split(`
|
|
3
|
+
`)[0]?.trim()??""};function K(W){return W.trim().match(/^v?(\d+\.\d+\.\d+)/)?.[1]??null}function j(W,b=G){let z=K(W),Q=K(b);if(!z||!Q)return!0;let J=z.split(".").map(Number),$=Q.split(".").map(Number);for(let X=0;X<3;X++){let q=J[X]??0,H=$[X]??0;if(q!==H)return q>H}return!0}function P(W=process.env){return W[O]==="1"}function p(W={}){let b=W.env??process.env,z=W.platform??process.platform,Q=W.home??b.HOME??b.USERPROFILE??l(),J=a(z),$=[],X=b[F]?.trim();if(X)$.push(X);for(let w of(b.PATH??b.Path??"").split(o))if(w)$.push(Y(w,J));let q=b.BUN_INSTALL?.trim();if(q)$.push(Y(q,"bin",J));if(Q)$.push(Y(Q,".bun","bin",J));let H=W.launcherDir;if(H)$.push(Y(H,"..","..","node_modules","bun","bin",J)),$.push(Y(H,"..","..","..","bun","bin",J));return $}function e(W={}){let b=W.isExecutable??B;return p(W).find((z)=>b(z))??null}function D(W={}){let b=W.isExecutable??B,z=W.bunVersionOf??n;if(P(W.env??process.env))return{bun:e(W),stale:null,unusable:null};let Q=null,J=null;for(let $ of p(W)){if(!b($))continue;let X=z($);if(X===null){J??=$;continue}if(j(X))return{bun:$,stale:Q,unusable:J};Q??={path:$,version:K(X)??X}}return{bun:null,stale:Q,unusable:J}}function A(W){return r(T(W))}function R(W){return t(T(W)).replace(/\.[cm]?[jt]s$/,"")}function W1(W=process.platform){return W==="win32"?["powershell","-NoProfile","-Command","irm bun.sh/install.ps1 | iex"]:["bash","-c","curl -fsSL https://bun.sh/install | bash"]}function y(W=x(),b=process.platform){let z=b==="win32"?'powershell -c "irm bun.sh/install.ps1 | iex"':"curl -fsSL https://bun.sh/install | bash";return[`${W}: Rove runs on the Bun runtime, and no Bun was found on this machine.`,"","Install Bun, then run this command again:",` ${z}`," npm install -g bun # any platform, if you already have npm","","Or install Bun and Rove together in one step:"," curl -fsSL https://rove.run/install.sh | sh","",`Already have Bun somewhere unusual? Point Rove at it: ${F}=/path/to/bun`,""].join(`
|
|
4
|
+
`)}function g(W,b,z=x()){return[`${z}: this machine's Bun is too old for Rove — found ${b} at ${W}, need ${G} or newer.`,"","Rove's terminals are built on Bun's PTY API. An older Bun ignores it silently,","so every terminal and engine tab would open empty and stay empty.","","Upgrade Bun, then run this command again:"," bun upgrade # Bun installed itself (~/.bun)"," brew upgrade bun # Homebrew"," npm install -g bun@latest # npm-managed Bun","",`Have a newer Bun elsewhere? Point Rove at it: ${F}=/path/to/bun`,`Run on this one anyway (unsupported, terminals will be blank): ${O}=1`,""].join(`
|
|
5
|
+
`)}function I(W,b=x()){return[`${b}: the Bun at ${W} could not be run — \`${W} --version\` failed or never returned.`,"","Rove skipped it rather than starting through it, which would hang or fail","with a message from that binary instead of this one.","","Reinstall Bun, then run this command again:"," curl -fsSL https://bun.sh/install | bash","",`Have a working Bun elsewhere? Point Rove at it: ${F}=/path/to/bun`,""].join(`
|
|
6
|
+
`)}function f(W=process.env,b=process.stdin,z=process.stdout){if(W[i]==="1")return!1;if(W.CI==="true"||W.CI==="1")return!1;return Boolean(b.isTTY&&z.isTTY)}function c(W={},b=L){let z=W.platform??process.platform,[Q,...J]=W1(z);if(!Q)return null;let $=b(Q,J,{stdio:"inherit"});if($.error||$.status!==0)return null;return D(W).bun}function b1(W){if(typeof W.status==="number")return W.status;if(W.signal)return 128+(Object.hasOwn(M,W.signal)?M[W.signal]:0);return 1}var M={SIGINT:2,SIGQUIT:3,SIGKILL:9,SIGTERM:15};function _(W,b,z,Q=L){let J=Q(W,[b,...z],{stdio:"inherit"});if(J.error)return process.stderr.write(`rove: could not start Bun at ${W}: ${J.error.message}
|
|
7
|
+
`),1;return b1(J)}var S=A(import.meta.url),Z=R(import.meta.url),N=z1(S,`${Z}-run.js`);async function Q1(W){let b=$1({input:process.stdin,output:process.stdout});try{let z=(await b.question(W)).trim().toLowerCase();return z===""||z==="y"||z==="yes"}finally{b.close()}}async function X1(){let W={launcherDir:S},b=D(W);if(b.bun||!f())return b;let z=b.stale?`${Z}: Bun ${b.stale.version} is too old for Rove (needs ${G}+). Install the latest Bun now? [Y/n] `:`${Z}: Rove runs on the Bun runtime, and none is installed. Install Bun now? [Y/n] `;if(!await Q1(z))return b;return{bun:c(W),stale:b.stale,unusable:b.unusable}}var v=globalThis.Bun;if(v){let W=v.version;if(W&&!P()&&!j(W))process.stderr.write(g(process.execPath,W,Z)),process.exit(1);await import(J1(N).href)}else{let{bun:W,stale:b,unusable:z}=await X1();if(!W){let Q=b?g(b.path,b.version,Z):z?I(z,Z):y(Z);process.stderr.write(Q),process.exit(1)}process.exit(_(W,N,process.argv.slice(2)))}
|
|
@@ -32,6 +32,14 @@ var COMPAT_STATE_DIR_BASENAME = ".kobe";
|
|
|
32
32
|
function readRoveEnv(suffix, env = process.env) {
|
|
33
33
|
return env[`${ROVE_ENV_PREFIX}${suffix}`] ?? env[`${LEGACY_KOBE_ENV_PREFIX}${suffix}`];
|
|
34
34
|
}
|
|
35
|
+
function readRoveHomeDirEnv(env = process.env) {
|
|
36
|
+
for (const key of [`${ROVE_ENV_PREFIX}HOME_DIR`, `${LEGACY_KOBE_ENV_PREFIX}HOME_DIR`]) {
|
|
37
|
+
const value = env[key]?.trim();
|
|
38
|
+
if (value)
|
|
39
|
+
return value;
|
|
40
|
+
}
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
35
43
|
|
|
36
44
|
// ../kobe-daemon/src/daemon/paths.ts
|
|
37
45
|
function stateDirs(homeDir) {
|
|
@@ -68,12 +76,7 @@ function legacyPtyHostPidPath(homeDir) {
|
|
|
68
76
|
return legacyRuntimePath(homeDir, "pty.pid");
|
|
69
77
|
}
|
|
70
78
|
function runtimeDataPath(homeDir, name) {
|
|
71
|
-
|
|
72
|
-
const canonicalPath = join(canonical, name);
|
|
73
|
-
if (existsSync2(canonicalPath))
|
|
74
|
-
return canonicalPath;
|
|
75
|
-
const legacyPath = join(legacy, name);
|
|
76
|
-
return existsSync2(legacyPath) ? legacyPath : canonicalPath;
|
|
79
|
+
return join(stateDirs(homeDir).canonical, name);
|
|
77
80
|
}
|
|
78
81
|
var SOCKET_PATH_SAFETY_LIMIT = 100;
|
|
79
82
|
function shortHomeTag(homeDir) {
|
|
@@ -90,7 +93,7 @@ function fitSocketPath(naturalPath, homeDir, role, pidTag) {
|
|
|
90
93
|
throw new Error(`daemon socket path exceeds ${SOCKET_PATH_SAFETY_LIMIT} bytes even after fallback: ${fallback}`);
|
|
91
94
|
}
|
|
92
95
|
function resolveDaemonHomeDir(homeDir) {
|
|
93
|
-
const explicit = homeDir ??
|
|
96
|
+
const explicit = homeDir ?? readRoveHomeDirEnv();
|
|
94
97
|
return explicit && explicit.length > 0 ? explicit : homedir();
|
|
95
98
|
}
|
|
96
99
|
function isWindowsPipePath(path) {
|
|
@@ -103,7 +106,7 @@ function defaultPtyHostSocketPath(homeDir, platform = process.platform) {
|
|
|
103
106
|
const override = readRoveEnv("PTY_SOCKET_PATH");
|
|
104
107
|
if (override && override.length > 0)
|
|
105
108
|
return override;
|
|
106
|
-
const explicit = homeDir ??
|
|
109
|
+
const explicit = homeDir ?? readRoveHomeDirEnv();
|
|
107
110
|
if (platform === "win32")
|
|
108
111
|
return windowsPipePath(explicit || homedir(), "pty");
|
|
109
112
|
if (explicit && explicit.length > 0) {
|
|
@@ -116,19 +119,19 @@ function defaultPtyHostSocketPath(homeDir, platform = process.platform) {
|
|
|
116
119
|
const home = homedir();
|
|
117
120
|
return fitSocketPath(runtimePath(home, "pty.sock", "pty.pid"), home, "pty");
|
|
118
121
|
}
|
|
119
|
-
function defaultPtyHostPidPath(homeDir =
|
|
122
|
+
function defaultPtyHostPidPath(homeDir = readRoveHomeDirEnv() ?? homedir()) {
|
|
120
123
|
const override = readRoveEnv("PTY_PID_PATH");
|
|
121
124
|
if (override && override.length > 0)
|
|
122
125
|
return override;
|
|
123
126
|
return runtimePath(homeDir, "pty.pid", "pty.pid");
|
|
124
127
|
}
|
|
125
|
-
function defaultPtyHostLogPath(homeDir =
|
|
128
|
+
function defaultPtyHostLogPath(homeDir = readRoveHomeDirEnv() ?? homedir()) {
|
|
126
129
|
return join(homeDir, ROVE_STATE_DIR_BASENAME, "pty.log");
|
|
127
130
|
}
|
|
128
|
-
function defaultPtyExitsPath(homeDir =
|
|
131
|
+
function defaultPtyExitsPath(homeDir = readRoveHomeDirEnv() ?? homedir()) {
|
|
129
132
|
return runtimeDataPath(homeDir, "pty-exits.json");
|
|
130
133
|
}
|
|
131
|
-
function defaultPtyFreezeDir(homeDir =
|
|
134
|
+
function defaultPtyFreezeDir(homeDir = readRoveHomeDirEnv() ?? homedir()) {
|
|
132
135
|
return runtimeDataPath(homeDir, "pty-sessions");
|
|
133
136
|
}
|
|
134
137
|
|
|
@@ -288,18 +291,19 @@ class ClientWriter {
|
|
|
288
291
|
}
|
|
289
292
|
|
|
290
293
|
// ../kobe-daemon/src/daemon/compat-link.ts
|
|
291
|
-
import { lstat,
|
|
294
|
+
import { lstat, symlink, unlink } from "node:fs/promises";
|
|
292
295
|
import { dirname } from "node:path";
|
|
293
296
|
async function linkLegacyRuntimePath(canonical, legacy) {
|
|
294
297
|
if (canonical === legacy)
|
|
295
298
|
return false;
|
|
296
299
|
try {
|
|
300
|
+
if (!await lstat(dirname(legacy)).catch(() => null))
|
|
301
|
+
return false;
|
|
297
302
|
const existing = await lstat(legacy).catch(() => null);
|
|
298
303
|
if (existing && !existing.isSymbolicLink())
|
|
299
304
|
return false;
|
|
300
305
|
if (existing)
|
|
301
306
|
await unlink(legacy).catch(() => {});
|
|
302
|
-
await mkdir(dirname(legacy), { recursive: true });
|
|
303
307
|
await symlink(canonical, legacy);
|
|
304
308
|
return true;
|
|
305
309
|
} catch {
|
|
@@ -340,6 +344,30 @@ function requireString(payload, key) {
|
|
|
340
344
|
throw new Error(`${key} is required`);
|
|
341
345
|
return value;
|
|
342
346
|
}
|
|
347
|
+
|
|
348
|
+
// ../kobe-daemon/src/daemon/owner-only.ts
|
|
349
|
+
import { chmod, mkdir } from "node:fs/promises";
|
|
350
|
+
import { join as join2 } from "node:path";
|
|
351
|
+
var OWNER_ONLY_DIR_MODE = 448;
|
|
352
|
+
var OWNER_ONLY_FILE_MODE = 384;
|
|
353
|
+
async function tighten(path, mode) {
|
|
354
|
+
try {
|
|
355
|
+
await chmod(path, mode);
|
|
356
|
+
} catch {}
|
|
357
|
+
}
|
|
358
|
+
function tightenDirPermissions(dir) {
|
|
359
|
+
return tighten(dir, OWNER_ONLY_DIR_MODE);
|
|
360
|
+
}
|
|
361
|
+
function tightenFilePermissions(file) {
|
|
362
|
+
return tighten(file, OWNER_ONLY_FILE_MODE);
|
|
363
|
+
}
|
|
364
|
+
async function ensureOwnerOnlyDir(dir) {
|
|
365
|
+
await mkdir(dir, { recursive: true, mode: OWNER_ONLY_DIR_MODE });
|
|
366
|
+
await tightenDirPermissions(dir);
|
|
367
|
+
}
|
|
368
|
+
function ensureOwnerOnlyStateDir(homeDir) {
|
|
369
|
+
return ensureOwnerOnlyDir(join2(homeDir, ROVE_STATE_DIR_BASENAME));
|
|
370
|
+
}
|
|
343
371
|
// ../kobe-plugin-sdk/dist/contract.js
|
|
344
372
|
var DAEMON_CHANNELS = [
|
|
345
373
|
"task.snapshot",
|
|
@@ -366,9 +394,10 @@ var DAEMON_CHANNELS = [
|
|
|
366
394
|
// ../kobe-daemon/src/daemon/channels.ts
|
|
367
395
|
var CHANNEL_NAMES = DAEMON_CHANNELS;
|
|
368
396
|
var CHANNEL_NAME_SET = new Set(CHANNEL_NAMES);
|
|
397
|
+
// ../kobe-daemon/src/daemon/protocol-compat.ts
|
|
398
|
+
var DAEMON_PROTOCOL_VERSION = 4;
|
|
369
399
|
|
|
370
400
|
// ../kobe-daemon/src/daemon/protocol.ts
|
|
371
|
-
var DAEMON_PROTOCOL_VERSION = 4;
|
|
372
401
|
var BLOCKING_RPCS = new Set([
|
|
373
402
|
"ui.prompt",
|
|
374
403
|
"task.land",
|
|
@@ -388,8 +417,47 @@ function frameToLine(frame) {
|
|
|
388
417
|
`;
|
|
389
418
|
}
|
|
390
419
|
|
|
420
|
+
// ../kobe-daemon/src/daemon/pty-data-migration.ts
|
|
421
|
+
import { existsSync as existsSync3, lstatSync, mkdirSync, renameSync as renameSync2, symlinkSync } from "node:fs";
|
|
422
|
+
import { homedir as homedir2 } from "node:os";
|
|
423
|
+
import { join as join3 } from "node:path";
|
|
424
|
+
var PTY_HOST_DATA_ENTRIES = ["pty-exits.json", "pty-sessions"];
|
|
425
|
+
function lstatIfExists(path) {
|
|
426
|
+
try {
|
|
427
|
+
return lstatSync(path);
|
|
428
|
+
} catch {
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
function migrateLegacyPtyHostData(homeDir = readRoveHomeDirEnv() ?? homedir2()) {
|
|
433
|
+
const canonicalDir = join3(homeDir, ROVE_STATE_DIR_BASENAME);
|
|
434
|
+
const legacyDir = join3(homeDir, COMPAT_STATE_DIR_BASENAME);
|
|
435
|
+
if (canonicalDir === legacyDir)
|
|
436
|
+
return [];
|
|
437
|
+
const moved = [];
|
|
438
|
+
for (const name of PTY_HOST_DATA_ENTRIES) {
|
|
439
|
+
const canonical = join3(canonicalDir, name);
|
|
440
|
+
const legacy = join3(legacyDir, name);
|
|
441
|
+
try {
|
|
442
|
+
if (existsSync3(canonical))
|
|
443
|
+
continue;
|
|
444
|
+
const stat = lstatIfExists(legacy);
|
|
445
|
+
if (!stat || stat.isSymbolicLink())
|
|
446
|
+
continue;
|
|
447
|
+
mkdirSync(canonicalDir, { recursive: true });
|
|
448
|
+
renameSync2(legacy, canonical);
|
|
449
|
+
moved.push(name);
|
|
450
|
+
try {
|
|
451
|
+
symlinkSync(canonical, legacy);
|
|
452
|
+
} catch {}
|
|
453
|
+
} catch {}
|
|
454
|
+
}
|
|
455
|
+
return moved;
|
|
456
|
+
}
|
|
457
|
+
|
|
391
458
|
// ../kobe-daemon/src/daemon/pty-exit-store.ts
|
|
392
|
-
import {
|
|
459
|
+
import { randomUUID } from "node:crypto";
|
|
460
|
+
import { mkdirSync as mkdirSync2, readFileSync as readFileSync2, renameSync as renameSync3, writeFileSync } from "node:fs";
|
|
393
461
|
import { dirname as dirname2 } from "node:path";
|
|
394
462
|
|
|
395
463
|
// ../kobe-daemon/src/daemon/terminal-rows.ts
|
|
@@ -422,14 +490,34 @@ function plainTail(raw) {
|
|
|
422
490
|
lines.pop();
|
|
423
491
|
return lines.slice(-TAIL_LINES);
|
|
424
492
|
}
|
|
425
|
-
function
|
|
493
|
+
function engineExitCodeFromTail(tail) {
|
|
494
|
+
for (let i = tail.length - 1;i >= 0; i--) {
|
|
495
|
+
const m = ENGINE_EXIT_BANNER.exec(tail[i] ?? "");
|
|
496
|
+
if (m?.[1])
|
|
497
|
+
return Number.parseInt(m[1], 10);
|
|
498
|
+
}
|
|
499
|
+
return null;
|
|
500
|
+
}
|
|
501
|
+
var ENGINE_EXIT_BANNER = /Engine exited \(code (\d+)\)/;
|
|
502
|
+
function readPtyExitStore(path = defaultPtyExitsPath()) {
|
|
503
|
+
const read = (status, records = {}) => ({
|
|
504
|
+
records,
|
|
505
|
+
status,
|
|
506
|
+
readable: status === "ok" || status === "absent"
|
|
507
|
+
});
|
|
508
|
+
let raw;
|
|
509
|
+
try {
|
|
510
|
+
raw = readFileSync2(path, "utf8");
|
|
511
|
+
} catch (err) {
|
|
512
|
+
return read(err.code === "ENOENT" ? "absent" : "unreadable");
|
|
513
|
+
}
|
|
426
514
|
try {
|
|
427
|
-
const parsed = JSON.parse(
|
|
515
|
+
const parsed = JSON.parse(raw);
|
|
428
516
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed))
|
|
429
|
-
return
|
|
430
|
-
return parsed;
|
|
517
|
+
return read("unparsable");
|
|
518
|
+
return read("ok", parsed);
|
|
431
519
|
} catch {
|
|
432
|
-
return
|
|
520
|
+
return read("unparsable");
|
|
433
521
|
}
|
|
434
522
|
}
|
|
435
523
|
function recordPtyExit(info, path = defaultPtyExitsPath()) {
|
|
@@ -437,27 +525,33 @@ function recordPtyExit(info, path = defaultPtyExitsPath()) {
|
|
|
437
525
|
return;
|
|
438
526
|
if (info.exit.code === 0 && info.exit.signal === null)
|
|
439
527
|
return;
|
|
528
|
+
const tail = plainTail(info.tail);
|
|
440
529
|
writeRecord(info.key, {
|
|
441
530
|
key: info.key,
|
|
442
531
|
pid: info.pid,
|
|
443
|
-
code: info.exit.code,
|
|
532
|
+
code: info.exit.code ?? engineExitCodeFromTail(tail),
|
|
444
533
|
signal: info.exit.signal,
|
|
445
534
|
at: info.exit.at,
|
|
446
|
-
tail
|
|
535
|
+
tail,
|
|
447
536
|
layer: "pty"
|
|
448
537
|
}, path);
|
|
449
538
|
}
|
|
450
539
|
function writeRecord(storeKey, record, path) {
|
|
451
|
-
const
|
|
540
|
+
const store = readPtyExitStore(path);
|
|
541
|
+
if (store.status === "unreadable")
|
|
542
|
+
throw new Error(`pty-exits store is unreadable (${path}) — refusing to overwrite it`);
|
|
543
|
+
const records = store.records;
|
|
452
544
|
records[storeKey] = record;
|
|
453
545
|
const newest = Object.entries(records).sort(([, a], [, b]) => a.at < b.at ? 1 : -1).slice(0, MAX_RECORDS);
|
|
454
|
-
|
|
455
|
-
|
|
546
|
+
mkdirSync2(dirname2(path), { recursive: true });
|
|
547
|
+
const tmp = `${path}.tmp-${process.pid}-${randomUUID()}`;
|
|
548
|
+
writeFileSync(tmp, JSON.stringify(Object.fromEntries(newest), null, 2), { encoding: "utf8", mode: 384 });
|
|
549
|
+
renameSync3(tmp, path);
|
|
456
550
|
}
|
|
457
551
|
|
|
458
552
|
// ../kobe-daemon/src/daemon/pty-freeze-store.ts
|
|
459
|
-
import { chmodSync, mkdirSync as
|
|
460
|
-
import { join as
|
|
553
|
+
import { chmodSync, mkdirSync as mkdirSync3, readFileSync as readFileSync3, readdirSync, renameSync as renameSync4, rmSync, statSync as statSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
554
|
+
import { join as join4 } from "node:path";
|
|
461
555
|
import { StringDecoder } from "node:string_decoder";
|
|
462
556
|
|
|
463
557
|
// ../kobe-daemon/src/daemon/terminal-colors.ts
|
|
@@ -567,7 +661,7 @@ function thawSession(record, cap) {
|
|
|
567
661
|
};
|
|
568
662
|
}
|
|
569
663
|
function recordFile(dir, key) {
|
|
570
|
-
return
|
|
664
|
+
return join4(dir, `${encodeURIComponent(key)}.json`);
|
|
571
665
|
}
|
|
572
666
|
function parseRecord(raw) {
|
|
573
667
|
try {
|
|
@@ -588,43 +682,64 @@ function parseRecord(raw) {
|
|
|
588
682
|
}
|
|
589
683
|
}
|
|
590
684
|
var FREEZE_TTL_MS = 14 * 24 * 60 * 60 * 1000;
|
|
591
|
-
var
|
|
685
|
+
var FREEZE_RESTORE_MAX_BYTES = 64 * 1024 * 1024;
|
|
592
686
|
function updatedAtMs(record) {
|
|
593
687
|
const t = Date.parse(record.updatedAt);
|
|
594
688
|
return Number.isFinite(t) ? t : 0;
|
|
595
689
|
}
|
|
596
|
-
function loadFrozenSessions(dir = defaultPtyFreezeDir(), now = Date.now()) {
|
|
690
|
+
function loadFrozenSessions(dir = defaultPtyFreezeDir(), now = Date.now(), report) {
|
|
597
691
|
let names;
|
|
598
692
|
try {
|
|
599
693
|
names = readdirSync(dir);
|
|
600
694
|
} catch {
|
|
601
695
|
return [];
|
|
602
696
|
}
|
|
603
|
-
const
|
|
604
|
-
const stale = [];
|
|
697
|
+
const entries = [];
|
|
605
698
|
for (const name of names) {
|
|
606
699
|
if (!name.endsWith(".json"))
|
|
607
700
|
continue;
|
|
701
|
+
try {
|
|
702
|
+
const st = statSync2(join4(dir, name));
|
|
703
|
+
entries.push({ name, size: st.size, mtimeMs: st.mtimeMs });
|
|
704
|
+
} catch {}
|
|
705
|
+
}
|
|
706
|
+
entries.sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
707
|
+
const kept = [];
|
|
708
|
+
const stale = [];
|
|
709
|
+
let bytesRead = 0;
|
|
710
|
+
let deferred = 0;
|
|
711
|
+
let unreadable = 0;
|
|
712
|
+
for (const entry of entries) {
|
|
713
|
+
if (now - entry.mtimeMs > FREEZE_TTL_MS) {
|
|
714
|
+
stale.push(entry.name);
|
|
715
|
+
continue;
|
|
716
|
+
}
|
|
717
|
+
if (bytesRead + entry.size > FREEZE_RESTORE_MAX_BYTES && kept.length > 0) {
|
|
718
|
+
deferred++;
|
|
719
|
+
continue;
|
|
720
|
+
}
|
|
608
721
|
let record = null;
|
|
609
722
|
try {
|
|
610
|
-
record = parseRecord(readFileSync3(
|
|
723
|
+
record = parseRecord(readFileSync3(join4(dir, entry.name), "utf8"));
|
|
611
724
|
} catch {}
|
|
612
|
-
|
|
725
|
+
bytesRead += entry.size;
|
|
726
|
+
if (!record) {
|
|
727
|
+
unreadable++;
|
|
613
728
|
continue;
|
|
729
|
+
}
|
|
614
730
|
if (now - updatedAtMs(record) > FREEZE_TTL_MS)
|
|
615
|
-
stale.push(name);
|
|
731
|
+
stale.push(entry.name);
|
|
616
732
|
else
|
|
617
|
-
kept.push(
|
|
733
|
+
kept.push(record);
|
|
618
734
|
}
|
|
619
|
-
kept.sort((a, b) => updatedAtMs(b.record) - updatedAtMs(a.record));
|
|
620
|
-
for (const over of kept.splice(FREEZE_MAX_RECORDS))
|
|
621
|
-
stale.push(over.name);
|
|
622
735
|
for (const name of stale) {
|
|
623
736
|
try {
|
|
624
|
-
rmSync(
|
|
737
|
+
rmSync(join4(dir, name), { force: true });
|
|
625
738
|
} catch {}
|
|
626
739
|
}
|
|
627
|
-
|
|
740
|
+
kept.sort((a, b) => updatedAtMs(b) - updatedAtMs(a));
|
|
741
|
+
report?.({ restored: kept.length, bytesRead, deferred, expired: stale.length, unreadable });
|
|
742
|
+
return kept;
|
|
628
743
|
}
|
|
629
744
|
var DIR_MODE = 448;
|
|
630
745
|
var FILE_MODE = 384;
|
|
@@ -642,7 +757,7 @@ function tightenExistingPermissions(dir) {
|
|
|
642
757
|
if (!name.endsWith(".json"))
|
|
643
758
|
continue;
|
|
644
759
|
try {
|
|
645
|
-
chmodSync(
|
|
760
|
+
chmodSync(join4(dir, name), FILE_MODE);
|
|
646
761
|
} catch {}
|
|
647
762
|
}
|
|
648
763
|
}
|
|
@@ -651,11 +766,11 @@ function fileFreezeSink(dir = defaultPtyFreezeDir()) {
|
|
|
651
766
|
return {
|
|
652
767
|
save(record) {
|
|
653
768
|
try {
|
|
654
|
-
|
|
769
|
+
mkdirSync3(dir, { recursive: true, mode: DIR_MODE });
|
|
655
770
|
const target = recordFile(dir, record.key);
|
|
656
771
|
const staging = `${target}.${process.pid}.tmp`;
|
|
657
772
|
writeFileSync2(staging, JSON.stringify(record), { encoding: "utf8", mode: FILE_MODE });
|
|
658
|
-
|
|
773
|
+
renameSync4(staging, target);
|
|
659
774
|
} catch {}
|
|
660
775
|
},
|
|
661
776
|
drop(key) {
|
|
@@ -672,7 +787,7 @@ function clearFrozenSessions(dir = defaultPtyFreezeDir()) {
|
|
|
672
787
|
}
|
|
673
788
|
|
|
674
789
|
// ../kobe-daemon/src/daemon/platform-shell.js
|
|
675
|
-
import { existsSync as
|
|
790
|
+
import { existsSync as existsSync4 } from "node:fs";
|
|
676
791
|
function windowsBashCandidates(env) {
|
|
677
792
|
const roots = [env.ProgramFiles, env["ProgramFiles(x86)"], env.LOCALAPPDATA && `${env.LOCALAPPDATA}\\Programs`];
|
|
678
793
|
return roots.filter(Boolean).map((root) => `${root}\\Git\\bin\\bash.exe`);
|
|
@@ -686,7 +801,7 @@ function resolveLoginShell(options = {}) {
|
|
|
686
801
|
const fallback = options.fallback ?? "/bin/bash";
|
|
687
802
|
const platform = options.platform ?? process.platform;
|
|
688
803
|
const env = options.env ?? process.env;
|
|
689
|
-
const exists = options.exists ??
|
|
804
|
+
const exists = options.exists ?? existsSync4;
|
|
690
805
|
const cacheable = platform === process.platform && env === process.env && options.exists === undefined;
|
|
691
806
|
if (cacheable) {
|
|
692
807
|
const hit = cache.get(fallback);
|
|
@@ -1323,6 +1438,20 @@ class PtyHost {
|
|
|
1323
1438
|
}
|
|
1324
1439
|
}
|
|
1325
1440
|
|
|
1441
|
+
// ../kobe-daemon/src/daemon/socket-guard.ts
|
|
1442
|
+
async function listenOnUnixSocket(server, socketPath) {
|
|
1443
|
+
await new Promise((resolve, reject) => {
|
|
1444
|
+
const evented = server;
|
|
1445
|
+
evented.once("error", reject);
|
|
1446
|
+
server.listen(socketPath, () => {
|
|
1447
|
+
evented.removeListener("error", reject);
|
|
1448
|
+
resolve();
|
|
1449
|
+
});
|
|
1450
|
+
});
|
|
1451
|
+
if (!isWindowsPipePath(socketPath))
|
|
1452
|
+
await tightenFilePermissions(socketPath);
|
|
1453
|
+
}
|
|
1454
|
+
|
|
1326
1455
|
// ../kobe-daemon/src/daemon/pty-server.ts
|
|
1327
1456
|
var DEFAULT_IDLE_EXIT_MS = 60000;
|
|
1328
1457
|
var DEFAULT_ORPHAN_CHECK_MS = 30000;
|
|
@@ -1341,6 +1470,7 @@ function resolveIdleExitMs() {
|
|
|
1341
1470
|
return Number.isFinite(n) && n >= 0 ? n : DEFAULT_IDLE_EXIT_MS;
|
|
1342
1471
|
}
|
|
1343
1472
|
async function startPtyHostServer(options = {}) {
|
|
1473
|
+
migrateLegacyPtyHostData();
|
|
1344
1474
|
const socketPath = options.socketPath ?? defaultPtyHostSocketPath();
|
|
1345
1475
|
const pidPath = options.pidPath ?? defaultPtyHostPidPath();
|
|
1346
1476
|
const freezeDir = options.freezeDir ?? defaultPtyFreezeDir();
|
|
@@ -1411,8 +1541,19 @@ async function startPtyHostServer(options = {}) {
|
|
|
1411
1541
|
driver: options.driver,
|
|
1412
1542
|
log
|
|
1413
1543
|
});
|
|
1414
|
-
ptys.restoreFrozen(loadFrozenSessions(freezeDir))
|
|
1544
|
+
ptys.restoreFrozen(loadFrozenSessions(freezeDir, Date.now(), (s) => {
|
|
1545
|
+
const mib = (bytes) => `${Math.round(bytes / (1024 * 1024))}MB`;
|
|
1546
|
+
const notes = [`restored ${s.restored} (${mib(s.bytesRead)})`];
|
|
1547
|
+
if (s.deferred > 0)
|
|
1548
|
+
notes.push(`${s.deferred} left unread past the ${mib(FREEZE_RESTORE_MAX_BYTES)} budget`);
|
|
1549
|
+
if (s.expired > 0)
|
|
1550
|
+
notes.push(`${s.expired} deleted past the ${FREEZE_TTL_MS / 86400000}-day TTL`);
|
|
1551
|
+
if (s.unreadable > 0)
|
|
1552
|
+
notes.push(`${s.unreadable} unreadable`);
|
|
1553
|
+
log("freeze", notes.join(", "));
|
|
1554
|
+
}));
|
|
1415
1555
|
const pipeSocket = isWindowsPipePath(socketPath);
|
|
1556
|
+
await ensureOwnerOnlyStateDir(resolveDaemonHomeDir());
|
|
1416
1557
|
if (!pipeSocket)
|
|
1417
1558
|
await mkdir2(dirname3(socketPath), { recursive: true });
|
|
1418
1559
|
await mkdir2(dirname3(pidPath), { recursive: true });
|
|
@@ -1560,10 +1701,7 @@ async function startPtyHostServer(options = {}) {
|
|
|
1560
1701
|
`);
|
|
1561
1702
|
}
|
|
1562
1703
|
}
|
|
1563
|
-
await
|
|
1564
|
-
server.once("error", reject);
|
|
1565
|
-
server.listen(socketPath, () => resolve());
|
|
1566
|
-
});
|
|
1704
|
+
await listenOnUnixSocket(server, socketPath);
|
|
1567
1705
|
await writeFile(pidPath, `${process.pid}
|
|
1568
1706
|
`, "utf8");
|
|
1569
1707
|
if (!pipeSocket) {
|