mirror of
https://gitee.com/zhangsken/opencode.git
synced 2026-10-16 10:30:01 +08:00
chore(core): remove dead modules and exports (#51667)
This commit is contained in:
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@opencode/core": patch
|
||||
---
|
||||
|
||||
Correct directory page headings when the read offset is zero.
|
||||
@@ -66,12 +66,6 @@
|
||||
"node": "./src/shell/parser-wasm.node.ts",
|
||||
"default": "./src/shell/parser-wasm.bun.ts"
|
||||
},
|
||||
"#process-lock-ffi": {
|
||||
"workerd": "./src/util/process-lock-ffi.workerd.ts",
|
||||
"bun": "./src/util/process-lock-ffi.bun.ts",
|
||||
"node": "./src/util/process-lock-ffi.node.ts",
|
||||
"default": "./src/util/process-lock-ffi.bun.ts"
|
||||
},
|
||||
"#v1-migration": {
|
||||
"types": "./src/database/v1-migration.bun.ts",
|
||||
"bun": "./src/database/v1-migration.bun.ts",
|
||||
|
||||
@@ -26,7 +26,6 @@ const result = await Bun.build({
|
||||
"#fff",
|
||||
"#photon-wasm",
|
||||
"#shell-parser-wasm",
|
||||
"#process-lock-ffi",
|
||||
"#v1-migration",
|
||||
],
|
||||
splitting: true,
|
||||
|
||||
@@ -30,12 +30,6 @@ export interface ExternalDirectoryAuthorization {
|
||||
readonly save: string
|
||||
}
|
||||
|
||||
export const externalDirectoryPermission = (input: ExternalDirectoryAuthorization) => ({
|
||||
action: input.action,
|
||||
resources: [input.resource],
|
||||
save: [input.save],
|
||||
})
|
||||
|
||||
export interface Target {
|
||||
readonly absolute: AbsolutePath
|
||||
/** Location-relative for internal paths, absolute for external paths. */
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
/** @deprecated Use FileAccess for path resolution and authorization. */
|
||||
export { FileAccess as LocationMutation } from "./file-access.js"
|
||||
export * from "./file-access.js"
|
||||
@@ -8,7 +8,6 @@ import { LocationServiceMap } from "./location-service-map.js"
|
||||
export { LocationServiceMap } from "./location-service-map.js"
|
||||
|
||||
export type LocationServices = Instance.Services
|
||||
export type LocationError = Instance.Error
|
||||
|
||||
export function buildLocationServiceMap(
|
||||
replacements: LayerNode.Replacements = [],
|
||||
|
||||
@@ -50,15 +50,6 @@ export class StepFailedError extends Schema.TaggedError<StepFailedError>()("Sess
|
||||
}
|
||||
}
|
||||
|
||||
export class UserInterruptedError extends Schema.TaggedError<UserInterruptedError>()(
|
||||
"Session.UserInterruptedError",
|
||||
{},
|
||||
) {
|
||||
override get message() {
|
||||
return "Session interrupted by user"
|
||||
}
|
||||
}
|
||||
|
||||
export class PromptConflictError extends Schema.TaggedError<PromptConflictError>()("Session.PromptConflictError", {
|
||||
sessionID: SessionSchema.ID,
|
||||
messageID: SessionMessage.ID,
|
||||
|
||||
@@ -12,7 +12,6 @@ import { SessionRunner } from "./runner/index.js"
|
||||
import { SessionSchema } from "./schema.js"
|
||||
import { SessionStore } from "./store.js"
|
||||
import { toSessionError } from "./to-session-error.js"
|
||||
import { UserInterruptedError } from "./error.js"
|
||||
import { SessionInbox } from "./inbox.js"
|
||||
|
||||
export interface Interface {
|
||||
@@ -51,9 +50,7 @@ type InterruptReason = "user" | "shutdown" | "inactivity"
|
||||
export function terminal(exit: Exit.Exit<void, SessionRunner.RunError>, reason?: InterruptReason) {
|
||||
if (Exit.isSuccess(exit)) return { type: "succeeded" as const }
|
||||
if (Cause.hasInterrupts(exit.cause)) return { type: "interrupted" as const, reason: reason ?? "shutdown" }
|
||||
const failure = Cause.squash(exit.cause)
|
||||
if (failure instanceof UserInterruptedError) return { type: "interrupted" as const, reason: "user" as const }
|
||||
return { type: "failed" as const, error: toSessionError(failure) }
|
||||
return { type: "failed" as const, error: toSessionError(Cause.squash(exit.cause)) }
|
||||
}
|
||||
|
||||
/** Process-local execution: drains run in this process using the selected instance. */
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { AIError } from "@opencode/ai"
|
||||
import { Context, Data, Effect } from "effect"
|
||||
import { SessionSchema } from "../schema.js"
|
||||
import type { Promotable } from "../inbox.js"
|
||||
import type { AgentNotFoundError, MessageDecodeError, StepFailedError, UserInterruptedError } from "../error.js"
|
||||
import type { AgentNotFoundError, MessageDecodeError, StepFailedError } from "../error.js"
|
||||
import { SessionRunnerModel } from "./model.js"
|
||||
import type { Instructions } from "../../instructions/index.js"
|
||||
|
||||
@@ -14,7 +14,6 @@ export type RunError =
|
||||
| MessageDecodeError
|
||||
| AgentNotFoundError
|
||||
| StepFailedError
|
||||
| UserInterruptedError
|
||||
| Instructions.InitializationBlocked
|
||||
|
||||
export type Continuation = { readonly step: number }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
export * as SessionRunnerRetry from "./retry.js"
|
||||
|
||||
import { AIError, isContextOverflowFailure } from "@opencode/ai"
|
||||
import { AIError } from "@opencode/ai"
|
||||
import { Agent } from "@opencode/schema/agent"
|
||||
import { Model } from "@opencode/schema/model"
|
||||
import { SessionError } from "@opencode/schema/session-error"
|
||||
@@ -10,7 +10,6 @@ import type { PluginHooks } from "../../plugin/hooks.js"
|
||||
import { SessionEvent } from "../event.js"
|
||||
import { SessionMessage } from "../message.js"
|
||||
import { SessionSchema } from "../schema.js"
|
||||
import { toSessionError } from "../to-session-error.js"
|
||||
|
||||
interface Input {
|
||||
readonly cause: AIError
|
||||
@@ -119,24 +118,6 @@ export const policy = (sessionID: SessionSchema.ID) =>
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* Retries one auxiliary request's transient failures under a shared `policy` allowance, letting the
|
||||
* session retry hook adjust each decision. Context overflow is never transient: callers recover it.
|
||||
*/
|
||||
export const transient =
|
||||
(decide: Effect.Success<ReturnType<typeof policy>>, input: Pick<Input, "agent" | "model" | "hook">) =>
|
||||
<A, R>(effect: Effect.Effect<A, AIError, R>) =>
|
||||
Effect.retry(effect, {
|
||||
while: (cause) =>
|
||||
Effect.gen(function* () {
|
||||
if (isContextOverflowFailure(cause)) return false
|
||||
const decision = yield* decide({ ...input, cause, error: toSessionError(cause), retry: isRetryable(cause) })
|
||||
if (!decision.retry) return false
|
||||
yield* Effect.sleep(decision.delay)
|
||||
return true
|
||||
}),
|
||||
})
|
||||
|
||||
export const make = (bus: Bus.Interface, sessionID: SessionSchema.ID) =>
|
||||
Effect.gen(function* () {
|
||||
const decide = yield* policy(sessionID)
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Tool } from "@opencode/schema/tool"
|
||||
import { SessionError } from "@opencode/schema/session-error"
|
||||
import { Permission } from "../permission.js"
|
||||
import { Integration } from "../integration.js"
|
||||
import { AgentNotFoundError, StepFailedError, UserInterruptedError } from "./error.js"
|
||||
import { AgentNotFoundError, StepFailedError } from "./error.js"
|
||||
import { SessionRunnerModel } from "./runner/model.js"
|
||||
|
||||
export function toSessionError(cause: unknown): SessionError.Error {
|
||||
@@ -51,7 +51,6 @@ export function toSessionError(cause: unknown): SessionError.Error {
|
||||
if (cause instanceof SessionRunnerModel.UnsupportedCompactionError)
|
||||
return { type: "provider.unsupported-operation", message: cause.message }
|
||||
if (cause instanceof AgentNotFoundError) return { type: "unknown", message: cause.message }
|
||||
if (cause instanceof UserInterruptedError) return { type: "aborted", message: cause.message }
|
||||
if (
|
||||
cause instanceof SessionRunnerModel.ModelNotSelectedError ||
|
||||
cause instanceof SessionRunnerModel.ModelUnavailableError ||
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
export function findLast<T>(
|
||||
items: readonly T[],
|
||||
predicate: (item: T, index: number, items: readonly T[]) => boolean,
|
||||
): T | undefined {
|
||||
for (let i = items.length - 1; i >= 0; i -= 1) {
|
||||
const item = items[i]
|
||||
if (predicate(item, i, items)) return item
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
import { dlopen, read, type Pointer } from "bun:ffi"
|
||||
import { existsSync } from "node:fs"
|
||||
|
||||
export type LockResult =
|
||||
| { readonly acquired: true }
|
||||
| { readonly acquired: false; readonly held: true }
|
||||
| { readonly acquired: false; readonly held: false; readonly code: number }
|
||||
|
||||
const LOCK_EX = 2
|
||||
const LOCK_NB = 4
|
||||
const DARWIN_EWOULDBLOCK = 35
|
||||
const LINUX_EWOULDBLOCK = 11
|
||||
|
||||
export function lockDarwin(fd: number): LockResult {
|
||||
const library = dlopen("/usr/lib/libSystem.B.dylib", {
|
||||
flock: { args: ["i32", "i32"], returns: "i32" },
|
||||
__error: { args: [], returns: "ptr" },
|
||||
})
|
||||
try {
|
||||
const result = library.symbols.flock(fd, LOCK_EX | LOCK_NB)
|
||||
const code = result === 0 ? 0 : errorCode(library.symbols.__error())
|
||||
if (result === 0) return { acquired: true }
|
||||
if (code === DARWIN_EWOULDBLOCK) return { acquired: false, held: true }
|
||||
return { acquired: false, held: false, code }
|
||||
} finally {
|
||||
library.close()
|
||||
}
|
||||
}
|
||||
|
||||
export function lockLinux(fd: number): LockResult {
|
||||
const musl = `/lib/libc.musl-${process.arch === "arm64" ? "aarch64" : "x86_64"}.so.1`
|
||||
const library = dlopen(existsSync(musl) ? musl : "libc.so.6", {
|
||||
flock: { args: ["i32", "i32"], returns: "i32" },
|
||||
__errno_location: { args: [], returns: "ptr" },
|
||||
})
|
||||
try {
|
||||
const result = library.symbols.flock(fd, LOCK_EX | LOCK_NB)
|
||||
const code = result === 0 ? 0 : errorCode(library.symbols.__errno_location())
|
||||
if (result === 0) return { acquired: true }
|
||||
if (code === LINUX_EWOULDBLOCK) return { acquired: false, held: true }
|
||||
return { acquired: false, held: false, code }
|
||||
} finally {
|
||||
library.close()
|
||||
}
|
||||
}
|
||||
|
||||
function errorCode(pointer: Pointer | bigint | null) {
|
||||
if (pointer === null) throw new Error("Failed to read process lock error code")
|
||||
return read.i32(pointer, 0)
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
import { dlopen, getInt32 } from "node:ffi"
|
||||
|
||||
export type LockResult =
|
||||
| { readonly acquired: true }
|
||||
| { readonly acquired: false; readonly held: true }
|
||||
| { readonly acquired: false; readonly held: false; readonly code: number }
|
||||
|
||||
const LOCK_EX = 2
|
||||
const LOCK_NB = 4
|
||||
const DARWIN_EWOULDBLOCK = 35
|
||||
const LINUX_EWOULDBLOCK = 11
|
||||
|
||||
export function lockDarwin(fd: number): LockResult {
|
||||
const library = dlopen("/usr/lib/libSystem.B.dylib", {
|
||||
flock: { arguments: ["int32", "int32"], return: "int32" },
|
||||
__error: { arguments: [], return: "pointer" },
|
||||
})
|
||||
try {
|
||||
const result = library.functions.flock(fd, LOCK_EX | LOCK_NB)
|
||||
const code = result === 0 ? 0 : getInt32(library.functions.__error(), 0)
|
||||
if (result === 0) return { acquired: true }
|
||||
if (code === DARWIN_EWOULDBLOCK) return { acquired: false, held: true }
|
||||
return { acquired: false, held: false, code }
|
||||
} finally {
|
||||
library.lib.close()
|
||||
}
|
||||
}
|
||||
|
||||
export function lockLinux(fd: number): LockResult {
|
||||
const library = dlopen("libc.so.6", {
|
||||
flock: { arguments: ["int32", "int32"], return: "int32" },
|
||||
__errno_location: { arguments: [], return: "pointer" },
|
||||
})
|
||||
try {
|
||||
const result = library.functions.flock(fd, LOCK_EX | LOCK_NB)
|
||||
const code = result === 0 ? 0 : getInt32(library.functions.__errno_location(), 0)
|
||||
if (result === 0) return { acquired: true }
|
||||
if (code === LINUX_EWOULDBLOCK) return { acquired: false, held: true }
|
||||
return { acquired: false, held: false, code }
|
||||
} finally {
|
||||
library.lib.close()
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
export type LockResult =
|
||||
| { readonly acquired: true }
|
||||
| { readonly acquired: false; readonly held: true }
|
||||
| { readonly acquired: false; readonly held: false; readonly code: number }
|
||||
|
||||
// workerd has no FFI and no cross-process file locking; a Durable Object is
|
||||
// already single-threaded per instance, so nothing on this runtime should
|
||||
// reach these.
|
||||
const unavailable = (_fd: number): LockResult => {
|
||||
throw new Error("Process locks are unavailable on the workerd runtime")
|
||||
}
|
||||
|
||||
export const lockDarwin = unavailable
|
||||
export const lockLinux = unavailable
|
||||
@@ -1,131 +0,0 @@
|
||||
import { lockDarwin, lockLinux, type LockResult } from "#process-lock-ffi"
|
||||
import { closeSync, mkdirSync, openSync } from "node:fs"
|
||||
import { connect, createServer, type Server, type Socket } from "node:net"
|
||||
import path from "node:path"
|
||||
import { Effect, Schema } from "effect"
|
||||
import { Hash } from "@opencode/util/hash"
|
||||
|
||||
export namespace ProcessLock {
|
||||
export class HeldError extends Schema.TaggedError<HeldError>()("ProcessLockHeldError", {
|
||||
file: Schema.String,
|
||||
}) {
|
||||
override get message() {
|
||||
return `Process lock is already held: ${this.file}`
|
||||
}
|
||||
}
|
||||
|
||||
export class SystemError extends Schema.TaggedError<SystemError>()("ProcessLockSystemError", {
|
||||
file: Schema.String,
|
||||
operation: Schema.Literals(["open", "acquire"]),
|
||||
code: Schema.String,
|
||||
}) {
|
||||
override get message() {
|
||||
return `Process lock ${this.operation} failed for ${this.file}: ${this.code}`
|
||||
}
|
||||
}
|
||||
|
||||
export type LockError = HeldError | SystemError
|
||||
|
||||
const acquirePosix = Effect.fnUntraced(function* (file: string) {
|
||||
const fd = yield* Effect.try({
|
||||
try: () => {
|
||||
mkdirSync(path.dirname(file), { recursive: true })
|
||||
return openSync(file, "a+", 0o600)
|
||||
},
|
||||
catch: (cause) =>
|
||||
new SystemError({
|
||||
file,
|
||||
operation: "open",
|
||||
code: cause instanceof Error ? cause.message : String(cause),
|
||||
}),
|
||||
})
|
||||
const result = yield* Effect.try({
|
||||
try: () => lock(fd),
|
||||
catch: (cause) =>
|
||||
new SystemError({
|
||||
file,
|
||||
operation: "acquire",
|
||||
code: cause instanceof Error ? cause.message : String(cause),
|
||||
}),
|
||||
}).pipe(
|
||||
Effect.tapError(() =>
|
||||
Effect.sync(() => {
|
||||
closeSync(fd)
|
||||
}),
|
||||
),
|
||||
)
|
||||
if (result.acquired) return fd
|
||||
closeSync(fd)
|
||||
return yield* result.held
|
||||
? new HeldError({ file })
|
||||
: new SystemError({ file, operation: "acquire", code: String(result.code) })
|
||||
})
|
||||
|
||||
export const acquire = Effect.fn("ProcessLock.acquire")(function* (file: string) {
|
||||
if (process.platform === "win32") {
|
||||
yield* Effect.acquireRelease(acquireWindows(file), closeWindows)
|
||||
return
|
||||
}
|
||||
yield* Effect.acquireRelease(acquirePosix(file), (fd) =>
|
||||
Effect.sync(() => {
|
||||
closeSync(fd)
|
||||
}),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
function lock(fd: number): LockResult {
|
||||
if (process.platform === "darwin") return lockDarwin(fd)
|
||||
if (process.platform === "linux") return lockLinux(fd)
|
||||
throw new Error(`Unsupported process lock platform: ${process.platform}`)
|
||||
}
|
||||
|
||||
function acquireWindows(file: string) {
|
||||
return Effect.callback<Server, ProcessLock.LockError>((resume) => {
|
||||
const server = createServer()
|
||||
let probe: Socket | undefined
|
||||
const pipe = `\\\\.\\pipe\\opencode-process-lock-${Hash.sha256(path.resolve(file).toLowerCase())}`
|
||||
const onError = (cause: NodeJS.ErrnoException) => {
|
||||
server.off("listening", onListening)
|
||||
probe = connect(pipe)
|
||||
const onProbeError = () => {
|
||||
probe?.off("connect", onConnect)
|
||||
resume(
|
||||
Effect.fail(
|
||||
new ProcessLock.SystemError({
|
||||
file,
|
||||
operation: "acquire",
|
||||
code: cause.code ?? cause.message,
|
||||
}),
|
||||
),
|
||||
)
|
||||
}
|
||||
const onConnect = () => {
|
||||
probe?.off("error", onProbeError)
|
||||
probe?.destroy()
|
||||
resume(Effect.fail(new ProcessLock.HeldError({ file })))
|
||||
}
|
||||
probe.once("connect", onConnect)
|
||||
probe.once("error", onProbeError)
|
||||
}
|
||||
const onListening = () => {
|
||||
server.off("error", onError)
|
||||
resume(Effect.succeed(server))
|
||||
}
|
||||
server.once("error", onError)
|
||||
server.once("listening", onListening)
|
||||
server.on("connection", (socket) => socket.destroy())
|
||||
server.listen(pipe)
|
||||
return Effect.sync(() => {
|
||||
probe?.destroy()
|
||||
server.close()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function closeWindows(server: Server) {
|
||||
return Effect.callback<void>((resume) => {
|
||||
if (!server.listening) return resume(Effect.void)
|
||||
server.close((error) => resume(error ? Effect.die(error) : Effect.void))
|
||||
})
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
import { ProcessLock } from "@opencode/core/util/process-lock"
|
||||
import { Effect, Schema } from "effect"
|
||||
import fs from "node:fs/promises"
|
||||
|
||||
const input = Schema.decodeUnknownSync(
|
||||
Schema.fromJsonString(Schema.Struct({ file: Schema.String, ready: Schema.String })),
|
||||
)(process.argv[2])
|
||||
|
||||
await Effect.runPromise(
|
||||
Effect.scoped(
|
||||
Effect.gen(function* () {
|
||||
yield* ProcessLock.acquire(input.file)
|
||||
yield* Effect.promise(() => fs.writeFile(input.ready, String(process.pid)))
|
||||
return yield* Effect.never
|
||||
}),
|
||||
),
|
||||
)
|
||||
@@ -15,7 +15,6 @@ import { AbsolutePath } from "@opencode/core/schema"
|
||||
import { Session } from "@opencode/core/session"
|
||||
import { SessionExecution } from "@opencode/core/session/execution"
|
||||
import { SessionRestart } from "@opencode/core/session/execution/restart"
|
||||
import { UserInterruptedError } from "@opencode/core/session/error"
|
||||
import { SessionEvent } from "@opencode/core/session/event"
|
||||
import { SessionInbox } from "@opencode/core/session/inbox"
|
||||
import { SessionMessage } from "@opencode/core/session/message"
|
||||
@@ -50,10 +49,6 @@ describe("SessionExecution lifecycle", () => {
|
||||
const interrupted = Effect.runSyncExit(Effect.interrupt)
|
||||
expect(SessionExecution.terminal(interrupted)).toEqual({ type: "interrupted", reason: "shutdown" })
|
||||
expect(SessionExecution.terminal(interrupted, "user")).toEqual({ type: "interrupted", reason: "user" })
|
||||
expect(SessionExecution.terminal(Exit.fail(new UserInterruptedError()))).toEqual({
|
||||
type: "interrupted",
|
||||
reason: "user",
|
||||
})
|
||||
})
|
||||
|
||||
it.effect("the sweep only lists claimed top-level Sessions", () =>
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
import { expect } from "bun:test"
|
||||
import { ProcessLock } from "@opencode/core/util/process-lock"
|
||||
import { Effect } from "effect"
|
||||
import fs from "node:fs/promises"
|
||||
import os from "node:os"
|
||||
import path from "node:path"
|
||||
import { it } from "../lib/effect"
|
||||
|
||||
const worker = path.join(import.meta.dir, "../fixture/process-lock-worker.ts")
|
||||
|
||||
it.live(
|
||||
"releases ownership when the scope closes",
|
||||
Effect.gen(function* () {
|
||||
const root = yield* temp("opencode-process-lock-")
|
||||
const file = path.join(root, "service.lock")
|
||||
yield* Effect.scoped(ProcessLock.acquire(file))
|
||||
yield* Effect.scoped(ProcessLock.acquire(file))
|
||||
}),
|
||||
)
|
||||
|
||||
it.live(
|
||||
"releases ownership when the process dies",
|
||||
Effect.gen(function* () {
|
||||
const root = yield* temp("opencode-process-lock-death-")
|
||||
const file = path.join(root, "service.lock")
|
||||
const ready = path.join(root, "ready")
|
||||
const child = yield* Effect.acquireRelease(
|
||||
Effect.sync(() =>
|
||||
Bun.spawn([process.execPath, worker, JSON.stringify({ file, ready })], {
|
||||
stdout: "ignore",
|
||||
stderr: "pipe",
|
||||
}),
|
||||
),
|
||||
(child) =>
|
||||
Effect.promise(async () => {
|
||||
kill(child)
|
||||
await child.exited
|
||||
}),
|
||||
)
|
||||
yield* Effect.promise(async () => {
|
||||
for (let attempt = 0; attempt < 100 && !(await Bun.file(ready).exists()); attempt++) await Bun.sleep(20)
|
||||
})
|
||||
expect(yield* Effect.promise(() => Bun.file(ready).exists())).toBe(true)
|
||||
|
||||
const error = yield* Effect.scoped(ProcessLock.acquire(file)).pipe(Effect.flip)
|
||||
expect(error._tag).toBe("ProcessLockHeldError")
|
||||
|
||||
if (process.platform !== "win32") {
|
||||
process.kill(child.pid, "SIGSTOP")
|
||||
const paused = yield* Effect.scoped(ProcessLock.acquire(file)).pipe(Effect.flip)
|
||||
expect(paused._tag).toBe("ProcessLockHeldError")
|
||||
process.kill(child.pid, "SIGCONT")
|
||||
}
|
||||
|
||||
kill(child)
|
||||
yield* Effect.promise(() => child.exited)
|
||||
yield* Effect.scoped(ProcessLock.acquire(file))
|
||||
}),
|
||||
)
|
||||
|
||||
function temp(prefix: string) {
|
||||
return Effect.acquireRelease(
|
||||
Effect.promise(() => fs.mkdtemp(path.join(os.tmpdir(), prefix))),
|
||||
(root) => Effect.promise(() => fs.rm(root, { recursive: true, force: true })),
|
||||
)
|
||||
}
|
||||
|
||||
function kill(child: Bun.Subprocess) {
|
||||
if (process.platform === "win32") return child.kill()
|
||||
return child.kill("SIGKILL")
|
||||
}
|
||||
@@ -23,8 +23,8 @@ import type { ServerOptions } from "./options"
|
||||
*
|
||||
* - Database runs on the injected `DurableObjectStorage` SQLite.
|
||||
* - Watcher and fff are disabled through their existing option flags; pty, fff,
|
||||
* shell-parser, photon, and process-lock native modules resolve to inert
|
||||
* stubs under the `workerd` bundle condition.
|
||||
* shell-parser, and photon native modules resolve to inert stubs under the
|
||||
* `workerd` bundle condition.
|
||||
* - Bare locations use a typed no-execution-plane process spawner; FileSystem,
|
||||
* FileSystemSearch, and Pty fail with a clear defect until a remote sandbox
|
||||
* backs them; Snapshot and Vcs degrade to no-op results.
|
||||
|
||||
Reference in New Issue
Block a user