Skip to content

Commit 894b720

Browse files
authored
Merge branch 'dev' into feat/kiro-provider
2 parents 1543eaa + 4781564 commit 894b720

39 files changed

Lines changed: 357 additions & 248 deletions

.github/VOUCHED.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ rekram1-node
3232
-ricardo-m-l
3333
-robinmordasiewicz
3434
rubdos
35+
-saisharan0103 spamming ai prs
3536
shantur
3637
simonklee
3738
-spider-yamet clawdbot/llm psychosis, spam pinging the team

packages/console/app/src/routes/zen/util/handler.ts

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -141,20 +141,34 @@ export async function handler(
141141
)
142142
validateModelSettings(billingSource, authInfo)
143143
updateProviderKey(authInfo, providerInfo)
144-
logger.metric({ provider: providerInfo.id })
144+
logger.metric({
145+
provider: providerInfo.id,
146+
"provider.model": providerInfo.model,
147+
})
145148

146149
const startTimestamp = Date.now()
147150
const reqUrl = providerInfo.modifyUrl(providerInfo.api, isStream)
148151
const reqBody = JSON.stringify(
149152
providerInfo.modifyBody({
150153
...createBodyConverter(opts.format, providerInfo.format)(body),
151154
model: providerInfo.model,
152-
...providerInfo.payloadModifier,
153-
...Object.fromEntries(
154-
Object.entries(providerInfo.payloadMappings ?? {})
155-
.map(([k, v]) => [k, input.request.headers.get(v)])
156-
.filter(([_k, v]) => !!v),
157-
),
155+
...(() => {
156+
const replacer = (obj: Record<string, any>): Record<string, any> =>
157+
Object.fromEntries(
158+
Object.entries(obj).flatMap(([k, v]) => {
159+
if (Array.isArray(v)) return [[k, v]]
160+
if (typeof v === "object") return [[k, replacer(v)]]
161+
if (v === "$ip") return [[k, ip]]
162+
if (v === "$workspace") return authInfo?.workspaceID ? [[k, authInfo?.workspaceID]] : []
163+
if (v.startsWith("$header.")) {
164+
const headerValue = input.request.headers.get(v.slice(8))
165+
return headerValue ? [[k, headerValue]] : []
166+
}
167+
return [[k, v]]
168+
}),
169+
)
170+
return replacer(providerInfo.payloadModifier ?? {})
171+
})(),
158172
}),
159173
)
160174
logger.debug("REQUEST URL: " + reqUrl)
@@ -514,7 +528,6 @@ export async function handler(
514528
reqModel,
515529
providerModel: modelProvider.model,
516530
adjustCacheUsage: providerProps.adjustCacheUsage,
517-
safetyIdentifier: modelProvider.safetyIdentifier ? ip : undefined,
518531
workspaceID: authInfo?.workspaceID,
519532
}
520533
if (format === "anthropic") return anthropicHelper(opts)

packages/console/app/src/routes/zen/util/provider/openai-compatible.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ type Usage = {
2323
}
2424
}
2525

26-
export const oaCompatHelper: ProviderHelper = ({ adjustCacheUsage, safetyIdentifier }) => ({
26+
export const oaCompatHelper: ProviderHelper = ({ adjustCacheUsage }) => ({
2727
format: "oa-compat",
2828
modifyUrl: (providerApi: string) => providerApi + "/chat/completions",
2929
modifyHeaders: (headers: Headers, body: Record<string, any>, apiKey: string) => {
@@ -34,7 +34,6 @@ export const oaCompatHelper: ProviderHelper = ({ adjustCacheUsage, safetyIdentif
3434
return {
3535
...body,
3636
...(body.stream ? { stream_options: { include_usage: true } } : {}),
37-
...(safetyIdentifier ? { safety_identifier: safetyIdentifier } : {}),
3837
}
3938
},
4039
createBinaryStreamDecoder: () => undefined,

packages/console/app/src/routes/zen/util/provider/openai.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,7 @@ export const openaiHelper: ProviderHelper = ({ workspaceID }) => ({
1818
modifyHeaders: (headers: Headers, body: Record<string, any>, apiKey: string) => {
1919
headers.set("authorization", `Bearer ${apiKey}`)
2020
},
21-
modifyBody: (body: Record<string, any>) => ({
22-
...body,
23-
...(workspaceID ? { safety_identifier: workspaceID } : {}),
24-
}),
21+
modifyBody: (body: Record<string, any>) => body,
2522
createBinaryStreamDecoder: () => undefined,
2623
streamSeparator: "\n\n",
2724
createUsageParser: () => {

packages/console/app/src/routes/zen/util/provider/provider.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ export type ProviderHelper = (input: {
3737
reqModel: string
3838
providerModel: string
3939
adjustCacheUsage?: boolean
40-
safetyIdentifier?: string
4140
workspaceID?: string
4241
}) => {
4342
format: ZenData.Format

packages/console/core/src/model.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ export namespace ZenData {
4040
disabled: z.boolean().optional(),
4141
storeModel: z.string().optional(),
4242
payloadModifier: z.record(z.string(), z.any()).optional(),
43-
safetyIdentifier: z.boolean().optional(),
4443
}),
4544
),
4645
})

packages/core/src/npm.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,13 +120,17 @@ export const layer = Layer.effect(
120120
}
121121
})()
122122

123-
if (yield* afs.existsSafe(dir)) {
123+
if (yield* afs.existsSafe(path.join(dir, "node_modules", name))) {
124124
return resolveEntryPoint(name, path.join(dir, "node_modules", name))
125125
}
126126

127127
const tree = yield* reify({ dir, add: [pkg] })
128128
const first = tree.edgesOut.values().next().value?.to
129-
if (!first) return yield* new InstallFailedError({ add: [pkg], dir })
129+
if (!first) {
130+
const result = resolveEntryPoint(name, path.join(dir, "node_modules", name))
131+
if (Option.isSome(result.entrypoint)) return result
132+
return yield* new InstallFailedError({ add: [pkg], dir })
133+
}
130134
return resolveEntryPoint(first.name, first.path)
131135
}, Effect.scoped)
132136

packages/core/test/global.test.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { describe, expect, test } from "bun:test"
2+
import fs from "fs/promises"
3+
import os from "os"
4+
import path from "path"
5+
import { Global } from "@opencode-ai/core/global"
6+
7+
describe("global paths", () => {
8+
test("tmp path is under the system temp directory", () => {
9+
expect(Global.Path.tmp).toBe(path.join(os.tmpdir(), "opencode"))
10+
expect(Global.make().tmp).toBe(Global.Path.tmp)
11+
})
12+
13+
test("tmp path is created on module load", async () => {
14+
expect((await fs.stat(Global.Path.tmp)).isDirectory()).toBe(true)
15+
})
16+
})

packages/core/test/npm.test.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
import fs from "fs/promises"
22
import path from "path"
33
import { describe, expect, test } from "bun:test"
4+
import { NodeFileSystem } from "@effect/platform-node"
5+
import { Effect, Layer, Option } from "effect"
6+
import { AppFileSystem } from "@opencode-ai/core/filesystem"
7+
import { Global } from "@opencode-ai/core/global"
48
import { Npm } from "@opencode-ai/core/npm"
9+
import { EffectFlock } from "@opencode-ai/core/util/effect-flock"
510
import { tmpdir } from "./fixture/tmpdir"
611

712
const win = process.platform === "win32"
@@ -15,6 +20,14 @@ const writePackage = (dir: string, pkg: Record<string, unknown>) =>
1520
}),
1621
)
1722

