@saadnvd1/agent-os 0.3.592 → 0.3.595
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/app/api/bus/resurrect/route.test.ts +47 -0
- package/app/api/bus/resurrect/route.ts +36 -0
- package/app/api/sessions/[id]/pause/route.ts +5 -2
- package/app/api/sessions/[id]/resurrect/route.test.ts +32 -0
- package/app/api/sessions/[id]/resurrect/route.ts +24 -0
- package/app/api/sessions/ended/route.ts +19 -0
- package/components/Archived/ArchivedRow.tsx +11 -7
- package/components/Chat/PausedBanner.tsx +1 -1
- package/components/Providers.tsx +5 -1
- package/components/SessionList/LiveLine.tsx +1 -1
- package/components/SessionList/OrchestratorPinRow.tsx +10 -5
- package/components/SessionList/QuickChangeRow.tsx +1 -1
- package/components/SessionList/RowParts.tsx +37 -2
- package/components/SessionList/RowShell.tsx +6 -2
- package/components/SessionList/RowSubtitle.tsx +20 -12
- package/components/SessionList/SessionRow.tsx +28 -17
- package/components/SessionList/SessionRowMenu.tsx +12 -1
- package/components/SessionList/SessionShelves.tsx +40 -8
- package/components/SessionList/SidebarExtras.tsx +7 -1
- package/components/SessionList/index.tsx +2 -0
- package/components/SessionList/useDoneAction.ts +14 -0
- package/components/SessionList/useResurrectAction.test.ts +96 -0
- package/components/SessionList/useSessionTips.ts +62 -0
- package/components/Tasks/TaskRow.tsx +18 -0
- package/components/ui/HoverTip.tsx +20 -0
- package/data/done/index.ts +17 -0
- package/data/presence/index.ts +14 -7
- package/lib/db/migrations.ts +11 -0
- package/lib/db/types.ts +2 -0
- package/lib/done/worktree.ts +18 -2
- package/lib/hover-tip.ts +161 -0
- package/lib/orchestrator/act.ts +44 -5
- package/lib/orchestrator/brief.ts +2 -1
- package/lib/orchestrator/digest.ts +3 -2
- package/lib/orchestrator/serve.ts +6 -0
- package/lib/orchestrator/shell-guard.ts +2 -1
- package/lib/orchestrator/tool-names.ts +1 -0
- package/lib/orchestrator/tool-schemas.ts +6 -0
- package/lib/orchestrator/tools.ts +3 -1
- package/lib/resurrect/find.ts +111 -0
- package/lib/resurrect/index.ts +422 -0
- package/lib/resurrect/plan.ts +61 -0
- package/lib/resurrect/snapshot.ts +229 -0
- package/lib/security/demo.ts +1 -0
- package/lib/sidebar/paused.ts +8 -1
- package/lib/sidebar/row-actions.ts +7 -3
- package/lib/sidebar/row-badge.ts +40 -0
- package/lib/sidebar/row-details.ts +53 -0
- package/lib/sidebar/shelves.ts +7 -1
- package/lib/tasks/auto-hold.ts +17 -0
- package/lib/tasks/finish.ts +9 -0
- package/lib/tasks/pause-hold.ts +1 -1
- package/lib/tasks/pause.ts +76 -8
- package/lib/tasks/queue.ts +39 -12
- package/package.json +1 -1
package/lib/tasks/queue.ts
CHANGED
|
@@ -22,6 +22,7 @@ import { getProject } from "../projects";
|
|
|
22
22
|
import { isRemoteHost } from "../hosts";
|
|
23
23
|
import { getWorkspace } from "../workspaces";
|
|
24
24
|
import { isPaused } from "../orchestrator/pause";
|
|
25
|
+
import { autoHold } from "./auto-hold";
|
|
25
26
|
import {
|
|
26
27
|
BrakeRefused,
|
|
27
28
|
braked,
|
|
@@ -77,7 +78,13 @@ import { peerReading, peerSource, refreshPeers } from "../hosts/peer-load";
|
|
|
77
78
|
import { hostLink, linkedHostIds } from "../hosts/remote-api";
|
|
78
79
|
import { hostTasks } from "./remote";
|
|
79
80
|
import { projectMachines } from "../hosts/project-machines";
|
|
80
|
-
import {
|
|
81
|
+
import {
|
|
82
|
+
type DueResume,
|
|
83
|
+
claimResume,
|
|
84
|
+
dueResumes,
|
|
85
|
+
resumeHoldFor,
|
|
86
|
+
setPauseNote,
|
|
87
|
+
} from "./pause";
|
|
81
88
|
|
|
82
89
|
export type QueueStatus =
|
|
83
90
|
| "queued"
|
|
@@ -562,16 +569,6 @@ const sqliteMs = (v: string) =>
|
|
|
562
569
|
export const queuedView = (id: string) =>
|
|
563
570
|
listQueue().find((q) => q.id === id) ?? null;
|
|
564
571
|
|
|
565
|
-
// Why an automatic start has to wait, or null. A start now by a person
|
|
566
|
-
// isn't held.
|
|
567
|
-
function autoHold(workspaceId: string | null, planOnly = false): Hold | null {
|
|
568
|
-
if (workspaceId && isPaused(workspaceId))
|
|
569
|
-
return { code: "orch_paused", text: "Waiting: the orchestrator is paused" };
|
|
570
|
-
if (planOnly) return null;
|
|
571
|
-
const window = brakesEnabled() ? windowRefusal(readUsage()) : null;
|
|
572
|
-
return window ? { code: "window", text: `Waiting: ${window}` } : null;
|
|
573
|
-
}
|
|
574
|
-
|
|
575
572
|
const requestNeeds = (
|
|
576
573
|
projectId: string,
|
|
577
574
|
workingDirectory: string,
|
|
@@ -959,7 +956,18 @@ export async function tickOnce(now = Date.now()): Promise<"stale" | void> {
|
|
|
959
956
|
WHERE q.status IN ('queued', 'starting') ORDER BY q.position`
|
|
960
957
|
)
|
|
961
958
|
.all() as QueueRowWithWorkspace[];
|
|
962
|
-
const
|
|
959
|
+
const due = dueResumes();
|
|
960
|
+
// A deliberate resume starts past the slot limit; only a red machine holds
|
|
961
|
+
// it, and the task says so.
|
|
962
|
+
for (const d of due.filter((x) => x.resumeBy)) {
|
|
963
|
+
const s = db
|
|
964
|
+
.prepare(`SELECT * FROM sessions WHERE id = ?`)
|
|
965
|
+
.get(d.sessionId) as Session | undefined;
|
|
966
|
+
const why = s ? resumeHoldFor(s, d.resumeBy!) : null;
|
|
967
|
+
if (why) setPauseNote(d.sessionId, `held: ${why}`);
|
|
968
|
+
else await claimResume(d.sessionId, { reason: d.resumeBy!, force: true });
|
|
969
|
+
}
|
|
970
|
+
const resumes = due.filter((x) => !x.resumeBy);
|
|
963
971
|
if (!rows.length && !resumes.length) return;
|
|
964
972
|
const queued = rows.filter((r) => r.status === "queued");
|
|
965
973
|
const used = usedFinishes();
|
|
@@ -1051,6 +1059,11 @@ export async function tickOnce(now = Date.now()): Promise<"stale" | void> {
|
|
|
1051
1059
|
const plan = planStarts(candidates, groups, home, now);
|
|
1052
1060
|
for (const r of queued)
|
|
1053
1061
|
noteWaiting(r, withStayReason(r, plan.explain.get(r.id)));
|
|
1062
|
+
for (const d of resumes)
|
|
1063
|
+
setPauseNote(
|
|
1064
|
+
d.sessionId,
|
|
1065
|
+
resumeWaitNote(d, plan.explain.get(`resume:${d.sessionId}`))
|
|
1066
|
+
);
|
|
1054
1067
|
|
|
1055
1068
|
for (const id of plan.start) {
|
|
1056
1069
|
if (id.startsWith("resume:")) {
|
|
@@ -1067,6 +1080,20 @@ export async function tickOnce(now = Date.now()): Promise<"stale" | void> {
|
|
|
1067
1080
|
}
|
|
1068
1081
|
}
|
|
1069
1082
|
|
|
1083
|
+
// What a timed resume still waiting for its turn says on its task.
|
|
1084
|
+
function resumeWaitNote(
|
|
1085
|
+
d: DueResume,
|
|
1086
|
+
explain: { code: WaitCode | null; text: string | null } | undefined
|
|
1087
|
+
): string | null {
|
|
1088
|
+
if (!explain) return null;
|
|
1089
|
+
if (explain.code && explain.code !== "slot" && explain.text)
|
|
1090
|
+
return `held: ${explain.text.replace(/^Waiting: /, "")}`;
|
|
1091
|
+
const slots = slotState(d.projectId);
|
|
1092
|
+
return slots.limit === null
|
|
1093
|
+
? "resuming: waiting for its turn"
|
|
1094
|
+
: `resuming: waiting for a slot, ${slots.running} of ${slots.limit} running`;
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1070
1097
|
// Writes why a row waits when that changed: its hold text and code. A bare
|
|
1071
1098
|
// rank isn't stored (the view computes it), so the stream stays quiet.
|
|
1072
1099
|
const MACHINE_HOLDS = new Set<WaitCode>([
|