refactor(effect): upgrade opencode to beta.46 context APIs (#21977)

This commit is contained in:
Kit Langton
2026-04-10 23:06:28 -04:00
committed by GitHub
parent af8aff3788
commit 9581bf0670
75 changed files with 195 additions and 209 deletions
+15 -7
View File
@@ -413,7 +413,7 @@
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "7.28.4", "@babel/core": "7.28.4",
"@effect/language-service": "0.79.0", "@effect/language-service": "0.84.2",
"@octokit/webhooks-types": "7.6.1", "@octokit/webhooks-types": "7.6.1",
"@opencode-ai/script": "workspace:*", "@opencode-ai/script": "workspace:*",
"@parcel/watcher-darwin-arm64": "2.5.1", "@parcel/watcher-darwin-arm64": "2.5.1",
@@ -641,7 +641,7 @@
}, },
"catalog": { "catalog": {
"@cloudflare/workers-types": "4.20251008.0", "@cloudflare/workers-types": "4.20251008.0",
"@effect/platform-node": "4.0.0-beta.43", "@effect/platform-node": "4.0.0-beta.46",
"@hono/zod-validator": "0.4.2", "@hono/zod-validator": "0.4.2",
"@kobalte/core": "0.13.11", "@kobalte/core": "0.13.11",
"@lydell/node-pty": "1.2.0-beta.10", "@lydell/node-pty": "1.2.0-beta.10",
@@ -668,7 +668,7 @@
"dompurify": "3.3.1", "dompurify": "3.3.1",
"drizzle-kit": "1.0.0-beta.19-d95b7a4", "drizzle-kit": "1.0.0-beta.19-d95b7a4",
"drizzle-orm": "1.0.0-beta.19-d95b7a4", "drizzle-orm": "1.0.0-beta.19-d95b7a4",
"effect": "4.0.0-beta.43", "effect": "4.0.0-beta.46",
"fuzzysort": "3.1.0", "fuzzysort": "3.1.0",
"hono": "4.10.7", "hono": "4.10.7",
"hono-openapi": "1.1.2", "hono-openapi": "1.1.2",
@@ -1025,11 +1025,11 @@
"@drizzle-team/brocli": ["@drizzle-team/brocli@0.11.0", "", {}, "sha512-hD3pekGiPg0WPCCGAZmusBBJsDqGUR66Y452YgQsZOnkdQ7ViEPKuyP4huUGEZQefp8g34RRodXYmJ2TbCH+tg=="], "@drizzle-team/brocli": ["@drizzle-team/brocli@0.11.0", "", {}, "sha512-hD3pekGiPg0WPCCGAZmusBBJsDqGUR66Y452YgQsZOnkdQ7ViEPKuyP4huUGEZQefp8g34RRodXYmJ2TbCH+tg=="],
"@effect/language-service": ["@effect/language-service@0.79.0", "", { "bin": { "effect-language-service": "cli.js" } }, "sha512-DEmIOsg1GjjP6s9HXH1oJrW+gDmzkhVv9WOZl6to5eNyyCrjz1S2PDqQ7aYrW/HuifhfwI5Bik1pK4pj7Z+lrg=="], "@effect/language-service": ["@effect/language-service@0.84.2", "", { "bin": { "effect-language-service": "cli.js" } }, "sha512-l04qNxpiA8rY5yXWckRPJ7Mk5MNerXuNymSFf+IdflfI5i8jgL1bpBNLuP6ijg7wgjdHc/KmTnCj2kT0SCntuA=="],
"@effect/platform-node": ["@effect/platform-node@4.0.0-beta.43", "", { "dependencies": { "@effect/platform-node-shared": "^4.0.0-beta.43", "mime": "^4.1.0", "undici": "^7.24.0" }, "peerDependencies": { "effect": "^4.0.0-beta.43", "ioredis": "^5.7.0" } }, "sha512-Uq6E1rjaIpjHauzjwoB2HzAg3battYt2Boy8XO50GoHiWCXKE6WapYZ0/AnaBx5v5qg2sOfqpuiLsUf9ZgxOkA=="], "@effect/platform-node": ["@effect/platform-node@4.0.0-beta.46", "", { "dependencies": { "@effect/platform-node-shared": "^4.0.0-beta.46", "mime": "^4.1.0", "undici": "^7.24.0" }, "peerDependencies": { "effect": "^4.0.0-beta.46", "ioredis": "^5.7.0" } }, "sha512-6AFRKjJO95dFl5lK/YnJi04uePjQDFi3+K1aXwcz/EfVlRwJ4+lg5O4vbievfKL/hnfcShVp3/eXnNS9tvlMZQ=="],
"@effect/platform-node-shared": ["@effect/platform-node-shared@4.0.0-beta.43", "", { "dependencies": { "@types/ws": "^8.18.1", "ws": "^8.19.0" }, "peerDependencies": { "effect": "^4.0.0-beta.43" } }, "sha512-A9q0GEb61pYcQ06Dr6gXj1nKlDI3KHsar1sk3qb1ZY+kVSR64tBAylI8zGon23KY+NPtTUj/sEIToB7jc3Qt5w=="], "@effect/platform-node-shared": ["@effect/platform-node-shared@4.0.0-beta.46", "", { "dependencies": { "@types/ws": "^8.18.1", "ws": "^8.19.0" }, "peerDependencies": { "effect": "^4.0.0-beta.46" } }, "sha512-Yzci82XbZ1W3tuiownsJawrJZTGeTrTZKLD0uxdBWCBzlVyqDwoSwRwO5qh33DurJj9B7iS8MDf14fpGRBPNGQ=="],
"@electron/asar": ["@electron/asar@3.4.1", "", { "dependencies": { "commander": "^5.0.0", "glob": "^7.1.6", "minimatch": "^3.0.4" }, "bin": { "asar": "bin/asar.js" } }, "sha512-i4/rNPRS84t0vSRa2HorerGRXWyF4vThfHesw0dmcWHp+cspK743UanA0suA5Q5y8kzY2y6YKrvbIUn69BCAiA=="], "@electron/asar": ["@electron/asar@3.4.1", "", { "dependencies": { "commander": "^5.0.0", "glob": "^7.1.6", "minimatch": "^3.0.4" }, "bin": { "asar": "bin/asar.js" } }, "sha512-i4/rNPRS84t0vSRa2HorerGRXWyF4vThfHesw0dmcWHp+cspK743UanA0suA5Q5y8kzY2y6YKrvbIUn69BCAiA=="],
@@ -2889,7 +2889,7 @@
"ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="], "ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="],
"effect": ["effect@4.0.0-beta.43", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.5.3", "find-my-way-ts": "^0.1.6", "ini": "^6.0.0", "kubernetes-types": "^1.30.0", "msgpackr": "^1.11.8", "multipasta": "^0.2.7", "toml": "^3.0.0", "uuid": "^13.0.0", "yaml": "^2.8.2" } }, "sha512-AJYyDimIwJOn87uUz/JzmgDc5GfjxJbXvEbTvNzMa+M3Uer344bLo/O5mMRkqc1vBleA+Ygs4+dbE3QsqOkKTQ=="], "effect": ["effect@4.0.0-beta.46", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.5.3", "find-my-way-ts": "^0.1.6", "ini": "^6.0.0", "kubernetes-types": "^1.30.0", "msgpackr": "^1.11.8", "multipasta": "^0.2.7", "toml": "^3.0.0", "uuid": "^13.0.0", "yaml": "^2.8.2" } }, "sha512-3f6gXvvUMtEueCRY0tU76Vq2Pej1SAwwE+s0Owd5nD53yS5n4RZhUA1rlCGFuSbQFA225pGy8vO72+lpvu7u5A=="],
"ejs": ["ejs@3.1.10", "", { "dependencies": { "jake": "^10.8.5" }, "bin": { "ejs": "bin/cli.js" } }, "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA=="], "ejs": ["ejs@3.1.10", "", { "dependencies": { "jake": "^10.8.5" }, "bin": { "ejs": "bin/cli.js" } }, "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA=="],
@@ -5509,6 +5509,10 @@
"@solidjs/start/vite-plugin-solid": ["vite-plugin-solid@2.11.11", "", { "dependencies": { "@babel/core": "^7.23.3", "@types/babel__core": "^7.20.4", "babel-preset-solid": "^1.8.4", "merge-anything": "^5.1.7", "solid-refresh": "^0.6.3", "vitefu": "^1.0.4" }, "peerDependencies": { "@testing-library/jest-dom": "^5.16.6 || ^5.17.0 || ^6.*", "solid-js": "^1.7.2", "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" }, "optionalPeers": ["@testing-library/jest-dom"] }, "sha512-YMZCXsLw9kyuvQFEdwLP27fuTQJLmjNoHy90AOJnbRuJ6DwShUxKFo38gdFrWn9v11hnGicKCZEaeI/TFs6JKw=="], "@solidjs/start/vite-plugin-solid": ["vite-plugin-solid@2.11.11", "", { "dependencies": { "@babel/core": "^7.23.3", "@types/babel__core": "^7.20.4", "babel-preset-solid": "^1.8.4", "merge-anything": "^5.1.7", "solid-refresh": "^0.6.3", "vitefu": "^1.0.4" }, "peerDependencies": { "@testing-library/jest-dom": "^5.16.6 || ^5.17.0 || ^6.*", "solid-js": "^1.7.2", "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" }, "optionalPeers": ["@testing-library/jest-dom"] }, "sha512-YMZCXsLw9kyuvQFEdwLP27fuTQJLmjNoHy90AOJnbRuJ6DwShUxKFo38gdFrWn9v11hnGicKCZEaeI/TFs6JKw=="],
"@standard-community/standard-json/effect": ["effect@4.0.0-beta.43", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.5.3", "find-my-way-ts": "^0.1.6", "ini": "^6.0.0", "kubernetes-types": "^1.30.0", "msgpackr": "^1.11.8", "multipasta": "^0.2.7", "toml": "^3.0.0", "uuid": "^13.0.0", "yaml": "^2.8.2" } }, "sha512-AJYyDimIwJOn87uUz/JzmgDc5GfjxJbXvEbTvNzMa+M3Uer344bLo/O5mMRkqc1vBleA+Ygs4+dbE3QsqOkKTQ=="],
"@standard-community/standard-openapi/effect": ["effect@4.0.0-beta.43", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.5.3", "find-my-way-ts": "^0.1.6", "ini": "^6.0.0", "kubernetes-types": "^1.30.0", "msgpackr": "^1.11.8", "multipasta": "^0.2.7", "toml": "^3.0.0", "uuid": "^13.0.0", "yaml": "^2.8.2" } }, "sha512-AJYyDimIwJOn87uUz/JzmgDc5GfjxJbXvEbTvNzMa+M3Uer344bLo/O5mMRkqc1vBleA+Ygs4+dbE3QsqOkKTQ=="],
"@tailwindcss/oxide/detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], "@tailwindcss/oxide/detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.9.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-mukuNALVsoix/w1BJwFzwXBN/dHeejQtuVzcDsfOEsdpCumXb/E9j8w11h5S54tT1xhifGfbbSm/ICrObRb3KA=="], "@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.9.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-mukuNALVsoix/w1BJwFzwXBN/dHeejQtuVzcDsfOEsdpCumXb/E9j8w11h5S54tT1xhifGfbbSm/ICrObRb3KA=="],
@@ -6435,6 +6439,10 @@
"@solidjs/start/shiki/@shikijs/types": ["@shikijs/types@1.29.2", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.1", "@types/hast": "^3.0.4" } }, "sha512-VJjK0eIijTZf0QSTODEXCqinjBn0joAHQ+aPSBzrv4O2d/QSbsMw+ZeSRx03kV34Hy7NzUvV/7NqfYGRLrASmw=="], "@solidjs/start/shiki/@shikijs/types": ["@shikijs/types@1.29.2", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.1", "@types/hast": "^3.0.4" } }, "sha512-VJjK0eIijTZf0QSTODEXCqinjBn0joAHQ+aPSBzrv4O2d/QSbsMw+ZeSRx03kV34Hy7NzUvV/7NqfYGRLrASmw=="],
"@standard-community/standard-json/effect/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
"@standard-community/standard-openapi/effect/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
"@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime/@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="], "@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime/@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
"@vitest/expect/@vitest/utils/@vitest/pretty-format": ["@vitest/pretty-format@3.2.4", "", { "dependencies": { "tinyrainbow": "^2.0.0" } }, "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA=="], "@vitest/expect/@vitest/utils/@vitest/pretty-format": ["@vitest/pretty-format@3.2.4", "", { "dependencies": { "tinyrainbow": "^2.0.0" } }, "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA=="],
+2 -2
View File
@@ -26,7 +26,7 @@
"packages/slack" "packages/slack"
], ],
"catalog": { "catalog": {
"@effect/platform-node": "4.0.0-beta.43", "@effect/platform-node": "4.0.0-beta.46",
"@types/bun": "1.3.11", "@types/bun": "1.3.11",
"@types/cross-spawn": "6.0.6", "@types/cross-spawn": "6.0.6",
"@octokit/rest": "22.0.0", "@octokit/rest": "22.0.0",
@@ -47,7 +47,7 @@
"dompurify": "3.3.1", "dompurify": "3.3.1",
"drizzle-kit": "1.0.0-beta.19-d95b7a4", "drizzle-kit": "1.0.0-beta.19-d95b7a4",
"drizzle-orm": "1.0.0-beta.19-d95b7a4", "drizzle-orm": "1.0.0-beta.19-d95b7a4",
"effect": "4.0.0-beta.43", "effect": "4.0.0-beta.46",
"ai": "6.0.149", "ai": "6.0.149",
"cross-spawn": "7.0.6", "cross-spawn": "7.0.6",
"hono": "4.10.7", "hono": "4.10.7",
+1 -1
View File
@@ -43,7 +43,7 @@
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "7.28.4", "@babel/core": "7.28.4",
"@effect/language-service": "0.79.0", "@effect/language-service": "0.84.2",
"@octokit/webhooks-types": "7.6.1", "@octokit/webhooks-types": "7.6.1",
"@opencode-ai/script": "workspace:*", "@opencode-ai/script": "workspace:*",
"@parcel/watcher-darwin-arm64": "2.5.1", "@parcel/watcher-darwin-arm64": "2.5.1",
+1 -1
View File
@@ -23,7 +23,7 @@ export namespace Foo {
readonly get: (id: FooID) => Effect.Effect<FooInfo, FooError> readonly get: (id: FooID) => Effect.Effect<FooInfo, FooError>
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/Foo") {} export class Service extends Context.Service<Service, Interface>()("@opencode/Foo") {}
export const layer = Layer.effect( export const layer = Layer.effect(
Service, Service,
+2 -2
View File
@@ -1,4 +1,4 @@
import { Cache, Clock, Duration, Effect, Layer, Option, Schema, SchemaGetter, ServiceMap } from "effect" import { Cache, Clock, Duration, Effect, Layer, Option, Schema, SchemaGetter, Context } from "effect"
import { import {
FetchHttpClient, FetchHttpClient,
HttpClient, HttpClient,
@@ -181,7 +181,7 @@ export namespace Account {
readonly poll: (input: Login) => Effect.Effect<PollResult, AccountError> readonly poll: (input: Login) => Effect.Effect<PollResult, AccountError>
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/Account") {} export class Service extends Context.Service<Service, Interface>()("@opencode/Account") {}
export const layer: Layer.Layer<Service, never, AccountRepo | HttpClient.HttpClient> = Layer.effect( export const layer: Layer.Layer<Service, never, AccountRepo | HttpClient.HttpClient> = Layer.effect(
Service, Service,
+2 -2
View File
@@ -1,5 +1,5 @@
import { eq } from "drizzle-orm" import { eq } from "drizzle-orm"
import { Effect, Layer, Option, Schema, ServiceMap } from "effect" import { Effect, Layer, Option, Schema, Context } from "effect"
import { Database } from "@/storage/db" import { Database } from "@/storage/db"
import { AccountStateTable, AccountTable } from "./account.sql" import { AccountStateTable, AccountTable } from "./account.sql"
@@ -38,7 +38,7 @@ export namespace AccountRepo {
} }
} }
export class AccountRepo extends ServiceMap.Service<AccountRepo, AccountRepo.Service>()("@opencode/AccountRepo") { export class AccountRepo extends Context.Service<AccountRepo, AccountRepo.Service>()("@opencode/AccountRepo") {
static readonly layer: Layer.Layer<AccountRepo> = Layer.effect( static readonly layer: Layer.Layer<AccountRepo> = Layer.effect(
AccountRepo, AccountRepo,
Effect.gen(function* () { Effect.gen(function* () {
+6 -26
View File
@@ -1,42 +1,22 @@
import { Schema } from "effect" import { Schema } from "effect"
import type * as HttpClientError from "effect/unstable/http/HttpClientError" import type * as HttpClientError from "effect/unstable/http/HttpClientError"
import { withStatics } from "@/util/schema" export const AccountID = Schema.String.pipe(Schema.brand("AccountID"))
export const AccountID = Schema.String.pipe(
Schema.brand("AccountID"),
withStatics((s) => ({ make: (id: string) => s.makeUnsafe(id) })),
)
export type AccountID = Schema.Schema.Type<typeof AccountID> export type AccountID = Schema.Schema.Type<typeof AccountID>
export const OrgID = Schema.String.pipe( export const OrgID = Schema.String.pipe(Schema.brand("OrgID"))
Schema.brand("OrgID"),
withStatics((s) => ({ make: (id: string) => s.makeUnsafe(id) })),
)
export type OrgID = Schema.Schema.Type<typeof OrgID> export type OrgID = Schema.Schema.Type<typeof OrgID>
export const AccessToken = Schema.String.pipe( export const AccessToken = Schema.String.pipe(Schema.brand("AccessToken"))
Schema.brand("AccessToken"),
withStatics((s) => ({ make: (token: string) => s.makeUnsafe(token) })),
)
export type AccessToken = Schema.Schema.Type<typeof AccessToken> export type AccessToken = Schema.Schema.Type<typeof AccessToken>
export const RefreshToken = Schema.String.pipe( export const RefreshToken = Schema.String.pipe(Schema.brand("RefreshToken"))
Schema.brand("RefreshToken"),
withStatics((s) => ({ make: (token: string) => s.makeUnsafe(token) })),
)
export type RefreshToken = Schema.Schema.Type<typeof RefreshToken> export type RefreshToken = Schema.Schema.Type<typeof RefreshToken>
export const DeviceCode = Schema.String.pipe( export const DeviceCode = Schema.String.pipe(Schema.brand("DeviceCode"))
Schema.brand("DeviceCode"),
withStatics((s) => ({ make: (code: string) => s.makeUnsafe(code) })),
)
export type DeviceCode = Schema.Schema.Type<typeof DeviceCode> export type DeviceCode = Schema.Schema.Type<typeof DeviceCode>
export const UserCode = Schema.String.pipe( export const UserCode = Schema.String.pipe(Schema.brand("UserCode"))
Schema.brand("UserCode"),
withStatics((s) => ({ make: (code: string) => s.makeUnsafe(code) })),
)
export type UserCode = Schema.Schema.Type<typeof UserCode> export type UserCode = Schema.Schema.Type<typeof UserCode>
export class Info extends Schema.Class<Info>("Account")({ export class Info extends Schema.Class<Info>("Account")({
+2 -2
View File
@@ -19,7 +19,7 @@ import { Global } from "@/global"
import path from "path" import path from "path"
import { Plugin } from "@/plugin" import { Plugin } from "@/plugin"
import { Skill } from "../skill" import { Skill } from "../skill"
import { Effect, ServiceMap, Layer } from "effect" import { Effect, Context, Layer } from "effect"
import { InstanceState } from "@/effect/instance-state" import { InstanceState } from "@/effect/instance-state"
import { makeRuntime } from "@/effect/run-service" import { makeRuntime } from "@/effect/run-service"
@@ -67,7 +67,7 @@ export namespace Agent {
type State = Omit<Interface, "generate"> type State = Omit<Interface, "generate">
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/Agent") {} export class Service extends Context.Service<Service, Interface>()("@opencode/Agent") {}
export const layer = Layer.effect( export const layer = Layer.effect(
Service, Service,
+2 -2
View File
@@ -1,5 +1,5 @@
import path from "path" import path from "path"
import { Effect, Layer, Record, Result, Schema, ServiceMap } from "effect" import { Effect, Layer, Record, Result, Schema, Context } from "effect"
import { makeRuntime } from "@/effect/run-service" import { makeRuntime } from "@/effect/run-service"
import { zod } from "@/util/effect-zod" import { zod } from "@/util/effect-zod"
import { Global } from "../global" import { Global } from "../global"
@@ -49,7 +49,7 @@ export namespace Auth {
readonly remove: (key: string) => Effect.Effect<void, AuthError> readonly remove: (key: string) => Effect.Effect<void, AuthError>
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/Auth") {} export class Service extends Context.Service<Service, Interface>()("@opencode/Auth") {}
export const layer = Layer.effect( export const layer = Layer.effect(
Service, Service,
+2 -2
View File
@@ -1,5 +1,5 @@
import z from "zod" import z from "zod"
import { Effect, Exit, Layer, PubSub, Scope, ServiceMap, Stream } from "effect" import { Effect, Exit, Layer, PubSub, Scope, Context, Stream } from "effect"
import { EffectLogger } from "@/effect/logger" import { EffectLogger } from "@/effect/logger"
import { Log } from "../util/log" import { Log } from "../util/log"
import { BusEvent } from "./bus-event" import { BusEvent } from "./bus-event"
@@ -42,7 +42,7 @@ export namespace Bus {
readonly subscribeAllCallback: (callback: (event: any) => unknown) => Effect.Effect<() => void> readonly subscribeAllCallback: (callback: (event: any) => unknown) => Effect.Effect<() => void>
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/Bus") {} export class Service extends Context.Service<Service, Interface>()("@opencode/Bus") {}
export const layer = Layer.effect( export const layer = Layer.effect(
Service, Service,
+4 -3
View File
@@ -1,8 +1,9 @@
import { BusEvent } from "@/bus/bus-event" import { BusEvent } from "@/bus/bus-event"
import { InstanceState } from "@/effect/instance-state" import { InstanceState } from "@/effect/instance-state"
import { makeRuntime } from "@/effect/run-service" import { makeRuntime } from "@/effect/run-service"
import type { InstanceContext } from "@/project/instance"
import { SessionID, MessageID } from "@/session/schema" import { SessionID, MessageID } from "@/session/schema"
import { Effect, Layer, ServiceMap } from "effect" import { Effect, Layer, Context } from "effect"
import { EffectLogger } from "@/effect/logger" import { EffectLogger } from "@/effect/logger"
import z from "zod" import z from "zod"
import { Config } from "../config/config" import { Config } from "../config/config"
@@ -71,7 +72,7 @@ export namespace Command {
readonly list: () => Effect.Effect<Info[]> readonly list: () => Effect.Effect<Info[]>
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/Command") {} export class Service extends Context.Service<Service, Interface>()("@opencode/Command") {}
export const layer = Layer.effect( export const layer = Layer.effect(
Service, Service,
@@ -80,7 +81,7 @@ export namespace Command {
const mcp = yield* MCP.Service const mcp = yield* MCP.Service
const skill = yield* Skill.Service const skill = yield* Skill.Service
const init = Effect.fn("Command.state")(function* (ctx) { const init = Effect.fn("Command.state")(function* (ctx: InstanceContext) {
const cfg = yield* config.get() const cfg = yield* config.get()
const commands: Record<string, Info> = {} const commands: Record<string, Info> = {}
+2 -2
View File
@@ -37,7 +37,7 @@ import type { ConsoleState } from "./console-state"
import { AppFileSystem } from "@/filesystem" import { AppFileSystem } from "@/filesystem"
import { InstanceState } from "@/effect/instance-state" import { InstanceState } from "@/effect/instance-state"
import { makeRuntime } from "@/effect/run-service" import { makeRuntime } from "@/effect/run-service"
import { Duration, Effect, Layer, Option, ServiceMap } from "effect" import { Duration, Effect, Layer, Option, Context } from "effect"
import { Flock } from "@/util/flock" import { Flock } from "@/util/flock"
import { isPathPluginSpec, parsePluginSpecifier, resolvePathPluginTarget } from "@/plugin/shared" import { isPathPluginSpec, parsePluginSpecifier, resolvePathPluginTarget } from "@/plugin/shared"
import { Npm } from "@/npm" import { Npm } from "@/npm"
@@ -1127,7 +1127,7 @@ export namespace Config {
readonly waitForDependencies: () => Effect.Effect<void> readonly waitForDependencies: () => Effect.Effect<void>
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/Config") {} export class Service extends Context.Service<Service, Interface>()("@opencode/Config") {}
function globalConfigFile() { function globalConfigFile() {
const candidates = ["opencode.jsonc", "opencode.json", "config.json"].map((file) => const candidates = ["opencode.jsonc", "opencode.json", "config.json"].map((file) =>
@@ -10,8 +10,7 @@ export type WorkspaceID = typeof workspaceIdSchema.Type
export const WorkspaceID = workspaceIdSchema.pipe( export const WorkspaceID = workspaceIdSchema.pipe(
withStatics((schema: typeof workspaceIdSchema) => ({ withStatics((schema: typeof workspaceIdSchema) => ({
make: (id: string) => schema.makeUnsafe(id), ascending: (id?: string) => schema.make(Identifier.ascending("workspace", id)),
ascending: (id?: string) => schema.makeUnsafe(Identifier.ascending("workspace", id)),
zod: Identifier.schema("workspace").pipe(z.custom<WorkspaceID>()), zod: Identifier.schema("workspace").pipe(z.custom<WorkspaceID>()),
})), })),
) )
@@ -1,11 +1,11 @@
import { Context } from "../util/context" import { LocalContext } from "../util/local-context"
import type { WorkspaceID } from "../control-plane/schema" import type { WorkspaceID } from "../control-plane/schema"
export interface WorkspaceContext { export interface WorkspaceContext {
workspaceID: string workspaceID: string
} }
const context = Context.create<WorkspaceContext>("instance") const context = LocalContext.create<WorkspaceContext>("instance")
export const WorkspaceContext = { export const WorkspaceContext = {
async provide<R>(input: { workspaceID: WorkspaceID; fn: () => R }): Promise<R> { async provide<R>(input: { workspaceID: WorkspaceID; fn: () => R }): Promise<R> {
@@ -402,6 +402,7 @@ export const make = Effect.gen(function* () {
const fd = yield* setupFds(command, proc, extra) const fd = yield* setupFds(command, proc, extra)
const out = setupOutput(command, proc, sout, serr) const out = setupOutput(command, proc, sout, serr)
let ref = true
return makeHandle({ return makeHandle({
pid: ProcessId(proc.pid!), pid: ProcessId(proc.pid!),
stdin: yield* setupStdin(command, proc, sin), stdin: yield* setupStdin(command, proc, sin),
@@ -432,6 +433,18 @@ export const make = Effect.gen(function* () {
orElse: () => send("SIGKILL").pipe(Effect.andThen(Deferred.await(signal)), Effect.asVoid), orElse: () => send("SIGKILL").pipe(Effect.andThen(Deferred.await(signal)), Effect.asVoid),
}) })
}, },
unref: Effect.sync(() => {
if (ref) {
proc.unref()
ref = false
}
return Effect.sync(() => {
if (!ref) {
proc.ref()
ref = true
}
})
}),
}) })
} }
case "PipedCommand": { case "PipedCommand": {
+3 -3
View File
@@ -1,10 +1,10 @@
import { ServiceMap } from "effect" import { Context } from "effect"
import type { InstanceContext } from "@/project/instance" import type { InstanceContext } from "@/project/instance"
export const InstanceRef = ServiceMap.Reference<InstanceContext | undefined>("~opencode/InstanceRef", { export const InstanceRef = Context.Reference<InstanceContext | undefined>("~opencode/InstanceRef", {
defaultValue: () => undefined, defaultValue: () => undefined,
}) })
export const WorkspaceRef = ServiceMap.Reference<string | undefined>("~opencode/WorkspaceRef", { export const WorkspaceRef = Context.Reference<string | undefined>("~opencode/WorkspaceRef", {
defaultValue: () => undefined, defaultValue: () => undefined,
}) })
@@ -1,7 +1,7 @@
import { Effect, Fiber, ScopedCache, Scope, ServiceMap } from "effect" import { Effect, Fiber, ScopedCache, Scope, Context } from "effect"
import { EffectLogger } from "@/effect/logger" import { EffectLogger } from "@/effect/logger"
import { Instance, type InstanceContext } from "@/project/instance" import { Instance, type InstanceContext } from "@/project/instance"
import { Context } from "@/util/context" import { LocalContext } from "@/util/local-context"
import { InstanceRef, WorkspaceRef } from "./instance-ref" import { InstanceRef, WorkspaceRef } from "./instance-ref"
import { registerDisposer } from "./instance-registry" import { registerDisposer } from "./instance-registry"
import { WorkspaceContext } from "@/control-plane/workspace-context" import { WorkspaceContext } from "@/control-plane/workspace-context"
@@ -18,10 +18,10 @@ export namespace InstanceState {
try { try {
return Instance.bind(fn) return Instance.bind(fn)
} catch (err) { } catch (err) {
if (!(err instanceof Context.NotFound)) throw err if (!(err instanceof LocalContext.NotFound)) throw err
} }
const fiber = Fiber.getCurrent() const fiber = Fiber.getCurrent()
const ctx = fiber ? ServiceMap.getReferenceUnsafe(fiber.services, InstanceRef) : undefined const ctx = fiber ? Context.getReferenceUnsafe(fiber.context, InstanceRef) : undefined
if (!ctx) return fn if (!ctx) return fn
return ((...args: any[]) => Instance.restore(ctx, () => fn(...args))) as F return ((...args: any[]) => Instance.restore(ctx, () => fn(...args))) as F
} }
+4 -4
View File
@@ -1,7 +1,7 @@
import { Effect, Layer, ManagedRuntime } from "effect" import { Effect, Layer, ManagedRuntime } from "effect"
import * as ServiceMap from "effect/ServiceMap" import * as Context from "effect/Context"
import { Instance } from "@/project/instance" import { Instance } from "@/project/instance"
import { Context } from "@/util/context" import { LocalContext } from "@/util/local-context"
import { InstanceRef, WorkspaceRef } from "./instance-ref" import { InstanceRef, WorkspaceRef } from "./instance-ref"
import { Observability } from "./oltp" import { Observability } from "./oltp"
import { WorkspaceContext } from "@/control-plane/workspace-context" import { WorkspaceContext } from "@/control-plane/workspace-context"
@@ -14,12 +14,12 @@ export function attach<A, E, R>(effect: Effect.Effect<A, E, R>): Effect.Effect<A
const workspaceID = WorkspaceContext.workspaceID const workspaceID = WorkspaceContext.workspaceID
return effect.pipe(Effect.provideService(InstanceRef, ctx), Effect.provideService(WorkspaceRef, workspaceID)) return effect.pipe(Effect.provideService(InstanceRef, ctx), Effect.provideService(WorkspaceRef, workspaceID))
} catch (err) { } catch (err) {
if (!(err instanceof Context.NotFound)) throw err if (!(err instanceof LocalContext.NotFound)) throw err
} }
return effect return effect
} }
export function makeRuntime<I, S, E>(service: ServiceMap.Service<I, S>, layer: Layer.Layer<I, E>) { export function makeRuntime<I, S, E>(service: Context.Service<I, S>, layer: Layer.Layer<I, E>) {
let rt: ManagedRuntime.ManagedRuntime<I, E> | undefined let rt: ManagedRuntime.ManagedRuntime<I, E> | undefined
const getRuntime = () => (rt ??= ManagedRuntime.make(Layer.merge(layer, Observability.layer), { memoMap })) const getRuntime = () => (rt ??= ManagedRuntime.make(Layer.merge(layer, Observability.layer), { memoMap }))
+2 -2
View File
@@ -3,7 +3,7 @@ import { InstanceState } from "@/effect/instance-state"
import { makeRuntime } from "@/effect/run-service" import { makeRuntime } from "@/effect/run-service"
import { AppFileSystem } from "@/filesystem" import { AppFileSystem } from "@/filesystem"
import { Git } from "@/git" import { Git } from "@/git"
import { Effect, Layer, ServiceMap } from "effect" import { Effect, Layer, Context } from "effect"
import { formatPatch, structuredPatch } from "diff" import { formatPatch, structuredPatch } from "diff"
import fuzzysort from "fuzzysort" import fuzzysort from "fuzzysort"
import ignore from "ignore" import ignore from "ignore"
@@ -337,7 +337,7 @@ export namespace File {
}) => Effect.Effect<string[]> }) => Effect.Effect<string[]>
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/File") {} export class Service extends Context.Service<Service, Interface>()("@opencode/File") {}
export const layer = Layer.effect( export const layer = Layer.effect(
Service, Service,
+2 -2
View File
@@ -3,7 +3,7 @@ import path from "path"
import { Global } from "../global" import { Global } from "../global"
import fs from "fs/promises" import fs from "fs/promises"
import z from "zod" import z from "zod"
import { Effect, Layer, ServiceMap } from "effect" import { Effect, Layer, Context } from "effect"
import * as Stream from "effect/Stream" import * as Stream from "effect/Stream"
import { ChildProcess } from "effect/unstable/process" import { ChildProcess } from "effect/unstable/process"
import { ChildProcessSpawner } from "effect/unstable/process/ChildProcessSpawner" import { ChildProcessSpawner } from "effect/unstable/process/ChildProcessSpawner"
@@ -291,7 +291,7 @@ export namespace Ripgrep {
}) => Stream.Stream<string, PlatformError> }) => Stream.Stream<string, PlatformError>
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/Ripgrep") {} export class Service extends Context.Service<Service, Interface>()("@opencode/Ripgrep") {}
export const layer: Layer.Layer<Service, never, ChildProcessSpawner | AppFileSystem.Service> = Layer.effect( export const layer: Layer.Layer<Service, never, ChildProcessSpawner | AppFileSystem.Service> = Layer.effect(
Service, Service,
+2 -2
View File
@@ -1,4 +1,4 @@
import { DateTime, Effect, Layer, Option, Semaphore, ServiceMap } from "effect" import { DateTime, Effect, Layer, Option, Semaphore, Context } from "effect"
import { InstanceState } from "@/effect/instance-state" import { InstanceState } from "@/effect/instance-state"
import { makeRuntime } from "@/effect/run-service" import { makeRuntime } from "@/effect/run-service"
import { AppFileSystem } from "@/filesystem" import { AppFileSystem } from "@/filesystem"
@@ -37,7 +37,7 @@ export namespace FileTime {
readonly withLock: <T>(filepath: string, fn: () => Effect.Effect<T>) => Effect.Effect<T> readonly withLock: <T>(filepath: string, fn: () => Effect.Effect<T>) => Effect.Effect<T>
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/FileTime") {} export class Service extends Context.Service<Service, Interface>()("@opencode/FileTime") {}
export const layer = Layer.effect( export const layer = Layer.effect(
Service, Service,
+2 -2
View File
@@ -1,4 +1,4 @@
import { Cause, Effect, Layer, Scope, ServiceMap } from "effect" import { Cause, Effect, Layer, Scope, Context } from "effect"
// @ts-ignore // @ts-ignore
import { createWrapper } from "@parcel/watcher/wrapper" import { createWrapper } from "@parcel/watcher/wrapper"
import type ParcelWatcher from "@parcel/watcher" import type ParcelWatcher from "@parcel/watcher"
@@ -65,7 +65,7 @@ export namespace FileWatcher {
readonly init: () => Effect.Effect<void> readonly init: () => Effect.Effect<void>
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/FileWatcher") {} export class Service extends Context.Service<Service, Interface>()("@opencode/FileWatcher") {}
export const layer = Layer.effect( export const layer = Layer.effect(
Service, Service,
+2 -2
View File
@@ -3,7 +3,7 @@ import { dirname, join, relative, resolve as pathResolve } from "path"
import { realpathSync } from "fs" import { realpathSync } from "fs"
import * as NFS from "fs/promises" import * as NFS from "fs/promises"
import { lookup } from "mime-types" import { lookup } from "mime-types"
import { Effect, FileSystem, Layer, Schema, ServiceMap } from "effect" import { Effect, FileSystem, Layer, Schema, Context } from "effect"
import type { PlatformError } from "effect/PlatformError" import type { PlatformError } from "effect/PlatformError"
import { Glob } from "../util/glob" import { Glob } from "../util/glob"
@@ -36,7 +36,7 @@ export namespace AppFileSystem {
readonly globMatch: (pattern: string, filepath: string) => boolean readonly globMatch: (pattern: string, filepath: string) => boolean
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/FileSystem") {} export class Service extends Context.Service<Service, Interface>()("@opencode/FileSystem") {}
export const layer = Layer.effect( export const layer = Layer.effect(
Service, Service,
+2 -2
View File
@@ -1,4 +1,4 @@
import { Effect, Layer, ServiceMap } from "effect" import { Effect, Layer, Context } from "effect"
import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process" import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process"
import * as CrossSpawnSpawner from "@/effect/cross-spawn-spawner" import * as CrossSpawnSpawner from "@/effect/cross-spawn-spawner"
import { InstanceState } from "@/effect/instance-state" import { InstanceState } from "@/effect/instance-state"
@@ -31,7 +31,7 @@ export namespace Format {
readonly file: (filepath: string) => Effect.Effect<void> readonly file: (filepath: string) => Effect.Effect<void>
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/Format") {} export class Service extends Context.Service<Service, Interface>()("@opencode/Format") {}
export const layer = Layer.effect( export const layer = Layer.effect(
Service, Service,
+2 -2
View File
@@ -1,5 +1,5 @@
import * as CrossSpawnSpawner from "@/effect/cross-spawn-spawner" import * as CrossSpawnSpawner from "@/effect/cross-spawn-spawner"
import { Effect, Layer, ServiceMap, Stream } from "effect" import { Effect, Layer, Context, Stream } from "effect"
import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process" import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process"
import { makeRuntime } from "@/effect/run-service" import { makeRuntime } from "@/effect/run-service"
@@ -80,7 +80,7 @@ export namespace Git {
return "modified" return "modified"
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/Git") {} export class Service extends Context.Service<Service, Interface>()("@opencode/Git") {}
export const layer = Layer.effect( export const layer = Layer.effect(
Service, Service,
+2 -2
View File
@@ -1,4 +1,4 @@
import { Effect, Layer, Schema, ServiceMap, Stream } from "effect" import { Effect, Layer, Schema, Context, Stream } from "effect"
import { FetchHttpClient, HttpClient, HttpClientRequest, HttpClientResponse } from "effect/unstable/http" import { FetchHttpClient, HttpClient, HttpClientRequest, HttpClientResponse } from "effect/unstable/http"
import * as CrossSpawnSpawner from "@/effect/cross-spawn-spawner" import * as CrossSpawnSpawner from "@/effect/cross-spawn-spawner"
import { makeRuntime } from "@/effect/run-service" import { makeRuntime } from "@/effect/run-service"
@@ -91,7 +91,7 @@ export namespace Installation {
readonly upgrade: (method: Method, target: string) => Effect.Effect<void, UpgradeFailedError> readonly upgrade: (method: Method, target: string) => Effect.Effect<void, UpgradeFailedError>
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/Installation") {} export class Service extends Context.Service<Service, Interface>()("@opencode/Installation") {}
export const layer: Layer.Layer<Service, never, HttpClient.HttpClient | ChildProcessSpawner.ChildProcessSpawner> = export const layer: Layer.Layer<Service, never, HttpClient.HttpClient | ChildProcessSpawner.ChildProcessSpawner> =
Layer.effect( Layer.effect(
+2 -2
View File
@@ -11,7 +11,7 @@ import { Instance } from "../project/instance"
import { Flag } from "@/flag/flag" import { Flag } from "@/flag/flag"
import { Process } from "../util/process" import { Process } from "../util/process"
import { spawn as lspspawn } from "./launch" import { spawn as lspspawn } from "./launch"
import { Effect, Layer, ServiceMap } from "effect" import { Effect, Layer, Context } from "effect"
import { InstanceState } from "@/effect/instance-state" import { InstanceState } from "@/effect/instance-state"
import { makeRuntime } from "@/effect/run-service" import { makeRuntime } from "@/effect/run-service"
@@ -156,7 +156,7 @@ export namespace LSP {
readonly outgoingCalls: (input: LocInput) => Effect.Effect<any[]> readonly outgoingCalls: (input: LocInput) => Effect.Effect<any[]>
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/LSP") {} export class Service extends Context.Service<Service, Interface>()("@opencode/LSP") {}
export const layer = Layer.effect( export const layer = Layer.effect(
Service, Service,
+2 -2
View File
@@ -1,7 +1,7 @@
import path from "path" import path from "path"
import z from "zod" import z from "zod"
import { Global } from "../global" import { Global } from "../global"
import { Effect, Layer, ServiceMap } from "effect" import { Effect, Layer, Context } from "effect"
import { AppFileSystem } from "@/filesystem" import { AppFileSystem } from "@/filesystem"
import { makeRuntime } from "@/effect/run-service" import { makeRuntime } from "@/effect/run-service"
@@ -49,7 +49,7 @@ export namespace McpAuth {
readonly isTokenExpired: (mcpName: string) => Effect.Effect<boolean | null> readonly isTokenExpired: (mcpName: string) => Effect.Effect<boolean | null>
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/McpAuth") {} export class Service extends Context.Service<Service, Interface>()("@opencode/McpAuth") {}
export const layer = Layer.effect( export const layer = Layer.effect(
Service, Service,
+2 -2
View File
@@ -24,7 +24,7 @@ import { BusEvent } from "../bus/bus-event"
import { Bus } from "@/bus" import { Bus } from "@/bus"
import { TuiEvent } from "@/cli/cmd/tui/event" import { TuiEvent } from "@/cli/cmd/tui/event"
import open from "open" import open from "open"
import { Effect, Exit, Layer, Option, ServiceMap, Stream } from "effect" import { Effect, Exit, Layer, Option, Context, Stream } from "effect"
import { EffectLogger } from "@/effect/logger" import { EffectLogger } from "@/effect/logger"
import { InstanceState } from "@/effect/instance-state" import { InstanceState } from "@/effect/instance-state"
import { makeRuntime } from "@/effect/run-service" import { makeRuntime } from "@/effect/run-service"
@@ -240,7 +240,7 @@ export namespace MCP {
readonly getAuthStatus: (mcpName: string) => Effect.Effect<AuthStatus> readonly getAuthStatus: (mcpName: string) => Effect.Effect<AuthStatus>
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/MCP") {} export class Service extends Context.Service<Service, Interface>()("@opencode/MCP") {}
export const layer = Layer.effect( export const layer = Layer.effect(
Service, Service,
+2 -2
View File
@@ -10,7 +10,7 @@ import { PermissionTable } from "@/session/session.sql"
import { Database, eq } from "@/storage/db" import { Database, eq } from "@/storage/db"
import { Log } from "@/util/log" import { Log } from "@/util/log"
import { Wildcard } from "@/util/wildcard" import { Wildcard } from "@/util/wildcard"
import { Deferred, Effect, Layer, Schema, ServiceMap } from "effect" import { Deferred, Effect, Layer, Schema, Context } from "effect"
import os from "os" import os from "os"
import z from "zod" import z from "zod"
import { evaluate as evalRule } from "./evaluate" import { evaluate as evalRule } from "./evaluate"
@@ -135,7 +135,7 @@ export namespace Permission {
return evalRule(permission, pattern, ...rulesets) return evalRule(permission, pattern, ...rulesets)
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/Permission") {} export class Service extends Context.Service<Service, Interface>()("@opencode/Permission") {}
export const layer = Layer.effect( export const layer = Layer.effect(
Service, Service,
+1 -5
View File
@@ -5,12 +5,8 @@ import { Identifier } from "@/id/id"
import { Newtype } from "@/util/schema" import { Newtype } from "@/util/schema"
export class PermissionID extends Newtype<PermissionID>()("PermissionID", Schema.String) { export class PermissionID extends Newtype<PermissionID>()("PermissionID", Schema.String) {
static make(id: string): PermissionID {
return this.makeUnsafe(id)
}
static ascending(id?: string): PermissionID { static ascending(id?: string): PermissionID {
return this.makeUnsafe(Identifier.ascending("permission", id)) return this.make(Identifier.ascending("permission", id))
} }
static readonly zod = Identifier.schema("permission") as unknown as z.ZodType<PermissionID> static readonly zod = Identifier.schema("permission") as unknown as z.ZodType<PermissionID>
+2 -2
View File
@@ -11,7 +11,7 @@ import { CopilotAuthPlugin } from "./github-copilot/copilot"
import { gitlabAuthPlugin as GitlabAuthPlugin } from "opencode-gitlab-auth" import { gitlabAuthPlugin as GitlabAuthPlugin } from "opencode-gitlab-auth"
import { PoeAuthPlugin } from "opencode-poe-auth" import { PoeAuthPlugin } from "opencode-poe-auth"
import { CloudflareAIGatewayAuthPlugin, CloudflareWorkersAuthPlugin } from "./cloudflare" import { CloudflareAIGatewayAuthPlugin, CloudflareWorkersAuthPlugin } from "./cloudflare"
import { Effect, Layer, ServiceMap, Stream } from "effect" import { Effect, Layer, Context, Stream } from "effect"
import { EffectLogger } from "@/effect/logger" import { EffectLogger } from "@/effect/logger"
import { InstanceState } from "@/effect/instance-state" import { InstanceState } from "@/effect/instance-state"
import { makeRuntime } from "@/effect/run-service" import { makeRuntime } from "@/effect/run-service"
@@ -45,7 +45,7 @@ export namespace Plugin {
readonly init: () => Effect.Effect<void> readonly init: () => Effect.Effect<void>
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/Plugin") {} export class Service extends Context.Service<Service, Interface>()("@opencode/Plugin") {}
// Built-in plugins that are directly imported (not installed from npm) // Built-in plugins that are directly imported (not installed from npm)
const INTERNAL_PLUGINS: PluginInstance[] = [ const INTERNAL_PLUGINS: PluginInstance[] = [
+2 -2
View File
@@ -3,7 +3,7 @@ import { disposeInstance } from "@/effect/instance-registry"
import { Filesystem } from "@/util/filesystem" import { Filesystem } from "@/util/filesystem"
import { iife } from "@/util/iife" import { iife } from "@/util/iife"
import { Log } from "@/util/log" import { Log } from "@/util/log"
import { Context } from "../util/context" import { LocalContext } from "../util/local-context"
import { Project } from "./project" import { Project } from "./project"
import { WorkspaceContext } from "@/control-plane/workspace-context" import { WorkspaceContext } from "@/control-plane/workspace-context"
import { State } from "./state" import { State } from "./state"
@@ -14,7 +14,7 @@ export interface InstanceContext {
project: Project.Info project: Project.Info
} }
const context = Context.create<InstanceContext>("instance") const context = LocalContext.create<InstanceContext>("instance")
const cache = new Map<string, Promise<InstanceContext>>() const cache = new Map<string, Promise<InstanceContext>>()
const disposal = { const disposal = {
+2 -2
View File
@@ -8,7 +8,7 @@ import { BusEvent } from "@/bus/bus-event"
import { GlobalBus } from "@/bus/global" import { GlobalBus } from "@/bus/global"
import { which } from "../util/which" import { which } from "../util/which"
import { ProjectID } from "./schema" import { ProjectID } from "./schema"
import { Effect, Layer, Path, Scope, ServiceMap, Stream } from "effect" import { Effect, Layer, Path, Scope, Context, Stream } from "effect"
import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process" import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process"
import { NodeFileSystem, NodePath } from "@effect/platform-node" import { NodeFileSystem, NodePath } from "@effect/platform-node"
import { makeRuntime } from "@/effect/run-service" import { makeRuntime } from "@/effect/run-service"
@@ -100,7 +100,7 @@ export namespace Project {
readonly removeSandbox: (id: ProjectID, directory: string) => Effect.Effect<void> readonly removeSandbox: (id: ProjectID, directory: string) => Effect.Effect<void>
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/Project") {} export class Service extends Context.Service<Service, Interface>()("@opencode/Project") {}
type GitResult = { code: number; text: string; stderr: string } type GitResult = { code: number; text: string; stderr: string }
+1 -2
View File
@@ -9,8 +9,7 @@ export type ProjectID = typeof projectIdSchema.Type
export const ProjectID = projectIdSchema.pipe( export const ProjectID = projectIdSchema.pipe(
withStatics((schema: typeof projectIdSchema) => ({ withStatics((schema: typeof projectIdSchema) => ({
global: schema.makeUnsafe("global"), global: schema.make("global"),
make: (id: string) => schema.makeUnsafe(id),
zod: z.string().pipe(z.custom<ProjectID>()), zod: z.string().pipe(z.custom<ProjectID>()),
})), })),
) )
+2 -2
View File
@@ -1,4 +1,4 @@
import { Effect, Layer, ServiceMap, Stream } from "effect" import { Effect, Layer, Context, Stream } from "effect"
import { formatPatch, structuredPatch } from "diff" import { formatPatch, structuredPatch } from "diff"
import path from "path" import path from "path"
import { Bus } from "@/bus" import { Bus } from "@/bus"
@@ -151,7 +151,7 @@ export namespace Vcs {
root: Git.Base | undefined root: Git.Base | undefined
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/Vcs") {} export class Service extends Context.Service<Service, Interface>()("@opencode/Vcs") {}
export const layer: Layer.Layer<Service, never, AppFileSystem.Service | Git.Service | Bus.Service> = Layer.effect( export const layer: Layer.Layer<Service, never, AppFileSystem.Service | Git.Service | Bus.Service> = Layer.effect(
Service, Service,
+2 -2
View File
@@ -5,7 +5,7 @@ import { InstanceState } from "@/effect/instance-state"
import { makeRuntime } from "@/effect/run-service" import { makeRuntime } from "@/effect/run-service"
import { Plugin } from "../plugin" import { Plugin } from "../plugin"
import { ProviderID } from "./schema" import { ProviderID } from "./schema"
import { Array as Arr, Effect, Layer, Record, Result, ServiceMap } from "effect" import { Array as Arr, Effect, Layer, Record, Result, Context } from "effect"
import z from "zod" import z from "zod"
export namespace ProviderAuth { export namespace ProviderAuth {
@@ -109,7 +109,7 @@ export namespace ProviderAuth {
pending: Map<ProviderID, AuthOAuthResult> pending: Map<ProviderID, AuthOAuthResult>
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/ProviderAuth") {} export class Service extends Context.Service<Service, Interface>()("@opencode/ProviderAuth") {}
export const layer: Layer.Layer<Service, never, Auth.Service | Plugin.Service> = Layer.effect( export const layer: Layer.Layer<Service, never, Auth.Service | Plugin.Service> = Layer.effect(
Service, Service,
+2 -2
View File
@@ -19,7 +19,7 @@ import { iife } from "@/util/iife"
import { Global } from "../global" import { Global } from "../global"
import path from "path" import path from "path"
import { Filesystem } from "../util/filesystem" import { Filesystem } from "../util/filesystem"
import { Effect, Layer, ServiceMap } from "effect" import { Effect, Layer, Context } from "effect"
import { EffectLogger } from "@/effect/logger" import { EffectLogger } from "@/effect/logger"
import { InstanceState } from "@/effect/instance-state" import { InstanceState } from "@/effect/instance-state"
import { makeRuntime } from "@/effect/run-service" import { makeRuntime } from "@/effect/run-service"
@@ -925,7 +925,7 @@ export namespace Provider {
varsLoaders: Record<string, CustomVarsLoader> varsLoaders: Record<string, CustomVarsLoader>
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/Provider") {} export class Service extends Context.Service<Service, Interface>()("@opencode/Provider") {}
function cost(c: ModelsDev.Model["cost"]): Model["cost"] { function cost(c: ModelsDev.Model["cost"]): Model["cost"] {
const result: Model["cost"] = { const result: Model["cost"] = {
+11 -13
View File
@@ -9,20 +9,19 @@ export type ProviderID = typeof providerIdSchema.Type
export const ProviderID = providerIdSchema.pipe( export const ProviderID = providerIdSchema.pipe(
withStatics((schema: typeof providerIdSchema) => ({ withStatics((schema: typeof providerIdSchema) => ({
make: (id: string) => schema.makeUnsafe(id),
zod: z.string().pipe(z.custom<ProviderID>()), zod: z.string().pipe(z.custom<ProviderID>()),
// Well-known providers // Well-known providers
opencode: schema.makeUnsafe("opencode"), opencode: schema.make("opencode"),
anthropic: schema.makeUnsafe("anthropic"), anthropic: schema.make("anthropic"),
openai: schema.makeUnsafe("openai"), openai: schema.make("openai"),
google: schema.makeUnsafe("google"), google: schema.make("google"),
googleVertex: schema.makeUnsafe("google-vertex"), googleVertex: schema.make("google-vertex"),
githubCopilot: schema.makeUnsafe("github-copilot"), githubCopilot: schema.make("github-copilot"),
amazonBedrock: schema.makeUnsafe("amazon-bedrock"), amazonBedrock: schema.make("amazon-bedrock"),
azure: schema.makeUnsafe("azure"), azure: schema.make("azure"),
openrouter: schema.makeUnsafe("openrouter"), openrouter: schema.make("openrouter"),
mistral: schema.makeUnsafe("mistral"), mistral: schema.make("mistral"),
gitlab: schema.makeUnsafe("gitlab"), gitlab: schema.make("gitlab"),
})), })),
) )
@@ -32,7 +31,6 @@ export type ModelID = typeof modelIdSchema.Type
export const ModelID = modelIdSchema.pipe( export const ModelID = modelIdSchema.pipe(
withStatics((schema: typeof modelIdSchema) => ({ withStatics((schema: typeof modelIdSchema) => ({
make: (id: string) => schema.makeUnsafe(id),
zod: z.string().pipe(z.custom<ModelID>()), zod: z.string().pipe(z.custom<ModelID>()),
})), })),
) )
+2 -2
View File
@@ -10,7 +10,7 @@ import { lazy } from "@opencode-ai/util/lazy"
import { Shell } from "@/shell/shell" import { Shell } from "@/shell/shell"
import { Plugin } from "@/plugin" import { Plugin } from "@/plugin"
import { PtyID } from "./schema" import { PtyID } from "./schema"
import { Effect, Layer, ServiceMap } from "effect" import { Effect, Layer, Context } from "effect"
import { EffectLogger } from "@/effect/logger" import { EffectLogger } from "@/effect/logger"
export namespace Pty { export namespace Pty {
@@ -113,7 +113,7 @@ export namespace Pty {
) => Effect.Effect<{ onMessage: (message: string | ArrayBuffer) => void; onClose: () => void } | undefined> ) => Effect.Effect<{ onMessage: (message: string | ArrayBuffer) => void; onClose: () => void } | undefined>
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/Pty") {} export class Service extends Context.Service<Service, Interface>()("@opencode/Pty") {}
export const layer = Layer.effect( export const layer = Layer.effect(
Service, Service,
+1 -2
View File
@@ -10,8 +10,7 @@ export type PtyID = typeof ptyIdSchema.Type
export const PtyID = ptyIdSchema.pipe( export const PtyID = ptyIdSchema.pipe(
withStatics((schema: typeof ptyIdSchema) => ({ withStatics((schema: typeof ptyIdSchema) => ({
make: (id: string) => schema.makeUnsafe(id), ascending: (id?: string) => schema.make(Identifier.ascending("pty", id)),
ascending: (id?: string) => schema.makeUnsafe(Identifier.ascending("pty", id)),
zod: Identifier.schema("pty").pipe(z.custom<PtyID>()), zod: Identifier.schema("pty").pipe(z.custom<PtyID>()),
})), })),
) )
+2 -2
View File
@@ -1,4 +1,4 @@
import { Deferred, Effect, Layer, Schema, ServiceMap } from "effect" import { Deferred, Effect, Layer, Schema, Context } from "effect"
import { Bus } from "@/bus" import { Bus } from "@/bus"
import { BusEvent } from "@/bus/bus-event" import { BusEvent } from "@/bus/bus-event"
import { InstanceState } from "@/effect/instance-state" import { InstanceState } from "@/effect/instance-state"
@@ -104,7 +104,7 @@ export namespace Question {
readonly list: () => Effect.Effect<Request[]> readonly list: () => Effect.Effect<Request[]>
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/Question") {} export class Service extends Context.Service<Service, Interface>()("@opencode/Question") {}
export const layer = Layer.effect( export const layer = Layer.effect(
Service, Service,
+1 -5
View File
@@ -5,12 +5,8 @@ import { Identifier } from "@/id/id"
import { Newtype } from "@/util/schema" import { Newtype } from "@/util/schema"
export class QuestionID extends Newtype<QuestionID>()("QuestionID", Schema.String) { export class QuestionID extends Newtype<QuestionID>()("QuestionID", Schema.String) {
static make(id: string): QuestionID {
return this.makeUnsafe(id)
}
static ascending(id?: string): QuestionID { static ascending(id?: string): QuestionID {
return this.makeUnsafe(Identifier.ascending("question", id)) return this.make(Identifier.ascending("question", id))
} }
static readonly zod = Identifier.schema("question") as unknown as z.ZodType<QuestionID> static readonly zod = Identifier.schema("question") as unknown as z.ZodType<QuestionID>
+2 -2
View File
@@ -15,7 +15,7 @@ import { Plugin } from "@/plugin"
import { Config } from "@/config/config" import { Config } from "@/config/config"
import { NotFoundError } from "@/storage/db" import { NotFoundError } from "@/storage/db"
import { ModelID, ProviderID } from "@/provider/schema" import { ModelID, ProviderID } from "@/provider/schema"
import { Effect, Layer, ServiceMap } from "effect" import { Effect, Layer, Context } from "effect"
import { makeRuntime } from "@/effect/run-service" import { makeRuntime } from "@/effect/run-service"
import { InstanceState } from "@/effect/instance-state" import { InstanceState } from "@/effect/instance-state"
import { isOverflow as overflow } from "./overflow" import { isOverflow as overflow } from "./overflow"
@@ -58,7 +58,7 @@ export namespace SessionCompaction {
}) => Effect.Effect<void> }) => Effect.Effect<void>
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/SessionCompaction") {} export class Service extends Context.Service<Service, Interface>()("@opencode/SessionCompaction") {}
export const layer: Layer.Layer< export const layer: Layer.Layer<
Service, Service,
+2 -2
View File
@@ -29,7 +29,7 @@ import type { Provider } from "@/provider/provider"
import { Permission } from "@/permission" import { Permission } from "@/permission"
import { Global } from "@/global" import { Global } from "@/global"
import type { LanguageModelV2Usage } from "@ai-sdk/provider" import type { LanguageModelV2Usage } from "@ai-sdk/provider"
import { Effect, Layer, ServiceMap } from "effect" import { Effect, Layer, Context } from "effect"
import { makeRuntime } from "@/effect/run-service" import { makeRuntime } from "@/effect/run-service"
export namespace Session { export namespace Session {
@@ -354,7 +354,7 @@ export namespace Session {
}) => Effect.Effect<void> }) => Effect.Effect<void>
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/Session") {} export class Service extends Context.Service<Service, Interface>()("@opencode/Session") {}
type Patch = z.infer<typeof Event.Updated.schema>["info"] type Patch = z.infer<typeof Event.Updated.schema>["info"]
+2 -2
View File
@@ -1,6 +1,6 @@
import os from "os" import os from "os"
import path from "path" import path from "path"
import { Effect, Layer, ServiceMap } from "effect" import { Effect, Layer, Context } from "effect"
import { FetchHttpClient, HttpClient, HttpClientRequest } from "effect/unstable/http" import { FetchHttpClient, HttpClient, HttpClientRequest } from "effect/unstable/http"
import { Config } from "@/config/config" import { Config } from "@/config/config"
import { InstanceState } from "@/effect/instance-state" import { InstanceState } from "@/effect/instance-state"
@@ -64,7 +64,7 @@ export namespace Instruction {
) => Effect.Effect<{ filepath: string; content: string }[], AppFileSystem.Error> ) => Effect.Effect<{ filepath: string; content: string }[], AppFileSystem.Error>
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/Instruction") {} export class Service extends Context.Service<Service, Interface>()("@opencode/Instruction") {}
export const layer: Layer.Layer<Service, never, AppFileSystem.Service | Config.Service | HttpClient.HttpClient> = export const layer: Layer.Layer<Service, never, AppFileSystem.Service | Config.Service | HttpClient.HttpClient> =
Layer.effect( Layer.effect(
+2 -2
View File
@@ -1,6 +1,6 @@
import { Provider } from "@/provider/provider" import { Provider } from "@/provider/provider"
import { Log } from "@/util/log" import { Log } from "@/util/log"
import { Cause, Effect, Layer, Record, ServiceMap } from "effect" import { Cause, Effect, Layer, Record, Context } from "effect"
import * as Queue from "effect/Queue" import * as Queue from "effect/Queue"
import * as Stream from "effect/Stream" import * as Stream from "effect/Stream"
import { streamText, wrapLanguageModel, type ModelMessage, type Tool, tool, jsonSchema } from "ai" import { streamText, wrapLanguageModel, type ModelMessage, type Tool, tool, jsonSchema } from "ai"
@@ -51,7 +51,7 @@ export namespace LLM {
readonly stream: (input: StreamInput) => Stream.Stream<Event, unknown> readonly stream: (input: StreamInput) => Stream.Stream<Event, unknown>
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/LLM") {} export class Service extends Context.Service<Service, Interface>()("@opencode/LLM") {}
export const layer = Layer.effect( export const layer = Layer.effect(
Service, Service,
+2 -2
View File
@@ -1,4 +1,4 @@
import { Cause, Deferred, Effect, Layer, ServiceMap } from "effect" import { Cause, Deferred, Effect, Layer, Context } from "effect"
import * as Stream from "effect/Stream" import * as Stream from "effect/Stream"
import { Agent } from "@/agent/agent" import { Agent } from "@/agent/agent"
import { Bus } from "@/bus" import { Bus } from "@/bus"
@@ -76,7 +76,7 @@ export namespace SessionProcessor {
type StreamEvent = Event type StreamEvent = Event
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/SessionProcessor") {} export class Service extends Context.Service<Service, Interface>()("@opencode/SessionProcessor") {}
export const layer: Layer.Layer< export const layer: Layer.Layer<
Service, Service,
+2 -2
View File
@@ -43,7 +43,7 @@ import { AppFileSystem } from "@/filesystem"
import { Truncate } from "@/tool/truncate" import { Truncate } from "@/tool/truncate"
import { decodeDataUrl } from "@/util/data-url" import { decodeDataUrl } from "@/util/data-url"
import { Process } from "@/util/process" import { Process } from "@/util/process"
import { Cause, Effect, Exit, Layer, Option, Scope, ServiceMap } from "effect" import { Cause, Effect, Exit, Layer, Option, Scope, Context } from "effect"
import { EffectLogger } from "@/effect/logger" import { EffectLogger } from "@/effect/logger"
import { InstanceState } from "@/effect/instance-state" import { InstanceState } from "@/effect/instance-state"
import { makeRuntime } from "@/effect/run-service" import { makeRuntime } from "@/effect/run-service"
@@ -76,7 +76,7 @@ export namespace SessionPrompt {
readonly resolvePromptParts: (template: string) => Effect.Effect<PromptInput["parts"]> readonly resolvePromptParts: (template: string) => Effect.Effect<PromptInput["parts"]>
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/SessionPrompt") {} export class Service extends Context.Service<Service, Interface>()("@opencode/SessionPrompt") {}
export const layer = Layer.effect( export const layer = Layer.effect(
Service, Service,
+2 -2
View File
@@ -1,5 +1,5 @@
import z from "zod" import z from "zod"
import { Effect, Layer, ServiceMap } from "effect" import { Effect, Layer, Context } from "effect"
import { makeRuntime } from "@/effect/run-service" import { makeRuntime } from "@/effect/run-service"
import { Bus } from "../bus" import { Bus } from "../bus"
import { Snapshot } from "../snapshot" import { Snapshot } from "../snapshot"
@@ -29,7 +29,7 @@ export namespace SessionRevert {
readonly cleanup: (session: Session.Info) => Effect.Effect<void> readonly cleanup: (session: Session.Info) => Effect.Effect<void>
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/SessionRevert") {} export class Service extends Context.Service<Service, Interface>()("@opencode/SessionRevert") {}
export const layer = Layer.effect( export const layer = Layer.effect(
Service, Service,
+2 -2
View File
@@ -1,7 +1,7 @@
import { InstanceState } from "@/effect/instance-state" import { InstanceState } from "@/effect/instance-state"
import { Runner } from "@/effect/runner" import { Runner } from "@/effect/runner"
import { makeRuntime } from "@/effect/run-service" import { makeRuntime } from "@/effect/run-service"
import { Effect, Layer, Scope, ServiceMap } from "effect" import { Effect, Layer, Scope, Context } from "effect"
import { Session } from "." import { Session } from "."
import { MessageV2 } from "./message-v2" import { MessageV2 } from "./message-v2"
import { SessionID } from "./schema" import { SessionID } from "./schema"
@@ -23,7 +23,7 @@ export namespace SessionRunState {
) => Effect.Effect<MessageV2.WithParts> ) => Effect.Effect<MessageV2.WithParts>
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/SessionRunState") {} export class Service extends Context.Service<Service, Interface>()("@opencode/SessionRunState") {}
export const layer = Layer.effect( export const layer = Layer.effect(
Service, Service,
+3 -6
View File
@@ -7,8 +7,7 @@ import { withStatics } from "@/util/schema"
export const SessionID = Schema.String.pipe( export const SessionID = Schema.String.pipe(
Schema.brand("SessionID"), Schema.brand("SessionID"),
withStatics((s) => ({ withStatics((s) => ({
make: (id: string) => s.makeUnsafe(id), descending: (id?: string) => s.make(Identifier.descending("session", id)),
descending: (id?: string) => s.makeUnsafe(Identifier.descending("session", id)),
zod: Identifier.schema("session").pipe(z.custom<Schema.Schema.Type<typeof s>>()), zod: Identifier.schema("session").pipe(z.custom<Schema.Schema.Type<typeof s>>()),
})), })),
) )
@@ -18,8 +17,7 @@ export type SessionID = Schema.Schema.Type<typeof SessionID>
export const MessageID = Schema.String.pipe( export const MessageID = Schema.String.pipe(
Schema.brand("MessageID"), Schema.brand("MessageID"),
withStatics((s) => ({ withStatics((s) => ({
make: (id: string) => s.makeUnsafe(id), ascending: (id?: string) => s.make(Identifier.ascending("message", id)),
ascending: (id?: string) => s.makeUnsafe(Identifier.ascending("message", id)),
zod: Identifier.schema("message").pipe(z.custom<Schema.Schema.Type<typeof s>>()), zod: Identifier.schema("message").pipe(z.custom<Schema.Schema.Type<typeof s>>()),
})), })),
) )
@@ -29,8 +27,7 @@ export type MessageID = Schema.Schema.Type<typeof MessageID>
export const PartID = Schema.String.pipe( export const PartID = Schema.String.pipe(
Schema.brand("PartID"), Schema.brand("PartID"),
withStatics((s) => ({ withStatics((s) => ({
make: (id: string) => s.makeUnsafe(id), ascending: (id?: string) => s.make(Identifier.ascending("part", id)),
ascending: (id?: string) => s.makeUnsafe(Identifier.ascending("part", id)),
zod: Identifier.schema("part").pipe(z.custom<Schema.Schema.Type<typeof s>>()), zod: Identifier.schema("part").pipe(z.custom<Schema.Schema.Type<typeof s>>()),
})), })),
) )
+2 -2
View File
@@ -2,7 +2,7 @@ import { BusEvent } from "@/bus/bus-event"
import { Bus } from "@/bus" import { Bus } from "@/bus"
import { InstanceState } from "@/effect/instance-state" import { InstanceState } from "@/effect/instance-state"
import { SessionID } from "./schema" import { SessionID } from "./schema"
import { Effect, Layer, ServiceMap } from "effect" import { Effect, Layer, Context } from "effect"
import z from "zod" import z from "zod"
export namespace SessionStatus { export namespace SessionStatus {
@@ -49,7 +49,7 @@ export namespace SessionStatus {
readonly set: (sessionID: SessionID, status: Info) => Effect.Effect<void> readonly set: (sessionID: SessionID, status: Info) => Effect.Effect<void>
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/SessionStatus") {} export class Service extends Context.Service<Service, Interface>()("@opencode/SessionStatus") {}
export const layer = Layer.effect( export const layer = Layer.effect(
Service, Service,
+2 -2
View File
@@ -1,5 +1,5 @@
import z from "zod" import z from "zod"
import { Effect, Layer, ServiceMap } from "effect" import { Effect, Layer, Context } from "effect"
import { makeRuntime } from "@/effect/run-service" import { makeRuntime } from "@/effect/run-service"
import { Bus } from "@/bus" import { Bus } from "@/bus"
import { Snapshot } from "@/snapshot" import { Snapshot } from "@/snapshot"
@@ -71,7 +71,7 @@ export namespace SessionSummary {
readonly computeDiff: (input: { messages: MessageV2.WithParts[] }) => Effect.Effect<Snapshot.FileDiff[]> readonly computeDiff: (input: { messages: MessageV2.WithParts[] }) => Effect.Effect<Snapshot.FileDiff[]>
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/SessionSummary") {} export class Service extends Context.Service<Service, Interface>()("@opencode/SessionSummary") {}
export const layer = Layer.effect( export const layer = Layer.effect(
Service, Service,
+2 -2
View File
@@ -1,7 +1,7 @@
import { BusEvent } from "@/bus/bus-event" import { BusEvent } from "@/bus/bus-event"
import { Bus } from "@/bus" import { Bus } from "@/bus"
import { SessionID } from "./schema" import { SessionID } from "./schema"
import { Effect, Layer, ServiceMap } from "effect" import { Effect, Layer, Context } from "effect"
import z from "zod" import z from "zod"
import { Database, eq, asc } from "../storage/db" import { Database, eq, asc } from "../storage/db"
import { TodoTable } from "./session.sql" import { TodoTable } from "./session.sql"
@@ -31,7 +31,7 @@ export namespace Todo {
readonly get: (sessionID: SessionID) => Effect.Effect<Info[]> readonly get: (sessionID: SessionID) => Effect.Effect<Info[]>
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/SessionTodo") {} export class Service extends Context.Service<Service, Interface>()("@opencode/SessionTodo") {}
export const layer = Layer.effect( export const layer = Layer.effect(
Service, Service,
+2 -2
View File
@@ -3,7 +3,7 @@ import { Session } from "@/session"
import { SessionID } from "@/session/schema" import { SessionID } from "@/session/schema"
import { SyncEvent } from "@/sync" import { SyncEvent } from "@/sync"
import { fn } from "@/util/fn" import { fn } from "@/util/fn"
import { Effect, Layer, Scope, ServiceMap } from "effect" import { Effect, Layer, Scope, Context } from "effect"
import { Config } from "../config/config" import { Config } from "../config/config"
import { Flag } from "../flag/flag" import { Flag } from "../flag/flag"
import { ShareNext } from "./share-next" import { ShareNext } from "./share-next"
@@ -15,7 +15,7 @@ export namespace SessionShare {
readonly unshare: (sessionID: SessionID) => Effect.Effect<void, unknown> readonly unshare: (sessionID: SessionID) => Effect.Effect<void, unknown>
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/SessionShare") {} export class Service extends Context.Service<Service, Interface>()("@opencode/SessionShare") {}
export const layer = Layer.effect( export const layer = Layer.effect(
Service, Service,
+2 -2
View File
@@ -1,5 +1,5 @@
import type * as SDK from "@opencode-ai/sdk/v2" import type * as SDK from "@opencode-ai/sdk/v2"
import { Effect, Exit, Layer, Option, Schema, Scope, ServiceMap, Stream } from "effect" import { Effect, Exit, Layer, Option, Schema, Scope, Context, Stream } from "effect"
import { FetchHttpClient, HttpClient, HttpClientRequest, HttpClientResponse } from "effect/unstable/http" import { FetchHttpClient, HttpClient, HttpClientRequest, HttpClientResponse } from "effect/unstable/http"
import { Account } from "@/account" import { Account } from "@/account"
import { Bus } from "@/bus" import { Bus } from "@/bus"
@@ -73,7 +73,7 @@ export namespace ShareNext {
readonly remove: (sessionID: SessionID) => Effect.Effect<void, unknown> readonly remove: (sessionID: SessionID) => Effect.Effect<void, unknown>
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/ShareNext") {} export class Service extends Context.Service<Service, Interface>()("@opencode/ShareNext") {}
const db = <T>(fn: (d: Parameters<typeof Database.use>[0] extends (trx: infer D) => any ? D : never) => T) => const db = <T>(fn: (d: Parameters<typeof Database.use>[0] extends (trx: infer D) => any ? D : never) => T) =>
Effect.sync(() => Database.use(fn)) Effect.sync(() => Database.use(fn))
+2 -2
View File
@@ -1,5 +1,5 @@
import { NodePath } from "@effect/platform-node" import { NodePath } from "@effect/platform-node"
import { Effect, Layer, Path, Schema, ServiceMap } from "effect" import { Effect, Layer, Path, Schema, Context } from "effect"
import { FetchHttpClient, HttpClient, HttpClientRequest, HttpClientResponse } from "effect/unstable/http" import { FetchHttpClient, HttpClient, HttpClientRequest, HttpClientResponse } from "effect/unstable/http"
import { withTransientReadRetry } from "@/util/effect-http-client" import { withTransientReadRetry } from "@/util/effect-http-client"
import { AppFileSystem } from "@/filesystem" import { AppFileSystem } from "@/filesystem"
@@ -23,7 +23,7 @@ export namespace Discovery {
readonly pull: (url: string) => Effect.Effect<string[]> readonly pull: (url: string) => Effect.Effect<string[]>
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/SkillDiscovery") {} export class Service extends Context.Service<Service, Interface>()("@opencode/SkillDiscovery") {}
export const layer: Layer.Layer<Service, never, AppFileSystem.Service | Path.Path | HttpClient.HttpClient> = export const layer: Layer.Layer<Service, never, AppFileSystem.Service | Path.Path | HttpClient.HttpClient> =
Layer.effect( Layer.effect(
+2 -2
View File
@@ -2,7 +2,7 @@ import os from "os"
import path from "path" import path from "path"
import { pathToFileURL } from "url" import { pathToFileURL } from "url"
import z from "zod" import z from "zod"
import { Effect, Layer, ServiceMap } from "effect" import { Effect, Layer, Context } from "effect"
import { NamedError } from "@opencode-ai/util/error" import { NamedError } from "@opencode-ai/util/error"
import type { Agent } from "@/agent/agent" import type { Agent } from "@/agent/agent"
import { Bus } from "@/bus" import { Bus } from "@/bus"
@@ -187,7 +187,7 @@ export namespace Skill {
log.info("init", { count: Object.keys(state.skills).length }) log.info("init", { count: Object.keys(state.skills).length })
}) })
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/Skill") {} export class Service extends Context.Service<Service, Interface>()("@opencode/Skill") {}
export const layer = Layer.effect( export const layer = Layer.effect(
Service, Service,
+2 -2
View File
@@ -1,4 +1,4 @@
import { Cause, Duration, Effect, Layer, Schedule, Semaphore, ServiceMap, Stream } from "effect" import { Cause, Duration, Effect, Layer, Schedule, Semaphore, Context, Stream } from "effect"
import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process" import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process"
import { formatPatch, structuredPatch } from "diff" import { formatPatch, structuredPatch } from "diff"
import path from "path" import path from "path"
@@ -57,7 +57,7 @@ export namespace Snapshot {
readonly diffFull: (from: string, to: string) => Effect.Effect<Snapshot.FileDiff[]> readonly diffFull: (from: string, to: string) => Effect.Effect<Snapshot.FileDiff[]>
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/Snapshot") {} export class Service extends Context.Service<Service, Interface>()("@opencode/Snapshot") {}
export const layer: Layer.Layer< export const layer: Layer.Layer<
Service, Service,
+4 -4
View File
@@ -2,7 +2,7 @@ import { type SQLiteBunDatabase } from "drizzle-orm/bun-sqlite"
import { migrate } from "drizzle-orm/bun-sqlite/migrator" import { migrate } from "drizzle-orm/bun-sqlite/migrator"
import { type SQLiteTransaction } from "drizzle-orm/sqlite-core" import { type SQLiteTransaction } from "drizzle-orm/sqlite-core"
export * from "drizzle-orm" export * from "drizzle-orm"
import { Context } from "../util/context" import { LocalContext } from "../util/local-context"
import { lazy } from "../util/lazy" import { lazy } from "../util/lazy"
import { Global } from "../global" import { Global } from "../global"
import { Log } from "../util/log" import { Log } from "../util/log"
@@ -122,7 +122,7 @@ export namespace Database {
export type TxOrDb = Transaction | Client export type TxOrDb = Transaction | Client
const ctx = Context.create<{ const ctx = LocalContext.create<{
tx: TxOrDb tx: TxOrDb
effects: (() => void | Promise<void>)[] effects: (() => void | Promise<void>)[]
}>("database") }>("database")
@@ -131,7 +131,7 @@ export namespace Database {
try { try {
return callback(ctx.use().tx) return callback(ctx.use().tx)
} catch (err) { } catch (err) {
if (err instanceof Context.NotFound) { if (err instanceof LocalContext.NotFound) {
const effects: (() => void | Promise<void>)[] = [] const effects: (() => void | Promise<void>)[] = []
const result = ctx.provide({ effects, tx: Client() }, () => callback(Client())) const result = ctx.provide({ effects, tx: Client() }, () => callback(Client()))
for (const effect of effects) effect() for (const effect of effects) effect()
@@ -161,7 +161,7 @@ export namespace Database {
try { try {
return callback(ctx.use().tx) return callback(ctx.use().tx)
} catch (err) { } catch (err) {
if (err instanceof Context.NotFound) { if (err instanceof LocalContext.NotFound) {
const effects: (() => void | Promise<void>)[] = [] const effects: (() => void | Promise<void>)[] = []
const txCallback = InstanceState.bind((tx: TxOrDb) => ctx.provide({ tx, effects }, () => callback(tx))) const txCallback = InstanceState.bind((tx: TxOrDb) => ctx.provide({ tx, effects }, () => callback(tx)))
const result = Client().transaction(txCallback, { behavior: options?.behavior }) const result = Client().transaction(txCallback, { behavior: options?.behavior })
+2 -2
View File
@@ -4,7 +4,7 @@ import { Global } from "../global"
import { NamedError } from "@opencode-ai/util/error" import { NamedError } from "@opencode-ai/util/error"
import z from "zod" import z from "zod"
import { AppFileSystem } from "@/filesystem" import { AppFileSystem } from "@/filesystem"
import { Effect, Exit, Layer, Option, RcMap, Schema, ServiceMap, TxReentrantLock } from "effect" import { Effect, Exit, Layer, Option, RcMap, Schema, Context, TxReentrantLock } from "effect"
import { Git } from "@/git" import { Git } from "@/git"
export namespace Storage { export namespace Storage {
@@ -65,7 +65,7 @@ export namespace Storage {
readonly list: (prefix: string[]) => Effect.Effect<string[][], AppFileSystem.Error> readonly list: (prefix: string[]) => Effect.Effect<string[][], AppFileSystem.Error>
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/Storage") {} export class Service extends Context.Service<Service, Interface>()("@opencode/Storage") {}
function file(dir: string, key: string[]) { function file(dir: string, key: string[]) {
return path.join(dir, ...key) + ".json" return path.join(dir, ...key) + ".json"
+1 -2
View File
@@ -7,8 +7,7 @@ import { withStatics } from "@/util/schema"
export const EventID = Schema.String.pipe( export const EventID = Schema.String.pipe(
Schema.brand("EventID"), Schema.brand("EventID"),
withStatics((s) => ({ withStatics((s) => ({
make: (id: string) => s.makeUnsafe(id), ascending: (id?: string) => s.make(Identifier.ascending("event", id)),
ascending: (id?: string) => s.makeUnsafe(Identifier.ascending("event", id)),
zod: Identifier.schema("event").pipe(z.custom<Schema.Schema.Type<typeof s>>()), zod: Identifier.schema("event").pipe(z.custom<Schema.Schema.Type<typeof s>>()),
})), })),
) )
+2 -2
View File
@@ -29,7 +29,7 @@ import { ApplyPatchTool } from "./apply_patch"
import { Glob } from "../util/glob" import { Glob } from "../util/glob"
import path from "path" import path from "path"
import { pathToFileURL } from "url" import { pathToFileURL } from "url"
import { Effect, Layer, ServiceMap } from "effect" import { Effect, Layer, Context } from "effect"
import { EffectLogger } from "@/effect/logger" import { EffectLogger } from "@/effect/logger"
import { FetchHttpClient, HttpClient } from "effect/unstable/http" import { FetchHttpClient, HttpClient } from "effect/unstable/http"
import { ChildProcessSpawner } from "effect/unstable/process/ChildProcessSpawner" import { ChildProcessSpawner } from "effect/unstable/process/ChildProcessSpawner"
@@ -74,7 +74,7 @@ export namespace ToolRegistry {
}) => Effect.Effect<Tool.Def[]> }) => Effect.Effect<Tool.Def[]>
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/ToolRegistry") {} export class Service extends Context.Service<Service, Interface>()("@opencode/ToolRegistry") {}
export const layer: Layer.Layer< export const layer: Layer.Layer<
Service, Service,
+1 -2
View File
@@ -10,8 +10,7 @@ export type ToolID = typeof toolIdSchema.Type
export const ToolID = toolIdSchema.pipe( export const ToolID = toolIdSchema.pipe(
withStatics((schema: typeof toolIdSchema) => ({ withStatics((schema: typeof toolIdSchema) => ({
make: (id: string) => schema.makeUnsafe(id), ascending: (id?: string) => schema.make(Identifier.ascending("tool", id)),
ascending: (id?: string) => schema.makeUnsafe(Identifier.ascending("tool", id)),
zod: Identifier.schema("tool").pipe(z.custom<ToolID>()), zod: Identifier.schema("tool").pipe(z.custom<ToolID>()),
})), })),
) )
+2 -2
View File
@@ -1,5 +1,5 @@
import { NodePath } from "@effect/platform-node" import { NodePath } from "@effect/platform-node"
import { Cause, Duration, Effect, Layer, Schedule, ServiceMap } from "effect" import { Cause, Duration, Effect, Layer, Schedule, Context } from "effect"
import path from "path" import path from "path"
import type { Agent } from "../agent/agent" import type { Agent } from "../agent/agent"
import { makeRuntime } from "@/effect/run-service" import { makeRuntime } from "@/effect/run-service"
@@ -41,7 +41,7 @@ export namespace Truncate {
readonly output: (text: string, options?: Options, agent?: Agent.Info) => Effect.Effect<Result> readonly output: (text: string, options?: Options, agent?: Agent.Info) => Effect.Effect<Result>
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/Truncate") {} export class Service extends Context.Service<Service, Interface>()("@opencode/Truncate") {}
export const layer = Layer.effect( export const layer = Layer.effect(
Service, Service,
@@ -1,6 +1,6 @@
import { AsyncLocalStorage } from "async_hooks" import { AsyncLocalStorage } from "async_hooks"
export namespace Context { export namespace LocalContext {
export class NotFound extends Error { export class NotFound extends Error {
constructor(public override readonly name: string) { constructor(public override readonly name: string) {
super(`No context found for ${name}`) super(`No context found for ${name}`)
+5 -5
View File
@@ -6,7 +6,7 @@ import { Schema } from "effect"
* @example * @example
* export const Foo = fooSchema.pipe( * export const Foo = fooSchema.pipe(
* withStatics((schema) => ({ * withStatics((schema) => ({
* zero: schema.makeUnsafe(0), * zero: schema.make(0),
* from: Schema.decodeUnknownOption(schema), * from: Schema.decodeUnknownOption(schema),
* })) * }))
* ) * )
@@ -26,7 +26,7 @@ type NewtypeBrand<Tag extends string> = { readonly [NewtypeBrand]: Tag }
* @example * @example
* class QuestionID extends Newtype<QuestionID>()("QuestionID", Schema.String) { * class QuestionID extends Newtype<QuestionID>()("QuestionID", Schema.String) {
* static make(id: string): QuestionID { * static make(id: string): QuestionID {
* return this.makeUnsafe(id) * return this.make(id)
* } * }
* } * }
* *
@@ -39,7 +39,7 @@ export function Newtype<Self>() {
abstract class Base { abstract class Base {
declare readonly [NewtypeBrand]: Tag declare readonly [NewtypeBrand]: Tag
static makeUnsafe(value: Schema.Schema.Type<S>): Self { static make(value: Schema.Schema.Type<S>): Self {
return value as unknown as Self return value as unknown as Self
} }
} }
@@ -47,7 +47,7 @@ export function Newtype<Self>() {
Object.setPrototypeOf(Base, schema) Object.setPrototypeOf(Base, schema)
return Base as unknown as (abstract new (_: never) => Branded) & { return Base as unknown as (abstract new (_: never) => Branded) & {
readonly makeUnsafe: (value: Schema.Schema.Type<S>) => Self readonly make: (value: Schema.Schema.Type<S>) => Self
} & Omit<Schema.Opaque<Self, S, {}>, "makeUnsafe"> } & Omit<Schema.Opaque<Self, S, {}>, "make">
} }
} }
+2 -2
View File
@@ -13,7 +13,7 @@ import { errorMessage } from "../util/error"
import { BusEvent } from "@/bus/bus-event" import { BusEvent } from "@/bus/bus-event"
import { GlobalBus } from "@/bus/global" import { GlobalBus } from "@/bus/global"
import { Git } from "@/git" import { Git } from "@/git"
import { Effect, Layer, Path, Scope, ServiceMap, Stream } from "effect" import { Effect, Layer, Path, Scope, Context, Stream } from "effect"
import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process" import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process"
import { NodePath } from "@effect/platform-node" import { NodePath } from "@effect/platform-node"
import { AppFileSystem } from "@/filesystem" import { AppFileSystem } from "@/filesystem"
@@ -164,7 +164,7 @@ export namespace Worktree {
readonly reset: (input: ResetInput) => Effect.Effect<boolean> readonly reset: (input: ResetInput) => Effect.Effect<boolean>
} }
export class Service extends ServiceMap.Service<Service, Interface>()("@opencode/Worktree") {} export class Service extends Context.Service<Service, Interface>()("@opencode/Worktree") {}
type GitResult = { code: number; text: string; stderr: string } type GitResult = { code: number; text: string; stderr: string }
@@ -1,5 +1,5 @@
import { afterEach, expect, test } from "bun:test" import { afterEach, expect, test } from "bun:test"
import { Cause, Deferred, Duration, Effect, Exit, Fiber, Layer, ManagedRuntime, ServiceMap } from "effect" import { Cause, Deferred, Duration, Effect, Exit, Fiber, Layer, ManagedRuntime, Context } from "effect"
import { InstanceState } from "../../src/effect/instance-state" import { InstanceState } from "../../src/effect/instance-state"
import { InstanceRef } from "../../src/effect/instance-ref" import { InstanceRef } from "../../src/effect/instance-ref"
import { Instance } from "../../src/project/instance" import { Instance } from "../../src/project/instance"
@@ -122,7 +122,7 @@ test("InstanceState.get reads the current directory lazily", async () => {
readonly get: () => Effect.Effect<string> readonly get: () => Effect.Effect<string>
} }
class Test extends ServiceMap.Service<Test, Api>()("@test/InstanceStateLazy") { class Test extends Context.Service<Test, Api>()("@test/InstanceStateLazy") {
static readonly layer = Layer.effect( static readonly layer = Layer.effect(
Test, Test,
Effect.gen(function* () { Effect.gen(function* () {
@@ -166,7 +166,7 @@ test("InstanceState preserves directory across async boundaries", async () => {
readonly get: () => Effect.Effect<{ directory: string; worktree: string; project: string }> readonly get: () => Effect.Effect<{ directory: string; worktree: string; project: string }>
} }
class Test extends ServiceMap.Service<Test, Api>()("@test/InstanceStateAsync") { class Test extends Context.Service<Test, Api>()("@test/InstanceStateAsync") {
static readonly layer = Layer.effect( static readonly layer = Layer.effect(
Test, Test,
Effect.gen(function* () { Effect.gen(function* () {
@@ -234,7 +234,7 @@ test("InstanceState survives high-contention concurrent access", async () => {
readonly get: () => Effect.Effect<string> readonly get: () => Effect.Effect<string>
} }
class Test extends ServiceMap.Service<Test, Api>()("@test/HighContention") { class Test extends Context.Service<Test, Api>()("@test/HighContention") {
static readonly layer = Layer.effect( static readonly layer = Layer.effect(
Test, Test,
Effect.gen(function* () { Effect.gen(function* () {
@@ -284,7 +284,7 @@ test("InstanceState correct after interleaved init and dispose", async () => {
readonly get: () => Effect.Effect<string> readonly get: () => Effect.Effect<string>
} }
class Test extends ServiceMap.Service<Test, Api>()("@test/InterleavedDispose") { class Test extends Context.Service<Test, Api>()("@test/InterleavedDispose") {
static readonly layer = Layer.effect( static readonly layer = Layer.effect(
Test, Test,
Effect.gen(function* () { Effect.gen(function* () {
@@ -391,7 +391,7 @@ test("InstanceState survives deferred resume from the same instance context", as
readonly get: (gate: Deferred.Deferred<void>) => Effect.Effect<string> readonly get: (gate: Deferred.Deferred<void>) => Effect.Effect<string>
} }
class Test extends ServiceMap.Service<Test, Api>()("@test/DeferredResume") { class Test extends Context.Service<Test, Api>()("@test/DeferredResume") {
static readonly layer = Layer.effect( static readonly layer = Layer.effect(
Test, Test,
Effect.gen(function* () { Effect.gen(function* () {
@@ -438,7 +438,7 @@ test("InstanceState survives deferred resume outside ALS when InstanceRef is set
readonly get: (gate: Deferred.Deferred<void>) => Effect.Effect<string> readonly get: (gate: Deferred.Deferred<void>) => Effect.Effect<string>
} }
class Test extends ServiceMap.Service<Test, Api>()("@test/DeferredResumeOutside") { class Test extends Context.Service<Test, Api>()("@test/DeferredResumeOutside") {
static readonly layer = Layer.effect( static readonly layer = Layer.effect(
Test, Test,
Effect.gen(function* () { Effect.gen(function* () {
@@ -1,8 +1,8 @@
import { expect, test } from "bun:test" import { expect, test } from "bun:test"
import { Effect, Layer, ServiceMap } from "effect" import { Effect, Layer, Context } from "effect"
import { makeRuntime } from "../../src/effect/run-service" import { makeRuntime } from "../../src/effect/run-service"
class Shared extends ServiceMap.Service<Shared, { readonly id: number }>()("@test/Shared") {} class Shared extends Context.Service<Shared, { readonly id: number }>()("@test/Shared") {}
test("makeRuntime shares dependent layers through the shared memo map", async () => { test("makeRuntime shares dependent layers through the shared memo map", async () => {
let n = 0 let n = 0
@@ -15,7 +15,7 @@ test("makeRuntime shares dependent layers through the shared memo map", async ()
}), }),
) )
class One extends ServiceMap.Service<One, { readonly get: () => Effect.Effect<number> }>()("@test/One") {} class One extends Context.Service<One, { readonly get: () => Effect.Effect<number> }>()("@test/One") {}
const one = Layer.effect( const one = Layer.effect(
One, One,
Effect.gen(function* () { Effect.gen(function* () {
@@ -26,7 +26,7 @@ test("makeRuntime shares dependent layers through the shared memo map", async ()
}), }),
).pipe(Layer.provide(shared)) ).pipe(Layer.provide(shared))
class Two extends ServiceMap.Service<Two, { readonly get: () => Effect.Effect<number> }>()("@test/Two") {} class Two extends Context.Service<Two, { readonly get: () => Effect.Effect<number> }>()("@test/Two") {}
const two = Layer.effect( const two = Layer.effect(
Two, Two,
Effect.gen(function* () { Effect.gen(function* () {
+2 -2
View File
@@ -2,7 +2,7 @@ import { $ } from "bun"
import * as fs from "fs/promises" import * as fs from "fs/promises"
import os from "os" import os from "os"
import path from "path" import path from "path"
import { Effect, ServiceMap } from "effect" import { Effect, Context } from "effect"
import type * as PlatformError from "effect/PlatformError" import type * as PlatformError from "effect/PlatformError"
import type * as Scope from "effect/Scope" import type * as Scope from "effect/Scope"
import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process" import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process"
@@ -123,7 +123,7 @@ export function tmpdirScoped(options?: { git?: boolean; config?: Partial<Config.
export const provideInstance = export const provideInstance =
(directory: string) => (directory: string) =>
<A, E, R>(self: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> => <A, E, R>(self: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> =>
Effect.servicesWith((services: ServiceMap.ServiceMap<R>) => Effect.contextWith((services: Context.Context<R>) =>
Effect.promise<A>(async () => Effect.promise<A>(async () =>
Instance.provide({ Instance.provide({
directory, directory,
@@ -27,6 +27,7 @@ function mockSpawner(handler: (cmd: string, args: readonly string[]) => string =
all: Stream.empty, all: Stream.empty,
getInputFd: () => ({ [Symbol.for("effect/Sink/TypeId")]: Symbol.for("effect/Sink/TypeId") }) as any, getInputFd: () => ({ [Symbol.for("effect/Sink/TypeId")]: Symbol.for("effect/Sink/TypeId") }) as any,
getOutputFd: () => Stream.empty, getOutputFd: () => Stream.empty,
unref: Effect.succeed(Effect.void),
}), }),
) )
}) })
+2 -2
View File
@@ -1,6 +1,6 @@
import { NodeHttpServer, NodeHttpServerRequest } from "@effect/platform-node" import { NodeHttpServer, NodeHttpServerRequest } from "@effect/platform-node"
import * as Http from "node:http" import * as Http from "node:http"
import { Deferred, Effect, Layer, ServiceMap, Stream } from "effect" import { Deferred, Effect, Layer, Context, Stream } from "effect"
import * as HttpServer from "effect/unstable/http/HttpServer" import * as HttpServer from "effect/unstable/http/HttpServer"
import { HttpRouter, HttpServerRequest, HttpServerResponse } from "effect/unstable/http" import { HttpRouter, HttpServerRequest, HttpServerResponse } from "effect/unstable/http"
@@ -650,7 +650,7 @@ namespace TestLLMServer {
} }
} }
export class TestLLMServer extends ServiceMap.Service<TestLLMServer, TestLLMServer.Service>()("@test/LLMServer") { export class TestLLMServer extends Context.Service<TestLLMServer, TestLLMServer.Service>()("@test/LLMServer") {
static readonly layer = Layer.effect( static readonly layer = Layer.effect(
TestLLMServer, TestLLMServer,
Effect.gen(function* () { Effect.gen(function* () {
@@ -41,6 +41,7 @@ function mockGitFailure(failArg: string) {
all: Stream.empty, all: Stream.empty,
getInputFd: () => ({ [Symbol.for("effect/Sink/TypeId")]: Symbol.for("effect/Sink/TypeId") }) as any, getInputFd: () => ({ [Symbol.for("effect/Sink/TypeId")]: Symbol.for("effect/Sink/TypeId") }) as any,
getOutputFd: () => Stream.empty, getOutputFd: () => Stream.empty,
unref: Effect.succeed(Effect.void),
}) })
} }
return yield* real.spawn(command) return yield* real.spawn(command)