@saadnvd1/agent-os 0.3.684 → 0.3.692
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/discovered-models/route.ts +34 -0
- 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/Draft/DraftPanel.tsx +10 -2
- package/components/Draft/draftModels.test.ts +31 -0
- package/components/Draft/draftModels.ts +17 -0
- 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/agents/index.ts +37 -0
- 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/discovered-models.ts +87 -0
- 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/model-catalog.ts +9 -0
- 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 +13 -7
- 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/model-catalog.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { AgentType } from "./providers";
|
|
2
2
|
import { AGENT_DEFAULT_MODEL } from "./providers/registry";
|
|
3
|
+
import { supportsChat } from "./chat/capabilities";
|
|
3
4
|
|
|
4
5
|
export interface ModelOption {
|
|
5
6
|
value: string;
|
|
@@ -48,6 +49,14 @@ const DEFAULT_MODEL_BY_AGENT: Partial<Record<AgentType, string>> = {
|
|
|
48
49
|
gemini: "gemini-3.8-flash",
|
|
49
50
|
};
|
|
50
51
|
|
|
52
|
+
export function hasStaticModelCatalog(agentType: string): boolean {
|
|
53
|
+
return agentType in MODEL_OPTIONS_BY_AGENT;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// A chat agent with no fixed list: it reports what it can run itself.
|
|
57
|
+
export const discoversModels = (agentType: string): boolean =>
|
|
58
|
+
supportsChat(agentType) && !hasStaticModelCatalog(agentType);
|
|
59
|
+
|
|
51
60
|
export function getModelOptions(agentType: AgentType): ModelOption[] {
|
|
52
61
|
return MODEL_OPTIONS_BY_AGENT[agentType] ?? AGENT_DEFAULT_OPTIONS;
|
|
53
62
|
}
|
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 });
|
package/lib/recipes/store.ts
CHANGED
|
@@ -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
|
-
|
|
|
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
|
-
|
|
|
289
|
-
| undefined;
|
|
287
|
+
RunRow | undefined;
|
|
290
288
|
return row ? toRun(row) : null;
|
|
291
289
|
}
|
|
292
290
|
|
package/lib/schedules/store.ts
CHANGED
|
@@ -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
|
-
|
|
|
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
|
-
|
|
|
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
|
-
|
|
|
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
|
-
|
|
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;
|
package/lib/security/auth.ts
CHANGED
|
@@ -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
|
-
|
|
24
|
-
| { ok: false };
|
|
23
|
+
{ ok: true; via: Trust; deviceId?: string } | { ok: false };
|
|
25
24
|
|
|
26
25
|
export interface AuthRequest {
|
|
27
26
|
url?: string;
|
package/lib/security/passkeys.ts
CHANGED
|
@@ -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
|
-
|
|
|
58
|
-
| undefined) ?? null
|
|
57
|
+
PasskeyRow | undefined) ?? null
|
|
59
58
|
);
|
|
60
59
|
}
|
|
61
60
|
|
package/lib/security/presence.ts
CHANGED
|
@@ -147,13 +147,7 @@ const transportsOf = (k: PasskeyRow) =>
|
|
|
147
147
|
? (JSON.parse(k.transports) as AuthenticatorTransport[])
|
|
148
148
|
: undefined;
|
|
149
149
|
type AuthenticatorTransport =
|
|
150
|
-
| "
|
|
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
|
-
| "
|
|
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,
|
|
@@ -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
|
-
|
|
|
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
|
package/lib/sessions/launch.ts
CHANGED
|
@@ -11,7 +11,8 @@ import { randomUUID } from "crypto";
|
|
|
11
11
|
import { db, queries, type Session } from "../db";
|
|
12
12
|
import type { AgentType } from "../providers";
|
|
13
13
|
import type { ChatAccess, ChatFile, ChatImage } from "../chat/events";
|
|
14
|
-
import { resolveModelForAgent } from "../model-catalog";
|
|
14
|
+
import { discoversModels, resolveModelForAgent } from "../model-catalog";
|
|
15
|
+
import { isDiscoveredModel } from "../chat/discovered-models";
|
|
15
16
|
import { parseOverride, resolveRole, setSessionModel } from "../models/resolve";
|
|
16
17
|
import { ANTHROPIC } from "../models/roles";
|
|
17
18
|
import { getProject } from "../projects";
|
|
@@ -251,12 +252,18 @@ async function launch(input: LaunchInput, id: string): Promise<Launched> {
|
|
|
251
252
|
routed && (routed.provider.id === ANTHROPIC || view === "chat")
|
|
252
253
|
? routed
|
|
253
254
|
: null;
|
|
255
|
+
const wanted = input.model?.trim() || project?.default_model;
|
|
256
|
+
// An agent without a static list runs what it reports for this folder.
|
|
257
|
+
const discovered =
|
|
258
|
+
!interactive &&
|
|
259
|
+
wanted &&
|
|
260
|
+
discoversModels(agentType) &&
|
|
261
|
+
(await isDiscoveredModel(agentType, projectPath, wanted));
|
|
254
262
|
const model = interactive
|
|
255
263
|
? interactive.model
|
|
256
|
-
:
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
);
|
|
264
|
+
: discovered && wanted
|
|
265
|
+
? wanted
|
|
266
|
+
: resolveModelForAgent(agentType, wanted);
|
|
260
267
|
const text = input.prompt?.trim() ?? "";
|
|
261
268
|
const naming: Naming = text
|
|
262
269
|
? await nameFor(text, projectPath, input.name)
|
|
@@ -340,7 +347,6 @@ async function launch(input: LaunchInput, id: string): Promise<Launched> {
|
|
|
340
347
|
|
|
341
348
|
function sessionName(id: string): string | null {
|
|
342
349
|
const row = db.prepare(`SELECT name FROM sessions WHERE id = ?`).get(id) as
|
|
343
|
-
|
|
344
|
-
| undefined;
|
|
350
|
+
{ name: string } | undefined;
|
|
345
351
|
return row?.name ?? null;
|
|
346
352
|
}
|
package/lib/share/snapshot.ts
CHANGED
|
@@ -17,13 +17,7 @@ import {
|
|
|
17
17
|
} from "./redact";
|
|
18
18
|
|
|
19
19
|
export type SnapshotType =
|
|
20
|
-
| "
|
|
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;
|
package/lib/share/store.ts
CHANGED
|
@@ -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
|
-
|
|
|
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
|
-
| "
|
|
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
|
|
package/lib/sidebar/row-menu.ts
CHANGED
|
@@ -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<
|
package/lib/sidebar/shelves.ts
CHANGED
|
@@ -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
|
-
| "
|
|
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",
|
package/lib/simulator/index.ts
CHANGED
|
@@ -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
|
-
|
|
|
75
|
-
| undefined;
|
|
74
|
+
Session | undefined;
|
|
76
75
|
|
|
77
76
|
function declared(sessionId: string): {
|
|
78
77
|
config: NonNullable<ProjectConfig["simulator"]>;
|
package/lib/simulator/lease.ts
CHANGED
|
@@ -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
|
-
| "
|
|
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;
|
package/lib/stacks/index.ts
CHANGED
|
@@ -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;
|
package/lib/stacks/plan.ts
CHANGED
|
@@ -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
|
}
|
package/lib/stacks/restack.ts
CHANGED
|
@@ -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
|
-
|
|
|
114
|
-
| undefined) ?? null)
|
|
113
|
+
Session | undefined) ?? null)
|
|
115
114
|
: null;
|
|
116
115
|
|
|
117
116
|
const LIVE = new Set(["running", "pr"]);
|
package/lib/stacks/tick.ts
CHANGED
|
@@ -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
|
-
|
|
|
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;
|
package/lib/status/socket.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
|
73
|
-
| undefined;
|
|
72
|
+
Session | undefined;
|
|
74
73
|
if (!task)
|
|
75
74
|
return NextResponse.json({ error: "No such task" }, { status: 404 });
|
|
76
75
|
try {
|