mirror of
https://github.com/anomalyco/opencode.git
synced 2026-08-16 01:19:19 -04:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| eba2217601 |
@@ -45,13 +45,13 @@ jobs:
|
|||||||
|
|
||||||
- name: Check PR guidelines compliance
|
- name: Check PR guidelines compliance
|
||||||
env:
|
env:
|
||||||
OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }}
|
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
OPENCODE_PERMISSION: '{ "bash": { "*": "deny", "gh*": "allow", "gh pr review*": "deny" } }'
|
OPENCODE_PERMISSION: '{ "bash": { "*": "deny", "gh*": "allow", "gh pr review*": "deny" } }'
|
||||||
PR_TITLE: ${{ steps.pr-details.outputs.title }}
|
PR_TITLE: ${{ steps.pr-details.outputs.title }}
|
||||||
run: |
|
run: |
|
||||||
PR_BODY=$(jq -r .body pr_data.json)
|
PR_BODY=$(jq -r .body pr_data.json)
|
||||||
opencode run -m opencode/gpt-5.5 --variant medium "A new pull request has been created: '${PR_TITLE}'
|
opencode run -m anthropic/claude-opus-4-5 "A new pull request has been created: '${PR_TITLE}'
|
||||||
|
|
||||||
<pr-number>
|
<pr-number>
|
||||||
${{ steps.pr-number.outputs.number }}
|
${{ steps.pr-number.outputs.number }}
|
||||||
|
|||||||
@@ -1,30 +1,21 @@
|
|||||||
---
|
---
|
||||||
name: effect
|
name: effect
|
||||||
description: Work with Effect v4 / effect-smol TypeScript code in this repo
|
description: Answer questions about the Effect framework
|
||||||
---
|
---
|
||||||
|
|
||||||
# Effect
|
# Effect
|
||||||
|
|
||||||
This codebase uses Effect for typed, composable TypeScript services, schemas, and workflows.
|
This codebase uses Effect, a framework for writing typescript.
|
||||||
|
|
||||||
## Source Of Truth
|
## How to Answer Effect Questions
|
||||||
|
|
||||||
Use the current Effect v4 / effect-smol source, not memory or older Effect v2/v3 examples.
|
1. Clone the Effect repository: `https://github.com/Effect-TS/effect-smol` to
|
||||||
|
`.opencode/references/effect-smol` in this project NOT the skill folder.
|
||||||
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.
|
2. Use the explore agent to search the codebase for answers about Effect patterns, APIs, and concepts
|
||||||
2. Search `.opencode/references/effect-smol` for exact APIs, examples, tests, and naming patterns before answering or implementing Effect-specific code.
|
3. Provide responses based on the actual Effect source code and documentation
|
||||||
3. Also inspect existing repo code for local house style before introducing new patterns.
|
|
||||||
4. Prefer answers and implementations backed by specific source files or nearby repo examples.
|
|
||||||
|
|
||||||
## Guidelines
|
## Guidelines
|
||||||
|
|
||||||
- Prefer current Effect v4 APIs and project-local patterns over old blog posts, examples, or package-memory guesses.
|
- Always use the explore agent with the cloned repository when answering Effect-related questions
|
||||||
- Use `Effect.gen(function* () { ... })` for multi-step workflows.
|
- Reference specific files and patterns found in the Effect codebase
|
||||||
- Use `Effect.fn("Name")` or `Effect.fnUntraced(...)` for named effects when adding reusable service methods or important workflows.
|
- Do not answer from memory - always verify against the source
|
||||||
- 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.
|
|
||||||
- Keep HTTP handlers thin: decode input, read request context, call services, and map transport errors. Put business rules in services.
|
|
||||||
- In Effect service code, prefer Effect-aware platform abstractions and dependencies over ad hoc promises where the surrounding code already does so.
|
|
||||||
- Keep layer composition explicit. Avoid broad hidden provisioning that makes missing dependencies hard to see.
|
|
||||||
- In tests, prefer the repo's existing Effect test helpers and live tests for filesystem, git, child process, locks, or timing behavior.
|
|
||||||
- Do not introduce `any`, non-null assertions, unchecked casts, or older Effect APIs just to satisfy types.
|
|
||||||
- Do not answer from memory. Verify against `.opencode/references/effect-smol` or nearby code first.
|
|
||||||
|
|||||||
@@ -29,11 +29,11 @@
|
|||||||
},
|
},
|
||||||
"packages/app": {
|
"packages/app": {
|
||||||
"name": "@opencode-ai/app",
|
"name": "@opencode-ai/app",
|
||||||
"version": "1.14.25",
|
"version": "1.14.24",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@kobalte/core": "catalog:",
|
"@kobalte/core": "catalog:",
|
||||||
"@opencode-ai/core": "workspace:*",
|
|
||||||
"@opencode-ai/sdk": "workspace:*",
|
"@opencode-ai/sdk": "workspace:*",
|
||||||
|
"@opencode-ai/shared": "workspace:*",
|
||||||
"@opencode-ai/ui": "workspace:*",
|
"@opencode-ai/ui": "workspace:*",
|
||||||
"@shikijs/transformers": "3.9.2",
|
"@shikijs/transformers": "3.9.2",
|
||||||
"@solid-primitives/active-element": "2.1.3",
|
"@solid-primitives/active-element": "2.1.3",
|
||||||
@@ -83,7 +83,7 @@
|
|||||||
},
|
},
|
||||||
"packages/console/app": {
|
"packages/console/app": {
|
||||||
"name": "@opencode-ai/console-app",
|
"name": "@opencode-ai/console-app",
|
||||||
"version": "1.14.25",
|
"version": "1.14.24",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@cloudflare/vite-plugin": "1.15.2",
|
"@cloudflare/vite-plugin": "1.15.2",
|
||||||
"@ibm/plex": "6.4.1",
|
"@ibm/plex": "6.4.1",
|
||||||
@@ -117,7 +117,7 @@
|
|||||||
},
|
},
|
||||||
"packages/console/core": {
|
"packages/console/core": {
|
||||||
"name": "@opencode-ai/console-core",
|
"name": "@opencode-ai/console-core",
|
||||||
"version": "1.14.25",
|
"version": "1.14.24",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/client-sts": "3.782.0",
|
"@aws-sdk/client-sts": "3.782.0",
|
||||||
"@jsx-email/render": "1.1.1",
|
"@jsx-email/render": "1.1.1",
|
||||||
@@ -144,7 +144,7 @@
|
|||||||
},
|
},
|
||||||
"packages/console/function": {
|
"packages/console/function": {
|
||||||
"name": "@opencode-ai/console-function",
|
"name": "@opencode-ai/console-function",
|
||||||
"version": "1.14.25",
|
"version": "1.14.24",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ai-sdk/anthropic": "3.0.64",
|
"@ai-sdk/anthropic": "3.0.64",
|
||||||
"@ai-sdk/openai": "3.0.48",
|
"@ai-sdk/openai": "3.0.48",
|
||||||
@@ -168,7 +168,7 @@
|
|||||||
},
|
},
|
||||||
"packages/console/mail": {
|
"packages/console/mail": {
|
||||||
"name": "@opencode-ai/console-mail",
|
"name": "@opencode-ai/console-mail",
|
||||||
"version": "1.14.25",
|
"version": "1.14.24",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jsx-email/all": "2.2.3",
|
"@jsx-email/all": "2.2.3",
|
||||||
"@jsx-email/cli": "1.4.3",
|
"@jsx-email/cli": "1.4.3",
|
||||||
@@ -190,43 +190,9 @@
|
|||||||
"cloudflare": "5.2.0",
|
"cloudflare": "5.2.0",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"packages/core": {
|
|
||||||
"name": "@opencode-ai/core",
|
|
||||||
"version": "1.14.25",
|
|
||||||
"bin": {
|
|
||||||
"opencode": "./bin/opencode",
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@effect/opentelemetry": "catalog:",
|
|
||||||
"@effect/platform-node": "catalog:",
|
|
||||||
"@npmcli/arborist": "9.4.0",
|
|
||||||
"@npmcli/config": "10.8.1",
|
|
||||||
"@opentelemetry/api": "1.9.0",
|
|
||||||
"@opentelemetry/context-async-hooks": "2.6.1",
|
|
||||||
"@opentelemetry/exporter-trace-otlp-http": "0.214.0",
|
|
||||||
"@opentelemetry/sdk-trace-base": "2.6.1",
|
|
||||||
"cross-spawn": "catalog:",
|
|
||||||
"effect": "catalog:",
|
|
||||||
"glob": "13.0.5",
|
|
||||||
"mime-types": "3.0.2",
|
|
||||||
"minimatch": "10.2.5",
|
|
||||||
"npm-package-arg": "13.0.2",
|
|
||||||
"semver": "^7.6.3",
|
|
||||||
"xdg-basedir": "5.1.0",
|
|
||||||
"zod": "catalog:",
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@tsconfig/bun": "catalog:",
|
|
||||||
"@types/bun": "catalog:",
|
|
||||||
"@types/cross-spawn": "catalog:",
|
|
||||||
"@types/npm-package-arg": "6.1.4",
|
|
||||||
"@types/npmcli__arborist": "6.3.3",
|
|
||||||
"@types/semver": "catalog:",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"packages/desktop": {
|
"packages/desktop": {
|
||||||
"name": "@opencode-ai/desktop",
|
"name": "@opencode-ai/desktop",
|
||||||
"version": "1.14.25",
|
"version": "1.14.24",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@opencode-ai/app": "workspace:*",
|
"@opencode-ai/app": "workspace:*",
|
||||||
"@opencode-ai/ui": "workspace:*",
|
"@opencode-ai/ui": "workspace:*",
|
||||||
@@ -259,7 +225,7 @@
|
|||||||
},
|
},
|
||||||
"packages/desktop-electron": {
|
"packages/desktop-electron": {
|
||||||
"name": "@opencode-ai/desktop-electron",
|
"name": "@opencode-ai/desktop-electron",
|
||||||
"version": "1.14.25",
|
"version": "1.14.24",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"drizzle-orm": "catalog:",
|
"drizzle-orm": "catalog:",
|
||||||
"effect": "catalog:",
|
"effect": "catalog:",
|
||||||
@@ -303,9 +269,9 @@
|
|||||||
},
|
},
|
||||||
"packages/enterprise": {
|
"packages/enterprise": {
|
||||||
"name": "@opencode-ai/enterprise",
|
"name": "@opencode-ai/enterprise",
|
||||||
"version": "1.14.25",
|
"version": "1.14.24",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@opencode-ai/core": "workspace:*",
|
"@opencode-ai/shared": "workspace:*",
|
||||||
"@opencode-ai/ui": "workspace:*",
|
"@opencode-ai/ui": "workspace:*",
|
||||||
"@pierre/diffs": "catalog:",
|
"@pierre/diffs": "catalog:",
|
||||||
"@solidjs/meta": "catalog:",
|
"@solidjs/meta": "catalog:",
|
||||||
@@ -332,7 +298,7 @@
|
|||||||
},
|
},
|
||||||
"packages/function": {
|
"packages/function": {
|
||||||
"name": "@opencode-ai/function",
|
"name": "@opencode-ai/function",
|
||||||
"version": "1.14.25",
|
"version": "1.14.24",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@octokit/auth-app": "8.0.1",
|
"@octokit/auth-app": "8.0.1",
|
||||||
"@octokit/rest": "catalog:",
|
"@octokit/rest": "catalog:",
|
||||||
@@ -348,7 +314,7 @@
|
|||||||
},
|
},
|
||||||
"packages/opencode": {
|
"packages/opencode": {
|
||||||
"name": "opencode",
|
"name": "opencode",
|
||||||
"version": "1.14.25",
|
"version": "1.14.24",
|
||||||
"bin": {
|
"bin": {
|
||||||
"opencode": "./bin/opencode",
|
"opencode": "./bin/opencode",
|
||||||
},
|
},
|
||||||
@@ -387,6 +353,8 @@
|
|||||||
"@hono/zod-validator": "catalog:",
|
"@hono/zod-validator": "catalog:",
|
||||||
"@lydell/node-pty": "catalog:",
|
"@lydell/node-pty": "catalog:",
|
||||||
"@modelcontextprotocol/sdk": "1.27.1",
|
"@modelcontextprotocol/sdk": "1.27.1",
|
||||||
|
"@npmcli/arborist": "9.4.0",
|
||||||
|
"@npmcli/config": "10.8.1",
|
||||||
"@octokit/graphql": "9.0.2",
|
"@octokit/graphql": "9.0.2",
|
||||||
"@octokit/rest": "catalog:",
|
"@octokit/rest": "catalog:",
|
||||||
"@openauthjs/openauth": "catalog:",
|
"@openauthjs/openauth": "catalog:",
|
||||||
@@ -399,8 +367,8 @@
|
|||||||
"@opentelemetry/exporter-trace-otlp-http": "0.214.0",
|
"@opentelemetry/exporter-trace-otlp-http": "0.214.0",
|
||||||
"@opentelemetry/sdk-trace-base": "2.6.1",
|
"@opentelemetry/sdk-trace-base": "2.6.1",
|
||||||
"@opentelemetry/sdk-trace-node": "2.6.1",
|
"@opentelemetry/sdk-trace-node": "2.6.1",
|
||||||
"@opentui/core": "catalog:",
|
"@opentui/core": "0.1.103",
|
||||||
"@opentui/solid": "catalog:",
|
"@opentui/solid": "0.1.103",
|
||||||
"@parcel/watcher": "2.5.1",
|
"@parcel/watcher": "2.5.1",
|
||||||
"@pierre/diffs": "catalog:",
|
"@pierre/diffs": "catalog:",
|
||||||
"@solid-primitives/event-bus": "1.1.2",
|
"@solid-primitives/event-bus": "1.1.2",
|
||||||
@@ -435,7 +403,7 @@
|
|||||||
"open": "10.1.2",
|
"open": "10.1.2",
|
||||||
"opencode-gitlab-auth": "2.0.1",
|
"opencode-gitlab-auth": "2.0.1",
|
||||||
"opencode-poe-auth": "0.0.1",
|
"opencode-poe-auth": "0.0.1",
|
||||||
"opentui-spinner": "catalog:",
|
"opentui-spinner": "0.0.6",
|
||||||
"partial-json": "0.1.7",
|
"partial-json": "0.1.7",
|
||||||
"remeda": "catalog:",
|
"remeda": "catalog:",
|
||||||
"semver": "^7.6.3",
|
"semver": "^7.6.3",
|
||||||
@@ -458,8 +426,8 @@
|
|||||||
"@babel/core": "7.28.4",
|
"@babel/core": "7.28.4",
|
||||||
"@effect/language-service": "0.84.2",
|
"@effect/language-service": "0.84.2",
|
||||||
"@octokit/webhooks-types": "7.6.1",
|
"@octokit/webhooks-types": "7.6.1",
|
||||||
"@opencode-ai/core": "workspace:*",
|
|
||||||
"@opencode-ai/script": "workspace:*",
|
"@opencode-ai/script": "workspace:*",
|
||||||
|
"@opencode-ai/shared": "workspace:*",
|
||||||
"@parcel/watcher-darwin-arm64": "2.5.1",
|
"@parcel/watcher-darwin-arm64": "2.5.1",
|
||||||
"@parcel/watcher-darwin-x64": "2.5.1",
|
"@parcel/watcher-darwin-x64": "2.5.1",
|
||||||
"@parcel/watcher-linux-arm64-glibc": "2.5.1",
|
"@parcel/watcher-linux-arm64-glibc": "2.5.1",
|
||||||
@@ -475,6 +443,7 @@
|
|||||||
"@types/cross-spawn": "catalog:",
|
"@types/cross-spawn": "catalog:",
|
||||||
"@types/mime-types": "3.0.1",
|
"@types/mime-types": "3.0.1",
|
||||||
"@types/npm-package-arg": "6.1.4",
|
"@types/npm-package-arg": "6.1.4",
|
||||||
|
"@types/npmcli__arborist": "6.3.3",
|
||||||
"@types/semver": "^7.5.8",
|
"@types/semver": "^7.5.8",
|
||||||
"@types/turndown": "5.0.5",
|
"@types/turndown": "5.0.5",
|
||||||
"@types/which": "3.0.4",
|
"@types/which": "3.0.4",
|
||||||
@@ -491,15 +460,15 @@
|
|||||||
},
|
},
|
||||||
"packages/plugin": {
|
"packages/plugin": {
|
||||||
"name": "@opencode-ai/plugin",
|
"name": "@opencode-ai/plugin",
|
||||||
"version": "1.14.25",
|
"version": "1.14.24",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@opencode-ai/sdk": "workspace:*",
|
"@opencode-ai/sdk": "workspace:*",
|
||||||
"effect": "catalog:",
|
"effect": "catalog:",
|
||||||
"zod": "catalog:",
|
"zod": "catalog:",
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@opentui/core": "catalog:",
|
"@opentui/core": "0.1.103",
|
||||||
"@opentui/solid": "catalog:",
|
"@opentui/solid": "0.1.103",
|
||||||
"@tsconfig/node22": "catalog:",
|
"@tsconfig/node22": "catalog:",
|
||||||
"@types/node": "catalog:",
|
"@types/node": "catalog:",
|
||||||
"@typescript/native-preview": "catalog:",
|
"@typescript/native-preview": "catalog:",
|
||||||
@@ -526,7 +495,7 @@
|
|||||||
},
|
},
|
||||||
"packages/sdk/js": {
|
"packages/sdk/js": {
|
||||||
"name": "@opencode-ai/sdk",
|
"name": "@opencode-ai/sdk",
|
||||||
"version": "1.14.25",
|
"version": "1.14.24",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cross-spawn": "catalog:",
|
"cross-spawn": "catalog:",
|
||||||
},
|
},
|
||||||
@@ -539,9 +508,33 @@
|
|||||||
"typescript": "catalog:",
|
"typescript": "catalog:",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"packages/shared": {
|
||||||
|
"name": "@opencode-ai/shared",
|
||||||
|
"version": "1.14.24",
|
||||||
|
"bin": {
|
||||||
|
"opencode": "./bin/opencode",
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@effect/platform-node": "catalog:",
|
||||||
|
"@npmcli/arborist": "catalog:",
|
||||||
|
"effect": "catalog:",
|
||||||
|
"glob": "13.0.5",
|
||||||
|
"mime-types": "3.0.2",
|
||||||
|
"minimatch": "10.2.5",
|
||||||
|
"semver": "catalog:",
|
||||||
|
"xdg-basedir": "5.1.0",
|
||||||
|
"zod": "catalog:",
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@tsconfig/bun": "catalog:",
|
||||||
|
"@types/bun": "catalog:",
|
||||||
|
"@types/npmcli__arborist": "6.3.3",
|
||||||
|
"@types/semver": "catalog:",
|
||||||
|
},
|
||||||
|
},
|
||||||
"packages/slack": {
|
"packages/slack": {
|
||||||
"name": "@opencode-ai/slack",
|
"name": "@opencode-ai/slack",
|
||||||
"version": "1.14.25",
|
"version": "1.14.24",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@opencode-ai/sdk": "workspace:*",
|
"@opencode-ai/sdk": "workspace:*",
|
||||||
"@slack/bolt": "^3.17.1",
|
"@slack/bolt": "^3.17.1",
|
||||||
@@ -576,11 +569,11 @@
|
|||||||
},
|
},
|
||||||
"packages/ui": {
|
"packages/ui": {
|
||||||
"name": "@opencode-ai/ui",
|
"name": "@opencode-ai/ui",
|
||||||
"version": "1.14.25",
|
"version": "1.14.24",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@kobalte/core": "catalog:",
|
"@kobalte/core": "catalog:",
|
||||||
"@opencode-ai/core": "workspace:*",
|
|
||||||
"@opencode-ai/sdk": "workspace:*",
|
"@opencode-ai/sdk": "workspace:*",
|
||||||
|
"@opencode-ai/shared": "workspace:*",
|
||||||
"@pierre/diffs": "catalog:",
|
"@pierre/diffs": "catalog:",
|
||||||
"@shikijs/transformers": "3.9.2",
|
"@shikijs/transformers": "3.9.2",
|
||||||
"@solid-primitives/bounds": "0.1.3",
|
"@solid-primitives/bounds": "0.1.3",
|
||||||
@@ -625,7 +618,7 @@
|
|||||||
},
|
},
|
||||||
"packages/web": {
|
"packages/web": {
|
||||||
"name": "@opencode-ai/web",
|
"name": "@opencode-ai/web",
|
||||||
"version": "1.14.25",
|
"version": "1.14.24",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@astrojs/cloudflare": "12.6.3",
|
"@astrojs/cloudflare": "12.6.3",
|
||||||
"@astrojs/markdown-remark": "6.3.1",
|
"@astrojs/markdown-remark": "6.3.1",
|
||||||
@@ -685,8 +678,8 @@
|
|||||||
"@npmcli/arborist": "9.4.0",
|
"@npmcli/arborist": "9.4.0",
|
||||||
"@octokit/rest": "22.0.0",
|
"@octokit/rest": "22.0.0",
|
||||||
"@openauthjs/openauth": "0.0.0-20250322224806",
|
"@openauthjs/openauth": "0.0.0-20250322224806",
|
||||||
"@opentui/core": "0.1.103",
|
"@opentui/core": "0.1.99",
|
||||||
"@opentui/solid": "0.1.103",
|
"@opentui/solid": "0.1.99",
|
||||||
"@pierre/diffs": "1.1.0-beta.18",
|
"@pierre/diffs": "1.1.0-beta.18",
|
||||||
"@playwright/test": "1.59.1",
|
"@playwright/test": "1.59.1",
|
||||||
"@solid-primitives/storage": "4.3.3",
|
"@solid-primitives/storage": "4.3.3",
|
||||||
@@ -715,7 +708,6 @@
|
|||||||
"luxon": "3.6.1",
|
"luxon": "3.6.1",
|
||||||
"marked": "17.0.1",
|
"marked": "17.0.1",
|
||||||
"marked-shiki": "1.2.1",
|
"marked-shiki": "1.2.1",
|
||||||
"opentui-spinner": "0.0.6",
|
|
||||||
"remeda": "2.26.0",
|
"remeda": "2.26.0",
|
||||||
"remend": "1.3.0",
|
"remend": "1.3.0",
|
||||||
"semver": "7.7.4",
|
"semver": "7.7.4",
|
||||||
@@ -1561,8 +1553,6 @@
|
|||||||
|
|
||||||
"@opencode-ai/console-resource": ["@opencode-ai/console-resource@workspace:packages/console/resource"],
|
"@opencode-ai/console-resource": ["@opencode-ai/console-resource@workspace:packages/console/resource"],
|
||||||
|
|
||||||
"@opencode-ai/core": ["@opencode-ai/core@workspace:packages/core"],
|
|
||||||
|
|
||||||
"@opencode-ai/desktop": ["@opencode-ai/desktop@workspace:packages/desktop"],
|
"@opencode-ai/desktop": ["@opencode-ai/desktop@workspace:packages/desktop"],
|
||||||
|
|
||||||
"@opencode-ai/desktop-electron": ["@opencode-ai/desktop-electron@workspace:packages/desktop-electron"],
|
"@opencode-ai/desktop-electron": ["@opencode-ai/desktop-electron@workspace:packages/desktop-electron"],
|
||||||
@@ -1577,6 +1567,8 @@
|
|||||||
|
|
||||||
"@opencode-ai/sdk": ["@opencode-ai/sdk@workspace:packages/sdk/js"],
|
"@opencode-ai/sdk": ["@opencode-ai/sdk@workspace:packages/sdk/js"],
|
||||||
|
|
||||||
|
"@opencode-ai/shared": ["@opencode-ai/shared@workspace:packages/shared"],
|
||||||
|
|
||||||
"@opencode-ai/slack": ["@opencode-ai/slack@workspace:packages/slack"],
|
"@opencode-ai/slack": ["@opencode-ai/slack@workspace:packages/slack"],
|
||||||
|
|
||||||
"@opencode-ai/storybook": ["@opencode-ai/storybook@workspace:packages/storybook"],
|
"@opencode-ai/storybook": ["@opencode-ai/storybook@workspace:packages/storybook"],
|
||||||
|
|||||||
+4
-4
@@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"nodeModules": {
|
"nodeModules": {
|
||||||
"x86_64-linux": "sha256-LpzWEZzURUEj7fcHGvh33gM7D9GNPE+XIvU0/hmdcQM=",
|
"x86_64-linux": "sha256-V1Rt2k7ujkqGw4pDkn++WALTy1fAugvoKLhKvwFKkss=",
|
||||||
"aarch64-linux": "sha256-0zdO3zuj6g9cMZFEOsvQJcKKcPjGVZJ2DkJdDcb2VCM=",
|
"aarch64-linux": "sha256-ho0AuGbJ1qw9Hvb3EbGC8f0lWqqgUslvda/wTe32MFo=",
|
||||||
"aarch64-darwin": "sha256-dmT8R9Pmzh5tjO8NCCCtENiQpJQeifQpVdhaty1MXOs=",
|
"aarch64-darwin": "sha256-hdUyNmp+snwtnBckHXsPMgNFUYS1sYDdngkk+AXVqzc=",
|
||||||
"x86_64-darwin": "sha256-Q6rAQRoC6WaMAQl++YHAZmbNuO303cWgGaYzXaRlzy4="
|
"x86_64-darwin": "sha256-P57LpQNF8fplFKQBBIukhOKbIugbViyBUIUjClXohuk="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-3
@@ -34,8 +34,8 @@
|
|||||||
"@types/cross-spawn": "6.0.6",
|
"@types/cross-spawn": "6.0.6",
|
||||||
"@octokit/rest": "22.0.0",
|
"@octokit/rest": "22.0.0",
|
||||||
"@hono/zod-validator": "0.4.2",
|
"@hono/zod-validator": "0.4.2",
|
||||||
"@opentui/core": "0.1.103",
|
"@opentui/core": "0.1.99",
|
||||||
"@opentui/solid": "0.1.103",
|
"@opentui/solid": "0.1.99",
|
||||||
"ulid": "3.0.1",
|
"ulid": "3.0.1",
|
||||||
"@kobalte/core": "0.13.11",
|
"@kobalte/core": "0.13.11",
|
||||||
"@types/luxon": "3.7.1",
|
"@types/luxon": "3.7.1",
|
||||||
@@ -46,7 +46,6 @@
|
|||||||
"@cloudflare/workers-types": "4.20251008.0",
|
"@cloudflare/workers-types": "4.20251008.0",
|
||||||
"@openauthjs/openauth": "0.0.0-20250322224806",
|
"@openauthjs/openauth": "0.0.0-20250322224806",
|
||||||
"@pierre/diffs": "1.1.0-beta.18",
|
"@pierre/diffs": "1.1.0-beta.18",
|
||||||
"opentui-spinner": "0.0.6",
|
|
||||||
"@solid-primitives/storage": "4.3.3",
|
"@solid-primitives/storage": "4.3.3",
|
||||||
"@tailwindcss/vite": "4.1.11",
|
"@tailwindcss/vite": "4.1.11",
|
||||||
"diff": "8.0.2",
|
"diff": "8.0.2",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@opencode-ai/app",
|
"name": "@opencode-ai/app",
|
||||||
"version": "1.14.25",
|
"version": "1.14.24",
|
||||||
"description": "",
|
"description": "",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"exports": {
|
"exports": {
|
||||||
@@ -42,7 +42,7 @@
|
|||||||
"@kobalte/core": "catalog:",
|
"@kobalte/core": "catalog:",
|
||||||
"@opencode-ai/sdk": "workspace:*",
|
"@opencode-ai/sdk": "workspace:*",
|
||||||
"@opencode-ai/ui": "workspace:*",
|
"@opencode-ai/ui": "workspace:*",
|
||||||
"@opencode-ai/core": "workspace:*",
|
"@opencode-ai/shared": "workspace:*",
|
||||||
"@shikijs/transformers": "3.9.2",
|
"@shikijs/transformers": "3.9.2",
|
||||||
"@solid-primitives/active-element": "2.1.3",
|
"@solid-primitives/active-element": "2.1.3",
|
||||||
"@solid-primitives/audio": "1.4.2",
|
"@solid-primitives/audio": "1.4.2",
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { createStore } from "solid-js/store"
|
|||||||
import { useGlobalSDK } from "@/context/global-sdk"
|
import { useGlobalSDK } from "@/context/global-sdk"
|
||||||
import { useGlobalSync } from "@/context/global-sync"
|
import { useGlobalSync } from "@/context/global-sync"
|
||||||
import { type LocalProject, getAvatarColors } from "@/context/layout"
|
import { type LocalProject, getAvatarColors } from "@/context/layout"
|
||||||
import { getFilename } from "@opencode-ai/core/util/path"
|
import { getFilename } from "@opencode-ai/shared/util/path"
|
||||||
import { Avatar } from "@opencode-ai/ui/avatar"
|
import { Avatar } from "@opencode-ai/ui/avatar"
|
||||||
import { useLanguage } from "@/context/language"
|
import { useLanguage } from "@/context/language"
|
||||||
import { getProjectAvatarSource } from "@/pages/layout/sidebar-items"
|
import { getProjectAvatarSource } from "@/pages/layout/sidebar-items"
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { List } from "@opencode-ai/ui/list"
|
|||||||
import { showToast } from "@opencode-ai/ui/toast"
|
import { showToast } from "@opencode-ai/ui/toast"
|
||||||
import { extractPromptFromParts } from "@/utils/prompt"
|
import { extractPromptFromParts } from "@/utils/prompt"
|
||||||
import type { TextPart as SDKTextPart } from "@opencode-ai/sdk/v2/client"
|
import type { TextPart as SDKTextPart } from "@opencode-ai/sdk/v2/client"
|
||||||
import { base64Encode } from "@opencode-ai/core/util/encode"
|
import { base64Encode } from "@opencode-ai/shared/util/encode"
|
||||||
import { useLanguage } from "@/context/language"
|
import { useLanguage } from "@/context/language"
|
||||||
|
|
||||||
interface ForkableMessage {
|
interface ForkableMessage {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { Dialog } from "@opencode-ai/ui/dialog"
|
|||||||
import { FileIcon } from "@opencode-ai/ui/file-icon"
|
import { FileIcon } from "@opencode-ai/ui/file-icon"
|
||||||
import { List } from "@opencode-ai/ui/list"
|
import { List } from "@opencode-ai/ui/list"
|
||||||
import type { ListRef } from "@opencode-ai/ui/list"
|
import type { ListRef } from "@opencode-ai/ui/list"
|
||||||
import { getDirectory, getFilename } from "@opencode-ai/core/util/path"
|
import { getDirectory, getFilename } from "@opencode-ai/shared/util/path"
|
||||||
import fuzzysort from "fuzzysort"
|
import fuzzysort from "fuzzysort"
|
||||||
import { createMemo, createResource, createSignal } from "solid-js"
|
import { createMemo, createResource, createSignal } from "solid-js"
|
||||||
import { useGlobalSDK } from "@/context/global-sdk"
|
import { useGlobalSDK } from "@/context/global-sdk"
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import { FileIcon } from "@opencode-ai/ui/file-icon"
|
|||||||
import { Icon } from "@opencode-ai/ui/icon"
|
import { Icon } from "@opencode-ai/ui/icon"
|
||||||
import { Keybind } from "@opencode-ai/ui/keybind"
|
import { Keybind } from "@opencode-ai/ui/keybind"
|
||||||
import { List } from "@opencode-ai/ui/list"
|
import { List } from "@opencode-ai/ui/list"
|
||||||
import { base64Encode } from "@opencode-ai/core/util/encode"
|
import { base64Encode } from "@opencode-ai/shared/util/encode"
|
||||||
import { getDirectory, getFilename } from "@opencode-ai/core/util/path"
|
import { getDirectory, getFilename } from "@opencode-ai/shared/util/path"
|
||||||
import { useNavigate } from "@solidjs/router"
|
import { useNavigate } from "@solidjs/router"
|
||||||
import { createMemo, createSignal, Match, onCleanup, Show, Switch } from "solid-js"
|
import { createMemo, createSignal, Match, onCleanup, Show, Switch } from "solid-js"
|
||||||
import { formatKeybind, useCommand, type CommandOption } from "@/context/command"
|
import { formatKeybind, useCommand, type CommandOption } from "@/context/command"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { getFilename } from "@opencode-ai/core/util/path"
|
import { getFilename } from "@opencode-ai/shared/util/path"
|
||||||
import { type AgentPartInput, type FilePartInput, type Part, type TextPartInput } from "@opencode-ai/sdk/v2/client"
|
import { type AgentPartInput, type FilePartInput, type Part, type TextPartInput } from "@opencode-ai/sdk/v2/client"
|
||||||
import type { FileSelection } from "@/context/file"
|
import type { FileSelection } from "@/context/file"
|
||||||
import { encodeFilePath } from "@/context/file/path"
|
import { encodeFilePath } from "@/context/file/path"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { Component, For, Show } from "solid-js"
|
|||||||
import { FileIcon } from "@opencode-ai/ui/file-icon"
|
import { FileIcon } from "@opencode-ai/ui/file-icon"
|
||||||
import { IconButton } from "@opencode-ai/ui/icon-button"
|
import { IconButton } from "@opencode-ai/ui/icon-button"
|
||||||
import { Tooltip } from "@opencode-ai/ui/tooltip"
|
import { Tooltip } from "@opencode-ai/ui/tooltip"
|
||||||
import { getDirectory, getFilename, getFilenameTruncated } from "@opencode-ai/core/util/path"
|
import { getDirectory, getFilename, getFilenameTruncated } from "@opencode-ai/shared/util/path"
|
||||||
import type { ContextItem } from "@/context/prompt"
|
import type { ContextItem } from "@/context/prompt"
|
||||||
|
|
||||||
type PromptContextItem = ContextItem & { key: string }
|
type PromptContextItem = ContextItem & { key: string }
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Component, For, Match, Show, Switch } from "solid-js"
|
import { Component, For, Match, Show, Switch } from "solid-js"
|
||||||
import { FileIcon } from "@opencode-ai/ui/file-icon"
|
import { FileIcon } from "@opencode-ai/ui/file-icon"
|
||||||
import { Icon } from "@opencode-ai/ui/icon"
|
import { Icon } from "@opencode-ai/ui/icon"
|
||||||
import { getDirectory, getFilename } from "@opencode-ai/core/util/path"
|
import { getDirectory, getFilename } from "@opencode-ai/shared/util/path"
|
||||||
|
|
||||||
export type AtOption =
|
export type AtOption =
|
||||||
| { type: "agent"; name: string; display: string }
|
| { type: "agent"; name: string; display: string }
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ beforeAll(async () => {
|
|||||||
showToast: () => 0,
|
showToast: () => 0,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
mock.module("@opencode-ai/core/util/encode", () => ({
|
mock.module("@opencode-ai/shared/util/encode", () => ({
|
||||||
base64Encode: (value: string) => value,
|
base64Encode: (value: string) => value,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { Message, Session } from "@opencode-ai/sdk/v2/client"
|
import type { Message, Session } from "@opencode-ai/sdk/v2/client"
|
||||||
import { showToast } from "@opencode-ai/ui/toast"
|
import { showToast } from "@opencode-ai/ui/toast"
|
||||||
import { base64Encode } from "@opencode-ai/core/util/encode"
|
import { base64Encode } from "@opencode-ai/shared/util/encode"
|
||||||
import { Binary } from "@opencode-ai/core/util/binary"
|
import { Binary } from "@opencode-ai/shared/util/binary"
|
||||||
import { useNavigate, useParams } from "@solidjs/router"
|
import { useNavigate, useParams } from "@solidjs/router"
|
||||||
import { batch, type Accessor } from "solid-js"
|
import { batch, type Accessor } from "solid-js"
|
||||||
import type { FileSelection } from "@/context/file"
|
import type { FileSelection } from "@/context/file"
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { createMemo, createEffect, on, onCleanup, For, Show } from "solid-js"
|
import { createMemo, createEffect, on, onCleanup, For, Show } from "solid-js"
|
||||||
import type { JSX } from "solid-js"
|
import type { JSX } from "solid-js"
|
||||||
import { useSync } from "@/context/sync"
|
import { useSync } from "@/context/sync"
|
||||||
import { checksum } from "@opencode-ai/core/util/encode"
|
import { checksum } from "@opencode-ai/shared/util/encode"
|
||||||
import { findLast } from "@opencode-ai/core/util/array"
|
import { findLast } from "@opencode-ai/shared/util/array"
|
||||||
import { same } from "@/utils/same"
|
import { same } from "@/utils/same"
|
||||||
import { Icon } from "@opencode-ai/ui/icon"
|
import { Icon } from "@opencode-ai/ui/icon"
|
||||||
import { Accordion } from "@opencode-ai/ui/accordion"
|
import { Accordion } from "@opencode-ai/ui/accordion"
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { Keybind } from "@opencode-ai/ui/keybind"
|
|||||||
import { Spinner } from "@opencode-ai/ui/spinner"
|
import { Spinner } from "@opencode-ai/ui/spinner"
|
||||||
import { showToast } from "@opencode-ai/ui/toast"
|
import { showToast } from "@opencode-ai/ui/toast"
|
||||||
import { Tooltip, TooltipKeybind } from "@opencode-ai/ui/tooltip"
|
import { Tooltip, TooltipKeybind } from "@opencode-ai/ui/tooltip"
|
||||||
import { getFilename } from "@opencode-ai/core/util/path"
|
import { getFilename } from "@opencode-ai/shared/util/path"
|
||||||
import { createEffect, createMemo, createSignal, For, onMount, Show } from "solid-js"
|
import { createEffect, createMemo, createSignal, For, onMount, Show } from "solid-js"
|
||||||
import { createStore } from "solid-js/store"
|
import { createStore } from "solid-js/store"
|
||||||
import { Portal } from "solid-js/web"
|
import { Portal } from "solid-js/web"
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { useSDK } from "@/context/sdk"
|
|||||||
import { useLanguage } from "@/context/language"
|
import { useLanguage } from "@/context/language"
|
||||||
import { Icon } from "@opencode-ai/ui/icon"
|
import { Icon } from "@opencode-ai/ui/icon"
|
||||||
import { Mark } from "@opencode-ai/ui/logo"
|
import { Mark } from "@opencode-ai/ui/logo"
|
||||||
import { getDirectory, getFilename } from "@opencode-ai/core/util/path"
|
import { getDirectory, getFilename } from "@opencode-ai/shared/util/path"
|
||||||
|
|
||||||
const MAIN_WORKTREE = "main"
|
const MAIN_WORKTREE = "main"
|
||||||
const CREATE_WORKTREE = "create"
|
const CREATE_WORKTREE = "create"
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { FileIcon } from "@opencode-ai/ui/file-icon"
|
|||||||
import { IconButton } from "@opencode-ai/ui/icon-button"
|
import { IconButton } from "@opencode-ai/ui/icon-button"
|
||||||
import { TooltipKeybind } from "@opencode-ai/ui/tooltip"
|
import { TooltipKeybind } from "@opencode-ai/ui/tooltip"
|
||||||
import { Tabs } from "@opencode-ai/ui/tabs"
|
import { Tabs } from "@opencode-ai/ui/tabs"
|
||||||
import { getFilename } from "@opencode-ai/core/util/path"
|
import { getFilename } from "@opencode-ai/shared/util/path"
|
||||||
import { useFile } from "@/context/file"
|
import { useFile } from "@/context/file"
|
||||||
import { useLanguage } from "@/context/language"
|
import { useLanguage } from "@/context/language"
|
||||||
import { useCommand } from "@/context/command"
|
import { useCommand } from "@/context/command"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { createStore, produce, reconcile } from "solid-js/store"
|
|||||||
import { createSimpleContext } from "@opencode-ai/ui/context"
|
import { createSimpleContext } from "@opencode-ai/ui/context"
|
||||||
import { showToast } from "@opencode-ai/ui/toast"
|
import { showToast } from "@opencode-ai/ui/toast"
|
||||||
import { useParams } from "@solidjs/router"
|
import { useParams } from "@solidjs/router"
|
||||||
import { getFilename } from "@opencode-ai/core/util/path"
|
import { getFilename } from "@opencode-ai/shared/util/path"
|
||||||
import { useSDK } from "./sdk"
|
import { useSDK } from "./sdk"
|
||||||
import { useSync } from "./sync"
|
import { useSync } from "./sync"
|
||||||
import { useLanguage } from "@/context/language"
|
import { useLanguage } from "@/context/language"
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import type {
|
|||||||
Todo,
|
Todo,
|
||||||
} from "@opencode-ai/sdk/v2/client"
|
} from "@opencode-ai/sdk/v2/client"
|
||||||
import { showToast } from "@opencode-ai/ui/toast"
|
import { showToast } from "@opencode-ai/ui/toast"
|
||||||
import { getFilename } from "@opencode-ai/core/util/path"
|
import { getFilename } from "@opencode-ai/shared/util/path"
|
||||||
import { batch, createContext, getOwner, onCleanup, onMount, type ParentProps, untrack, useContext } from "solid-js"
|
import { batch, createContext, getOwner, onCleanup, onMount, type ParentProps, untrack, useContext } from "solid-js"
|
||||||
import { createStore, produce, reconcile } from "solid-js/store"
|
import { createStore, produce, reconcile } from "solid-js/store"
|
||||||
import { useLanguage } from "@/context/language"
|
import { useLanguage } from "@/context/language"
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ import type {
|
|||||||
Todo,
|
Todo,
|
||||||
} from "@opencode-ai/sdk/v2/client"
|
} from "@opencode-ai/sdk/v2/client"
|
||||||
import { showToast } from "@opencode-ai/ui/toast"
|
import { showToast } from "@opencode-ai/ui/toast"
|
||||||
import { getFilename } from "@opencode-ai/core/util/path"
|
import { getFilename } from "@opencode-ai/shared/util/path"
|
||||||
import { retry } from "@opencode-ai/core/util/retry"
|
import { retry } from "@opencode-ai/shared/util/retry"
|
||||||
import { batch } from "solid-js"
|
import { batch } from "solid-js"
|
||||||
import { reconcile, type SetStoreFunction, type Store } from "solid-js/store"
|
import { reconcile, type SetStoreFunction, type Store } from "solid-js/store"
|
||||||
import type { State, VcsCache } from "./types"
|
import type { State, VcsCache } from "./types"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Binary } from "@opencode-ai/core/util/binary"
|
import { Binary } from "@opencode-ai/shared/util/binary"
|
||||||
import { produce, reconcile, type SetStoreFunction, type Store } from "solid-js/store"
|
import { produce, reconcile, type SetStoreFunction, type Store } from "solid-js/store"
|
||||||
import type {
|
import type {
|
||||||
Message,
|
Message,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { createSimpleContext } from "@opencode-ai/ui/context"
|
import { createSimpleContext } from "@opencode-ai/ui/context"
|
||||||
import { base64Encode } from "@opencode-ai/core/util/encode"
|
import { base64Encode } from "@opencode-ai/shared/util/encode"
|
||||||
import { useParams } from "@solidjs/router"
|
import { useParams } from "@solidjs/router"
|
||||||
import { batch, createEffect, createMemo } from "solid-js"
|
import { batch, createEffect, createMemo } from "solid-js"
|
||||||
import { createStore } from "solid-js/store"
|
import { createStore } from "solid-js/store"
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import { useGlobalSync } from "./global-sync"
|
|||||||
import { usePlatform } from "@/context/platform"
|
import { usePlatform } from "@/context/platform"
|
||||||
import { useLanguage } from "@/context/language"
|
import { useLanguage } from "@/context/language"
|
||||||
import { useSettings } from "@/context/settings"
|
import { useSettings } from "@/context/settings"
|
||||||
import { Binary } from "@opencode-ai/core/util/binary"
|
import { Binary } from "@opencode-ai/shared/util/binary"
|
||||||
import { base64Encode } from "@opencode-ai/core/util/encode"
|
import { base64Encode } from "@opencode-ai/shared/util/encode"
|
||||||
import { decode64 } from "@/utils/base64"
|
import { decode64 } from "@/utils/base64"
|
||||||
import { EventSessionError } from "@opencode-ai/sdk/v2"
|
import { EventSessionError } from "@opencode-ai/sdk/v2"
|
||||||
import { Persist, persisted } from "@/utils/persist"
|
import { Persist, persisted } from "@/utils/persist"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { describe, expect, test } from "bun:test"
|
import { describe, expect, test } from "bun:test"
|
||||||
import type { PermissionRequest, Session } from "@opencode-ai/sdk/v2/client"
|
import type { PermissionRequest, Session } from "@opencode-ai/sdk/v2/client"
|
||||||
import { base64Encode } from "@opencode-ai/core/util/encode"
|
import { base64Encode } from "@opencode-ai/shared/util/encode"
|
||||||
import { autoRespondsPermission, isDirectoryAutoAccepting } from "./permission-auto-respond"
|
import { autoRespondsPermission, isDirectoryAutoAccepting } from "./permission-auto-respond"
|
||||||
|
|
||||||
const session = (input: { id: string; parentID?: string }) =>
|
const session = (input: { id: string; parentID?: string }) =>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { base64Encode } from "@opencode-ai/core/util/encode"
|
import { base64Encode } from "@opencode-ai/shared/util/encode"
|
||||||
|
|
||||||
export function acceptKey(sessionID: string, directory?: string) {
|
export function acceptKey(sessionID: string, directory?: string) {
|
||||||
if (!directory) return sessionID
|
if (!directory) return sessionID
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { createSimpleContext } from "@opencode-ai/ui/context"
|
import { createSimpleContext } from "@opencode-ai/ui/context"
|
||||||
import { checksum } from "@opencode-ai/core/util/encode"
|
import { checksum } from "@opencode-ai/shared/util/encode"
|
||||||
import { useParams } from "@solidjs/router"
|
import { useParams } from "@solidjs/router"
|
||||||
import { batch, createMemo, createRoot, getOwner, onCleanup } from "solid-js"
|
import { batch, createMemo, createRoot, getOwner, onCleanup } from "solid-js"
|
||||||
import { createStore, type SetStoreFunction } from "solid-js/store"
|
import { createStore, type SetStoreFunction } from "solid-js/store"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { batch, createMemo } from "solid-js"
|
import { batch, createMemo } from "solid-js"
|
||||||
import { createStore, produce, reconcile } from "solid-js/store"
|
import { createStore, produce, reconcile } from "solid-js/store"
|
||||||
import { Binary } from "@opencode-ai/core/util/binary"
|
import { Binary } from "@opencode-ai/shared/util/binary"
|
||||||
import { retry } from "@opencode-ai/core/util/retry"
|
import { retry } from "@opencode-ai/shared/util/retry"
|
||||||
import { createSimpleContext } from "@opencode-ai/ui/context"
|
import { createSimpleContext } from "@opencode-ai/ui/context"
|
||||||
import {
|
import {
|
||||||
clearSessionPrefetch,
|
clearSessionPrefetch,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { DataProvider } from "@opencode-ai/ui/context"
|
import { DataProvider } from "@opencode-ai/ui/context"
|
||||||
import { showToast } from "@opencode-ai/ui/toast"
|
import { showToast } from "@opencode-ai/ui/toast"
|
||||||
import { base64Encode } from "@opencode-ai/core/util/encode"
|
import { base64Encode } from "@opencode-ai/shared/util/encode"
|
||||||
import { useLocation, useNavigate, useParams } from "@solidjs/router"
|
import { useLocation, useNavigate, useParams } from "@solidjs/router"
|
||||||
import { createEffect, createMemo, createResource, type ParentProps, Show } from "solid-js"
|
import { createEffect, createMemo, createResource, type ParentProps, Show } from "solid-js"
|
||||||
import { useLanguage } from "@/context/language"
|
import { useLanguage } from "@/context/language"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { Button } from "@opencode-ai/ui/button"
|
|||||||
import { Logo } from "@opencode-ai/ui/logo"
|
import { Logo } from "@opencode-ai/ui/logo"
|
||||||
import { useLayout } from "@/context/layout"
|
import { useLayout } from "@/context/layout"
|
||||||
import { useNavigate } from "@solidjs/router"
|
import { useNavigate } from "@solidjs/router"
|
||||||
import { base64Encode } from "@opencode-ai/core/util/encode"
|
import { base64Encode } from "@opencode-ai/shared/util/encode"
|
||||||
import { Icon } from "@opencode-ai/ui/icon"
|
import { Icon } from "@opencode-ai/ui/icon"
|
||||||
import { usePlatform } from "@/context/platform"
|
import { usePlatform } from "@/context/platform"
|
||||||
import { DateTime } from "luxon"
|
import { DateTime } from "luxon"
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import { useLocation, useNavigate, useParams } from "@solidjs/router"
|
|||||||
import { useLayout, LocalProject } from "@/context/layout"
|
import { useLayout, LocalProject } from "@/context/layout"
|
||||||
import { useGlobalSync } from "@/context/global-sync"
|
import { useGlobalSync } from "@/context/global-sync"
|
||||||
import { Persist, persisted } from "@/utils/persist"
|
import { Persist, persisted } from "@/utils/persist"
|
||||||
import { base64Encode } from "@opencode-ai/core/util/encode"
|
import { base64Encode } from "@opencode-ai/shared/util/encode"
|
||||||
import { decode64 } from "@/utils/base64"
|
import { decode64 } from "@/utils/base64"
|
||||||
import { ResizeHandle } from "@opencode-ai/ui/resize-handle"
|
import { ResizeHandle } from "@opencode-ai/ui/resize-handle"
|
||||||
import { Button } from "@opencode-ai/ui/button"
|
import { Button } from "@opencode-ai/ui/button"
|
||||||
@@ -25,7 +25,7 @@ import { IconButton } from "@opencode-ai/ui/icon-button"
|
|||||||
import { Tooltip } from "@opencode-ai/ui/tooltip"
|
import { Tooltip } from "@opencode-ai/ui/tooltip"
|
||||||
import { DropdownMenu } from "@opencode-ai/ui/dropdown-menu"
|
import { DropdownMenu } from "@opencode-ai/ui/dropdown-menu"
|
||||||
import { Dialog } from "@opencode-ai/ui/dialog"
|
import { Dialog } from "@opencode-ai/ui/dialog"
|
||||||
import { getFilename } from "@opencode-ai/core/util/path"
|
import { getFilename } from "@opencode-ai/shared/util/path"
|
||||||
import { Session, type Message } from "@opencode-ai/sdk/v2/client"
|
import { Session, type Message } from "@opencode-ai/sdk/v2/client"
|
||||||
import { usePlatform } from "@/context/platform"
|
import { usePlatform } from "@/context/platform"
|
||||||
import { useSettings } from "@/context/settings"
|
import { useSettings } from "@/context/settings"
|
||||||
@@ -48,8 +48,8 @@ import {
|
|||||||
} from "@/context/global-sync/session-prefetch"
|
} from "@/context/global-sync/session-prefetch"
|
||||||
import { useNotification } from "@/context/notification"
|
import { useNotification } from "@/context/notification"
|
||||||
import { usePermission } from "@/context/permission"
|
import { usePermission } from "@/context/permission"
|
||||||
import { Binary } from "@opencode-ai/core/util/binary"
|
import { Binary } from "@opencode-ai/shared/util/binary"
|
||||||
import { retry } from "@opencode-ai/core/util/retry"
|
import { retry } from "@opencode-ai/shared/util/retry"
|
||||||
import { playSoundById } from "@/utils/sound"
|
import { playSoundById } from "@/utils/sound"
|
||||||
import { createAim } from "@/utils/aim"
|
import { createAim } from "@/utils/aim"
|
||||||
import { setNavigate } from "@/utils/notification-click"
|
import { setNavigate } from "@/utils/notification-click"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { getFilename } from "@opencode-ai/core/util/path"
|
import { getFilename } from "@opencode-ai/shared/util/path"
|
||||||
import { type Session } from "@opencode-ai/sdk/v2/client"
|
import { type Session } from "@opencode-ai/sdk/v2/client"
|
||||||
|
|
||||||
type SessionStore = {
|
type SessionStore = {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { Icon } from "@opencode-ai/ui/icon"
|
|||||||
import { IconButton } from "@opencode-ai/ui/icon-button"
|
import { IconButton } from "@opencode-ai/ui/icon-button"
|
||||||
import { Spinner } from "@opencode-ai/ui/spinner"
|
import { Spinner } from "@opencode-ai/ui/spinner"
|
||||||
import { Tooltip } from "@opencode-ai/ui/tooltip"
|
import { Tooltip } from "@opencode-ai/ui/tooltip"
|
||||||
import { getFilename } from "@opencode-ai/core/util/path"
|
import { getFilename } from "@opencode-ai/shared/util/path"
|
||||||
import { A, useParams } from "@solidjs/router"
|
import { A, useParams } from "@solidjs/router"
|
||||||
import { type Accessor, createMemo, For, type JSX, Match, Show, Switch } from "solid-js"
|
import { type Accessor, createMemo, For, type JSX, Match, Show, Switch } from "solid-js"
|
||||||
import { useGlobalSync } from "@/context/global-sync"
|
import { useGlobalSync } from "@/context/global-sync"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { createMemo, For, Show, type Accessor, type JSX } from "solid-js"
|
import { createMemo, For, Show, type Accessor, type JSX } from "solid-js"
|
||||||
import { createStore } from "solid-js/store"
|
import { createStore } from "solid-js/store"
|
||||||
import { base64Encode } from "@opencode-ai/core/util/encode"
|
import { base64Encode } from "@opencode-ai/shared/util/encode"
|
||||||
import { Button } from "@opencode-ai/ui/button"
|
import { Button } from "@opencode-ai/ui/button"
|
||||||
import { ContextMenu } from "@opencode-ai/ui/context-menu"
|
import { ContextMenu } from "@opencode-ai/ui/context-menu"
|
||||||
import { HoverCard } from "@opencode-ai/ui/hover-card"
|
import { HoverCard } from "@opencode-ai/ui/hover-card"
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ import { createEffect, createMemo, For, Show, type Accessor, type JSX } from "so
|
|||||||
import { createStore } from "solid-js/store"
|
import { createStore } from "solid-js/store"
|
||||||
import { createSortable } from "@thisbeyond/solid-dnd"
|
import { createSortable } from "@thisbeyond/solid-dnd"
|
||||||
import { createMediaQuery } from "@solid-primitives/media"
|
import { createMediaQuery } from "@solid-primitives/media"
|
||||||
import { base64Encode } from "@opencode-ai/core/util/encode"
|
import { base64Encode } from "@opencode-ai/shared/util/encode"
|
||||||
import { getFilename } from "@opencode-ai/core/util/path"
|
import { getFilename } from "@opencode-ai/shared/util/path"
|
||||||
import { Button } from "@opencode-ai/ui/button"
|
import { Button } from "@opencode-ai/ui/button"
|
||||||
import { Collapsible } from "@opencode-ai/ui/collapsible"
|
import { Collapsible } from "@opencode-ai/ui/collapsible"
|
||||||
import { DropdownMenu } from "@opencode-ai/ui/dropdown-menu"
|
import { DropdownMenu } from "@opencode-ai/ui/dropdown-menu"
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ import { createAutoScroll } from "@opencode-ai/ui/hooks"
|
|||||||
import { previewSelectedLines } from "@opencode-ai/ui/pierre/selection-bridge"
|
import { previewSelectedLines } from "@opencode-ai/ui/pierre/selection-bridge"
|
||||||
import { Button } from "@opencode-ai/ui/button"
|
import { Button } from "@opencode-ai/ui/button"
|
||||||
import { showToast } from "@opencode-ai/ui/toast"
|
import { showToast } from "@opencode-ai/ui/toast"
|
||||||
import { checksum } from "@opencode-ai/core/util/encode"
|
import { checksum } from "@opencode-ai/shared/util/encode"
|
||||||
import { useSearchParams } from "@solidjs/router"
|
import { useSearchParams } from "@solidjs/router"
|
||||||
import { NewSessionView, SessionHeader } from "@/components/session"
|
import { NewSessionView, SessionHeader } from "@/components/session"
|
||||||
import { useComments } from "@/context/comments"
|
import { useComments } from "@/context/comments"
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import type { FileSearchHandle } from "@opencode-ai/ui/file"
|
|||||||
import { useFileComponent } from "@opencode-ai/ui/context/file"
|
import { useFileComponent } from "@opencode-ai/ui/context/file"
|
||||||
import { cloneSelectedLineRange, previewSelectedLines } from "@opencode-ai/ui/pierre/selection-bridge"
|
import { cloneSelectedLineRange, previewSelectedLines } from "@opencode-ai/ui/pierre/selection-bridge"
|
||||||
import { createLineCommentController } from "@opencode-ai/ui/line-comment-annotations"
|
import { createLineCommentController } from "@opencode-ai/ui/line-comment-annotations"
|
||||||
import { sampledChecksum } from "@opencode-ai/core/util/encode"
|
import { sampledChecksum } from "@opencode-ai/shared/util/encode"
|
||||||
import { DropdownMenu } from "@opencode-ai/ui/dropdown-menu"
|
import { DropdownMenu } from "@opencode-ai/ui/dropdown-menu"
|
||||||
import { IconButton } from "@opencode-ai/ui/icon-button"
|
import { IconButton } from "@opencode-ai/ui/icon-button"
|
||||||
import { Tabs } from "@opencode-ai/ui/tabs"
|
import { Tabs } from "@opencode-ai/ui/tabs"
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ import { ScrollView } from "@opencode-ai/ui/scroll-view"
|
|||||||
import { TextField } from "@opencode-ai/ui/text-field"
|
import { TextField } from "@opencode-ai/ui/text-field"
|
||||||
import type { AssistantMessage, Message as MessageType, Part, TextPart, UserMessage } from "@opencode-ai/sdk/v2"
|
import type { AssistantMessage, Message as MessageType, Part, TextPart, UserMessage } from "@opencode-ai/sdk/v2"
|
||||||
import { showToast } from "@opencode-ai/ui/toast"
|
import { showToast } from "@opencode-ai/ui/toast"
|
||||||
import { Binary } from "@opencode-ai/core/util/binary"
|
import { Binary } from "@opencode-ai/shared/util/binary"
|
||||||
import { getFilename } from "@opencode-ai/core/util/path"
|
import { getFilename } from "@opencode-ai/shared/util/path"
|
||||||
import { Popover as KobaltePopover } from "@kobalte/core/popover"
|
import { Popover as KobaltePopover } from "@kobalte/core/popover"
|
||||||
import { shouldMarkBoundaryGesture, normalizeWheelDelta } from "@/pages/session/message-gesture"
|
import { shouldMarkBoundaryGesture, normalizeWheelDelta } from "@/pages/session/message-gesture"
|
||||||
import { SessionContextUsage } from "@/components/session-context-usage"
|
import { SessionContextUsage } from "@/components/session-context-usage"
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import { useSettings } from "@/context/settings"
|
|||||||
import { useSync } from "@/context/sync"
|
import { useSync } from "@/context/sync"
|
||||||
import { useTerminal } from "@/context/terminal"
|
import { useTerminal } from "@/context/terminal"
|
||||||
import { showToast } from "@opencode-ai/ui/toast"
|
import { showToast } from "@opencode-ai/ui/toast"
|
||||||
import { findLast } from "@opencode-ai/core/util/array"
|
import { findLast } from "@opencode-ai/shared/util/array"
|
||||||
import { createSessionTabs } from "@/pages/session/helpers"
|
import { createSessionTabs } from "@/pages/session/helpers"
|
||||||
import { extractPromptFromParts } from "@/utils/prompt"
|
import { extractPromptFromParts } from "@/utils/prompt"
|
||||||
import { UserMessage } from "@opencode-ai/sdk/v2"
|
import { UserMessage } from "@opencode-ai/sdk/v2"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { base64Decode } from "@opencode-ai/core/util/encode"
|
import { base64Decode } from "@opencode-ai/shared/util/encode"
|
||||||
|
|
||||||
export function decode64(value: string | undefined) {
|
export function decode64(value: string | undefined) {
|
||||||
if (value === undefined) return
|
if (value === undefined) return
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Platform, usePlatform } from "@/context/platform"
|
import { Platform, usePlatform } from "@/context/platform"
|
||||||
import { makePersisted, type AsyncStorage, type SyncStorage } from "@solid-primitives/storage"
|
import { makePersisted, type AsyncStorage, type SyncStorage } from "@solid-primitives/storage"
|
||||||
import { checksum } from "@opencode-ai/core/util/encode"
|
import { checksum } from "@opencode-ai/shared/util/encode"
|
||||||
import { createResource, type Accessor } from "solid-js"
|
import { createResource, type Accessor } from "solid-js"
|
||||||
import type { SetStoreFunction, Store } from "solid-js/store"
|
import type { SetStoreFunction, Store } from "solid-js/store"
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@opencode-ai/console-app",
|
"name": "@opencode-ai/console-app",
|
||||||
"version": "1.14.25",
|
"version": "1.14.24",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://json.schemastore.org/package.json",
|
"$schema": "https://json.schemastore.org/package.json",
|
||||||
"name": "@opencode-ai/console-core",
|
"name": "@opencode-ai/console-core",
|
||||||
"version": "1.14.25",
|
"version": "1.14.24",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@opencode-ai/console-function",
|
"name": "@opencode-ai/console-function",
|
||||||
"version": "1.14.25",
|
"version": "1.14.24",
|
||||||
"$schema": "https://json.schemastore.org/package.json",
|
"$schema": "https://json.schemastore.org/package.json",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@opencode-ai/console-mail",
|
"name": "@opencode-ai/console-mail",
|
||||||
"version": "1.14.25",
|
"version": "1.14.24",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jsx-email/all": "2.2.3",
|
"@jsx-email/all": "2.2.3",
|
||||||
"@jsx-email/cli": "1.4.3",
|
"@jsx-email/cli": "1.4.3",
|
||||||
|
|||||||
@@ -1,65 +0,0 @@
|
|||||||
import path from "path"
|
|
||||||
import fs from "fs/promises"
|
|
||||||
import { xdgData, xdgCache, xdgConfig, xdgState } from "xdg-basedir"
|
|
||||||
import os from "os"
|
|
||||||
import { Context, Effect, Layer } from "effect"
|
|
||||||
import { Flock } from "./util/flock"
|
|
||||||
|
|
||||||
const app = "opencode"
|
|
||||||
const data = path.join(xdgData!, app)
|
|
||||||
const cache = path.join(xdgCache!, app)
|
|
||||||
const config = path.join(xdgConfig!, app)
|
|
||||||
const state = path.join(xdgState!, app)
|
|
||||||
|
|
||||||
const paths = {
|
|
||||||
get home() {
|
|
||||||
return process.env.OPENCODE_TEST_HOME ?? os.homedir()
|
|
||||||
},
|
|
||||||
data,
|
|
||||||
bin: path.join(cache, "bin"),
|
|
||||||
log: path.join(data, "log"),
|
|
||||||
cache,
|
|
||||||
config,
|
|
||||||
state,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Path = paths
|
|
||||||
|
|
||||||
Flock.setGlobal({ state })
|
|
||||||
|
|
||||||
await Promise.all([
|
|
||||||
fs.mkdir(Path.data, { recursive: true }),
|
|
||||||
fs.mkdir(Path.config, { recursive: true }),
|
|
||||||
fs.mkdir(Path.state, { recursive: true }),
|
|
||||||
fs.mkdir(Path.log, { recursive: true }),
|
|
||||||
fs.mkdir(Path.bin, { recursive: true }),
|
|
||||||
])
|
|
||||||
|
|
||||||
export class Service extends Context.Service<Service, Interface>()("@opencode/Global") {}
|
|
||||||
|
|
||||||
export interface Interface {
|
|
||||||
readonly home: string
|
|
||||||
readonly data: string
|
|
||||||
readonly cache: string
|
|
||||||
readonly config: string
|
|
||||||
readonly state: string
|
|
||||||
readonly bin: string
|
|
||||||
readonly log: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export const layer = Layer.effect(
|
|
||||||
Service,
|
|
||||||
Effect.gen(function* () {
|
|
||||||
return Service.of({
|
|
||||||
home: Path.home,
|
|
||||||
data: Path.data,
|
|
||||||
cache: Path.cache,
|
|
||||||
config: Path.config,
|
|
||||||
state: Path.state,
|
|
||||||
bin: Path.bin,
|
|
||||||
log: Path.log,
|
|
||||||
})
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
|
|
||||||
export * as Global from "./global"
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@opencode-ai/desktop-electron",
|
"name": "@opencode-ai/desktop-electron",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "1.14.25",
|
"version": "1.14.24",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"homepage": "https://opencode.ai",
|
"homepage": "https://opencode.ai",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@opencode-ai/desktop",
|
"name": "@opencode-ai/desktop",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "1.14.25",
|
"version": "1.14.24",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@opencode-ai/enterprise",
|
"name": "@opencode-ai/enterprise",
|
||||||
"version": "1.14.25",
|
"version": "1.14.24",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
"shell-prod": "sst shell --target Teams --stage production"
|
"shell-prod": "sst shell --target Teams --stage production"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@opencode-ai/core": "workspace:*",
|
"@opencode-ai/shared": "workspace:*",
|
||||||
"@opencode-ai/ui": "workspace:*",
|
"@opencode-ai/ui": "workspace:*",
|
||||||
"aws4fetch": "^1.0.20",
|
"aws4fetch": "^1.0.20",
|
||||||
"@pierre/diffs": "catalog:",
|
"@pierre/diffs": "catalog:",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Message, Model, Part, Session, SnapshotFileDiff } from "@opencode-ai/sdk/v2"
|
import { Message, Model, Part, Session, SnapshotFileDiff } from "@opencode-ai/sdk/v2"
|
||||||
import { fn } from "@opencode-ai/core/util/fn"
|
import { fn } from "@opencode-ai/shared/util/fn"
|
||||||
import { iife } from "@opencode-ai/core/util/iife"
|
import { iife } from "@opencode-ai/shared/util/iife"
|
||||||
import z from "zod"
|
import z from "zod"
|
||||||
import { Storage } from "./storage"
|
import { Storage } from "./storage"
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { AwsClient } from "aws4fetch"
|
import { AwsClient } from "aws4fetch"
|
||||||
import { lazy } from "@opencode-ai/core/util/lazy"
|
import { lazy } from "@opencode-ai/shared/util/lazy"
|
||||||
|
|
||||||
export namespace Storage {
|
export namespace Storage {
|
||||||
export interface Adapter {
|
export interface Adapter {
|
||||||
|
|||||||
@@ -10,9 +10,9 @@ import { Share } from "~/core/share"
|
|||||||
import { Logo, Mark } from "@opencode-ai/ui/logo"
|
import { Logo, Mark } from "@opencode-ai/ui/logo"
|
||||||
import { IconButton } from "@opencode-ai/ui/icon-button"
|
import { IconButton } from "@opencode-ai/ui/icon-button"
|
||||||
import { ProviderIcon } from "@opencode-ai/ui/provider-icon"
|
import { ProviderIcon } from "@opencode-ai/ui/provider-icon"
|
||||||
import { iife } from "@opencode-ai/core/util/iife"
|
import { iife } from "@opencode-ai/shared/util/iife"
|
||||||
import { Binary } from "@opencode-ai/core/util/binary"
|
import { Binary } from "@opencode-ai/shared/util/binary"
|
||||||
import { NamedError } from "@opencode-ai/core/util/error"
|
import { NamedError } from "@opencode-ai/shared/util/error"
|
||||||
import { DateTime } from "luxon"
|
import { DateTime } from "luxon"
|
||||||
import { createStore } from "solid-js/store"
|
import { createStore } from "solid-js/store"
|
||||||
import z from "zod"
|
import z from "zod"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { describe, expect, test } from "bun:test"
|
import { describe, expect, test } from "bun:test"
|
||||||
import { Share } from "../../src/core/share"
|
import { Share } from "../../src/core/share"
|
||||||
import { Storage } from "../../src/core/storage"
|
import { Storage } from "../../src/core/storage"
|
||||||
import { Identifier } from "@opencode-ai/core/util/identifier"
|
import { Identifier } from "@opencode-ai/shared/util/identifier"
|
||||||
|
|
||||||
describe.concurrent("core.share", () => {
|
describe.concurrent("core.share", () => {
|
||||||
test("should create a share", async () => {
|
test("should create a share", async () => {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
id = "opencode"
|
id = "opencode"
|
||||||
name = "OpenCode"
|
name = "OpenCode"
|
||||||
description = "The open source coding agent."
|
description = "The open source coding agent."
|
||||||
version = "1.14.25"
|
version = "1.14.24"
|
||||||
schema_version = 1
|
schema_version = 1
|
||||||
authors = ["Anomaly"]
|
authors = ["Anomaly"]
|
||||||
repository = "https://github.com/anomalyco/opencode"
|
repository = "https://github.com/anomalyco/opencode"
|
||||||
@@ -11,26 +11,26 @@ name = "OpenCode"
|
|||||||
icon = "./icons/opencode.svg"
|
icon = "./icons/opencode.svg"
|
||||||
|
|
||||||
[agent_servers.opencode.targets.darwin-aarch64]
|
[agent_servers.opencode.targets.darwin-aarch64]
|
||||||
archive = "https://github.com/anomalyco/opencode/releases/download/v1.14.25/opencode-darwin-arm64.zip"
|
archive = "https://github.com/anomalyco/opencode/releases/download/v1.14.24/opencode-darwin-arm64.zip"
|
||||||
cmd = "./opencode"
|
cmd = "./opencode"
|
||||||
args = ["acp"]
|
args = ["acp"]
|
||||||
|
|
||||||
[agent_servers.opencode.targets.darwin-x86_64]
|
[agent_servers.opencode.targets.darwin-x86_64]
|
||||||
archive = "https://github.com/anomalyco/opencode/releases/download/v1.14.25/opencode-darwin-x64.zip"
|
archive = "https://github.com/anomalyco/opencode/releases/download/v1.14.24/opencode-darwin-x64.zip"
|
||||||
cmd = "./opencode"
|
cmd = "./opencode"
|
||||||
args = ["acp"]
|
args = ["acp"]
|
||||||
|
|
||||||
[agent_servers.opencode.targets.linux-aarch64]
|
[agent_servers.opencode.targets.linux-aarch64]
|
||||||
archive = "https://github.com/anomalyco/opencode/releases/download/v1.14.25/opencode-linux-arm64.tar.gz"
|
archive = "https://github.com/anomalyco/opencode/releases/download/v1.14.24/opencode-linux-arm64.tar.gz"
|
||||||
cmd = "./opencode"
|
cmd = "./opencode"
|
||||||
args = ["acp"]
|
args = ["acp"]
|
||||||
|
|
||||||
[agent_servers.opencode.targets.linux-x86_64]
|
[agent_servers.opencode.targets.linux-x86_64]
|
||||||
archive = "https://github.com/anomalyco/opencode/releases/download/v1.14.25/opencode-linux-x64.tar.gz"
|
archive = "https://github.com/anomalyco/opencode/releases/download/v1.14.24/opencode-linux-x64.tar.gz"
|
||||||
cmd = "./opencode"
|
cmd = "./opencode"
|
||||||
args = ["acp"]
|
args = ["acp"]
|
||||||
|
|
||||||
[agent_servers.opencode.targets.windows-x86_64]
|
[agent_servers.opencode.targets.windows-x86_64]
|
||||||
archive = "https://github.com/anomalyco/opencode/releases/download/v1.14.25/opencode-windows-x64.zip"
|
archive = "https://github.com/anomalyco/opencode/releases/download/v1.14.24/opencode-windows-x64.zip"
|
||||||
cmd = "./opencode.exe"
|
cmd = "./opencode.exe"
|
||||||
args = ["acp"]
|
args = ["acp"]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@opencode-ai/function",
|
"name": "@opencode-ai/function",
|
||||||
"version": "1.14.25",
|
"version": "1.14.24",
|
||||||
"$schema": "https://json.schemastore.org/package.json",
|
"$schema": "https://json.schemastore.org/package.json",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://json.schemastore.org/package.json",
|
"$schema": "https://json.schemastore.org/package.json",
|
||||||
"version": "1.14.25",
|
"version": "1.14.24",
|
||||||
"name": "opencode",
|
"name": "opencode",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -45,7 +45,7 @@
|
|||||||
"@effect/language-service": "0.84.2",
|
"@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:*",
|
||||||
"@opencode-ai/core": "workspace:*",
|
"@opencode-ai/shared": "workspace:*",
|
||||||
"@parcel/watcher-darwin-arm64": "2.5.1",
|
"@parcel/watcher-darwin-arm64": "2.5.1",
|
||||||
"@parcel/watcher-darwin-x64": "2.5.1",
|
"@parcel/watcher-darwin-x64": "2.5.1",
|
||||||
"@parcel/watcher-linux-arm64-glibc": "2.5.1",
|
"@parcel/watcher-linux-arm64-glibc": "2.5.1",
|
||||||
@@ -61,6 +61,7 @@
|
|||||||
"@types/cross-spawn": "catalog:",
|
"@types/cross-spawn": "catalog:",
|
||||||
"@types/mime-types": "3.0.1",
|
"@types/mime-types": "3.0.1",
|
||||||
"@types/npm-package-arg": "6.1.4",
|
"@types/npm-package-arg": "6.1.4",
|
||||||
|
"@types/npmcli__arborist": "6.3.3",
|
||||||
"@types/semver": "^7.5.8",
|
"@types/semver": "^7.5.8",
|
||||||
"@types/turndown": "5.0.5",
|
"@types/turndown": "5.0.5",
|
||||||
"@types/which": "3.0.4",
|
"@types/which": "3.0.4",
|
||||||
@@ -109,6 +110,8 @@
|
|||||||
"@hono/zod-validator": "catalog:",
|
"@hono/zod-validator": "catalog:",
|
||||||
"@lydell/node-pty": "catalog:",
|
"@lydell/node-pty": "catalog:",
|
||||||
"@modelcontextprotocol/sdk": "1.27.1",
|
"@modelcontextprotocol/sdk": "1.27.1",
|
||||||
|
"@npmcli/arborist": "9.4.0",
|
||||||
|
"@npmcli/config": "10.8.1",
|
||||||
"@octokit/graphql": "9.0.2",
|
"@octokit/graphql": "9.0.2",
|
||||||
"@octokit/rest": "catalog:",
|
"@octokit/rest": "catalog:",
|
||||||
"@openauthjs/openauth": "catalog:",
|
"@openauthjs/openauth": "catalog:",
|
||||||
@@ -121,8 +124,8 @@
|
|||||||
"@opentelemetry/exporter-trace-otlp-http": "0.214.0",
|
"@opentelemetry/exporter-trace-otlp-http": "0.214.0",
|
||||||
"@opentelemetry/sdk-trace-base": "2.6.1",
|
"@opentelemetry/sdk-trace-base": "2.6.1",
|
||||||
"@opentelemetry/sdk-trace-node": "2.6.1",
|
"@opentelemetry/sdk-trace-node": "2.6.1",
|
||||||
"@opentui/core": "catalog:",
|
"@opentui/core": "0.1.103",
|
||||||
"@opentui/solid": "catalog:",
|
"@opentui/solid": "0.1.103",
|
||||||
"@parcel/watcher": "2.5.1",
|
"@parcel/watcher": "2.5.1",
|
||||||
"@pierre/diffs": "catalog:",
|
"@pierre/diffs": "catalog:",
|
||||||
"@solid-primitives/event-bus": "1.1.2",
|
"@solid-primitives/event-bus": "1.1.2",
|
||||||
@@ -157,7 +160,7 @@
|
|||||||
"open": "10.1.2",
|
"open": "10.1.2",
|
||||||
"opencode-gitlab-auth": "2.0.1",
|
"opencode-gitlab-auth": "2.0.1",
|
||||||
"opencode-poe-auth": "0.0.1",
|
"opencode-poe-auth": "0.0.1",
|
||||||
"opentui-spinner": "catalog:",
|
"opentui-spinner": "0.0.6",
|
||||||
"partial-json": "0.1.7",
|
"partial-json": "0.1.7",
|
||||||
"remeda": "catalog:",
|
"remeda": "catalog:",
|
||||||
"semver": "^7.6.3",
|
"semver": "^7.6.3",
|
||||||
|
|||||||
@@ -30,46 +30,6 @@ Plan for replacing instance Hono route implementations with Effect `HttpApi` whi
|
|||||||
- Regenerate the SDK after schema or OpenAPI-affecting changes and verify the diff is expected.
|
- Regenerate the SDK after schema or OpenAPI-affecting changes and verify the diff is expected.
|
||||||
- Do not delete a Hono route until the SDK/OpenAPI pipeline no longer depends on its Hono `describeRoute` entry.
|
- Do not delete a Hono route until the SDK/OpenAPI pipeline no longer depends on its Hono `describeRoute` entry.
|
||||||
|
|
||||||
## Route Slice Checklist
|
|
||||||
|
|
||||||
Use this checklist for each small HttpApi migration PR:
|
|
||||||
|
|
||||||
1. Read the legacy Hono route and copy behavior exactly, including default values, headers, operation IDs, response schemas, and status codes.
|
|
||||||
2. Put the new `HttpApiGroup`, route paths, DTO schemas, and handlers in `src/server/routes/instance/httpapi/*`.
|
|
||||||
3. Mount the new paths in `src/server/routes/instance/index.ts` only inside the `OPENCODE_EXPERIMENTAL_HTTPAPI` block.
|
|
||||||
4. Use `InstanceState.context` / `InstanceState.directory` inside HttpApi handlers instead of `Instance.directory`, `Instance.worktree`, or `Instance.project` ALS globals.
|
|
||||||
5. Reuse existing services directly. If a service returns plain objects, use `Schema.Struct`; use `Schema.Class` only when handlers return actual class instances.
|
|
||||||
6. Keep legacy Hono routes and `.zod` compatibility in place for SDK/OpenAPI generation.
|
|
||||||
7. Add tests that hit the Hono-mounted bridge via `InstanceRoutes`, not only the raw `HttpApi` web handler, when the route depends on auth or instance context.
|
|
||||||
8. Run `bun typecheck` from `packages/opencode`, relevant `bun run test:ci ...` tests from `packages/opencode`, and `./packages/sdk/js/script/build.ts` from the repo root.
|
|
||||||
|
|
||||||
## Hono Deletion Checklist
|
|
||||||
|
|
||||||
Use this checklist before deleting any Hono route implementation. A route being `bridged` is not enough.
|
|
||||||
|
|
||||||
1. `HttpApi` parity is complete for the route path, method, auth behavior, query parameters, request body, response status, response headers, and error status.
|
|
||||||
2. The route is mounted by default, not only behind `OPENCODE_EXPERIMENTAL_HTTPAPI`.
|
|
||||||
3. If a fallback flag exists, tests cover both the default `HttpApi` path and the fallback Hono path until the fallback is removed.
|
|
||||||
4. OpenAPI generation uses the Effect `HttpApi` route as the source for that path.
|
|
||||||
5. Generated SDK output is unchanged from the Hono-generated contract, or the SDK diff is intentionally reviewed and accepted.
|
|
||||||
6. The legacy Hono `describeRoute`, validator, and handler for that path are removed.
|
|
||||||
7. Any duplicate Zod-only DTOs are deleted or kept only as `.zod` compatibility on the canonical Effect Schema.
|
|
||||||
8. Bridge tests exist for auth, instance selection, success response, and route-specific side effects.
|
|
||||||
9. Mutation routes prove persisted side effects and cleanup behavior in tests. If the mutation disposes/reloads the active instance, disposal happens through an explicit post-response lifecycle hook rather than inline handler teardown.
|
|
||||||
10. Streaming, SSE, websocket, and UI bridge routes have a specific non-Hono replacement plan. Do not force them through `HttpApi` if raw Effect HTTP is a better fit.
|
|
||||||
|
|
||||||
Hono can be removed from the instance server only after all mounted Hono route groups meet this checklist and `server/routes/instance/index.ts` no longer depends on Hono routing for default behavior.
|
|
||||||
|
|
||||||
## Experimental Read Slice Guidance
|
|
||||||
|
|
||||||
For the experimental route group, port read-only JSON routes before mutations:
|
|
||||||
|
|
||||||
- Good first batch: `GET /console`, `GET /console/orgs`, `GET /tool/ids`, `GET /resource`.
|
|
||||||
- Consider `GET /worktree` only if the handler uses `InstanceState.context` instead of `Instance.project`.
|
|
||||||
- Defer `POST /console/switch`, worktree create/remove/reset, and `GET /session` to separate PRs because they mutate state or have broader pagination/session behavior.
|
|
||||||
- Preserve response headers such as pagination cursors if a route is ported.
|
|
||||||
- If SDK generation changes, explain whether it is a semantic contract change or a generator-equivalent type normalization.
|
|
||||||
|
|
||||||
## Schema Notes
|
## Schema Notes
|
||||||
|
|
||||||
- Use `Schema.Struct(...).annotate({ identifier })` for named OpenAPI refs when handlers return plain objects.
|
- Use `Schema.Struct(...).annotate({ identifier })` for named OpenAPI refs when handlers return plain objects.
|
||||||
@@ -110,7 +70,7 @@ Good near-term candidates:
|
|||||||
- top-level reads: `GET /path`, `GET /vcs`, `GET /vcs/diff`, `GET /command`, `GET /agent`, `GET /skill`, `GET /lsp`, `GET /formatter`
|
- top-level reads: `GET /path`, `GET /vcs`, `GET /vcs/diff`, `GET /command`, `GET /agent`, `GET /skill`, `GET /lsp`, `GET /formatter`
|
||||||
- simple mutations: `POST /instance/dispose`
|
- simple mutations: `POST /instance/dispose`
|
||||||
- experimental JSON reads: console, tool, worktree list, resource list
|
- experimental JSON reads: console, tool, worktree list, resource list
|
||||||
- deferred JSON mutations: workspace/worktree create/remove/reset, file search, MCP auth flows
|
- deferred JSON mutations: `PATCH /config`, project git init, workspace/worktree create/remove/reset, file search, MCP auth flows
|
||||||
|
|
||||||
Keep large or stateful groups for later:
|
Keep large or stateful groups for later:
|
||||||
|
|
||||||
@@ -170,198 +130,31 @@ Use raw Effect HTTP routes where `HttpApi` does not fit. The goal is deleting Ho
|
|||||||
|
|
||||||
## Current Route Status
|
## Current Route Status
|
||||||
|
|
||||||
| Area | Status | Notes |
|
| Area | Status | Notes |
|
||||||
| ------------------------- | ----------------- | -------------------------------------------------------------------------------------------------- |
|
| ------------------------ | ----------------- | -------------------------------------------------------------- |
|
||||||
| `question` | `bridged` | `GET /question`, reply, reject |
|
| `question` | `bridged` | `GET /question`, reply, reject |
|
||||||
| `permission` | `bridged` | list and reply |
|
| `permission` | `bridged` | list and reply |
|
||||||
| `provider` | `bridged` | list, auth, OAuth authorize/callback |
|
| `provider` | `bridged` | list, auth, OAuth authorize/callback |
|
||||||
| `config` | `bridged` | read, providers, update |
|
| `config` | `bridged` partial | reads only; mutation remains Hono |
|
||||||
| `project` | `bridged` | list, current, git init, update |
|
| `project` | `bridged` partial | reads only; git-init remains Hono |
|
||||||
| `file` | `bridged` partial | find text/file/symbol, list/content/status |
|
| `file` | `bridged` partial | list/content/status only |
|
||||||
| `mcp` | `bridged` | status, add, OAuth, connect/disconnect |
|
| `mcp` | `bridged` partial | status only |
|
||||||
| `workspace` | `bridged` partial | adaptor/list/status; create/remove/session-restore remain |
|
| `workspace` | `implemented` | `HttpApi` group exists, but bridge mounting needs verification |
|
||||||
| top-level instance routes | `bridged` | path, vcs, command, agent, skill, lsp, formatter, dispose |
|
| top-level instance reads | `next` | path, vcs, command, agent, skill, lsp, formatter |
|
||||||
| experimental JSON routes | `bridged` partial | console, tool, worktree list/mutations, resource list; global session list remains later |
|
| experimental JSON routes | `next/later` | console, tool, worktree, resource, global session list |
|
||||||
| `session` | `later/special` | large stateful surface plus streaming |
|
| `session` | `later/special` | large stateful surface plus streaming |
|
||||||
| `sync` | `later` | process/control side effects |
|
| `sync` | `later` | process/control side effects |
|
||||||
| `event` | `special` | SSE |
|
| `event` | `special` | SSE |
|
||||||
| `pty` | `special` | websocket |
|
| `pty` | `special` | websocket |
|
||||||
| `tui` | `special` | UI bridge |
|
| `tui` | `special` | UI bridge |
|
||||||
|
|
||||||
## Full Route Checklist
|
## Next PRs
|
||||||
|
|
||||||
This checklist tracks bridge parity only. Checked routes are available through the experimental `HttpApi` bridge; Hono deletion is tracked separately by the deletion checklist above.
|
1. Add bridge-level auth and instance-context tests for the current `HttpApi` bridge.
|
||||||
|
2. Produce a generated route inventory from Hono registrations and update `Current Route Status` with exact paths.
|
||||||
### Top-Level Instance Routes
|
3. Fix the `workspace` status: mount it if it should be reachable, or remove it from the composed `HttpApi` layer.
|
||||||
|
4. Port the top-level JSON reads.
|
||||||
- [x] `POST /instance/dispose` - dispose active instance after response.
|
5. Start the Effect OpenAPI/SDK generation path for already-bridged routes.
|
||||||
- [x] `GET /path` - current directory and worktree paths.
|
|
||||||
- [x] `GET /vcs` - current VCS status.
|
|
||||||
- [x] `GET /vcs/diff` - VCS diff summary.
|
|
||||||
- [x] `GET /command` - command catalog.
|
|
||||||
- [x] `GET /agent` - agent catalog.
|
|
||||||
- [x] `GET /skill` - skill catalog.
|
|
||||||
- [x] `GET /lsp` - LSP status.
|
|
||||||
- [x] `GET /formatter` - formatter status.
|
|
||||||
|
|
||||||
### Config Routes
|
|
||||||
|
|
||||||
- [x] `GET /config` - read config.
|
|
||||||
- [x] `PATCH /config` - update config and dispose active instance after response.
|
|
||||||
- [x] `GET /config/providers` - config provider summary.
|
|
||||||
|
|
||||||
### Project Routes
|
|
||||||
|
|
||||||
- [x] `GET /project` - list projects.
|
|
||||||
- [x] `GET /project/current` - current project.
|
|
||||||
- [x] `POST /project/git/init` - initialize git and reload active instance after response.
|
|
||||||
- [x] `PATCH /project/:projectID` - update project metadata.
|
|
||||||
|
|
||||||
### Provider Routes
|
|
||||||
|
|
||||||
- [x] `GET /provider` - list providers.
|
|
||||||
- [x] `GET /provider/auth` - list provider auth methods.
|
|
||||||
- [x] `POST /provider/:providerID/oauth/authorize` - start provider OAuth.
|
|
||||||
- [x] `POST /provider/:providerID/oauth/callback` - finish provider OAuth.
|
|
||||||
|
|
||||||
### Question Routes
|
|
||||||
|
|
||||||
- [x] `GET /question` - list questions.
|
|
||||||
- [x] `POST /question/:requestID/reply` - reply to question.
|
|
||||||
- [x] `POST /question/:requestID/reject` - reject question.
|
|
||||||
|
|
||||||
### Permission Routes
|
|
||||||
|
|
||||||
- [x] `GET /permission` - list permission requests.
|
|
||||||
- [x] `POST /permission/:requestID/reply` - reply to permission request.
|
|
||||||
|
|
||||||
### File Routes
|
|
||||||
|
|
||||||
- [x] `GET /find` - text search.
|
|
||||||
- [x] `GET /find/file` - file search.
|
|
||||||
- [x] `GET /find/symbol` - symbol search.
|
|
||||||
- [x] `GET /file` - list directory entries.
|
|
||||||
- [x] `GET /file/content` - read file content.
|
|
||||||
- [x] `GET /file/status` - file status.
|
|
||||||
|
|
||||||
### MCP Routes
|
|
||||||
|
|
||||||
- [x] `GET /mcp` - MCP status.
|
|
||||||
- [x] `POST /mcp` - add MCP server at runtime.
|
|
||||||
- [x] `POST /mcp/:name/auth` - start MCP OAuth.
|
|
||||||
- [x] `POST /mcp/:name/auth/callback` - finish MCP OAuth callback.
|
|
||||||
- [x] `POST /mcp/:name/auth/authenticate` - run MCP OAuth authenticate flow.
|
|
||||||
- [x] `DELETE /mcp/:name/auth` - remove MCP OAuth credentials.
|
|
||||||
- [x] `POST /mcp/:name/connect` - connect MCP server.
|
|
||||||
- [x] `POST /mcp/:name/disconnect` - disconnect MCP server.
|
|
||||||
|
|
||||||
### Experimental Routes
|
|
||||||
|
|
||||||
- [x] `GET /experimental/console` - active Console provider metadata.
|
|
||||||
- [x] `GET /experimental/console/orgs` - switchable Console orgs.
|
|
||||||
- [x] `POST /experimental/console/switch` - switch active Console org.
|
|
||||||
- [x] `GET /experimental/tool/ids` - tool IDs.
|
|
||||||
- [x] `GET /experimental/tool` - tools for provider/model.
|
|
||||||
- [x] `GET /experimental/worktree` - list worktrees.
|
|
||||||
- [x] `POST /experimental/worktree` - create worktree.
|
|
||||||
- [x] `DELETE /experimental/worktree` - remove worktree.
|
|
||||||
- [x] `POST /experimental/worktree/reset` - reset worktree.
|
|
||||||
- [ ] `GET /experimental/session` - global session list.
|
|
||||||
- [x] `GET /experimental/resource` - MCP resources.
|
|
||||||
|
|
||||||
### Workspace Routes
|
|
||||||
|
|
||||||
- [x] `GET /experimental/workspace/adaptor` - list workspace adaptors.
|
|
||||||
- [ ] `POST /experimental/workspace` - create workspace.
|
|
||||||
- [x] `GET /experimental/workspace` - list workspaces.
|
|
||||||
- [x] `GET /experimental/workspace/status` - workspace status.
|
|
||||||
- [ ] `DELETE /experimental/workspace/:id` - remove workspace.
|
|
||||||
- [ ] `POST /experimental/workspace/:id/session-restore` - restore session into workspace.
|
|
||||||
|
|
||||||
### Sync Routes
|
|
||||||
|
|
||||||
- [ ] `POST /sync/start` - start workspace sync.
|
|
||||||
- [ ] `POST /sync/replay` - replay sync events.
|
|
||||||
- [ ] `POST /sync/history` - list sync event history.
|
|
||||||
|
|
||||||
### Session Routes
|
|
||||||
|
|
||||||
- [ ] `GET /session` - list sessions.
|
|
||||||
- [ ] `GET /session/status` - session status map.
|
|
||||||
- [ ] `GET /session/:sessionID` - get session.
|
|
||||||
- [ ] `GET /session/:sessionID/children` - get child sessions.
|
|
||||||
- [ ] `GET /session/:sessionID/todo` - get session todos.
|
|
||||||
- [ ] `POST /session` - create session.
|
|
||||||
- [ ] `DELETE /session/:sessionID` - delete session.
|
|
||||||
- [ ] `PATCH /session/:sessionID` - update session metadata.
|
|
||||||
- [ ] `POST /session/:sessionID/init` - run project init command.
|
|
||||||
- [ ] `POST /session/:sessionID/fork` - fork session.
|
|
||||||
- [ ] `POST /session/:sessionID/abort` - abort session.
|
|
||||||
- [ ] `POST /session/:sessionID/share` - share session.
|
|
||||||
- [ ] `GET /session/:sessionID/diff` - session diff.
|
|
||||||
- [ ] `DELETE /session/:sessionID/share` - unshare session.
|
|
||||||
- [ ] `POST /session/:sessionID/summarize` - summarize session.
|
|
||||||
- [ ] `GET /session/:sessionID/message` - list session messages.
|
|
||||||
- [ ] `GET /session/:sessionID/message/:messageID` - get message.
|
|
||||||
- [ ] `DELETE /session/:sessionID/message/:messageID` - delete message.
|
|
||||||
- [ ] `DELETE /session/:sessionID/message/:messageID/part/:partID` - delete part.
|
|
||||||
- [ ] `PATCH /session/:sessionID/message/:messageID/part/:partID` - update part.
|
|
||||||
- [ ] `POST /session/:sessionID/message` - prompt with streaming response.
|
|
||||||
- [ ] `POST /session/:sessionID/prompt_async` - async prompt.
|
|
||||||
- [ ] `POST /session/:sessionID/command` - run command.
|
|
||||||
- [ ] `POST /session/:sessionID/shell` - run shell command.
|
|
||||||
- [ ] `POST /session/:sessionID/revert` - revert message.
|
|
||||||
- [ ] `POST /session/:sessionID/unrevert` - restore reverted messages.
|
|
||||||
- [ ] `POST /session/:sessionID/permissions/:permissionID` - deprecated permission response route.
|
|
||||||
|
|
||||||
### Event Routes
|
|
||||||
|
|
||||||
- [ ] `GET /event` - SSE event stream; replace with raw Effect HTTP, not `HttpApi`.
|
|
||||||
|
|
||||||
### PTY Routes
|
|
||||||
|
|
||||||
- [ ] `GET /pty` - list PTY sessions.
|
|
||||||
- [ ] `POST /pty` - create PTY session.
|
|
||||||
- [ ] `GET /pty/:ptyID` - get PTY session.
|
|
||||||
- [ ] `PUT /pty/:ptyID` - update PTY session.
|
|
||||||
- [ ] `DELETE /pty/:ptyID` - remove PTY session.
|
|
||||||
- [ ] `GET /pty/:ptyID/connect` - PTY websocket; replace with raw Effect HTTP/websocket support.
|
|
||||||
|
|
||||||
### TUI Routes
|
|
||||||
|
|
||||||
- [ ] `POST /tui/append-prompt` - append prompt.
|
|
||||||
- [ ] `POST /tui/open-help` - open help.
|
|
||||||
- [ ] `POST /tui/open-sessions` - open sessions.
|
|
||||||
- [ ] `POST /tui/open-themes` - open themes.
|
|
||||||
- [ ] `POST /tui/open-models` - open models.
|
|
||||||
- [ ] `POST /tui/submit-prompt` - submit prompt.
|
|
||||||
- [ ] `POST /tui/clear-prompt` - clear prompt.
|
|
||||||
- [ ] `POST /tui/execute-command` - execute command.
|
|
||||||
- [ ] `POST /tui/show-toast` - show toast.
|
|
||||||
- [ ] `POST /tui/publish` - publish TUI event.
|
|
||||||
- [ ] `POST /tui/select-session` - select session.
|
|
||||||
- [ ] `GET /tui/control/next` - get next TUI request.
|
|
||||||
- [ ] `POST /tui/control/response` - submit TUI control response.
|
|
||||||
|
|
||||||
## Remaining PR Plan
|
|
||||||
|
|
||||||
Prefer smaller PRs from here so route behavior and SDK/OpenAPI fallout stays reviewable.
|
|
||||||
|
|
||||||
1. [x] Bridge `PATCH /project/:projectID`.
|
|
||||||
2. [x] Bridge MCP add/connect/disconnect routes.
|
|
||||||
3. [x] Bridge MCP OAuth routes: start, callback, authenticate, remove.
|
|
||||||
4. [x] Bridge experimental console switch and tool list routes.
|
|
||||||
5. [ ] Bridge experimental global session list.
|
|
||||||
6. [ ] Bridge workspace create/remove/session-restore routes.
|
|
||||||
7. [ ] Bridge sync start/replay/history routes.
|
|
||||||
8. [ ] Bridge session read routes: list, status, get, children, todo, diff, messages.
|
|
||||||
9. [ ] Bridge session lifecycle mutation routes: create, delete, update, fork, abort.
|
|
||||||
10. [ ] Bridge session share/summary/message/part mutation routes.
|
|
||||||
11. [ ] Replace event SSE with non-Hono Effect HTTP.
|
|
||||||
12. [ ] Replace pty websocket/control routes with non-Hono Effect HTTP.
|
|
||||||
13. [ ] Replace tui bridge routes or explicitly isolate them behind a non-Hono compatibility layer.
|
|
||||||
14. [ ] Switch OpenAPI/SDK generation to Effect routes and compare SDK output.
|
|
||||||
15. [ ] Flip ported JSON routes default-on, keep a short fallback, then delete replaced Hono route files.
|
|
||||||
|
|
||||||
## Checklist
|
## Checklist
|
||||||
|
|
||||||
@@ -371,10 +164,10 @@ Prefer smaller PRs from here so route behavior and SDK/OpenAPI fallout stays rev
|
|||||||
- [x] Provide auth, instance lookup, and observability in the Effect route layer.
|
- [x] Provide auth, instance lookup, and observability in the Effect route layer.
|
||||||
- [x] Attach auth middleware in route modules.
|
- [x] Attach auth middleware in route modules.
|
||||||
- [x] Support `auth_token` as a query security scheme.
|
- [x] Support `auth_token` as a query security scheme.
|
||||||
- [x] Add bridge-level auth and instance tests.
|
- [ ] Add bridge-level auth and instance tests.
|
||||||
- [x] Complete exact Hono route inventory.
|
- [ ] Complete exact Hono route inventory.
|
||||||
- [x] Resolve implemented-but-unmounted route groups.
|
- [ ] Resolve implemented-but-unmounted route groups.
|
||||||
- [x] Port remaining top-level JSON reads.
|
- [ ] Port remaining JSON routes.
|
||||||
- [ ] Generate SDK/OpenAPI from Effect routes.
|
- [ ] Generate SDK/OpenAPI from Effect routes.
|
||||||
- [ ] Flip ported JSON routes to default-on with fallback.
|
- [ ] Flip ported JSON routes to default-on with fallback.
|
||||||
- [ ] Delete replaced Hono route implementations.
|
- [ ] Delete replaced Hono route implementations.
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ import {
|
|||||||
import { Log } from "../util"
|
import { Log } from "../util"
|
||||||
import { pathToFileURL } from "url"
|
import { pathToFileURL } from "url"
|
||||||
import { Filesystem } from "../util"
|
import { Filesystem } from "../util"
|
||||||
import { Hash } from "@opencode-ai/core/util/hash"
|
import { Hash } from "@opencode-ai/shared/util/hash"
|
||||||
import { ACPSessionManager } from "./session"
|
import { ACPSessionManager } from "./session"
|
||||||
import type { ACPConfig } from "./types"
|
import type { ACPConfig } from "./types"
|
||||||
import { Provider } from "../provider"
|
import { Provider } from "../provider"
|
||||||
@@ -50,7 +50,7 @@ import { Result, Schema } from "effect"
|
|||||||
import { LoadAPIKeyError } from "ai"
|
import { LoadAPIKeyError } from "ai"
|
||||||
import type { AssistantMessage, Event, OpencodeClient, SessionMessageResponse, ToolPart } from "@opencode-ai/sdk/v2"
|
import type { AssistantMessage, Event, OpencodeClient, SessionMessageResponse, ToolPart } from "@opencode-ai/sdk/v2"
|
||||||
import { applyPatch } from "diff"
|
import { applyPatch } from "diff"
|
||||||
import { InstallationVersion } from "@opencode-ai/core/installation/version"
|
import { InstallationVersion } from "@/installation/version"
|
||||||
|
|
||||||
type ModeOption = { id: string; name: string; description?: string }
|
type ModeOption = { id: string; name: string; description?: string }
|
||||||
type ModelOption = { modelId: string; name: string }
|
type ModelOption = { modelId: string; name: string }
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import z from "zod"
|
|||||||
import { Provider } from "../provider"
|
import { Provider } from "../provider"
|
||||||
import { ModelID, ProviderID } from "../provider/schema"
|
import { ModelID, ProviderID } from "../provider/schema"
|
||||||
import { generateObject, streamObject, type ModelMessage } from "ai"
|
import { generateObject, streamObject, type ModelMessage } from "ai"
|
||||||
|
import { Instance } from "../project/instance"
|
||||||
import { Truncate } from "../tool"
|
import { Truncate } from "../tool"
|
||||||
import { Auth } from "../auth"
|
import { Auth } from "../auth"
|
||||||
import { ProviderTransform } from "../provider"
|
import { ProviderTransform } from "../provider"
|
||||||
@@ -14,41 +15,41 @@ import PROMPT_SUMMARY from "./prompt/summary.txt"
|
|||||||
import PROMPT_TITLE from "./prompt/title.txt"
|
import PROMPT_TITLE from "./prompt/title.txt"
|
||||||
import { Permission } from "@/permission"
|
import { Permission } from "@/permission"
|
||||||
import { mergeDeep, pipe, sortBy, values } from "remeda"
|
import { mergeDeep, pipe, sortBy, values } from "remeda"
|
||||||
import { Global } from "@opencode-ai/core/global"
|
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, Context, Layer, Schema } from "effect"
|
import { Effect, Context, Layer } from "effect"
|
||||||
import { InstanceState } from "@/effect"
|
import { InstanceState } from "@/effect"
|
||||||
import * as Option from "effect/Option"
|
import * as Option from "effect/Option"
|
||||||
import * as OtelTracer from "@effect/opentelemetry/Tracer"
|
import * as OtelTracer from "@effect/opentelemetry/Tracer"
|
||||||
import { zod } from "@/util/effect-zod"
|
|
||||||
import { withStatics, type DeepMutable } from "@/util/schema"
|
|
||||||
|
|
||||||
export const Info = Schema.Struct({
|
export const Info = z
|
||||||
name: Schema.String,
|
.object({
|
||||||
description: Schema.optional(Schema.String),
|
name: z.string(),
|
||||||
mode: Schema.Literals(["subagent", "primary", "all"]),
|
description: z.string().optional(),
|
||||||
native: Schema.optional(Schema.Boolean),
|
mode: z.enum(["subagent", "primary", "all"]),
|
||||||
hidden: Schema.optional(Schema.Boolean),
|
native: z.boolean().optional(),
|
||||||
topP: Schema.optional(Schema.Number),
|
hidden: z.boolean().optional(),
|
||||||
temperature: Schema.optional(Schema.Number),
|
topP: z.number().optional(),
|
||||||
color: Schema.optional(Schema.String),
|
temperature: z.number().optional(),
|
||||||
permission: Permission.Ruleset,
|
color: z.string().optional(),
|
||||||
model: Schema.optional(
|
permission: Permission.Ruleset.zod,
|
||||||
Schema.Struct({
|
model: z
|
||||||
modelID: ModelID,
|
.object({
|
||||||
providerID: ProviderID,
|
modelID: ModelID.zod,
|
||||||
}),
|
providerID: ProviderID.zod,
|
||||||
),
|
})
|
||||||
variant: Schema.optional(Schema.String),
|
.optional(),
|
||||||
prompt: Schema.optional(Schema.String),
|
variant: z.string().optional(),
|
||||||
options: Schema.Record(Schema.String, Schema.Unknown),
|
prompt: z.string().optional(),
|
||||||
steps: Schema.optional(Schema.Number),
|
options: z.record(z.string(), z.any()),
|
||||||
})
|
steps: z.number().int().positive().optional(),
|
||||||
.annotate({ identifier: "Agent" })
|
})
|
||||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
.meta({
|
||||||
export type Info = DeepMutable<Schema.Schema.Type<typeof Info>>
|
ref: "Agent",
|
||||||
|
})
|
||||||
|
export type Info = z.infer<typeof Info>
|
||||||
|
|
||||||
export interface Interface {
|
export interface Interface {
|
||||||
readonly get: (agent: string) => Effect.Effect<Info>
|
readonly get: (agent: string) => Effect.Effect<Info>
|
||||||
@@ -78,7 +79,7 @@ export const layer = Layer.effect(
|
|||||||
const provider = yield* Provider.Service
|
const provider = yield* Provider.Service
|
||||||
|
|
||||||
const state = yield* InstanceState.make<State>(
|
const state = yield* InstanceState.make<State>(
|
||||||
Effect.fn("Agent.state")(function* (ctx) {
|
Effect.fn("Agent.state")(function* (_ctx) {
|
||||||
const cfg = yield* config.get()
|
const cfg = yield* config.get()
|
||||||
const skillDirs = yield* skill.dirs()
|
const skillDirs = yield* skill.dirs()
|
||||||
const whitelistedDirs = [Truncate.GLOB, ...skillDirs.map((dir) => path.join(dir, "*"))]
|
const whitelistedDirs = [Truncate.GLOB, ...skillDirs.map((dir) => path.join(dir, "*"))]
|
||||||
@@ -135,7 +136,7 @@ export const layer = Layer.effect(
|
|||||||
edit: {
|
edit: {
|
||||||
"*": "deny",
|
"*": "deny",
|
||||||
[path.join(".opencode", "plans", "*.md")]: "allow",
|
[path.join(".opencode", "plans", "*.md")]: "allow",
|
||||||
[path.relative(ctx.worktree, path.join(Global.Path.data, path.join("plans", "*.md")))]: "allow",
|
[path.relative(Instance.worktree, path.join(Global.Path.data, path.join("plans", "*.md")))]: "allow",
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
user,
|
user,
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import path from "path"
|
import path from "path"
|
||||||
import { Effect, Layer, Record, Result, Schema, Context } from "effect"
|
import { Effect, Layer, Record, Result, Schema, Context } from "effect"
|
||||||
import { zod } from "@/util/effect-zod"
|
import { zod } from "@/util/effect-zod"
|
||||||
import { Global } from "@opencode-ai/core/global"
|
import { Global } from "../global"
|
||||||
import { AppFileSystem } from "@opencode-ai/core/filesystem"
|
import { AppFileSystem } from "@opencode-ai/shared/filesystem"
|
||||||
|
|
||||||
export const OAUTH_DUMMY_KEY = "opencode-oauth-dummy-key"
|
export const OAUTH_DUMMY_KEY = "opencode-oauth-dummy-key"
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { cmd } from "./cmd"
|
|||||||
import * as prompts from "@clack/prompts"
|
import * as prompts from "@clack/prompts"
|
||||||
import { AppRuntime } from "@/effect/app-runtime"
|
import { AppRuntime } from "@/effect/app-runtime"
|
||||||
import { UI } from "../ui"
|
import { UI } from "../ui"
|
||||||
import { Global } from "@opencode-ai/core/global"
|
import { Global } from "../../global"
|
||||||
import { Agent } from "../../agent/agent"
|
import { Agent } from "../../agent/agent"
|
||||||
import { Provider } from "../../provider"
|
import { Provider } from "../../provider"
|
||||||
import path from "path"
|
import path from "path"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Global } from "@opencode-ai/core/global"
|
import { Global } from "../../../global"
|
||||||
import { bootstrap } from "../../bootstrap"
|
import { bootstrap } from "../../bootstrap"
|
||||||
import { cmd } from "../cmd"
|
import { cmd } from "../cmd"
|
||||||
import { ConfigCommand } from "./config"
|
import { ConfigCommand } from "./config"
|
||||||
@@ -9,7 +9,6 @@ import { ScrapCommand } from "./scrap"
|
|||||||
import { SkillCommand } from "./skill"
|
import { SkillCommand } from "./skill"
|
||||||
import { SnapshotCommand } from "./snapshot"
|
import { SnapshotCommand } from "./snapshot"
|
||||||
import { AgentCommand } from "./agent"
|
import { AgentCommand } from "./agent"
|
||||||
import { StartupCommand } from "./startup"
|
|
||||||
|
|
||||||
export const DebugCommand = cmd({
|
export const DebugCommand = cmd({
|
||||||
command: "debug",
|
command: "debug",
|
||||||
@@ -23,7 +22,6 @@ export const DebugCommand = cmd({
|
|||||||
.command(ScrapCommand)
|
.command(ScrapCommand)
|
||||||
.command(SkillCommand)
|
.command(SkillCommand)
|
||||||
.command(SnapshotCommand)
|
.command(SnapshotCommand)
|
||||||
.command(StartupCommand)
|
|
||||||
.command(AgentCommand)
|
.command(AgentCommand)
|
||||||
.command(PathsCommand)
|
.command(PathsCommand)
|
||||||
.command({
|
.command({
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
import { EOL } from "os"
|
|
||||||
import { cmd } from "../cmd"
|
|
||||||
|
|
||||||
export const StartupCommand = cmd({
|
|
||||||
command: "startup",
|
|
||||||
describe: "print startup timing",
|
|
||||||
builder: (yargs) => yargs,
|
|
||||||
handler() {
|
|
||||||
process.stdout.write(performance.now().toString() + EOL)
|
|
||||||
},
|
|
||||||
})
|
|
||||||
@@ -11,9 +11,9 @@ import { Config } from "../../config"
|
|||||||
import { ConfigMCP } from "../../config/mcp"
|
import { ConfigMCP } from "../../config/mcp"
|
||||||
import { Instance } from "../../project/instance"
|
import { Instance } from "../../project/instance"
|
||||||
import { Installation } from "../../installation"
|
import { Installation } from "../../installation"
|
||||||
import { InstallationVersion } from "@opencode-ai/core/installation/version"
|
import { InstallationVersion } from "../../installation/version"
|
||||||
import path from "path"
|
import path from "path"
|
||||||
import { Global } from "@opencode-ai/core/global"
|
import { Global } from "../../global"
|
||||||
import { modify, applyEdits } from "jsonc-parser"
|
import { modify, applyEdits } from "jsonc-parser"
|
||||||
import { Filesystem } from "../../util"
|
import { Filesystem } from "../../util"
|
||||||
import { Bus } from "../../bus"
|
import { Bus } from "../../bus"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { intro, log, outro, spinner } from "@clack/prompts"
|
|||||||
import type { Argv } from "yargs"
|
import type { Argv } from "yargs"
|
||||||
|
|
||||||
import { ConfigPaths } from "../../config"
|
import { ConfigPaths } from "../../config"
|
||||||
import { Global } from "@opencode-ai/core/global"
|
import { Global } from "../../global"
|
||||||
import { installPlugin, patchPluginConfig, readPluginManifest } from "../../plugin/install"
|
import { installPlugin, patchPluginConfig, readPluginManifest } from "../../plugin/install"
|
||||||
import { resolvePluginTarget } from "../../plugin/shared"
|
import { resolvePluginTarget } from "../../plugin/shared"
|
||||||
import { Instance } from "../../project/instance"
|
import { Instance } from "../../project/instance"
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { map, pipe, sortBy, values } from "remeda"
|
|||||||
import path from "path"
|
import path from "path"
|
||||||
import os from "os"
|
import os from "os"
|
||||||
import { Config } from "../../config"
|
import { Config } from "../../config"
|
||||||
import { Global } from "@opencode-ai/core/global"
|
import { Global } from "../../global"
|
||||||
import { Plugin } from "../../plugin"
|
import { Plugin } from "../../plugin"
|
||||||
import { Instance } from "../../project/instance"
|
import { Instance } from "../../project/instance"
|
||||||
import type { Hooks } from "@opencode-ai/plugin"
|
import type { Hooks } from "@opencode-ai/plugin"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import path from "path"
|
|||||||
import { pathToFileURL } from "url"
|
import { pathToFileURL } from "url"
|
||||||
import { UI } from "../ui"
|
import { UI } from "../ui"
|
||||||
import { cmd } from "./cmd"
|
import { cmd } from "./cmd"
|
||||||
import { Flag } from "@opencode-ai/core/flag/flag"
|
import { Flag } from "../../flag/flag"
|
||||||
import { bootstrap } from "../bootstrap"
|
import { bootstrap } from "../bootstrap"
|
||||||
import { EOL } from "os"
|
import { EOL } from "os"
|
||||||
import { Filesystem } from "../../util"
|
import { Filesystem } from "../../util"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Server } from "../../server/server"
|
import { Server } from "../../server/server"
|
||||||
import { cmd } from "./cmd"
|
import { cmd } from "./cmd"
|
||||||
import { withNetworkOptions, resolveNetworkOptions } from "../network"
|
import { withNetworkOptions, resolveNetworkOptions } from "../network"
|
||||||
import { Flag } from "@opencode-ai/core/flag/flag"
|
import { Flag } from "../../flag/flag"
|
||||||
|
|
||||||
export const ServeCommand = cmd({
|
export const ServeCommand = cmd({
|
||||||
command: "serve",
|
command: "serve",
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { SessionID } from "../../session/schema"
|
|||||||
import { bootstrap } from "../bootstrap"
|
import { bootstrap } from "../bootstrap"
|
||||||
import { UI } from "../ui"
|
import { UI } from "../ui"
|
||||||
import { Locale } from "../../util"
|
import { Locale } from "../../util"
|
||||||
import { Flag } from "@opencode-ai/core/flag/flag"
|
import { Flag } from "../../flag/flag"
|
||||||
import { Filesystem } from "../../util"
|
import { Filesystem } from "../../util"
|
||||||
import { Process } from "../../util"
|
import { Process } from "../../util"
|
||||||
import { EOL } from "os"
|
import { EOL } from "os"
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import {
|
|||||||
on,
|
on,
|
||||||
} from "solid-js"
|
} from "solid-js"
|
||||||
import { win32DisableProcessedInput, win32InstallCtrlCGuard } from "./win32"
|
import { win32DisableProcessedInput, win32InstallCtrlCGuard } from "./win32"
|
||||||
import { Flag } from "@opencode-ai/core/flag/flag"
|
import { Flag } from "@/flag/flag"
|
||||||
import semver from "semver"
|
import semver from "semver"
|
||||||
import { DialogProvider, useDialog } from "@tui/ui/dialog"
|
import { DialogProvider, useDialog } from "@tui/ui/dialog"
|
||||||
import { DialogProvider as DialogProviderList } from "@tui/component/dialog-provider"
|
import { DialogProvider as DialogProviderList } from "@tui/component/dialog-provider"
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { useProject } from "@tui/context/project"
|
|||||||
import { useKeybind } from "../context/keybind"
|
import { useKeybind } from "../context/keybind"
|
||||||
import { useTheme } from "../context/theme"
|
import { useTheme } from "../context/theme"
|
||||||
import { useSDK } from "../context/sdk"
|
import { useSDK } from "../context/sdk"
|
||||||
import { Flag } from "@opencode-ai/core/flag/flag"
|
import { Flag } from "@/flag/flag"
|
||||||
import { DialogSessionRename } from "./dialog-session-rename"
|
import { DialogSessionRename } from "./dialog-session-rename"
|
||||||
import { Keybind } from "@/util"
|
import { Keybind } from "@/util"
|
||||||
import { createDebouncedSignal } from "../util/signal"
|
import { createDebouncedSignal } from "../util/signal"
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { useProject } from "@tui/context/project"
|
|||||||
import { createMemo, createSignal, onMount } from "solid-js"
|
import { createMemo, createSignal, onMount } from "solid-js"
|
||||||
import { setTimeout as sleep } from "node:timers/promises"
|
import { setTimeout as sleep } from "node:timers/promises"
|
||||||
import { errorData, errorMessage } from "@/util/error"
|
import { errorData, errorMessage } from "@/util/error"
|
||||||
import * as Log from "@opencode-ai/core/util/log"
|
import * as Log from "@/util/log"
|
||||||
import { useSDK } from "../context/sdk"
|
import { useSDK } from "../context/sdk"
|
||||||
import { useToast } from "../ui/toast"
|
import { useToast } from "../ui/toast"
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { TextAttributes } from "@opentui/core"
|
|||||||
import { useKeyboard, useRenderer, useTerminalDimensions } from "@opentui/solid"
|
import { useKeyboard, useRenderer, useTerminalDimensions } from "@opentui/solid"
|
||||||
import * as Clipboard from "@tui/util/clipboard"
|
import * as Clipboard from "@tui/util/clipboard"
|
||||||
import { createSignal } from "solid-js"
|
import { createSignal } from "solid-js"
|
||||||
import { InstallationVersion } from "@opencode-ai/core/installation/version"
|
import { InstallationVersion } from "@/installation/version"
|
||||||
import { win32FlushInputBuffer } from "../win32"
|
import { win32FlushInputBuffer } from "../win32"
|
||||||
import { getScrollAcceleration } from "../util/scroll"
|
import { getScrollAcceleration } from "../util/scroll"
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import path from "path"
|
import path from "path"
|
||||||
import { Global } from "@opencode-ai/core/global"
|
import { Global } from "@/global"
|
||||||
import { Filesystem } from "@/util"
|
import { Filesystem } from "@/util"
|
||||||
import { onMount } from "solid-js"
|
import { onMount } from "solid-js"
|
||||||
import { createStore } from "solid-js/store"
|
import { createStore } from "solid-js/store"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import path from "path"
|
import path from "path"
|
||||||
import { Global } from "@opencode-ai/core/global"
|
import { Global } from "@/global"
|
||||||
import { Filesystem } from "@/util"
|
import { Filesystem } from "@/util"
|
||||||
import { onMount } from "solid-js"
|
import { onMount } from "solid-js"
|
||||||
import { createStore, produce, unwrap } from "solid-js/store"
|
import { createStore, produce, unwrap } from "solid-js/store"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import path from "path"
|
import path from "path"
|
||||||
import { Global } from "@opencode-ai/core/global"
|
import { Global } from "@/global"
|
||||||
import { Filesystem } from "@/util"
|
import { Filesystem } from "@/util"
|
||||||
import { onMount } from "solid-js"
|
import { onMount } from "solid-js"
|
||||||
import { createStore, produce, unwrap } from "solid-js/store"
|
import { createStore, produce, unwrap } from "solid-js/store"
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ import { type ParseError as JsoncParseError, applyEdits, modify, parse as parseJ
|
|||||||
import { unique } from "remeda"
|
import { unique } from "remeda"
|
||||||
import z from "zod"
|
import z from "zod"
|
||||||
import { TuiInfo, TuiOptions } from "./tui-schema"
|
import { TuiInfo, TuiOptions } from "./tui-schema"
|
||||||
import { Flag } from "@opencode-ai/core/flag/flag"
|
import { Flag } from "@/flag/flag"
|
||||||
import { Global } from "@opencode-ai/core/global"
|
import { Global } from "@/global"
|
||||||
import { Filesystem, Log } from "@/util"
|
import { Filesystem, Log } from "@/util"
|
||||||
import * as ConfigPaths from "@/config/paths"
|
import * as ConfigPaths from "@/config/paths"
|
||||||
|
|
||||||
|
|||||||
@@ -7,18 +7,18 @@ import { ConfigParse } from "@/config/parse"
|
|||||||
import * as ConfigPaths from "@/config/paths"
|
import * as ConfigPaths from "@/config/paths"
|
||||||
import { migrateTuiConfig } from "./tui-migrate"
|
import { migrateTuiConfig } from "./tui-migrate"
|
||||||
import { TuiInfo } from "./tui-schema"
|
import { TuiInfo } from "./tui-schema"
|
||||||
import { Flag } from "@opencode-ai/core/flag/flag"
|
import { Flag } from "@/flag/flag"
|
||||||
import { isRecord } from "@/util/record"
|
import { isRecord } from "@/util/record"
|
||||||
import { Global } from "@opencode-ai/core/global"
|
import { Global } from "@/global"
|
||||||
import { AppFileSystem } from "@opencode-ai/core/filesystem"
|
import { AppFileSystem } from "@opencode-ai/shared/filesystem"
|
||||||
import { CurrentWorkingDirectory } from "./cwd"
|
import { CurrentWorkingDirectory } from "./cwd"
|
||||||
import { ConfigPlugin } from "@/config/plugin"
|
import { ConfigPlugin } from "@/config/plugin"
|
||||||
import { ConfigKeybinds } from "@/config/keybinds"
|
import { ConfigKeybinds } from "@/config/keybinds"
|
||||||
import { InstallationLocal, InstallationVersion } from "@opencode-ai/core/installation/version"
|
import { InstallationLocal, InstallationVersion } from "@/installation/version"
|
||||||
import { makeRuntime } from "@opencode-ai/core/effect/runtime"
|
import { makeRuntime } from "@/effect/runtime"
|
||||||
import { Filesystem, Log } from "@/util"
|
import { Filesystem, Log } from "@/util"
|
||||||
import { ConfigVariable } from "@/config/variable"
|
import { ConfigVariable } from "@/config/variable"
|
||||||
import { Npm } from "@opencode-ai/core/npm"
|
import { Npm } from "@/npm"
|
||||||
|
|
||||||
const log = Log.create({ service: "tui.config" })
|
const log = Log.create({ service: "tui.config" })
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createMemo } from "solid-js"
|
import { createMemo } from "solid-js"
|
||||||
import { useProject } from "./project"
|
import { useProject } from "./project"
|
||||||
import { useSync } from "./sync"
|
import { useSync } from "./sync"
|
||||||
import { Global } from "@opencode-ai/core/global"
|
import { Global } from "@/global"
|
||||||
|
|
||||||
export function useDirectory() {
|
export function useDirectory() {
|
||||||
const project = useProject()
|
const project = useProject()
|
||||||
|
|||||||
@@ -1,172 +0,0 @@
|
|||||||
import { Database } from "bun:sqlite"
|
|
||||||
import os from "node:os"
|
|
||||||
import path from "node:path"
|
|
||||||
import z from "zod"
|
|
||||||
import { Filesystem } from "@/util"
|
|
||||||
import type { EditorSelection } from "./editor"
|
|
||||||
|
|
||||||
const ZedEditorRowSchema = z.object({
|
|
||||||
editor_id: z.number(),
|
|
||||||
workspace_id: z.number(),
|
|
||||||
workspace_paths: z.string().nullable(),
|
|
||||||
timestamp: z.string(),
|
|
||||||
buffer_path: z.string().nullable(),
|
|
||||||
selection_start: z.number().nullable(),
|
|
||||||
selection_end: z.number().nullable(),
|
|
||||||
})
|
|
||||||
|
|
||||||
const ZedEditorContentsSchema = z.object({
|
|
||||||
contents: z.string().nullable(),
|
|
||||||
})
|
|
||||||
|
|
||||||
type ZedEditorRow = z.infer<typeof ZedEditorRowSchema>
|
|
||||||
|
|
||||||
export async function resolveZedSelection(dbPath: string): Promise<EditorSelection | undefined> {
|
|
||||||
const row = queryZedActiveEditor(dbPath, process.cwd())
|
|
||||||
if (!row?.buffer_path || row.selection_start == null || row.selection_end == null) return
|
|
||||||
|
|
||||||
const text =
|
|
||||||
queryZedEditorContents(dbPath, row) ??
|
|
||||||
(await Bun.file(row.buffer_path)
|
|
||||||
.text()
|
|
||||||
.catch(() => undefined))
|
|
||||||
if (text == null) return
|
|
||||||
|
|
||||||
const startOffset = Math.min(row.selection_start, row.selection_end)
|
|
||||||
const endOffset = Math.max(row.selection_start, row.selection_end)
|
|
||||||
|
|
||||||
return {
|
|
||||||
text: text.slice(startOffset, endOffset),
|
|
||||||
filePath: row.buffer_path,
|
|
||||||
selection: offsetsToSelection(text, startOffset, endOffset),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function queryZedActiveEditor(dbPath: string, cwd: string) {
|
|
||||||
let db: Database | undefined
|
|
||||||
try {
|
|
||||||
db = new Database(dbPath, { readonly: true })
|
|
||||||
return db
|
|
||||||
.query(
|
|
||||||
`select
|
|
||||||
e.item_id as editor_id,
|
|
||||||
e.workspace_id as workspace_id,
|
|
||||||
w.paths as workspace_paths,
|
|
||||||
w.timestamp as timestamp,
|
|
||||||
e.buffer_path as buffer_path,
|
|
||||||
s.start as selection_start,
|
|
||||||
s.end as selection_end
|
|
||||||
from items i
|
|
||||||
join panes p on p.pane_id = i.pane_id and p.workspace_id = i.workspace_id
|
|
||||||
join workspaces w on w.workspace_id = i.workspace_id
|
|
||||||
join editors e on e.item_id = i.item_id and e.workspace_id = i.workspace_id
|
|
||||||
left join editor_selections s on s.editor_id = e.item_id and s.workspace_id = e.workspace_id
|
|
||||||
where i.active = 1 and p.active = 1 and i.kind = 'Editor' and e.buffer_path is not null
|
|
||||||
order by w.timestamp desc`,
|
|
||||||
)
|
|
||||||
.all()
|
|
||||||
.flatMap((row) => {
|
|
||||||
const parsed = ZedEditorRowSchema.safeParse(row)
|
|
||||||
return parsed.success ? [parsed.data] : []
|
|
||||||
})
|
|
||||||
.map((row) => ({ row, score: scoreZedWorkspace(row.workspace_paths, cwd) }))
|
|
||||||
.filter((entry) => entry.score > 0)
|
|
||||||
.sort((left, right) => right.score - left.score || right.row.timestamp.localeCompare(left.row.timestamp))[0]?.row
|
|
||||||
} catch {
|
|
||||||
return
|
|
||||||
} finally {
|
|
||||||
db?.close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function queryZedEditorContents(dbPath: string, row: ZedEditorRow) {
|
|
||||||
let db: Database | undefined
|
|
||||||
try {
|
|
||||||
db = new Database(dbPath, { readonly: true })
|
|
||||||
return ZedEditorContentsSchema.safeParse(
|
|
||||||
db
|
|
||||||
.query(
|
|
||||||
`select contents
|
|
||||||
from editors
|
|
||||||
where item_id = $editorID and workspace_id = $workspaceID`,
|
|
||||||
)
|
|
||||||
.get({ $editorID: row.editor_id, $workspaceID: row.workspace_id }),
|
|
||||||
).data?.contents
|
|
||||||
} catch {
|
|
||||||
return
|
|
||||||
} finally {
|
|
||||||
db?.close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function resolveZedDbPath() {
|
|
||||||
const candidates = [
|
|
||||||
process.env.OPENCODE_ZED_DB,
|
|
||||||
path.join(os.homedir(), "Library", "Application Support", "Zed", "db", "0-stable", "db.sqlite"),
|
|
||||||
path.join(os.homedir(), ".local", "share", "zed", "db", "0-stable", "db.sqlite"),
|
|
||||||
].filter((item): item is string => Boolean(item))
|
|
||||||
|
|
||||||
return candidates.find((item) => Filesystem.stat(item)?.isFile())
|
|
||||||
}
|
|
||||||
|
|
||||||
function scoreZedWorkspace(workspacePaths: string | null, cwd: string) {
|
|
||||||
return zedWorkspacePaths(workspacePaths).reduce((score, item) => {
|
|
||||||
if (pathContains(item, cwd)) return Math.max(score, 2)
|
|
||||||
if (pathContains(cwd, item)) return Math.max(score, 1)
|
|
||||||
return score
|
|
||||||
}, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
function zedWorkspacePaths(value: string | null) {
|
|
||||||
if (!value) return []
|
|
||||||
const parsed = parseJson(value)
|
|
||||||
if (Array.isArray(parsed)) return parsed.filter((item): item is string => typeof item === "string")
|
|
||||||
return value.split(/\r?\n/).filter(Boolean)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function offsetToPosition(text: string, offset: number) {
|
|
||||||
return offsetsToSelection(text, offset, offset).start
|
|
||||||
}
|
|
||||||
|
|
||||||
function offsetsToSelection(text: string, startOffset: number, endOffset: number) {
|
|
||||||
const start = Math.max(0, Math.min(startOffset, text.length))
|
|
||||||
const end = Math.max(0, Math.min(endOffset, text.length))
|
|
||||||
let line = 1
|
|
||||||
let lineStart = 0
|
|
||||||
let startPosition = position(line, lineStart, start)
|
|
||||||
let endPosition = position(line, lineStart, end)
|
|
||||||
|
|
||||||
for (let index = 0; index <= end; index++) {
|
|
||||||
if (index === start) startPosition = position(line, lineStart, index)
|
|
||||||
if (index === end) {
|
|
||||||
endPosition = position(line, lineStart, index)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if (text[index] === "\n") {
|
|
||||||
line += 1
|
|
||||||
lineStart = index + 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return { start: startPosition, end: endPosition }
|
|
||||||
}
|
|
||||||
|
|
||||||
function position(line: number, lineStart: number, offset: number) {
|
|
||||||
return {
|
|
||||||
line,
|
|
||||||
character: offset - lineStart + 1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function pathContains(parent: string, child: string) {
|
|
||||||
const relative = path.relative(path.resolve(parent), path.resolve(child))
|
|
||||||
return relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative))
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseJson(value: string) {
|
|
||||||
try {
|
|
||||||
return JSON.parse(value) as unknown
|
|
||||||
} catch {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -4,9 +4,7 @@ import path from "node:path"
|
|||||||
import { onCleanup, onMount } from "solid-js"
|
import { onCleanup, onMount } from "solid-js"
|
||||||
import { createStore } from "solid-js/store"
|
import { createStore } from "solid-js/store"
|
||||||
import z from "zod"
|
import z from "zod"
|
||||||
import { isRecord } from "@/util/record"
|
|
||||||
import { createSimpleContext } from "./helper"
|
import { createSimpleContext } from "./helper"
|
||||||
import { resolveZedDbPath, resolveZedSelection } from "./editor-zed"
|
|
||||||
|
|
||||||
const MCP_PROTOCOL_VERSION = "2025-11-25"
|
const MCP_PROTOCOL_VERSION = "2025-11-25"
|
||||||
|
|
||||||
@@ -92,8 +90,6 @@ export const { use: useEditorContext, provider: EditorContextProvider } = create
|
|||||||
let reconnect: ReturnType<typeof setTimeout> | undefined
|
let reconnect: ReturnType<typeof setTimeout> | undefined
|
||||||
let attempt = 0
|
let attempt = 0
|
||||||
let requestID = 0
|
let requestID = 0
|
||||||
let zedSelection: Promise<void> | undefined
|
|
||||||
let lastZedSelectionKey: string | undefined
|
|
||||||
const pending = new Map<number, string>()
|
const pending = new Map<number, string>()
|
||||||
|
|
||||||
const send = (payload: JsonRpcMessage) => {
|
const send = (payload: JsonRpcMessage) => {
|
||||||
@@ -118,29 +114,7 @@ export const { use: useEditorContext, provider: EditorContextProvider } = create
|
|||||||
|
|
||||||
const connection = resolveEditorConnection()
|
const connection = resolveEditorConnection()
|
||||||
if (!connection) {
|
if (!connection) {
|
||||||
const dbPath = resolveZedDbPath()
|
setStore("status", "disabled")
|
||||||
if (!dbPath) {
|
|
||||||
setStore("status", "disabled")
|
|
||||||
scheduleReconnect(1000)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
zedSelection ??= resolveZedSelection(dbPath)
|
|
||||||
.then((selection) => {
|
|
||||||
if (closed || socket) return
|
|
||||||
const key = editorSelectionKey(selection)
|
|
||||||
if (key !== lastZedSelectionKey) {
|
|
||||||
lastZedSelectionKey = key
|
|
||||||
setStore("selection", selection)
|
|
||||||
setStore("status", selection ? "connected" : "disabled")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
if (closed || socket) return
|
|
||||||
setStore("status", "disabled")
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
zedSelection = undefined
|
|
||||||
})
|
|
||||||
scheduleReconnect(1000)
|
scheduleReconnect(1000)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -222,7 +196,7 @@ export const { use: useEditorContext, provider: EditorContextProvider } = create
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
enabled() {
|
enabled() {
|
||||||
return Boolean(resolveEditorConnection() || resolveZedDbPath())
|
return Boolean(resolveEditorConnection())
|
||||||
},
|
},
|
||||||
connected() {
|
connected() {
|
||||||
return store.status === "connected"
|
return store.status === "connected"
|
||||||
@@ -315,18 +289,6 @@ function scoreEditorLock(lock: EditorLockFile, cwd: string) {
|
|||||||
return workspaceMatch * 1_000_000_000_000 + lock.mtimeMs
|
return workspaceMatch * 1_000_000_000_000 + lock.mtimeMs
|
||||||
}
|
}
|
||||||
|
|
||||||
function editorSelectionKey(selection: EditorSelection | undefined) {
|
|
||||||
if (!selection) return ""
|
|
||||||
return [
|
|
||||||
selection.filePath,
|
|
||||||
selection.selection.start.line,
|
|
||||||
selection.selection.start.character,
|
|
||||||
selection.selection.end.line,
|
|
||||||
selection.selection.end.character,
|
|
||||||
selection.text,
|
|
||||||
].join("\0")
|
|
||||||
}
|
|
||||||
|
|
||||||
function pathContains(parent: string, child: string) {
|
function pathContains(parent: string, child: string) {
|
||||||
const relative = path.relative(path.resolve(parent), path.resolve(child))
|
const relative = path.relative(path.resolve(parent), path.resolve(child))
|
||||||
return relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative))
|
return relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative))
|
||||||
@@ -351,3 +313,7 @@ function parseMessage(value: unknown) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
||||||
|
return typeof value === "object" && value !== null && !Array.isArray(value)
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Global } from "@opencode-ai/core/global"
|
import { Global } from "@/global"
|
||||||
import { Filesystem } from "@/util"
|
import { Filesystem } from "@/util"
|
||||||
import { Flock } from "@opencode-ai/core/util/flock"
|
import { Flock } from "@opencode-ai/shared/util/flock"
|
||||||
import { rename, rm } from "fs/promises"
|
import { rename, rm } from "fs/promises"
|
||||||
import { createSignal, type Setter } from "solid-js"
|
import { createSignal, type Setter } from "solid-js"
|
||||||
import { createStore, unwrap } from "solid-js/store"
|
import { createStore, unwrap } from "solid-js/store"
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { useSync } from "@tui/context/sync"
|
|||||||
import { useTheme } from "@tui/context/theme"
|
import { useTheme } from "@tui/context/theme"
|
||||||
import { uniqueBy } from "remeda"
|
import { uniqueBy } from "remeda"
|
||||||
import path from "path"
|
import path from "path"
|
||||||
import { Global } from "@opencode-ai/core/global"
|
import { Global } from "@/global"
|
||||||
import { iife } from "@/util/iife"
|
import { iife } from "@/util/iife"
|
||||||
import { useToast } from "../ui/toast"
|
import { useToast } from "../ui/toast"
|
||||||
import { useArgs } from "./args"
|
import { useArgs } from "./args"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { createOpencodeClient } from "@opencode-ai/sdk/v2"
|
|||||||
import type { GlobalEvent } from "@opencode-ai/sdk/v2"
|
import type { GlobalEvent } from "@opencode-ai/sdk/v2"
|
||||||
import { createSimpleContext } from "./helper"
|
import { createSimpleContext } from "./helper"
|
||||||
import { createGlobalEmitter } from "@solid-primitives/event-bus"
|
import { createGlobalEmitter } from "@solid-primitives/event-bus"
|
||||||
import { Flag } from "@opencode-ai/core/flag/flag"
|
import { Flag } from "@/flag/flag"
|
||||||
import { batch, onCleanup, onMount } from "solid-js"
|
import { batch, onCleanup, onMount } from "solid-js"
|
||||||
|
|
||||||
export type EventSource = {
|
export type EventSource = {
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import { createStore, produce, reconcile } from "solid-js/store"
|
|||||||
import { useProject } from "@tui/context/project"
|
import { useProject } from "@tui/context/project"
|
||||||
import { useEvent } from "@tui/context/event"
|
import { useEvent } from "@tui/context/event"
|
||||||
import { useSDK } from "@tui/context/sdk"
|
import { useSDK } from "@tui/context/sdk"
|
||||||
import { Binary } from "@opencode-ai/core/util/binary"
|
import { Binary } from "@opencode-ai/shared/util/binary"
|
||||||
import { createSimpleContext } from "./helper"
|
import { createSimpleContext } from "./helper"
|
||||||
import type { Snapshot } from "@/snapshot"
|
import type { Snapshot } from "@/snapshot"
|
||||||
import { useExit } from "./exit"
|
import { useExit } from "./exit"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { CliRenderEvents, SyntaxStyle, RGBA, type TerminalColors } from "@opentu
|
|||||||
import path from "path"
|
import path from "path"
|
||||||
import { createEffect, createMemo, onCleanup, onMount } from "solid-js"
|
import { createEffect, createMemo, onCleanup, onMount } from "solid-js"
|
||||||
import { createSimpleContext } from "./helper"
|
import { createSimpleContext } from "./helper"
|
||||||
import { Glob } from "@opencode-ai/core/util/glob"
|
import { Glob } from "@opencode-ai/shared/util/glob"
|
||||||
import aura from "./theme/aura.json" with { type: "json" }
|
import aura from "./theme/aura.json" with { type: "json" }
|
||||||
import ayu from "./theme/ayu.json" with { type: "json" }
|
import ayu from "./theme/ayu.json" with { type: "json" }
|
||||||
import catppuccin from "./theme/catppuccin.json" with { type: "json" }
|
import catppuccin from "./theme/catppuccin.json" with { type: "json" }
|
||||||
@@ -39,7 +39,7 @@ import carbonfox from "./theme/carbonfox.json" with { type: "json" }
|
|||||||
import { useKV } from "./kv"
|
import { useKV } from "./kv"
|
||||||
import { useRenderer } from "@opentui/solid"
|
import { useRenderer } from "@opentui/solid"
|
||||||
import { createStore, produce } from "solid-js/store"
|
import { createStore, produce } from "solid-js/store"
|
||||||
import { Global } from "@opencode-ai/core/global"
|
import { Global } from "@/global"
|
||||||
import { Filesystem } from "@/util"
|
import { Filesystem } from "@/util"
|
||||||
import { useTuiConfig } from "./tui-config"
|
import { useTuiConfig } from "./tui-config"
|
||||||
import { isRecord } from "@/util/record"
|
import { isRecord } from "@/util/record"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { TuiPlugin, TuiPluginApi, TuiPluginModule } from "@opencode-ai/plugin/tui"
|
import type { TuiPlugin, TuiPluginApi, TuiPluginModule } from "@opencode-ai/plugin/tui"
|
||||||
import { createMemo, Match, Show, Switch } from "solid-js"
|
import { createMemo, Match, Show, Switch } from "solid-js"
|
||||||
import { Global } from "@opencode-ai/core/global"
|
import { Global } from "@/global"
|
||||||
|
|
||||||
const id = "internal:home-footer"
|
const id = "internal:home-footer"
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { createMemo, For } from "solid-js"
|
import { For } from "solid-js"
|
||||||
import { DEFAULT_THEMES, useTheme } from "@tui/context/theme"
|
import { DEFAULT_THEMES, useTheme } from "@tui/context/theme"
|
||||||
|
|
||||||
const themeCount = Object.keys(DEFAULT_THEMES).length
|
const themeCount = Object.keys(DEFAULT_THEMES).length
|
||||||
@@ -30,12 +30,9 @@ function parse(tip: string): TipPart[] {
|
|||||||
return parts
|
return parts
|
||||||
}
|
}
|
||||||
|
|
||||||
const NO_MODELS_TIP = "Run {highlight}/connect{/highlight} to add an AI provider and start coding"
|
export function Tips() {
|
||||||
|
|
||||||
export function Tips(props: { connected?: boolean }) {
|
|
||||||
const theme = useTheme().theme
|
const theme = useTheme().theme
|
||||||
const randomTip = TIPS[Math.floor(Math.random() * TIPS.length)]
|
const parts = parse(TIPS[Math.floor(Math.random() * TIPS.length)])
|
||||||
const parts = createMemo(() => parse(props.connected === false ? NO_MODELS_TIP : randomTip))
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<box flexDirection="row" maxWidth="100%">
|
<box flexDirection="row" maxWidth="100%">
|
||||||
@@ -43,7 +40,7 @@ export function Tips(props: { connected?: boolean }) {
|
|||||||
● Tip{" "}
|
● Tip{" "}
|
||||||
</text>
|
</text>
|
||||||
<text flexShrink={1}>
|
<text flexShrink={1}>
|
||||||
<For each={parts()}>
|
<For each={parts}>
|
||||||
{(part) => <span style={{ fg: part.highlight ? theme.text : theme.textMuted }}>{part.text}</span>}
|
{(part) => <span style={{ fg: part.highlight ? theme.text : theme.textMuted }}>{part.text}</span>}
|
||||||
</For>
|
</For>
|
||||||
</text>
|
</text>
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ import { Tips } from "./tips-view"
|
|||||||
|
|
||||||
const id = "internal:home-tips"
|
const id = "internal:home-tips"
|
||||||
|
|
||||||
function View(props: { show: boolean; connected: boolean }) {
|
function View(props: { show: boolean }) {
|
||||||
return (
|
return (
|
||||||
<box height={4} minHeight={0} width="100%" maxWidth={75} alignItems="center" paddingTop={3} flexShrink={1}>
|
<box height={4} minHeight={0} width="100%" maxWidth={75} alignItems="center" paddingTop={3} flexShrink={1}>
|
||||||
<Show when={props.show}>
|
<Show when={props.show}>
|
||||||
<Tips connected={props.connected} />
|
<Tips />
|
||||||
</Show>
|
</Show>
|
||||||
</box>
|
</box>
|
||||||
)
|
)
|
||||||
@@ -35,13 +35,8 @@ const tui: TuiPlugin = async (api) => {
|
|||||||
home_bottom() {
|
home_bottom() {
|
||||||
const hidden = createMemo(() => api.kv.get("tips_hidden", false))
|
const hidden = createMemo(() => api.kv.get("tips_hidden", false))
|
||||||
const first = createMemo(() => api.state.session.count() === 0)
|
const first = createMemo(() => api.state.session.count() === 0)
|
||||||
const connected = createMemo(() =>
|
const show = createMemo(() => !first() && !hidden())
|
||||||
api.state.provider.some(
|
return <View show={show()} />
|
||||||
(item) => item.id !== "opencode" || Object.values(item.models).some((model) => model.cost?.input !== 0),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
const show = createMemo(() => (!first() || !connected()) && !hidden())
|
|
||||||
return <View show={show()} connected={connected()} />
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { TuiPlugin, TuiPluginApi, TuiPluginModule } from "@opencode-ai/plugin/tui"
|
import type { TuiPlugin, TuiPluginApi, TuiPluginModule } from "@opencode-ai/plugin/tui"
|
||||||
import { createMemo, Show } from "solid-js"
|
import { createMemo, Show } from "solid-js"
|
||||||
import { Global } from "@opencode-ai/core/global"
|
import { Global } from "@/global"
|
||||||
|
|
||||||
const id = "internal:sidebar-footer"
|
const id = "internal:sidebar-footer"
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Layer } from "effect"
|
import { Layer } from "effect"
|
||||||
import { TuiConfig } from "./config/tui"
|
import { TuiConfig } from "./config/tui"
|
||||||
import { Npm } from "@opencode-ai/core/npm"
|
import { Npm } from "@/npm"
|
||||||
import { Observability } from "@opencode-ai/core/effect/observability"
|
import { Observability } from "@/effect/observability"
|
||||||
|
|
||||||
export const CliLayer = Observability.layer.pipe(Layer.merge(TuiConfig.layer), Layer.provide(Npm.defaultLayer))
|
export const CliLayer = Observability.layer.pipe(Layer.merge(TuiConfig.layer), Layer.provide(Npm.defaultLayer))
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import { DialogSelect, type DialogSelectOption as SelectOption } from "../ui/dia
|
|||||||
import { Prompt } from "../component/prompt"
|
import { Prompt } from "../component/prompt"
|
||||||
import { Slot as HostSlot } from "./slots"
|
import { Slot as HostSlot } from "./slots"
|
||||||
import type { useToast } from "../ui/toast"
|
import type { useToast } from "../ui/toast"
|
||||||
import { InstallationVersion } from "@opencode-ai/core/installation/version"
|
import { InstallationVersion } from "@/installation/version"
|
||||||
|
|
||||||
type RouteEntry = {
|
type RouteEntry = {
|
||||||
key: symbol
|
key: symbol
|
||||||
|
|||||||
@@ -29,11 +29,11 @@ import { PluginLoader } from "@/plugin/loader"
|
|||||||
import { PluginMeta } from "@/plugin/meta"
|
import { PluginMeta } from "@/plugin/meta"
|
||||||
import { installPlugin as installModulePlugin, patchPluginConfig, readPluginManifest } from "@/plugin/install"
|
import { installPlugin as installModulePlugin, patchPluginConfig, readPluginManifest } from "@/plugin/install"
|
||||||
import { hasTheme, upsertTheme } from "../context/theme"
|
import { hasTheme, upsertTheme } from "../context/theme"
|
||||||
import { Global } from "@opencode-ai/core/global"
|
import { Global } from "@/global"
|
||||||
import { Filesystem } from "@/util"
|
import { Filesystem } from "@/util"
|
||||||
import { Process } from "@/util"
|
import { Process } from "@/util"
|
||||||
import { Flock } from "@opencode-ai/core/util/flock"
|
import { Flock } from "@opencode-ai/shared/util/flock"
|
||||||
import { Flag } from "@opencode-ai/core/flag/flag"
|
import { Flag } from "@/flag/flag"
|
||||||
import { INTERNAL_TUI_PLUGINS, type InternalTuiPlugin } from "./internal"
|
import { INTERNAL_TUI_PLUGINS, type InternalTuiPlugin } from "./internal"
|
||||||
import { setupSlots, Slot as View } from "./slots"
|
import { setupSlots, Slot as View } from "./slots"
|
||||||
import type { HostPluginApi, HostSlots } from "./slots"
|
import type { HostPluginApi, HostSlots } from "./slots"
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ import { DialogForkFromTimeline } from "./dialog-fork-from-timeline"
|
|||||||
import { DialogSessionRename } from "../../component/dialog-session-rename"
|
import { DialogSessionRename } from "../../component/dialog-session-rename"
|
||||||
import { Sidebar } from "./sidebar"
|
import { Sidebar } from "./sidebar"
|
||||||
import { SubagentFooter } from "./subagent-footer.tsx"
|
import { SubagentFooter } from "./subagent-footer.tsx"
|
||||||
import { Flag } from "@opencode-ai/core/flag/flag"
|
import { Flag } from "@/flag/flag"
|
||||||
import { LANGUAGE_EXTENSIONS } from "@/lsp/language"
|
import { LANGUAGE_EXTENSIONS } from "@/lsp/language"
|
||||||
import parsers from "../../../../../../parsers-config.ts"
|
import parsers from "../../../../../../parsers-config.ts"
|
||||||
import * as Clipboard from "../../util/clipboard"
|
import * as Clipboard from "../../util/clipboard"
|
||||||
@@ -76,7 +76,7 @@ import stripAnsi from "strip-ansi"
|
|||||||
import { usePromptRef } from "../../context/prompt"
|
import { usePromptRef } from "../../context/prompt"
|
||||||
import { useExit } from "../../context/exit"
|
import { useExit } from "../../context/exit"
|
||||||
import { Filesystem } from "@/util"
|
import { Filesystem } from "@/util"
|
||||||
import { Global } from "@opencode-ai/core/global"
|
import { Global } from "@/global"
|
||||||
import { PermissionPrompt } from "./permission"
|
import { PermissionPrompt } from "./permission"
|
||||||
import { QuestionPrompt } from "./question"
|
import { QuestionPrompt } from "./question"
|
||||||
import { DialogExportOptions } from "../../ui/dialog-export-options"
|
import { DialogExportOptions } from "../../ui/dialog-export-options"
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import path from "path"
|
|||||||
import { LANGUAGE_EXTENSIONS } from "@/lsp/language"
|
import { LANGUAGE_EXTENSIONS } from "@/lsp/language"
|
||||||
import { Keybind } from "@/util"
|
import { Keybind } from "@/util"
|
||||||
import { Locale } from "@/util"
|
import { Locale } from "@/util"
|
||||||
import { Global } from "@opencode-ai/core/global"
|
import { Global } from "@/global"
|
||||||
import { useDialog } from "../../ui/dialog"
|
import { useDialog } from "../../ui/dialog"
|
||||||
import { getScrollAcceleration } from "../../util/scroll"
|
import { getScrollAcceleration } from "../../util/scroll"
|
||||||
import { useTuiConfig } from "../../context/tui-config"
|
import { useTuiConfig } from "../../context/tui-config"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { useSync } from "@tui/context/sync"
|
|||||||
import { createMemo, Show } from "solid-js"
|
import { createMemo, Show } from "solid-js"
|
||||||
import { useTheme } from "../../context/theme"
|
import { useTheme } from "../../context/theme"
|
||||||
import { useTuiConfig } from "../../context/tui-config"
|
import { useTuiConfig } from "../../context/tui-config"
|
||||||
import { InstallationChannel, InstallationVersion } from "@opencode-ai/core/installation/version"
|
import { InstallationChannel, InstallationVersion } from "@/installation/version"
|
||||||
import { TuiPluginRuntime } from "../../plugin"
|
import { TuiPluginRuntime } from "../../plugin"
|
||||||
|
|
||||||
import { getScrollAcceleration } from "../../util/scroll"
|
import { getScrollAcceleration } from "../../util/scroll"
|
||||||
|
|||||||
@@ -15,12 +15,7 @@ import type { EventSource } from "./context/sdk"
|
|||||||
import { win32DisableProcessedInput, win32InstallCtrlCGuard } from "./win32"
|
import { win32DisableProcessedInput, win32InstallCtrlCGuard } from "./win32"
|
||||||
import { writeHeapSnapshot } from "v8"
|
import { writeHeapSnapshot } from "v8"
|
||||||
import { TuiConfig } from "./config/tui"
|
import { TuiConfig } from "./config/tui"
|
||||||
import {
|
import { OPENCODE_PROCESS_ROLE, OPENCODE_RUN_ID, ensureRunID, sanitizedProcessEnv } from "@/util/opencode-process"
|
||||||
OPENCODE_PROCESS_ROLE,
|
|
||||||
OPENCODE_RUN_ID,
|
|
||||||
ensureRunID,
|
|
||||||
sanitizedProcessEnv,
|
|
||||||
} from "@opencode-ai/core/util/opencode-process"
|
|
||||||
import { validateSession } from "./validate-session"
|
import { validateSession } from "./validate-session"
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { useTheme } from "@tui/context/theme"
|
|||||||
import { MouseButton, Renderable, RGBA } from "@opentui/core"
|
import { MouseButton, Renderable, RGBA } from "@opentui/core"
|
||||||
import { createStore } from "solid-js/store"
|
import { createStore } from "solid-js/store"
|
||||||
import { useToast } from "./toast"
|
import { useToast } from "./toast"
|
||||||
import { Flag } from "@opencode-ai/core/flag/flag"
|
import { Flag } from "@/flag/flag"
|
||||||
import * as Selection from "@tui/util/selection"
|
import * as Selection from "@tui/util/selection"
|
||||||
|
|
||||||
export function Dialog(
|
export function Dialog(
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ import { Rpc } from "@/util"
|
|||||||
import { upgrade } from "@/cli/upgrade"
|
import { upgrade } from "@/cli/upgrade"
|
||||||
import { Config } from "@/config"
|
import { Config } from "@/config"
|
||||||
import { GlobalBus } from "@/bus/global"
|
import { GlobalBus } from "@/bus/global"
|
||||||
import { Flag } from "@opencode-ai/core/flag/flag"
|
import { Flag } from "@/flag/flag"
|
||||||
import { writeHeapSnapshot } from "node:v8"
|
import { writeHeapSnapshot } from "node:v8"
|
||||||
import { Heap } from "@/cli/heap"
|
import { Heap } from "@/cli/heap"
|
||||||
import { AppRuntime } from "@/effect/app-runtime"
|
import { AppRuntime } from "@/effect/app-runtime"
|
||||||
import { ensureProcessMetadata } from "@opencode-ai/core/util/opencode-process"
|
import { ensureProcessMetadata } from "@/util/opencode-process"
|
||||||
|
|
||||||
ensureProcessMetadata("worker")
|
ensureProcessMetadata("worker")
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user