mirror of
https://github.com/anomalyco/opencode.git
synced 2026-08-24 18:46:26 +00:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f4f781da7b |
@@ -95,7 +95,7 @@ await Effect.runPromise(
|
||||
),
|
||||
write(
|
||||
emitEffectImported(effectContract, {
|
||||
module: "../../contract.js",
|
||||
module: "../../contract",
|
||||
api: "ClientApi",
|
||||
shapeModule: "../api/api.js",
|
||||
}),
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Effect, Stream, Schema } from "effect"
|
||||
import { Sse } from "effect/unstable/encoding"
|
||||
import { HttpClientError } from "effect/unstable/http"
|
||||
import { HttpApiClient } from "effect/unstable/httpapi"
|
||||
import { ClientApi } from "../../contract.js"
|
||||
import { ClientApi } from "../../contract"
|
||||
import type {
|
||||
HealthGetOutput,
|
||||
ServerGetOutput,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Core or Server. Preserve these datatype exports so internal model reorganizations do not require caller migrations.
|
||||
import type { Effect } from "effect"
|
||||
|
||||
export * from "./generated/index.js"
|
||||
export * from "./generated/index"
|
||||
export type {
|
||||
AgentApi,
|
||||
AppApi,
|
||||
@@ -47,4 +47,4 @@ export { Skill } from "@opencode-ai/schema/skill"
|
||||
export { Prompt } from "@opencode-ai/schema/prompt"
|
||||
export { PromptInput } from "@opencode-ai/schema/prompt-input"
|
||||
export type { OpenCodeEvent } from "@opencode-ai/protocol/groups/event"
|
||||
export type OpenCodeClient = Effect.Success<ReturnType<typeof import("./generated/client.js").make>>
|
||||
export type OpenCodeClient = Effect.Success<ReturnType<typeof import("./generated/client").make>>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
export * as Watcher from "./watcher.js"
|
||||
|
||||
// @ts-ignore
|
||||
import { createWrapper } from "@parcel/watcher/wrapper.js"
|
||||
import { createWrapper } from "@parcel/watcher/wrapper"
|
||||
import type ParcelWatcher from "@parcel/watcher"
|
||||
import { FileSystem } from "@opencode-ai/schema/filesystem"
|
||||
import { makeGlobalNode } from "@opencode-ai/util/effect/app-node"
|
||||
|
||||
@@ -71,34 +71,6 @@ try {
|
||||
JSON.stringify({ name: "opencode-sdk-consumer", private: true, type: "module" }),
|
||||
)
|
||||
await Promise.all([
|
||||
Bun.write(
|
||||
join(consumer, "node-import.mjs"),
|
||||
'await import("@opencode-ai/sdk")\nawait import("@opencode-ai/simulation/backend")\n',
|
||||
),
|
||||
Bun.write(
|
||||
join(consumer, "consumer.ts"),
|
||||
`import { OpenCode, Tool } from "@opencode-ai/sdk"
|
||||
import { OpenCodeWorkerd } from "@opencode-ai/sdk/workerd"
|
||||
|
||||
OpenCode.create satisfies Function
|
||||
OpenCodeWorkerd.create satisfies Function
|
||||
Tool.Error satisfies Function
|
||||
`,
|
||||
),
|
||||
Bun.write(
|
||||
join(consumer, "tsconfig.json"),
|
||||
JSON.stringify({
|
||||
compilerOptions: {
|
||||
target: "ES2022",
|
||||
module: "NodeNext",
|
||||
moduleResolution: "NodeNext",
|
||||
strict: true,
|
||||
noEmit: true,
|
||||
lib: ["ES2022", "DOM", "ESNext.Disposable"],
|
||||
},
|
||||
include: ["consumer.ts"],
|
||||
}),
|
||||
),
|
||||
Bun.write(
|
||||
join(consumer, "wrangler.jsonc"),
|
||||
JSON.stringify({
|
||||
@@ -176,10 +148,7 @@ try {
|
||||
|
||||
const sdk = archives.get("@opencode-ai/sdk")
|
||||
if (!sdk) throw new Error("Packed SDK archive was not created")
|
||||
await $`npm install --ignore-scripts --no-audit --no-fund --package-lock=false ${sdk} @types/json-schema@7.0.15 typescript@5.8.2 wrangler@4.110.0`.cwd(consumer)
|
||||
await $`node node-import.mjs`.cwd(consumer)
|
||||
await $`node_modules/.bin/tsc --noEmit`.cwd(consumer)
|
||||
|
||||
await $`npm install --ignore-scripts --no-audit --no-fund --package-lock=false ${sdk} wrangler@4.110.0`.cwd(consumer)
|
||||
await $`node_modules/.bin/wrangler deploy --dry-run --config wrangler.jsonc --outdir dist`.cwd(consumer)
|
||||
|
||||
const transpiler = new Bun.Transpiler({ loader: "js" })
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
export * as OpenCode from "./opencode.js"
|
||||
export * as Tool from "./tool.js"
|
||||
export * as OpenCode from "./opencode"
|
||||
export * as Tool from "./tool"
|
||||
|
||||
export { ClientError } from "@opencode-ai/client/effect"
|
||||
export type { OpenCodeEvent } from "@opencode-ai/client/effect"
|
||||
|
||||
@@ -9,10 +9,10 @@ import { createEmbeddedRoutes } from "@opencode-ai/server/routes"
|
||||
import type { LayerNode } from "@opencode-ai/util/effect/layer-node"
|
||||
import { Config, Context, Effect, Layer, ManagedRuntime, Scope } from "effect"
|
||||
import { FetchHttpClient, HttpEffect, HttpRouter, HttpServer, HttpServerRequest } from "effect/unstable/http"
|
||||
import * as Logging from "./logging.js"
|
||||
import * as Logging from "./logging"
|
||||
|
||||
export type { LogEntry, LogLevel, LogOptions, LogWriter } from "./logging.js"
|
||||
import type { LogOptions } from "./logging.js"
|
||||
export type { LogEntry, LogLevel, LogOptions, LogWriter } from "./logging"
|
||||
import type { LogOptions } from "./logging"
|
||||
|
||||
export interface CreateOptions {
|
||||
readonly app?: {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
export * as OpenCodeWorkerd from "./workerd.js"
|
||||
export * as OpenCodeWorkerd from "./workerd"
|
||||
|
||||
import type { DurableObjectStorage } from "@opencode-ai/core/database/sqlite.workerd"
|
||||
import { ServerWorkerd } from "@opencode-ai/server/workerd"
|
||||
import { Config, Effect, Layer, Scope } from "effect"
|
||||
import * as OpenCode from "./opencode.js"
|
||||
import * as OpenCode from "./opencode"
|
||||
|
||||
export interface CreateOptions extends Pick<OpenCode.CreateOptions, "log" | "workspaceProviders"> {
|
||||
readonly storage: DurableObjectStorage
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
import { $ } from "bun"
|
||||
import { rm } from "node:fs/promises"
|
||||
import { extname } from "node:path"
|
||||
import { fileURLToPath } from "node:url"
|
||||
|
||||
process.chdir(fileURLToPath(new URL("..", import.meta.url)))
|
||||
@@ -14,26 +13,10 @@ const files = await Array.fromAsync(new Bun.Glob("**/*.ts").scan({ cwd: "src" })
|
||||
)
|
||||
const transpiler = new Bun.Transpiler({ loader: "ts", target: "bun" })
|
||||
await Promise.all(
|
||||
files
|
||||
.map(async (file) =>
|
||||
Bun.write(
|
||||
file.replace(/^src\//, "dist/").replace(/\.ts$/, ".js"),
|
||||
withRelativeExtensions(await transpiler.transform(await Bun.file(file).text())),
|
||||
),
|
||||
)
|
||||
.concat(
|
||||
await Array.fromAsync(new Bun.Glob("**/*.d.ts").scan({ cwd: "dist" })).then((declarations) =>
|
||||
declarations.map(async (file) =>
|
||||
Bun.write(`dist/${file}`, withRelativeExtensions(await Bun.file(`dist/${file}`).text())),
|
||||
),
|
||||
),
|
||||
files.map(async (file) =>
|
||||
Bun.write(
|
||||
file.replace(/^src\//, "dist/").replace(/\.ts$/, ".js"),
|
||||
await transpiler.transform(await Bun.file(file).text()),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
function withRelativeExtensions(source: string) {
|
||||
return source.replaceAll(
|
||||
/((?:from\s*|import\s*(?:\(\s*)?)["'])(\.{1,2}\/[^"']+)(["'])/g,
|
||||
(match, prefix: string, specifier: string, suffix: string) =>
|
||||
extname(specifier) ? match : `${prefix}${specifier}.js${suffix}`,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4,10 +4,10 @@ import { httpClient } from "@opencode-ai/util/effect/app-node-platform"
|
||||
import { SdkPlugins } from "@opencode-ai/core/plugin/sdk"
|
||||
import { Config, Effect, FileSystem, Layer } from "effect"
|
||||
import { HttpClient } from "effect/unstable/http"
|
||||
import { DriveManifest } from "../manifest.js"
|
||||
import { SimulationNetwork } from "./network.js"
|
||||
import { SimulationOpenAI } from "./openai.js"
|
||||
import { SimulatedProvider } from "./simulated-provider.js"
|
||||
import { DriveManifest } from "../manifest"
|
||||
import { SimulationNetwork } from "./network"
|
||||
import { SimulationOpenAI } from "./openai"
|
||||
import { SimulatedProvider } from "./simulated-provider"
|
||||
|
||||
/**
|
||||
* Layer replacements applied when the server is built in simulation mode.
|
||||
@@ -56,4 +56,4 @@ export const simulationReplacements: (app: {
|
||||
return [[httpClient, networkNode]] satisfies LayerNode.Replacements
|
||||
})
|
||||
|
||||
export * as Simulation from "./index.js"
|
||||
export * as Simulation from "./index"
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Clock, Effect, Layer, Ref } from "effect"
|
||||
import { HttpClient, HttpClientResponse, type HttpMethod } from "effect/unstable/http"
|
||||
import { HttpClientError, TransportError } from "effect/unstable/http/HttpClientError"
|
||||
import type { HttpClientRequest } from "effect/unstable/http"
|
||||
import { SimulationProtocol } from "../protocol/index.js"
|
||||
import { SimulationProtocol } from "../protocol"
|
||||
|
||||
/**
|
||||
* Simulated network.
|
||||
@@ -82,4 +82,4 @@ export const make = Effect.fn("SimulationNetwork.make")(function* (routes: reado
|
||||
export const layer = (routes: readonly Route[] = []) =>
|
||||
Layer.effect(HttpClient.HttpClient, make(routes).pipe(Effect.map((run) => run.client)))
|
||||
|
||||
export * as SimulationNetwork from "./network.js"
|
||||
export * as SimulationNetwork from "./network"
|
||||
|
||||
@@ -2,8 +2,8 @@ import { Effect, Schema, Stream } from "effect"
|
||||
import { HttpClientResponse } from "effect/unstable/http"
|
||||
import { HttpClientError, TransportError } from "effect/unstable/http/HttpClientError"
|
||||
import { OpenAIChatEvent, DEFAULT_BASE_URL, PATH } from "@opencode-ai/ai/protocols/openai-chat"
|
||||
import { SimulationNetwork } from "./network.js"
|
||||
import { SimulatedProvider } from "./simulated-provider.js"
|
||||
import { SimulationNetwork } from "./network"
|
||||
import { SimulatedProvider } from "./simulated-provider"
|
||||
|
||||
/**
|
||||
* Driver-answered OpenAI endpoint for the simulated network.
|
||||
@@ -130,4 +130,4 @@ export const route = (provider: SimulatedProvider.Interface): SimulationNetwork.
|
||||
},
|
||||
})
|
||||
|
||||
export * as SimulationOpenAI from "./openai.js"
|
||||
export * as SimulationOpenAI from "./openai"
|
||||
|
||||
@@ -20,8 +20,8 @@ import {
|
||||
Semaphore,
|
||||
Stream,
|
||||
} from "effect"
|
||||
import { SimulationControlServer } from "../control-server.js"
|
||||
import { SimulationProtocol } from "../protocol/index.js"
|
||||
import { SimulationControlServer } from "../control-server"
|
||||
import { SimulationProtocol } from "../protocol"
|
||||
|
||||
export interface ProviderRequest {
|
||||
readonly url: string
|
||||
@@ -916,4 +916,4 @@ function releaseController(
|
||||
)
|
||||
}
|
||||
|
||||
export * as SimulatedProvider from "./simulated-provider.js"
|
||||
export * as SimulatedProvider from "./simulated-provider"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Effect, Fiber, FiberSet, Queue, Stream } from "effect"
|
||||
import { SimulationProtocol } from "./protocol/index.js"
|
||||
import { SimulationProtocol } from "./protocol"
|
||||
|
||||
export interface Server {
|
||||
readonly url: string
|
||||
@@ -181,4 +181,4 @@ function send(socket: Socket, response: SimulationProtocol.JsonRpc.Response | un
|
||||
return socket.send(JSON.stringify(response))
|
||||
}
|
||||
|
||||
export * as SimulationControlServer from "./control-server.js"
|
||||
export * as SimulationControlServer from "./control-server"
|
||||
|
||||
@@ -107,4 +107,4 @@ export const resolve = Effect.fn("DriveManifest.resolve")(function* () {
|
||||
)
|
||||
})
|
||||
|
||||
export * as DriveManifest from "./manifest.js"
|
||||
export * as DriveManifest from "./manifest"
|
||||
|
||||
@@ -14,6 +14,6 @@ export function roots(app: string) {
|
||||
cache: path.join(cache!, app),
|
||||
config: path.join(config!, app),
|
||||
state: path.join(state!, app),
|
||||
tmp: path.join(os.tmpdir(), app),
|
||||
tmp: path.join(process.env.XDG_RUNTIME_DIR || os.tmpdir(), app),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,12 +65,21 @@ const acquire = (input: Partial<Interface>) =>
|
||||
const service = Service.of(make(input))
|
||||
yield* Effect.promise(() =>
|
||||
Promise.all(
|
||||
[service.data, service.config, service.state, service.log, service.bin, service.repos, service.tmp].map(
|
||||
(directory) => fs.promises.mkdir(directory, { recursive: true }),
|
||||
[service.data, service.config, service.state, service.log, service.bin, service.repos].map((directory) =>
|
||||
fs.promises.mkdir(directory, { recursive: true }),
|
||||
),
|
||||
),
|
||||
)
|
||||
const canonicalTmp = yield* Effect.promise(() => fs.promises.realpath(service.tmp))
|
||||
const temporary = yield* Effect.promise(async () => {
|
||||
if (input.tmp !== undefined || process.env.XDG_RUNTIME_DIR) {
|
||||
await fs.promises.mkdir(service.tmp, { recursive: true })
|
||||
return service.tmp
|
||||
}
|
||||
await fs.promises.mkdir(path.dirname(service.tmp), { recursive: true })
|
||||
return fs.promises.mkdtemp(`${service.tmp}-`)
|
||||
})
|
||||
yield* Effect.promise(() => fs.promises.access(temporary, fs.constants.W_OK | fs.constants.X_OK))
|
||||
const canonicalTmp = yield* Effect.promise(() => fs.promises.realpath(temporary))
|
||||
return Service.of({ ...service, tmp: input.tmp ?? canonicalTmp })
|
||||
})
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ describe("global roots", () => {
|
||||
XDG_CACHE_HOME: path.join(root, "cache"),
|
||||
XDG_CONFIG_HOME: path.join(root, "config"),
|
||||
XDG_STATE_HOME: path.join(root, "state"),
|
||||
XDG_RUNTIME_DIR: path.join(root, "runtime"),
|
||||
}
|
||||
|
||||
expect(run(env)).toEqual({
|
||||
@@ -20,7 +21,7 @@ describe("global roots", () => {
|
||||
cache: path.join(env.XDG_CACHE_HOME, "opencode"),
|
||||
config: path.join(env.XDG_CONFIG_HOME, "opencode"),
|
||||
state: path.join(env.XDG_STATE_HOME, "opencode"),
|
||||
tmp: path.join(os.tmpdir(), "opencode"),
|
||||
tmp: path.join(env.XDG_RUNTIME_DIR, "opencode"),
|
||||
})
|
||||
})
|
||||
|
||||
@@ -33,6 +34,7 @@ describe("global roots", () => {
|
||||
XDG_CACHE_HOME: "",
|
||||
XDG_CONFIG_HOME: "",
|
||||
XDG_STATE_HOME: "",
|
||||
XDG_RUNTIME_DIR: "",
|
||||
...(process.platform === "win32" ? { USERPROFILE: home } : { HOME: home }),
|
||||
}),
|
||||
).toEqual({
|
||||
|
||||
@@ -19,6 +19,7 @@ describe("global", () => {
|
||||
XDG_CACHE_HOME: directories[1],
|
||||
XDG_CONFIG_HOME: directories[2],
|
||||
XDG_STATE_HOME: directories[3],
|
||||
XDG_RUNTIME_DIR: "",
|
||||
TMPDIR: directories[4],
|
||||
},
|
||||
stderr: "pipe",
|
||||
@@ -70,6 +71,7 @@ describe("global", () => {
|
||||
XDG_CACHE_HOME: directories[1],
|
||||
XDG_CONFIG_HOME: directories[2],
|
||||
XDG_STATE_HOME: directories[3],
|
||||
XDG_RUNTIME_DIR: "",
|
||||
TMPDIR: directories[4],
|
||||
},
|
||||
stdout: "pipe",
|
||||
@@ -77,7 +79,9 @@ describe("global", () => {
|
||||
})
|
||||
|
||||
expect(result.exitCode, result.stderr.toString()).toBe(0)
|
||||
expect(result.stdout.toString()).toBe(fs.realpathSync(path.join(directories[4], "opencode")))
|
||||
const temporary = result.stdout.toString()
|
||||
expect(path.dirname(temporary)).toBe(fs.realpathSync(directories[4]))
|
||||
expect(path.basename(temporary)).toMatch(/^opencode-.{6}$/)
|
||||
const created = [
|
||||
path.join(directories[0], "opencode"),
|
||||
path.join(directories[1], "opencode", "bin"),
|
||||
@@ -85,7 +89,7 @@ describe("global", () => {
|
||||
path.join(directories[3], "opencode"),
|
||||
path.join(directories[0], "opencode", "log"),
|
||||
path.join(directories[0], "opencode", "repos"),
|
||||
path.join(directories[4], "opencode"),
|
||||
temporary,
|
||||
]
|
||||
created.forEach((directory) => expect(fs.statSync(directory).isDirectory()).toBe(true))
|
||||
fs.rmSync(root, { recursive: true, force: true })
|
||||
|
||||
Reference in New Issue
Block a user