tryharness 0.7.2 → 0.7.4
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/lib/daemon.mjs +14 -3
- package/lib/desktop.mjs +6 -1
- package/package.json +5 -5
package/lib/daemon.mjs
CHANGED
|
@@ -369,7 +369,9 @@ export async function startDaemon() {
|
|
|
369
369
|
const realDir = (dir) => { try { return fs.realpathSync(dir); } catch { return path.resolve(dir); } };
|
|
370
370
|
const within = (dir, root) => { const rel = path.relative(realDir(root), realDir(dir)); return rel === "" || (!rel.startsWith("..") && !path.isAbsolute(rel)); };
|
|
371
371
|
const aboveHome = (dir) => within(os.homedir(), dir);
|
|
372
|
-
|
|
372
|
+
// A coding agent's own scratch folder, for the person's tasks that name none: nothing of theirs is in it.
|
|
373
|
+
const scratchFolder = (agent) => path.join(paths.home, "work", agent);
|
|
374
|
+
const covers = (rule, dir) => realDir(dir) === realDir(scratchFolder(rule.agent)) || rule.workspaces.some((root) => rule.mode === "default" && aboveHome(root) ? realDir(root) === realDir(dir) : within(dir, root));
|
|
373
375
|
const standingRules = () => store.standing(runners(), startOfToday());
|
|
374
376
|
// null when the run may start now; otherwise why it waits for the person.
|
|
375
377
|
const standingVerdict = ({ trust, target, workspace }) => {
|
|
@@ -616,7 +618,12 @@ export async function startDaemon() {
|
|
|
616
618
|
// which Claude Code and Codex start in the session's folder); never home or above it.
|
|
617
619
|
const posterFolder = !request.thread && !goalParent && request.inSession !== true && POSTERS_WITH_FOLDER.has(agent) && RUNNERS.has(String(request.targetAgent || ""))
|
|
618
620
|
&& typeof request.posterCwd === "string" && path.isAbsolute(request.posterCwd) && !aboveHome(request.posterCwd) ? request.posterCwd : null;
|
|
619
|
-
|
|
621
|
+
// The person's own task for a coding agent that names no folder runs in that agent's scratch folder, so it starts like
|
|
622
|
+
// any covered run (same daily limit, same off switch) instead of waiting for a session to look at the board.
|
|
623
|
+
const target = String(request.targetAgent || "");
|
|
624
|
+
const scratch = !request.runWorkspace && !goalParent && !posterFolder && !request.thread && provenance.trust === "user" && RUNNERS.has(target) && installedAgents.includes(target) ? scratchFolder(target) : null;
|
|
625
|
+
if (scratch) fs.mkdirSync(scratch, { recursive: true });
|
|
626
|
+
const runWorkspace = request.runWorkspace ? String(request.runWorkspace) : goalParent?.goal.workspace && RUNNERS.has(target) ? goalParent.goal.workspace : posterFolder ?? scratch;
|
|
620
627
|
if (runWorkspace && !path.isAbsolute(runWorkspace)) return { ok: false, error: "a run needs an absolute workspace directory" };
|
|
621
628
|
if (runWorkspace && !request.targetAgent && !(Array.isArray(request.targetAgents) && request.targetAgents.length)) return { ok: false, error: "a run needs a target agent" };
|
|
622
629
|
const refs = Array.isArray(request.contextRefs) ? request.contextRefs.slice(0, 50) : [];
|
|
@@ -646,7 +653,8 @@ export async function startDaemon() {
|
|
|
646
653
|
}
|
|
647
654
|
const task = store.postTask({ id: request.id != null ? String(request.id) : randomUUID(), objective: objective.slice(0, 500), brief: String(request.brief || "").slice(0, 200_000),
|
|
648
655
|
originAgent: agent, provenance, targetAgent: request.targetAgent ? String(request.targetAgent) : null, parentId: request.parentId ? String(request.parentId) : null, contextRefs: refs,
|
|
649
|
-
|
|
656
|
+
// Asking for a run in a folder is the person's Start; a scratch folder they never asked for goes by standing permission.
|
|
657
|
+
runWorkspace: thread ? null : runWorkspace, runAuthorizedBy: !thread && runWorkspace && !scratch && agent === "user" ? "user" : null });
|
|
650
658
|
if (thread) store.openThread(task.id, { withAgent: String(thread.with), role: thread.role });
|
|
651
659
|
// A job in a goal's room runs on the goal's authority; anywhere else, standing permission decides.
|
|
652
660
|
const standing = thread ? undefined : goalParent ? (task.run_workspace && store.authorizeGoalRun(task.id) ? { started: true, by: "goal" } : undefined) : applyStanding(task);
|
|
@@ -777,6 +785,9 @@ export async function startDaemon() {
|
|
|
777
785
|
|
|
778
786
|
const control = net.createServer((socket) => {
|
|
779
787
|
socket.setEncoding("utf8");
|
|
788
|
+
// A caller that hung up before its answer (its own timeout, a killed hook) loses that answer; it never takes the
|
|
789
|
+
// daemon, and the runs it holds, down with it.
|
|
790
|
+
socket.on("error", () => {});
|
|
780
791
|
let buffer = "";
|
|
781
792
|
socket.on("data", (chunk) => {
|
|
782
793
|
buffer += chunk;
|
package/lib/desktop.mjs
CHANGED
|
@@ -80,7 +80,12 @@ export function canShowDesktop({ env = process.env, platform = process.platform
|
|
|
80
80
|
|
|
81
81
|
export function openDesktop({ target, platform = process.platform, execute = run }) {
|
|
82
82
|
if (platform === "darwin") {
|
|
83
|
-
|
|
83
|
+
// Just after the old copy quits, LaunchServices can still refuse (error -600) for a moment.
|
|
84
|
+
let opened = execute("open", [target]);
|
|
85
|
+
for (let i = 0; i < 20 && !opened.ok && /-600/.test(opened.stderr); i++) {
|
|
86
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 250);
|
|
87
|
+
opened = execute("open", [target]);
|
|
88
|
+
}
|
|
84
89
|
if (!opened.ok) throw new Error(opened.stderr.trim() || opened.error || "open failed");
|
|
85
90
|
return;
|
|
86
91
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tryharness",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.4",
|
|
4
4
|
"description": "Harness Relay: the daemon that turns the agents on this machine into your personal swarm. Memory, history, and work handed between any of them.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"tryharness": "cli.mjs"
|
|
@@ -35,9 +35,9 @@
|
|
|
35
35
|
"onnxruntime-web": "1.26.0-dev.20260416-b7804b056c"
|
|
36
36
|
},
|
|
37
37
|
"optionalDependencies": {
|
|
38
|
-
"tryharness-desktop-darwin-arm64": "0.7.
|
|
39
|
-
"tryharness-desktop-darwin-x64": "0.7.
|
|
40
|
-
"tryharness-desktop-linux-x64": "0.7.
|
|
41
|
-
"tryharness-desktop-win32-x64": "0.7.
|
|
38
|
+
"tryharness-desktop-darwin-arm64": "0.7.4",
|
|
39
|
+
"tryharness-desktop-darwin-x64": "0.7.4",
|
|
40
|
+
"tryharness-desktop-linux-x64": "0.7.4",
|
|
41
|
+
"tryharness-desktop-win32-x64": "0.7.4"
|
|
42
42
|
}
|
|
43
43
|
}
|