@saadnvd1/agent-os 0.3.684 → 0.3.691
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/dev-servers/detect/route.ts +1 -2
- package/app/api/projects/[id]/dev-servers/[dsId]/route.ts +2 -4
- package/app/page.tsx +1 -2
- package/components/Artifacts/ArtifactsPanel.tsx +1 -1
- package/components/FileExplorer/FileTabs.tsx +1 -1
- package/components/Pane/DesktopTabBar.tsx +2 -2
- package/components/QuickSwitcher.tsx +24 -21
- package/components/SessionList/SessionRowMenu.tsx +0 -1
- package/components/Settings/ExperimentsSection.test.ts +7 -1
- package/components/Settings/NoApprovalsSection.test.ts +7 -1
- package/components/Terminal/TerminalToolbar.tsx +1 -1
- package/components/Terminal/VirtualKeyboard.tsx +1 -1
- package/components/WorkerCard.tsx +1 -7
- package/components/Workspaces/WorkspaceNameDialog.tsx +5 -3
- package/components/a/AButton.tsx +1 -6
- package/components/a/AIconButton.tsx +1 -5
- package/contexts/PaneContext.tsx +1 -6
- package/data/lumifyhub/index.ts +2 -4
- package/hooks/useDirectoryBrowser.ts +5 -4
- package/hooks/useDrawerAnimation.ts +11 -14
- package/hooks/useFileDrop.ts +2 -6
- package/hooks/useKeybarVisibility.ts +10 -29
- package/hooks/useSidebarPinned.ts +7 -23
- package/hooks/useSpeechRecognition.ts +19 -5
- package/hooks/useStoredFlag.ts +47 -0
- package/hooks/useViewport.ts +11 -17
- package/lib/approvals/no-approvals.ts +1 -7
- package/lib/artifacts/store.ts +1 -2
- package/lib/away/report.ts +1 -2
- package/lib/away/run.ts +1 -2
- package/lib/away/state.ts +1 -2
- package/lib/bookmarks/store.ts +1 -2
- package/lib/bus/delivery.ts +1 -2
- package/lib/bus/index.ts +1 -2
- package/lib/chat/compact-context.ts +1 -2
- package/lib/chat/stop.ts +1 -2
- package/lib/chat/worker/host.ts +1 -1
- package/lib/code-health/reports.ts +1 -2
- package/lib/db/lumifyhub.ts +2 -4
- package/lib/db/schedules-move.ts +1 -2
- package/lib/db/session-parts/tasks.ts +1 -2
- package/lib/db/stacks.ts +3 -9
- package/lib/db/types.ts +1 -7
- package/lib/doctor/checks.ts +7 -9
- package/lib/done/archive.ts +1 -2
- package/lib/experiments/meter.ts +1 -7
- package/lib/health/env/classes.ts +0 -2
- package/lib/health/env/recordHit.ts +1 -2
- package/lib/health/spin.ts +1 -4
- package/lib/health/store.ts +1 -2
- package/lib/hosts/index.ts +1 -2
- package/lib/hosts/peer-sync.ts +2 -4
- package/lib/hosts/remote-api.ts +1 -2
- package/lib/lumifyhub/types.ts +2 -8
- package/lib/notify/index.ts +1 -2
- package/lib/notify/push/index.ts +2 -7
- package/lib/orchestrator/external-pr.ts +1 -2
- package/lib/orchestrator/gates.ts +1 -6
- package/lib/orchestrator/needs-you-items.ts +16 -20
- package/lib/orchestrator/pr-wake.ts +1 -2
- package/lib/orchestrator/rebase.ts +1 -2
- package/lib/orchestrator/review.ts +1 -2
- package/lib/orchestrator/usage.ts +1 -2
- package/lib/plans/claim.ts +1 -2
- package/lib/plans/features.ts +4 -11
- package/lib/plans/release.ts +2 -4
- package/lib/ports.ts +1 -2
- package/lib/program-status/records.ts +1 -1
- package/lib/project-config/database.ts +1 -2
- package/lib/projects.ts +1 -2
- package/lib/recipes/settle.ts +2 -4
- package/lib/recipes/store.ts +2 -4
- package/lib/schedules/store.ts +2 -4
- package/lib/search/conversations/backfill.ts +2 -4
- package/lib/security/auth.ts +1 -2
- package/lib/security/passkeys.ts +1 -2
- package/lib/security/presence.ts +1 -7
- package/lib/session-artifacts/types.ts +1 -8
- package/lib/session-audit/transcript.ts +1 -3
- package/lib/session-logs/index.ts +1 -2
- package/lib/sessions/launch.ts +1 -2
- package/lib/share/snapshot.ts +1 -7
- package/lib/share/store.ts +1 -2
- package/lib/sidebar/orchestrator-row.ts +1 -6
- package/lib/sidebar/row-menu.ts +1 -2
- package/lib/sidebar/shelves.ts +1 -6
- package/lib/simulator/index.ts +1 -2
- package/lib/simulator/lease.ts +1 -5
- package/lib/stacks/index.ts +1 -1
- package/lib/stacks/plan.ts +1 -1
- package/lib/stacks/restack.ts +1 -2
- package/lib/stacks/tick.ts +1 -2
- package/lib/status/socket.ts +1 -2
- package/lib/tasks/contract/authorize.ts +1 -2
- package/lib/tasks/contract/plan.ts +1 -2
- package/lib/tasks/contract/sync.ts +1 -2
- package/lib/tasks/holds.ts +1 -5
- package/lib/tasks/index.ts +1 -2
- package/lib/tasks/loop-types.ts +1 -6
- package/lib/tasks/move-guard.ts +1 -2
- package/lib/tasks/move.ts +1 -2
- package/lib/tasks/moved-away.ts +1 -2
- package/lib/tasks/pause-hold.ts +1 -2
- package/lib/tasks/pause.ts +3 -6
- package/lib/tasks/pr-activity.ts +1 -3
- package/lib/tasks/queue-rows.ts +2 -4
- package/lib/tasks/queue-types.ts +1 -5
- package/lib/tasks/queue.ts +1 -2
- package/lib/tasks/refresh-base.ts +1 -2
- package/lib/tasks/start.ts +2 -4
- package/lib/tasks/starter.ts +1 -2
- package/lib/tasks/state.ts +1 -6
- package/lib/theme-config.ts +1 -8
- package/lib/updates/banner.ts +1 -6
- package/lib/updates/run.ts +1 -2
- package/lib/usage/aggregate.ts +1 -1
- package/lib/usage/nightly.ts +1 -2
- package/lib/usage/rate-limits.ts +1 -2
- package/lib/usage/turns.ts +1 -2
- package/lib/usage/windows.ts +5 -7
- package/lib/workspaces.ts +1 -2
- package/lib/worktree-sweep/databases.ts +0 -1
- package/package.json +3 -3
package/lib/away/run.ts
CHANGED
|
@@ -70,8 +70,7 @@ function orchestrated(): { workspaceId: string; orchestratorId: string }[] {
|
|
|
70
70
|
|
|
71
71
|
const sessionRow = (id: string) =>
|
|
72
72
|
db.prepare(`SELECT * FROM session_rows WHERE id = ?`).get(id) as
|
|
73
|
-
|
|
|
74
|
-
| undefined;
|
|
73
|
+
Session | undefined;
|
|
75
74
|
|
|
76
75
|
// Away mode reaches a workspace only through an orchestrator that's been
|
|
77
76
|
// working inside the window: one left alone isn't told or woken.
|
package/lib/away/state.ts
CHANGED
|
@@ -43,8 +43,7 @@ export function activeAway(): AwayRow | null {
|
|
|
43
43
|
export function getAway(id: number): AwayRow | null {
|
|
44
44
|
return (
|
|
45
45
|
(db.prepare(`SELECT * FROM away_periods WHERE id = ?`).get(id) as
|
|
46
|
-
|
|
|
47
|
-
| undefined) ?? null
|
|
46
|
+
AwayRow | undefined) ?? null
|
|
48
47
|
);
|
|
49
48
|
}
|
|
50
49
|
|
package/lib/bookmarks/store.ts
CHANGED
|
@@ -83,8 +83,7 @@ function toBookmark(r: Joined): Bookmark {
|
|
|
83
83
|
|
|
84
84
|
export function getBookmark(id: string): Bookmark | null {
|
|
85
85
|
const r = db.prepare(`${SELECT} WHERE b.id = ?`).get(id) as
|
|
86
|
-
|
|
|
87
|
-
| undefined;
|
|
86
|
+
Joined | undefined;
|
|
88
87
|
return r ? toBookmark(r) : null;
|
|
89
88
|
}
|
|
90
89
|
|
package/lib/bus/delivery.ts
CHANGED
|
@@ -7,8 +7,7 @@ import { WORKING_LINE } from "../claude-working-line";
|
|
|
7
7
|
|
|
8
8
|
export type DeliveryState = "delivered" | "queued" | "failed";
|
|
9
9
|
export type Delivery =
|
|
10
|
-
|
|
11
|
-
| { state: "failed"; why: string };
|
|
10
|
+
{ state: "delivered" | "queued" } | { state: "failed"; why: string };
|
|
12
11
|
|
|
13
12
|
export interface PaneView {
|
|
14
13
|
text: string;
|
package/lib/bus/index.ts
CHANGED
|
@@ -70,8 +70,7 @@ function candidates(sessions: Session[]): Candidate[] {
|
|
|
70
70
|
const sessionById = (id: string | null | undefined) =>
|
|
71
71
|
id
|
|
72
72
|
? (db.prepare(`SELECT * FROM session_rows WHERE id = ?`).get(id) as
|
|
73
|
-
|
|
|
74
|
-
| undefined)
|
|
73
|
+
Session | undefined)
|
|
75
74
|
: undefined;
|
|
76
75
|
|
|
77
76
|
// A chat has no pane: its worker is the state, and it can always take a
|
|
@@ -31,8 +31,7 @@ export async function compactContext(sessionId: string): Promise<string> {
|
|
|
31
31
|
`SELECT working_directory, task_prompt, role FROM session_rows WHERE id = ?`
|
|
32
32
|
)
|
|
33
33
|
.get(sessionId) as
|
|
34
|
-
|
|
35
|
-
| undefined;
|
|
34
|
+
Pick<Session, "working_directory" | "task_prompt" | "role"> | undefined;
|
|
36
35
|
// An orchestrator starts fresh instead of compacting.
|
|
37
36
|
if (!session || session.role === "orchestrator") return "";
|
|
38
37
|
const tools = lastItems(sessionId, 400, "tool").filter(
|
package/lib/chat/stop.ts
CHANGED
|
@@ -70,8 +70,7 @@ export async function stopChatAtTurnEnd(
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
export type TurnStop =
|
|
73
|
-
|
|
74
|
-
| { stopped: false; reason: string };
|
|
73
|
+
{ stopped: true; killed: boolean } | { stopped: false; reason: string };
|
|
75
74
|
|
|
76
75
|
export interface TurnStopOptions {
|
|
77
76
|
// How long the turn gets to end after the interrupt before its agent is
|
package/lib/chat/worker/host.ts
CHANGED
|
@@ -20,8 +20,7 @@ interface NpmVuln {
|
|
|
20
20
|
isDirect?: boolean;
|
|
21
21
|
via?: (string | { title?: string; source?: number })[];
|
|
22
22
|
fixAvailable?:
|
|
23
|
-
| boolean
|
|
24
|
-
| { name?: string; version?: string; isSemVerMajor?: boolean };
|
|
23
|
+
boolean | { name?: string; version?: string; isSemVerMajor?: boolean };
|
|
25
24
|
}
|
|
26
25
|
|
|
27
26
|
interface PnpmAdvisory {
|
package/lib/db/lumifyhub.ts
CHANGED
|
@@ -24,8 +24,7 @@ export const ATTEMPT_TTL_MINUTES = 10;
|
|
|
24
24
|
export const lumifyhubQueries = {
|
|
25
25
|
getConnection: (db: Database.Database) =>
|
|
26
26
|
(db.prepare(`SELECT * FROM lumifyhub_connection WHERE id = 1`).get() as
|
|
27
|
-
|
|
|
28
|
-
| undefined) ?? null,
|
|
27
|
+
LumifyHubConnection | undefined) ?? null,
|
|
29
28
|
|
|
30
29
|
saveConnection: (
|
|
31
30
|
db: Database.Database,
|
|
@@ -65,8 +64,7 @@ export const lumifyhubQueries = {
|
|
|
65
64
|
FROM lumifyhub_connect_attempts WHERE state = ?`
|
|
66
65
|
)
|
|
67
66
|
.get(`-${ATTEMPT_TTL_MINUTES} minutes`, state) as
|
|
68
|
-
|
|
69
|
-
| undefined;
|
|
67
|
+
(LumifyHubConnectAttempt & { fresh: number }) | undefined;
|
|
70
68
|
db.prepare(`DELETE FROM lumifyhub_connect_attempts WHERE state = ?`).run(
|
|
71
69
|
state
|
|
72
70
|
);
|
package/lib/db/schedules-move.ts
CHANGED
|
@@ -200,8 +200,7 @@ export function revertSchedulesMove(db: Database.Database): {
|
|
|
200
200
|
for (const s of moved) {
|
|
201
201
|
const r = s.recipe_id
|
|
202
202
|
? (recipe.get(s.recipe_id) as
|
|
203
|
-
|
|
204
|
-
| undefined)
|
|
203
|
+
{ brief: string; project_id: string } | undefined)
|
|
205
204
|
: undefined;
|
|
206
205
|
restore.run(
|
|
207
206
|
s.migrated_from_kind,
|
|
@@ -20,8 +20,7 @@ export function startTaskClock(
|
|
|
20
20
|
const row = db
|
|
21
21
|
.prepare(`SELECT created_at, task_since FROM session_rows WHERE id = ?`)
|
|
22
22
|
.get(sessionId) as
|
|
23
|
-
|
|
24
|
-
| undefined;
|
|
23
|
+
{ created_at: string; task_since: string | null } | undefined;
|
|
25
24
|
if (!row || row.task_since) return;
|
|
26
25
|
setTask(db, sessionId, { task_since: at ?? row.created_at });
|
|
27
26
|
}
|
package/lib/db/stacks.ts
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import type Database from "better-sqlite3";
|
|
2
2
|
|
|
3
3
|
export type StackStatus =
|
|
4
|
-
| "
|
|
5
|
-
| "paused"
|
|
6
|
-
| "landing"
|
|
7
|
-
| "landed"
|
|
8
|
-
| "failed";
|
|
4
|
+
"running" | "paused" | "landing" | "landed" | "failed";
|
|
9
5
|
|
|
10
6
|
export type StackItemStatus =
|
|
11
7
|
| "planned"
|
|
@@ -131,8 +127,7 @@ export const stackQueries = {
|
|
|
131
127
|
|
|
132
128
|
get: (db: Database.Database, id: string) =>
|
|
133
129
|
(db.prepare(`SELECT * FROM stacks WHERE id = ?`).get(id) as
|
|
134
|
-
|
|
|
135
|
-
| undefined) ?? null,
|
|
130
|
+
StackRow | undefined) ?? null,
|
|
136
131
|
|
|
137
132
|
// The board's stack that has not finished yet, if any.
|
|
138
133
|
openForBoard: (db: Database.Database, boardId: string) =>
|
|
@@ -150,8 +145,7 @@ export const stackQueries = {
|
|
|
150
145
|
|
|
151
146
|
item: (db: Database.Database, id: string) =>
|
|
152
147
|
(db.prepare(`SELECT * FROM stack_items WHERE id = ?`).get(id) as
|
|
153
|
-
|
|
|
154
|
-
| undefined) ?? null,
|
|
148
|
+
StackItemRow | undefined) ?? null,
|
|
155
149
|
|
|
156
150
|
itemForSession: (db: Database.Database, sessionId: string) =>
|
|
157
151
|
(db
|
package/lib/db/types.ts
CHANGED
|
@@ -42,13 +42,7 @@ export interface Session {
|
|
|
42
42
|
// done: finished without a merge (no PR, or its PR closed).
|
|
43
43
|
// moving: handing it to another machine (moved_to); moved: handed over.
|
|
44
44
|
task_status:
|
|
45
|
-
| "
|
|
46
|
-
| "merged"
|
|
47
|
-
| "dropped"
|
|
48
|
-
| "done"
|
|
49
|
-
| "moving"
|
|
50
|
-
| "moved"
|
|
51
|
-
| null;
|
|
45
|
+
"running" | "merged" | "dropped" | "done" | "moving" | "moved" | null;
|
|
52
46
|
moved_to: string | null;
|
|
53
47
|
// The session on another machine this task arrived from.
|
|
54
48
|
moved_from: string | null;
|
package/lib/doctor/checks.ts
CHANGED
|
@@ -207,15 +207,13 @@ export function runDoctor(
|
|
|
207
207
|
d
|
|
208
208
|
.probe(fresh)
|
|
209
209
|
.then(checkAgents)
|
|
210
|
-
.catch(
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
})
|
|
218
|
-
),
|
|
210
|
+
.catch((): DoctorCheck => ({
|
|
211
|
+
id: "agents",
|
|
212
|
+
label: "Agent CLI",
|
|
213
|
+
status: "warn",
|
|
214
|
+
detail: "Couldn't check the agent CLIs",
|
|
215
|
+
fix: "Check again",
|
|
216
|
+
})),
|
|
219
217
|
]);
|
|
220
218
|
if (!custom) cache = { at: Date.now(), checks };
|
|
221
219
|
return checks;
|
package/lib/done/archive.ts
CHANGED
|
@@ -35,8 +35,7 @@ export function unarchiveSession(id: string): Session {
|
|
|
35
35
|
)
|
|
36
36
|
.run(id).changes;
|
|
37
37
|
const row = db.prepare(`SELECT * FROM session_rows WHERE id = ?`).get(id) as
|
|
38
|
-
|
|
|
39
|
-
| undefined;
|
|
38
|
+
Session | undefined;
|
|
40
39
|
if (!row) throw new Error("Session not found");
|
|
41
40
|
if (!changed) throw new Error(`${row.name} isn't archived`);
|
|
42
41
|
return row;
|
package/lib/experiments/meter.ts
CHANGED
|
@@ -18,13 +18,7 @@ import { experimentOn } from ".";
|
|
|
18
18
|
import { getExperiment, type ExperimentId } from "./registry";
|
|
19
19
|
|
|
20
20
|
export type ExperimentEvent =
|
|
21
|
-
| "
|
|
22
|
-
| "script"
|
|
23
|
-
| "shown"
|
|
24
|
-
| "accepted"
|
|
25
|
-
| "dismissed"
|
|
26
|
-
| "applied"
|
|
27
|
-
| "error";
|
|
21
|
+
"model" | "script" | "shown" | "accepted" | "dismissed" | "applied" | "error";
|
|
28
22
|
|
|
29
23
|
export interface MeterContext {
|
|
30
24
|
trigger: string;
|
|
@@ -7,8 +7,6 @@
|
|
|
7
7
|
|
|
8
8
|
import type { EnvClass } from "./types";
|
|
9
9
|
|
|
10
|
-
const OLD_PYTHON =
|
|
11
|
-
/python3?\.[0-9]\b|Python3?\.framework\/Versions\/3\.[0-9]\b|Python\/3\.[0-9]\b/i;
|
|
12
10
|
const USE_ENV =
|
|
13
11
|
"run it through the repo's own environment (`uv run …` when it has a pyproject.toml or uv.lock, else its .venv/bin/python), not a bare `python3`";
|
|
14
12
|
|
|
@@ -19,8 +19,7 @@ export function recordHit(
|
|
|
19
19
|
WHERE r.id = ?`
|
|
20
20
|
)
|
|
21
21
|
.get(sessionId) as
|
|
22
|
-
|
|
23
|
-
| undefined;
|
|
22
|
+
{ project_id: string | null; ws: string | null } | undefined;
|
|
24
23
|
db.prepare(
|
|
25
24
|
`INSERT INTO env_failures
|
|
26
25
|
(session_id, class, project_id, workspace_id, command, line,
|
package/lib/health/spin.ts
CHANGED
|
@@ -45,10 +45,7 @@ export interface SpinSample {
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
export type SpinClass =
|
|
48
|
-
| "
|
|
49
|
-
| "sleeping"
|
|
50
|
-
| "busy-with-output"
|
|
51
|
-
| "spinning";
|
|
48
|
+
"warming" | "sleeping" | "busy-with-output" | "spinning";
|
|
52
49
|
|
|
53
50
|
export function classifySpin(samples: SpinSample[]): SpinClass {
|
|
54
51
|
if (samples.length < 2) return "warming";
|
package/lib/health/store.ts
CHANGED
|
@@ -29,8 +29,7 @@ export interface RecordResult {
|
|
|
29
29
|
|
|
30
30
|
const rowOf = (id: number) =>
|
|
31
31
|
db.prepare(`SELECT * FROM health_anomalies WHERE id = ?`).get(id) as
|
|
32
|
-
|
|
|
33
|
-
| undefined;
|
|
32
|
+
AnomalyRow | undefined;
|
|
34
33
|
|
|
35
34
|
export function anomaly(id: number): AnomalyRow | null {
|
|
36
35
|
return rowOf(id) ?? null;
|
package/lib/hosts/index.ts
CHANGED
|
@@ -39,8 +39,7 @@ export function getHost(hostId: string | null | undefined): Host | null {
|
|
|
39
39
|
if (!isRemoteHost(hostId)) return LOCAL_HOST;
|
|
40
40
|
return (
|
|
41
41
|
(getDb().prepare(`SELECT * FROM hosts WHERE id = ?`).get(hostId) as
|
|
42
|
-
|
|
|
43
|
-
| undefined) ?? null
|
|
42
|
+
Host | undefined) ?? null
|
|
44
43
|
);
|
|
45
44
|
}
|
|
46
45
|
|
package/lib/hosts/peer-sync.ts
CHANGED
|
@@ -95,8 +95,7 @@ export function syncPeerMirrors(
|
|
|
95
95
|
const [name, view, tmuxName, projectId, prUrl, prNumber, prStatus, at] =
|
|
96
96
|
fields;
|
|
97
97
|
const cur = current.get(peer.id, hostId) as
|
|
98
|
-
|
|
99
|
-
| undefined;
|
|
98
|
+
Record<string, string | number | null> | undefined;
|
|
100
99
|
if (!cur) return;
|
|
101
100
|
const same =
|
|
102
101
|
cur.name === name &&
|
|
@@ -126,8 +125,7 @@ export function syncPeerMirrors(
|
|
|
126
125
|
db.transaction(() => {
|
|
127
126
|
for (const peer of listed) {
|
|
128
127
|
const row = owner.get(peer.id) as
|
|
129
|
-
|
|
130
|
-
| undefined;
|
|
128
|
+
{ host_id: string; project_id: string | null } | undefined;
|
|
131
129
|
// One started here for a project here keeps it (lib/hosts/peer-actions.ts).
|
|
132
130
|
const kept =
|
|
133
131
|
row?.project_id && here.has(row.project_id) ? row.project_id : null;
|
package/lib/hosts/remote-api.ts
CHANGED
|
@@ -21,8 +21,7 @@ export function hostLink(hostId: string | null | undefined): HostLink | null {
|
|
|
21
21
|
JOIN hosts h ON h.id = l.host_id WHERE l.host_id = ?`
|
|
22
22
|
)
|
|
23
23
|
.get(hostId) as
|
|
24
|
-
|
|
25
|
-
| undefined;
|
|
24
|
+
{ host_id: string; url: string; token: string; name: string } | undefined;
|
|
26
25
|
return row
|
|
27
26
|
? {
|
|
28
27
|
hostId: row.host_id,
|
package/lib/lumifyhub/types.ts
CHANGED
|
@@ -23,11 +23,7 @@ export interface LhBoard {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
export type LhListCategory =
|
|
26
|
-
| "
|
|
27
|
-
| "unstarted"
|
|
28
|
-
| "started"
|
|
29
|
-
| "completed"
|
|
30
|
-
| "canceled";
|
|
26
|
+
"backlog" | "unstarted" | "started" | "completed" | "canceled";
|
|
31
27
|
|
|
32
28
|
export interface LhList {
|
|
33
29
|
id: string;
|
|
@@ -39,9 +35,7 @@ export interface LhList {
|
|
|
39
35
|
|
|
40
36
|
// A TipTap/ProseMirror document, or a bare string on older cards.
|
|
41
37
|
export type LhRichText =
|
|
42
|
-
| string
|
|
43
|
-
| { type?: string; text?: string; content?: LhRichText[] }
|
|
44
|
-
| null;
|
|
38
|
+
string | { type?: string; text?: string; content?: LhRichText[] } | null;
|
|
45
39
|
|
|
46
40
|
export interface LhCard {
|
|
47
41
|
id: string;
|
package/lib/notify/index.ts
CHANGED
|
@@ -161,8 +161,7 @@ export async function notifyFrom(
|
|
|
161
161
|
): Promise<Outcome> {
|
|
162
162
|
const session = from
|
|
163
163
|
? (db.prepare(`SELECT * FROM session_rows WHERE id = ?`).get(from) as
|
|
164
|
-
|
|
|
165
|
-
| undefined)
|
|
164
|
+
Session | undefined)
|
|
166
165
|
: undefined;
|
|
167
166
|
if (from && !session) throw new Error("Unknown sender session");
|
|
168
167
|
const body = text.trim();
|
package/lib/notify/push/index.ts
CHANGED
|
@@ -39,11 +39,7 @@ export function pushStatus(): { linked: boolean; unavailable: string | null } {
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
export type PushOutcome =
|
|
42
|
-
| "
|
|
43
|
-
| "folded"
|
|
44
|
-
| "dropped"
|
|
45
|
-
| "muted"
|
|
46
|
-
| "unavailable";
|
|
42
|
+
"queued" | "folded" | "dropped" | "muted" | "unavailable";
|
|
47
43
|
|
|
48
44
|
export interface PushOptions {
|
|
49
45
|
/** Held text that goes by Telegram if no phone is reached. */
|
|
@@ -59,8 +55,7 @@ function isMirrored(sessionId: string): boolean {
|
|
|
59
55
|
const s = db
|
|
60
56
|
.prepare(`SELECT host_id, peer_mirror FROM session_rows WHERE id = ?`)
|
|
61
57
|
.get(sessionId) as
|
|
62
|
-
|
|
63
|
-
| undefined;
|
|
58
|
+
{ host_id: string | null; peer_mirror: number | null } | undefined;
|
|
64
59
|
return !!s && (!!s.peer_mirror || (!!s.host_id && s.host_id !== "local"));
|
|
65
60
|
}
|
|
66
61
|
|
|
@@ -59,8 +59,7 @@ export interface ExternalPR {
|
|
|
59
59
|
type WorkspaceTask = Session & { project_name: string };
|
|
60
60
|
|
|
61
61
|
export type GateTarget =
|
|
62
|
-
|
|
63
|
-
| { kind: "external"; pr: ExternalPR };
|
|
62
|
+
{ kind: "task"; task: WorkspaceTask } | { kind: "external"; pr: ExternalPR };
|
|
64
63
|
|
|
65
64
|
const FIELDS =
|
|
66
65
|
"number,url,state,headRefOid,headRefName,baseRefName,isDraft,labels,isCrossRepository,statusCheckRollup,body,title,mergeable";
|
|
@@ -19,12 +19,7 @@ import { untrusted } from "./untrusted";
|
|
|
19
19
|
import { markStatusDirty } from "../status/dirty";
|
|
20
20
|
|
|
21
21
|
export type GateName =
|
|
22
|
-
| "
|
|
23
|
-
| "review"
|
|
24
|
-
| "code-review"
|
|
25
|
-
| "blocked"
|
|
26
|
-
| "scope"
|
|
27
|
-
| "stack";
|
|
22
|
+
"ci" | "review" | "code-review" | "blocked" | "scope" | "stack";
|
|
28
23
|
|
|
29
24
|
export interface GateOutcome {
|
|
30
25
|
gate: GateName;
|
|
@@ -72,26 +72,22 @@ export function needsYouItems(input: {
|
|
|
72
72
|
}): NeedsYouItem[] {
|
|
73
73
|
const hidden = new Set(input.dismissed);
|
|
74
74
|
const items: NeedsYouItem[] = [
|
|
75
|
-
...input.asks.map(
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
at: sqliteMs(question.createdAt),
|
|
92
|
-
question,
|
|
93
|
-
})
|
|
94
|
-
),
|
|
75
|
+
...input.asks.map((ask): NeedsYouItem => ({
|
|
76
|
+
key: `ask:${ask.id}`,
|
|
77
|
+
kind: "ask",
|
|
78
|
+
title: ask.title,
|
|
79
|
+
sub: ask.kind,
|
|
80
|
+
at: sqliteMs(ask.createdAt),
|
|
81
|
+
ask,
|
|
82
|
+
})),
|
|
83
|
+
...input.questions.map((question): NeedsYouItem => ({
|
|
84
|
+
key: `question:${question.id}`,
|
|
85
|
+
kind: "question",
|
|
86
|
+
title: question.text,
|
|
87
|
+
sub: question.taskName ?? "Question",
|
|
88
|
+
at: sqliteMs(question.createdAt),
|
|
89
|
+
question,
|
|
90
|
+
})),
|
|
95
91
|
];
|
|
96
92
|
for (const card of input.cards ?? [])
|
|
97
93
|
items.push({
|
|
@@ -95,8 +95,7 @@ const failures = new Map<string, number>();
|
|
|
95
95
|
|
|
96
96
|
const sessionRow = (id: string) =>
|
|
97
97
|
db.prepare(`SELECT * FROM session_rows WHERE id = ?`).get(id) as
|
|
98
|
-
|
|
|
99
|
-
| undefined;
|
|
98
|
+
Session | undefined;
|
|
100
99
|
|
|
101
100
|
// True when this call took the key; false when it was taken before.
|
|
102
101
|
const claim = (task: string, key: string, kind: string) =>
|
|
@@ -74,8 +74,7 @@ const tried = new Map<string, string>();
|
|
|
74
74
|
|
|
75
75
|
const sessionRow = (id: string) =>
|
|
76
76
|
db.prepare(`SELECT * FROM session_rows WHERE id = ?`).get(id) as
|
|
77
|
-
|
|
|
78
|
-
| undefined;
|
|
77
|
+
Session | undefined;
|
|
79
78
|
|
|
80
79
|
// Every open task PR in the workspace that conflicts with its base.
|
|
81
80
|
export async function rebaseConflicting(
|
|
@@ -79,8 +79,7 @@ export function describeReview(row: CheckRow): string {
|
|
|
79
79
|
const baseBranchOf = (id: string) =>
|
|
80
80
|
(
|
|
81
81
|
db.prepare(`SELECT base_branch FROM sessions WHERE id = ?`).get(id) as
|
|
82
|
-
|
|
83
|
-
| undefined
|
|
82
|
+
{ base_branch: string | null } | undefined
|
|
84
83
|
)?.base_branch ?? null;
|
|
85
84
|
|
|
86
85
|
export interface ReviewTarget {
|
|
@@ -86,8 +86,7 @@ export interface LastSeen {
|
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
export type UsageState =
|
|
89
|
-
|
|
90
|
-
| { unknown: string; last?: LastSeen | null };
|
|
89
|
+
{ window: UsageWindow | null } | { unknown: string; last?: LastSeen | null };
|
|
91
90
|
|
|
92
91
|
export interface Series {
|
|
93
92
|
window: number | null;
|
package/lib/plans/claim.ts
CHANGED
|
@@ -89,8 +89,7 @@ export function pieceRefusal(
|
|
|
89
89
|
export function pieceStatus(id: number): string | undefined {
|
|
90
90
|
return (
|
|
91
91
|
db.prepare(`SELECT status FROM feature_pieces WHERE id = ?`).get(id) as
|
|
92
|
-
|
|
93
|
-
| undefined
|
|
92
|
+
{ status: string } | undefined
|
|
94
93
|
)?.status;
|
|
95
94
|
}
|
|
96
95
|
|
package/lib/plans/features.ts
CHANGED
|
@@ -21,11 +21,7 @@ import {
|
|
|
21
21
|
} from "./pieces";
|
|
22
22
|
|
|
23
23
|
export type PieceStatus =
|
|
24
|
-
| "
|
|
25
|
-
| "building"
|
|
26
|
-
| "merged"
|
|
27
|
-
| "blocked"
|
|
28
|
-
| "dropped";
|
|
24
|
+
"waiting" | "building" | "merged" | "blocked" | "dropped";
|
|
29
25
|
|
|
30
26
|
export interface Feature {
|
|
31
27
|
id: string;
|
|
@@ -70,8 +66,7 @@ function ref(id: string): ProjectRef | null {
|
|
|
70
66
|
const p = db
|
|
71
67
|
.prepare(`SELECT id, name, working_directory FROM projects WHERE id = ?`)
|
|
72
68
|
.get(id) as
|
|
73
|
-
|
|
74
|
-
| undefined;
|
|
69
|
+
{ id: string; name: string; working_directory: string } | undefined;
|
|
75
70
|
if (!p) return null;
|
|
76
71
|
const deploy = loadProjectConfig(expandHome(p.working_directory)).config
|
|
77
72
|
.deploy;
|
|
@@ -134,8 +129,7 @@ export function planFor(s: Session, text: string): PiecesResult | null {
|
|
|
134
129
|
|
|
135
130
|
export function getFeature(id: string): Feature | undefined {
|
|
136
131
|
return db.prepare(`SELECT * FROM features WHERE id = ?`).get(id) as
|
|
137
|
-
|
|
|
138
|
-
| undefined;
|
|
132
|
+
Feature | undefined;
|
|
139
133
|
}
|
|
140
134
|
|
|
141
135
|
export function piecesOf(featureId: string): FeaturePiece[] {
|
|
@@ -162,8 +156,7 @@ export function prOf(p: FeaturePiece): number | null {
|
|
|
162
156
|
const s = db
|
|
163
157
|
.prepare(`SELECT pr_number, project_id FROM session_rows WHERE id = ?`)
|
|
164
158
|
.get(p.session_id) as
|
|
165
|
-
|
|
166
|
-
| undefined;
|
|
159
|
+
{ pr_number: number | null; project_id: string | null } | undefined;
|
|
167
160
|
return s && s.project_id === p.project_id ? s.pr_number : null;
|
|
168
161
|
}
|
|
169
162
|
|
package/lib/plans/release.ts
CHANGED
|
@@ -39,8 +39,7 @@ export interface ReleaseDeps {
|
|
|
39
39
|
const sessionOf = (id: string | null) =>
|
|
40
40
|
id
|
|
41
41
|
? (db.prepare(`SELECT * FROM session_rows WHERE id = ?`).get(id) as
|
|
42
|
-
|
|
|
43
|
-
| undefined)
|
|
42
|
+
Session | undefined)
|
|
44
43
|
: undefined;
|
|
45
44
|
|
|
46
45
|
const setPiece = (id: number, status: string, note: string | null = null) =>
|
|
@@ -60,8 +59,7 @@ function syncPieces(feature: Feature, pieces: FeaturePiece[]): void {
|
|
|
60
59
|
const q = db
|
|
61
60
|
.prepare(`SELECT status, error FROM task_queue WHERE id = ?`)
|
|
62
61
|
.get(p.session_id) as
|
|
63
|
-
|
|
64
|
-
| undefined;
|
|
62
|
+
{ status: string; error: string | null } | undefined;
|
|
65
63
|
if (q?.status === "removed")
|
|
66
64
|
setPiece(p.id, "dropped", "removed from the queue");
|
|
67
65
|
else if (q?.status === "failed")
|
package/lib/ports.ts
CHANGED
|
@@ -132,8 +132,7 @@ export async function allocatePorts(
|
|
|
132
132
|
const held = db
|
|
133
133
|
.prepare(`SELECT port_slot, ports FROM sessions WHERE id = ?`)
|
|
134
134
|
.get(sessionId) as
|
|
135
|
-
|
|
136
|
-
| undefined;
|
|
135
|
+
{ port_slot: number | null; ports: string | null } | undefined;
|
|
137
136
|
if (!held) throw new Error(`No session ${sessionId}`);
|
|
138
137
|
const existing = parsePorts(held.ports);
|
|
139
138
|
if (held.port_slot != null && existing)
|
|
@@ -95,7 +95,7 @@ const RANK: Record<ProgramState, number> = {
|
|
|
95
95
|
};
|
|
96
96
|
|
|
97
97
|
function appOf(records: Records, id: string): string | undefined {
|
|
98
|
-
for (let path = id; ;
|
|
98
|
+
for (let path = id; ;) {
|
|
99
99
|
const app = records[path]?.app;
|
|
100
100
|
if (app) return app;
|
|
101
101
|
if (path === "") return undefined;
|
|
@@ -305,8 +305,7 @@ export async function ensureSessionDatabase(
|
|
|
305
305
|
let last = sessionDatabase(sessionId);
|
|
306
306
|
let written = (
|
|
307
307
|
db.prepare(`SELECT database FROM sessions WHERE id = ?`).get(sessionId) as
|
|
308
|
-
|
|
309
|
-
| undefined
|
|
308
|
+
{ database: string | null } | undefined
|
|
310
309
|
)?.database;
|
|
311
310
|
const save = (state: SessionDatabase) => {
|
|
312
311
|
const json = JSON.stringify(state);
|
package/lib/projects.ts
CHANGED
|
@@ -357,8 +357,7 @@ export function updateProjectDevServer(
|
|
|
357
357
|
updates: Partial<CreateDevServerOptions & { sortOrder?: number }>
|
|
358
358
|
): ProjectDevServer | undefined {
|
|
359
359
|
const existing = queries.getProjectDevServer(db).get(id) as
|
|
360
|
-
|
|
|
361
|
-
| undefined;
|
|
360
|
+
ProjectDevServer | undefined;
|
|
362
361
|
if (!existing) return undefined;
|
|
363
362
|
|
|
364
363
|
queries
|
package/lib/recipes/settle.ts
CHANGED
|
@@ -241,8 +241,7 @@ async function settleOne(
|
|
|
241
241
|
const q = db
|
|
242
242
|
.prepare(`SELECT status, error FROM task_queue WHERE id = ?`)
|
|
243
243
|
.get(run.session_id) as
|
|
244
|
-
|
|
245
|
-
| undefined;
|
|
244
|
+
{ status: string; error: string | null } | undefined;
|
|
246
245
|
if (!q || q.status === "removed")
|
|
247
246
|
finish(
|
|
248
247
|
run,
|
|
@@ -425,8 +424,7 @@ async function afterSettle(run: Live): Promise<void> {
|
|
|
425
424
|
const row = db
|
|
426
425
|
.prepare(`SELECT status, summary_source FROM recipe_runs WHERE id = ?`)
|
|
427
426
|
.get(run.id) as
|
|
428
|
-
|
|
429
|
-
| undefined;
|
|
427
|
+
{ status: RunStatus; summary_source: string | null } | undefined;
|
|
430
428
|
if (!row || !run.session_id || !finishesSession(row, run.recipe)) return;
|
|
431
429
|
try {
|
|
432
430
|
await doneSession(run.session_id, { by: "direct", noMerge: true });
|