@saadnvd1/agent-os 0.3.766 → 0.3.768
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.
|
@@ -25,7 +25,7 @@ import { getProject } from "../../projects";
|
|
|
25
25
|
import { planFor, splitOf } from "../../plans/features";
|
|
26
26
|
import { moveTask } from "../move-flow";
|
|
27
27
|
import * as client from "./client";
|
|
28
|
-
import { meetsNeeds, needsOf } from "../placement";
|
|
28
|
+
import { meetsNeeds, needsOf, taskPinnedToMac } from "../placement";
|
|
29
29
|
import { remotePlanPath } from "./plan-path";
|
|
30
30
|
import { DEFAULT_PRIORITY, isPriority } from "../schedule-types";
|
|
31
31
|
import { localHolds } from "../hold-checks";
|
|
@@ -55,6 +55,9 @@ function checkedSplit(s: Session, text: string | null) {
|
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
const pinned = (s: Session, project: { working_directory: string }) =>
|
|
59
|
+
taskPinnedToMac(s.id, expandHome(project.working_directory));
|
|
60
|
+
|
|
58
61
|
/**
|
|
59
62
|
* Where a written plan is built: "there" (approved on the machine that
|
|
60
63
|
* planned it) or "home" (moved here first). Pieces are checked against this
|
|
@@ -70,6 +73,9 @@ export function implementTarget(
|
|
|
70
73
|
// The project lives there: nothing here to build it in.
|
|
71
74
|
if (!project || isRemoteHost(project.host_id)) return "there";
|
|
72
75
|
if (split) return "home";
|
|
76
|
+
// An explicit Mac pin builds on the Mac, wherever the plan ran.
|
|
77
|
+
if (pinned(s, project))
|
|
78
|
+
return meetsNeeds(["mac"], machineCapabilities()) ? "home" : "there";
|
|
73
79
|
const { needs } = needsOf({
|
|
74
80
|
projectId: project.id,
|
|
75
81
|
projectPath: expandHome(project.working_directory),
|
|
@@ -229,6 +235,7 @@ export async function handoffHome(
|
|
|
229
235
|
projectPath: expandHome(project.working_directory),
|
|
230
236
|
prompt: s.task_prompt ?? "",
|
|
231
237
|
});
|
|
238
|
+
if (pinned(s, project) && !needs.includes("mac")) needs.push("mac");
|
|
232
239
|
const holds = localHolds(
|
|
233
240
|
{
|
|
234
241
|
needs,
|
package/lib/tasks/placement.ts
CHANGED
|
@@ -79,6 +79,28 @@ export function inferNeeds(projectPath: string): Need[] {
|
|
|
79
79
|
return [];
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
+
// Whether the starter asked for a Mac outright: the request's `machine`
|
|
83
|
+
// (stored on the queue row, which shares the task's id), a recipe's, or the
|
|
84
|
+
// project's own machine setting. A need read from the brief or the files
|
|
85
|
+
// doesn't count: that one a plan can ignore.
|
|
86
|
+
export function pinnedToMac(
|
|
87
|
+
stored: string | null,
|
|
88
|
+
projectPath: string
|
|
89
|
+
): boolean {
|
|
90
|
+
const asked = parseNeeds(stored);
|
|
91
|
+
if (asked) return asked.includes("mac");
|
|
92
|
+
return !!loadProjectConfig(projectPath).config.machine?.needs?.includes(
|
|
93
|
+
"mac"
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export function taskPinnedToMac(taskId: string, projectPath: string): boolean {
|
|
98
|
+
const row = db
|
|
99
|
+
.prepare(`SELECT machine_needs FROM task_queue WHERE id = ?`)
|
|
100
|
+
.get(taskId) as { machine_needs: string | null } | undefined;
|
|
101
|
+
return pinnedToMac(row?.machine_needs ?? null, projectPath);
|
|
102
|
+
}
|
|
103
|
+
|
|
82
104
|
export function needsOf(input: {
|
|
83
105
|
projectId: string;
|
|
84
106
|
projectPath: string;
|
|
@@ -13,6 +13,7 @@ import { usesGitCrypt } from "../worktree-add";
|
|
|
13
13
|
import { list as hostTasks } from "./contract/client";
|
|
14
14
|
import {
|
|
15
15
|
asPlanPhase,
|
|
16
|
+
pinnedToMac,
|
|
16
17
|
place,
|
|
17
18
|
unplaceable,
|
|
18
19
|
wantsPlacing,
|
|
@@ -90,11 +91,22 @@ async function peerOptions(
|
|
|
90
91
|
return out;
|
|
91
92
|
}
|
|
92
93
|
|
|
93
|
-
// A start that plans first goes by its plan phase: it needs no
|
|
94
|
-
// simulator, and a plan-only one that no machine can take starts here
|
|
94
|
+
// A start that plans first goes by its plan phase: it needs no simulator, and a plan-only one that no machine can take starts here
|
|
95
95
|
// as ever (it never waits on load).
|
|
96
96
|
const plansFirst = (r: QueueRow) => !!(r.plan || r.plan_only);
|
|
97
97
|
|
|
98
|
+
// Planning needs no simulator or Xcode, and a need read from the files or the
|
|
99
|
+
// brief doesn't hold it. Only an explicit Mac pin does: the work is Mac-only
|
|
100
|
+
// (often because the other machine can't reach what it touches).
|
|
101
|
+
const planNeeds = (r: QueueRow, needs: Need[]): Need[] => {
|
|
102
|
+
const project = getProject(r.project_id);
|
|
103
|
+
return project &&
|
|
104
|
+
needs.includes("mac") &&
|
|
105
|
+
pinnedToMac(r.machine_needs, expandHome(project.working_directory))
|
|
106
|
+
? ["mac"]
|
|
107
|
+
: [];
|
|
108
|
+
};
|
|
109
|
+
|
|
98
110
|
// Marks each start the home machine's load rules out as remote and returns
|
|
99
111
|
// where it goes. "stale": the line moved while the machines were asked, so
|
|
100
112
|
// this look is over, and the one a change during it asks for sees the line
|
|
@@ -143,7 +155,7 @@ export async function placeCandidates(
|
|
|
143
155
|
asked(c),
|
|
144
156
|
home,
|
|
145
157
|
options,
|
|
146
|
-
plan ? [] : (needsOf.get(c.id) ?? []),
|
|
158
|
+
plan ? planNeeds(r, needsOf.get(c.id) ?? []) : (needsOf.get(c.id) ?? []),
|
|
147
159
|
now
|
|
148
160
|
);
|
|
149
161
|
if (!spot) continue;
|