23+
const npmLayer = (cache: string) =>
24+
Npm.layer.pipe(
25+
Layer.provide(EffectFlock.layer),
26+
Layer.provide(AppFileSystem.layer),
27+
Layer.provide(Global.layerWith({ cache, state: path.join(cache, "state") })),
28+
Layer.provide(NodeFileSystem.layer),
29+
)
30+
1831
describe("Npm.sanitize", () => {
1932
test("keeps normal scoped package specs unchanged", () => {
2033
expect(Npm.sanitize("@opencode/acme")).toBe("@opencode/acme")
@@ -29,6 +42,28 @@ describe("Npm.sanitize", () => {
2942
})
3043
})
3144

45+
describe("Npm.add", () => {
46+
test("reifies when package cache directory exists without the package installed", async () => {
47+
await using tmp = await tmpdir()
48+
await fs.mkdir(path.join(tmp.path, "fixture-provider"))
49+
await writePackage(path.join(tmp.path, "fixture-provider"), {
50+
name: "fixture-provider",
51+
main: "index.js",
52+
})
53+
await Bun.write(path.join(tmp.path, "fixture-provider", "index.js"), "export const fixture = true\n")
54+
55+
const spec = `fixture-provider@file:${path.join(tmp.path, "fixture-provider")}`
56+
await fs.mkdir(path.join(tmp.path, "cache", "packages", Npm.sanitize(spec)), { recursive: true })
57+
58+
const entry = await Effect.gen(function* () {
59+
const npm = yield* Npm.Service
60+
return yield* npm.add(spec)
61+
}).pipe(Effect.scoped, Effect.provide(npmLayer(path.join(tmp.path, "cache"))), Effect.runPromise)
62+
63+
expect(Option.isSome(entry.entrypoint)).toBe(true)
64+
})
65+
})
66+
3267
describe("Npm.install", () => {
3368
test("respects omit from project .npmrc", async () => {
3469
await using tmp = await tmpdir()

packages/opencode/specs/effect/http-api.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ Use raw Effect HTTP routes where `HttpApi` does not fit. The goal is deleting Ho
198198
| `project` | `bridged` | list, current, git init, update |
199199
| `file` | `bridged` partial | find text/file/symbol, list/content/status |
200200
| `mcp` | `bridged` | status, add, OAuth, connect/disconnect |
201-
| `workspace` | `bridged` | adaptor/list/status/create/remove/session-restore |
201+
| `workspace` | `bridged` | adapter/list/status/create/remove/session-restore |
202202
| top-level instance routes | `bridged` | path, vcs, command, agent, skill, lsp, formatter, dispose |
203203
| experimental JSON routes | `bridged` | console, tool, worktree list/mutations, global session list, resource list |
204204
| `session` | `bridged` | read, lifecycle, prompt, message/part mutations, revert, permission reply |
@@ -290,7 +290,7 @@ This checklist tracks bridge parity only. Checked routes are available through t
290290

291291
### Workspace Routes
292292

293-
- [x] `GET /experimental/workspace/adaptor` - list workspace adaptors.
293+
- [x] `GET /experimental/workspace/adapter` - list workspace adapters.
294294
- [x] `POST /experimental/workspace` - create workspace.
295295
- [x] `GET /experimental/workspace` - list workspaces.
296296
- [x] `GET /experimental/workspace/status` - workspace status.

0 commit comments

Comments
 (0)