Skip to content

Commit 0e456c6

Browse files
Merge remote-tracking branch 'upstream/dev' into ocv
2 parents 60ed965 + f77277a commit 0e456c6

78 files changed

Lines changed: 1313 additions & 283 deletions

Some content is hidden

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

.opencode/skills/effect/SKILL.md

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,30 @@
11
---
22
name: effect
3-
description: Answer questions about the Effect framework
3+
description: Work with Effect v4 / effect-smol TypeScript code in this repo
44
---
55

66
# Effect
77

8-
This codebase uses Effect, a framework for writing typescript.
8+
This codebase uses Effect for typed, composable TypeScript services, schemas, and workflows.
99

10-
## How to Answer Effect Questions
10+
## Source Of Truth
1111

12-
1. Clone the Effect repository: `https://github.com/Effect-TS/effect-smol` to
13-
`.opencode/references/effect-smol` in this project NOT the skill folder.
14-
2. Use the explore agent to search the codebase for answers about Effect patterns, APIs, and concepts
15-
3. Provide responses based on the actual Effect source code and documentation
12+
Use the current Effect v4 / effect-smol source, not memory or older Effect v2/v3 examples.
13+
14+
1. If `.opencode/references/effect-smol` is missing, clone `https://github.com/Effect-TS/effect-smol` there. Do this in the project, not in the skill folder.
15+
2. Search `.opencode/references/effect-smol` for exact APIs, examples, tests, and naming patterns before answering or implementing Effect-specific code.
16+
3. Also inspect existing repo code for local house style before introducing new patterns.
17+
4. Prefer answers and implementations backed by specific source files or nearby repo examples.
1618

1719
## Guidelines
1820

19-
- Always use the explore agent with the cloned repository when answering Effect-related questions
20-
- Reference specific files and patterns found in the Effect codebase
21-
- Do not answer from memory - always verify against the source
21+
- Prefer current Effect v4 APIs and project-local patterns over old blog posts, examples, or package-memory guesses.
22+
- Use `Effect.gen(function* () { ... })` for multi-step workflows.
23+
- Use `Effect.fn("Name")` or `Effect.fnUntraced(...)` for named effects when adding reusable service methods or important workflows.
24+
- Prefer Effect `Schema` for API and domain data shapes. Use branded schemas for IDs and `Schema.TaggedErrorClass` for typed domain errors when modeling new error surfaces.
25+
- Keep HTTP handlers thin: decode input, read request context, call services, and map transport errors. Put business rules in services.
26+
- In Effect service code, prefer Effect-aware platform abstractions and dependencies over ad hoc promises where the surrounding code already does so.
27+
- Keep layer composition explicit. Avoid broad hidden provisioning that makes missing dependencies hard to see.
28+
- In tests, prefer the repo's existing Effect test helpers and live tests for filesystem, git, child process, locks, or timing behavior.
29+
- Do not introduce `any`, non-null assertions, unchecked casts, or older Effect APIs just to satisfy types.
30+
- Do not answer from memory. Verify against `.opencode/references/effect-smol` or nearby code first.

bun.lock

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

nix/hashes.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{
22
"nodeModules": {
3-
"x86_64-linux": "sha256-0w22pAViYEcELJpOrIVCjTQ73fnsSaJxb75heAIUdYE=",
4-
"aarch64-linux": "sha256-z1fpZ9HQU9n6W5xhKzuUduwQUJa/nrj9WFZdBLL/e/8=",
5-
"aarch64-darwin": "sha256-y5AraTdY2uDTltjQFlHjMoMo6FICgQNKSunIOnQAXnY=",
6-
"x86_64-darwin": "sha256-KQF6dJNQ587xp5h9ET+tLni9dLNwYnzxg2DX+KWfpoE="
3+
"x86_64-linux": "sha256-LpzWEZzURUEj7fcHGvh33gM7D9GNPE+XIvU0/hmdcQM=",
4+
"aarch64-linux": "sha256-0zdO3zuj6g9cMZFEOsvQJcKKcPjGVZJ2DkJdDcb2VCM=",
5+
"aarch64-darwin": "sha256-dmT8R9Pmzh5tjO8NCCCtENiQpJQeifQpVdhaty1MXOs=",
6+
"x86_64-darwin": "sha256-Q6rAQRoC6WaMAQl++YHAZmbNuO303cWgGaYzXaRlzy4="
77
}
88
}

packages/core/package.json

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,28 @@
1818
"imports": {},
1919
"devDependencies": {
2020
"@tsconfig/bun": "catalog:",
21-
"@types/semver": "catalog:",
2221
"@types/bun": "catalog:",
23-
"@types/npmcli__arborist": "6.3.3"
22+
"@types/cross-spawn": "catalog:",
23+
"@types/npm-package-arg": "6.1.4",
24+
"@types/npmcli__arborist": "6.3.3",
25+
"@types/semver": "catalog:"
2426
},
2527
"dependencies": {
2628
"@effect/opentelemetry": "catalog:",
2729
"@effect/platform-node": "catalog:",
28-
"@npmcli/arborist": "catalog:",
30+
"@npmcli/arborist": "9.4.0",
31+
"@npmcli/config": "10.8.1",
2932
"@opentelemetry/api": "1.9.0",
3033
"@opentelemetry/context-async-hooks": "2.6.1",
3134
"@opentelemetry/exporter-trace-otlp-http": "0.214.0",
3235
"@opentelemetry/sdk-trace-base": "2.6.1",
3336
"effect": "catalog:",
37+
"cross-spawn": "catalog:",
3438
"glob": "13.0.5",
3539
"mime-types": "3.0.2",
3640
"minimatch": "10.2.5",
37-
"semver": "catalog:",
41+
"npm-package-arg": "13.0.2",
42+
"semver": "^7.6.3",
3843
"xdg-basedir": "5.1.0",
3944
"zod": "catalog:"
4045
},
File renamed without changes.
Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
1-
export * as Npm from "."
1+
export * as Npm from "./npm"
22

