nearly-cli 0.1.12 → 0.1.16
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 +64 -6
- package/bin/nearly.mjs +12 -2
- package/package.json +2 -2
- package/scripts/agents.mjs +10 -6
- package/scripts/attach.mjs +141 -35
- package/scripts/build-recap.mjs +50 -11
- package/scripts/detect.mjs +2 -1
- package/scripts/doctor.mjs +30 -13
- package/scripts/hook.mjs +12 -5
- package/scripts/install-push-hook.mjs +29 -11
- package/scripts/post-recap.mjs +1 -1
- package/scripts/push-record.mjs +7 -5
- package/scripts/runtime.mjs +84 -0
- package/scripts/update-check.mjs +58 -5
- package/server/adapters.mjs +21 -5
- package/server/index.mjs +14 -4
- package/server/policy.mjs +821 -17
- package/server/reclaim.mjs +22 -2
- package/ui/recap.template.html +1 -1
package/server/reclaim.mjs
CHANGED
|
@@ -70,10 +70,30 @@ const freed = async (base) => (await identify(base)) === null;
|
|
|
70
70
|
// 'stood-down' it exited when asked (0.1.8 and later)
|
|
71
71
|
// 'ended' older build, idle, so we closed it
|
|
72
72
|
// 'stuck' ours by every test, but we could not end it
|
|
73
|
-
|
|
73
|
+
const parts = (v) => String(v || '').split('-')[0].split('.').map(Number);
|
|
74
|
+
function newer(a, b) {
|
|
75
|
+
const x = parts(a), y = parts(b);
|
|
76
|
+
if (x.some(Number.isNaN) || y.some(Number.isNaN)) return false;
|
|
77
|
+
for (let i = 0; i < 3; i++) if ((x[i] || 0) !== (y[i] || 0)) return (x[i] || 0) > (y[i] || 0);
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Whether the server on the port is good enough to keep: this build, the same
|
|
82
|
+
// version run from somewhere else, or a newer one.
|
|
83
|
+
//
|
|
84
|
+
// This used to compare install folders. A second `npx nearly-cli` never shares a
|
|
85
|
+
// folder with the runtime install, so it closed a server with live sessions and
|
|
86
|
+
// announced that it had closed "an older" one. And an old hook pinned to a past
|
|
87
|
+
// release would have replaced a newer server with itself.
|
|
88
|
+
export function keep(serverVersion, ourVersion) {
|
|
89
|
+
if (!serverVersion || !ourVersion) return false;
|
|
90
|
+
return serverVersion === ourVersion || newer(serverVersion, ourVersion);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export async function reclaim({ port, base, root, version, kill = process.kill.bind(process) }) {
|
|
74
94
|
const who = await identify(base);
|
|
75
95
|
if (!who) return { outcome: 'free' };
|
|
76
|
-
if (who.root && who.root === root) return { outcome: 'ours', who };
|
|
96
|
+
if ((who.root && who.root === root) || keep(who.version, version)) return { outcome: 'ours', who };
|
|
77
97
|
if (who.waiting > 0) return { outcome: 'busy', who };
|
|
78
98
|
|
|
79
99
|
// The polite path. A build that understands this will refuse if it is busy.
|
package/ui/recap.template.html
CHANGED
|
@@ -335,7 +335,7 @@ const render = {
|
|
|
335
335
|
<div class="col"><span class="lbl">${esc(askedFor)}</span><div class="body">${esc(s.task)}</div></div>
|
|
336
336
|
<div class="col"><span class="lbl">Agent reported</span><div class="body">${esc(s.report || '(no final message)')}</div></div>
|
|
337
337
|
</div>
|
|
338
|
-
${s.notDone.length ? `<div class="notdone">${s.notDone.map((n) => `<div class="row">${T(n.by === 'policy' ? 'never' : 'deny', n.by === 'policy' ? 'blocked by policy' : saidNo)}<span class="s" title="${esc(n.what)}">${esc(n.tool)} · ${esc(n.what)}</span></div>`).join('')}</div>` : ''}
|
|
338
|
+
${s.notDone.length ? `<div class="notdone">${s.notDone.map((n) => `<div class="row">${T(n.by === 'policy' ? 'never' : 'deny', n.by === 'policy' ? 'blocked by policy' : n.by === 'timeout' ? 'nobody answered' : saidNo)}<span class="s" title="${esc(n.what)}">${esc(n.tool)} · ${esc(n.what)}</span></div>`).join('')}</div>` : ''}
|
|
339
339
|
<div class="sub">${s.head ? `Worktree now at <span class="mono">${esc(s.head)}</span>` : ''}${s.turns ? ` · ${s.turns} turns` : ''}${s.cost != null ? ` · est. $${Number(s.cost).toFixed(2)} of subscription` : ''}</div>`,
|
|
340
340
|
|
|
341
341
|
credits: () => `
|