@saadnvd1/agent-os 0.3.680 → 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 (148) hide show
  1. package/README.md +2 -2
  2. package/app/api/dev-servers/detect/route.ts +1 -2
  3. package/app/api/projects/[id]/dev-servers/[dsId]/route.ts +2 -4
  4. package/app/page.tsx +1 -2
  5. package/components/Artifacts/ArtifactsPanel.tsx +1 -1
  6. package/components/FileExplorer/FileTabs.tsx +1 -1
  7. package/components/Pane/DesktopTabBar.tsx +2 -2
  8. package/components/QuickSwitcher.tsx +24 -21
  9. package/components/SessionList/SessionRowMenu.tsx +0 -1
  10. package/components/Settings/ExperimentsSection.test.ts +7 -1
  11. package/components/Settings/NoApprovalsSection.test.ts +7 -1
  12. package/components/Terminal/TerminalToolbar.tsx +1 -1
  13. package/components/Terminal/VirtualKeyboard.tsx +1 -1
  14. package/components/WorkerCard.tsx +1 -7
  15. package/components/Workspaces/WorkspaceNameDialog.tsx +5 -3
  16. package/components/a/AButton.tsx +1 -6
  17. package/components/a/AIconButton.tsx +1 -5
  18. package/contexts/PaneContext.tsx +1 -6
  19. package/data/lumifyhub/index.ts +2 -4
  20. package/hooks/useDirectoryBrowser.ts +5 -4
  21. package/hooks/useDrawerAnimation.ts +11 -14
  22. package/hooks/useFileDrop.ts +2 -6
  23. package/hooks/useKeybarVisibility.ts +10 -29
  24. package/hooks/useSidebarPinned.ts +7 -23
  25. package/hooks/useSpeechRecognition.ts +19 -5
  26. package/hooks/useStoredFlag.ts +47 -0
  27. package/hooks/useViewport.ts +11 -17
  28. package/lib/approvals/no-approvals.ts +1 -7
  29. package/lib/artifacts/store.ts +1 -2
  30. package/lib/away/report.ts +1 -2
  31. package/lib/away/run.ts +1 -2
  32. package/lib/away/state.ts +1 -2
  33. package/lib/bookmarks/store.ts +1 -2
  34. package/lib/bus/delivery.ts +1 -2
  35. package/lib/bus/index.ts +1 -2
  36. package/lib/chat/compact-context.ts +1 -2
  37. package/lib/chat/stop.ts +1 -2
  38. package/lib/chat/worker/host.ts +1 -1
  39. package/lib/code-health/reports.ts +39 -3
  40. package/lib/code-health/source.ts +1 -1
  41. package/lib/db/lumifyhub.ts +2 -4
  42. package/lib/db/schedules-move.ts +1 -2
  43. package/lib/db/session-parts/tasks.ts +1 -2
  44. package/lib/db/stacks.ts +3 -9
  45. package/lib/db/types.ts +1 -7
  46. package/lib/dev-instance/spawnServer.ts +10 -6
  47. package/lib/doctor/checks.ts +8 -10
  48. package/lib/done/archive.ts +1 -2
  49. package/lib/env-setup.ts +2 -0
  50. package/lib/experiments/meter.ts +1 -7
  51. package/lib/files.ts +1 -0
  52. package/lib/health/env/classes.ts +0 -2
  53. package/lib/health/env/recordHit.ts +1 -2
  54. package/lib/health/spin.ts +1 -4
  55. package/lib/health/store.ts +1 -2
  56. package/lib/hosts/index.ts +1 -2
  57. package/lib/hosts/peer-sync.ts +2 -4
  58. package/lib/hosts/remote-api.ts +1 -2
  59. package/lib/lumifyhub/types.ts +2 -8
  60. package/lib/notify/index.ts +1 -2
  61. package/lib/notify/push/index.ts +2 -7
  62. package/lib/orchestrator/brief.ts +1 -1
  63. package/lib/orchestrator/external-pr.ts +1 -2
  64. package/lib/orchestrator/gates.ts +1 -6
  65. package/lib/orchestrator/needs-you-items.ts +16 -20
  66. package/lib/orchestrator/pr-wake.ts +1 -2
  67. package/lib/orchestrator/rebase.ts +1 -2
  68. package/lib/orchestrator/review.ts +1 -2
  69. package/lib/orchestrator/usage.ts +1 -2
  70. package/lib/plans/claim.ts +1 -2
  71. package/lib/plans/features.ts +4 -11
  72. package/lib/plans/release.ts +2 -4
  73. package/lib/ports.ts +1 -2
  74. package/lib/program-status/records.ts +1 -1
  75. package/lib/project-config/database.ts +1 -2
  76. package/lib/projects.ts +1 -2
  77. package/lib/recipes/settle.ts +2 -4
  78. package/lib/recipes/store.ts +2 -4
  79. package/lib/schedules/store.ts +2 -4
  80. package/lib/search/conversations/backfill.ts +2 -4
  81. package/lib/security/auth.ts +1 -2
  82. package/lib/security/passkeys.ts +1 -2
  83. package/lib/security/presence.ts +1 -7
  84. package/lib/session-artifacts/types.ts +1 -8
  85. package/lib/session-audit/transcript.ts +1 -3
  86. package/lib/session-logs/index.ts +1 -2
  87. package/lib/sessions/launch.ts +1 -2
  88. package/lib/share/pdf.ts +32 -1
  89. package/lib/share/snapshot.ts +1 -7
  90. package/lib/share/store.ts +1 -2
  91. package/lib/sidebar/orchestrator-row.ts +1 -6
  92. package/lib/sidebar/row-menu.ts +1 -2
  93. package/lib/sidebar/shelves.ts +1 -6
  94. package/lib/simulator/index.ts +1 -2
  95. package/lib/simulator/lease.ts +1 -5
  96. package/lib/stacks/index.ts +1 -1
  97. package/lib/stacks/plan.ts +1 -1
  98. package/lib/stacks/restack.ts +1 -2
  99. package/lib/stacks/tick.ts +1 -2
  100. package/lib/status/socket.ts +1 -2
  101. package/lib/tasks/contract/authorize.ts +1 -2
  102. package/lib/tasks/contract/plan.ts +1 -2
  103. package/lib/tasks/contract/sync.ts +1 -2
  104. package/lib/tasks/holds.ts +1 -5
  105. package/lib/tasks/index.ts +1 -2
  106. package/lib/tasks/loop-types.ts +1 -6
  107. package/lib/tasks/move-guard.ts +1 -2
  108. package/lib/tasks/move.ts +1 -2
  109. package/lib/tasks/moved-away.ts +1 -2
  110. package/lib/tasks/pause-hold.ts +1 -2
  111. package/lib/tasks/pause.ts +3 -6
  112. package/lib/tasks/pr-activity.ts +1 -3
  113. package/lib/tasks/queue-rows.ts +2 -4
  114. package/lib/tasks/queue-types.ts +1 -5
  115. package/lib/tasks/queue.ts +1 -2
  116. package/lib/tasks/refresh-base.ts +1 -2
  117. package/lib/tasks/setup.ts +9 -2
  118. package/lib/tasks/start.ts +2 -4
  119. package/lib/tasks/starter.ts +1 -2
  120. package/lib/tasks/state.ts +1 -6
  121. package/lib/theme-config.ts +1 -8
  122. package/lib/updates/banner.ts +1 -6
  123. package/lib/updates/run.ts +1 -2
  124. package/lib/usage/aggregate.ts +1 -1
  125. package/lib/usage/nightly.ts +1 -2
  126. package/lib/usage/rate-limits.ts +1 -2
  127. package/lib/usage/turns.ts +1 -2
  128. package/lib/usage/windows.ts +5 -7
  129. package/lib/workspaces.ts +1 -2
  130. package/lib/worktree-deps/clone.ts +10 -0
  131. package/lib/worktree-deps/fastcopy.ts +8 -1
  132. package/lib/worktree-deps/index.ts +14 -19
  133. package/lib/worktree-deps/install.ts +17 -24
  134. package/lib/worktree-sweep/databases.ts +0 -1
  135. package/package.json +10 -17
  136. package/scripts/check-native.mjs +86 -0
  137. package/scripts/code-health/prepass.ts +3 -3
  138. package/scripts/install-deps +24 -0
  139. package/scripts/lib/commands.sh +2 -2
  140. package/scripts/lib/deps-swap.sh +68 -0
  141. package/scripts/lib/deps-swap.test.ts +115 -0
  142. package/scripts/lib/pnpm.sh +36 -0
  143. package/scripts/lib/prerequisites.sh +9 -9
  144. package/scripts/publish +3 -2
  145. package/scripts/redeploy +25 -8
  146. package/scripts/setup.sh +4 -4
  147. package/tsconfig.json +1 -0
  148. package/scripts/ensure-native.mjs +0 -23