33
import path from "path"
44
import { fileURLToPath } from "url"
55
import npa from "npm-package-arg"
66
import semver from "semver"
7+
// @ts-expect-error npm does not publish types for this internal config API.
78
import Config from "@npmcli/config"
9+
// @ts-expect-error npm does not publish types for this internal config API.
810
import { definitions, flatten, nerfDarts, shorthands } from "@npmcli/config/lib/definitions/index.js"
911
import { Effect, Schema, Context, Layer, Option, FileSystem, Stream } from "effect"
1012
import { NodeFileSystem } from "@effect/platform-node"
11-
import { AppFileSystem } from "@opencode-ai/core/filesystem"
12-
import { Global } from "@opencode-ai/core/global"
13-
import { EffectFlock } from "@opencode-ai/core/util/effect-flock"
14-
import { makeRuntime } from "@opencode-ai/core/effect/runtime"
13+
import { AppFileSystem } from "./filesystem"
14+
import { Global } from "./global"
15+
import { EffectFlock } from "./util/effect-flock"
16+
import { makeRuntime } from "./effect/runtime"
1517
import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process"
1618

17-
import * as CrossSpawnSpawner from "../effect/cross-spawn-spawner"
19+
import { CrossSpawnSpawner } from "./cross-spawn-spawner"
1820

1921
export class InstallFailedError extends Schema.TaggedErrorClass<InstallFailedError>()("NpmInstallFailedError", {
2022
add: Schema.Array(Schema.String).pipe(Schema.optional),
@@ -45,7 +47,7 @@ export interface Interface {
4547
export class Service extends Context.Service<Service, Interface>()("@opencode/Npm") {}
4648

4749
const illegal = process.platform === "win32" ? new Set(["<", ">", ":", '"', "|", "?", "*"]) : undefined
48-
const npmPath = fileURLToPath(new URL("../..", import.meta.url))
50+
const npmPath = fileURLToPath(new URL("..", import.meta.url))
4951

5052
export function sanitize(pkg: string) {
5153
if (!illegal) return pkg

packages/core/src/types.d.ts

Lines changed: 0 additions & 46 deletions
This file was deleted.

packages/opencode/test/effect/cross-spawn-spawner.test.ts renamed to packages/core/test/effect/cross-spawn-spawner.test.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { describe, expect } from "bun:test"
22
import fs from "node:fs/promises"
3+
import os from "node:os"
34
import path from "node:path"
45
import { Effect, Exit, Stream } from "effect"
56
import type * as PlatformError from "effect/PlatformError"
67
import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process"
7-
import * as CrossSpawnSpawner from "../../src/effect/cross-spawn-spawner"
8-
import { tmpdir } from "../fixture/fixture"
8+
import { CrossSpawnSpawner } from "@opencode-ai/core/cross-spawn-spawner"
99
import { testEffect } from "../lib/effect"
1010

1111
const live = CrossSpawnSpawner.defaultLayer
@@ -39,11 +39,21 @@ function alive(pid: number) {
3939
}
4040
}
4141

42+
async function tmpdir() {
43+
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "opencode-core-test-"))
44+
return {
45+
path: dir,
46+
async [Symbol.asyncDispose]() {
47+
await fs.rm(dir, { recursive: true, force: true })
48+
},
49+
}
50+
}
51+
4252
async function gone(pid: number, timeout = 5_000) {
4353
const end = Date.now() + timeout
4454
while (Date.now() < end) {
4555
if (!alive(pid)) return true
46-
await Bun.sleep(50)
56+
await new Promise((resolve) => setTimeout(resolve, 50))
4757
}
4858
return !alive(pid)
4959
}
@@ -395,7 +405,7 @@ describe("cross-spawn spawner", () => {
395405
const file = path.join(dir, "echo cmd.cmd")
396406

397407
yield* Effect.promise(() => fs.mkdir(dir, { recursive: true }))
398-
yield* Effect.promise(() => Bun.write(file, "@echo off\r\nif %~1==--stdio exit /b 0\r\nexit /b 7\r\n"))
408+
yield* Effect.promise(() => fs.writeFile(file, "@echo off\r\nif %~1==--stdio exit /b 0\r\nexit /b 7\r\n"))
399409

400410
const code = yield* ChildProcessSpawner.ChildProcessSpawner.use((svc) =>
401411
svc.exitCode(

packages/opencode/package.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@
6161
"@types/cross-spawn": "catalog:",
6262
"@types/mime-types": "3.0.1",
6363
"@types/npm-package-arg": "6.1.4",
64-
"@types/npmcli__arborist": "6.3.3",
6564
"@types/semver": "^7.5.8",
6665
"@types/turndown": "5.0.5",
6766
"@types/which": "3.0.4",
@@ -110,8 +109,6 @@
110109
"@hono/zod-validator": "catalog:",
111110
"@lydell/node-pty": "catalog:",
112111
"@modelcontextprotocol/sdk": "1.27.1",
113-
"@npmcli/arborist": "9.4.0",
114-
"@npmcli/config": "10.8.1",
115112
"@octokit/graphql": "9.0.2",
116113
"@octokit/rest": "catalog:",
117114
"@openauthjs/openauth": "catalog:",

0 commit comments

Comments
 (0)