Skip to content

Commit bec7f1c

Browse files
author
ultrabot-cloudhome-ops
committed
Merge branch 'opencode-mirror' into fork/local
2 parents e66652c + cf75036 commit bec7f1c

70 files changed

Lines changed: 126523 additions & 67948 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/* This file is auto-generated by SST. Do not edit. */
2+
/* tslint:disable */
3+
/* eslint-disable */
4+
/* deno-fmt-ignore-file */
5+
/* biome-ignore-all lint: auto-generated */
6+
7+
/// <reference path="../../sst-env.d.ts" />
8+
9+
import "sst"
10+
export {}

infra/lake.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ const athenaWorkgroup = new aws.athena.Workgroup("LakeAthenaWorkgroup", {
6767
configuration: {
6868
enforceWorkgroupConfiguration: true,
6969
publishCloudwatchMetricsEnabled: true,
70+
// Athena bills $5/TB scanned; kill any query that would scan more than 2 TB
71+
// so a regression cannot silently burn money. Stats sync full passes scan
72+
// ~250 GB as of 2026-07.
73+
bytesScannedCutoffPerQuery: 2 * 1024 ** 4,
7074
resultConfiguration: {
7175
outputLocation: $interpolate`s3://${athenaResultsBucket.bucket}/`,
7276
},

packages/app/src/components/prompt-input.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1335,6 +1335,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
13351335
onQueue: props.onQueue,
13361336
onAbort: props.onAbort,
13371337
onSubmit: props.onSubmit,
1338+
model: props.controls.model.selection,
13381339
})
13391340

13401341
const handleKeyDown = (event: KeyboardEvent) => {

packages/app/src/components/prompt-input/submit.test.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { beforeAll, beforeEach, describe, expect, mock, test } from "bun:test"
22
import type { Prompt } from "@/context/prompt"
3+
import type { ModelSelection } from "@/context/local"
34

45
let createPromptSubmit: typeof import("./submit").createPromptSubmit
56

@@ -33,6 +34,10 @@ const prompt = {
3334
current: () => promptValue,
3435
cursor: () => 0,
3536
dirty: () => true,
37+
model: {
38+
current: () => undefined,
39+
set: () => undefined,
40+
},
3641
reset: () => undefined,
3742
set: () => undefined,
3843
context: {
@@ -378,6 +383,39 @@ describe("prompt submit worktree selection", () => {
378383
})
379384
})
380385

386+
test("uses an injected model selection", async () => {
387+
params = { id: "session-1" }
388+
const model = {
389+
current: () => ({ id: "draft-model", provider: { id: "draft-provider" } }),
390+
variant: { current: () => "draft-variant" },
391+
} as unknown as ModelSelection
392+
const submit = createPromptSubmit({
393+
prompt,
394+
info: () => ({ id: "session-1" }),
395+
imageAttachments: () => [],
396+
commentCount: () => 0,
397+
autoAccept: () => false,
398+
mode: () => "normal",
399+
working: () => false,
400+
editor: () => undefined,
401+
queueScroll: () => undefined,
402+
promptLength: (value) => value.reduce((sum, part) => sum + ("content" in part ? part.content.length : 0), 0),
403+
addToHistory: () => undefined,
404+
resetHistoryNavigation: () => undefined,
405+
setMode: () => undefined,
406+
setPopover: () => undefined,
407+
model,
408+
})
409+
410+
await submit.handleSubmit({ preventDefault: () => undefined } as unknown as Event)
411+
412+
expect(optimistic[0]).toMatchObject({
413+
message: {
414+
model: { providerID: "draft-provider", modelID: "draft-model", variant: "draft-variant" },
415+
},
416+
})
417+
})
418+
381419
test("seeds new sessions before optimistic prompts are added", async () => {
382420
const submit = createPromptSubmit({
383421
prompt,

packages/app/src/components/prompt-input/submit.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { useTabs } from "@/context/tabs"
88
import { useServerSync, type ServerSync } from "@/context/server-sync"
99
import { useLanguage } from "@/context/language"
1010
import { useLayout } from "@/context/layout"
11-
import { useLocal } from "@/context/local"
11+
import { useLocal, type ModelSelection } from "@/context/local"
1212
import { usePermission } from "@/context/permission"
1313
import { type ContextItem, type ImageAttachmentPart, type Prompt, type usePrompt } from "@/context/prompt"
1414
import { useSDK, type DirectorySDK } from "@/context/sdk"
@@ -191,6 +191,7 @@ type PromptSubmitInput = {
191191
onQueue?: (draft: FollowupDraft) => void
192192
onAbort?: () => void
193193
onSubmit?: () => void
194+
model?: ModelSelection
194195
}
195196

196197
export function createPromptSubmit(input: PromptSubmitInput) {
@@ -298,9 +299,10 @@ export function createPromptSubmit(input: PromptSubmitInput) {
298299
return
299300
}
300301

301-
const currentModel = local.model.current()
302+
const modelSelection = input.model ?? local.model
303+
const currentModel = modelSelection.current()
302304
const currentAgent = local.agent.current()
303-
const variant = local.model.variant.current()
305+
const variant = modelSelection.variant.current()
304306
if (!currentModel || !currentAgent) {
305307
showToast({
306308
title: language.t("prompt.toast.modelAgentRequired.title"),
@@ -377,7 +379,11 @@ export function createPromptSubmit(input: PromptSubmitInput) {
377379
await startTransition(() => {
378380
if (!session) return
379381
if (shouldAutoAccept) permission.enableAutoAccept(session.id, sessionDirectory)
380-
local.session.promote(sessionDirectory, session.id)
382+
local.session.promote(sessionDirectory, session.id, {
383+
agent: currentAgent.name,
384+
model: { providerID: currentModel.provider.id, modelID: currentModel.id },
385+
variant: variant ?? null,
386+
})
381387
layout.handoff.setTabs(base64Encode(sessionDirectory), session.id)
382388
const draftID = search.draftId
383389
if (draftID) tabs.promoteDraft(draftID, { server: tabs.draft(draftID).server, sessionId: session.id })

packages/app/src/components/titlebar.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { readSessionTabsRemovedDetail, SESSION_TABS_REMOVED_EVENT } from "@/comp
2525
import { useGlobal } from "@/context/global"
2626
import { ServerConnection, useServer } from "@/context/server"
2727
import { tabKey, useTabs } from "@/context/tabs"
28+
import type { PromptSession } from "@/context/prompt"
2829
import "./titlebar.css"
2930
import { newTabTooltipKeybind } from "./command-tooltip-keybind"
3031

@@ -324,13 +325,20 @@ export function Titlebar(props: { update?: TitlebarUpdate }) {
324325
const route = layout.route()
325326
const activeSession = session()
326327
if (route.type === "session" && activeSession) {
327-
tabs.newDraft({ server: route.server ?? server.key, directory: activeSession.directory }, "")
328+
const sessionTab = {
329+
type: "session" as const,
330+
server: route.server ?? server.key,
331+
sessionId: activeSession.id,
332+
}
333+
const model = tabs.stateValue<PromptSession>(sessionTab, "prompt")?.model.current()
334+
tabs.newDraft({ server: sessionTab.server, directory: activeSession.directory }, "", model)
328335
return
329336
}
330337

331338
const activeTab = currentTab()
332339
if (activeTab?.type === "draft") {
333-
tabs.newDraft({ server: activeTab.server, directory: activeTab.directory }, "")
340+
const model = tabs.stateValue<PromptSession>(activeTab, "prompt")?.model.current()
341+
tabs.newDraft({ server: activeTab.server, directory: activeTab.directory }, "", model)
334342
return
335343
}
336344

packages/app/src/context/local.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
6767
const list = createMemo(() => sync().data.agent.filter((item) => item.mode !== "subagent" && !item.hidden))
6868
const connected = createMemo(() => new Set(providers.connected().map((item) => item.id)))
6969

70-
const [saved, setSaved] = persisted(
70+
const [saved, setSaved, , savedReady] = persisted(
7171
{
7272
...Persist.serverWorkspace(serverSDK().scope, sdk().directory, "model-selection", ["model-selection.v1"]),
7373
migrate,
@@ -375,11 +375,12 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
375375
model,
376376
agent,
377377
session: {
378+
ready: savedReady,
378379
reset() {
379380
setStore({ draft: undefined, promoting: undefined })
380381
},
381-
promote(dir: string, session: string) {
382-
const next = clone(snapshot())
382+
promote(dir: string, session: string, state?: State) {
383+
const next = clone(state ?? snapshot())
383384
if (!next) return
384385
const key = handoffKey(serverSDK().scope, dir, session)
385386
handoff.set(key, next)
@@ -409,3 +410,5 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
409410
return result
410411
},
411412
})
413+
414+
export type ModelSelection = ReturnType<typeof useLocal>["model"]
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { describe, expect, test } from "bun:test"
2+
import { createRoot } from "solid-js"
3+
import { createPromptState, DEFAULT_PROMPT } from "./prompt-state"
4+
5+
describe("prompt state initialization", () => {
6+
test("initializes prompt text, cursor, and model together", () => {
7+
createRoot((dispose) => {
8+
const model = { providerID: "anthropic", modelID: "claude", variant: "high" }
9+
const prompt = createPromptState({ prompt: "hello", model })
10+
11+
expect(prompt.current()).toEqual([{ type: "text", content: "hello", start: 0, end: 5 }])
12+
expect(prompt.cursor()).toBe(5)
13+
expect(prompt.model.current()).toEqual(model)
14+
expect(prompt.model.current()).not.toBe(model)
15+
dispose()
16+
})
17+
})
18+
19+
test("uses the default prompt without initial values", () => {
20+
createRoot((dispose) => {
21+
const prompt = createPromptState()
22+
23+
expect(prompt.current()).toEqual(DEFAULT_PROMPT)
24+
expect(prompt.cursor()).toBeUndefined()
25+
expect(prompt.model.current()).toBeUndefined()
26+
dispose()
27+
})
28+
})
29+
})

0 commit comments

Comments
 (0)