@@ -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 });
@@ -26,8 +26,7 @@ export const toRun = (r: RunRow): RecipeRun => ({
26
26
 
27
27
  export function getRecipe(id: string): Recipe | null {
28
28
  const row = db.prepare(`SELECT * FROM recipes WHERE id = ?`).get(id) as
29
- | RecipeRow
30
- | undefined;
29
+ RecipeRow | undefined;
31
30
  return row ? toRecipe(row) : null;
32
31
  }
33
32
 
@@ -285,8 +284,7 @@ export function lastRevisionId(recipeId: string): number | null {
285
284
 
286
285
  export function getRun(id: number): RecipeRun | null {
287
286
  const row = db.prepare(`SELECT * FROM recipe_runs WHERE id = ?`).get(id) as
288
- | RunRow
289
- | undefined;
287
+ RunRow | undefined;
290
288
  return row ? toRun(row) : null;
291
289
  }
292
290
 
@@ -138,8 +138,7 @@ export function finishOneOff(id: string, now = Date.now()): boolean {
138
138
 
139
139
  export function getSchedule(id: string): Schedule | null {
140
140
  const row = db.prepare(`SELECT * FROM schedules WHERE id = ?`).get(id) as
141
- | Row
142
- | undefined;
141
+ Row | undefined;
143
142
  return row ? toSchedule(row) : null;
144
143
  }
145
144
 
@@ -164,8 +163,7 @@ export function findSchedule(ref: string): Schedule {
164
163
  export function getSessionRow(id: string): Session | null {
165
164
  return (
166
165
  (db.prepare(`SELECT * FROM session_rows WHERE id = ?`).get(id) as
167
- | Session
168
- | undefined) ?? null
166
+ Session | undefined) ?? null
169
167
  );
170
168
  }
171
169
 
@@ -13,8 +13,7 @@ interface State {
13
13
 
14
14
  const stateOf = (db: Database.Database): State | undefined =>
15
15
  db.prepare(`SELECT * FROM chat_search_state WHERE id = 1`).get() as
16
- | State
17
- | undefined;
16
+ State | undefined;
18
17
 
19
18
  // Starts the index over: the stored version is not this build's.
20
19
  function reset(db: Database.Database): void {
@@ -68,8 +67,7 @@ export function backfillStep(db: Database.Database, batch = BATCH): boolean {
68
67
  for (const r of rows) {
69
68
  if (!r.text) continue;
70
69
  const have = key.get(r.session_id, r.item_id) as
71
- | { id: number }
72
- | undefined;
70
+ { id: number } | undefined;
73
71
  if (have) del.run(have.id);
74
72
  else mk.run(r.session_id, r.item_id);
75
73
  const id = (key.get(r.session_id, r.item_id) as { id: number }).id;
@@ -20,8 +20,7 @@ export const REMOTE_HEADER = "x-agentos-remote";
20
20
  export type Trust = "loopback" | "tailnet" | "device" | "open";
21
21
 
22
22
  export type AuthResult =
23
- | { ok: true; via: Trust; deviceId?: string }
24
- | { ok: false };
23
+ { ok: true; via: Trust; deviceId?: string } | { ok: false };
25
24
 
26
25
  export interface AuthRequest {
27
26
  url?: string;
@@ -54,8 +54,7 @@ export function activePasskeyCount(): number {
54
54
  export function getPasskey(id: string): PasskeyRow | null {
55
55
  return (
56
56
  (getDb().prepare(`SELECT * FROM passkeys WHERE id = ?`).get(id) as
57
- | PasskeyRow
58
- | undefined) ?? null
57
+ PasskeyRow | undefined) ?? null
59
58
  );
60
59
  }
61
60
 
@@ -147,13 +147,7 @@ const transportsOf = (k: PasskeyRow) =>
147
147
  ? (JSON.parse(k.transports) as AuthenticatorTransport[])
148
148
  : undefined;
149
149
  type AuthenticatorTransport =
150
- | "ble"
151
- | "cable"
152
- | "hybrid"
153
- | "internal"
154
- | "nfc"
155
- | "smart-card"
156
- | "usb";
150
+ "ble" | "cable" | "hybrid" | "internal" | "nfc" | "smart-card" | "usb";
157
151
 
158
152
  // Options for an assertion on this host, or null when it has no passkey.
159
153
  export async function assertionOptions(
@@ -1,14 +1,7 @@
1
1
  // What a session produced, as the Artifacts view lists it. Client-safe.
2
2
 
3
3
  export type ArtifactKind =
4
- | "plan"
5
- | "file"
6
- | "page"
7
- | "image"
8
- | "log"
9
- | "pr"
10
- | "run"
11
- | "session-log";
4
+ "plan" | "file" | "page" | "image" | "log" | "pr" | "run" | "session-log";
12
5
 
13
6
  // live: there to open. kept: its worktree went, a copy was kept. in-pr:
14
7
  // committed, so the PR has it. gone: nothing left to open. outside: there,
@@ -50,9 +50,7 @@ export interface ToolCall {
50
50
  }
51
51
 
52
52
  export type InjectedKind =
53
- | "nudge"
54
- | "restart-mid-turn"
55
- | "restart-between-turns";
53
+ "nudge" | "restart-mid-turn" | "restart-between-turns";
56
54
 
57
55
  export interface Injected {
58
56
  kind: InjectedKind;
@@ -121,8 +121,7 @@ export async function writeLog(
121
121
  opts: CaptureOpts & { plan?: string | null } = {}
122
122
  ): Promise<boolean> {
123
123
  const row = db.prepare(`SELECT * FROM session_rows WHERE id = ?`).get(id) as
124
- | Session
125
- | undefined;
124
+ Session | undefined;
126
125
  const existing = getLog(id);
127
126
  if (!eligible(row) || (existing && !opts.rewrite)) return false;
128
127
  const info = opts.noGh
@@ -340,7 +340,6 @@ async function launch(input: LaunchInput, id: string): Promise<Launched> {
340
340
 
341
341
  function sessionName(id: string): string | null {
342
342
  const row = db.prepare(`SELECT name FROM sessions WHERE id = ?`).get(id) as
343
- | { name: string }
344
- | undefined;
343
+ { name: string } | undefined;
345
344
  return row?.name ?? null;
346
345
  }
package/lib/share/pdf.ts CHANGED
@@ -6,6 +6,7 @@
6
6
  */
7
7
 
8
8
  import fs from "fs";
9
+ import path from "path";
9
10
  import type { Browser, LaunchOptions } from "playwright";
10
11
 
11
12
  const IDLE_MS = 60_000;
@@ -32,13 +33,43 @@ h1,h2,h3,h4{break-after:avoid}
32
33
  img{max-width:100%;break-inside:avoid}
33
34
  `;
34
35
 
36
+ /**
37
+ * Playwright's headless shell, which `playwright install
38
+ * chromium-headless-shell` puts beside the full Chromium (same cache folder,
39
+ * the revision the locked package names). Null when it isn't installed.
40
+ */
41
+ export function headlessShellPath(chromiumExecutable: string): string | null {
42
+ // <cache>/chromium-<rev>/<platform>/...: the shell's folder has the same <rev>.
43
+ const m = /^(.*)[\\/]chromium-(\d+)[\\/]/.exec(chromiumExecutable);
44
+ if (!m) return null;
45
+ const folder = path.join(m[1], `chromium_headless_shell-${m[2]}`);
46
+ let platform: string | undefined;
47
+ try {
48
+ platform = fs
49
+ .readdirSync(folder)
50
+ .find((d) => d.startsWith("chrome-headless-shell-"));
51
+ } catch {
52
+ return null;
53
+ }
54
+ if (!platform) return null;
55
+ const exe = path.join(
56
+ folder,
57
+ platform,
58
+ process.platform === "win32"
59
+ ? "chrome-headless-shell.exe"
60
+ : "chrome-headless-shell"
61
+ );
62
+ return fs.existsSync(exe) ? exe : null;
63
+ }
64
+
35
65
  let found: LaunchOptions | null | undefined;
36
66
 
37
67
  /** How to launch a browser on this machine, or null when there is none. */
38
68
  export async function findBrowser(): Promise<LaunchOptions | null> {
39
69
  if (found !== undefined) return found;
40
70
  const { chromium } = await import("playwright");
41
- const candidates = [chromium.executablePath(), ...CHROME_PATHS];
71
+ const full = chromium.executablePath();
72
+ const candidates = [headlessShellPath(full), full, ...CHROME_PATHS];
42
73
  const path = candidates.find((p) => p && fs.existsSync(p));
43
74
  found = path ? { executablePath: path, headless: true } : null;
44
75
  return found;
@@ -17,13 +17,7 @@ import {
17
17
  } from "./redact";
18
18
 
19
19
  export type SnapshotType =
20
- | "user"
21
- | "assistant"
22
- | "plan"
23
- | "error"
24
- | "divider"
25
- | "artifact"
26
- | "detail";
20
+ "user" | "assistant" | "plan" | "error" | "divider" | "artifact" | "detail";
27
21
 
28
22
  export interface SnapshotItem {
29
23
  id: string;
@@ -28,8 +28,7 @@ export function listSharedLinks(): SharedLink[] {
28
28
 
29
29
  export function getSharedLink(id: string): SharedLink | undefined {
30
30
  return db.prepare(`SELECT * FROM shared_links WHERE id = ?`).get(id) as
31
- | SharedLink
32
- | undefined;
31
+ SharedLink | undefined;
33
32
  }
34
33
 
35
34
  export function markRevoked(id: string): void {
@@ -12,12 +12,7 @@ export interface OrchestratorRowCounts {
12
12
  }
13
13
 
14
14
  export type OrchestratorState =
15
- | "Paused"
16
- | "Failed"
17
- | "Working"
18
- | "Replied"
19
- | "Waiting"
20
- | "Idle";
15
+ "Paused" | "Failed" | "Working" | "Replied" | "Waiting" | "Idle";
21
16
 
22
17
  const plural = (n: number, one: string) => `${n} ${one}${n === 1 ? "" : "s"}`;
23
18
 
@@ -38,8 +38,7 @@ export type RowMenuItem =
38
38
  export type RowMenuGroup = "open" | "share" | "restart" | "move" | "automate";
39
39
 
40
40
  export type RowMenuEntry =
41
- | RowMenuItem
42
- | { group: RowMenuGroup; items: RowMenuItem[] };
41
+ RowMenuItem | { group: RowMenuGroup; items: RowMenuItem[] };
43
42
 
44
43
  export interface RowMenuInput {
45
44
  session: Pick<
@@ -8,12 +8,7 @@ import { isFinished, type TaskState } from "@/lib/tasks/state";
8
8
 
9
9
  // Why a session is blocked on you.
10
10
  export type SessionNeed =
11
- | "approve"
12
- | "answer"
13
- | "signin"
14
- | "input"
15
- | "unsent"
16
- | "failed";
11
+ "approve" | "answer" | "signin" | "input" | "unsent" | "failed";
17
12
 
18
13
  export const NEED_LABEL: Record<SessionNeed, string> = {
19
14
  approve: "Approve",
@@ -71,8 +71,7 @@ export { shutTaskSimulators, shutFinishedTaskSimulators } from "./task-devices";
71
71
 
72
72
  const session = (id: string) =>
73
73
  db.prepare(`SELECT * FROM session_rows WHERE id = ?`).get(id) as
74
- | Session
75
- | undefined;
74
+ Session | undefined;
76
75
 
77
76
  function declared(sessionId: string): {
78
77
  config: NonNullable<ProjectConfig["simulator"]>;
@@ -8,11 +8,7 @@ import { db } from "../db";
8
8
  import { baseName, deviceNameFor, ownsDevice, type SimDevice } from "./simctl";
9
9
 
10
10
  export type LeaseState =
11
- | "creating"
12
- | "starting"
13
- | "ready"
14
- | "failed"
15
- | "shutdown";
11
+ "creating" | "starting" | "ready" | "failed" | "shutdown";
16
12
 
17
13
  export interface Lease {
18
14
  session_id: string;
@@ -107,7 +107,7 @@ export function retryItem(stackId: string, itemId: string): StackView {
107
107
  }
108
108
  const items = q.items(db, stackId);
109
109
  const reset = new Set([item.id]);
110
- for (let grew = true; grew; ) {
110
+ for (let grew = true; grew;) {
111
111
  grew = false;
112
112
  for (const i of items) {
113
113
  if (reset.has(i.id) || i.status !== "held" || i.held_outside) continue;
@@ -132,7 +132,7 @@ export function planStack(cards: PlanCard[]): PlanItem[] {
132
132
  : best;
133
133
  });
134
134
  const chain = new Set<string>();
135
- for (let node: string | null = parent; node; ) {
135
+ for (let node: string | null = parent; node;) {
136
136
  chain.add(node);
137
137
  node = items.get(node)!.parent;
138
138
  }
@@ -110,8 +110,7 @@ const defaults: RestackDeps = {
110
110
  const sessionOf = (id: string | null) =>
111
111
  id
112
112
  ? ((db.prepare(`SELECT * FROM session_rows WHERE id = ?`).get(id) as
113
- | Session
114
- | undefined) ?? null)
113
+ Session | undefined) ?? null)
115
114
  : null;
116
115
 
117
116
  const LIVE = new Set(["running", "pr"]);
@@ -40,8 +40,7 @@ const LIVE = new Set(["running", "pr"]);
40
40
 
41
41
  const sessionOf = (id: string) =>
42
42
  db.prepare(`SELECT * FROM session_rows WHERE id = ?`).get(id) as
43
- | Session
44
- | undefined;
43
+ Session | undefined;
45
44
 
46
45
  async function refreshItem(item: StackItemRow): Promise<void> {
47
46
  if (!item.session_id || !LIVE.has(item.status)) return;
@@ -78,7 +78,6 @@ export function sessionFolder(sessionId: string): string | null {
78
78
  `SELECT worktree_path, working_directory FROM sessions WHERE id = ?`
79
79
  )
80
80
  .get(sessionId) as
81
- | { worktree_path: string | null; working_directory: string }
82
- | undefined;
81
+ { worktree_path: string | null; working_directory: string } | undefined;
83
82
  return s ? s.worktree_path || s.working_directory : null;
84
83
  }
@@ -69,8 +69,7 @@ export async function taskRoute(
69
69
  const refused = refuse(request, id, rule);
70
70
  if (refused) return refused;
71
71
  const task = db.prepare(`SELECT * FROM session_rows WHERE id = ?`).get(id) as
72
- | Session
73
- | undefined;
72
+ Session | undefined;
74
73
  if (!task)
75
74
  return NextResponse.json({ error: "No such task" }, { status: 404 });
76
75
  try {
@@ -41,8 +41,7 @@ export { remotePlanPath };
41
41
 
42
42
  const getSession = (id: string) =>
43
43
  db.prepare(`SELECT * FROM session_rows WHERE id = ?`).get(id) as
44
- | Session
45
- | undefined;
44
+ Session | undefined;
46
45
 
47
46
  async function readCopy(id: string): Promise<string | null> {
48
47
  try {
@@ -33,8 +33,7 @@ const FINISHED: Record<string, TaskStatus> = {
33
33
 
34
34
  const getSession = (id: string) =>
35
35
  db.prepare(`SELECT * FROM session_rows WHERE id = ?`).get(id) as
36
- | Session
37
- | undefined;
36
+ Session | undefined;
38
37
 
39
38
  // The plan-written line a held task stored on its machine (plan-step.ts),
40
39
  // once per distinct plan: the mirror keeps the last one it told about.
@@ -56,11 +56,7 @@ export interface MachineView {
56
56
  }
57
57
 
58
58
  export type MachineCode =
59
- | "needs"
60
- | "load_red"
61
- | "load_amber"
62
- | "heavy"
63
- | "spacing";
59
+ "needs" | "load_red" | "load_amber" | "heavy" | "spacing";
64
60
 
65
61
  // A reason a task isn't starting. `code` is also what a queue row stores and
66
62
  // the client reads. A hold that rests on a machine says which one, and when
@@ -447,8 +447,7 @@ export async function shellOnly(tmuxName: string): Promise<boolean> {
447
447
 
448
448
  // A chat's turn as its worker says: "unknown" when it can't be reached.
449
449
  type ChatTurn =
450
- | NonNullable<Awaited<ReturnType<typeof chatStateNow>>>
451
- | "unknown";
450
+ NonNullable<Awaited<ReturnType<typeof chatStateNow>>> | "unknown";
452
451
 
453
452
  // A chat between turns waits on the next message, as a terminal at its
454
453
  // prompt does. One whose worker can't be reached counts as busy.
@@ -100,12 +100,7 @@ export interface TaskDiffPatch {
100
100
  // -- Checks and the review verdict ----------------------------------------
101
101
 
102
102
  export type CheckState =
103
- | "pass"
104
- | "fail"
105
- | "pending"
106
- | "skipped"
107
- | "cancelled"
108
- | "neutral";
103
+ "pass" | "fail" | "pending" | "skipped" | "cancelled" | "neutral";
109
104
 
110
105
  export interface TaskCheck {
111
106
  name: string;
@@ -52,8 +52,7 @@ export function moveRefusal(session: Session): string | null {
52
52
  FROM session_rows s WHERE id = ?`
53
53
  )
54
54
  .get(session.id) as
55
- | { lh_card_id: string | null; stacked: number }
56
- | undefined;
55
+ { lh_card_id: string | null; stacked: number } | undefined;
57
56
  if (row?.lh_card_id) return "Card tasks run on this machine only for now";
58
57
  if (row?.stacked) return "Stacked tasks run on this machine only for now";
59
58
  return null;
package/lib/tasks/move.ts CHANGED
@@ -127,8 +127,7 @@ function orchestratorOf(
127
127
  const by = starterOrchestrator(session.started_by);
128
128
  if (!by) return undefined;
129
129
  const o = db.prepare(`SELECT name FROM sessions WHERE id = ?`).get(by) as
130
- | { name: string }
131
- | undefined;
130
+ { name: string } | undefined;
132
131
  return o ? { id: by, name: o.name } : undefined;
133
132
  }
134
133
 
@@ -14,8 +14,7 @@ import { archiveSession } from "../done/archive";
14
14
 
15
15
  export async function cleanUpMovedAway(id: string): Promise<WorktreeFate> {
16
16
  const s = db.prepare(`SELECT * FROM session_rows WHERE id = ?`).get(id) as
17
- | Session
18
- | undefined;
17
+ Session | undefined;
19
18
  if (!s || s.task_status !== "moved" || !s.held_by_device)
20
19
  return { action: "none" };
21
20
  await endSessionAgent(s).catch((err) =>
@@ -16,8 +16,7 @@ export function pauseHoldOf(sessionId: string): PauseHold | null {
16
16
  WHERE id = ? AND pause_state IN ('pausing', 'paused') AND pause_id IS NOT NULL`
17
17
  )
18
18
  .get(sessionId) as
19
- | { pause_id: number; paused_until: string | null }
20
- | undefined;
19
+ { pause_id: number; paused_until: string | null } | undefined;
21
20
  return row ? { pauseId: row.pause_id, until: row.paused_until } : null;
22
21
  }
23
22