@sma1lboy/rove 0.9.110 → 0.9.148
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-0b48bpkd.js +2 -0
- package/dist/cli/chunk-0dv2xssg.js +19 -0
- package/dist/cli/chunk-0sm2k04y.js +3 -0
- package/dist/cli/chunk-0vmrteyg.js +3 -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-1x0vahnn.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-39s1ndtm.js +106 -0
- package/dist/cli/chunk-3bfm4hrs.js +3 -0
- package/dist/cli/chunk-3rqa4pyt.js +28 -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-5ar3vspk.js +9 -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-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-7ngv7v9g.js +9 -0
- package/dist/cli/chunk-7nhdvr5v.js +4 -0
- package/dist/cli/chunk-7pfnda5z.js +12 -0
- package/dist/cli/chunk-7q67dz4c.js +3 -0
- package/dist/cli/chunk-8ddjfc2v.js +4 -0
- package/dist/cli/chunk-8g456mmt.js +3 -0
- package/dist/cli/chunk-8sbevss4.js +4 -0
- package/dist/cli/chunk-91j0an0j.js +2 -0
- package/dist/cli/chunk-99devyxr.js +2 -0
- package/dist/cli/chunk-9c1e5z6a.js +3 -0
- package/dist/cli/chunk-a4a4qaa2.js +3 -0
- package/dist/cli/chunk-adez6hq4.js +69 -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-b8d162tf.js +3 -0
- package/dist/cli/chunk-b99tf0jr.js +3 -0
- package/dist/cli/chunk-bj59a9mg.js +3 -0
- package/dist/cli/chunk-c6mthex1.js +5 -0
- package/dist/cli/chunk-cb2fpajx.js +3 -0
- package/dist/cli/chunk-cbkje3aw.js +2 -0
- package/dist/cli/chunk-df7qe9y7.js +4 -0
- package/dist/cli/chunk-dkxhmj9k.js +25 -0
- package/dist/cli/chunk-dqndd97s.js +7 -0
- package/dist/cli/chunk-dvabncrk.js +7 -0
- package/dist/cli/chunk-dvcb6mk4.js +3 -0
- package/dist/cli/chunk-dw853n4w.js +3 -0
- package/dist/cli/chunk-dx6b3dv8.js +7 -0
- package/dist/cli/chunk-e1g9mvww.js +11 -0
- package/dist/cli/chunk-ef11h2am.js +3 -0
- package/dist/cli/chunk-ef39ym8f.js +3 -0
- package/dist/cli/chunk-eq5f3z2f.js +3 -0
- package/dist/cli/chunk-ewdhz3dv.js +2 -0
- package/dist/cli/chunk-f6zsej8e.js +3 -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-j4xfsn9g.js +5 -0
- package/dist/cli/chunk-jfqbq12b.js +18 -0
- package/dist/cli/chunk-jsss3ze7.js +11 -0
- package/dist/cli/chunk-jvpzy378.js +3 -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-m0fz6g32.js +16 -0
- package/dist/cli/chunk-mb5m7ex7.js +2 -0
- package/dist/cli/chunk-me77sx3d.js +3 -0
- package/dist/cli/chunk-mfqjdpd8.js +2 -0
- package/dist/cli/chunk-mggca3k4.js +4 -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-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-nrnjt5b6.js +2 -0
- package/dist/cli/chunk-p7kztgsd.js +4 -0
- package/dist/cli/chunk-pbqwegjy.js +2 -0
- package/dist/cli/chunk-pcvk98rr.js +3 -0
- package/dist/cli/chunk-pdh5w4ht.js +3 -0
- package/dist/cli/chunk-pdj8kqa1.js +74 -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-qkehg2c1.js +3 -0
- package/dist/cli/chunk-qtke4x42.js +3 -0
- package/dist/cli/chunk-rxvbm4vt.js +7 -0
- package/dist/cli/chunk-s66eh0pw.js +8 -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-t0kta7rb.js +5 -0
- package/dist/cli/chunk-v5893dx3.js +2 -0
- package/dist/cli/chunk-vapjtyv9.js +7 -0
- package/dist/cli/chunk-vpzvcxc1.js +3 -0
- package/dist/cli/chunk-vqpa27cf.js +15 -0
- package/dist/cli/chunk-vws0j65e.js +4 -0
- package/dist/cli/chunk-vyb5a2rh.js +4 -0
- package/dist/cli/chunk-vzxbe80f.js +7 -0
- package/dist/cli/chunk-w5xy83ze.js +2 -0
- package/dist/cli/chunk-wqfp8d9w.js +3 -0
- package/dist/cli/chunk-wsvf9eka.js +33 -0
- package/dist/cli/chunk-x760j10f.js +3 -0
- package/dist/cli/chunk-x930m5fs.js +2 -0
- package/dist/cli/chunk-xbc3gcry.js +2 -0
- package/dist/cli/chunk-xy8be792.js +3 -0
- package/dist/cli/chunk-xzrqnpmh.js +4 -0
- package/dist/cli/chunk-y2yq6zca.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-yn5a7xcv.js +2 -0
- package/dist/cli/chunk-zb56ck5f.js +3 -0
- package/dist/cli/index.js +15 -850
- package/dist/cli/kobe-run.js +1 -858
- package/dist/cli/kobe.js +6 -6
- package/dist/cli/pty-host-node.mjs +167 -50
- package/dist/cli/rove-run.js +1 -858
- 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 +1 -1
- 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.148",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) {
|
|
@@ -85,7 +93,7 @@ function fitSocketPath(naturalPath, homeDir, role, pidTag) {
|
|
|
85
93
|
throw new Error(`daemon socket path exceeds ${SOCKET_PATH_SAFETY_LIMIT} bytes even after fallback: ${fallback}`);
|
|
86
94
|
}
|
|
87
95
|
function resolveDaemonHomeDir(homeDir) {
|
|
88
|
-
const explicit = homeDir ??
|
|
96
|
+
const explicit = homeDir ?? readRoveHomeDirEnv();
|
|
89
97
|
return explicit && explicit.length > 0 ? explicit : homedir();
|
|
90
98
|
}
|
|
91
99
|
function isWindowsPipePath(path) {
|
|
@@ -98,7 +106,7 @@ function defaultPtyHostSocketPath(homeDir, platform = process.platform) {
|
|
|
98
106
|
const override = readRoveEnv("PTY_SOCKET_PATH");
|
|
99
107
|
if (override && override.length > 0)
|
|
100
108
|
return override;
|
|
101
|
-
const explicit = homeDir ??
|
|
109
|
+
const explicit = homeDir ?? readRoveHomeDirEnv();
|
|
102
110
|
if (platform === "win32")
|
|
103
111
|
return windowsPipePath(explicit || homedir(), "pty");
|
|
104
112
|
if (explicit && explicit.length > 0) {
|
|
@@ -111,19 +119,19 @@ function defaultPtyHostSocketPath(homeDir, platform = process.platform) {
|
|
|
111
119
|
const home = homedir();
|
|
112
120
|
return fitSocketPath(runtimePath(home, "pty.sock", "pty.pid"), home, "pty");
|
|
113
121
|
}
|
|
114
|
-
function defaultPtyHostPidPath(homeDir =
|
|
122
|
+
function defaultPtyHostPidPath(homeDir = readRoveHomeDirEnv() ?? homedir()) {
|
|
115
123
|
const override = readRoveEnv("PTY_PID_PATH");
|
|
116
124
|
if (override && override.length > 0)
|
|
117
125
|
return override;
|
|
118
126
|
return runtimePath(homeDir, "pty.pid", "pty.pid");
|
|
119
127
|
}
|
|
120
|
-
function defaultPtyHostLogPath(homeDir =
|
|
128
|
+
function defaultPtyHostLogPath(homeDir = readRoveHomeDirEnv() ?? homedir()) {
|
|
121
129
|
return join(homeDir, ROVE_STATE_DIR_BASENAME, "pty.log");
|
|
122
130
|
}
|
|
123
|
-
function defaultPtyExitsPath(homeDir =
|
|
131
|
+
function defaultPtyExitsPath(homeDir = readRoveHomeDirEnv() ?? homedir()) {
|
|
124
132
|
return runtimeDataPath(homeDir, "pty-exits.json");
|
|
125
133
|
}
|
|
126
|
-
function defaultPtyFreezeDir(homeDir =
|
|
134
|
+
function defaultPtyFreezeDir(homeDir = readRoveHomeDirEnv() ?? homedir()) {
|
|
127
135
|
return runtimeDataPath(homeDir, "pty-sessions");
|
|
128
136
|
}
|
|
129
137
|
|
|
@@ -182,7 +190,7 @@ async function nodePtyDriver(spawn) {
|
|
|
182
190
|
|
|
183
191
|
// ../kobe-daemon/src/daemon/pty-server.ts
|
|
184
192
|
import { readFileSync as readFileSync4 } from "node:fs";
|
|
185
|
-
import { mkdir, unlink as unlink2, writeFile } from "node:fs/promises";
|
|
193
|
+
import { mkdir as mkdir2, unlink as unlink2, writeFile } from "node:fs/promises";
|
|
186
194
|
import { createServer } from "node:net";
|
|
187
195
|
import { dirname as dirname3 } from "node:path";
|
|
188
196
|
import { StringDecoder as StringDecoder3 } from "node:string_decoder";
|
|
@@ -336,6 +344,30 @@ function requireString(payload, key) {
|
|
|
336
344
|
throw new Error(`${key} is required`);
|
|
337
345
|
return value;
|
|
338
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
|
+
}
|
|
339
371
|
// ../kobe-plugin-sdk/dist/contract.js
|
|
340
372
|
var DAEMON_CHANNELS = [
|
|
341
373
|
"task.snapshot",
|
|
@@ -388,7 +420,7 @@ function frameToLine(frame) {
|
|
|
388
420
|
// ../kobe-daemon/src/daemon/pty-data-migration.ts
|
|
389
421
|
import { existsSync as existsSync3, lstatSync, mkdirSync, renameSync as renameSync2, symlinkSync } from "node:fs";
|
|
390
422
|
import { homedir as homedir2 } from "node:os";
|
|
391
|
-
import { join as
|
|
423
|
+
import { join as join3 } from "node:path";
|
|
392
424
|
var PTY_HOST_DATA_ENTRIES = ["pty-exits.json", "pty-sessions"];
|
|
393
425
|
function lstatIfExists(path) {
|
|
394
426
|
try {
|
|
@@ -397,15 +429,15 @@ function lstatIfExists(path) {
|
|
|
397
429
|
return;
|
|
398
430
|
}
|
|
399
431
|
}
|
|
400
|
-
function migrateLegacyPtyHostData(homeDir =
|
|
401
|
-
const canonicalDir =
|
|
402
|
-
const legacyDir =
|
|
432
|
+
function migrateLegacyPtyHostData(homeDir = readRoveHomeDirEnv() ?? homedir2()) {
|
|
433
|
+
const canonicalDir = join3(homeDir, ROVE_STATE_DIR_BASENAME);
|
|
434
|
+
const legacyDir = join3(homeDir, COMPAT_STATE_DIR_BASENAME);
|
|
403
435
|
if (canonicalDir === legacyDir)
|
|
404
436
|
return [];
|
|
405
437
|
const moved = [];
|
|
406
438
|
for (const name of PTY_HOST_DATA_ENTRIES) {
|
|
407
|
-
const canonical =
|
|
408
|
-
const legacy =
|
|
439
|
+
const canonical = join3(canonicalDir, name);
|
|
440
|
+
const legacy = join3(legacyDir, name);
|
|
409
441
|
try {
|
|
410
442
|
if (existsSync3(canonical))
|
|
411
443
|
continue;
|
|
@@ -424,7 +456,8 @@ function migrateLegacyPtyHostData(homeDir = readRoveEnv("HOME_DIR") ?? homedir2(
|
|
|
424
456
|
}
|
|
425
457
|
|
|
426
458
|
// ../kobe-daemon/src/daemon/pty-exit-store.ts
|
|
427
|
-
import {
|
|
459
|
+
import { randomUUID } from "node:crypto";
|
|
460
|
+
import { mkdirSync as mkdirSync2, readFileSync as readFileSync2, renameSync as renameSync3, writeFileSync } from "node:fs";
|
|
428
461
|
import { dirname as dirname2 } from "node:path";
|
|
429
462
|
|
|
430
463
|
// ../kobe-daemon/src/daemon/terminal-rows.ts
|
|
@@ -457,14 +490,34 @@ function plainTail(raw) {
|
|
|
457
490
|
lines.pop();
|
|
458
491
|
return lines.slice(-TAIL_LINES);
|
|
459
492
|
}
|
|
460
|
-
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
|
+
}
|
|
461
514
|
try {
|
|
462
|
-
const parsed = JSON.parse(
|
|
515
|
+
const parsed = JSON.parse(raw);
|
|
463
516
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed))
|
|
464
|
-
return
|
|
465
|
-
return parsed;
|
|
517
|
+
return read("unparsable");
|
|
518
|
+
return read("ok", parsed);
|
|
466
519
|
} catch {
|
|
467
|
-
return
|
|
520
|
+
return read("unparsable");
|
|
468
521
|
}
|
|
469
522
|
}
|
|
470
523
|
function recordPtyExit(info, path = defaultPtyExitsPath()) {
|
|
@@ -472,27 +525,33 @@ function recordPtyExit(info, path = defaultPtyExitsPath()) {
|
|
|
472
525
|
return;
|
|
473
526
|
if (info.exit.code === 0 && info.exit.signal === null)
|
|
474
527
|
return;
|
|
528
|
+
const tail = plainTail(info.tail);
|
|
475
529
|
writeRecord(info.key, {
|
|
476
530
|
key: info.key,
|
|
477
531
|
pid: info.pid,
|
|
478
|
-
code: info.exit.code,
|
|
532
|
+
code: info.exit.code ?? engineExitCodeFromTail(tail),
|
|
479
533
|
signal: info.exit.signal,
|
|
480
534
|
at: info.exit.at,
|
|
481
|
-
tail
|
|
535
|
+
tail,
|
|
482
536
|
layer: "pty"
|
|
483
537
|
}, path);
|
|
484
538
|
}
|
|
485
539
|
function writeRecord(storeKey, record, path) {
|
|
486
|
-
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;
|
|
487
544
|
records[storeKey] = record;
|
|
488
545
|
const newest = Object.entries(records).sort(([, a], [, b]) => a.at < b.at ? 1 : -1).slice(0, MAX_RECORDS);
|
|
489
546
|
mkdirSync2(dirname2(path), { recursive: true });
|
|
490
|
-
|
|
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);
|
|
491
550
|
}
|
|
492
551
|
|
|
493
552
|
// ../kobe-daemon/src/daemon/pty-freeze-store.ts
|
|
494
|
-
import { chmodSync, mkdirSync as mkdirSync3, readFileSync as readFileSync3, readdirSync, renameSync as
|
|
495
|
-
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";
|
|
496
555
|
import { StringDecoder } from "node:string_decoder";
|
|
497
556
|
|
|
498
557
|
// ../kobe-daemon/src/daemon/terminal-colors.ts
|
|
@@ -602,7 +661,7 @@ function thawSession(record, cap) {
|
|
|
602
661
|
};
|
|
603
662
|
}
|
|
604
663
|
function recordFile(dir, key) {
|
|
605
|
-
return
|
|
664
|
+
return join4(dir, `${encodeURIComponent(key)}.json`);
|
|
606
665
|
}
|
|
607
666
|
function parseRecord(raw) {
|
|
608
667
|
try {
|
|
@@ -623,43 +682,64 @@ function parseRecord(raw) {
|
|
|
623
682
|
}
|
|
624
683
|
}
|
|
625
684
|
var FREEZE_TTL_MS = 14 * 24 * 60 * 60 * 1000;
|
|
626
|
-
var
|
|
685
|
+
var FREEZE_RESTORE_MAX_BYTES = 64 * 1024 * 1024;
|
|
627
686
|
function updatedAtMs(record) {
|
|
628
687
|
const t = Date.parse(record.updatedAt);
|
|
629
688
|
return Number.isFinite(t) ? t : 0;
|
|
630
689
|
}
|
|
631
|
-
function loadFrozenSessions(dir = defaultPtyFreezeDir(), now = Date.now()) {
|
|
690
|
+
function loadFrozenSessions(dir = defaultPtyFreezeDir(), now = Date.now(), report) {
|
|
632
691
|
let names;
|
|
633
692
|
try {
|
|
634
693
|
names = readdirSync(dir);
|
|
635
694
|
} catch {
|
|
636
695
|
return [];
|
|
637
696
|
}
|
|
638
|
-
const
|
|
639
|
-
const stale = [];
|
|
697
|
+
const entries = [];
|
|
640
698
|
for (const name of names) {
|
|
641
699
|
if (!name.endsWith(".json"))
|
|
642
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
|
+
}
|
|
643
721
|
let record = null;
|
|
644
722
|
try {
|
|
645
|
-
record = parseRecord(readFileSync3(
|
|
723
|
+
record = parseRecord(readFileSync3(join4(dir, entry.name), "utf8"));
|
|
646
724
|
} catch {}
|
|
647
|
-
|
|
725
|
+
bytesRead += entry.size;
|
|
726
|
+
if (!record) {
|
|
727
|
+
unreadable++;
|
|
648
728
|
continue;
|
|
729
|
+
}
|
|
649
730
|
if (now - updatedAtMs(record) > FREEZE_TTL_MS)
|
|
650
|
-
stale.push(name);
|
|
731
|
+
stale.push(entry.name);
|
|
651
732
|
else
|
|
652
|
-
kept.push(
|
|
733
|
+
kept.push(record);
|
|
653
734
|
}
|
|
654
|
-
kept.sort((a, b) => updatedAtMs(b.record) - updatedAtMs(a.record));
|
|
655
|
-
for (const over of kept.splice(FREEZE_MAX_RECORDS))
|
|
656
|
-
stale.push(over.name);
|
|
657
735
|
for (const name of stale) {
|
|
658
736
|
try {
|
|
659
|
-
rmSync(
|
|
737
|
+
rmSync(join4(dir, name), { force: true });
|
|
660
738
|
} catch {}
|
|
661
739
|
}
|
|
662
|
-
|
|
740
|
+
kept.sort((a, b) => updatedAtMs(b) - updatedAtMs(a));
|
|
741
|
+
report?.({ restored: kept.length, bytesRead, deferred, expired: stale.length, unreadable });
|
|
742
|
+
return kept;
|
|
663
743
|
}
|
|
664
744
|
var DIR_MODE = 448;
|
|
665
745
|
var FILE_MODE = 384;
|
|
@@ -677,7 +757,7 @@ function tightenExistingPermissions(dir) {
|
|
|
677
757
|
if (!name.endsWith(".json"))
|
|
678
758
|
continue;
|
|
679
759
|
try {
|
|
680
|
-
chmodSync(
|
|
760
|
+
chmodSync(join4(dir, name), FILE_MODE);
|
|
681
761
|
} catch {}
|
|
682
762
|
}
|
|
683
763
|
}
|
|
@@ -690,7 +770,7 @@ function fileFreezeSink(dir = defaultPtyFreezeDir()) {
|
|
|
690
770
|
const target = recordFile(dir, record.key);
|
|
691
771
|
const staging = `${target}.${process.pid}.tmp`;
|
|
692
772
|
writeFileSync2(staging, JSON.stringify(record), { encoding: "utf8", mode: FILE_MODE });
|
|
693
|
-
|
|
773
|
+
renameSync4(staging, target);
|
|
694
774
|
} catch {}
|
|
695
775
|
},
|
|
696
776
|
drop(key) {
|
|
@@ -802,6 +882,7 @@ function freshSessionState(key, spec, argv) {
|
|
|
802
882
|
exit: null,
|
|
803
883
|
restored: false,
|
|
804
884
|
lastFreezeAtMs: 0,
|
|
885
|
+
frozenTotalBytes: 0,
|
|
805
886
|
lastHumanWriteMs: 0
|
|
806
887
|
};
|
|
807
888
|
}
|
|
@@ -1031,6 +1112,20 @@ class PtyChildController {
|
|
|
1031
1112
|
}
|
|
1032
1113
|
}
|
|
1033
1114
|
|
|
1115
|
+
// ../kobe-daemon/src/daemon/pty-freeze-policy.ts
|
|
1116
|
+
var FREEZE_INTERVAL_MS = 5000;
|
|
1117
|
+
var FREEZE_MIN_APPENDED_BYTES = 64 * 1024;
|
|
1118
|
+
var FREEZE_STALE_MS = 60000;
|
|
1119
|
+
function shouldFreeze(session, now) {
|
|
1120
|
+
const appended = session.totalBytes - (session.frozenTotalBytes ?? 0);
|
|
1121
|
+
if (appended <= 0)
|
|
1122
|
+
return false;
|
|
1123
|
+
const since = now - session.lastFreezeAtMs;
|
|
1124
|
+
if (since < FREEZE_INTERVAL_MS)
|
|
1125
|
+
return false;
|
|
1126
|
+
return appended >= FREEZE_MIN_APPENDED_BYTES || since >= FREEZE_STALE_MS;
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1034
1129
|
// ../kobe-daemon/src/daemon/pty-warm.ts
|
|
1035
1130
|
class WarmSpare {
|
|
1036
1131
|
deps;
|
|
@@ -1096,7 +1191,6 @@ function resolveHumanWriteQuietMs() {
|
|
|
1096
1191
|
const n = Number(raw);
|
|
1097
1192
|
return Number.isFinite(n) && n >= 0 ? n : DEFAULT_HUMAN_WRITE_QUIET_MS;
|
|
1098
1193
|
}
|
|
1099
|
-
var FREEZE_INTERVAL_MS = 5000;
|
|
1100
1194
|
|
|
1101
1195
|
class PtyHost {
|
|
1102
1196
|
sessions = new Map;
|
|
@@ -1344,9 +1438,10 @@ class PtyHost {
|
|
|
1344
1438
|
if (session.closedByRequest)
|
|
1345
1439
|
return;
|
|
1346
1440
|
const now = Date.now();
|
|
1347
|
-
if (!force &&
|
|
1441
|
+
if (!force && !shouldFreeze(session, now))
|
|
1348
1442
|
return;
|
|
1349
1443
|
session.lastFreezeAtMs = now;
|
|
1444
|
+
session.frozenTotalBytes = session.totalBytes;
|
|
1350
1445
|
freeze.save(freezeSession(session));
|
|
1351
1446
|
}
|
|
1352
1447
|
liveCount() {
|
|
@@ -1358,6 +1453,20 @@ class PtyHost {
|
|
|
1358
1453
|
}
|
|
1359
1454
|
}
|
|
1360
1455
|
|
|
1456
|
+
// ../kobe-daemon/src/daemon/socket-guard.ts
|
|
1457
|
+
async function listenOnUnixSocket(server, socketPath) {
|
|
1458
|
+
await new Promise((resolve, reject) => {
|
|
1459
|
+
const evented = server;
|
|
1460
|
+
evented.once("error", reject);
|
|
1461
|
+
server.listen(socketPath, () => {
|
|
1462
|
+
evented.removeListener("error", reject);
|
|
1463
|
+
resolve();
|
|
1464
|
+
});
|
|
1465
|
+
});
|
|
1466
|
+
if (!isWindowsPipePath(socketPath))
|
|
1467
|
+
await tightenFilePermissions(socketPath);
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1361
1470
|
// ../kobe-daemon/src/daemon/pty-server.ts
|
|
1362
1471
|
var DEFAULT_IDLE_EXIT_MS = 60000;
|
|
1363
1472
|
var DEFAULT_ORPHAN_CHECK_MS = 30000;
|
|
@@ -1447,11 +1556,22 @@ async function startPtyHostServer(options = {}) {
|
|
|
1447
1556
|
driver: options.driver,
|
|
1448
1557
|
log
|
|
1449
1558
|
});
|
|
1450
|
-
ptys.restoreFrozen(loadFrozenSessions(freezeDir))
|
|
1559
|
+
ptys.restoreFrozen(loadFrozenSessions(freezeDir, Date.now(), (s) => {
|
|
1560
|
+
const mib = (bytes) => `${Math.round(bytes / (1024 * 1024))}MB`;
|
|
1561
|
+
const notes = [`restored ${s.restored} (${mib(s.bytesRead)})`];
|
|
1562
|
+
if (s.deferred > 0)
|
|
1563
|
+
notes.push(`${s.deferred} left unread past the ${mib(FREEZE_RESTORE_MAX_BYTES)} budget`);
|
|
1564
|
+
if (s.expired > 0)
|
|
1565
|
+
notes.push(`${s.expired} deleted past the ${FREEZE_TTL_MS / 86400000}-day TTL`);
|
|
1566
|
+
if (s.unreadable > 0)
|
|
1567
|
+
notes.push(`${s.unreadable} unreadable`);
|
|
1568
|
+
log("freeze", notes.join(", "));
|
|
1569
|
+
}));
|
|
1451
1570
|
const pipeSocket = isWindowsPipePath(socketPath);
|
|
1571
|
+
await ensureOwnerOnlyStateDir(resolveDaemonHomeDir());
|
|
1452
1572
|
if (!pipeSocket)
|
|
1453
|
-
await
|
|
1454
|
-
await
|
|
1573
|
+
await mkdir2(dirname3(socketPath), { recursive: true });
|
|
1574
|
+
await mkdir2(dirname3(pidPath), { recursive: true });
|
|
1455
1575
|
const server = createServer((socket) => {
|
|
1456
1576
|
const client = {
|
|
1457
1577
|
socket,
|
|
@@ -1596,10 +1716,7 @@ async function startPtyHostServer(options = {}) {
|
|
|
1596
1716
|
`);
|
|
1597
1717
|
}
|
|
1598
1718
|
}
|
|
1599
|
-
await
|
|
1600
|
-
server.once("error", reject);
|
|
1601
|
-
server.listen(socketPath, () => resolve());
|
|
1602
|
-
});
|
|
1719
|
+
await listenOnUnixSocket(server, socketPath);
|
|
1603
1720
|
await writeFile(pidPath, `${process.pid}
|
|
1604
1721
|
`, "utf8");
|
|
1605
1722
|
if (!pipeSocket) {
|