@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.
Files changed (123) hide show
  1. package/app/api/dev-servers/detect/route.ts +1 -2
  2. package/app/api/projects/[id]/dev-servers/[dsId]/route.ts +2 -4
  3. package/app/page.tsx +1 -2
  4. package/components/Artifacts/ArtifactsPanel.tsx +1 -1
  5. package/components/FileExplorer/FileTabs.tsx +1 -1
  6. package/components/Pane/DesktopTabBar.tsx +2 -2
  7. package/components/QuickSwitcher.tsx +24 -21
  8. package/components/SessionList/SessionRowMenu.tsx +0 -1
  9. package/components/Settings/ExperimentsSection.test.ts +7 -1
  10. package/components/Settings/NoApprovalsSection.test.ts +7 -1
  11. package/components/Terminal/TerminalToolbar.tsx +1 -1
  12. package/components/Terminal/VirtualKeyboard.tsx +1 -1
  13. package/components/WorkerCard.tsx +1 -7
  14. package/components/Workspaces/WorkspaceNameDialog.tsx +5 -3
  15. package/components/a/AButton.tsx +1 -6
  16. package/components/a/AIconButton.tsx +1 -5
  17. package/contexts/PaneContext.tsx +1 -6
  18. package/data/lumifyhub/index.ts +2 -4
  19. package/hooks/useDirectoryBrowser.ts +5 -4
  20. package/hooks/useDrawerAnimation.ts +11 -14
  21. package/hooks/useFileDrop.ts +2 -6
  22. package/hooks/useKeybarVisibility.ts +10 -29
  23. package/hooks/useSidebarPinned.ts +7 -23
  24. package/hooks/useSpeechRecognition.ts +19 -5
  25. package/hooks/useStoredFlag.ts +47 -0
  26. package/hooks/useViewport.ts +11 -17
  27. package/lib/approvals/no-approvals.ts +1 -7
  28. package/lib/artifacts/store.ts +1 -2
  29. package/lib/away/report.ts +1 -2
  30. package/lib/away/run.ts +1 -2
  31. package/lib/away/state.ts +1 -2
  32. package/lib/bookmarks/store.ts +1 -2
  33. package/lib/bus/delivery.ts +1 -2
  34. package/lib/bus/index.ts +1 -2
  35. package/lib/chat/compact-context.ts +1 -2
  36. package/lib/chat/stop.ts +1 -2
  37. package/lib/chat/worker/host.ts +1 -1
  38. package/lib/code-health/reports.ts +1 -2
  39. package/lib/db/lumifyhub.ts +2 -4
  40. package/lib/db/schedules-move.ts +1 -2
  41. package/lib/db/session-parts/tasks.ts +1 -2
  42. package/lib/db/stacks.ts +3 -9
  43. package/lib/db/types.ts +1 -7
  44. package/lib/doctor/checks.ts +7 -9
  45. package/lib/done/archive.ts +1 -2
  46. package/lib/experiments/meter.ts +1 -7
  47. package/lib/health/env/classes.ts +0 -2
  48. package/lib/health/env/recordHit.ts +1 -2
  49. package/lib/health/spin.ts +1 -4
  50. package/lib/health/store.ts +1 -2
  51. package/lib/hosts/index.ts +1 -2
  52. package/lib/hosts/peer-sync.ts +2 -4
  53. package/lib/hosts/remote-api.ts +1 -2
  54. package/lib/lumifyhub/types.ts +2 -8
  55. package/lib/notify/index.ts +1 -2
  56. package/lib/notify/push/index.ts +2 -7
  57. package/lib/orchestrator/external-pr.ts +1 -2
  58. package/lib/orchestrator/gates.ts +1 -6
  59. package/lib/orchestrator/needs-you-items.ts +16 -20
  60. package/lib/orchestrator/pr-wake.ts +1 -2
  61. package/lib/orchestrator/rebase.ts +1 -2
  62. package/lib/orchestrator/review.ts +1 -2
  63. package/lib/orchestrator/usage.ts +1 -2
  64. package/lib/plans/claim.ts +1 -2
  65. package/lib/plans/features.ts +4 -11
  66. package/lib/plans/release.ts +2 -4
  67. package/lib/ports.ts +1 -2
  68. package/lib/program-status/records.ts +1 -1
  69. package/lib/project-config/database.ts +1 -2
  70. package/lib/projects.ts +1 -2
  71. package/lib/recipes/settle.ts +2 -4
  72. package/lib/recipes/store.ts +2 -4
  73. package/lib/schedules/store.ts +2 -4
  74. package/lib/search/conversations/backfill.ts +2 -4
  75. package/lib/security/auth.ts +1 -2
  76. package/lib/security/passkeys.ts +1 -2
  77. package/lib/security/presence.ts +1 -7
  78. package/lib/session-artifacts/types.ts +1 -8
  79. package/lib/session-audit/transcript.ts +1 -3
  80. package/lib/session-logs/index.ts +1 -2
  81. package/lib/sessions/launch.ts +1 -2
  82. package/lib/share/snapshot.ts +1 -7
  83. package/lib/share/store.ts +1 -2
  84. package/lib/sidebar/orchestrator-row.ts +1 -6
  85. package/lib/sidebar/row-menu.ts +1 -2
  86. package/lib/sidebar/shelves.ts +1 -6
  87. package/lib/simulator/index.ts +1 -2
  88. package/lib/simulator/lease.ts +1 -5
  89. package/lib/stacks/index.ts +1 -1
  90. package/lib/stacks/plan.ts +1 -1
  91. package/lib/stacks/restack.ts +1 -2
  92. package/lib/stacks/tick.ts +1 -2
  93. package/lib/status/socket.ts +1 -2
  94. package/lib/tasks/contract/authorize.ts +1 -2
  95. package/lib/tasks/contract/plan.ts +1 -2
  96. package/lib/tasks/contract/sync.ts +1 -2
  97. package/lib/tasks/holds.ts +1 -5
  98. package/lib/tasks/index.ts +1 -2
  99. package/lib/tasks/loop-types.ts +1 -6
  100. package/lib/tasks/move-guard.ts +1 -2
  101. package/lib/tasks/move.ts +1 -2
  102. package/lib/tasks/moved-away.ts +1 -2
  103. package/lib/tasks/pause-hold.ts +1 -2
  104. package/lib/tasks/pause.ts +3 -6
  105. package/lib/tasks/pr-activity.ts +1 -3
  106. package/lib/tasks/queue-rows.ts +2 -4
  107. package/lib/tasks/queue-types.ts +1 -5
  108. package/lib/tasks/queue.ts +1 -2
  109. package/lib/tasks/refresh-base.ts +1 -2
  110. package/lib/tasks/start.ts +2 -4
  111. package/lib/tasks/starter.ts +1 -2
  112. package/lib/tasks/state.ts +1 -6
  113. package/lib/theme-config.ts +1 -8
  114. package/lib/updates/banner.ts +1 -6
  115. package/lib/updates/run.ts +1 -2
  116. package/lib/usage/aggregate.ts +1 -1
  117. package/lib/usage/nightly.ts +1 -2
  118. package/lib/usage/rate-limits.ts +1 -2
  119. package/lib/usage/turns.ts +1 -2
  120. package/lib/usage/windows.ts +5 -7
  121. package/lib/workspaces.ts +1 -2
  122. package/lib/worktree-sweep/databases.ts +0 -1
  123. 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
