@saadnvd1/agent-os 0.3.851 → 0.3.853
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.
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import { useState } from "react";
|
|
4
|
-
import { GitFork, Square } from "lucide-react";
|
|
4
|
+
import { CircleCheck, GitFork, Square } from "lucide-react";
|
|
5
5
|
import { toast } from "sonner";
|
|
6
6
|
import { useExperiment } from "@/data/experiments";
|
|
7
7
|
import {
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
import { formatElapsed } from "@/lib/chat/elapsed";
|
|
14
14
|
import { Button } from "@/components/ui/button";
|
|
15
15
|
import { StatusPill } from "@/components/ui/status-pill";
|
|
16
|
+
import { useDoneAction } from "@/components/SessionList/useDoneAction";
|
|
16
17
|
import { SessionAnchor } from "./SessionAnchor";
|
|
17
18
|
|
|
18
19
|
type Tone = "amber" | "muted" | "green" | "primary" | "red";
|
|
@@ -73,12 +74,14 @@ export const runningNote = (c: ChildView, now = Date.now()): string | null => {
|
|
|
73
74
|
function Row({
|
|
74
75
|
c,
|
|
75
76
|
onStop,
|
|
77
|
+
onDone,
|
|
76
78
|
stopping,
|
|
77
79
|
again,
|
|
78
80
|
}: {
|
|
79
81
|
c: ChildView;
|
|
80
82
|
again: ReturnType<typeof useRunAgain>;
|
|
81
83
|
onStop: () => void;
|
|
84
|
+
onDone: () => void;
|
|
82
85
|
stopping: boolean;
|
|
83
86
|
}) {
|
|
84
87
|
const { text, tone } = stateLabel(c);
|
|
@@ -144,6 +147,16 @@ function Row({
|
|
|
144
147
|
<Square aria-hidden className="size-4" />
|
|
145
148
|
</Button>
|
|
146
149
|
)}
|
|
150
|
+
<Button
|
|
151
|
+
size="sm"
|
|
152
|
+
variant="ghost"
|
|
153
|
+
aria-label={`Mark fork ${c.n} done`}
|
|
154
|
+
data-tip="Done"
|
|
155
|
+
className="size-11 shrink-0"
|
|
156
|
+
onClick={onDone}
|
|
157
|
+
>
|
|
158
|
+
<CircleCheck aria-hidden className="size-4" />
|
|
159
|
+
</Button>
|
|
147
160
|
</li>
|
|
148
161
|
);
|
|
149
162
|
}
|
|
@@ -154,10 +167,11 @@ export function ForksStrip({ sessionId }: { sessionId: string }) {
|
|
|
154
167
|
const { data } = useForkChildren(sessionId, on);
|
|
155
168
|
const cancel = useCancelForks(sessionId);
|
|
156
169
|
const again = useRunAgain(sessionId);
|
|
170
|
+
const markDone = useDoneAction();
|
|
157
171
|
const [collapsed, setCollapsed] = useState(false);
|
|
158
172
|
if (!on || !data) return null;
|
|
159
173
|
if (data.asChild) return <ForkOfBanner info={data.asChild} />;
|
|
160
|
-
const
|
|
174
|
+
const children = data.children.filter((c) => !c.done);
|
|
161
175
|
if (!children.length) return null;
|
|
162
176
|
const open = children.filter((c) => c.state !== "settled").length;
|
|
163
177
|
const stop = (ref?: string) =>
|
|
@@ -206,6 +220,14 @@ export function ForksStrip({ sessionId }: { sessionId: string }) {
|
|
|
206
220
|
stopping={cancel.isPending}
|
|
207
221
|
again={again}
|
|
208
222
|
onStop={() => stop(String(c.n))}
|
|
223
|
+
onDone={() =>
|
|
224
|
+
markDone({
|
|
225
|
+
id: c.id,
|
|
226
|
+
name: c.label,
|
|
227
|
+
task_status: null,
|
|
228
|
+
pr_status: null,
|
|
229
|
+
})
|
|
230
|
+
}
|
|
209
231
|
/>
|
|
210
232
|
))}
|
|
211
233
|
</ul>
|
|
@@ -9,12 +9,18 @@ import {
|
|
|
9
9
|
} from "@/data/done";
|
|
10
10
|
import { useSettleSession } from "@/data/sessions/shelf";
|
|
11
11
|
|
|
12
|
+
export type DoneTarget = Pick<
|
|
13
|
+
Session,
|
|
14
|
+
"id" | "name" | "task_status" | "pr_status"
|
|
15
|
+
> &
|
|
16
|
+
Partial<Pick<Session, "settled_at">>;
|
|
17
|
+
|
|
12
18
|
// Done from a session's menu: an open PR merges through the gates, after an
|
|
13
19
|
// in-app confirmation; a failing gate comes back as an error toast naming it.
|
|
14
20
|
export function useDoneAction() {
|
|
15
21
|
const done = useDoneSession();
|
|
16
22
|
const settle = useSettleSession();
|
|
17
|
-
const run = (session:
|
|
23
|
+
const run = (session: DoneTarget, merges: boolean) => {
|
|
18
24
|
const id = toast.loading(
|
|
19
25
|
merges ? `Merging ${session.name}…` : `Finishing ${session.name}…`
|
|
20
26
|
);
|
|
@@ -38,7 +44,7 @@ export function useDoneAction() {
|
|
|
38
44
|
onError: (e) => toast.error(e.message, { id, duration: 12000 }),
|
|
39
45
|
});
|
|
40
46
|
};
|
|
41
|
-
return (session:
|
|
47
|
+
return (session: DoneTarget) => {
|
|
42
48
|
const merges =
|
|
43
49
|
session.task_status === "running" && session.pr_status === "open";
|
|
44
50
|
if (!merges) return run(session, false);
|
package/content/whats-new.json
CHANGED
|
@@ -2033,6 +2033,14 @@
|
|
|
2033
2033
|
"area": "Updates",
|
|
2034
2034
|
"text": "You can update AgentOS by hand again on machines that deploy themselves, and Update now skips the hourly wait.",
|
|
2035
2035
|
"url": "https://github.com/saadnvd1/agent-os/pull/571"
|
|
2036
|
+
},
|
|
2037
|
+
{
|
|
2038
|
+
"id": 573,
|
|
2039
|
+
"date": "2026-11-02",
|
|
2040
|
+
"kind": "new",
|
|
2041
|
+
"area": "AgentOS",
|
|
2042
|
+
"text": "Mark a fork as done straight from the Forks list above the chat box.",
|
|
2043
|
+
"url": "https://github.com/saadnvd1/agent-os/pull/573"
|
|
2036
2044
|
}
|
|
2037
2045
|
]
|
|
2038
2046
|
}
|
package/data/done/index.ts
CHANGED
|
@@ -5,6 +5,7 @@ import type { ArchivedView } from "@/lib/done/archive";
|
|
|
5
5
|
import type { ResurrectOutcome } from "@/lib/resurrect";
|
|
6
6
|
import { sessionKeys } from "../sessions/keys";
|
|
7
7
|
import { taskKeys } from "../tasks";
|
|
8
|
+
import { forkKeys } from "../fork";
|
|
8
9
|
|
|
9
10
|
export const archivedKeys = {
|
|
10
11
|
all: ["archived-sessions"] as const,
|
|
@@ -52,7 +53,12 @@ function useDoneMutation<V, R>(fn: (v: V) => Promise<R>) {
|
|
|
52
53
|
return useMutation({
|
|
53
54
|
mutationFn: fn,
|
|
54
55
|
onSettled: () => {
|
|
55
|
-
for (const queryKey of [
|
|
56
|
+
for (const queryKey of [
|
|
57
|
+
sessionKeys.all,
|
|
58
|
+
taskKeys.all,
|
|
59
|
+
archivedKeys.all,
|
|
60
|
+
forkKeys.all,
|
|
61
|
+
])
|
|
56
62
|
queryClient.invalidateQueries({ queryKey });
|
|
57
63
|
},
|
|
58
64
|
});
|
package/lib/fork/types.ts
CHANGED
|
@@ -65,6 +65,8 @@ export interface ChildView {
|
|
|
65
65
|
excerpt: string | null;
|
|
66
66
|
resultKind: ResultKind | null;
|
|
67
67
|
worktree: boolean;
|
|
68
|
+
// Marked done or archived as a session: it leaves the strip.
|
|
69
|
+
done: boolean;
|
|
68
70
|
fellBack: boolean;
|
|
69
71
|
startedAt: number | null;
|
|
70
72
|
settledAt: number | null;
|
package/lib/fork/view.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/** What clients and `aos children` show, and the numbers behind them. */
|
|
2
2
|
|
|
3
3
|
import { lastItems } from "../chat/store";
|
|
4
|
+
import { db } from "../db";
|
|
4
5
|
import { childrenOf, getGroup } from "./ledger";
|
|
5
6
|
import type { ChildRow, ChildView, GroupView } from "./types";
|
|
6
7
|
|
|
@@ -17,6 +18,7 @@ export const childView = (c: ChildRow): ChildView => ({
|
|
|
17
18
|
excerpt: c.result ? c.result.slice(0, 600) : null,
|
|
18
19
|
resultKind: c.result_kind,
|
|
19
20
|
worktree: !!c.worktree,
|
|
21
|
+
done: false,
|
|
20
22
|
fellBack: !!c.fell_back,
|
|
21
23
|
startedAt: c.started_at,
|
|
22
24
|
settledAt: c.settled_at,
|
|
@@ -32,6 +34,13 @@ const activityOf = (c: ChildRow): string | null => {
|
|
|
32
34
|
return tool && tool.kind === "tool" ? tool.title : null;
|
|
33
35
|
};
|
|
34
36
|
|
|
37
|
+
const isDone = (id: string): boolean =>
|
|
38
|
+
!!db
|
|
39
|
+
.prepare(
|
|
40
|
+
`SELECT 1 FROM sessions WHERE id = ? AND (settled_at IS NOT NULL OR archived_at IS NOT NULL)`
|
|
41
|
+
)
|
|
42
|
+
.get(id);
|
|
43
|
+
|
|
35
44
|
export function childrenView(parentId: string): {
|
|
36
45
|
children: ChildView[];
|
|
37
46
|
groups: GroupView[];
|
|
@@ -57,6 +66,7 @@ export function childrenView(parentId: string): {
|
|
|
57
66
|
children: rows.map((c, i) => ({
|
|
58
67
|
...childView(c),
|
|
59
68
|
n: i + 1,
|
|
69
|
+
done: isDone(c.child_session_id),
|
|
60
70
|
activity: activityOf(c),
|
|
61
71
|
})),
|
|
62
72
|
groups,
|