Skip to content

Commit 784c602

Browse files
committed
Merge remote-tracking branch 'origin/dev' into analysis-task-model-override-port
2 parents 473ed05 + 0448a30 commit 784c602

155 files changed

Lines changed: 5619 additions & 1557 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

AGENTS.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
- To regenerate the JavaScript SDK, run `./packages/sdk/js/script/build.ts`.
2-
- ALWAYS USE PARALLEL TOOLS WHEN APPLICABLE.
32
- The default branch in this repo is `dev`.
43
- Local `main` ref may not exist; use `dev` or `origin/dev` for diffs.
5-
- Prefer automation: execute requested actions without confirmation unless blocked by missing info or safety/irreversibility.
64

75
## Commits and PR Titles
86

bun.lock

Lines changed: 31 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

infra/stage.ts

Lines changed: 2 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -7,50 +7,8 @@ export const domain = (() => {
77
export const zoneID = "430ba34c138cfb5360826c4909f99be8"
88
// Dev owns the shared AWS lake/stats infra for all non-production stages.
99
export const awsStage = $app.stage === "production" ? "production" : "dev"
10-
export const deployAws = $app.stage === awsStage
11-
12-
const githubActionsDeployRole = (() => {
13-
if ($app.stage !== "dev" && $app.stage !== "production") return
14-
15-
const provider = new aws.iam.OpenIdConnectProvider("GithubActionsOidcProvider", {
16-
url: "https://token.actions.githubusercontent.com",
17-
clientIdLists: ["sts.amazonaws.com"],
18-
})
19-
const role = new aws.iam.Role("GithubActionsDeployRole", {
20-
name: `opencode-${$app.stage}-github-actions-deploy`,
21-
maxSessionDuration: 3600,
22-
assumeRolePolicy: aws.iam.getPolicyDocumentOutput({
23-
statements: [
24-
{
25-
effect: "Allow",
26-
actions: ["sts:AssumeRoleWithWebIdentity"],
27-
principals: [{ type: "Federated", identifiers: [provider.arn] }],
28-
conditions: [
29-
{
30-
test: "StringEquals",
31-
variable: "token.actions.githubusercontent.com:aud",
32-
values: ["sts.amazonaws.com"],
33-
},
34-
{
35-
test: "StringEquals",
36-
variable: "token.actions.githubusercontent.com:sub",
37-
values: [`repo:anomalyco/opencode:environment:${$app.stage}`],
38-
},
39-
],
40-
},
41-
],
42-
}).json,
43-
})
44-
45-
new aws.iam.RolePolicyAttachment("GithubActionsDeployRoleAdmin", {
46-
role: role.name,
47-
policyArn: "arn:aws:iam::aws:policy/AdministratorAccess",
48-
})
49-
50-
return role
51-
})()
52-
53-
export const githubActionsDeployRoleArn = githubActionsDeployRole?.arn
10+
// Temporarily omit AWS infra so SST removes the lake/stats resources.
11+
export const deployAws = false
5412

5513
new cloudflare.RegionalHostname("RegionalHostname", {
5614
hostname: domain,

nix/hashes.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{
22
"nodeModules": {
3-
"x86_64-linux": "sha256-6s5msV+dYMHHt9Gc/CqvCrUj8K7ELjxoAe6ejHSJo4I=",
4-
"aarch64-linux": "sha256-SP94UPy5LePd7ZdC3eENIXiozc67blpg1SN9Ug5yiv8=",
5-
"aarch64-darwin": "sha256-jv3lffiAQ5kxDAbXNavsHD+tjjdgT0dT0JxN0bWMYTE=",
6-
"x86_64-darwin": "sha256-aYNtcarg516ZmqaO62mnUZYiSyWt8rJjUHQslhrhGHM="
3+
"x86_64-linux": "sha256-FT8N4SBP7OmVu73OwNyPJvBoxFd2+IXzNnFubB8y6J0=",
4+
"aarch64-linux": "sha256-rGst01voY1/qr/fIMEgfL2zep/+W2RhjJh5pKs+/P3s=",
5+
"aarch64-darwin": "sha256-+oTdR3CuR88Ra3QQsDn7ixNwJf0YjOxySTSiRsPPUOg=",
6+
"x86_64-darwin": "sha256-3ZkB83KWtp6N7u9xhzmCouv27UuisXYvr2SBap4k++E="
77
}
88
}

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@
144144
"@standard-community/standard-openapi@0.2.9": "patches/@standard-community%2Fstandard-openapi@0.2.9.patch",
145145
"solid-js@1.9.10": "patches/solid-js@1.9.10.patch",
146146
"virtua@0.49.1": "patches/virtua@0.49.1.patch",
147-
"@ai-sdk/xai@3.0.82": "patches/@ai-sdk%2Fxai@3.0.82.patch"
147+
"@ai-sdk/xai@3.0.82": "patches/@ai-sdk%2Fxai@3.0.82.patch",
148+
"gcp-metadata@8.1.2": "patches/gcp-metadata@8.1.2.patch"
148149
}
149150
}

packages/app/e2e/regression/session-timeline-collapse-state.spec.ts

Lines changed: 9 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { expect, test, type Locator, type Page, type Route } from "@playwright/test"
1+
import { expect, test, type Locator, type Page } from "@playwright/test"
2+
import { mockOpenCodeServer } from "../utils/mock-server"
23

34
const directory = "C:/OpenCode/TimelineStateRegression"
45
const projectID = "proj_timeline_state_regression"
@@ -299,39 +300,13 @@ function readExpanded(element: Element) {
299300
}
300301

301302
async function mockServer(page: Page, events: EventPayload[]) {
302-
await page.route("**/*", async (route) => {
303-
const url = new URL(route.request().url())
304-
const targetPort = process.env.PLAYWRIGHT_SERVER_PORT ?? "4096"
305-
if (url.port !== targetPort) return route.fallback()
306-
307-
const path = url.pathname
308-
if (path === "/global/event") return sse(route, events.splice(0))
309-
if (
310-
path === "/global/config" ||
311-
path === "/config" ||
312-
path === "/provider/auth" ||
313-
path === "/mcp" ||
314-
path === "/session/status"
315-
)
316-
return json(route, {})
317-
if (
318-
["/skill", "/command", "/lsp", "/formatter", "/permission", "/question", "/vcs/status", "/vcs/diff"].includes(
319-
path,
320-
)
321-
)
322-
return json(route, [])
323-
if (path === "/provider") return json(route, provider())
324-
if (path === "/path")
325-
return json(route, { state: directory, config: directory, worktree: directory, directory, home: "C:/OpenCode" })
326-
if (path === "/project") return json(route, [project()])
327-
if (path === "/project/current") return json(route, project())
328-
if (path === "/agent") return json(route, [{ name: "build", mode: "primary" }])
329-
if (path === "/vcs") return json(route, { branch: "main", default_branch: "main" })
330-
if (path === "/session") return json(route, [session()])
331-
if (path === `/session/${sessionID}`) return json(route, session())
332-
if (/^\/session\/[^/]+\/(children|todo|diff)$/.test(path)) return json(route, [])
333-
if (path === `/session/${sessionID}/message`) return json(route, [userMessage, assistantMessage])
334-
return json(route, {})
303+
await mockOpenCodeServer(page, {
304+
directory,
305+
project: project(),
306+
provider: provider(),
307+
sessions: [session()],
308+
pageMessages: () => ({ items: [userMessage, assistantMessage] }),
309+
events: () => events.splice(0),
335310
})
336311
}
337312

@@ -372,24 +347,6 @@ function provider() {
372347
}
373348
}
374349

375-
function json(route: Route, body: unknown, headers?: Record<string, string>) {
376-
return route.fulfill({
377-
status: 200,
378-
contentType: "application/json",
379-
headers: { "access-control-allow-origin": "*", "access-control-expose-headers": "x-next-cursor", ...headers },
380-
body: JSON.stringify(body ?? null),
381-
})
382-
}
383-
384-
function sse(route: Route, events: EventPayload[]) {
385-
return route.fulfill({
386-
status: 200,
387-
contentType: "text/event-stream",
388-
headers: { "access-control-allow-origin": "*" },
389-
body: events.map((event) => `data: ${JSON.stringify(event)}\n\n`).join(""),
390-
})
391-
}
392-
393350
function base64Encode(value: string) {
394351
return Buffer.from(value, "utf8").toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "")
395352
}

packages/app/e2e/regression/session-timeline-context-resize.spec.ts

Lines changed: 8 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { expect, test, type Page, type Route } from "@playwright/test"
1+
import { expect, test, type Page } from "@playwright/test"
2+
import { mockOpenCodeServer } from "../utils/mock-server"
23

34
const directory = "C:/OpenCode/ContextResizeRegression"
45
const projectID = "proj_context_resize_regression"
@@ -207,33 +208,12 @@ function contextTool(partID: string, messageID: string, tool: string, input: Rec
207208
}
208209

209210
async function mockServer(page: Page) {
210-
await page.route("**/*", async (route) => {
211-
const url = new URL(route.request().url())
212-
const targetPort = process.env.PLAYWRIGHT_SERVER_PORT ?? "4096"
213-
if (url.port !== targetPort) return route.fallback()
214-
215-
const path = url.pathname
216-
if (path === "/global/event" || path === "/event") return sse(route)
217-
if (["/global/config", "/config", "/provider/auth", "/mcp", "/session/status"].includes(path))
218-
return json(route, {})
219-
if (
220-
["/skill", "/command", "/lsp", "/formatter", "/permission", "/question", "/vcs/status", "/vcs/diff"].includes(
221-
path,
222-
)
223-
)
224-
return json(route, [])
225-
if (path === "/provider") return json(route, provider())
226-
if (path === "/path")
227-
return json(route, { state: directory, config: directory, worktree: directory, directory, home: "C:/OpenCode" })
228-
if (path === "/project") return json(route, [project()])
229-
if (path === "/project/current") return json(route, project())
230-
if (path === "/agent") return json(route, [{ name: "build", mode: "primary" }])
231-
if (path === "/vcs") return json(route, { branch: "main", default_branch: "main" })
232-
if (path === "/session") return json(route, [session()])
233-
if (path === `/session/${sessionID}`) return json(route, session())
234-
if (/^\/session\/[^/]+\/(children|todo|diff)$/.test(path)) return json(route, [])
235-
if (path === `/session/${sessionID}/message`) return json(route, messages)
236-
return json(route, {})
211+
await mockOpenCodeServer(page, {
212+
directory,
213+
project: project(),
214+
provider: provider(),
215+
sessions: [session()],
216+
pageMessages: () => ({ items: messages }),
237217
})
238218
}
239219

@@ -282,19 +262,6 @@ function provider() {
282262
}
283263
}
284264

285-
function json(route: Route, body: unknown, headers?: Record<string, string>) {
286-
return route.fulfill({
287-
status: 200,
288-
contentType: "application/json",
289-
headers: { "access-control-allow-origin": "*", "access-control-expose-headers": "x-next-cursor", ...headers },
290-
body: JSON.stringify(body ?? null),
291-
})
292-
}
293-
294-
function sse(route: Route) {
295-
return route.fulfill({ status: 200, contentType: "text/event-stream", body: ": ok\n\n" })
296-
}
297-
298265
function base64Encode(value: string) {
299266
return Buffer.from(value, "utf8").toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "")
300267
}

packages/app/e2e/utils/mock-server.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export interface MockServerConfig {
1818
project: unknown
1919
sessions: ({ id: string } & Record<string, unknown>)[]
2020
pageMessages: (sessionId: string, limit: number, before?: string) => { items: unknown[]; cursor?: string }
21+
events?: () => unknown[]
2122
}
2223

2324
export async function mockOpenCodeServer(page: Page, config: MockServerConfig) {
@@ -43,7 +44,8 @@ export async function mockOpenCodeServer(page: Page, config: MockServerConfig) {
4344
if (url.port !== targetPort) return route.fallback()
4445

4546
const path = url.pathname
46-
if (path === "/global/event" || path === "/event") return sse(route)
47+
if (path === "/global/event" || path === "/event") return sse(route, config.events?.())
48+
if (path === "/global/health") return json(route, { healthy: true })
4749
if (emptyObject.has(path)) return json(route, {})
4850
if (emptyList.has(path)) return json(route, [])
4951
if (path in staticRoutes) return json(route, staticRoutes[path])
@@ -81,6 +83,10 @@ function json(route: Route, body: unknown, headers?: Record<string, string>) {
8183
})
8284
}
8385

84-
function sse(route: Route) {
85-
return route.fulfill({ status: 200, contentType: "text/event-stream", body: ": ok\n\n" })
86+
function sse(route: Route, events?: unknown[]) {
87+
return route.fulfill({
88+
status: 200,
89+
contentType: "text/event-stream",
90+
body: events?.map((event) => `data: ${JSON.stringify(event)}\n\n`).join("") || ": ok\n\n",
91+
})
8692
}
854 KB
Binary file not shown.

0 commit comments

Comments
 (0)