- | Session
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
- | AwayRow
47
- | undefined) ?? null
46
+ AwayRow | undefined) ?? null
48
47
  );
49
48
  }
50
49
 
@@ -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
- | Joined
87
- | undefined;
86
+ Joined | undefined;
88
87
  return r ? toBookmark(r) : null;
89
88
  }
90
89
 
@@ -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
- | { state: "delivered" | "queued" }
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
- | Session
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
- | Pick<Session, "working_directory" | "task_prompt" | "role">
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
- | { stopped: true; killed: boolean }
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
@@ -551,7 +551,7 @@ export class ChatHost {
551
551
  this.compactingNow
552
552
  )
553
553
  return;
554
- for (let next; (next = claimNext(this.session.id)); ) {
554
+ for (let next; (next = claimNext(this.session.id));) {
555
555
  this.emit({ type: "queue" });
556
556
  this.sendUser(next);
557
557
  }
@@ -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 {
@@ -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
- | LumifyHubConnection
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
- | (LumifyHubConnectAttempt & { fresh: number })
69
- | undefined;
67
+ (LumifyHubConnectAttempt & { fresh: number }) | undefined;
70
68
  db.prepare(`DELETE FROM lumifyhub_connect_attempts WHERE state = ?`).run(
71
69
  state
72
70
  );
@@ -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
- | { brief: string; project_id: string }
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
- | { created_at: string; task_since: string | null }
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
- | "running"
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
- | StackRow
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
- | StackItemRow
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
- | "running"
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;
@@ -207,15 +207,13 @@ export function runDoctor(
207
207
  d
208
208
  .probe(fresh)
209
209
  .then(checkAgents)
210
- .catch(
211
- (): DoctorCheck => ({
212
- id: "agents",
213
- label: "Agent CLI",
214
- status: "warn",
215
- detail: "Couldn't check the agent CLIs",
216
- fix: "Check again",
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;
@@ -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
- | Session
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;
@@ -18,13 +18,7 @@ import { experimentOn } from ".";
18
18
  import { getExperiment, type ExperimentId } from "./registry";
19
19
 
20
20
  export type ExperimentEvent =
21
- | "model"
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
- | { project_id: string | null; ws: string | null }
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,
@@ -45,10 +45,7 @@ export interface SpinSample {
45
45
  }
46
46
 
47
47
  export type SpinClass =
48
- | "warming"
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";
@@ -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
- | AnomalyRow
33
- | undefined;
32
+ AnomalyRow | undefined;
34
33
 
35
34
  export function anomaly(id: number): AnomalyRow | null {
36
35
  return rowOf(id) ?? null;
@@ -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
- | Host
43
- | undefined) ?? null
42
+ Host | undefined) ?? null
44
43
  );
45
44
  }
46
45
 
@@ -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
- | Record<string, string | number | null>
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
- | { host_id: string; project_id: string | null }
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;
@@ -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
- | { host_id: string; url: string; token: string; name: string }
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,
@@ -23,11 +23,7 @@ export interface LhBoard {
23
23
  }
24
24
 
25
25
  export type LhListCategory =
26
- | "backlog"
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;
@@ -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
- | Session
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();
@@ -39,11 +39,7 @@ export function pushStatus(): { linked: boolean; unavailable: string | null } {
39
39
  }
40
40
 
41
41
  export type PushOutcome =
42
- | "queued"
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
- | { host_id: string | null; peer_mirror: number | null }
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
- | { kind: "task"; task: WorkspaceTask }
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
- | "ci"
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
- (ask): NeedsYouItem => ({
77
- key: `ask:${ask.id}`,
78
- kind: "ask",
79
- title: ask.title,
80
- sub: ask.kind,
81
- at: sqliteMs(ask.createdAt),
82
- ask,
83
- })
84
- ),
85
- ...input.questions.map(
86
- (question): NeedsYouItem => ({
87
- key: `question:${question.id}`,
88
- kind: "question",
89
- title: question.text,
90
- sub: question.taskName ?? "Question",
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
- | Session
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
- | Session
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
- | { base_branch: string | null }
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
- | { window: UsageWindow | null }
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;
@@ -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
- | { status: string }
93
- | undefined
92
+ { status: string } | undefined
94
93
  )?.status;
95
94
  }
96
95
 
@@ -21,11 +21,7 @@ import {
21
21
  } from "./pieces";
22
22
 
23
23
  export type PieceStatus =
24
- | "waiting"
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
- | { id: string; name: string; working_directory: string }
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
- | Feature
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
- | { pr_number: number | null; project_id: string | null }
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
 
@@ -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
- | Session
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
- | { status: string; error: string | null }
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
- | { port_slot: number | null; ports: string | null }
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
- | { database: string | null }
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
- | ProjectDevServer
361
- | undefined;
360
+ ProjectDevServer | undefined;
362
361
  if (!existing) return undefined;
363
362
 
364
363
  queries
@@ -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
- | { status: string; error: string | null }
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
- | { status: RunStatus; summary_source: string | null }
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 });