Compare commits
144 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5b1feb4c54 | |||
| ca2f54a68d | |||
| 0033c4474c | |||
| 80bcc8d478 | |||
| d0f6065e4c | |||
| b6da0a9cda | |||
| 967fa4d3bb | |||
| a35dc04d15 | |||
| 51bc4246d2 | |||
| a5e6263c58 | |||
| 966f5acef4 | |||
| 0b395cd13e | |||
| 35239bddef | |||
| 41367fa3ba | |||
| 97caa6bf82 | |||
| 191eb357bc | |||
| b03d064127 | |||
| 945ad08380 | |||
| cbc8847af8 | |||
| d58ebc5cf4 | |||
| 9fbeafb63e | |||
| 91bd295209 | |||
| d4bf70be06 | |||
| ae8904c4ff | |||
| 9209c04370 | |||
| 379e7f3f20 | |||
| 366d11e1f8 | |||
| 58836e75f0 | |||
| 0acac216ae | |||
| 276d162044 | |||
| 1b0ed983c5 | |||
| 2e8d690ab1 | |||
| 1ff8d289af | |||
| d54ffbda1c | |||
| c00058ed7a | |||
| 2c2fc3499b | |||
| ea3c6c3481 | |||
| 9b68b7195a | |||
| 7739cc53b4 | |||
| 3fa78a8b01 | |||
| e57d0c2fee | |||
| 2a4f2bf527 | |||
| aa07f38b07 | |||
| 9d1f17d836 | |||
| b420952e59 | |||
| bb9e445257 | |||
| 528fb1d404 | |||
| c8d9f7aa89 | |||
| cd7ec93cdf | |||
| 796b652d2b | |||
| 4d74849c1a | |||
| 937a7c48a5 | |||
| 704eb00de4 | |||
| bad4599bf9 | |||
| 892fd85ba7 | |||
| 0eaa47d857 | |||
| faca24d487 | |||
| c103202ad5 | |||
| ce78a4265d | |||
| c4a2353ac3 | |||
| 576efed196 | |||
| dfc0075f90 | |||
| acd15dcc8a | |||
| 139c4fd555 | |||
| e0f3df8252 | |||
| 9cd2e3a1c3 | |||
| f584f80219 | |||
| 45eac589f8 | |||
| fab1768826 | |||
| 51fc10e407 | |||
| 7a1c8465f5 | |||
| 5290e9ca7e | |||
| c361c2953f | |||
| ccb7669736 | |||
| f25f1485d5 | |||
| 55ecb06748 | |||
| dc6991e5a8 | |||
| 738b3065dc | |||
| 26cc537cb1 | |||
| ede354b0e6 | |||
| 61eabfc60c | |||
| 2789b770aa | |||
| 8718b98ee1 | |||
| c8b2f987f9 | |||
| 52b55b826f | |||
| e8c20235b8 | |||
| 17701628bd | |||
| 0efc6163f1 | |||
| 1e191ba815 | |||
| f19d863689 | |||
| 4a1ef327ca | |||
| 025a6392ce | |||
| e578c442be | |||
| 0cecb1bff2 | |||
| 5d8971c1ed | |||
| a9b62d67df | |||
| 3525e61906 | |||
| 059e6c46db | |||
| 5cf195e0af | |||
| 244d1debe4 | |||
| 35734b42fe | |||
| a3128e32c5 | |||
| 5f8a72bfc4 | |||
| 418a1cf5f3 | |||
| 60ebd074ac | |||
| 216dd363e8 | |||
| 141f33d24b | |||
| c4d8a8183e | |||
| 58244eb687 | |||
| e9071b0a80 | |||
| c68907ece2 | |||
| af3998c8a6 | |||
| fad2618757 | |||
| 21e01dbe04 | |||
| 3beadeebff | |||
| dcee1c3642 | |||
| 00d1a7e090 | |||
| bbb56c2a88 | |||
| 5186c6964b | |||
| 79c66e353f | |||
| 41f5e8a861 | |||
| c5b67927af | |||
| 301ecb185e | |||
| 151df05eeb | |||
| 55adcdfd07 | |||
| daaa2e5911 | |||
| daff119fe4 | |||
| e0d1ff42c0 | |||
| de413c56ae | |||
| da61b0290a | |||
| d03e6cedde | |||
| 7feb6ab962 | |||
| 854d4b7a53 | |||
| aa5999b188 | |||
| 37c5eab6f8 | |||
| 6daa2b9aeb | |||
| 5a5a2e5fa0 | |||
| 95c43fc675 | |||
| e7053c41f4 | |||
| fc6d4b4010 | |||
| 2893588016 | |||
| f2d4d816fb | |||
| 097d930668 | |||
| 7cab6824d1 |
+3
-1
@@ -12,8 +12,10 @@ adamdotdevin
|
||||
ariane-emory
|
||||
-atharvau AI review spamming literally every PR
|
||||
-borealbytes
|
||||
-carycooper777
|
||||
-danieljoshuanazareth
|
||||
-danieljoshuanazareth
|
||||
-davidbernat looks to be a clawdbot that spams team and sends super weird emails, doesnt appear to be a real person
|
||||
edemaine
|
||||
-florianleibert
|
||||
fwang
|
||||
@@ -31,6 +33,6 @@ rubdos
|
||||
shantur
|
||||
simonklee
|
||||
-spider-yamet clawdbot/llm psychosis, spam pinging the team
|
||||
-terisuke
|
||||
thdxr
|
||||
-toastythebot
|
||||
-davidbernat looks to be a clawdbot that spams team and sends super weird emails, doesnt appear to be a real person
|
||||
|
||||
@@ -1,899 +0,0 @@
|
||||
---
|
||||
description: Translate content for a specified locale while preserving technical terms
|
||||
mode: subagent
|
||||
model: opencode/gpt-5.4
|
||||
---
|
||||
|
||||
You are a professional translator and localization specialist.
|
||||
|
||||
Translate the user's content into the requested target locale (language + region, e.g. fr-FR, de-DE).
|
||||
|
||||
Requirements:
|
||||
|
||||
- Preserve meaning, intent, tone, and formatting (including Markdown/MDX structure).
|
||||
- Preserve all technical terms and artifacts exactly: product/company names, API names, identifiers, code, commands/flags, file paths, URLs, versions, error messages, config keys/values, and anything inside inline code or code blocks.
|
||||
- Also preserve every term listed in the Do-Not-Translate glossary below.
|
||||
- Also apply locale-specific guidance from `.opencode/glossary/<locale>.md` when available (for example, `zh-cn.md`).
|
||||
- Do not modify fenced code blocks.
|
||||
- Output ONLY the translation (no commentary).
|
||||
|
||||
If the target locale is missing, ask the user to provide it.
|
||||
If no locale-specific glossary exists, use the global glossary only.
|
||||
|
||||
---
|
||||
|
||||
# Locale-Specific Glossaries
|
||||
|
||||
When a locale glossary exists, use it to:
|
||||
|
||||
- Apply preferred wording for recurring UI/docs terms in that locale
|
||||
- Preserve locale-specific do-not-translate terms and casing decisions
|
||||
- Prefer natural phrasing over literal translation when the locale file calls it out
|
||||
- If the repo uses a locale alias slug, apply that file too (for example, `pt-BR` maps to `br.md` in this repo)
|
||||
|
||||
Locale guidance does not override code/command preservation rules or the global Do-Not-Translate glossary below.
|
||||
|
||||
---
|
||||
|
||||
# Do-Not-Translate Terms (OpenCode Docs)
|
||||
|
||||
Generated from: `packages/web/src/content/docs/*.mdx` (default English docs)
|
||||
Generated on: 2026-02-10
|
||||
|
||||
Use this as a translation QA checklist / glossary. Preserve listed terms exactly (spelling, casing, punctuation).
|
||||
|
||||
General rules (verbatim, even if not listed below):
|
||||
|
||||
- Anything inside inline code (single backticks) or fenced code blocks (triple backticks)
|
||||
- MDX/JS code in docs: `import ... from "..."`, component tags, identifiers
|
||||
- CLI commands, flags, config keys/values, file paths, URLs/domains, and env vars
|
||||
|
||||
## Proper nouns and product names
|
||||
|
||||
Additional (not reliably captured via link text):
|
||||
|
||||
```text
|
||||
Astro
|
||||
Bun
|
||||
Chocolatey
|
||||
Cursor
|
||||
Docker
|
||||
Git
|
||||
GitHub Actions
|
||||
GitLab CI
|
||||
GNOME Terminal
|
||||
Homebrew
|
||||
Mise
|
||||
Neovim
|
||||
Node.js
|
||||
npm
|
||||
Obsidian
|
||||
opencode
|
||||
opencode-ai
|
||||
Paru
|
||||
pnpm
|
||||
ripgrep
|
||||
Scoop
|
||||
SST
|
||||
Starlight
|
||||
Visual Studio Code
|
||||
VS Code
|
||||
VSCodium
|
||||
Windsurf
|
||||
Windows Terminal
|
||||
Yarn
|
||||
Zellij
|
||||
Zed
|
||||
anomalyco
|
||||
```
|
||||
|
||||
Extracted from link labels in the English docs (review and prune as desired):
|
||||
|
||||
```text
|
||||
@openspoon/subtask2
|
||||
302.AI console
|
||||
ACP progress report
|
||||
Agent Client Protocol
|
||||
Agent Skills
|
||||
Agentic
|
||||
AGENTS.md
|
||||
AI SDK
|
||||
Alacritty
|
||||
Anthropic
|
||||
Anthropic's Data Policies
|
||||
Atom One
|
||||
Avante.nvim
|
||||
Ayu
|
||||
Azure AI Foundry
|
||||
Azure portal
|
||||
Baseten
|
||||
built-in GITHUB_TOKEN
|
||||
Bun.$
|
||||
Catppuccin
|
||||
Cerebras console
|
||||
ChatGPT Plus or Pro
|
||||
Cloudflare dashboard
|
||||
CodeCompanion.nvim
|
||||
CodeNomad
|
||||
Configuring Adapters: Environment Variables
|
||||
Context7 MCP server
|
||||
Cortecs console
|
||||
Deep Infra dashboard
|
||||
DeepSeek console
|
||||
Duo Agent Platform
|
||||
Everforest
|
||||
Fireworks AI console
|
||||
Firmware dashboard
|
||||
Ghostty
|
||||
GitLab CLI agents docs
|
||||
GitLab docs
|
||||
GitLab User Settings > Access Tokens
|
||||
Granular Rules (Object Syntax)
|
||||
Grep by Vercel
|
||||
Groq console
|
||||
Gruvbox
|
||||
Helicone
|
||||
Helicone documentation
|
||||
Helicone Header Directory
|
||||
Helicone's Model Directory
|
||||
Hugging Face Inference Providers
|
||||
Hugging Face settings
|
||||
install WSL
|
||||
IO.NET console
|
||||
JetBrains IDE
|
||||
Kanagawa
|
||||
Kitty
|
||||
MiniMax API Console
|
||||
Models.dev
|
||||
Moonshot AI console
|
||||
Nebius Token Factory console
|
||||
Nord
|
||||
OAuth
|
||||
Ollama integration docs
|
||||
OpenAI's Data Policies
|
||||
OpenChamber
|
||||
OpenCode
|
||||
OpenCode config
|
||||
OpenCode Config
|
||||
OpenCode TUI with the opencode theme
|
||||
OpenCode Web - Active Session
|
||||
OpenCode Web - New Session
|
||||
OpenCode Web - See Servers
|
||||
OpenCode Zen
|
||||
OpenCode-Obsidian
|
||||
OpenRouter dashboard
|
||||
OpenWork
|
||||
OVHcloud panel
|
||||
Pro+ subscription
|
||||
SAP BTP Cockpit
|
||||
Scaleway Console IAM settings
|
||||
Scaleway Generative APIs
|
||||
SDK documentation
|
||||
Sentry MCP server
|
||||
shell API
|
||||
Together AI console
|
||||
Tokyonight
|
||||
Unified Billing
|
||||
Venice AI console
|
||||
Vercel dashboard
|
||||
WezTerm
|
||||
Windows Subsystem for Linux (WSL)
|
||||
WSL
|
||||
WSL (Windows Subsystem for Linux)
|
||||
WSL extension
|
||||
xAI console
|
||||
Z.AI API console
|
||||
Zed
|
||||
ZenMux dashboard
|
||||
Zod
|
||||
```
|
||||
|
||||
## Acronyms and initialisms
|
||||
|
||||
```text
|
||||
ACP
|
||||
AGENTS
|
||||
AI
|
||||
AI21
|
||||
ANSI
|
||||
API
|
||||
AST
|
||||
AWS
|
||||
BTP
|
||||
CD
|
||||
CDN
|
||||
CI
|
||||
CLI
|
||||
CMD
|
||||
CORS
|
||||
DEBUG
|
||||
EKS
|
||||
ERROR
|
||||
FAQ
|
||||
GLM
|
||||
GNOME
|
||||
GPT
|
||||
HTML
|
||||
HTTP
|
||||
HTTPS
|
||||
IAM
|
||||
ID
|
||||
IDE
|
||||
INFO
|
||||
IO
|
||||
IP
|
||||
IRSA
|
||||
JS
|
||||
JSON
|
||||
JSONC
|
||||
K2
|
||||
LLM
|
||||
LM
|
||||
LSP
|
||||
M2
|
||||
MCP
|
||||
MR
|
||||
NET
|
||||
NPM
|
||||
NTLM
|
||||
OIDC
|
||||
OS
|
||||
PAT
|
||||
PATH
|
||||
PHP
|
||||
PR
|
||||
PTY
|
||||
README
|
||||
RFC
|
||||
RPC
|
||||
SAP
|
||||
SDK
|
||||
SKILL
|
||||
SSE
|
||||
SSO
|
||||
TS
|
||||
TTY
|
||||
TUI
|
||||
UI
|
||||
URL
|
||||
US
|
||||
UX
|
||||
VCS
|
||||
VPC
|
||||
VPN
|
||||
VS
|
||||
WARN
|
||||
WSL
|
||||
X11
|
||||
YAML
|
||||
```
|
||||
|
||||
## Code identifiers used in prose (CamelCase, mixedCase)
|
||||
|
||||
```text
|
||||
apiKey
|
||||
AppleScript
|
||||
AssistantMessage
|
||||
baseURL
|
||||
BurntSushi
|
||||
ChatGPT
|
||||
ClangFormat
|
||||
CodeCompanion
|
||||
CodeNomad
|
||||
DeepSeek
|
||||
DefaultV2
|
||||
FileContent
|
||||
FileDiff
|
||||
FileNode
|
||||
fineGrained
|
||||
FormatterStatus
|
||||
GitHub
|
||||
GitLab
|
||||
iTerm2
|
||||
JavaScript
|
||||
JetBrains
|
||||
macOS
|
||||
mDNS
|
||||
MiniMax
|
||||
NeuralNomadsAI
|
||||
NickvanDyke
|
||||
NoeFabris
|
||||
OpenAI
|
||||
OpenAPI
|
||||
OpenChamber
|
||||
OpenCode
|
||||
OpenRouter
|
||||
OpenTUI
|
||||
OpenWork
|
||||
ownUserPermissions
|
||||
PowerShell
|
||||
ProviderAuthAuthorization
|
||||
ProviderAuthMethod
|
||||
ProviderInitError
|
||||
SessionStatus
|
||||
TabItem
|
||||
tokenType
|
||||
ToolIDs
|
||||
ToolList
|
||||
TypeScript
|
||||
typesUrl
|
||||
UserMessage
|
||||
VcsInfo
|
||||
WebView2
|
||||
WezTerm
|
||||
xAI
|
||||
ZenMux
|
||||
```
|
||||
|
||||
## OpenCode CLI commands (as shown in docs)
|
||||
|
||||
```text
|
||||
opencode
|
||||
opencode [project]
|
||||
opencode /path/to/project
|
||||
opencode acp
|
||||
opencode agent [command]
|
||||
opencode agent create
|
||||
opencode agent list
|
||||
opencode attach [url]
|
||||
opencode attach http://10.20.30.40:4096
|
||||
opencode attach http://localhost:4096
|
||||
opencode auth [command]
|
||||
opencode auth list
|
||||
opencode auth login
|
||||
opencode auth logout
|
||||
opencode auth ls
|
||||
opencode export [sessionID]
|
||||
opencode github [command]
|
||||
opencode github install
|
||||
opencode github run
|
||||
opencode import <file>
|
||||
opencode import https://opncd.ai/s/abc123
|
||||
opencode import session.json
|
||||
opencode mcp [command]
|
||||
opencode mcp add
|
||||
opencode mcp auth [name]
|
||||
opencode mcp auth list
|
||||
opencode mcp auth ls
|
||||
opencode mcp auth my-oauth-server
|
||||
opencode mcp auth sentry
|
||||
opencode mcp debug <name>
|
||||
opencode mcp debug my-oauth-server
|
||||
opencode mcp list
|
||||
opencode mcp logout [name]
|
||||
opencode mcp logout my-oauth-server
|
||||
opencode mcp ls
|
||||
opencode models --refresh
|
||||
opencode models [provider]
|
||||
opencode models anthropic
|
||||
opencode run [message..]
|
||||
opencode run Explain the use of context in Go
|
||||
opencode serve
|
||||
opencode serve --cors http://localhost:5173 --cors https://app.example.com
|
||||
opencode serve --hostname 0.0.0.0 --port 4096
|
||||
opencode serve [--port <number>] [--hostname <string>] [--cors <origin>]
|
||||
opencode session [command]
|
||||
opencode session list
|
||||
opencode session delete <sessionID>
|
||||
opencode stats
|
||||
opencode uninstall
|
||||
opencode upgrade
|
||||
opencode upgrade [target]
|
||||
opencode upgrade v0.1.48
|
||||
opencode web
|
||||
opencode web --cors https://example.com
|
||||
opencode web --hostname 0.0.0.0
|
||||
opencode web --mdns
|
||||
opencode web --mdns --mdns-domain myproject.local
|
||||
opencode web --port 4096
|
||||
opencode web --port 4096 --hostname 0.0.0.0
|
||||
opencode.server.close()
|
||||
```
|
||||
|
||||
## Slash commands and routes
|
||||
|
||||
```text
|
||||
/agent
|
||||
/auth/:id
|
||||
/clear
|
||||
/command
|
||||
/config
|
||||
/config/providers
|
||||
/connect
|
||||
/continue
|
||||
/doc
|
||||
/editor
|
||||
/event
|
||||
/experimental/tool?provider=<p>&model=<m>
|
||||
/experimental/tool/ids
|
||||
/export
|
||||
/file?path=<path>
|
||||
/file/content?path=<p>
|
||||
/file/status
|
||||
/find?pattern=<pat>
|
||||
/find/file
|
||||
/find/file?query=<q>
|
||||
/find/symbol?query=<q>
|
||||
/formatter
|
||||
/global/event
|
||||
/global/health
|
||||
/help
|
||||
/init
|
||||
/instance/dispose
|
||||
/log
|
||||
/lsp
|
||||
/mcp
|
||||
/mnt/
|
||||
/mnt/c/
|
||||
/mnt/d/
|
||||
/models
|
||||
/oc
|
||||
/opencode
|
||||
/path
|
||||
/project
|
||||
/project/current
|
||||
/provider
|
||||
/provider/{id}/oauth/authorize
|
||||
/provider/{id}/oauth/callback
|
||||
/provider/auth
|
||||
/q
|
||||
/quit
|
||||
/redo
|
||||
/resume
|
||||
/session
|
||||
/session/:id
|
||||
/session/:id/abort
|
||||
/session/:id/children
|
||||
/session/:id/command
|
||||
/session/:id/diff
|
||||
/session/:id/fork
|
||||
/session/:id/init
|
||||
/session/:id/message
|
||||
/session/:id/message/:messageID
|
||||
/session/:id/permissions/:permissionID
|
||||
/session/:id/prompt_async
|
||||
/session/:id/revert
|
||||
/session/:id/share
|
||||
/session/:id/shell
|
||||
/session/:id/summarize
|
||||
/session/:id/todo
|
||||
/session/:id/unrevert
|
||||
/session/status
|
||||
/share
|
||||
/summarize
|
||||
/theme
|
||||
/tui
|
||||
/tui/append-prompt
|
||||
/tui/clear-prompt
|
||||
/tui/control/next
|
||||
/tui/control/response
|
||||
/tui/execute-command
|
||||
/tui/open-help
|
||||
/tui/open-models
|
||||
/tui/open-sessions
|
||||
/tui/open-themes
|
||||
/tui/show-toast
|
||||
/tui/submit-prompt
|
||||
/undo
|
||||
/Users/username
|
||||
/Users/username/projects/*
|
||||
/vcs
|
||||
```
|
||||
|
||||
## CLI flags and short options
|
||||
|
||||
```text
|
||||
--agent
|
||||
--attach
|
||||
--command
|
||||
--continue
|
||||
--cors
|
||||
--cwd
|
||||
--days
|
||||
--dir
|
||||
--dry-run
|
||||
--event
|
||||
--file
|
||||
--force
|
||||
--fork
|
||||
--format
|
||||
--help
|
||||
--hostname
|
||||
--hostname 0.0.0.0
|
||||
--keep-config
|
||||
--keep-data
|
||||
--log-level
|
||||
--max-count
|
||||
--mdns
|
||||
--mdns-domain
|
||||
--method
|
||||
--model
|
||||
--models
|
||||
--port
|
||||
--print-logs
|
||||
--project
|
||||
--prompt
|
||||
--refresh
|
||||
--session
|
||||
--share
|
||||
--title
|
||||
--token
|
||||
--tools
|
||||
--verbose
|
||||
--version
|
||||
--wait
|
||||
|
||||
-c
|
||||
-d
|
||||
-f
|
||||
-h
|
||||
-m
|
||||
-n
|
||||
-s
|
||||
-v
|
||||
```
|
||||
|
||||
## Environment variables
|
||||
|
||||
```text
|
||||
AI_API_URL
|
||||
AI_FLOW_CONTEXT
|
||||
AI_FLOW_EVENT
|
||||
AI_FLOW_INPUT
|
||||
AICORE_DEPLOYMENT_ID
|
||||
AICORE_RESOURCE_GROUP
|
||||
AICORE_SERVICE_KEY
|
||||
ANTHROPIC_API_KEY
|
||||
AWS_ACCESS_KEY_ID
|
||||
AWS_BEARER_TOKEN_BEDROCK
|
||||
AWS_PROFILE
|
||||
AWS_REGION
|
||||
AWS_ROLE_ARN
|
||||
AWS_SECRET_ACCESS_KEY
|
||||
AWS_WEB_IDENTITY_TOKEN_FILE
|
||||
AZURE_COGNITIVE_SERVICES_RESOURCE_NAME
|
||||
AZURE_RESOURCE_NAME
|
||||
CI_PROJECT_DIR
|
||||
CI_SERVER_FQDN
|
||||
CI_WORKLOAD_REF
|
||||
CLOUDFLARE_ACCOUNT_ID
|
||||
CLOUDFLARE_API_TOKEN
|
||||
CLOUDFLARE_GATEWAY_ID
|
||||
CONTEXT7_API_KEY
|
||||
GITHUB_TOKEN
|
||||
GITLAB_AI_GATEWAY_URL
|
||||
GITLAB_HOST
|
||||
GITLAB_INSTANCE_URL
|
||||
GITLAB_OAUTH_CLIENT_ID
|
||||
GITLAB_TOKEN
|
||||
GITLAB_TOKEN_OPENCODE
|
||||
GOOGLE_APPLICATION_CREDENTIALS
|
||||
GOOGLE_CLOUD_PROJECT
|
||||
HTTP_PROXY
|
||||
HTTPS_PROXY
|
||||
K2_
|
||||
MY_API_KEY
|
||||
MY_ENV_VAR
|
||||
MY_MCP_CLIENT_ID
|
||||
MY_MCP_CLIENT_SECRET
|
||||
NO_PROXY
|
||||
NODE_ENV
|
||||
NODE_EXTRA_CA_CERTS
|
||||
NPM_AUTH_TOKEN
|
||||
OC_ALLOW_WAYLAND
|
||||
OPENCODE_API_KEY
|
||||
OPENCODE_AUTH_JSON
|
||||
OPENCODE_AUTO_SHARE
|
||||
OPENCODE_CLIENT
|
||||
OPENCODE_CONFIG
|
||||
OPENCODE_CONFIG_CONTENT
|
||||
OPENCODE_CONFIG_DIR
|
||||
OPENCODE_DISABLE_AUTOCOMPACT
|
||||
OPENCODE_DISABLE_AUTOUPDATE
|
||||
OPENCODE_DISABLE_CLAUDE_CODE
|
||||
OPENCODE_DISABLE_CLAUDE_CODE_PROMPT
|
||||
OPENCODE_DISABLE_CLAUDE_CODE_SKILLS
|
||||
OPENCODE_DISABLE_DEFAULT_PLUGINS
|
||||
OPENCODE_DISABLE_LSP_DOWNLOAD
|
||||
OPENCODE_DISABLE_MODELS_FETCH
|
||||
OPENCODE_DISABLE_PRUNE
|
||||
OPENCODE_DISABLE_TERMINAL_TITLE
|
||||
OPENCODE_ENABLE_EXA
|
||||
OPENCODE_ENABLE_EXPERIMENTAL_MODELS
|
||||
OPENCODE_EXPERIMENTAL
|
||||
OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS
|
||||
OPENCODE_EXPERIMENTAL_DISABLE_COPY_ON_SELECT
|
||||
OPENCODE_EXPERIMENTAL_DISABLE_FILEWATCHER
|
||||
OPENCODE_EXPERIMENTAL_EXA
|
||||
OPENCODE_EXPERIMENTAL_FILEWATCHER
|
||||
OPENCODE_EXPERIMENTAL_ICON_DISCOVERY
|
||||
OPENCODE_EXPERIMENTAL_LSP_TOOL
|
||||
OPENCODE_EXPERIMENTAL_LSP_TY
|
||||
OPENCODE_EXPERIMENTAL_MARKDOWN
|
||||
OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX
|
||||
OPENCODE_EXPERIMENTAL_OXFMT
|
||||
OPENCODE_EXPERIMENTAL_PLAN_MODE
|
||||
OPENCODE_ENABLE_QUESTION_TOOL
|
||||
OPENCODE_FAKE_VCS
|
||||
OPENCODE_GIT_BASH_PATH
|
||||
OPENCODE_MODEL
|
||||
OPENCODE_MODELS_URL
|
||||
OPENCODE_PERMISSION
|
||||
OPENCODE_PORT
|
||||
OPENCODE_SERVER_PASSWORD
|
||||
OPENCODE_SERVER_USERNAME
|
||||
PROJECT_ROOT
|
||||
RESOURCE_NAME
|
||||
RUST_LOG
|
||||
VARIABLE_NAME
|
||||
VERTEX_LOCATION
|
||||
XDG_CONFIG_HOME
|
||||
```
|
||||
|
||||
## Package/module identifiers
|
||||
|
||||
```text
|
||||
../../../config.mjs
|
||||
@astrojs/starlight/components
|
||||
@opencode-ai/plugin
|
||||
@opencode-ai/sdk
|
||||
path
|
||||
shescape
|
||||
zod
|
||||
|
||||
@
|
||||
@ai-sdk/anthropic
|
||||
@ai-sdk/cerebras
|
||||
@ai-sdk/google
|
||||
@ai-sdk/openai
|
||||
@ai-sdk/openai-compatible
|
||||
@File#L37-42
|
||||
@modelcontextprotocol/server-everything
|
||||
@opencode
|
||||
```
|
||||
|
||||
## GitHub owner/repo slugs referenced in docs
|
||||
|
||||
```text
|
||||
24601/opencode-zellij-namer
|
||||
angristan/opencode-wakatime
|
||||
anomalyco/opencode
|
||||
apps/opencode-agent
|
||||
athal7/opencode-devcontainers
|
||||
awesome-opencode/awesome-opencode
|
||||
backnotprop/plannotator
|
||||
ben-vargas/ai-sdk-provider-opencode-sdk
|
||||
btriapitsyn/openchamber
|
||||
BurntSushi/ripgrep
|
||||
Cluster444/agentic
|
||||
code-yeongyu/oh-my-opencode
|
||||
darrenhinde/opencode-agents
|
||||
different-ai/opencode-scheduler
|
||||
different-ai/openwork
|
||||
features/copilot
|
||||
folke/tokyonight.nvim
|
||||
franlol/opencode-md-table-formatter
|
||||
ggml-org/llama.cpp
|
||||
ghoulr/opencode-websearch-cited.git
|
||||
H2Shami/opencode-helicone-session
|
||||
hosenur/portal
|
||||
jamesmurdza/daytona
|
||||
jenslys/opencode-gemini-auth
|
||||
JRedeker/opencode-morph-fast-apply
|
||||
JRedeker/opencode-shell-strategy
|
||||
kdcokenny/ocx
|
||||
kdcokenny/opencode-background-agents
|
||||
kdcokenny/opencode-notify
|
||||
kdcokenny/opencode-workspace
|
||||
kdcokenny/opencode-worktree
|
||||
login/device
|
||||
mohak34/opencode-notifier
|
||||
morhetz/gruvbox
|
||||
mtymek/opencode-obsidian
|
||||
NeuralNomadsAI/CodeNomad
|
||||
nick-vi/opencode-type-inject
|
||||
NickvanDyke/opencode.nvim
|
||||
NoeFabris/opencode-antigravity-auth
|
||||
nordtheme/nord
|
||||
numman-ali/opencode-openai-codex-auth
|
||||
olimorris/codecompanion.nvim
|
||||
panta82/opencode-notificator
|
||||
rebelot/kanagawa.nvim
|
||||
remorses/kimaki
|
||||
sainnhe/everforest
|
||||
shekohex/opencode-google-antigravity-auth
|
||||
shekohex/opencode-pty.git
|
||||
spoons-and-mirrors/subtask2
|
||||
sudo-tee/opencode.nvim
|
||||
supermemoryai/opencode-supermemory
|
||||
Tarquinen/opencode-dynamic-context-pruning
|
||||
Th3Whit3Wolf/one-nvim
|
||||
upstash/context7
|
||||
vtemian/micode
|
||||
vtemian/octto
|
||||
yetone/avante.nvim
|
||||
zenobi-us/opencode-plugin-template
|
||||
zenobi-us/opencode-skillful
|
||||
```
|
||||
|
||||
## Paths, filenames, globs, and URLs
|
||||
|
||||
```text
|
||||
./.opencode/themes/*.json
|
||||
./<project-slug>/storage/
|
||||
./config/#custom-directory
|
||||
./global/storage/
|
||||
.agents/skills/*/SKILL.md
|
||||
.agents/skills/<name>/SKILL.md
|
||||
.clang-format
|
||||
.claude
|
||||
.claude/skills
|
||||
.claude/skills/*/SKILL.md
|
||||
.claude/skills/<name>/SKILL.md
|
||||
.env
|
||||
.github/workflows/opencode.yml
|
||||
.gitignore
|
||||
.gitlab-ci.yml
|
||||
.ignore
|
||||
.NET SDK
|
||||
.npmrc
|
||||
.ocamlformat
|
||||
.opencode
|
||||
.opencode/
|
||||
.opencode/agents/
|
||||
.opencode/commands/
|
||||
.opencode/commands/test.md
|
||||
.opencode/modes/
|
||||
.opencode/plans/*.md
|
||||
.opencode/plugins/
|
||||
.opencode/skills/<name>/SKILL.md
|
||||
.opencode/skills/git-release/SKILL.md
|
||||
.opencode/tools/
|
||||
.well-known/opencode
|
||||
{ type: "raw" \| "patch", content: string }
|
||||
{file:path/to/file}
|
||||
**/*.js
|
||||
%USERPROFILE%/intelephense/license.txt
|
||||
%USERPROFILE%\.cache\opencode
|
||||
%USERPROFILE%\.config\opencode\opencode.jsonc
|
||||
%USERPROFILE%\.config\opencode\plugins
|
||||
%USERPROFILE%\.local\share\opencode
|
||||
%USERPROFILE%\.local\share\opencode\log
|
||||
<project-root>/.opencode/themes/*.json
|
||||
<providerId>/<modelId>
|
||||
<your-project>/.opencode/plugins/
|
||||
~
|
||||
~/...
|
||||
~/.agents/skills/*/SKILL.md
|
||||
~/.agents/skills/<name>/SKILL.md
|
||||
~/.aws/credentials
|
||||
~/.bashrc
|
||||
~/.cache/opencode
|
||||
~/.cache/opencode/node_modules/
|
||||
~/.claude/CLAUDE.md
|
||||
~/.claude/skills/
|
||||
~/.claude/skills/*/SKILL.md
|
||||
~/.claude/skills/<name>/SKILL.md
|
||||
~/.config/opencode
|
||||
~/.config/opencode/AGENTS.md
|
||||
~/.config/opencode/agents/
|
||||
~/.config/opencode/commands/
|
||||
~/.config/opencode/modes/
|
||||
~/.config/opencode/opencode.json
|
||||
~/.config/opencode/opencode.jsonc
|
||||
~/.config/opencode/plugins/
|
||||
~/.config/opencode/skills/*/SKILL.md
|
||||
~/.config/opencode/skills/<name>/SKILL.md
|
||||
~/.config/opencode/themes/*.json
|
||||
~/.config/opencode/tools/
|
||||
~/.config/zed/settings.json
|
||||
~/.local/share
|
||||
~/.local/share/opencode/
|
||||
~/.local/share/opencode/auth.json
|
||||
~/.local/share/opencode/log/
|
||||
~/.local/share/opencode/mcp-auth.json
|
||||
~/.local/share/opencode/opencode.jsonc
|
||||
~/.npmrc
|
||||
~/.zshrc
|
||||
~/code/
|
||||
~/Library/Application Support
|
||||
~/projects/*
|
||||
~/projects/personal/
|
||||
${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts
|
||||
$HOME/intelephense/license.txt
|
||||
$HOME/projects/*
|
||||
$XDG_CONFIG_HOME/opencode/themes/*.json
|
||||
agent/
|
||||
agents/
|
||||
build/
|
||||
commands/
|
||||
dist/
|
||||
http://<wsl-ip>:4096
|
||||
http://127.0.0.1:8080/callback
|
||||
http://localhost:<port>
|
||||
http://localhost:4096
|
||||
http://localhost:4096/doc
|
||||
https://app.example.com
|
||||
https://AZURE_COGNITIVE_SERVICES_RESOURCE_NAME.cognitiveservices.azure.com/
|
||||
https://opencode.ai/zen/v1/chat/completions
|
||||
https://opencode.ai/zen/v1/messages
|
||||
https://opencode.ai/zen/v1/models/gemini-3-flash
|
||||
https://opencode.ai/zen/v1/models/gemini-3-pro
|
||||
https://opencode.ai/zen/v1/responses
|
||||
https://RESOURCE_NAME.openai.azure.com/
|
||||
laravel/pint
|
||||
log/
|
||||
model: "anthropic/claude-sonnet-4-5"
|
||||
modes/
|
||||
node_modules/
|
||||
openai/gpt-4.1
|
||||
opencode.ai/config.json
|
||||
opencode/<model-id>
|
||||
opencode/gpt-5.1-codex
|
||||
opencode/gpt-5.2-codex
|
||||
opencode/kimi-k2
|
||||
openrouter/google/gemini-2.5-flash
|
||||
opncd.ai/s/<share-id>
|
||||
packages/*/AGENTS.md
|
||||
plugins/
|
||||
project/
|
||||
provider_id/model_id
|
||||
provider/model
|
||||
provider/model-id
|
||||
rm -rf ~/.cache/opencode
|
||||
skills/
|
||||
skills/*/SKILL.md
|
||||
src/**/*.ts
|
||||
themes/
|
||||
tools/
|
||||
```
|
||||
|
||||
## Keybind strings
|
||||
|
||||
```text
|
||||
alt+b
|
||||
Alt+Ctrl+K
|
||||
alt+d
|
||||
alt+f
|
||||
Cmd+Esc
|
||||
Cmd+Option+K
|
||||
Cmd+Shift+Esc
|
||||
Cmd+Shift+G
|
||||
Cmd+Shift+P
|
||||
ctrl+a
|
||||
ctrl+b
|
||||
ctrl+d
|
||||
ctrl+e
|
||||
Ctrl+Esc
|
||||
ctrl+f
|
||||
ctrl+g
|
||||
ctrl+k
|
||||
Ctrl+Shift+Esc
|
||||
Ctrl+Shift+P
|
||||
ctrl+t
|
||||
ctrl+u
|
||||
ctrl+w
|
||||
ctrl+x
|
||||
DELETE
|
||||
Shift+Enter
|
||||
WIN+R
|
||||
```
|
||||
|
||||
## Model ID strings referenced
|
||||
|
||||
```text
|
||||
{env:OPENCODE_MODEL}
|
||||
anthropic/claude-3-5-sonnet-20241022
|
||||
anthropic/claude-haiku-4-20250514
|
||||
anthropic/claude-haiku-4-5
|
||||
anthropic/claude-sonnet-4-20250514
|
||||
anthropic/claude-sonnet-4-5
|
||||
gitlab/duo-chat-haiku-4-5
|
||||
lmstudio/google/gemma-3n-e4b
|
||||
openai/gpt-4.1
|
||||
openai/gpt-5
|
||||
opencode/gpt-5.1-codex
|
||||
opencode/gpt-5.2-codex
|
||||
opencode/kimi-k2
|
||||
openrouter/google/gemini-2.5-flash
|
||||
```
|
||||
@@ -0,0 +1,14 @@
|
||||
---
|
||||
description: translate English to other languages
|
||||
model: opencode/claude-opus-4-7
|
||||
---
|
||||
|
||||
run git diff and translate changed english doc and UI copy files to other international languages. Translate all languages in parallel to save time.
|
||||
|
||||
Requirements:
|
||||
|
||||
- Preserve meaning, intent, tone, and formatting (including Markdown/MDX structure).
|
||||
- Preserve all technical terms and artifacts exactly: product/company names, API names, identifiers, code, commands/flags, file paths, URLs, versions, error messages, config keys/values, and anything inside inline code or code blocks.
|
||||
- Also preserve every term listed in the Do-Not-Translate glossary below.
|
||||
- Also apply locale-specific guidance from `.opencode/glossary/<locale>.md` when available (for example, `zh-cn.md`).
|
||||
- Do not modify fenced code blocks.
|
||||
@@ -3,8 +3,8 @@ import { tool } from "@opencode-ai/plugin"
|
||||
const TEAM = {
|
||||
desktop: ["adamdotdevin", "iamdavidhill", "Brendonovich", "nexxeln"],
|
||||
zen: ["fwang", "MrMushrooooom"],
|
||||
tui: ["thdxr", "kommander", "rekram1-node"],
|
||||
core: ["thdxr", "rekram1-node", "jlongster"],
|
||||
tui: ["kommander", "rekram1-node", "simonklee"],
|
||||
core: ["kitlangton", "rekram1-node", "jlongster"],
|
||||
docs: ["R44VC0RP"],
|
||||
windows: ["Hona"],
|
||||
} as const
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
},
|
||||
"packages/app": {
|
||||
"name": "@opencode-ai/app",
|
||||
"version": "1.14.25",
|
||||
"version": "1.14.29",
|
||||
"dependencies": {
|
||||
"@kobalte/core": "catalog:",
|
||||
"@opencode-ai/core": "workspace:*",
|
||||
@@ -83,7 +83,7 @@
|
||||
},
|
||||
"packages/console/app": {
|
||||
"name": "@opencode-ai/console-app",
|
||||
"version": "1.14.25",
|
||||
"version": "1.14.29",
|
||||
"dependencies": {
|
||||
"@cloudflare/vite-plugin": "1.15.2",
|
||||
"@ibm/plex": "6.4.1",
|
||||
@@ -117,7 +117,7 @@
|
||||
},
|
||||
"packages/console/core": {
|
||||
"name": "@opencode-ai/console-core",
|
||||
"version": "1.14.25",
|
||||
"version": "1.14.29",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-sts": "3.782.0",
|
||||
"@jsx-email/render": "1.1.1",
|
||||
@@ -144,7 +144,7 @@
|
||||
},
|
||||
"packages/console/function": {
|
||||
"name": "@opencode-ai/console-function",
|
||||
"version": "1.14.25",
|
||||
"version": "1.14.29",
|
||||
"dependencies": {
|
||||
"@ai-sdk/anthropic": "3.0.64",
|
||||
"@ai-sdk/openai": "3.0.48",
|
||||
@@ -168,7 +168,7 @@
|
||||
},
|
||||
"packages/console/mail": {
|
||||
"name": "@opencode-ai/console-mail",
|
||||
"version": "1.14.25",
|
||||
"version": "1.14.29",
|
||||
"dependencies": {
|
||||
"@jsx-email/all": "2.2.3",
|
||||
"@jsx-email/cli": "1.4.3",
|
||||
@@ -192,7 +192,7 @@
|
||||
},
|
||||
"packages/core": {
|
||||
"name": "@opencode-ai/core",
|
||||
"version": "1.14.25",
|
||||
"version": "1.14.29",
|
||||
"bin": {
|
||||
"opencode": "./bin/opencode",
|
||||
},
|
||||
@@ -226,7 +226,7 @@
|
||||
},
|
||||
"packages/desktop": {
|
||||
"name": "@opencode-ai/desktop",
|
||||
"version": "1.14.25",
|
||||
"version": "1.14.29",
|
||||
"dependencies": {
|
||||
"@opencode-ai/app": "workspace:*",
|
||||
"@opencode-ai/ui": "workspace:*",
|
||||
@@ -259,7 +259,7 @@
|
||||
},
|
||||
"packages/desktop-electron": {
|
||||
"name": "@opencode-ai/desktop-electron",
|
||||
"version": "1.14.25",
|
||||
"version": "1.14.29",
|
||||
"dependencies": {
|
||||
"drizzle-orm": "catalog:",
|
||||
"effect": "catalog:",
|
||||
@@ -303,7 +303,7 @@
|
||||
},
|
||||
"packages/enterprise": {
|
||||
"name": "@opencode-ai/enterprise",
|
||||
"version": "1.14.25",
|
||||
"version": "1.14.29",
|
||||
"dependencies": {
|
||||
"@opencode-ai/core": "workspace:*",
|
||||
"@opencode-ai/ui": "workspace:*",
|
||||
@@ -332,7 +332,7 @@
|
||||
},
|
||||
"packages/function": {
|
||||
"name": "@opencode-ai/function",
|
||||
"version": "1.14.25",
|
||||
"version": "1.14.29",
|
||||
"dependencies": {
|
||||
"@octokit/auth-app": "8.0.1",
|
||||
"@octokit/rest": "catalog:",
|
||||
@@ -348,7 +348,7 @@
|
||||
},
|
||||
"packages/opencode": {
|
||||
"name": "opencode",
|
||||
"version": "1.14.25",
|
||||
"version": "1.14.29",
|
||||
"bin": {
|
||||
"opencode": "./bin/opencode",
|
||||
},
|
||||
@@ -393,7 +393,7 @@
|
||||
"@opencode-ai/plugin": "workspace:*",
|
||||
"@opencode-ai/script": "workspace:*",
|
||||
"@opencode-ai/sdk": "workspace:*",
|
||||
"@openrouter/ai-sdk-provider": "2.5.1",
|
||||
"@openrouter/ai-sdk-provider": "2.8.1",
|
||||
"@opentelemetry/api": "1.9.0",
|
||||
"@opentelemetry/context-async-hooks": "2.6.1",
|
||||
"@opentelemetry/exporter-trace-otlp-http": "0.214.0",
|
||||
@@ -491,7 +491,7 @@
|
||||
},
|
||||
"packages/plugin": {
|
||||
"name": "@opencode-ai/plugin",
|
||||
"version": "1.14.25",
|
||||
"version": "1.14.29",
|
||||
"dependencies": {
|
||||
"@opencode-ai/sdk": "workspace:*",
|
||||
"effect": "catalog:",
|
||||
@@ -506,8 +506,8 @@
|
||||
"typescript": "catalog:",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@opentui/core": ">=0.1.103",
|
||||
"@opentui/solid": ">=0.1.103",
|
||||
"@opentui/core": ">=0.1.105",
|
||||
"@opentui/solid": ">=0.1.105",
|
||||
},
|
||||
"optionalPeers": [
|
||||
"@opentui/core",
|
||||
@@ -526,7 +526,7 @@
|
||||
},
|
||||
"packages/sdk/js": {
|
||||
"name": "@opencode-ai/sdk",
|
||||
"version": "1.14.25",
|
||||
"version": "1.14.29",
|
||||
"dependencies": {
|
||||
"cross-spawn": "catalog:",
|
||||
},
|
||||
@@ -541,7 +541,7 @@
|
||||
},
|
||||
"packages/slack": {
|
||||
"name": "@opencode-ai/slack",
|
||||
"version": "1.14.25",
|
||||
"version": "1.14.29",
|
||||
"dependencies": {
|
||||
"@opencode-ai/sdk": "workspace:*",
|
||||
"@slack/bolt": "^3.17.1",
|
||||
@@ -576,7 +576,7 @@
|
||||
},
|
||||
"packages/ui": {
|
||||
"name": "@opencode-ai/ui",
|
||||
"version": "1.14.25",
|
||||
"version": "1.14.29",
|
||||
"dependencies": {
|
||||
"@kobalte/core": "catalog:",
|
||||
"@opencode-ai/core": "workspace:*",
|
||||
@@ -625,7 +625,7 @@
|
||||
},
|
||||
"packages/web": {
|
||||
"name": "@opencode-ai/web",
|
||||
"version": "1.14.25",
|
||||
"version": "1.14.29",
|
||||
"dependencies": {
|
||||
"@astrojs/cloudflare": "12.6.3",
|
||||
"@astrojs/markdown-remark": "6.3.1",
|
||||
@@ -677,16 +677,16 @@
|
||||
},
|
||||
"catalog": {
|
||||
"@cloudflare/workers-types": "4.20251008.0",
|
||||
"@effect/opentelemetry": "4.0.0-beta.48",
|
||||
"@effect/platform-node": "4.0.0-beta.48",
|
||||
"@effect/opentelemetry": "4.0.0-beta.57",
|
||||
"@effect/platform-node": "4.0.0-beta.57",
|
||||
"@hono/zod-validator": "0.4.2",
|
||||
"@kobalte/core": "0.13.11",
|
||||
"@lydell/node-pty": "1.2.0-beta.10",
|
||||
"@npmcli/arborist": "9.4.0",
|
||||
"@octokit/rest": "22.0.0",
|
||||
"@openauthjs/openauth": "0.0.0-20250322224806",
|
||||
"@opentui/core": "0.1.103",
|
||||
"@opentui/solid": "0.1.103",
|
||||
"@opentui/core": "0.1.105",
|
||||
"@opentui/solid": "0.1.105",
|
||||
"@pierre/diffs": "1.1.0-beta.18",
|
||||
"@playwright/test": "1.59.1",
|
||||
"@solid-primitives/storage": "4.3.3",
|
||||
@@ -708,7 +708,7 @@
|
||||
"dompurify": "3.3.1",
|
||||
"drizzle-kit": "1.0.0-beta.19-d95b7a4",
|
||||
"drizzle-orm": "1.0.0-beta.19-d95b7a4",
|
||||
"effect": "4.0.0-beta.48",
|
||||
"effect": "4.0.0-beta.57",
|
||||
"fuzzysort": "3.1.0",
|
||||
"hono": "4.10.7",
|
||||
"hono-openapi": "1.1.2",
|
||||
@@ -1071,11 +1071,11 @@
|
||||
|
||||
"@effect/language-service": ["@effect/language-service@0.84.2", "", { "bin": { "effect-language-service": "cli.js" } }, "sha512-l04qNxpiA8rY5yXWckRPJ7Mk5MNerXuNymSFf+IdflfI5i8jgL1bpBNLuP6ijg7wgjdHc/KmTnCj2kT0SCntuA=="],
|
||||
|
||||
"@effect/opentelemetry": ["@effect/opentelemetry@4.0.0-beta.48", "", { "peerDependencies": { "@opentelemetry/api": "^1.9", "@opentelemetry/resources": "^2.0.0", "@opentelemetry/sdk-logs": ">=0.203.0 <0.300.0", "@opentelemetry/sdk-metrics": "^2.0.0", "@opentelemetry/sdk-trace-base": "^2.0.0", "@opentelemetry/sdk-trace-node": "^2.0.0", "@opentelemetry/sdk-trace-web": "^2.0.0", "@opentelemetry/semantic-conventions": "^1.33.0", "effect": "^4.0.0-beta.48" }, "optionalPeers": ["@opentelemetry/api", "@opentelemetry/resources", "@opentelemetry/sdk-logs", "@opentelemetry/sdk-metrics", "@opentelemetry/sdk-trace-base", "@opentelemetry/sdk-trace-node", "@opentelemetry/sdk-trace-web"] }, "sha512-vHk/X1vgDrviGcOTHQqzm2D81TtyPE/C7Qdksg5eAdbGpnqL4Dm4lk6PzTReQ0pO1/avIvWqpxy315IURV0Ldw=="],
|
||||
"@effect/opentelemetry": ["@effect/opentelemetry@4.0.0-beta.57", "", { "peerDependencies": { "@opentelemetry/api": "^1.9", "@opentelemetry/resources": "^2.0.0", "@opentelemetry/sdk-logs": ">=0.203.0 <0.300.0", "@opentelemetry/sdk-metrics": "^2.0.0", "@opentelemetry/sdk-trace-base": "^2.0.0", "@opentelemetry/sdk-trace-node": "^2.0.0", "@opentelemetry/sdk-trace-web": "^2.0.0", "@opentelemetry/semantic-conventions": "^1.33.0", "effect": "^4.0.0-beta.57" }, "optionalPeers": ["@opentelemetry/api", "@opentelemetry/resources", "@opentelemetry/sdk-logs", "@opentelemetry/sdk-metrics", "@opentelemetry/sdk-trace-base", "@opentelemetry/sdk-trace-node", "@opentelemetry/sdk-trace-web"] }, "sha512-gdjZPEP0QQg4qmI1vd+443kheeQZKytrjJIzCJncy6ZEpyk/SfrqeStLqLXdTRcms3IB0ls0vOV7KNq7YmBRVA=="],
|
||||
|
||||
"@effect/platform-node": ["@effect/platform-node@4.0.0-beta.48", "", { "dependencies": { "@effect/platform-node-shared": "^4.0.0-beta.48", "mime": "^4.1.0", "undici": "^8.0.2" }, "peerDependencies": { "effect": "^4.0.0-beta.48", "ioredis": "^5.7.0" } }, "sha512-8J6H0k9rtbp9O1QvKOyOPRcCTJ8WrR7IzZLJtYFTZ4bXVEEMCTo84h0CRpi7ccpA9t7DLqotip0NeFgiBosNKQ=="],
|
||||
"@effect/platform-node": ["@effect/platform-node@4.0.0-beta.57", "", { "dependencies": { "@effect/platform-node-shared": "^4.0.0-beta.57", "mime": "^4.1.0", "undici": "^8.0.2" }, "peerDependencies": { "effect": "^4.0.0-beta.57", "ioredis": "^5.7.0" } }, "sha512-la0xxPSAYOsY0d+uVxEBxok3jYB31iPQmIaZZRUj2SNWqcGGHJc6KorKtI8guqSLuv9FGZ255kBWXRbG6hMeeg=="],
|
||||
|
||||
"@effect/platform-node-shared": ["@effect/platform-node-shared@4.0.0-beta.48", "", { "dependencies": { "@types/ws": "^8.18.1", "ws": "^8.20.0" }, "peerDependencies": { "effect": "^4.0.0-beta.48" } }, "sha512-wlhcdDHyacydCgiWdM8JwtQkViQhZsC8uJZ9wMoZXYxlCTvqfdzLeWw4A1UVMoq7sS6/KR1aZVeFkUjrqonncQ=="],
|
||||
"@effect/platform-node-shared": ["@effect/platform-node-shared@4.0.0-beta.57", "", { "dependencies": { "@types/ws": "^8.18.1", "ws": "^8.20.0" }, "peerDependencies": { "effect": "^4.0.0-beta.57" } }, "sha512-C976X6f+qHUtLSqcqImuCrjhAHnJV17NC2RvvybsAuDfkyIWU4MyiO2XwgiBeijeNupyr1M/KPKnyjtkNxV9Hw=="],
|
||||
|
||||
"@electron/asar": ["@electron/asar@3.4.1", "", { "dependencies": { "commander": "^5.0.0", "glob": "^7.1.6", "minimatch": "^3.0.4" }, "bin": { "asar": "bin/asar.js" } }, "sha512-i4/rNPRS84t0vSRa2HorerGRXWyF4vThfHesw0dmcWHp+cspK743UanA0suA5Q5y8kzY2y6YKrvbIUn69BCAiA=="],
|
||||
|
||||
@@ -1585,7 +1585,7 @@
|
||||
|
||||
"@opencode-ai/web": ["@opencode-ai/web@workspace:packages/web"],
|
||||
|
||||
"@openrouter/ai-sdk-provider": ["@openrouter/ai-sdk-provider@2.5.1", "", { "peerDependencies": { "ai": "^6.0.0", "zod": "^3.25.0 || ^4.0.0" } }, "sha512-r1fJL1Cb3gQDa2MpWH/sfx1BsEW0uzlRriJM6eihaKqbtKDmZoBisF32VcVaQYassighX7NGCkF68EsrZA43uQ=="],
|
||||
"@openrouter/ai-sdk-provider": ["@openrouter/ai-sdk-provider@2.8.1", "", { "peerDependencies": { "ai": "^6.0.0", "zod": "^3.25.0 || ^4.0.0" } }, "sha512-Y6j3yivgoEUf/kutD/k5GX/mzZfioRFoSx0gbQ+mIOzMaH/vJv1rCkztiuvlLw5xRYQil7oxHUZvmSfXqOx1NQ=="],
|
||||
|
||||
"@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="],
|
||||
|
||||
@@ -1601,7 +1601,7 @@
|
||||
|
||||
"@opentelemetry/otlp-transformer": ["@opentelemetry/otlp-transformer@0.214.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.214.0", "@opentelemetry/core": "2.6.1", "@opentelemetry/resources": "2.6.1", "@opentelemetry/sdk-logs": "0.214.0", "@opentelemetry/sdk-metrics": "2.6.1", "@opentelemetry/sdk-trace-base": "2.6.1", "protobufjs": "^7.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-DSaYcuBRh6uozfsWN3R8HsN0yDhCuWP7tOFdkUOVaWD1KVJg8m4qiLUsg/tNhTLS9HUYUcwNpwL2eroLtsZZ/w=="],
|
||||
|
||||
"@opentelemetry/resources": ["@opentelemetry/resources@2.2.0", "", { "dependencies": { "@opentelemetry/core": "2.2.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A=="],
|
||||
"@opentelemetry/resources": ["@opentelemetry/resources@2.6.1", "", { "dependencies": { "@opentelemetry/core": "2.6.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-lID/vxSuKWXM55XhAKNoYXu9Cutoq5hFdkbTdI/zDKQktXzcWBVhNsOkiZFTMU9UtEWuGRNe0HUgmsFldIdxVA=="],
|
||||
|
||||
"@opentelemetry/sdk-logs": ["@opentelemetry/sdk-logs@0.214.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.214.0", "@opentelemetry/core": "2.6.1", "@opentelemetry/resources": "2.6.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.4.0 <1.10.0" } }, "sha512-zf6acnScjhsaBUU22zXZ/sLWim1dfhUAbGXdMmHmNG3LfBnQ3DKsOCITb2IZwoUsNNMTogqFKBnlIPPftUgGwA=="],
|
||||
|
||||
@@ -1613,21 +1613,21 @@
|
||||
|
||||
"@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.40.0", "", {}, "sha512-cifvXDhcqMwwTlTK04GBNeIe7yyo28Mfby85QXFe1Yk8nmi36Ab/5UQwptOx84SsoGNRg+EVSjwzfSZMy6pmlw=="],
|
||||
|
||||
"@opentui/core": ["@opentui/core@0.1.103", "", { "dependencies": { "bun-ffi-structs": "0.1.2", "diff": "8.0.2", "jimp": "1.6.0", "marked": "17.0.1", "yoga-layout": "3.2.1" }, "optionalDependencies": { "@dimforge/rapier2d-simd-compat": "^0.17.3", "@opentui/core-darwin-arm64": "0.1.103", "@opentui/core-darwin-x64": "0.1.103", "@opentui/core-linux-arm64": "0.1.103", "@opentui/core-linux-x64": "0.1.103", "@opentui/core-win32-arm64": "0.1.103", "@opentui/core-win32-x64": "0.1.103", "bun-webgpu": "0.1.5", "planck": "^1.4.2", "three": "0.177.0" }, "peerDependencies": { "web-tree-sitter": "0.25.10" } }, "sha512-PWVv/bDmlk1i6X1f0zXs+jSaTrQ/ByX8wFbP2WinOObTGf//UbcRP4dbWxPXvOyka9QlmRBG/7GbloQSIStyVw=="],
|
||||
"@opentui/core": ["@opentui/core@0.1.105", "", { "dependencies": { "bun-ffi-structs": "0.1.2", "diff": "8.0.2", "jimp": "1.6.0", "marked": "17.0.1", "yoga-layout": "3.2.1" }, "optionalDependencies": { "@dimforge/rapier2d-simd-compat": "^0.17.3", "@opentui/core-darwin-arm64": "0.1.105", "@opentui/core-darwin-x64": "0.1.105", "@opentui/core-linux-arm64": "0.1.105", "@opentui/core-linux-x64": "0.1.105", "@opentui/core-win32-arm64": "0.1.105", "@opentui/core-win32-x64": "0.1.105", "bun-webgpu": "0.1.5", "planck": "^1.4.2", "three": "0.177.0" }, "peerDependencies": { "web-tree-sitter": "0.25.10" } }, "sha512-vllSOOCW6VIThV/96GRLJ1IxIBuR+ci6FDvnPIAG4s7SJ/FW6zAkqDn1xrtBwwk/lM3QWjLqy8BZc+zwWvveJA=="],
|
||||
|
||||
"@opentui/core-darwin-arm64": ["@opentui/core-darwin-arm64@0.1.103", "", { "os": "darwin", "cpu": "arm64" }, "sha512-lxCyedDkcen12IgBtXjkJ7iY66xa7VC4nxRNKCUeLY2ZP9hUE1AsDtbyQzqY+BQadsI/ZME9STzaHDCUFg0TpA=="],
|
||||
"@opentui/core-darwin-arm64": ["@opentui/core-darwin-arm64@0.1.105", "", { "os": "darwin", "cpu": "arm64" }, "sha512-1pIL7aer9amwj8EpYoMNtvavKetIe+nX8uBRmYsMQb+KvJoUAZUqENfRW+qHE5WrsOyxx8/QoyXTHw15GG5iLQ=="],
|
||||
|
||||
"@opentui/core-darwin-x64": ["@opentui/core-darwin-x64@0.1.103", "", { "os": "darwin", "cpu": "x64" }, "sha512-QMYD+zUDGQliJ6m5nuNvA72jtluFeyVMoHkuA5m/Xmed/u8eLfahAKmDj3kY66ntUroPHWevcpbpvd7NCFEoFQ=="],
|
||||
"@opentui/core-darwin-x64": ["@opentui/core-darwin-x64@0.1.105", "", { "os": "darwin", "cpu": "x64" }, "sha512-hLIRSWlK3gY2NRXJGWiTBiMYSmRDjOYFZF6WtUVXhY2SL3sp08dhmr/6dmAVH+3pKCsCipLEsrrcQX6SAihCTA=="],
|
||||
|
||||
"@opentui/core-linux-arm64": ["@opentui/core-linux-arm64@0.1.103", "", { "os": "linux", "cpu": "arm64" }, "sha512-GzOvNr9dN6JaQ9qs7m8E75wLAHwT5CyxqkE6rEr1BO23/d2Ix7e3GYw/JRY5VnTge+eXrfDVbqNtPcQamUNiEA=="],
|
||||
"@opentui/core-linux-arm64": ["@opentui/core-linux-arm64@0.1.105", "", { "os": "linux", "cpu": "arm64" }, "sha512-jlRKfPkozTZEkHEePuCWYcTIUtPm+ieInAwGVqGmjbvqjxdVv1/W/Dt6LEZ/9jpRiOPd+FjXAfLe6wa/XWHr+w=="],
|
||||
|
||||
"@opentui/core-linux-x64": ["@opentui/core-linux-x64@0.1.103", "", { "os": "linux", "cpu": "x64" }, "sha512-odywllco5zUKNc60uD3JKaCybK64u6BfmpScs4a8Qn89yH/yk23bzWXDRWaGgQdY65L2/VCbcGs1ezA1S/2YTw=="],
|
||||
"@opentui/core-linux-x64": ["@opentui/core-linux-x64@0.1.105", "", { "os": "linux", "cpu": "x64" }, "sha512-kfWS1WMg6qHShmxZX9s1tZc/8JcXw6uyy2UtyTbJdRFExtXGH37oKHi8QK8iPL2ExCx4z7zqVnVJfO3X/Wh7lA=="],
|
||||
|
||||
"@opentui/core-win32-arm64": ["@opentui/core-win32-arm64@0.1.103", "", { "os": "win32", "cpu": "arm64" }, "sha512-tZL5w3Y0JnO7RkIvfuNDAzJn0j6+JIYl6M8DgPM5p8AQt+162S8LmbumzmqQLZl4cEev2eN7/tw72WIk6b+/CQ=="],
|
||||
"@opentui/core-win32-arm64": ["@opentui/core-win32-arm64@0.1.105", "", { "os": "win32", "cpu": "arm64" }, "sha512-UFx6A8OpBVbGWK6OAw4GqAqKZgIITJfSOd35pG9yDVKQouHN2OGc2HeeXrH2A4h42p40Xl6IfcqqfllkpC13Dg=="],
|
||||
|
||||
"@opentui/core-win32-x64": ["@opentui/core-win32-x64@0.1.103", "", { "os": "win32", "cpu": "x64" }, "sha512-wqnibt/OE5ldSzVPxEbriA0TjI2B11CJl4uJoLxTZ47KDx7tAFIMdhBf9IRAGNCSbcDuZ8ZGEFhV+SLaftkrlw=="],
|
||||
"@opentui/core-win32-x64": ["@opentui/core-win32-x64@0.1.105", "", { "os": "win32", "cpu": "x64" }, "sha512-f9FqqUmxehwhF+cgyazm0YT0v0BYTTCPzd6eztqhl74N3x/kC+jOOz2rdJDC/tTBo1JVsF64KupOnhIs6/Cogg=="],
|
||||
|
||||
"@opentui/solid": ["@opentui/solid@0.1.103", "", { "dependencies": { "@babel/core": "7.28.0", "@babel/preset-typescript": "7.27.1", "@opentui/core": "0.1.103", "babel-plugin-module-resolver": "5.0.2", "babel-preset-solid": "1.9.10", "entities": "7.0.1", "s-js": "^0.4.9" }, "peerDependencies": { "solid-js": "1.9.11" } }, "sha512-L28WFBs17Z5JXkJhPagLy8tUamkttDaaQDdb2KEO01IQ9r81yLBRpYqD/lHp6UoSISXgwQVDQ9yNtxwR1BQZvQ=="],
|
||||
"@opentui/solid": ["@opentui/solid@0.1.105", "", { "dependencies": { "@babel/core": "7.28.0", "@babel/preset-typescript": "7.27.1", "@opentui/core": "0.1.105", "babel-plugin-module-resolver": "5.0.2", "babel-preset-solid": "1.9.10", "entities": "7.0.1", "s-js": "^0.4.9" }, "peerDependencies": { "solid-js": "1.9.11" } }, "sha512-uxnaMP802sCI487pv/Hk9xdFdIj9mkg3eNliAqbqR0Shmd4phcjKEZvPRpijjmI99j4s9nul71jzF3h1oz31Nw=="],
|
||||
|
||||
"@oslojs/asn1": ["@oslojs/asn1@1.0.0", "", { "dependencies": { "@oslojs/binary": "1.0.0" } }, "sha512-zw/wn0sj0j0QKbIXfIlnEcTviaCzYOY3V5rAyjR6YtOByFtJiT574+8p9Wlach0lZH9fddD4yb9laEAIl4vXQA=="],
|
||||
|
||||
@@ -3035,7 +3035,7 @@
|
||||
|
||||
"ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="],
|
||||
|
||||
"effect": ["effect@4.0.0-beta.48", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.6.0", "find-my-way-ts": "^0.1.6", "ini": "^6.0.0", "kubernetes-types": "^1.30.0", "msgpackr": "^1.11.9", "multipasta": "^0.2.7", "toml": "^4.1.1", "uuid": "^13.0.0", "yaml": "^2.8.3" } }, "sha512-MMAM/ZabuNdNmgXiin+BAanQXK7qM8mlt7nfXDoJ/Gn9V8i89JlCq+2N0AiWmqFLXjGLA0u3FjiOjSOYQk5uMw=="],
|
||||
"effect": ["effect@4.0.0-beta.57", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.6.0", "find-my-way-ts": "^0.1.6", "ini": "^6.0.0", "kubernetes-types": "^1.30.0", "msgpackr": "^1.11.9", "multipasta": "^0.2.7", "toml": "^4.1.1", "uuid": "^13.0.0", "yaml": "^2.8.3" } }, "sha512-rg32VgXnLKaPRs9tbRDaZ5jxmzNY7ojXt85gSHGUTwdlbWH5Ik+OCUY2q14TXliygPGoHwCAvNWS4bQJOqf00g=="],
|
||||
|
||||
"ejs": ["ejs@3.1.10", "", { "dependencies": { "jake": "^10.8.5" }, "bin": { "ejs": "bin/cli.js" } }, "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA=="],
|
||||
|
||||
@@ -5595,18 +5595,6 @@
|
||||
|
||||
"@opencode-ai/web/@shikijs/transformers": ["@shikijs/transformers@3.20.0", "", { "dependencies": { "@shikijs/core": "3.20.0", "@shikijs/types": "3.20.0" } }, "sha512-PrHHMRr3Q5W1qB/42kJW6laqFyWdhrPF2hNR9qjOm1xcSiAO3hAHo7HaVyHE6pMyevmy3i51O8kuGGXC78uK3g=="],
|
||||
|
||||
"@opentelemetry/exporter-trace-otlp-http/@opentelemetry/resources": ["@opentelemetry/resources@2.6.1", "", { "dependencies": { "@opentelemetry/core": "2.6.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-lID/vxSuKWXM55XhAKNoYXu9Cutoq5hFdkbTdI/zDKQktXzcWBVhNsOkiZFTMU9UtEWuGRNe0HUgmsFldIdxVA=="],
|
||||
|
||||
"@opentelemetry/otlp-transformer/@opentelemetry/resources": ["@opentelemetry/resources@2.6.1", "", { "dependencies": { "@opentelemetry/core": "2.6.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-lID/vxSuKWXM55XhAKNoYXu9Cutoq5hFdkbTdI/zDKQktXzcWBVhNsOkiZFTMU9UtEWuGRNe0HUgmsFldIdxVA=="],
|
||||
|
||||
"@opentelemetry/resources/@opentelemetry/core": ["@opentelemetry/core@2.2.0", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-FuabnnUm8LflnieVxs6eP7Z383hgQU4W1e3KJS6aOG3RxWxcHyBxH8fDMHNgu/gFx/M2jvTOW/4/PHhLz6bjWw=="],
|
||||
|
||||
"@opentelemetry/sdk-logs/@opentelemetry/resources": ["@opentelemetry/resources@2.6.1", "", { "dependencies": { "@opentelemetry/core": "2.6.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-lID/vxSuKWXM55XhAKNoYXu9Cutoq5hFdkbTdI/zDKQktXzcWBVhNsOkiZFTMU9UtEWuGRNe0HUgmsFldIdxVA=="],
|
||||
|
||||
"@opentelemetry/sdk-metrics/@opentelemetry/resources": ["@opentelemetry/resources@2.6.1", "", { "dependencies": { "@opentelemetry/core": "2.6.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-lID/vxSuKWXM55XhAKNoYXu9Cutoq5hFdkbTdI/zDKQktXzcWBVhNsOkiZFTMU9UtEWuGRNe0HUgmsFldIdxVA=="],
|
||||
|
||||
"@opentelemetry/sdk-trace-base/@opentelemetry/resources": ["@opentelemetry/resources@2.6.1", "", { "dependencies": { "@opentelemetry/core": "2.6.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-lID/vxSuKWXM55XhAKNoYXu9Cutoq5hFdkbTdI/zDKQktXzcWBVhNsOkiZFTMU9UtEWuGRNe0HUgmsFldIdxVA=="],
|
||||
|
||||
"@opentui/solid/@babel/core": ["@babel/core@7.28.0", "", { "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.0", "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-module-transforms": "^7.27.3", "@babel/helpers": "^7.27.6", "@babel/parser": "^7.28.0", "@babel/template": "^7.27.2", "@babel/traverse": "^7.28.0", "@babel/types": "^7.28.0", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ=="],
|
||||
|
||||
"@opentui/solid/babel-preset-solid": ["babel-preset-solid@1.9.10", "", { "dependencies": { "babel-plugin-jsx-dom-expressions": "^0.40.3" }, "peerDependencies": { "@babel/core": "^7.0.0", "solid-js": "^1.9.10" }, "optionalPeers": ["solid-js"] }, "sha512-HCelrgua/Y+kqO8RyL04JBWS/cVdrtUv/h45GntgQY+cJl4eBcKkCDV3TdMjtKx1nXwRaR9QXslM/Npm1dxdZQ=="],
|
||||
@@ -5675,6 +5663,10 @@
|
||||
|
||||
"@solidjs/start/vite-plugin-solid": ["vite-plugin-solid@2.11.12", "", { "dependencies": { "@babel/core": "^7.23.3", "@types/babel__core": "^7.20.4", "babel-preset-solid": "^1.8.4", "merge-anything": "^5.1.7", "solid-refresh": "^0.6.3", "vitefu": "^1.0.4" }, "peerDependencies": { "@testing-library/jest-dom": "^5.16.6 || ^5.17.0 || ^6.*", "solid-js": "^1.7.2", "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" }, "optionalPeers": ["@testing-library/jest-dom"] }, "sha512-FgjPcx2OwX9h6f28jli7A4bG7PP3te8uyakE5iqsmpq3Jqi1TWLgSroC9N6cMfGRU2zXsl4Q6ISvTr2VL0QHpA=="],
|
||||
|
||||
"@standard-community/standard-json/effect": ["effect@4.0.0-beta.48", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.6.0", "find-my-way-ts": "^0.1.6", "ini": "^6.0.0", "kubernetes-types": "^1.30.0", "msgpackr": "^1.11.9", "multipasta": "^0.2.7", "toml": "^4.1.1", "uuid": "^13.0.0", "yaml": "^2.8.3" } }, "sha512-MMAM/ZabuNdNmgXiin+BAanQXK7qM8mlt7nfXDoJ/Gn9V8i89JlCq+2N0AiWmqFLXjGLA0u3FjiOjSOYQk5uMw=="],
|
||||
|
||||
"@standard-community/standard-openapi/effect": ["effect@4.0.0-beta.48", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.6.0", "find-my-way-ts": "^0.1.6", "ini": "^6.0.0", "kubernetes-types": "^1.30.0", "msgpackr": "^1.11.9", "multipasta": "^0.2.7", "toml": "^4.1.1", "uuid": "^13.0.0", "yaml": "^2.8.3" } }, "sha512-MMAM/ZabuNdNmgXiin+BAanQXK7qM8mlt7nfXDoJ/Gn9V8i89JlCq+2N0AiWmqFLXjGLA0u3FjiOjSOYQk5uMw=="],
|
||||
|
||||
"@tailwindcss/oxide/detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
|
||||
|
||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.9.2", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" }, "bundled": true }, "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA=="],
|
||||
@@ -5723,6 +5715,8 @@
|
||||
|
||||
"ai-gateway-provider/@ai-sdk/xai": ["@ai-sdk/xai@3.0.75", "", { "dependencies": { "@ai-sdk/openai-compatible": "2.0.37", "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.21" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-V8UKK4fNpI9cnrtsZBvUp9O9J6Y9fTKBRoSLyEaNGPirACewixmLDbXsSgAeownPVWiWpK34bFysd+XouI5Ywg=="],
|
||||
|
||||
"ai-gateway-provider/@openrouter/ai-sdk-provider": ["@openrouter/ai-sdk-provider@2.5.1", "", { "peerDependencies": { "ai": "^6.0.0", "zod": "^3.25.0 || ^4.0.0" } }, "sha512-r1fJL1Cb3gQDa2MpWH/sfx1BsEW0uzlRriJM6eihaKqbtKDmZoBisF32VcVaQYassighX7NGCkF68EsrZA43uQ=="],
|
||||
|
||||
"ajv-keywords/ajv": ["ajv@6.14.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw=="],
|
||||
|
||||
"ansi-align/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
|
||||
@@ -6591,6 +6585,10 @@
|
||||
|
||||
"@solidjs/start/shiki/@shikijs/types": ["@shikijs/types@1.29.2", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.1", "@types/hast": "^3.0.4" } }, "sha512-VJjK0eIijTZf0QSTODEXCqinjBn0joAHQ+aPSBzrv4O2d/QSbsMw+ZeSRx03kV34Hy7NzUvV/7NqfYGRLrASmw=="],
|
||||
|
||||
"@standard-community/standard-json/effect/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
|
||||
|
||||
"@standard-community/standard-openapi/effect/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
|
||||
|
||||
"@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime/@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
|
||||
|
||||
"@vitest/expect/@vitest/utils/@vitest/pretty-format": ["@vitest/pretty-format@3.2.4", "", { "dependencies": { "tinyrainbow": "^2.0.0" } }, "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA=="],
|
||||
|
||||
@@ -115,6 +115,27 @@ const zenLiteCouponFirstMonth100 = new stripe.Coupon("ZenLiteCouponFirstMonth100
|
||||
appliesToProducts: [zenLiteProduct.id],
|
||||
duration: "once",
|
||||
})
|
||||
const zenLiteCouponThreeMonths100 = new stripe.Coupon("ZenLiteCoupon3Months100", {
|
||||
name: "3 months 100% off",
|
||||
percentOff: 100,
|
||||
appliesToProducts: [zenLiteProduct.id],
|
||||
duration: "repeating",
|
||||
durationInMonths: 3,
|
||||
})
|
||||
const zenLiteCouponSixMonths100 = new stripe.Coupon("ZenLiteCoupon6Months100", {
|
||||
name: "6 months 100% off",
|
||||
percentOff: 100,
|
||||
appliesToProducts: [zenLiteProduct.id],
|
||||
duration: "repeating",
|
||||
durationInMonths: 6,
|
||||
})
|
||||
const zenLiteCouponTwelveMonths100 = new stripe.Coupon("ZenLiteCoupon12Months100", {
|
||||
name: "12 months 100% off",
|
||||
percentOff: 100,
|
||||
appliesToProducts: [zenLiteProduct.id],
|
||||
duration: "repeating",
|
||||
durationInMonths: 12,
|
||||
})
|
||||
const zenLitePrice = new stripe.Price("ZenLitePrice", {
|
||||
product: zenLiteProduct.id,
|
||||
currency: "usd",
|
||||
@@ -131,6 +152,9 @@ const ZEN_LITE_PRICE = new sst.Linkable("ZEN_LITE_PRICE", {
|
||||
priceInr: 92900,
|
||||
firstMonth50Coupon: zenLiteCouponFirstMonth50.id,
|
||||
firstMonth100Coupon: zenLiteCouponFirstMonth100.id,
|
||||
threeMonths100Coupon: zenLiteCouponThreeMonths100.id,
|
||||
sixMonths100Coupon: zenLiteCouponSixMonths100.id,
|
||||
twelveMonths100Coupon: zenLiteCouponTwelveMonths100.id,
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
+4
-4
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"nodeModules": {
|
||||
"x86_64-linux": "sha256-LpzWEZzURUEj7fcHGvh33gM7D9GNPE+XIvU0/hmdcQM=",
|
||||
"aarch64-linux": "sha256-0zdO3zuj6g9cMZFEOsvQJcKKcPjGVZJ2DkJdDcb2VCM=",
|
||||
"aarch64-darwin": "sha256-dmT8R9Pmzh5tjO8NCCCtENiQpJQeifQpVdhaty1MXOs=",
|
||||
"x86_64-darwin": "sha256-Q6rAQRoC6WaMAQl++YHAZmbNuO303cWgGaYzXaRlzy4="
|
||||
"x86_64-linux": "sha256-h2T/LnUnISZZDn9ZQkZ/A59P+6+QdfOlrgl4RXK/vgM=",
|
||||
"aarch64-linux": "sha256-+DRohG1ZEB/2LtZU90GWoqJkeyu/sW8A8oKT3f/TtQ0=",
|
||||
"aarch64-darwin": "sha256-k4nsk/WduuxY8HgjRuqzGT9EjEo7V/2mAzBTYee0fZ0=",
|
||||
"x86_64-darwin": "sha256-3dSvfN2+5lXwOx57x8NSIWbEZ1fp6+1T6bJpAuUNPyk="
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -64,7 +64,7 @@ stdenvNoCC.mkDerivation (finalAttrs: {
|
||||
[
|
||||
ripgrep
|
||||
]
|
||||
# bun runs sysctl to detect if dunning on rosetta2
|
||||
# bun runs sysctl to detect if running on rosetta2
|
||||
++ lib.optional stdenvNoCC.hostPlatform.isDarwin sysctl
|
||||
)
|
||||
}
|
||||
|
||||
+5
-5
@@ -27,15 +27,15 @@
|
||||
"packages/slack"
|
||||
],
|
||||
"catalog": {
|
||||
"@effect/opentelemetry": "4.0.0-beta.48",
|
||||
"@effect/platform-node": "4.0.0-beta.48",
|
||||
"@effect/opentelemetry": "4.0.0-beta.57",
|
||||
"@effect/platform-node": "4.0.0-beta.57",
|
||||
"@npmcli/arborist": "9.4.0",
|
||||
"@types/bun": "1.3.12",
|
||||
"@types/cross-spawn": "6.0.6",
|
||||
"@octokit/rest": "22.0.0",
|
||||
"@hono/zod-validator": "0.4.2",
|
||||
"@opentui/core": "0.1.103",
|
||||
"@opentui/solid": "0.1.103",
|
||||
"@opentui/core": "0.1.105",
|
||||
"@opentui/solid": "0.1.105",
|
||||
"ulid": "3.0.1",
|
||||
"@kobalte/core": "0.13.11",
|
||||
"@types/luxon": "3.7.1",
|
||||
@@ -53,7 +53,7 @@
|
||||
"dompurify": "3.3.1",
|
||||
"drizzle-kit": "1.0.0-beta.19-d95b7a4",
|
||||
"drizzle-orm": "1.0.0-beta.19-d95b7a4",
|
||||
"effect": "4.0.0-beta.48",
|
||||
"effect": "4.0.0-beta.57",
|
||||
"ai": "6.0.168",
|
||||
"cross-spawn": "7.0.6",
|
||||
"hono": "4.10.7",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/app",
|
||||
"version": "1.14.25",
|
||||
"version": "1.14.29",
|
||||
"description": "",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
|
||||
@@ -82,7 +82,15 @@ declare global {
|
||||
}
|
||||
|
||||
function QueryProvider(props: ParentProps) {
|
||||
const client = new QueryClient()
|
||||
const client = new QueryClient({
|
||||
defaultOptions: {
|
||||
queries: {
|
||||
refetchOnReconnect: false,
|
||||
refetchOnMount: false,
|
||||
refetchOnWindowFocus: false,
|
||||
},
|
||||
},
|
||||
})
|
||||
return <QueryClientProvider client={client}>{props.children}</QueryClientProvider>
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import { useMutation } from "@tanstack/solid-query"
|
||||
import { Component, createEffect, createMemo, on, Show } from "solid-js"
|
||||
import { createStore } from "solid-js/store"
|
||||
import { useMutation, useQueryClient } from "@tanstack/solid-query"
|
||||
import { Component, createMemo, Show } from "solid-js"
|
||||
import { useSync } from "@/context/sync"
|
||||
import { useSDK } from "@/context/sdk"
|
||||
import { Dialog } from "@opencode-ai/ui/dialog"
|
||||
import { List } from "@opencode-ai/ui/list"
|
||||
import { Switch } from "@opencode-ai/ui/switch"
|
||||
import { showToast } from "@opencode-ai/ui/toast"
|
||||
import { useLanguage } from "@/context/language"
|
||||
import { loadMcpQuery } from "@/context/global-sync"
|
||||
|
||||
const statusLabels = {
|
||||
connected: "mcp.status.connected",
|
||||
@@ -20,48 +19,7 @@ export const DialogSelectMcp: Component = () => {
|
||||
const sync = useSync()
|
||||
const sdk = useSDK()
|
||||
const language = useLanguage()
|
||||
const [state, setState] = createStore({
|
||||
done: false,
|
||||
loading: false,
|
||||
})
|
||||
|
||||
createEffect(
|
||||
on(
|
||||
() => sync.data.mcp_ready,
|
||||
(ready, prev) => {
|
||||
if (!ready && prev) setState("done", false)
|
||||
},
|
||||
{ defer: true },
|
||||
),
|
||||
)
|
||||
|
||||
createEffect(() => {
|
||||
if (state.done || state.loading) return
|
||||
if (sync.data.mcp_ready) {
|
||||
setState("done", true)
|
||||
return
|
||||
}
|
||||
|
||||
setState("loading", true)
|
||||
void sdk.client.mcp
|
||||
.status()
|
||||
.then((result) => {
|
||||
sync.set("mcp", result.data ?? {})
|
||||
sync.set("mcp_ready", true)
|
||||
setState("done", true)
|
||||
})
|
||||
.catch((err) => {
|
||||
setState("done", true)
|
||||
showToast({
|
||||
variant: "error",
|
||||
title: language.t("common.requestFailed"),
|
||||
description: err instanceof Error ? err.message : String(err),
|
||||
})
|
||||
})
|
||||
.finally(() => {
|
||||
setState("loading", false)
|
||||
})
|
||||
})
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
const items = createMemo(() =>
|
||||
Object.entries(sync.data.mcp ?? {})
|
||||
@@ -71,16 +29,10 @@ export const DialogSelectMcp: Component = () => {
|
||||
|
||||
const toggle = useMutation(() => ({
|
||||
mutationFn: async (name: string) => {
|
||||
const status = sync.data.mcp[name]
|
||||
if (status?.status === "connected") {
|
||||
await sdk.client.mcp.disconnect({ name })
|
||||
} else {
|
||||
await sdk.client.mcp.connect({ name })
|
||||
}
|
||||
|
||||
const result = await sdk.client.mcp.status()
|
||||
if (result.data) sync.set("mcp", result.data)
|
||||
if (sync.data.mcp[name]?.status === "connected") await sdk.client.mcp.disconnect({ name })
|
||||
else await sdk.client.mcp.connect({ name })
|
||||
},
|
||||
onSuccess: () => queryClient.refetchQueries({ queryKey: loadMcpQuery(sync.directory).queryKey }),
|
||||
}))
|
||||
|
||||
const enabledCount = createMemo(() => items().filter((i) => i.status === "connected").length)
|
||||
|
||||
@@ -11,7 +11,9 @@ import { showToast } from "@opencode-ai/ui/toast"
|
||||
import { useParams } from "@solidjs/router"
|
||||
import { useLanguage } from "@/context/language"
|
||||
import { usePermission } from "@/context/permission"
|
||||
import { usePlatform } from "@/context/platform"
|
||||
import { usePlatform, type DisplayBackend } from "@/context/platform"
|
||||
import { useGlobalSync } from "@/context/global-sync"
|
||||
import { useGlobalSDK } from "@/context/global-sdk"
|
||||
import {
|
||||
monoDefault,
|
||||
monoFontFamily,
|
||||
@@ -40,6 +42,18 @@ type ThemeOption = {
|
||||
name: string
|
||||
}
|
||||
|
||||
type ShellOption = {
|
||||
path: string
|
||||
name: string
|
||||
acceptable: boolean
|
||||
}
|
||||
|
||||
type ShellSelectOption = {
|
||||
id: string
|
||||
value: string
|
||||
label: string
|
||||
}
|
||||
|
||||
// To prevent audio from overlapping/playing very quickly when navigating the settings menus,
|
||||
// delay the playback by 100ms during quick selection changes and pause existing sounds.
|
||||
const stopDemoSound = () => {
|
||||
@@ -75,10 +89,6 @@ export const SettingsGeneral: Component = () => {
|
||||
const params = useParams()
|
||||
const settings = useSettings()
|
||||
|
||||
onMount(() => {
|
||||
void theme.loadThemes()
|
||||
})
|
||||
|
||||
const [store, setStore] = createStore({
|
||||
checking: false,
|
||||
})
|
||||
@@ -165,6 +175,70 @@ export const SettingsGeneral: Component = () => {
|
||||
|
||||
const themeOptions = createMemo<ThemeOption[]>(() => theme.ids().map((id) => ({ id, name: theme.name(id) })))
|
||||
|
||||
const globalSync = useGlobalSync()
|
||||
const globalSdk = useGlobalSDK()
|
||||
|
||||
const [shells] = createResource(
|
||||
() =>
|
||||
globalSdk.client.pty
|
||||
.shells()
|
||||
.then((res) => res.data ?? [])
|
||||
.catch(() => [] as ShellOption[]),
|
||||
{ initialValue: [] as ShellOption[] },
|
||||
)
|
||||
|
||||
const [displayBackend, { refetch: refetchDisplayBackend }] = createResource(
|
||||
() => (linux() && platform.getDisplayBackend ? true : false),
|
||||
() => Promise.resolve(platform.getDisplayBackend?.() ?? null).catch(() => null as DisplayBackend | null),
|
||||
{ initialValue: null as DisplayBackend | null },
|
||||
)
|
||||
|
||||
onMount(() => {
|
||||
void theme.loadThemes()
|
||||
})
|
||||
|
||||
const autoOption = { id: "auto", value: "", label: language.t("settings.general.row.shell.autoDefault") }
|
||||
const currentShell = createMemo(() => globalSync.data.config.shell ?? "")
|
||||
|
||||
const shellOptions = createMemo<ShellSelectOption[]>(() => {
|
||||
const list = shells.latest
|
||||
const current = globalSync.data.config.shell
|
||||
|
||||
const nameCounts = new Map<string, number>()
|
||||
for (const s of list) {
|
||||
nameCounts.set(s.name, (nameCounts.get(s.name) || 0) + 1)
|
||||
}
|
||||
|
||||
const options = [
|
||||
autoOption,
|
||||
...list.map((s) => {
|
||||
const ambiguousName = (nameCounts.get(s.name) || 0) > 1
|
||||
const text = ambiguousName ? s.path : s.name
|
||||
const label = s.acceptable ? text : `${text} (${language.t("settings.general.row.shell.terminalOnly")})`
|
||||
return {
|
||||
id: s.path,
|
||||
// Prefer name over path - "bash" is much cleaner than the explicit full route even when it may change due to PATH.
|
||||
value: ambiguousName ? s.path : s.name,
|
||||
label,
|
||||
}
|
||||
}),
|
||||
]
|
||||
|
||||
if (current && !options.some((o) => o.value === current)) {
|
||||
options.push({ id: current, value: current, label: current })
|
||||
}
|
||||
|
||||
return options
|
||||
})
|
||||
|
||||
const onDisplayBackendChange = (checked: boolean) => {
|
||||
const update = platform.setDisplayBackend?.(checked ? "wayland" : "auto")
|
||||
if (!update) return
|
||||
void update.finally(() => {
|
||||
void refetchDisplayBackend()
|
||||
})
|
||||
}
|
||||
|
||||
const colorSchemeOptions = createMemo((): { value: ColorScheme; label: string }[] => [
|
||||
{ value: "system", label: language.t("theme.scheme.system") },
|
||||
{ value: "light", label: language.t("theme.scheme.light") },
|
||||
@@ -243,6 +317,27 @@ export const SettingsGeneral: Component = () => {
|
||||
</div>
|
||||
</SettingsRow>
|
||||
|
||||
<SettingsRow
|
||||
title={language.t("settings.general.row.shell.title")}
|
||||
description={language.t("settings.general.row.shell.description")}
|
||||
>
|
||||
<Select
|
||||
data-action="settings-shell"
|
||||
options={shellOptions()}
|
||||
current={shellOptions().find((o) => o.value === currentShell()) ?? autoOption}
|
||||
value={(o) => o.id}
|
||||
label={(o) => o.label}
|
||||
onSelect={(option) => {
|
||||
if (!option) return
|
||||
globalSync.updateConfig({ shell: option.value })
|
||||
}}
|
||||
variant="secondary"
|
||||
size="small"
|
||||
triggerVariant="settings"
|
||||
triggerStyle={{ "min-width": "180px" }}
|
||||
/>
|
||||
</SettingsRow>
|
||||
|
||||
<SettingsRow
|
||||
title={language.t("settings.general.row.reasoningSummaries.title")}
|
||||
description={language.t("settings.general.row.reasoningSummaries.description")}
|
||||
@@ -651,70 +746,32 @@ export const SettingsGeneral: Component = () => {
|
||||
|
||||
<SoundsSection />
|
||||
|
||||
{/*<Show when={platform.platform === "desktop" && platform.os === "windows" && platform.getWslEnabled}>
|
||||
{(_) => {
|
||||
const [enabledResource, actions] = createResource(() => platform.getWslEnabled?.())
|
||||
const enabled = () => (enabledResource.state === "pending" ? undefined : enabledResource.latest)
|
||||
|
||||
return (
|
||||
<div class="flex flex-col gap-1">
|
||||
<h3 class="text-14-medium text-text-strong pb-2">{language.t("settings.desktop.section.wsl")}</h3>
|
||||
|
||||
<SettingsList>
|
||||
<SettingsRow
|
||||
title={language.t("settings.desktop.wsl.title")}
|
||||
description={language.t("settings.desktop.wsl.description")}
|
||||
>
|
||||
<div data-action="settings-wsl">
|
||||
<Switch
|
||||
checked={enabled() ?? false}
|
||||
disabled={enabledResource.state === "pending"}
|
||||
onChange={(checked) => platform.setWslEnabled?.(checked)?.finally(() => actions.refetch())}
|
||||
/>
|
||||
</div>
|
||||
</SettingsRow>
|
||||
</SettingsList>
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
</Show>*/}
|
||||
|
||||
<UpdatesSection />
|
||||
|
||||
<Show when={linux()}>
|
||||
{(_) => {
|
||||
const [valueResource, actions] = createResource(() => platform.getDisplayBackend?.())
|
||||
const value = () => (valueResource.state === "pending" ? undefined : valueResource.latest)
|
||||
<div class="flex flex-col gap-1">
|
||||
<h3 class="text-14-medium text-text-strong pb-2">{language.t("settings.general.section.display")}</h3>
|
||||
|
||||
const onChange = (checked: boolean) =>
|
||||
platform.setDisplayBackend?.(checked ? "wayland" : "auto").finally(() => actions.refetch())
|
||||
|
||||
return (
|
||||
<div class="flex flex-col gap-1">
|
||||
<h3 class="text-14-medium text-text-strong pb-2">{language.t("settings.general.section.display")}</h3>
|
||||
|
||||
<SettingsList>
|
||||
<SettingsRow
|
||||
title={
|
||||
<div class="flex items-center gap-2">
|
||||
<span>{language.t("settings.general.row.wayland.title")}</span>
|
||||
<Tooltip value={language.t("settings.general.row.wayland.tooltip")} placement="top">
|
||||
<span class="text-text-weak">
|
||||
<Icon name="help" size="small" />
|
||||
</span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
}
|
||||
description={language.t("settings.general.row.wayland.description")}
|
||||
>
|
||||
<div data-action="settings-wayland">
|
||||
<Switch checked={value() === "wayland"} onChange={onChange} />
|
||||
</div>
|
||||
</SettingsRow>
|
||||
</SettingsList>
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
<SettingsList>
|
||||
<SettingsRow
|
||||
title={
|
||||
<div class="flex items-center gap-2">
|
||||
<span>{language.t("settings.general.row.wayland.title")}</span>
|
||||
<Tooltip value={language.t("settings.general.row.wayland.tooltip")} placement="top">
|
||||
<span class="text-text-weak">
|
||||
<Icon name="help" size="small" />
|
||||
</span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
}
|
||||
description={language.t("settings.general.row.wayland.description")}
|
||||
>
|
||||
<div data-action="settings-wayland">
|
||||
<Switch checked={displayBackend.latest === "wayland"} onChange={onDisplayBackendChange} />
|
||||
</div>
|
||||
</SettingsRow>
|
||||
</SettingsList>
|
||||
</div>
|
||||
</Show>
|
||||
|
||||
<Show when={desktop() && import.meta.env.VITE_OPENCODE_CHANNEL === "beta"}>
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useDialog } from "@opencode-ai/ui/context/dialog"
|
||||
import { Icon } from "@opencode-ai/ui/icon"
|
||||
import { Switch } from "@opencode-ai/ui/switch"
|
||||
import { Tabs } from "@opencode-ai/ui/tabs"
|
||||
import { useMutation } from "@tanstack/solid-query"
|
||||
import { useMutation, useQueryClient } from "@tanstack/solid-query"
|
||||
import { showToast } from "@opencode-ai/ui/toast"
|
||||
import { useNavigate } from "@solidjs/router"
|
||||
import { type Accessor, createEffect, createMemo, For, type JSXElement, onCleanup, Show } from "solid-js"
|
||||
@@ -15,6 +15,7 @@ import { useSDK } from "@/context/sdk"
|
||||
import { normalizeServerUrl, ServerConnection, useServer } from "@/context/server"
|
||||
import { useSync } from "@/context/sync"
|
||||
import { useCheckServerHealth, type ServerHealth } from "@/utils/server-health"
|
||||
import { loadMcpQuery } from "@/context/global-sync"
|
||||
|
||||
const pollMs = 10_000
|
||||
|
||||
@@ -137,14 +138,14 @@ const useMcpToggleMutation = () => {
|
||||
const sync = useSync()
|
||||
const sdk = useSDK()
|
||||
const language = useLanguage()
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
return useMutation(() => ({
|
||||
mutationFn: async (name: string) => {
|
||||
const status = sync.data.mcp[name]
|
||||
await (status?.status === "connected" ? sdk.client.mcp.disconnect({ name }) : sdk.client.mcp.connect({ name }))
|
||||
const result = await sdk.client.mcp.status()
|
||||
if (result.data) sync.set("mcp", result.data)
|
||||
},
|
||||
onSuccess: () => queryClient.refetchQueries({ queryKey: loadMcpQuery(sync.directory).queryKey }),
|
||||
onError: (err) => {
|
||||
showToast({
|
||||
variant: "error",
|
||||
@@ -162,14 +163,6 @@ export function StatusPopoverBody(props: { shown: Accessor<boolean> }) {
|
||||
const dialog = useDialog()
|
||||
const language = useLanguage()
|
||||
const navigate = useNavigate()
|
||||
const sdk = useSDK()
|
||||
|
||||
const [load, setLoad] = createStore({
|
||||
lspDone: false,
|
||||
lspLoading: false,
|
||||
mcpDone: false,
|
||||
mcpLoading: false,
|
||||
})
|
||||
|
||||
const fail = (err: unknown) => {
|
||||
showToast({
|
||||
@@ -181,40 +174,6 @@ export function StatusPopoverBody(props: { shown: Accessor<boolean> }) {
|
||||
|
||||
createEffect(() => {
|
||||
if (!props.shown()) return
|
||||
|
||||
if (!sync.data.mcp_ready && !load.mcpDone && !load.mcpLoading) {
|
||||
setLoad("mcpLoading", true)
|
||||
void sdk.client.mcp
|
||||
.status()
|
||||
.then((result) => {
|
||||
sync.set("mcp", result.data ?? {})
|
||||
sync.set("mcp_ready", true)
|
||||
})
|
||||
.catch((err) => {
|
||||
setLoad("mcpDone", true)
|
||||
fail(err)
|
||||
})
|
||||
.finally(() => {
|
||||
setLoad("mcpLoading", false)
|
||||
})
|
||||
}
|
||||
|
||||
if (!sync.data.lsp_ready && !load.lspDone && !load.lspLoading) {
|
||||
setLoad("lspLoading", true)
|
||||
void sdk.client.lsp
|
||||
.status()
|
||||
.then((result) => {
|
||||
sync.set("lsp", result.data ?? [])
|
||||
sync.set("lsp_ready", true)
|
||||
})
|
||||
.catch((err) => {
|
||||
setLoad("lspDone", true)
|
||||
fail(err)
|
||||
})
|
||||
.finally(() => {
|
||||
setLoad("lspLoading", false)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
let dialogRun = 0
|
||||
|
||||
@@ -14,17 +14,25 @@ import { createStore, produce, reconcile } from "solid-js/store"
|
||||
import { useLanguage } from "@/context/language"
|
||||
import type { InitError } from "../pages/error"
|
||||
import { useGlobalSDK } from "./global-sdk"
|
||||
import { bootstrapDirectory, bootstrapGlobal, clearProviderRev } from "./global-sync/bootstrap"
|
||||
import {
|
||||
bootstrapDirectory,
|
||||
bootstrapGlobal,
|
||||
clearProviderRev,
|
||||
loadGlobalConfigQuery,
|
||||
loadPathQuery,
|
||||
loadProjectsQuery,
|
||||
loadProvidersQuery,
|
||||
} from "./global-sync/bootstrap"
|
||||
import { createChildStoreManager } from "./global-sync/child-store"
|
||||
import { applyDirectoryEvent, applyGlobalEvent, cleanupDroppedSessionCaches } from "./global-sync/event-reducer"
|
||||
import { createRefreshQueue } from "./global-sync/queue"
|
||||
import { clearSessionPrefetchDirectory } from "./global-sync/session-prefetch"
|
||||
import { estimateRootSessionTotal, loadRootSessionsWithFallback } from "./global-sync/session-load"
|
||||
import { trimSessions } from "./global-sync/session-trim"
|
||||
import type { ProjectMeta } from "./global-sync/types"
|
||||
import { SESSION_RECENT_LIMIT } from "./global-sync/types"
|
||||
import { formatServerError } from "@/utils/server-errors"
|
||||
import { queryOptions, skipToken, useQueryClient } from "@tanstack/solid-query"
|
||||
import { queryOptions, skipToken, useMutation, useQueries, useQuery, useQueryClient } from "@tanstack/solid-query"
|
||||
import { createRefreshQueue } from "./global-sync/queue"
|
||||
|
||||
type GlobalStore = {
|
||||
ready: boolean
|
||||
@@ -43,6 +51,18 @@ type GlobalStore = {
|
||||
export const loadSessionsQuery = (directory: string) =>
|
||||
queryOptions<null>({ queryKey: [directory, "loadSessions"], queryFn: skipToken })
|
||||
|
||||
export const loadMcpQuery = (directory: string, sdk?: OpencodeClient) =>
|
||||
queryOptions({
|
||||
queryKey: [directory, "mcp"],
|
||||
queryFn: sdk ? () => sdk.mcp.status().then((r) => r.data ?? {}) : skipToken,
|
||||
})
|
||||
|
||||
export const loadLspQuery = (directory: string, sdk?: OpencodeClient) =>
|
||||
queryOptions({
|
||||
queryKey: [directory, "lsp"],
|
||||
queryFn: sdk ? () => sdk.lsp.status().then((r) => r.data ?? []) : skipToken,
|
||||
})
|
||||
|
||||
function createGlobalSync() {
|
||||
const globalSDK = useGlobalSDK()
|
||||
const language = useLanguage()
|
||||
@@ -54,15 +74,34 @@ function createGlobalSync() {
|
||||
const sessionLoads = new Map<string, Promise<void>>()
|
||||
const sessionMeta = new Map<string, { limit: number }>()
|
||||
|
||||
const [configQuery, providerQuery, pathQuery] = useQueries(() => ({
|
||||
queries: [loadGlobalConfigQuery(), loadProvidersQuery(null), loadPathQuery(null), loadProjectsQuery()],
|
||||
}))
|
||||
|
||||
const [globalStore, setGlobalStore] = createStore<GlobalStore>({
|
||||
ready: false,
|
||||
path: { state: "", config: "", worktree: "", directory: "", home: "" },
|
||||
get ready() {
|
||||
return bootstrap.isPending
|
||||
},
|
||||
project: [],
|
||||
session_todo: {},
|
||||
provider: { all: [], connected: [], default: {} },
|
||||
provider_auth: {},
|
||||
config: {},
|
||||
reload: undefined,
|
||||
get path() {
|
||||
const EMPTY = { state: "", config: "", worktree: "", directory: "", home: "" }
|
||||
if (pathQuery.isLoading) return EMPTY
|
||||
return pathQuery.data ?? EMPTY
|
||||
},
|
||||
get provider() {
|
||||
const EMPTY = { all: [], connected: [], default: {} }
|
||||
if (providerQuery.isLoading) return EMPTY
|
||||
return providerQuery.data ?? EMPTY
|
||||
},
|
||||
get config() {
|
||||
if (configQuery.isLoading) return {}
|
||||
return configQuery.data ?? {}
|
||||
},
|
||||
get reload() {
|
||||
return updateConfigMutation.isPending ? "pending" : undefined
|
||||
},
|
||||
})
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
@@ -88,6 +127,22 @@ function createGlobalSync() {
|
||||
return (setGlobalStore as (...args: unknown[]) => unknown)(...input)
|
||||
}) as typeof setGlobalStore
|
||||
|
||||
const bootstrap = useQuery(() => ({
|
||||
queryKey: ["bootstrap"],
|
||||
queryFn: async () => {
|
||||
await bootstrapGlobal({
|
||||
globalSDK: globalSDK.client,
|
||||
requestFailedTitle: language.t("common.requestFailed"),
|
||||
translate: language.t,
|
||||
formatMoreCount: (count) => language.t("common.moreCountSuffix", { count }),
|
||||
setGlobalStore: setBootStore,
|
||||
queryClient,
|
||||
})
|
||||
bootedAt = Date.now()
|
||||
return bootedAt
|
||||
},
|
||||
}))
|
||||
|
||||
const set = ((...input: unknown[]) => {
|
||||
if (input[0] === "project" && (Array.isArray(input[1]) || typeof input[1] === "function")) {
|
||||
setProjects(input[1] as Project[] | ((draft: Project[]) => Project[]))
|
||||
@@ -114,10 +169,21 @@ function createGlobalSync() {
|
||||
|
||||
const queue = createRefreshQueue({
|
||||
paused,
|
||||
bootstrap,
|
||||
bootstrap: () => queryClient.fetchQuery({ queryKey: ["bootstrap"] }),
|
||||
bootstrapInstance,
|
||||
})
|
||||
|
||||
const sdkFor = (directory: string) => {
|
||||
const cached = sdkCache.get(directory)
|
||||
if (cached) return cached
|
||||
const sdk = globalSDK.createClient({
|
||||
directory,
|
||||
throwOnError: true,
|
||||
})
|
||||
sdkCache.set(directory, sdk)
|
||||
return sdk
|
||||
}
|
||||
|
||||
const children = createChildStoreManager({
|
||||
owner,
|
||||
isBooting: (directory) => booting.has(directory),
|
||||
@@ -133,19 +199,9 @@ function createGlobalSync() {
|
||||
clearSessionPrefetchDirectory(directory)
|
||||
},
|
||||
translate: language.t,
|
||||
getSdk: sdkFor,
|
||||
})
|
||||
|
||||
const sdkFor = (directory: string) => {
|
||||
const cached = sdkCache.get(directory)
|
||||
if (cached) return cached
|
||||
const sdk = globalSDK.createClient({
|
||||
directory,
|
||||
throwOnError: true,
|
||||
})
|
||||
sdkCache.set(directory, sdk)
|
||||
return sdk
|
||||
}
|
||||
|
||||
async function loadSessions(directory: string) {
|
||||
const pending = sessionLoads.get(directory)
|
||||
if (pending) return pending
|
||||
@@ -264,26 +320,13 @@ function createGlobalSync() {
|
||||
const event = e.details
|
||||
const recent = bootingRoot || Date.now() - bootedAt < 1500
|
||||
|
||||
if (event.type === "session.error") {
|
||||
const error = event.properties.error
|
||||
if (error?.name !== "MessageAbortedError") {
|
||||
console.error("[global-sync] session error", {
|
||||
scope: directory === "global" ? "global" : "workspace",
|
||||
directory: directory === "global" ? undefined : directory,
|
||||
project: directory === "global" ? undefined : getFilename(directory),
|
||||
sessionID: event.properties.sessionID,
|
||||
error,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (directory === "global") {
|
||||
applyGlobalEvent({
|
||||
event,
|
||||
project: globalStore.project,
|
||||
refresh: () => {
|
||||
if (recent) return
|
||||
queue.refresh()
|
||||
bootstrap.refetch()
|
||||
},
|
||||
setGlobalProject: setProjects,
|
||||
})
|
||||
@@ -309,12 +352,7 @@ function createGlobalSync() {
|
||||
setSessionTodo,
|
||||
vcsCache: children.vcsCache.get(directory),
|
||||
loadLsp: () => {
|
||||
void sdkFor(directory)
|
||||
.lsp.status()
|
||||
.then((x) => {
|
||||
setStore("lsp", x.data ?? [])
|
||||
setStore("lsp_ready", true)
|
||||
})
|
||||
void queryClient.fetchQuery(loadLspQuery(directory, sdkFor(directory)))
|
||||
},
|
||||
})
|
||||
})
|
||||
@@ -329,23 +367,6 @@ function createGlobalSync() {
|
||||
}
|
||||
})
|
||||
|
||||
async function bootstrap() {
|
||||
bootingRoot = true
|
||||
try {
|
||||
await bootstrapGlobal({
|
||||
globalSDK: globalSDK.client,
|
||||
requestFailedTitle: language.t("common.requestFailed"),
|
||||
translate: language.t,
|
||||
formatMoreCount: (count) => language.t("common.moreCountSuffix", { count }),
|
||||
setGlobalStore: setBootStore,
|
||||
queryClient,
|
||||
})
|
||||
bootedAt = Date.now()
|
||||
} finally {
|
||||
bootingRoot = false
|
||||
}
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
if (typeof requestAnimationFrame === "function") {
|
||||
eventFrame = requestAnimationFrame(() => {
|
||||
@@ -361,7 +382,6 @@ function createGlobalSync() {
|
||||
void globalSDK.event.start()
|
||||
}, 0)
|
||||
}
|
||||
void bootstrap()
|
||||
})
|
||||
|
||||
const projectApi = {
|
||||
@@ -374,21 +394,10 @@ function createGlobalSync() {
|
||||
},
|
||||
}
|
||||
|
||||
const updateConfig = async (config: Config) => {
|
||||
setGlobalStore("reload", "pending")
|
||||
return globalSDK.client.global.config
|
||||
.update({ config })
|
||||
.then(bootstrap)
|
||||
.then(() => {
|
||||
queue.refresh()
|
||||
setGlobalStore("reload", undefined)
|
||||
queue.refresh()
|
||||
})
|
||||
.catch((error) => {
|
||||
setGlobalStore("reload", undefined)
|
||||
throw error
|
||||
})
|
||||
}
|
||||
const updateConfigMutation = useMutation(() => ({
|
||||
mutationFn: (config: Config) => globalSDK.client.global.config.update({ config }),
|
||||
onSuccess: () => bootstrap.refetch(),
|
||||
}))
|
||||
|
||||
return {
|
||||
data: globalStore,
|
||||
@@ -401,8 +410,8 @@ function createGlobalSync() {
|
||||
},
|
||||
child: children.child,
|
||||
peek: children.peek,
|
||||
bootstrap,
|
||||
updateConfig,
|
||||
// bootstrap,
|
||||
updateConfig: updateConfigMutation.mutateAsync,
|
||||
project: projectApi,
|
||||
todo: {
|
||||
set: setSessionTodo,
|
||||
|
||||
@@ -19,6 +19,7 @@ import type { State, VcsCache } from "./types"
|
||||
import { cmp, normalizeAgentList, normalizeProviderList } from "./utils"
|
||||
import { formatServerError } from "@/utils/server-errors"
|
||||
import { QueryClient, queryOptions, skipToken } from "@tanstack/solid-query"
|
||||
import { loadMcpQuery } from "../global-sync"
|
||||
|
||||
type GlobalStore = {
|
||||
ready: boolean
|
||||
@@ -66,6 +67,62 @@ function runAll(list: Array<() => Promise<unknown>>) {
|
||||
return Promise.allSettled(list.map((item) => item()))
|
||||
}
|
||||
|
||||
function showErrors(input: {
|
||||
errors: unknown[]
|
||||
title: string
|
||||
translate: (key: string, vars?: Record<string, string | number>) => string
|
||||
formatMoreCount: (count: number) => string
|
||||
}) {
|
||||
if (input.errors.length === 0) return
|
||||
const message = formatServerError(input.errors[0], input.translate)
|
||||
const more = input.errors.length > 1 ? input.formatMoreCount(input.errors.length - 1) : ""
|
||||
showToast({
|
||||
variant: "error",
|
||||
title: input.title,
|
||||
description: message + more,
|
||||
})
|
||||
}
|
||||
|
||||
export const loadGlobalConfigQuery = (
|
||||
sdk?: OpencodeClient,
|
||||
transform?: (x: Awaited<ReturnType<OpencodeClient["global"]["config"]["get"]>>) => void,
|
||||
) =>
|
||||
queryOptions({
|
||||
queryKey: ["config"],
|
||||
queryFn: sdk
|
||||
? () =>
|
||||
retry(() =>
|
||||
sdk.global.config.get().then((x) => {
|
||||
transform?.(x)
|
||||
return x.data!
|
||||
}),
|
||||
)
|
||||
: skipToken,
|
||||
})
|
||||
|
||||
export const loadProjectsQuery = (
|
||||
sdk?: OpencodeClient,
|
||||
transform?: (x: Awaited<ReturnType<OpencodeClient["project"]["list"]>>["data"]) => void,
|
||||
) =>
|
||||
queryOptions({
|
||||
queryKey: ["project"],
|
||||
queryFn: sdk
|
||||
? () =>
|
||||
retry(() =>
|
||||
sdk.project
|
||||
.list()
|
||||
.then((x) => {
|
||||
return (x.data ?? [])
|
||||
.filter((p) => !!p?.id)
|
||||
.filter((p) => !!p.worktree && !p.worktree.includes("opencode-test"))
|
||||
.slice()
|
||||
.sort((a, b) => cmp(a.id, b.id))
|
||||
})
|
||||
.then(transform),
|
||||
)
|
||||
: skipToken,
|
||||
})
|
||||
|
||||
export async function bootstrapGlobal(input: {
|
||||
globalSDK: OpencodeClient
|
||||
requestFailedTitle: string
|
||||
@@ -74,53 +131,15 @@ export async function bootstrapGlobal(input: {
|
||||
setGlobalStore: SetStoreFunction<GlobalStore>
|
||||
queryClient: QueryClient
|
||||
}) {
|
||||
const fast = [
|
||||
() =>
|
||||
retry(() =>
|
||||
input.globalSDK.global.config.get().then((x) => {
|
||||
input.setGlobalStore("config", x.data!)
|
||||
}),
|
||||
),
|
||||
]
|
||||
|
||||
const slow = [
|
||||
() => input.queryClient.fetchQuery(loadGlobalConfigQuery(input.globalSDK)),
|
||||
() => input.queryClient.fetchQuery(loadProvidersQuery(null, input.globalSDK)),
|
||||
() => input.queryClient.fetchQuery(loadPathQuery(null, input.globalSDK)),
|
||||
() =>
|
||||
input.queryClient.fetchQuery({
|
||||
...loadProvidersQuery(null),
|
||||
queryFn: () =>
|
||||
retry(() =>
|
||||
input.globalSDK.provider.list().then((x) => {
|
||||
input.setGlobalStore("provider", normalizeProviderList(x.data!))
|
||||
return null
|
||||
}),
|
||||
),
|
||||
}),
|
||||
() =>
|
||||
retry(() =>
|
||||
input.globalSDK.path.get().then((x) => {
|
||||
input.setGlobalStore("path", x.data!)
|
||||
}),
|
||||
),
|
||||
() =>
|
||||
retry(() =>
|
||||
input.globalSDK.project.list().then((x) => {
|
||||
const projects = (x.data ?? [])
|
||||
.filter((p) => !!p?.id)
|
||||
.filter((p) => !!p.worktree && !p.worktree.includes("opencode-test"))
|
||||
.slice()
|
||||
.sort((a, b) => cmp(a.id, b.id))
|
||||
input.setGlobalStore("project", projects)
|
||||
}),
|
||||
input.queryClient.fetchQuery(
|
||||
loadProjectsQuery(input.globalSDK, (data) => input.setGlobalStore("project", data ?? [])),
|
||||
),
|
||||
]
|
||||
await runAll(fast)
|
||||
// showErrors({
|
||||
// errors: errors(await runAll(fast)),
|
||||
// title: input.requestFailedTitle,
|
||||
// translate: input.translate,
|
||||
// formatMoreCount: input.formatMoreCount,
|
||||
// })
|
||||
await waitForPaint()
|
||||
await runAll(slow)
|
||||
// showErrors({
|
||||
// errors: errors(),
|
||||
@@ -128,7 +147,6 @@ export async function bootstrapGlobal(input: {
|
||||
// translate: input.translate,
|
||||
// formatMoreCount: input.formatMoreCount,
|
||||
// })
|
||||
input.setGlobalStore("ready", true)
|
||||
}
|
||||
|
||||
function groupBySession<T extends { id: string; sessionID: string }>(input: T[]) {
|
||||
@@ -179,26 +197,28 @@ function warmSessions(input: {
|
||||
).then(() => undefined)
|
||||
}
|
||||
|
||||
export const loadProvidersQuery = (directory: string | null) =>
|
||||
queryOptions<null>({ queryKey: [directory, "providers"], queryFn: skipToken })
|
||||
export const loadProvidersQuery = (directory: string | null, sdk?: OpencodeClient) =>
|
||||
queryOptions({
|
||||
queryKey: [directory, "providers"],
|
||||
queryFn: sdk ? () => retry(() => sdk.provider.list().then((x) => normalizeProviderList(x.data!))) : skipToken,
|
||||
})
|
||||
|
||||
export const loadAgentsQuery = (
|
||||
directory: string | null,
|
||||
sdk?: OpencodeClient,
|
||||
transform?: (x: Awaited<ReturnType<OpencodeClient["app"]["agents"]>>) => void,
|
||||
) =>
|
||||
queryOptions<null>({
|
||||
queryOptions({
|
||||
queryKey: [directory, "agents"],
|
||||
queryFn:
|
||||
sdk && transform
|
||||
? () =>
|
||||
retry(() =>
|
||||
sdk.app
|
||||
.agents()
|
||||
.then(transform)
|
||||
.then(() => null),
|
||||
)
|
||||
: skipToken,
|
||||
queryFn: sdk
|
||||
? () =>
|
||||
retry(() =>
|
||||
sdk.app.agents().then((x) => {
|
||||
transform?.(x)
|
||||
return x.data!
|
||||
}),
|
||||
)
|
||||
: skipToken,
|
||||
})
|
||||
|
||||
export const loadPathQuery = (
|
||||
@@ -208,16 +228,15 @@ export const loadPathQuery = (
|
||||
) =>
|
||||
queryOptions<Path>({
|
||||
queryKey: [directory, "path"],
|
||||
queryFn:
|
||||
sdk && transform
|
||||
? () =>
|
||||
retry(() =>
|
||||
sdk.path.get().then(async (x) => {
|
||||
transform(x)
|
||||
return x.data!
|
||||
}),
|
||||
)
|
||||
: skipToken,
|
||||
queryFn: sdk
|
||||
? () =>
|
||||
retry(() =>
|
||||
sdk.path.get().then(async (x) => {
|
||||
transform?.(x)
|
||||
return x.data!
|
||||
}),
|
||||
)
|
||||
: skipToken,
|
||||
})
|
||||
|
||||
export async function bootstrapDirectory(input: {
|
||||
@@ -245,15 +264,8 @@ export async function bootstrapDirectory(input: {
|
||||
input.setStore("provider", input.global.provider)
|
||||
}
|
||||
if (Object.keys(input.store.config).length === 0 && Object.keys(input.global.config).length > 0) {
|
||||
input.setStore("config", input.global.config)
|
||||
input.setStore("config", reconcile(input.global.config, { merge: false }))
|
||||
}
|
||||
if (loading || input.store.provider.all.length === 0) {
|
||||
input.setStore("provider_ready", false)
|
||||
}
|
||||
input.setStore("mcp_ready", false)
|
||||
input.setStore("mcp", {})
|
||||
input.setStore("lsp_ready", false)
|
||||
input.setStore("lsp", [])
|
||||
if (loading) input.setStore("status", "partial")
|
||||
|
||||
const rev = (providerRev.get(input.directory) ?? 0) + 1
|
||||
@@ -265,7 +277,8 @@ export async function bootstrapDirectory(input: {
|
||||
input.queryClient.ensureQueryData(
|
||||
loadAgentsQuery(input.directory, input.sdk, (x) => input.setStore("agent", normalizeAgentList(x.data))),
|
||||
),
|
||||
() => retry(() => input.sdk.config.get().then((x) => input.setStore("config", x.data!))),
|
||||
() =>
|
||||
retry(() => input.sdk.config.get().then((x) => input.setStore("config", reconcile(x.data!, { merge: false })))),
|
||||
() => retry(() => input.sdk.session.status().then((x) => input.setStore("session_status", x.data!))),
|
||||
!seededProject &&
|
||||
(() => retry(() => input.sdk.project.current()).then((x) => input.setStore("project", x.data!.id))),
|
||||
@@ -339,33 +352,15 @@ export async function bootstrapDirectory(input: {
|
||||
}),
|
||||
),
|
||||
() => Promise.resolve(input.loadSessions(input.directory)),
|
||||
() => input.queryClient.fetchQuery(loadMcpQuery(input.directory, input.sdk)),
|
||||
() =>
|
||||
retry(() =>
|
||||
input.sdk.mcp.status().then((x) => {
|
||||
input.setStore("mcp", x.data!)
|
||||
input.setStore("mcp_ready", true)
|
||||
}),
|
||||
),
|
||||
() =>
|
||||
input.queryClient.ensureQueryData({
|
||||
...loadProvidersQuery(input.directory),
|
||||
queryFn: () =>
|
||||
retry(() => input.sdk.provider.list())
|
||||
.then((x) => {
|
||||
if (providerRev.get(input.directory) !== rev) return
|
||||
input.setStore("provider", normalizeProviderList(x.data!))
|
||||
input.setStore("provider_ready", true)
|
||||
})
|
||||
.catch((err) => {
|
||||
if (providerRev.get(input.directory) !== rev) console.error("Failed to refresh provider list", err)
|
||||
const project = getFilename(input.directory)
|
||||
showToast({
|
||||
variant: "error",
|
||||
title: input.translate("toast.project.reloadFailed.title", { project }),
|
||||
description: formatServerError(err, input.translate),
|
||||
})
|
||||
})
|
||||
.then(() => null),
|
||||
input.queryClient.fetchQuery(loadProvidersQuery(input.directory, input.sdk)).catch((err) => {
|
||||
const project = getFilename(input.directory)
|
||||
showToast({
|
||||
variant: "error",
|
||||
title: input.translate("toast.project.reloadFailed.title", { project }),
|
||||
description: formatServerError(err, input.translate),
|
||||
})
|
||||
}),
|
||||
].filter(Boolean) as (() => Promise<any>)[]
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ describe("createChildStoreManager", () => {
|
||||
onBootstrap() {},
|
||||
onDispose() {},
|
||||
translate: (key) => key,
|
||||
getSdk: () => null!,
|
||||
})
|
||||
|
||||
Array.from({ length: 30 }, (_, index) => `/pinned-${index}`).forEach((directory) => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createRoot, getOwner, onCleanup, runWithOwner, type Owner } from "solid-js"
|
||||
import { createStore, type SetStoreFunction, type Store } from "solid-js/store"
|
||||
import { Persist, persisted } from "@/utils/persist"
|
||||
import type { VcsInfo } from "@opencode-ai/sdk/v2/client"
|
||||
import type { OpencodeClient, VcsInfo } from "@opencode-ai/sdk/v2/client"
|
||||
import {
|
||||
DIR_IDLE_TTL_MS,
|
||||
MAX_DIR_STORES,
|
||||
@@ -14,8 +14,9 @@ import {
|
||||
type VcsCache,
|
||||
} from "./types"
|
||||
import { canDisposeDirectory, pickDirectoriesToEvict } from "./eviction"
|
||||
import { useQuery } from "@tanstack/solid-query"
|
||||
import { loadPathQuery } from "./bootstrap"
|
||||
import { useQueries } from "@tanstack/solid-query"
|
||||
import { loadPathQuery, loadProvidersQuery } from "./bootstrap"
|
||||
import { loadLspQuery, loadMcpQuery } from "../global-sync"
|
||||
|
||||
export function createChildStoreManager(input: {
|
||||
owner: Owner
|
||||
@@ -24,6 +25,7 @@ export function createChildStoreManager(input: {
|
||||
onBootstrap: (directory: string) => void
|
||||
onDispose: (directory: string) => void
|
||||
translate: (key: string, vars?: Record<string, string | number>) => string
|
||||
getSdk: (directory: string) => OpencodeClient
|
||||
}) {
|
||||
const children: Record<string, [Store<State>, SetStoreFunction<State>]> = {}
|
||||
const vcsCache = new Map<string, VcsCache>()
|
||||
@@ -156,14 +158,27 @@ export function createChildStoreManager(input: {
|
||||
|
||||
const init = () =>
|
||||
createRoot((dispose) => {
|
||||
const sdk = input.getSdk(directory)
|
||||
|
||||
const initialMeta = meta[0].value
|
||||
const initialIcon = icon[0].value
|
||||
|
||||
const pathQuery = useQuery(() => loadPathQuery(directory))
|
||||
const [pathQuery, mcpQuery, lspQuery, providerQuery] = useQueries(() => ({
|
||||
queries: [
|
||||
loadPathQuery(directory, sdk),
|
||||
loadMcpQuery(directory, sdk),
|
||||
loadLspQuery(directory, sdk),
|
||||
loadProvidersQuery(directory, sdk),
|
||||
],
|
||||
}))
|
||||
|
||||
const child = createStore<State>({
|
||||
project: "",
|
||||
projectMeta: undefined,
|
||||
projectMeta: initialMeta,
|
||||
icon: initialIcon,
|
||||
provider_ready: false,
|
||||
get provider_ready() {
|
||||
return providerQuery.isLoading
|
||||
},
|
||||
provider: { all: [], connected: [], default: {} },
|
||||
config: {},
|
||||
get path() {
|
||||
@@ -181,10 +196,18 @@ export function createChildStoreManager(input: {
|
||||
todo: {},
|
||||
permission: {},
|
||||
question: {},
|
||||
mcp_ready: false,
|
||||
mcp: {},
|
||||
lsp_ready: false,
|
||||
lsp: [],
|
||||
get mcp_ready() {
|
||||
return mcpQuery.isLoading
|
||||
},
|
||||
get mcp() {
|
||||
return mcpQuery.isLoading ? {} : (mcpQuery.data ?? {})
|
||||
},
|
||||
get lsp_ready() {
|
||||
return lspQuery.isLoading
|
||||
},
|
||||
get lsp() {
|
||||
return lspQuery.isLoading ? [] : (lspQuery.data ?? [])
|
||||
},
|
||||
vcs: vcsStore.value,
|
||||
limit: 5,
|
||||
message: {},
|
||||
@@ -207,6 +230,11 @@ export function createChildStoreManager(input: {
|
||||
child[1]("vcs", (value) => value ?? cached)
|
||||
})
|
||||
|
||||
onPersistedInit(meta[2], () => {
|
||||
if (child[0].projectMeta !== initialMeta) return
|
||||
child[1]("projectMeta", meta[0].value)
|
||||
})
|
||||
|
||||
onPersistedInit(icon[2], () => {
|
||||
if (child[0].icon !== initialIcon) return
|
||||
child[1]("icon", icon[0].value)
|
||||
|
||||
@@ -391,7 +391,14 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext(
|
||||
? globalSync.data.project.find((x) => x.id === projectID)
|
||||
: globalSync.data.project.find((x) => x.worktree === project.worktree)
|
||||
|
||||
return { ...metadata, ...project }
|
||||
// Preserve local icon override from per-workspace localStorage cache (childStore.icon).
|
||||
// Without this, different subdirectories of the same git repo would share the same
|
||||
// icon from the database instead of using their individual overrides.
|
||||
const base = { ...metadata, ...project }
|
||||
if (childStore.icon) {
|
||||
return { ...base, icon: { ...base.icon, override: childStore.icon } }
|
||||
}
|
||||
return base
|
||||
}
|
||||
|
||||
const roots = createMemo(() => {
|
||||
|
||||
@@ -728,6 +728,11 @@ export const dict = {
|
||||
|
||||
"settings.general.row.language.title": "Language",
|
||||
"settings.general.row.language.description": "Change the display language for OpenCode",
|
||||
"settings.general.row.shell.title": "Terminal Shell",
|
||||
"settings.general.row.shell.description":
|
||||
"Choose the shell used for your terminal. Compatible shells are also used for agent tool calls.",
|
||||
"settings.general.row.shell.autoDefault": "Auto (Default)",
|
||||
"settings.general.row.shell.terminalOnly": "terminal only",
|
||||
"settings.general.row.appearance.title": "Appearance",
|
||||
"settings.general.row.appearance.description": "Customise how OpenCode looks on your device",
|
||||
"settings.general.row.colorScheme.title": "Color scheme",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/console-app",
|
||||
"version": "1.14.25",
|
||||
"version": "1.14.29",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@@ -204,6 +204,14 @@ export function IconGemini(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
|
||||
)
|
||||
}
|
||||
|
||||
export function IconDeepSeek(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
|
||||
return (
|
||||
<svg {...props} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M23.748 4.482c-.254-.124-.364.113-.512.234-.051.039-.094.09-.137.136-.372.397-.806.657-1.373.626-.829-.046-1.537.214-2.163.848-.133-.782-.575-1.249-1.247-1.548-.352-.156-.708-.311-.955-.65-.172-.241-.219-.51-.305-.774-.055-.16-.11-.323-.293-.35-.2-.031-.278.136-.356.276-.313.572-.434 1.202-.422 1.84.027 1.436.633 2.58 1.838 3.393.137.093.172.187.129.323-.082.28-.18.552-.266.833-.055.179-.137.217-.329.14a5.526 5.526 0 0 1-1.736-1.18c-.857-.828-1.631-1.742-2.597-2.458a11.365 11.365 0 0 0-.689-.471c-.985-.957.13-1.743.388-1.836.27-.098.093-.432-.779-.428-.872.004-1.67.295-2.687.684a3.055 3.055 0 0 1-.465.137 9.597 9.597 0 0 0-2.883-.102c-1.885.21-3.39 1.102-4.497 2.623C.082 8.606-.231 10.684.152 12.85c.403 2.284 1.569 4.175 3.36 5.653 1.858 1.533 3.997 2.284 6.438 2.14 1.482-.085 3.133-.284 4.994-1.86.47.234.962.327 1.78.397.63.059 1.236-.03 1.705-.128.735-.156.684-.837.419-.961-2.155-1.004-1.682-.595-2.113-.926 1.096-1.296 2.746-2.642 3.392-7.003.05-.347.007-.565 0-.845-.004-.17.035-.237.23-.256a4.173 4.173 0 0 0 1.545-.475c1.396-.763 1.96-2.015 2.093-3.517.02-.23-.004-.467-.247-.588zM11.581 18c-2.089-1.642-3.102-2.183-3.52-2.16-.392.024-.321.471-.235.763.09.288.207.486.371.739.114.167.192.416-.113.603-.673.416-1.842-.14-1.897-.167-1.361-.802-2.5-1.86-3.301-3.307-.774-1.393-1.224-2.887-1.298-4.482-.02-.386.093-.522.477-.592a4.696 4.696 0 0 1 1.529-.039c2.132.312 3.946 1.265 5.468 2.774.868.86 1.525 1.887 2.202 2.891.72 1.066 1.494 2.082 2.48 2.914.348.292.625.514.891.677-.802.09-2.14.11-3.054-.614zm1-6.44a.306.306 0 0 1 .415-.287.302.302 0 0 1 .2.288.306.306 0 0 1-.31.307.303.303 0 0 1-.304-.308zm3.11 1.596c-.2.081-.399.151-.59.16a1.245 1.245 0 0 1-.798-.254c-.274-.23-.47-.358-.552-.758a1.73 1.73 0 0 1 .016-.588c.07-.327-.008-.537-.239-.727-.187-.156-.426-.199-.688-.199a.559.559 0 0 1-.254-.078c-.11-.054-.2-.19-.114-.358.028-.054.16-.186.192-.21.356-.202.767-.136 1.146.016.352.144.618.408 1.001.782.391.451.462.576.685.914.176.265.336.537.445.848.067.195-.019.354-.25.452z" />
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export function IconMiMo(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
|
||||
return (
|
||||
<svg {...props} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
|
||||
|
||||
@@ -9,8 +9,8 @@ export const config = {
|
||||
github: {
|
||||
repoUrl: "https://github.com/anomalyco/opencode",
|
||||
starsFormatted: {
|
||||
compact: "140K",
|
||||
full: "140,000",
|
||||
compact: "150K",
|
||||
full: "150,000",
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import { Footer } from "~/component/footer"
|
||||
import { Header } from "~/component/header"
|
||||
import { config } from "~/config"
|
||||
import { getLastSeenWorkspaceID } from "../workspace/common"
|
||||
import { IconMiniMax, IconMiMo, IconZai, IconAlibaba } from "~/component/icon"
|
||||
import { IconMiniMax, IconMiMo, IconZai, IconAlibaba, IconDeepSeek } from "~/component/icon"
|
||||
import { useI18n } from "~/context/i18n"
|
||||
import { useLanguage } from "~/context/language"
|
||||
import { LocaleLinks } from "~/component/locale-links"
|
||||
@@ -65,11 +65,11 @@ function LimitsGraph(props: { href: string }) {
|
||||
{ id: "glm-5.1", name: "GLM-5.1", req: 880, d: "100ms" },
|
||||
{ id: "kimi-k2.6", name: "Kimi K2.6 (3x usage)", req: 3450, baseReq: 1150, d: "150ms" },
|
||||
{ id: "mimo-v2.5-pro", name: "MiMo-V2.5-Pro", req: 1290, d: "150ms" },
|
||||
{ id: "deepseek-v4-pro", name: "DeepSeek V4 Pro", req: 1300, d: "200ms" },
|
||||
{ id: "qwen3.6-plus", name: "Qwen3.6 Plus", req: 3300, d: "280ms" },
|
||||
{ id: "minimax-m2.7", name: "MiniMax M2.7", req: 3400, d: "300ms" },
|
||||
{ id: "deepseek-v4-flash", name: "DeepSeek V4 Flash", req: 7450, d: "340ms" },
|
||||
{ id: "deepseek-v4-pro", name: "DeepSeek V4 Pro", req: 3450, d: "200ms" },
|
||||
{ id: "qwen3.5-plus", name: "Qwen3.5 Plus", req: 10200, d: "360ms" },
|
||||
{ id: "deepseek-v4-flash", name: "DeepSeek V4 Flash", req: 31650, d: "340ms" },
|
||||
]
|
||||
|
||||
const w = 720
|
||||
@@ -340,6 +340,9 @@ export default function Home() {
|
||||
<div>
|
||||
<IconAlibaba width="24" height="24" />
|
||||
</div>
|
||||
<div>
|
||||
<IconDeepSeek width="24" height="24" />
|
||||
</div>
|
||||
<div>
|
||||
<IconMiMo width="24" height="24" />
|
||||
</div>
|
||||
|
||||
@@ -160,8 +160,16 @@ export async function POST(input: APIEvent) {
|
||||
userID: userID,
|
||||
})
|
||||
|
||||
if (userEmail && coupon === LiteData.firstMonth100Coupon) {
|
||||
await Billing.redeemCoupon(userEmail, "GOFREEMONTH")
|
||||
if (userEmail) {
|
||||
if (coupon === LiteData.firstMonth100Coupon) {
|
||||
await Billing.redeemCoupon(userEmail, "GOFREEMONTH")
|
||||
} else if (coupon === LiteData.threeMonths100Coupon) {
|
||||
await Billing.redeemCoupon(userEmail, "GO3MONTHS100")
|
||||
} else if (coupon === LiteData.sixMonths100Coupon) {
|
||||
await Billing.redeemCoupon(userEmail, "GO6MONTHS100")
|
||||
} else if (coupon === LiteData.twelveMonths100Coupon) {
|
||||
await Billing.redeemCoupon(userEmail, "GO12MONTHS100")
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
@@ -24,15 +24,23 @@ import { useI18n } from "~/context/i18n"
|
||||
|
||||
Chart.register(BarController, BarElement, CategoryScale, LinearScale, Tooltip, Legend)
|
||||
|
||||
async function getCosts(workspaceID: string, year: number, month: number) {
|
||||
async function getCosts(workspaceID: string, year: number, month: number, tzOffset: string) {
|
||||
"use server"
|
||||
return withActor(async () => {
|
||||
const startDate = new Date(year, month, 1)
|
||||
const endDate = new Date(year, month + 1, 1)
|
||||
const timezoneOffset = (() => {
|
||||
const m = /^([+-])(\d{2}):(\d{2})$/.exec(tzOffset)
|
||||
if (!m) return 0
|
||||
const sign = m[1] === "-" ? -1 : 1
|
||||
return sign * (Number(m[2]) * 60 + Number(m[3])) * 60_000
|
||||
})()
|
||||
|
||||
const monthStartUTC = new Date(Date.UTC(year, month, 1, 0, 0, 0) - timezoneOffset)
|
||||
const monthEndUTC = new Date(Date.UTC(year, month + 1, 1, 0, 0, 0) - timezoneOffset)
|
||||
const dateExpr = sql<string>`DATE(CONVERT_TZ(${UsageTable.timeCreated}, '+00:00', ${tzOffset}))`
|
||||
const usageData = await Database.use((tx) =>
|
||||
tx
|
||||
.select({
|
||||
date: sql<string>`DATE(${UsageTable.timeCreated})`,
|
||||
date: dateExpr,
|
||||
model: UsageTable.model,
|
||||
totalCost: sum(UsageTable.cost),
|
||||
keyId: UsageTable.keyID,
|
||||
@@ -42,16 +50,11 @@ async function getCosts(workspaceID: string, year: number, month: number) {
|
||||
.where(
|
||||
and(
|
||||
eq(UsageTable.workspaceID, workspaceID),
|
||||
gte(UsageTable.timeCreated, startDate),
|
||||
lt(UsageTable.timeCreated, endDate),
|
||||
gte(UsageTable.timeCreated, monthStartUTC),
|
||||
lt(UsageTable.timeCreated, monthEndUTC),
|
||||
),
|
||||
)
|
||||
.groupBy(
|
||||
sql`DATE(${UsageTable.timeCreated})`,
|
||||
UsageTable.model,
|
||||
UsageTable.keyID,
|
||||
sql`JSON_EXTRACT(${UsageTable.enrichment}, '$.plan')`,
|
||||
)
|
||||
.groupBy(dateExpr, UsageTable.model, UsageTable.keyID, sql`JSON_EXTRACT(${UsageTable.enrichment}, '$.plan')`)
|
||||
.then((x) =>
|
||||
x.map((r) => ({
|
||||
...r,
|
||||
@@ -125,15 +128,45 @@ function getModelColor(model: string): string {
|
||||
}
|
||||
|
||||
function formatDateLabel(dateStr: string): string {
|
||||
const date = new Date()
|
||||
const [y, m, d] = dateStr.split("-").map(Number)
|
||||
date.setFullYear(y)
|
||||
date.setMonth(m - 1)
|
||||
date.setDate(d)
|
||||
date.setHours(0, 0, 0, 0)
|
||||
const month = date.toLocaleDateString(undefined, { month: "short" })
|
||||
const day = date.getUTCDate().toString().padStart(2, "0")
|
||||
return `${month} ${day}`
|
||||
const [, m, d] = dateStr.split("-").map(Number)
|
||||
const month = new Date(2000, m - 1, 1).toLocaleDateString(undefined, { month: "short" })
|
||||
return `${month} ${d.toString().padStart(2, "0")}`
|
||||
}
|
||||
|
||||
// Compute the UTC offset (in MySQL CONVERT_TZ format like "+05:30") for the
|
||||
// given IANA timezone at the given instant. Honors DST.
|
||||
function getTimezoneOffset(timezone: string, at: Date): string {
|
||||
const parts = new Intl.DateTimeFormat("en-US", {
|
||||
timeZone: timezone,
|
||||
hourCycle: "h23",
|
||||
year: "numeric",
|
||||
month: "2-digit",
|
||||
day: "2-digit",
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
second: "2-digit",
|
||||
})
|
||||
.formatToParts(at)
|
||||
.reduce<Record<string, string>>((acc, p) => {
|
||||
if (p.type !== "literal") acc[p.type] = p.value
|
||||
return acc
|
||||
}, {})
|
||||
const asUTC = Date.UTC(
|
||||
Number(parts.year),
|
||||
Number(parts.month) - 1,
|
||||
Number(parts.day),
|
||||
Number(parts.hour),
|
||||
Number(parts.minute),
|
||||
Number(parts.second),
|
||||
)
|
||||
const diffMinutes = Math.round((asUTC - at.getTime()) / 60_000)
|
||||
const sign = diffMinutes < 0 ? "-" : "+"
|
||||
const abs = Math.abs(diffMinutes)
|
||||
const hh = Math.floor(abs / 60)
|
||||
.toString()
|
||||
.padStart(2, "0")
|
||||
const mm = (abs % 60).toString().padStart(2, "0")
|
||||
return `${sign}${hh}:${mm}`
|
||||
}
|
||||
|
||||
function addOpacityToColor(color: string, opacity: number): string {
|
||||
@@ -152,6 +185,7 @@ export function GraphSection() {
|
||||
let chartInstance: Chart | undefined
|
||||
const params = useParams()
|
||||
const i18n = useI18n()
|
||||
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone
|
||||
const now = new Date()
|
||||
const [store, setStore] = createStore({
|
||||
data: null as Awaited<ReturnType<typeof getCosts>> | null,
|
||||
@@ -185,10 +219,13 @@ export function GraphSection() {
|
||||
})
|
||||
|
||||
const getDates = createMemo(() => {
|
||||
const daysInMonth = new Date(store.year, store.month + 1, 0).getDate()
|
||||
// Number of days in the month is independent of timezone.
|
||||
const daysInMonth = new Date(Date.UTC(store.year, store.month + 1, 0)).getUTCDate()
|
||||
const yyyy = store.year.toString().padStart(4, "0")
|
||||
const mm = (store.month + 1).toString().padStart(2, "0")
|
||||
return Array.from({ length: daysInMonth }, (_, i) => {
|
||||
const date = new Date(store.year, store.month, i + 1)
|
||||
return date.toISOString().split("T")[0]
|
||||
const dd = (i + 1).toString().padStart(2, "0")
|
||||
return `${yyyy}-${mm}-${dd}`
|
||||
})
|
||||
})
|
||||
|
||||
@@ -415,7 +452,11 @@ export function GraphSection() {
|
||||
})
|
||||
|
||||
createEffect(async () => {
|
||||
const data = await getCosts(params.id!, store.year, store.month)
|
||||
// Compute the offset for mid-month so DST transitions don't bias to the
|
||||
// wrong side.
|
||||
const midMonth = new Date(Date.UTC(store.year, store.month, 15, 12, 0, 0))
|
||||
const tzOffset = getTimezoneOffset(timezone, midMonth)
|
||||
const data = await getCosts(params.id!, store.year, store.month, tzOffset)
|
||||
setStore({ data })
|
||||
})
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import type { APIEvent } from "@solidjs/start/server"
|
||||
import { ZenData } from "@opencode-ai/console-core/model.js"
|
||||
import { buildModelsResponse, buildOptionsResponse } from "../../util/modelsHandler"
|
||||
|
||||
export async function OPTIONS(_input: APIEvent) {
|
||||
return buildOptionsResponse()
|
||||
}
|
||||
|
||||
export async function GET(_input: APIEvent) {
|
||||
const models = Object.keys(ZenData.list("lite").models)
|
||||
return buildModelsResponse(models)
|
||||
}
|
||||
@@ -101,12 +101,13 @@ export async function handler(
|
||||
const requestId = input.request.headers.get("x-opencode-request") ?? ""
|
||||
const projectId = input.request.headers.get("x-opencode-project") ?? ""
|
||||
const ocClient = input.request.headers.get("x-opencode-client") ?? ""
|
||||
const userAgent = input.request.headers.get("user-agent") ?? ""
|
||||
logger.metric({
|
||||
is_stream: isStream,
|
||||
session: sessionId,
|
||||
request: requestId,
|
||||
client: ocClient,
|
||||
...(model === "mimo-v2-pro-free" && JSON.stringify(body).length < 1000 ? { payload: JSON.stringify(body) } : {}),
|
||||
user_agent: userAgent,
|
||||
})
|
||||
const zenData = ZenData.list(opts.modelList)
|
||||
const modelInfo = validateModel(zenData, model)
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
export async function buildOptionsResponse() {
|
||||
return new Response(null, {
|
||||
status: 200,
|
||||
headers: {
|
||||
"Access-Control-Allow-Origin": "*",
|
||||
"Access-Control-Allow-Methods": "GET, POST, OPTIONS",
|
||||
"Access-Control-Allow-Headers": "Content-Type, Authorization",
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export async function buildModelsResponse(models: string[]) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
object: "list",
|
||||
data: models
|
||||
.filter((id) => !id.startsWith("alpha-"))
|
||||
.map((id) => ({
|
||||
id,
|
||||
object: "model",
|
||||
created: Math.floor(Date.now() / 1000),
|
||||
owned_by: "opencode",
|
||||
})),
|
||||
}),
|
||||
{
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
@@ -1,61 +1,34 @@
|
||||
import type { APIEvent } from "@solidjs/start/server"
|
||||
import { ZenData } from "@opencode-ai/console-core/model.js"
|
||||
import { and, Database, eq, isNull } from "@opencode-ai/console-core/drizzle/index.js"
|
||||
import { KeyTable } from "@opencode-ai/console-core/schema/key.sql.js"
|
||||
import { WorkspaceTable } from "@opencode-ai/console-core/schema/workspace.sql.js"
|
||||
import { ModelTable } from "@opencode-ai/console-core/schema/model.sql.js"
|
||||
import { ZenData } from "@opencode-ai/console-core/model.js"
|
||||
import { buildOptionsResponse, buildModelsResponse } from "~/routes/zen/util/modelsHandler"
|
||||
|
||||
export async function OPTIONS(_input: APIEvent) {
|
||||
return new Response(null, {
|
||||
status: 200,
|
||||
headers: {
|
||||
"Access-Control-Allow-Origin": "*",
|
||||
"Access-Control-Allow-Methods": "GET, POST, OPTIONS",
|
||||
"Access-Control-Allow-Headers": "Content-Type, Authorization",
|
||||
},
|
||||
})
|
||||
return buildOptionsResponse()
|
||||
}
|
||||
|
||||
export async function GET(input: APIEvent) {
|
||||
const zenData = ZenData.list("full")
|
||||
const disabledModels = await authenticate()
|
||||
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
object: "list",
|
||||
data: Object.entries(zenData.models)
|
||||
.filter(([id]) => !disabledModels.includes(id))
|
||||
.filter(([id]) => !id.startsWith("alpha-"))
|
||||
.map(([id, _model]) => ({
|
||||
id,
|
||||
object: "model",
|
||||
created: Math.floor(Date.now() / 1000),
|
||||
owned_by: "opencode",
|
||||
})),
|
||||
}),
|
||||
{
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
async function authenticate() {
|
||||
const disabledModels = await (() => {
|
||||
const apiKey = input.request.headers.get("authorization")?.split(" ")[1]
|
||||
if (!apiKey) return []
|
||||
if (!apiKey) return [] as string[]
|
||||
|
||||
const disabledModels = await Database.use((tx) =>
|
||||
return Database.use((tx) =>
|
||||
tx
|
||||
.select({
|
||||
model: ModelTable.model,
|
||||
})
|
||||
.from(KeyTable)
|
||||
.innerJoin(WorkspaceTable, eq(WorkspaceTable.id, KeyTable.workspaceID))
|
||||
.leftJoin(ModelTable, and(eq(ModelTable.workspaceID, KeyTable.workspaceID), isNull(ModelTable.timeDeleted)))
|
||||
.innerJoin(ModelTable, and(eq(ModelTable.workspaceID, KeyTable.workspaceID), isNull(ModelTable.timeDeleted)))
|
||||
.where(and(eq(KeyTable.key, apiKey), isNull(KeyTable.timeDeleted)))
|
||||
.then((rows) => rows.map((row) => row.model)),
|
||||
)
|
||||
})()
|
||||
|
||||
return disabledModels
|
||||
}
|
||||
const models = Object.keys(ZenData.list("full").models).filter((id) => !disabledModels.includes(id))
|
||||
|
||||
return buildModelsResponse(models)
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE `coupon` MODIFY COLUMN `type` enum('BUILDATHON','GOFREEMONTH','GO3MONTHS100','GO6MONTHS100','GO12MONTHS100') NOT NULL;
|
||||
@@ -0,0 +1,2619 @@
|
||||
{
|
||||
"version": "6",
|
||||
"dialect": "mysql",
|
||||
"id": "b3b243c0-8097-4d8a-a439-243d5a7d543f",
|
||||
"prevIds": ["9e2d81ba-88b4-4704-a8b6-4a27dd2bd8d9"],
|
||||
"ddl": [
|
||||
{
|
||||
"name": "account",
|
||||
"entityType": "tables"
|
||||
},
|
||||
{
|
||||
"name": "auth",
|
||||
"entityType": "tables"
|
||||
},
|
||||
{
|
||||
"name": "benchmark",
|
||||
"entityType": "tables"
|
||||
},
|
||||
{
|
||||
"name": "billing",
|
||||
"entityType": "tables"
|
||||
},
|
||||
{
|
||||
"name": "coupon",
|
||||
"entityType": "tables"
|
||||
},
|
||||
{
|
||||
"name": "lite",
|
||||
"entityType": "tables"
|
||||
},
|
||||
{
|
||||
"name": "payment",
|
||||
"entityType": "tables"
|
||||
},
|
||||
{
|
||||
"name": "subscription",
|
||||
"entityType": "tables"
|
||||
},
|
||||
{
|
||||
"name": "usage",
|
||||
"entityType": "tables"
|
||||
},
|
||||
{
|
||||
"name": "ip_rate_limit",
|
||||
"entityType": "tables"
|
||||
},
|
||||
{
|
||||
"name": "ip",
|
||||
"entityType": "tables"
|
||||
},
|
||||
{
|
||||
"name": "key_rate_limit",
|
||||
"entityType": "tables"
|
||||
},
|
||||
{
|
||||
"name": "model_tpm_rate_limit",
|
||||
"entityType": "tables"
|
||||
},
|
||||
{
|
||||
"name": "key",
|
||||
"entityType": "tables"
|
||||
},
|
||||
{
|
||||
"name": "model",
|
||||
"entityType": "tables"
|
||||
},
|
||||
{
|
||||
"name": "provider",
|
||||
"entityType": "tables"
|
||||
},
|
||||
{
|
||||
"name": "user",
|
||||
"entityType": "tables"
|
||||
},
|
||||
{
|
||||
"name": "workspace",
|
||||
"entityType": "tables"
|
||||
},
|
||||
{
|
||||
"type": "varchar(30)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "id",
|
||||
"entityType": "columns",
|
||||
"table": "account"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": "(now())",
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_created",
|
||||
"entityType": "columns",
|
||||
"table": "account"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": "(CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3))",
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_updated",
|
||||
"entityType": "columns",
|
||||
"table": "account"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_deleted",
|
||||
"entityType": "columns",
|
||||
"table": "account"
|
||||
},
|
||||
{
|
||||
"type": "varchar(30)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "id",
|
||||
"entityType": "columns",
|
||||
"table": "auth"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": "(now())",
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_created",
|
||||
"entityType": "columns",
|
||||
"table": "auth"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": "(CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3))",
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_updated",
|
||||
"entityType": "columns",
|
||||
"table": "auth"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_deleted",
|
||||
"entityType": "columns",
|
||||
"table": "auth"
|
||||
},
|
||||
{
|
||||
"type": "enum('email','github','google')",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "provider",
|
||||
"entityType": "columns",
|
||||
"table": "auth"
|
||||
},
|
||||
{
|
||||
"type": "varchar(255)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "subject",
|
||||
"entityType": "columns",
|
||||
"table": "auth"
|
||||
},
|
||||
{
|
||||
"type": "varchar(30)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "account_id",
|
||||
"entityType": "columns",
|
||||
"table": "auth"
|
||||
},
|
||||
{
|
||||
"type": "varchar(30)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "id",
|
||||
"entityType": "columns",
|
||||
"table": "benchmark"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": "(now())",
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_created",
|
||||
"entityType": "columns",
|
||||
"table": "benchmark"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": "(CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3))",
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_updated",
|
||||
"entityType": "columns",
|
||||
"table": "benchmark"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_deleted",
|
||||
"entityType": "columns",
|
||||
"table": "benchmark"
|
||||
},
|
||||
{
|
||||
"type": "varchar(64)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "model",
|
||||
"entityType": "columns",
|
||||
"table": "benchmark"
|
||||
},
|
||||
{
|
||||
"type": "varchar(64)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "agent",
|
||||
"entityType": "columns",
|
||||
"table": "benchmark"
|
||||
},
|
||||
{
|
||||
"type": "mediumtext",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "result",
|
||||
"entityType": "columns",
|
||||
"table": "benchmark"
|
||||
},
|
||||
{
|
||||
"type": "varchar(30)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "id",
|
||||
"entityType": "columns",
|
||||
"table": "billing"
|
||||
},
|
||||
{
|
||||
"type": "varchar(30)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "workspace_id",
|
||||
"entityType": "columns",
|
||||
"table": "billing"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": "(now())",
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_created",
|
||||
"entityType": "columns",
|
||||
"table": "billing"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": "(CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3))",
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_updated",
|
||||
"entityType": "columns",
|
||||
"table": "billing"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_deleted",
|
||||
"entityType": "columns",
|
||||
"table": "billing"
|
||||
},
|
||||
{
|
||||
"type": "varchar(255)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "customer_id",
|
||||
"entityType": "columns",
|
||||
"table": "billing"
|
||||
},
|
||||
{
|
||||
"type": "varchar(255)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "payment_method_id",
|
||||
"entityType": "columns",
|
||||
"table": "billing"
|
||||
},
|
||||
{
|
||||
"type": "varchar(32)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "payment_method_type",
|
||||
"entityType": "columns",
|
||||
"table": "billing"
|
||||
},
|
||||
{
|
||||
"type": "varchar(4)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "payment_method_last4",
|
||||
"entityType": "columns",
|
||||
"table": "billing"
|
||||
},
|
||||
{
|
||||
"type": "bigint",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "balance",
|
||||
"entityType": "columns",
|
||||
"table": "billing"
|
||||
},
|
||||
{
|
||||
"type": "int",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "monthly_limit",
|
||||
"entityType": "columns",
|
||||
"table": "billing"
|
||||
},
|
||||
{
|
||||
"type": "bigint",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "monthly_usage",
|
||||
"entityType": "columns",
|
||||
"table": "billing"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_monthly_usage_updated",
|
||||
"entityType": "columns",
|
||||
"table": "billing"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "reload",
|
||||
"entityType": "columns",
|
||||
"table": "billing"
|
||||
},
|
||||
{
|
||||
"type": "int",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "reload_trigger",
|
||||
"entityType": "columns",
|
||||
"table": "billing"
|
||||
},
|
||||
{
|
||||
"type": "int",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "reload_amount",
|
||||
"entityType": "columns",
|
||||
"table": "billing"
|
||||
},
|
||||
{
|
||||
"type": "varchar(255)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "reload_error",
|
||||
"entityType": "columns",
|
||||
"table": "billing"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_reload_error",
|
||||
"entityType": "columns",
|
||||
"table": "billing"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_reload_locked_till",
|
||||
"entityType": "columns",
|
||||
"table": "billing"
|
||||
},
|
||||
{
|
||||
"type": "json",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "subscription",
|
||||
"entityType": "columns",
|
||||
"table": "billing"
|
||||
},
|
||||
{
|
||||
"type": "varchar(28)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "subscription_id",
|
||||
"entityType": "columns",
|
||||
"table": "billing"
|
||||
},
|
||||
{
|
||||
"type": "enum('20','100','200')",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "subscription_plan",
|
||||
"entityType": "columns",
|
||||
"table": "billing"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_subscription_booked",
|
||||
"entityType": "columns",
|
||||
"table": "billing"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_subscription_selected",
|
||||
"entityType": "columns",
|
||||
"table": "billing"
|
||||
},
|
||||
{
|
||||
"type": "varchar(28)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "lite_subscription_id",
|
||||
"entityType": "columns",
|
||||
"table": "billing"
|
||||
},
|
||||
{
|
||||
"type": "json",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "lite",
|
||||
"entityType": "columns",
|
||||
"table": "billing"
|
||||
},
|
||||
{
|
||||
"type": "varchar(255)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "email",
|
||||
"entityType": "columns",
|
||||
"table": "coupon"
|
||||
},
|
||||
{
|
||||
"type": "enum('BUILDATHON','GOFREEMONTH','GO3MONTHS100','GO6MONTHS100','GO12MONTHS100')",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "type",
|
||||
"entityType": "columns",
|
||||
"table": "coupon"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_redeemed",
|
||||
"entityType": "columns",
|
||||
"table": "coupon"
|
||||
},
|
||||
{
|
||||
"type": "varchar(30)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "id",
|
||||
"entityType": "columns",
|
||||
"table": "lite"
|
||||
},
|
||||
{
|
||||
"type": "varchar(30)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "workspace_id",
|
||||
"entityType": "columns",
|
||||
"table": "lite"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": "(now())",
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_created",
|
||||
"entityType": "columns",
|
||||
"table": "lite"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": "(CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3))",
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_updated",
|
||||
"entityType": "columns",
|
||||
"table": "lite"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_deleted",
|
||||
"entityType": "columns",
|
||||
"table": "lite"
|
||||
},
|
||||
{
|
||||
"type": "varchar(30)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "user_id",
|
||||
"entityType": "columns",
|
||||
"table": "lite"
|
||||
},
|
||||
{
|
||||
"type": "bigint",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "rolling_usage",
|
||||
"entityType": "columns",
|
||||
"table": "lite"
|
||||
},
|
||||
{
|
||||
"type": "bigint",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "weekly_usage",
|
||||
"entityType": "columns",
|
||||
"table": "lite"
|
||||
},
|
||||
{
|
||||
"type": "bigint",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "monthly_usage",
|
||||
"entityType": "columns",
|
||||
"table": "lite"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_rolling_updated",
|
||||
"entityType": "columns",
|
||||
"table": "lite"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_weekly_updated",
|
||||
"entityType": "columns",
|
||||
"table": "lite"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_monthly_updated",
|
||||
"entityType": "columns",
|
||||
"table": "lite"
|
||||
},
|
||||
{
|
||||
"type": "varchar(30)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "id",
|
||||
"entityType": "columns",
|
||||
"table": "payment"
|
||||
},
|
||||
{
|
||||
"type": "varchar(30)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "workspace_id",
|
||||
"entityType": "columns",
|
||||
"table": "payment"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": "(now())",
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_created",
|
||||
"entityType": "columns",
|
||||
"table": "payment"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": "(CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3))",
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_updated",
|
||||
"entityType": "columns",
|
||||
"table": "payment"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_deleted",
|
||||
"entityType": "columns",
|
||||
"table": "payment"
|
||||
},
|
||||
{
|
||||
"type": "varchar(255)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "customer_id",
|
||||
"entityType": "columns",
|
||||
"table": "payment"
|
||||
},
|
||||
{
|
||||
"type": "varchar(255)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "invoice_id",
|
||||
"entityType": "columns",
|
||||
"table": "payment"
|
||||
},
|
||||
{
|
||||
"type": "varchar(255)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "payment_id",
|
||||
"entityType": "columns",
|
||||
"table": "payment"
|
||||
},
|
||||
{
|
||||
"type": "bigint",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "amount",
|
||||
"entityType": "columns",
|
||||
"table": "payment"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_refunded",
|
||||
"entityType": "columns",
|
||||
"table": "payment"
|
||||
},
|
||||
{
|
||||
"type": "json",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "enrichment",
|
||||
"entityType": "columns",
|
||||
"table": "payment"
|
||||
},
|
||||
{
|
||||
"type": "varchar(30)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "id",
|
||||
"entityType": "columns",
|
||||
"table": "subscription"
|
||||
},
|
||||
{
|
||||
"type": "varchar(30)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "workspace_id",
|
||||
"entityType": "columns",
|
||||
"table": "subscription"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": "(now())",
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_created",
|
||||
"entityType": "columns",
|
||||
"table": "subscription"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": "(CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3))",
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_updated",
|
||||
"entityType": "columns",
|
||||
"table": "subscription"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_deleted",
|
||||
"entityType": "columns",
|
||||
"table": "subscription"
|
||||
},
|
||||
{
|
||||
"type": "varchar(30)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "user_id",
|
||||
"entityType": "columns",
|
||||
"table": "subscription"
|
||||
},
|
||||
{
|
||||
"type": "bigint",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "rolling_usage",
|
||||
"entityType": "columns",
|
||||
"table": "subscription"
|
||||
},
|
||||
{
|
||||
"type": "bigint",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "fixed_usage",
|
||||
"entityType": "columns",
|
||||
"table": "subscription"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_rolling_updated",
|
||||
"entityType": "columns",
|
||||
"table": "subscription"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_fixed_updated",
|
||||
"entityType": "columns",
|
||||
"table": "subscription"
|
||||
},
|
||||
{
|
||||
"type": "varchar(30)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "id",
|
||||
"entityType": "columns",
|
||||
"table": "usage"
|
||||
},
|
||||
{
|
||||
"type": "varchar(30)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "workspace_id",
|
||||
"entityType": "columns",
|
||||
"table": "usage"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": "(now())",
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_created",
|
||||
"entityType": "columns",
|
||||
"table": "usage"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": "(CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3))",
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_updated",
|
||||
"entityType": "columns",
|
||||
"table": "usage"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_deleted",
|
||||
"entityType": "columns",
|
||||
"table": "usage"
|
||||
},
|
||||
{
|
||||
"type": "varchar(255)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "model",
|
||||
"entityType": "columns",
|
||||
"table": "usage"
|
||||
},
|
||||
{
|
||||
"type": "varchar(255)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "provider",
|
||||
"entityType": "columns",
|
||||
"table": "usage"
|
||||
},
|
||||
{
|
||||
"type": "int",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "input_tokens",
|
||||
"entityType": "columns",
|
||||
"table": "usage"
|
||||
},
|
||||
{
|
||||
"type": "int",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "output_tokens",
|
||||
"entityType": "columns",
|
||||
"table": "usage"
|
||||
},
|
||||
{
|
||||
"type": "int",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "reasoning_tokens",
|
||||
"entityType": "columns",
|
||||
"table": "usage"
|
||||
},
|
||||
{
|
||||
"type": "int",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "cache_read_tokens",
|
||||
"entityType": "columns",
|
||||
"table": "usage"
|
||||
},
|
||||
{
|
||||
"type": "int",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "cache_write_5m_tokens",
|
||||
"entityType": "columns",
|
||||
"table": "usage"
|
||||
},
|
||||
{
|
||||
"type": "int",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "cache_write_1h_tokens",
|
||||
"entityType": "columns",
|
||||
"table": "usage"
|
||||
},
|
||||
{
|
||||
"type": "bigint",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "cost",
|
||||
"entityType": "columns",
|
||||
"table": "usage"
|
||||
},
|
||||
{
|
||||
"type": "varchar(30)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "key_id",
|
||||
"entityType": "columns",
|
||||
"table": "usage"
|
||||
},
|
||||
{
|
||||
"type": "varchar(30)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "session_id",
|
||||
"entityType": "columns",
|
||||
"table": "usage"
|
||||
},
|
||||
{
|
||||
"type": "json",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "enrichment",
|
||||
"entityType": "columns",
|
||||
"table": "usage"
|
||||
},
|
||||
{
|
||||
"type": "varchar(45)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "ip",
|
||||
"entityType": "columns",
|
||||
"table": "ip_rate_limit"
|
||||
},
|
||||
{
|
||||
"type": "varchar(10)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "interval",
|
||||
"entityType": "columns",
|
||||
"table": "ip_rate_limit"
|
||||
},
|
||||
{
|
||||
"type": "int",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "count",
|
||||
"entityType": "columns",
|
||||
"table": "ip_rate_limit"
|
||||
},
|
||||
{
|
||||
"type": "varchar(45)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "ip",
|
||||
"entityType": "columns",
|
||||
"table": "ip"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": "(now())",
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_created",
|
||||
"entityType": "columns",
|
||||
"table": "ip"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": "(CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3))",
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_updated",
|
||||
"entityType": "columns",
|
||||
"table": "ip"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_deleted",
|
||||
"entityType": "columns",
|
||||
"table": "ip"
|
||||
},
|
||||
{
|
||||
"type": "int",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "usage",
|
||||
"entityType": "columns",
|
||||
"table": "ip"
|
||||
},
|
||||
{
|
||||
"type": "varchar(255)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "key",
|
||||
"entityType": "columns",
|
||||
"table": "key_rate_limit"
|
||||
},
|
||||
{
|
||||
"type": "varchar(40)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "interval",
|
||||
"entityType": "columns",
|
||||
"table": "key_rate_limit"
|
||||
},
|
||||
{
|
||||
"type": "int",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "count",
|
||||
"entityType": "columns",
|
||||
"table": "key_rate_limit"
|
||||
},
|
||||
{
|
||||
"type": "varchar(255)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "id",
|
||||
"entityType": "columns",
|
||||
"table": "model_tpm_rate_limit"
|
||||
},
|
||||
{
|
||||
"type": "bigint",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "interval",
|
||||
"entityType": "columns",
|
||||
"table": "model_tpm_rate_limit"
|
||||
},
|
||||
{
|
||||
"type": "int",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "count",
|
||||
"entityType": "columns",
|
||||
"table": "model_tpm_rate_limit"
|
||||
},
|
||||
{
|
||||
"type": "varchar(30)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "id",
|
||||
"entityType": "columns",
|
||||
"table": "key"
|
||||
},
|
||||
{
|
||||
"type": "varchar(30)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "workspace_id",
|
||||
"entityType": "columns",
|
||||
"table": "key"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": "(now())",
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_created",
|
||||
"entityType": "columns",
|
||||
"table": "key"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": "(CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3))",
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_updated",
|
||||
"entityType": "columns",
|
||||
"table": "key"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_deleted",
|
||||
"entityType": "columns",
|
||||
"table": "key"
|
||||
},
|
||||
{
|
||||
"type": "varchar(255)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "name",
|
||||
"entityType": "columns",
|
||||
"table": "key"
|
||||
},
|
||||
{
|
||||
"type": "varchar(255)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "key",
|
||||
"entityType": "columns",
|
||||
"table": "key"
|
||||
},
|
||||
{
|
||||
"type": "varchar(30)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "user_id",
|
||||
"entityType": "columns",
|
||||
"table": "key"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_used",
|
||||
"entityType": "columns",
|
||||
"table": "key"
|
||||
},
|
||||
{
|
||||
"type": "varchar(30)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "id",
|
||||
"entityType": "columns",
|
||||
"table": "model"
|
||||
},
|
||||
{
|
||||
"type": "varchar(30)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "workspace_id",
|
||||
"entityType": "columns",
|
||||
"table": "model"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": "(now())",
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_created",
|
||||
"entityType": "columns",
|
||||
"table": "model"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": "(CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3))",
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_updated",
|
||||
"entityType": "columns",
|
||||
"table": "model"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_deleted",
|
||||
"entityType": "columns",
|
||||
"table": "model"
|
||||
},
|
||||
{
|
||||
"type": "varchar(64)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "model",
|
||||
"entityType": "columns",
|
||||
"table": "model"
|
||||
},
|
||||
{
|
||||
"type": "varchar(30)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "id",
|
||||
"entityType": "columns",
|
||||
"table": "provider"
|
||||
},
|
||||
{
|
||||
"type": "varchar(30)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "workspace_id",
|
||||
"entityType": "columns",
|
||||
"table": "provider"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": "(now())",
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_created",
|
||||
"entityType": "columns",
|
||||
"table": "provider"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": "(CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3))",
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_updated",
|
||||
"entityType": "columns",
|
||||
"table": "provider"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_deleted",
|
||||
"entityType": "columns",
|
||||
"table": "provider"
|
||||
},
|
||||
{
|
||||
"type": "varchar(64)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "provider",
|
||||
"entityType": "columns",
|
||||
"table": "provider"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "credentials",
|
||||
"entityType": "columns",
|
||||
"table": "provider"
|
||||
},
|
||||
{
|
||||
"type": "varchar(30)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "id",
|
||||
"entityType": "columns",
|
||||
"table": "user"
|
||||
},
|
||||
{
|
||||
"type": "varchar(30)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "workspace_id",
|
||||
"entityType": "columns",
|
||||
"table": "user"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": "(now())",
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_created",
|
||||
"entityType": "columns",
|
||||
"table": "user"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": "(CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3))",
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_updated",
|
||||
"entityType": "columns",
|
||||
"table": "user"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_deleted",
|
||||
"entityType": "columns",
|
||||
"table": "user"
|
||||
},
|
||||
{
|
||||
"type": "varchar(30)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "account_id",
|
||||
"entityType": "columns",
|
||||
"table": "user"
|
||||
},
|
||||
{
|
||||
"type": "varchar(255)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "email",
|
||||
"entityType": "columns",
|
||||
"table": "user"
|
||||
},
|
||||
{
|
||||
"type": "varchar(255)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "name",
|
||||
"entityType": "columns",
|
||||
"table": "user"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_seen",
|
||||
"entityType": "columns",
|
||||
"table": "user"
|
||||
},
|
||||
{
|
||||
"type": "int",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "color",
|
||||
"entityType": "columns",
|
||||
"table": "user"
|
||||
},
|
||||
{
|
||||
"type": "enum('admin','member')",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "role",
|
||||
"entityType": "columns",
|
||||
"table": "user"
|
||||
},
|
||||
{
|
||||
"type": "int",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "monthly_limit",
|
||||
"entityType": "columns",
|
||||
"table": "user"
|
||||
},
|
||||
{
|
||||
"type": "bigint",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "monthly_usage",
|
||||
"entityType": "columns",
|
||||
"table": "user"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_monthly_usage_updated",
|
||||
"entityType": "columns",
|
||||
"table": "user"
|
||||
},
|
||||
{
|
||||
"type": "varchar(30)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "id",
|
||||
"entityType": "columns",
|
||||
"table": "workspace"
|
||||
},
|
||||
{
|
||||
"type": "varchar(255)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "slug",
|
||||
"entityType": "columns",
|
||||
"table": "workspace"
|
||||
},
|
||||
{
|
||||
"type": "varchar(255)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "name",
|
||||
"entityType": "columns",
|
||||
"table": "workspace"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": "(now())",
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_created",
|
||||
"entityType": "columns",
|
||||
"table": "workspace"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": true,
|
||||
"autoIncrement": false,
|
||||
"default": "(CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3))",
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_updated",
|
||||
"entityType": "columns",
|
||||
"table": "workspace"
|
||||
},
|
||||
{
|
||||
"type": "timestamp(3)",
|
||||
"notNull": false,
|
||||
"autoIncrement": false,
|
||||
"default": null,
|
||||
"onUpdateNow": false,
|
||||
"onUpdateNowFsp": null,
|
||||
"charSet": null,
|
||||
"collation": null,
|
||||
"generated": null,
|
||||
"name": "time_deleted",
|
||||
"entityType": "columns",
|
||||
"table": "workspace"
|
||||
},
|
||||
{
|
||||
"columns": ["id"],
|
||||
"name": "PRIMARY",
|
||||
"table": "account",
|
||||
"entityType": "pks"
|
||||
},
|
||||
{
|
||||
"columns": ["id"],
|
||||
"name": "PRIMARY",
|
||||
"table": "auth",
|
||||
"entityType": "pks"
|
||||
},
|
||||
{
|
||||
"columns": ["id"],
|
||||
"name": "PRIMARY",
|
||||
"table": "benchmark",
|
||||
"entityType": "pks"
|
||||
},
|
||||
{
|
||||
"columns": ["workspace_id", "id"],
|
||||
"name": "PRIMARY",
|
||||
"table": "billing",
|
||||
"entityType": "pks"
|
||||
},
|
||||
{
|
||||
"columns": ["email", "type"],
|
||||
"name": "PRIMARY",
|
||||
"table": "coupon",
|
||||
"entityType": "pks"
|
||||
},
|
||||
{
|
||||
"columns": ["workspace_id", "id"],
|
||||
"name": "PRIMARY",
|
||||
"table": "lite",
|
||||
"entityType": "pks"
|
||||
},
|
||||
{
|
||||
"columns": ["workspace_id", "id"],
|
||||
"name": "PRIMARY",
|
||||
"table": "payment",
|
||||
"entityType": "pks"
|
||||
},
|
||||
{
|
||||
"columns": ["workspace_id", "id"],
|
||||
"name": "PRIMARY",
|
||||
"table": "subscription",
|
||||
"entityType": "pks"
|
||||
},
|
||||
{
|
||||
"columns": ["workspace_id", "id"],
|
||||
"name": "PRIMARY",
|
||||
"table": "usage",
|
||||
"entityType": "pks"
|
||||
},
|
||||
{
|
||||
"columns": ["ip", "interval"],
|
||||
"name": "PRIMARY",
|
||||
"table": "ip_rate_limit",
|
||||
"entityType": "pks"
|
||||
},
|
||||
{
|
||||
"columns": ["ip"],
|
||||
"name": "PRIMARY",
|
||||
"table": "ip",
|
||||
"entityType": "pks"
|
||||
},
|
||||
{
|
||||
"columns": ["key", "interval"],
|
||||
"name": "PRIMARY",
|
||||
"table": "key_rate_limit",
|
||||
"entityType": "pks"
|
||||
},
|
||||
{
|
||||
"columns": ["id", "interval"],
|
||||
"name": "PRIMARY",
|
||||
"table": "model_tpm_rate_limit",
|
||||
"entityType": "pks"
|
||||
},
|
||||
{
|
||||
"columns": ["workspace_id", "id"],
|
||||
"name": "PRIMARY",
|
||||
"table": "key",
|
||||
"entityType": "pks"
|
||||
},
|
||||
{
|
||||
"columns": ["workspace_id", "id"],
|
||||
"name": "PRIMARY",
|
||||
"table": "model",
|
||||
"entityType": "pks"
|
||||
},
|
||||
{
|
||||
"columns": ["workspace_id", "id"],
|
||||
"name": "PRIMARY",
|
||||
"table": "provider",
|
||||
"entityType": "pks"
|
||||
},
|
||||
{
|
||||
"columns": ["workspace_id", "id"],
|
||||
"name": "PRIMARY",
|
||||
"table": "user",
|
||||
"entityType": "pks"
|
||||
},
|
||||
{
|
||||
"columns": ["id"],
|
||||
"name": "PRIMARY",
|
||||
"table": "workspace",
|
||||
"entityType": "pks"
|
||||
},
|
||||
{
|
||||
"columns": [
|
||||
{
|
||||
"value": "provider",
|
||||
"isExpression": false
|
||||
},
|
||||
{
|
||||
"value": "subject",
|
||||
"isExpression": false
|
||||
}
|
||||
],
|
||||
"isUnique": true,
|
||||
"using": null,
|
||||
"algorithm": null,
|
||||
"lock": null,
|
||||
"nameExplicit": true,
|
||||
"name": "provider",
|
||||
"entityType": "indexes",
|
||||
"table": "auth"
|
||||
},
|
||||
{
|
||||
"columns": [
|
||||
{
|
||||
"value": "account_id",
|
||||
"isExpression": false
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"using": null,
|
||||
"algorithm": null,
|
||||
"lock": null,
|
||||
"nameExplicit": true,
|
||||
"name": "account_id",
|
||||
"entityType": "indexes",
|
||||
"table": "auth"
|
||||
},
|
||||
{
|
||||
"columns": [
|
||||
{
|
||||
"value": "time_created",
|
||||
"isExpression": false
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"using": null,
|
||||
"algorithm": null,
|
||||
"lock": null,
|
||||
"nameExplicit": true,
|
||||
"name": "time_created",
|
||||
"entityType": "indexes",
|
||||
"table": "benchmark"
|
||||
},
|
||||
{
|
||||
"columns": [
|
||||
{
|
||||
"value": "customer_id",
|
||||
"isExpression": false
|
||||
}
|
||||
],
|
||||
"isUnique": true,
|
||||
"using": null,
|
||||
"algorithm": null,
|
||||
"lock": null,
|
||||
"nameExplicit": true,
|
||||
"name": "global_customer_id",
|
||||
"entityType": "indexes",
|
||||
"table": "billing"
|
||||
},
|
||||
{
|
||||
"columns": [
|
||||
{
|
||||
"value": "subscription_id",
|
||||
"isExpression": false
|
||||
}
|
||||
],
|
||||
"isUnique": true,
|
||||
"using": null,
|
||||
"algorithm": null,
|
||||
"lock": null,
|
||||
"nameExplicit": true,
|
||||
"name": "global_subscription_id",
|
||||
"entityType": "indexes",
|
||||
"table": "billing"
|
||||
},
|
||||
{
|
||||
"columns": [
|
||||
{
|
||||
"value": "workspace_id",
|
||||
"isExpression": false
|
||||
},
|
||||
{
|
||||
"value": "user_id",
|
||||
"isExpression": false
|
||||
}
|
||||
],
|
||||
"isUnique": true,
|
||||
"using": null,
|
||||
"algorithm": null,
|
||||
"lock": null,
|
||||
"nameExplicit": true,
|
||||
"name": "workspace_user_id",
|
||||
"entityType": "indexes",
|
||||
"table": "lite"
|
||||
},
|
||||
{
|
||||
"columns": [
|
||||
{
|
||||
"value": "workspace_id",
|
||||
"isExpression": false
|
||||
},
|
||||
{
|
||||
"value": "user_id",
|
||||
"isExpression": false
|
||||
}
|
||||
],
|
||||
"isUnique": true,
|
||||
"using": null,
|
||||
"algorithm": null,
|
||||
"lock": null,
|
||||
"nameExplicit": true,
|
||||
"name": "workspace_user_id",
|
||||
"entityType": "indexes",
|
||||
"table": "subscription"
|
||||
},
|
||||
{
|
||||
"columns": [
|
||||
{
|
||||
"value": "workspace_id",
|
||||
"isExpression": false
|
||||
},
|
||||
{
|
||||
"value": "time_created",
|
||||
"isExpression": false
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"using": null,
|
||||
"algorithm": null,
|
||||
"lock": null,
|
||||
"nameExplicit": true,
|
||||
"name": "usage_time_created",
|
||||
"entityType": "indexes",
|
||||
"table": "usage"
|
||||
},
|
||||
{
|
||||
"columns": [
|
||||
{
|
||||
"value": "key",
|
||||
"isExpression": false
|
||||
}
|
||||
],
|
||||
"isUnique": true,
|
||||
"using": null,
|
||||
"algorithm": null,
|
||||
"lock": null,
|
||||
"nameExplicit": true,
|
||||
"name": "global_key",
|
||||
"entityType": "indexes",
|
||||
"table": "key"
|
||||
},
|
||||
{
|
||||
"columns": [
|
||||
{
|
||||
"value": "workspace_id",
|
||||
"isExpression": false
|
||||
},
|
||||
{
|
||||
"value": "model",
|
||||
"isExpression": false
|
||||
}
|
||||
],
|
||||
"isUnique": true,
|
||||
"using": null,
|
||||
"algorithm": null,
|
||||
"lock": null,
|
||||
"nameExplicit": true,
|
||||
"name": "model_workspace_model",
|
||||
"entityType": "indexes",
|
||||
"table": "model"
|
||||
},
|
||||
{
|
||||
"columns": [
|
||||
{
|
||||
"value": "workspace_id",
|
||||
"isExpression": false
|
||||
},
|
||||
{
|
||||
"value": "provider",
|
||||
"isExpression": false
|
||||
}
|
||||
],
|
||||
"isUnique": true,
|
||||
"using": null,
|
||||
"algorithm": null,
|
||||
"lock": null,
|
||||
"nameExplicit": true,
|
||||
"name": "workspace_provider",
|
||||
"entityType": "indexes",
|
||||
"table": "provider"
|
||||
},
|
||||
{
|
||||
"columns": [
|
||||
{
|
||||
"value": "workspace_id",
|
||||
"isExpression": false
|
||||
},
|
||||
{
|
||||
"value": "account_id",
|
||||
"isExpression": false
|
||||
}
|
||||
],
|
||||
"isUnique": true,
|
||||
"using": null,
|
||||
"algorithm": null,
|
||||
"lock": null,
|
||||
"nameExplicit": true,
|
||||
"name": "user_account_id",
|
||||
"entityType": "indexes",
|
||||
"table": "user"
|
||||
},
|
||||
{
|
||||
"columns": [
|
||||
{
|
||||
"value": "workspace_id",
|
||||
"isExpression": false
|
||||
},
|
||||
{
|
||||
"value": "email",
|
||||
"isExpression": false
|
||||
}
|
||||
],
|
||||
"isUnique": true,
|
||||
"using": null,
|
||||
"algorithm": null,
|
||||
"lock": null,
|
||||
"nameExplicit": true,
|
||||
"name": "user_email",
|
||||
"entityType": "indexes",
|
||||
"table": "user"
|
||||
},
|
||||
{
|
||||
"columns": [
|
||||
{
|
||||
"value": "account_id",
|
||||
"isExpression": false
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"using": null,
|
||||
"algorithm": null,
|
||||
"lock": null,
|
||||
"nameExplicit": true,
|
||||
"name": "global_account_id",
|
||||
"entityType": "indexes",
|
||||
"table": "user"
|
||||
},
|
||||
{
|
||||
"columns": [
|
||||
{
|
||||
"value": "email",
|
||||
"isExpression": false
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"using": null,
|
||||
"algorithm": null,
|
||||
"lock": null,
|
||||
"nameExplicit": true,
|
||||
"name": "global_email",
|
||||
"entityType": "indexes",
|
||||
"table": "user"
|
||||
},
|
||||
{
|
||||
"columns": [
|
||||
{
|
||||
"value": "slug",
|
||||
"isExpression": false
|
||||
}
|
||||
],
|
||||
"isUnique": true,
|
||||
"using": null,
|
||||
"algorithm": null,
|
||||
"lock": null,
|
||||
"nameExplicit": true,
|
||||
"name": "slug",
|
||||
"entityType": "indexes",
|
||||
"table": "workspace"
|
||||
}
|
||||
],
|
||||
"renames": []
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode-ai/console-core",
|
||||
"version": "1.14.25",
|
||||
"version": "1.14.29",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -176,13 +176,13 @@ export namespace Billing {
|
||||
)
|
||||
}
|
||||
|
||||
export const hasCoupon = async (email: string, type: (typeof CouponType)[number]) => {
|
||||
export const getCoupons = async (email: string) => {
|
||||
return await Database.use((tx) =>
|
||||
tx
|
||||
.select()
|
||||
.select({ type: CouponTable.type, timeRedeemed: CouponTable.timeRedeemed })
|
||||
.from(CouponTable)
|
||||
.where(and(eq(CouponTable.email, email), eq(CouponTable.type, type), isNull(CouponTable.timeRedeemed)))
|
||||
.then((rows) => rows.length > 0),
|
||||
.where(and(eq(CouponTable.email, email), isNull(CouponTable.timeRedeemed)))
|
||||
.then((rows) => rows.map((row) => row.type)),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -290,9 +290,16 @@ export namespace Billing {
|
||||
if (billing.subscriptionID) throw new Error("Already subscribed to Black")
|
||||
if (billing.liteSubscriptionID) throw new Error("Already subscribed to Lite")
|
||||
|
||||
const coupon = (await Billing.hasCoupon(email, "GOFREEMONTH"))
|
||||
? LiteData.firstMonth100Coupon
|
||||
: LiteData.firstMonth50Coupon
|
||||
const coupons = await Billing.getCoupons(email)
|
||||
const coupon = coupons.includes("GO12MONTHS100")
|
||||
? LiteData.twelveMonths100Coupon
|
||||
: coupons.includes("GO6MONTHS100")
|
||||
? LiteData.sixMonths100Coupon
|
||||
: coupons.includes("GO3MONTHS100")
|
||||
? LiteData.threeMonths100Coupon
|
||||
: coupons.includes("GOFREEMONTH")
|
||||
? LiteData.firstMonth100Coupon
|
||||
: LiteData.firstMonth50Coupon
|
||||
const createSession = () =>
|
||||
Billing.stripe().checkout.sessions.create({
|
||||
mode: "subscription",
|
||||
|
||||
@@ -13,5 +13,8 @@ export namespace LiteData {
|
||||
export const priceInr = fn(z.void(), () => Resource.ZEN_LITE_PRICE.priceInr)
|
||||
export const firstMonth100Coupon = Resource.ZEN_LITE_PRICE.firstMonth100Coupon
|
||||
export const firstMonth50Coupon = Resource.ZEN_LITE_PRICE.firstMonth50Coupon
|
||||
export const threeMonths100Coupon = Resource.ZEN_LITE_PRICE.threeMonths100Coupon
|
||||
export const sixMonths100Coupon = Resource.ZEN_LITE_PRICE.sixMonths100Coupon
|
||||
export const twelveMonths100Coupon = Resource.ZEN_LITE_PRICE.twelveMonths100Coupon
|
||||
export const planName = fn(z.void(), () => "lite")
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ export const UsageTable = mysqlTable(
|
||||
(table) => [...workspaceIndexes(table), index("usage_time_created").on(table.workspaceID, table.timeCreated)],
|
||||
)
|
||||
|
||||
export const CouponType = ["BUILDATHON", "GOFREEMONTH"] as const
|
||||
export const CouponType = ["BUILDATHON", "GOFREEMONTH", "GO3MONTHS100", "GO6MONTHS100", "GO12MONTHS100"] as const
|
||||
export const CouponTable = mysqlTable(
|
||||
"coupon",
|
||||
{
|
||||
|
||||
Vendored
+3
@@ -148,6 +148,9 @@ declare module "sst" {
|
||||
"price": string
|
||||
"priceInr": number
|
||||
"product": string
|
||||
"sixMonths100Coupon": string
|
||||
"threeMonths100Coupon": string
|
||||
"twelveMonths100Coupon": string
|
||||
"type": "sst.sst.Linkable"
|
||||
}
|
||||
"ZEN_MODELS1": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/console-function",
|
||||
"version": "1.14.25",
|
||||
"version": "1.14.29",
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
|
||||
+3
@@ -148,6 +148,9 @@ declare module "sst" {
|
||||
"price": string
|
||||
"priceInr": number
|
||||
"product": string
|
||||
"sixMonths100Coupon": string
|
||||
"threeMonths100Coupon": string
|
||||
"twelveMonths100Coupon": string
|
||||
"type": "sst.sst.Linkable"
|
||||
}
|
||||
"ZEN_MODELS1": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/console-mail",
|
||||
"version": "1.14.25",
|
||||
"version": "1.14.29",
|
||||
"dependencies": {
|
||||
"@jsx-email/all": "2.2.3",
|
||||
"@jsx-email/cli": "1.4.3",
|
||||
|
||||
+3
@@ -148,6 +148,9 @@ declare module "sst" {
|
||||
"price": string
|
||||
"priceInr": number
|
||||
"product": string
|
||||
"sixMonths100Coupon": string
|
||||
"threeMonths100Coupon": string
|
||||
"twelveMonths100Coupon": string
|
||||
"type": "sst.sst.Linkable"
|
||||
}
|
||||
"ZEN_MODELS1": {
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"version": "1.14.25",
|
||||
"version": "1.14.29",
|
||||
"name": "@opencode-ai/core",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"test": "bun test",
|
||||
"test:ci": "mkdir -p .artifacts/unit && bun test --timeout 30000 --reporter=junit --reporter-outfile=.artifacts/unit/junit.xml",
|
||||
"typecheck": "tsgo --noEmit"
|
||||
},
|
||||
"bin": {
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
export * as NpmConfig from "./npm-config"
|
||||
|
||||
import { fileURLToPath } from "url"
|
||||
// @ts-expect-error npm does not publish types for this internal config API.
|
||||
import Config from "@npmcli/config"
|
||||
// @ts-expect-error npm does not publish types for this internal config API.
|
||||
import { definitions, flatten, nerfDarts, shorthands } from "@npmcli/config/lib/definitions/index.js"
|
||||
import { Effect } from "effect"
|
||||
|
||||
const npmPath = fileURLToPath(new URL("..", import.meta.url))
|
||||
|
||||
export const load = (dir: string) =>
|
||||
Effect.tryPromise({
|
||||
try: async () => {
|
||||
const config = new Config({
|
||||
npmPath,
|
||||
cwd: dir,
|
||||
env: { ...process.env },
|
||||
argv: [process.execPath, process.execPath],
|
||||
execPath: process.execPath,
|
||||
platform: process.platform,
|
||||
definitions,
|
||||
flatten,
|
||||
nerfDarts,
|
||||
shorthands,
|
||||
warn: false,
|
||||
})
|
||||
await config.load()
|
||||
return config.flat as Record<string, unknown>
|
||||
},
|
||||
catch: (cause) => cause,
|
||||
}).pipe(Effect.orElseSucceed(() => ({}) as Record<string, unknown>))
|
||||
|
||||
export const registry = (dir: string) =>
|
||||
load(dir).pipe(
|
||||
Effect.map((config) => {
|
||||
const registry = typeof config.registry === "string" ? config.registry : "https://registry.npmjs.org"
|
||||
return registry.endsWith("/") ? registry.slice(0, -1) : registry
|
||||
}),
|
||||
)
|
||||
@@ -1,22 +1,14 @@
|
||||
export * as Npm from "./npm"
|
||||
|
||||
import path from "path"
|
||||
import { fileURLToPath } from "url"
|
||||
import npa from "npm-package-arg"
|
||||
import semver from "semver"
|
||||
// @ts-expect-error npm does not publish types for this internal config API.
|
||||
import Config from "@npmcli/config"
|
||||
// @ts-expect-error npm does not publish types for this internal config API.
|
||||
import { definitions, flatten, nerfDarts, shorthands } from "@npmcli/config/lib/definitions/index.js"
|
||||
import { Effect, Schema, Context, Layer, Option, FileSystem, Stream } from "effect"
|
||||
import { Effect, Schema, Context, Layer, Option, FileSystem } from "effect"
|
||||
import { NodeFileSystem } from "@effect/platform-node"
|
||||
import { AppFileSystem } from "./filesystem"
|
||||
import { Global } from "./global"
|
||||
import { EffectFlock } from "./util/effect-flock"
|
||||
import { makeRuntime } from "./effect/runtime"
|
||||
import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process"
|
||||
|
||||
import { CrossSpawnSpawner } from "./cross-spawn-spawner"
|
||||
import { NpmConfig } from "./npm-config"
|
||||
|
||||
export class InstallFailedError extends Schema.TaggedErrorClass<InstallFailedError>()("NpmInstallFailedError", {
|
||||
add: Schema.Array(Schema.String).pipe(Schema.optional),
|
||||
@@ -40,46 +32,18 @@ export interface Interface {
|
||||
}[]
|
||||
},
|
||||
) => Effect.Effect<void, EffectFlock.LockError | InstallFailedError>
|
||||
readonly outdated: (pkg: string, cachedVersion: string) => Effect.Effect<boolean>
|
||||
readonly which: (pkg: string, bin?: string) => Effect.Effect<Option.Option<string>>
|
||||
}
|
||||
|
||||
export class Service extends Context.Service<Service, Interface>()("@opencode/Npm") {}
|
||||
|
||||
const illegal = process.platform === "win32" ? new Set(["<", ">", ":", '"', "|", "?", "*"]) : undefined
|
||||
const npmPath = fileURLToPath(new URL("..", import.meta.url))
|
||||
|
||||
export function sanitize(pkg: string) {
|
||||
if (!illegal) return pkg
|
||||
return Array.from(pkg, (char) => (illegal.has(char) || char.charCodeAt(0) < 32 ? "_" : char)).join("")
|
||||
}
|
||||
|
||||
const loadOptions = (dir: string) =>
|
||||
Effect.tryPromise({
|
||||
try: async () => {
|
||||
const config = new Config({
|
||||
npmPath,
|
||||
cwd: dir,
|
||||
env: { ...process.env },
|
||||
argv: [process.execPath, process.execPath],
|
||||
execPath: process.execPath,
|
||||
platform: process.platform,
|
||||
definitions,
|
||||
flatten,
|
||||
nerfDarts,
|
||||
shorthands,
|
||||
warn: false,
|
||||
})
|
||||
await config.load()
|
||||
return config.flat
|
||||
},
|
||||
catch: (cause) =>
|
||||
new InstallFailedError({
|
||||
cause,
|
||||
dir,
|
||||
}),
|
||||
})
|
||||
|
||||
const resolveEntryPoint = (name: string, dir: string): EntryPoint => {
|
||||
let entrypoint: Option.Option<string>
|
||||
try {
|
||||
@@ -110,39 +74,13 @@ export const layer = Layer.effect(
|
||||
const global = yield* Global.Service
|
||||
const fs = yield* FileSystem.FileSystem
|
||||
const flock = yield* EffectFlock.Service
|
||||
const spawner = yield* ChildProcessSpawner.ChildProcessSpawner
|
||||
const directory = (pkg: string) => path.join(global.cache, "packages", sanitize(pkg))
|
||||
const runView = Effect.fnUntraced(function* (cmd: string[]) {
|
||||
const handle = yield* spawner.spawn(
|
||||
ChildProcess.make(cmd[0], cmd.slice(1), {
|
||||
extendEnv: true,
|
||||
}),
|
||||
)
|
||||
const [stdout, stderr] = yield* Effect.all(
|
||||
[Stream.mkString(Stream.decodeText(handle.stdout)), Stream.mkString(Stream.decodeText(handle.stderr))],
|
||||
{ concurrency: 2 },
|
||||
)
|
||||
const code = yield* handle.exitCode
|
||||
if (code !== 0 || !stdout.trim()) {
|
||||
return yield* Effect.fail(stderr || stdout || `Failed to run ${cmd.join(" ")}`)
|
||||
}
|
||||
return yield* Schema.decodeUnknownEffect(Schema.fromJsonString(Schema.String))(stdout)
|
||||
}, Effect.scoped)
|
||||
const viewLatestVersion = Effect.fnUntraced(function* (pkg: string) {
|
||||
return yield* runView(["npm", "view", pkg, "dist-tags.latest", "--json"]).pipe(
|
||||
Effect.catch(() =>
|
||||
runView(["pnpm", "view", pkg, "dist-tags.latest", "--json"]).pipe(
|
||||
Effect.catch(() => runView(["bun", "pm", "view", pkg, "dist-tags.latest", "--json"])),
|
||||
),
|
||||
),
|
||||
)
|
||||
})
|
||||
const reify = (input: { dir: string; add?: string[] }) =>
|
||||
Effect.gen(function* () {
|
||||
yield* flock.acquire(`npm-install:${input.dir}`)
|
||||
const { Arborist } = yield* Effect.promise(() => import("@npmcli/arborist"))
|
||||
const add = input.add ?? []
|
||||
const npmOptions = yield* loadOptions(input.dir)
|
||||
const npmOptions = yield* NpmConfig.load(input.dir)
|
||||
const arborist = new Arborist({
|
||||
...npmOptions,
|
||||
path: input.dir,
|
||||
@@ -172,18 +110,6 @@ export const layer = Layer.effect(
|
||||
}),
|
||||
)
|
||||
|
||||
const outdated = Effect.fn("Npm.outdated")(function* (pkg: string, cachedVersion: string) {
|
||||
const latestVersion = yield* viewLatestVersion(pkg).pipe(Effect.option)
|
||||
if (Option.isNone(latestVersion)) {
|
||||
return false
|
||||
}
|
||||
|
||||
const range = /[\s^~*xX<>|=]/.test(cachedVersion)
|
||||
if (range) return !semver.satisfies(latestVersion.value, cachedVersion)
|
||||
|
||||
return semver.lt(cachedVersion, latestVersion.value)
|
||||
})
|
||||
|
||||
const add = Effect.fn("Npm.add")(function* (pkg: string) {
|
||||
const dir = directory(pkg)
|
||||
const name = (() => {
|
||||
@@ -309,7 +235,6 @@ export const layer = Layer.effect(
|
||||
return Service.of({
|
||||
add,
|
||||
install,
|
||||
outdated,
|
||||
which,
|
||||
})
|
||||
}),
|
||||
@@ -320,7 +245,6 @@ export const defaultLayer = layer.pipe(
|
||||
Layer.provide(AppFileSystem.layer),
|
||||
Layer.provide(Global.layer),
|
||||
Layer.provide(NodeFileSystem.layer),
|
||||
Layer.provide(CrossSpawnSpawner.defaultLayer),
|
||||
)
|
||||
|
||||
const { runPromise } = makeRuntime(Service, defaultLayer)
|
||||
@@ -337,10 +261,6 @@ export async function add(...args: Parameters<Interface["add"]>) {
|
||||
}
|
||||
}
|
||||
|
||||
export async function outdated(...args: Parameters<Interface["outdated"]>) {
|
||||
return runPromise((svc) => svc.outdated(...args))
|
||||
}
|
||||
|
||||
export async function which(...args: Parameters<Interface["which"]>) {
|
||||
const resolved = await runPromise((svc) => svc.which(...args))
|
||||
return Option.getOrUndefined(resolved)
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import fs from "fs/promises"
|
||||
import { tmpdir as osTmpdir } from "os"
|
||||
import path from "path"
|
||||
|
||||
export const tmpdir = async () => {
|
||||
const dir = await fs.mkdtemp(path.join(osTmpdir(), "opencode-core-test-"))
|
||||
return {
|
||||
path: dir,
|
||||
async [Symbol.asyncDispose]() {
|
||||
await fs.rm(dir, { recursive: true, force: true })
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
import path from "path"
|
||||
import { describe, expect, test } from "bun:test"
|
||||
import { Effect } from "effect"
|
||||
import { NpmConfig } from "@opencode-ai/core/npm-config"
|
||||
import { tmpdir } from "./fixture/tmpdir"
|
||||
|
||||
describe("NpmConfig.load", () => {
|
||||
test("reads registry from project .npmrc", async () => {
|
||||
await using tmp = await tmpdir()
|
||||
await Bun.write(path.join(tmp.path, ".npmrc"), "registry=https://registry.example.test/\n")
|
||||
|
||||
const config = await Effect.runPromise(NpmConfig.load(tmp.path))
|
||||
|
||||
expect(config.registry).toBe("https://registry.example.test/")
|
||||
})
|
||||
|
||||
test("reads scoped registries from project .npmrc", async () => {
|
||||
await using tmp = await tmpdir()
|
||||
await Bun.write(path.join(tmp.path, ".npmrc"), "@acme:registry=https://npm.acme.test/\n")
|
||||
|
||||
const config = await Effect.runPromise(NpmConfig.load(tmp.path))
|
||||
|
||||
expect(config["@acme:registry"]).toBe("https://npm.acme.test/")
|
||||
})
|
||||
|
||||
test("flattens boolean and list options", async () => {
|
||||
await using tmp = await tmpdir()
|
||||
await Bun.write(path.join(tmp.path, ".npmrc"), "ignore-scripts=true\nomit[]=dev\nomit[]=optional\n")
|
||||
|
||||
const config = await Effect.runPromise(NpmConfig.load(tmp.path))
|
||||
|
||||
expect(config.ignoreScripts).toBe(true)
|
||||
expect(config.omit).toEqual(["dev", "optional"])
|
||||
})
|
||||
})
|
||||
|
||||
describe("NpmConfig.registry", () => {
|
||||
test("normalizes configured registry without trailing slash", async () => {
|
||||
await using tmp = await tmpdir()
|
||||
await Bun.write(path.join(tmp.path, ".npmrc"), "registry=https://registry.example.test/\n")
|
||||
|
||||
await expect(Effect.runPromise(NpmConfig.registry(tmp.path))).resolves.toBe("https://registry.example.test")
|
||||
})
|
||||
|
||||
test("leaves configured registry without trailing slash unchanged", async () => {
|
||||
await using tmp = await tmpdir()
|
||||
await Bun.write(path.join(tmp.path, ".npmrc"), "registry=https://registry.example.test\n")
|
||||
|
||||
await expect(Effect.runPromise(NpmConfig.registry(tmp.path))).resolves.toBe("https://registry.example.test")
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,56 @@
|
||||
import fs from "fs/promises"
|
||||
import path from "path"
|
||||
import { describe, expect, test } from "bun:test"
|
||||
import { Npm } from "@opencode-ai/core/npm"
|
||||
import { tmpdir } from "./fixture/tmpdir"
|
||||
|
||||
const win = process.platform === "win32"
|
||||
|
||||
const writePackage = (dir: string, pkg: Record<string, unknown>) =>
|
||||
Bun.write(
|
||||
path.join(dir, "package.json"),
|
||||
JSON.stringify({
|
||||
version: "1.0.0",
|
||||
...pkg,
|
||||
}),
|
||||
)
|
||||
|
||||
describe("Npm.sanitize", () => {
|
||||
test("keeps normal scoped package specs unchanged", () => {
|
||||
expect(Npm.sanitize("@opencode/acme")).toBe("@opencode/acme")
|
||||
expect(Npm.sanitize("@opencode/acme@1.0.0")).toBe("@opencode/acme@1.0.0")
|
||||
expect(Npm.sanitize("prettier")).toBe("prettier")
|
||||
})
|
||||
|
||||
test("handles git https specs", () => {
|
||||
const spec = "acme@git+https://github.com/opencode/acme.git"
|
||||
const expected = win ? "acme@git+https_//github.com/opencode/acme.git" : spec
|
||||
expect(Npm.sanitize(spec)).toBe(expected)
|
||||
})
|
||||
})
|
||||
|
||||
describe("Npm.install", () => {
|
||||
test("respects omit from project .npmrc", async () => {
|
||||
await using tmp = await tmpdir()
|
||||
|
||||
await writePackage(tmp.path, {
|
||||
name: "fixture",
|
||||
dependencies: {
|
||||
"prod-pkg": "file:./prod-pkg",
|
||||
},
|
||||
devDependencies: {
|
||||
"dev-pkg": "file:./dev-pkg",
|
||||
},
|
||||
})
|
||||
await Bun.write(path.join(tmp.path, ".npmrc"), "omit=dev\n")
|
||||
await fs.mkdir(path.join(tmp.path, "prod-pkg"))
|
||||
await fs.mkdir(path.join(tmp.path, "dev-pkg"))
|
||||
await writePackage(path.join(tmp.path, "prod-pkg"), { name: "prod-pkg" })
|
||||
await writePackage(path.join(tmp.path, "dev-pkg"), { name: "dev-pkg" })
|
||||
|
||||
await Npm.install(tmp.path)
|
||||
|
||||
await expect(fs.stat(path.join(tmp.path, "node_modules", "prod-pkg"))).resolves.toBeDefined()
|
||||
await expect(fs.stat(path.join(tmp.path, "node_modules", "dev-pkg"))).rejects.toThrow()
|
||||
})
|
||||
})
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@opencode-ai/desktop-electron",
|
||||
"private": true,
|
||||
"version": "1.14.25",
|
||||
"version": "1.14.29",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"homepage": "https://opencode.ai",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@opencode-ai/desktop",
|
||||
"private": true,
|
||||
"version": "1.14.25",
|
||||
"version": "1.14.29",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/enterprise",
|
||||
"version": "1.14.25",
|
||||
"version": "1.14.29",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
Vendored
+3
@@ -148,6 +148,9 @@ declare module "sst" {
|
||||
"price": string
|
||||
"priceInr": number
|
||||
"product": string
|
||||
"sixMonths100Coupon": string
|
||||
"threeMonths100Coupon": string
|
||||
"twelveMonths100Coupon": string
|
||||
"type": "sst.sst.Linkable"
|
||||
}
|
||||
"ZEN_MODELS1": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
id = "opencode"
|
||||
name = "OpenCode"
|
||||
description = "The open source coding agent."
|
||||
version = "1.14.25"
|
||||
version = "1.14.29"
|
||||
schema_version = 1
|
||||
authors = ["Anomaly"]
|
||||
repository = "https://github.com/anomalyco/opencode"
|
||||
@@ -11,26 +11,26 @@ name = "OpenCode"
|
||||
icon = "./icons/opencode.svg"
|
||||
|
||||
[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.29/opencode-darwin-arm64.zip"
|
||||
cmd = "./opencode"
|
||||
args = ["acp"]
|
||||
|
||||
[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.29/opencode-darwin-x64.zip"
|
||||
cmd = "./opencode"
|
||||
args = ["acp"]
|
||||
|
||||
[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.29/opencode-linux-arm64.tar.gz"
|
||||
cmd = "./opencode"
|
||||
args = ["acp"]
|
||||
|
||||
[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.29/opencode-linux-x64.tar.gz"
|
||||
cmd = "./opencode"
|
||||
args = ["acp"]
|
||||
|
||||
[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.29/opencode-windows-x64.zip"
|
||||
cmd = "./opencode.exe"
|
||||
args = ["acp"]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/function",
|
||||
"version": "1.14.25",
|
||||
"version": "1.14.29",
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
|
||||
Vendored
+3
@@ -148,6 +148,9 @@ declare module "sst" {
|
||||
"price": string
|
||||
"priceInr": number
|
||||
"product": string
|
||||
"sixMonths100Coupon": string
|
||||
"threeMonths100Coupon": string
|
||||
"twelveMonths100Coupon": string
|
||||
"type": "sst.sst.Linkable"
|
||||
}
|
||||
"ZEN_MODELS1": {
|
||||
|
||||
@@ -7,3 +7,4 @@ src/provider/models-snapshot.js
|
||||
src/provider/models-snapshot.d.ts
|
||||
script/build-*.ts
|
||||
temporary-*.md
|
||||
.artifacts
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE `session` ADD `path` text;
|
||||
@@ -0,0 +1,1419 @@
|
||||
{
|
||||
"version": "7",
|
||||
"dialect": "sqlite",
|
||||
"id": "aaa2ebeb-caa4-478d-8365-4fc595d16856",
|
||||
"prevIds": ["66cbe0d7-def0-451b-b88a-7608513a9b44"],
|
||||
"ddl": [
|
||||
{
|
||||
"name": "account_state",
|
||||
"entityType": "tables"
|
||||
},
|
||||
{
|
||||
"name": "account",
|
||||
"entityType": "tables"
|
||||
},
|
||||
{
|
||||
"name": "control_account",
|
||||
"entityType": "tables"
|
||||
},
|
||||
{
|
||||
"name": "workspace",
|
||||
"entityType": "tables"
|
||||
},
|
||||
{
|
||||
"name": "project",
|
||||
"entityType": "tables"
|
||||
},
|
||||
{
|
||||
"name": "message",
|
||||
"entityType": "tables"
|
||||
},
|
||||
{
|
||||
"name": "part",
|
||||
"entityType": "tables"
|
||||
},
|
||||
{
|
||||
"name": "permission",
|
||||
"entityType": "tables"
|
||||
},
|
||||
{
|
||||
"name": "session_entry",
|
||||
"entityType": "tables"
|
||||
},
|
||||
{
|
||||
"name": "session",
|
||||
"entityType": "tables"
|
||||
},
|
||||
{
|
||||
"name": "todo",
|
||||
"entityType": "tables"
|
||||
},
|
||||
{
|
||||
"name": "session_share",
|
||||
"entityType": "tables"
|
||||
},
|
||||
{
|
||||
"name": "event_sequence",
|
||||
"entityType": "tables"
|
||||
},
|
||||
{
|
||||
"name": "event",
|
||||
"entityType": "tables"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "id",
|
||||
"entityType": "columns",
|
||||
"table": "account_state"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "active_account_id",
|
||||
"entityType": "columns",
|
||||
"table": "account_state"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "active_org_id",
|
||||
"entityType": "columns",
|
||||
"table": "account_state"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "id",
|
||||
"entityType": "columns",
|
||||
"table": "account"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "email",
|
||||
"entityType": "columns",
|
||||
"table": "account"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "url",
|
||||
"entityType": "columns",
|
||||
"table": "account"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "access_token",
|
||||
"entityType": "columns",
|
||||
"table": "account"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "refresh_token",
|
||||
"entityType": "columns",
|
||||
"table": "account"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "token_expiry",
|
||||
"entityType": "columns",
|
||||
"table": "account"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "time_created",
|
||||
"entityType": "columns",
|
||||
"table": "account"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "time_updated",
|
||||
"entityType": "columns",
|
||||
"table": "account"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "email",
|
||||
"entityType": "columns",
|
||||
"table": "control_account"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "url",
|
||||
"entityType": "columns",
|
||||
"table": "control_account"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "access_token",
|
||||
"entityType": "columns",
|
||||
"table": "control_account"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "refresh_token",
|
||||
"entityType": "columns",
|
||||
"table": "control_account"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "token_expiry",
|
||||
"entityType": "columns",
|
||||
"table": "control_account"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "active",
|
||||
"entityType": "columns",
|
||||
"table": "control_account"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "time_created",
|
||||
"entityType": "columns",
|
||||
"table": "control_account"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "time_updated",
|
||||
"entityType": "columns",
|
||||
"table": "control_account"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "id",
|
||||
"entityType": "columns",
|
||||
"table": "workspace"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "type",
|
||||
"entityType": "columns",
|
||||
"table": "workspace"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "''",
|
||||
"generated": null,
|
||||
"name": "name",
|
||||
"entityType": "columns",
|
||||
"table": "workspace"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "branch",
|
||||
"entityType": "columns",
|
||||
"table": "workspace"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "directory",
|
||||
"entityType": "columns",
|
||||
"table": "workspace"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "extra",
|
||||
"entityType": "columns",
|
||||
"table": "workspace"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "project_id",
|
||||
"entityType": "columns",
|
||||
"table": "workspace"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "id",
|
||||
"entityType": "columns",
|
||||
"table": "project"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "worktree",
|
||||
"entityType": "columns",
|
||||
"table": "project"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "vcs",
|
||||
"entityType": "columns",
|
||||
"table": "project"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "name",
|
||||
"entityType": "columns",
|
||||
"table": "project"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "icon_url",
|
||||
"entityType": "columns",
|
||||
"table": "project"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "icon_url_override",
|
||||
"entityType": "columns",
|
||||
"table": "project"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "icon_color",
|
||||
"entityType": "columns",
|
||||
"table": "project"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "time_created",
|
||||
"entityType": "columns",
|
||||
"table": "project"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "time_updated",
|
||||
"entityType": "columns",
|
||||
"table": "project"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "time_initialized",
|
||||
"entityType": "columns",
|
||||
"table": "project"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "sandboxes",
|
||||
"entityType": "columns",
|
||||
"table": "project"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "commands",
|
||||
"entityType": "columns",
|
||||
"table": "project"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "id",
|
||||
"entityType": "columns",
|
||||
"table": "message"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "session_id",
|
||||
"entityType": "columns",
|
||||
"table": "message"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "time_created",
|
||||
"entityType": "columns",
|
||||
"table": "message"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "time_updated",
|
||||
"entityType": "columns",
|
||||
"table": "message"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "data",
|
||||
"entityType": "columns",
|
||||
"table": "message"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "id",
|
||||
"entityType": "columns",
|
||||
"table": "part"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "message_id",
|
||||
"entityType": "columns",
|
||||
"table": "part"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "session_id",
|
||||
"entityType": "columns",
|
||||
"table": "part"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "time_created",
|
||||
"entityType": "columns",
|
||||
"table": "part"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "time_updated",
|
||||
"entityType": "columns",
|
||||
"table": "part"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "data",
|
||||
"entityType": "columns",
|
||||
"table": "part"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "project_id",
|
||||
"entityType": "columns",
|
||||
"table": "permission"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "time_created",
|
||||
"entityType": "columns",
|
||||
"table": "permission"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "time_updated",
|
||||
"entityType": "columns",
|
||||
"table": "permission"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "data",
|
||||
"entityType": "columns",
|
||||
"table": "permission"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "id",
|
||||
"entityType": "columns",
|
||||
"table": "session_entry"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "session_id",
|
||||
"entityType": "columns",
|
||||
"table": "session_entry"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "type",
|
||||
"entityType": "columns",
|
||||
"table": "session_entry"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "time_created",
|
||||
"entityType": "columns",
|
||||
"table": "session_entry"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "time_updated",
|
||||
"entityType": "columns",
|
||||
"table": "session_entry"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "data",
|
||||
"entityType": "columns",
|
||||
"table": "session_entry"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "id",
|
||||
"entityType": "columns",
|
||||
"table": "session"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "project_id",
|
||||
"entityType": "columns",
|
||||
"table": "session"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "workspace_id",
|
||||
"entityType": "columns",
|
||||
"table": "session"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "parent_id",
|
||||
"entityType": "columns",
|
||||
"table": "session"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "slug",
|
||||
"entityType": "columns",
|
||||
"table": "session"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "directory",
|
||||
"entityType": "columns",
|
||||
"table": "session"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "path",
|
||||
"entityType": "columns",
|
||||
"table": "session"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "title",
|
||||
"entityType": "columns",
|
||||
"table": "session"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "version",
|
||||
"entityType": "columns",
|
||||
"table": "session"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "share_url",
|
||||
"entityType": "columns",
|
||||
"table": "session"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "summary_additions",
|
||||
"entityType": "columns",
|
||||
"table": "session"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "summary_deletions",
|
||||
"entityType": "columns",
|
||||
"table": "session"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "summary_files",
|
||||
"entityType": "columns",
|
||||
"table": "session"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "summary_diffs",
|
||||
"entityType": "columns",
|
||||
"table": "session"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "revert",
|
||||
"entityType": "columns",
|
||||
"table": "session"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "permission",
|
||||
"entityType": "columns",
|
||||
"table": "session"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "time_created",
|
||||
"entityType": "columns",
|
||||
"table": "session"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "time_updated",
|
||||
"entityType": "columns",
|
||||
"table": "session"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "time_compacting",
|
||||
"entityType": "columns",
|
||||
"table": "session"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "time_archived",
|
||||
"entityType": "columns",
|
||||
"table": "session"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "session_id",
|
||||
"entityType": "columns",
|
||||
"table": "todo"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "content",
|
||||
"entityType": "columns",
|
||||
"table": "todo"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "status",
|
||||
"entityType": "columns",
|
||||
"table": "todo"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "priority",
|
||||
"entityType": "columns",
|
||||
"table": "todo"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "position",
|
||||
"entityType": "columns",
|
||||
"table": "todo"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "time_created",
|
||||
"entityType": "columns",
|
||||
"table": "todo"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "time_updated",
|
||||
"entityType": "columns",
|
||||
"table": "todo"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "session_id",
|
||||
"entityType": "columns",
|
||||
"table": "session_share"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "id",
|
||||
"entityType": "columns",
|
||||
"table": "session_share"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "secret",
|
||||
"entityType": "columns",
|
||||
"table": "session_share"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "url",
|
||||
"entityType": "columns",
|
||||
"table": "session_share"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "time_created",
|
||||
"entityType": "columns",
|
||||
"table": "session_share"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "time_updated",
|
||||
"entityType": "columns",
|
||||
"table": "session_share"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "aggregate_id",
|
||||
"entityType": "columns",
|
||||
"table": "event_sequence"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "seq",
|
||||
"entityType": "columns",
|
||||
"table": "event_sequence"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "id",
|
||||
"entityType": "columns",
|
||||
"table": "event"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "aggregate_id",
|
||||
"entityType": "columns",
|
||||
"table": "event"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "seq",
|
||||
"entityType": "columns",
|
||||
"table": "event"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "type",
|
||||
"entityType": "columns",
|
||||
"table": "event"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": null,
|
||||
"generated": null,
|
||||
"name": "data",
|
||||
"entityType": "columns",
|
||||
"table": "event"
|
||||
},
|
||||
{
|
||||
"columns": ["active_account_id"],
|
||||
"tableTo": "account",
|
||||
"columnsTo": ["id"],
|
||||
"onUpdate": "NO ACTION",
|
||||
"onDelete": "SET NULL",
|
||||
"nameExplicit": false,
|
||||
"name": "fk_account_state_active_account_id_account_id_fk",
|
||||
"entityType": "fks",
|
||||
"table": "account_state"
|
||||
},
|
||||
{
|
||||
"columns": ["project_id"],
|
||||
"tableTo": "project",
|
||||
"columnsTo": ["id"],
|
||||
"onUpdate": "NO ACTION",
|
||||
"onDelete": "CASCADE",
|
||||
"nameExplicit": false,
|
||||
"name": "fk_workspace_project_id_project_id_fk",
|
||||
"entityType": "fks",
|
||||
"table": "workspace"
|
||||
},
|
||||
{
|
||||
"columns": ["session_id"],
|
||||
"tableTo": "session",
|
||||
"columnsTo": ["id"],
|
||||
"onUpdate": "NO ACTION",
|
||||
"onDelete": "CASCADE",
|
||||
"nameExplicit": false,
|
||||
"name": "fk_message_session_id_session_id_fk",
|
||||
"entityType": "fks",
|
||||
"table": "message"
|
||||
},
|
||||
{
|
||||
"columns": ["message_id"],
|
||||
"tableTo": "message",
|
||||
"columnsTo": ["id"],
|
||||
"onUpdate": "NO ACTION",
|
||||
"onDelete": "CASCADE",
|
||||
"nameExplicit": false,
|
||||
"name": "fk_part_message_id_message_id_fk",
|
||||
"entityType": "fks",
|
||||
"table": "part"
|
||||
},
|
||||
{
|
||||
"columns": ["project_id"],
|
||||
"tableTo": "project",
|
||||
"columnsTo": ["id"],
|
||||
"onUpdate": "NO ACTION",
|
||||
"onDelete": "CASCADE",
|
||||
"nameExplicit": false,
|
||||
"name": "fk_permission_project_id_project_id_fk",
|
||||
"entityType": "fks",
|
||||
"table": "permission"
|
||||
},
|
||||
{
|
||||
"columns": ["session_id"],
|
||||
"tableTo": "session",
|
||||
"columnsTo": ["id"],
|
||||
"onUpdate": "NO ACTION",
|
||||
"onDelete": "CASCADE",
|
||||
"nameExplicit": false,
|
||||
"name": "fk_session_entry_session_id_session_id_fk",
|
||||
"entityType": "fks",
|
||||
"table": "session_entry"
|
||||
},
|
||||
{
|
||||
"columns": ["project_id"],
|
||||
"tableTo": "project",
|
||||
"columnsTo": ["id"],
|
||||
"onUpdate": "NO ACTION",
|
||||
"onDelete": "CASCADE",
|
||||
"nameExplicit": false,
|
||||
"name": "fk_session_project_id_project_id_fk",
|
||||
"entityType": "fks",
|
||||
"table": "session"
|
||||
},
|
||||
{
|
||||
"columns": ["session_id"],
|
||||
"tableTo": "session",
|
||||
"columnsTo": ["id"],
|
||||
"onUpdate": "NO ACTION",
|
||||
"onDelete": "CASCADE",
|
||||
"nameExplicit": false,
|
||||
"name": "fk_todo_session_id_session_id_fk",
|
||||
"entityType": "fks",
|
||||
"table": "todo"
|
||||
},
|
||||
{
|
||||
"columns": ["session_id"],
|
||||
"tableTo": "session",
|
||||
"columnsTo": ["id"],
|
||||
"onUpdate": "NO ACTION",
|
||||
"onDelete": "CASCADE",
|
||||
"nameExplicit": false,
|
||||
"name": "fk_session_share_session_id_session_id_fk",
|
||||
"entityType": "fks",
|
||||
"table": "session_share"
|
||||
},
|
||||
{
|
||||
"columns": ["aggregate_id"],
|
||||
"tableTo": "event_sequence",
|
||||
"columnsTo": ["aggregate_id"],
|
||||
"onUpdate": "NO ACTION",
|
||||
"onDelete": "CASCADE",
|
||||
"nameExplicit": false,
|
||||
"name": "fk_event_aggregate_id_event_sequence_aggregate_id_fk",
|
||||
"entityType": "fks",
|
||||
"table": "event"
|
||||
},
|
||||
{
|
||||
"columns": ["email", "url"],
|
||||
"nameExplicit": false,
|
||||
"name": "control_account_pk",
|
||||
"entityType": "pks",
|
||||
"table": "control_account"
|
||||
},
|
||||
{
|
||||
"columns": ["session_id", "position"],
|
||||
"nameExplicit": false,
|
||||
"name": "todo_pk",
|
||||
"entityType": "pks",
|
||||
"table": "todo"
|
||||
},
|
||||
{
|
||||
"columns": ["id"],
|
||||
"nameExplicit": false,
|
||||
"name": "account_state_pk",
|
||||
"table": "account_state",
|
||||
"entityType": "pks"
|
||||
},
|
||||
{
|
||||
"columns": ["id"],
|
||||
"nameExplicit": false,
|
||||
"name": "account_pk",
|
||||
"table": "account",
|
||||
"entityType": "pks"
|
||||
},
|
||||
{
|
||||
"columns": ["id"],
|
||||
"nameExplicit": false,
|
||||
"name": "workspace_pk",
|
||||
"table": "workspace",
|
||||
"entityType": "pks"
|
||||
},
|
||||
{
|
||||
"columns": ["id"],
|
||||
"nameExplicit": false,
|
||||
"name": "project_pk",
|
||||
"table": "project",
|
||||
"entityType": "pks"
|
||||
},
|
||||
{
|
||||
"columns": ["id"],
|
||||
"nameExplicit": false,
|
||||
"name": "message_pk",
|
||||
"table": "message",
|
||||
"entityType": "pks"
|
||||
},
|
||||
{
|
||||
"columns": ["id"],
|
||||
"nameExplicit": false,
|
||||
"name": "part_pk",
|
||||
"table": "part",
|
||||
"entityType": "pks"
|
||||
},
|
||||
{
|
||||
"columns": ["project_id"],
|
||||
"nameExplicit": false,
|
||||
"name": "permission_pk",
|
||||
"table": "permission",
|
||||
"entityType": "pks"
|
||||
},
|
||||
{
|
||||
"columns": ["id"],
|
||||
"nameExplicit": false,
|
||||
"name": "session_entry_pk",
|
||||
"table": "session_entry",
|
||||
"entityType": "pks"
|
||||
},
|
||||
{
|
||||
"columns": ["id"],
|
||||
"nameExplicit": false,
|
||||
"name": "session_pk",
|
||||
"table": "session",
|
||||
"entityType": "pks"
|
||||
},
|
||||
{
|
||||
"columns": ["session_id"],
|
||||
"nameExplicit": false,
|
||||
"name": "session_share_pk",
|
||||
"table": "session_share",
|
||||
"entityType": "pks"
|
||||
},
|
||||
{
|
||||
"columns": ["aggregate_id"],
|
||||
"nameExplicit": false,
|
||||
"name": "event_sequence_pk",
|
||||
"table": "event_sequence",
|
||||
"entityType": "pks"
|
||||
},
|
||||
{
|
||||
"columns": ["id"],
|
||||
"nameExplicit": false,
|
||||
"name": "event_pk",
|
||||
"table": "event",
|
||||
"entityType": "pks"
|
||||
},
|
||||
{
|
||||
"columns": [
|
||||
{
|
||||
"value": "session_id",
|
||||
"isExpression": false
|
||||
},
|
||||
{
|
||||
"value": "time_created",
|
||||
"isExpression": false
|
||||
},
|
||||
{
|
||||
"value": "id",
|
||||
"isExpression": false
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"where": null,
|
||||
"origin": "manual",
|
||||
"name": "message_session_time_created_id_idx",
|
||||
"entityType": "indexes",
|
||||
"table": "message"
|
||||
},
|
||||
{
|
||||
"columns": [
|
||||
{
|
||||
"value": "message_id",
|
||||
"isExpression": false
|
||||
},
|
||||
{
|
||||
"value": "id",
|
||||
"isExpression": false
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"where": null,
|
||||
"origin": "manual",
|
||||
"name": "part_message_id_id_idx",
|
||||
"entityType": "indexes",
|
||||
"table": "part"
|
||||
},
|
||||
{
|
||||
"columns": [
|
||||
{
|
||||
"value": "session_id",
|
||||
"isExpression": false
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"where": null,
|
||||
"origin": "manual",
|
||||
"name": "part_session_idx",
|
||||
"entityType": "indexes",
|
||||
"table": "part"
|
||||
},
|
||||
{
|
||||
"columns": [
|
||||
{
|
||||
"value": "session_id",
|
||||
"isExpression": false
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"where": null,
|
||||
"origin": "manual",
|
||||
"name": "session_entry_session_idx",
|
||||
"entityType": "indexes",
|
||||
"table": "session_entry"
|
||||
},
|
||||
{
|
||||
"columns": [
|
||||
{
|
||||
"value": "session_id",
|
||||
"isExpression": false
|
||||
},
|
||||
{
|
||||
"value": "type",
|
||||
"isExpression": false
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"where": null,
|
||||
"origin": "manual",
|
||||
"name": "session_entry_session_type_idx",
|
||||
"entityType": "indexes",
|
||||
"table": "session_entry"
|
||||
},
|
||||
{
|
||||
"columns": [
|
||||
{
|
||||
"value": "time_created",
|
||||
"isExpression": false
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"where": null,
|
||||
"origin": "manual",
|
||||
"name": "session_entry_time_created_idx",
|
||||
"entityType": "indexes",
|
||||
"table": "session_entry"
|
||||
},
|
||||
{
|
||||
"columns": [
|
||||
{
|
||||
"value": "project_id",
|
||||
"isExpression": false
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"where": null,
|
||||
"origin": "manual",
|
||||
"name": "session_project_idx",
|
||||
"entityType": "indexes",
|
||||
"table": "session"
|
||||
},
|
||||
{
|
||||
"columns": [
|
||||
{
|
||||
"value": "workspace_id",
|
||||
"isExpression": false
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"where": null,
|
||||
"origin": "manual",
|
||||
"name": "session_workspace_idx",
|
||||
"entityType": "indexes",
|
||||
"table": "session"
|
||||
},
|
||||
{
|
||||
"columns": [
|
||||
{
|
||||
"value": "parent_id",
|
||||
"isExpression": false
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"where": null,
|
||||
"origin": "manual",
|
||||
"name": "session_parent_idx",
|
||||
"entityType": "indexes",
|
||||
"table": "session"
|
||||
},
|
||||
{
|
||||
"columns": [
|
||||
{
|
||||
"value": "session_id",
|
||||
"isExpression": false
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"where": null,
|
||||
"origin": "manual",
|
||||
"name": "todo_session_idx",
|
||||
"entityType": "indexes",
|
||||
"table": "todo"
|
||||
}
|
||||
],
|
||||
"renames": []
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"version": "1.14.25",
|
||||
"version": "1.14.29",
|
||||
"name": "opencode",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
@@ -115,7 +115,7 @@
|
||||
"@opencode-ai/plugin": "workspace:*",
|
||||
"@opencode-ai/script": "workspace:*",
|
||||
"@opencode-ai/sdk": "workspace:*",
|
||||
"@openrouter/ai-sdk-provider": "2.5.1",
|
||||
"@openrouter/ai-sdk-provider": "2.8.1",
|
||||
"@opentelemetry/api": "1.9.0",
|
||||
"@opentelemetry/context-async-hooks": "2.6.1",
|
||||
"@opentelemetry/exporter-trace-otlp-http": "0.214.0",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bun
|
||||
|
||||
import { z } from "zod"
|
||||
import { Config } from "../src/config"
|
||||
import { Config } from "@/config/config"
|
||||
import { TuiConfig } from "../src/cli/cmd/tui/config/tui"
|
||||
|
||||
function generate(schema: z.ZodType) {
|
||||
|
||||
Executable
+52
@@ -0,0 +1,52 @@
|
||||
#!/bin/bash
|
||||
# Compare SDK types generated from Hono vs HttpApi specs.
|
||||
# Sorts types alphabetically so only meaningful body differences show.
|
||||
#
|
||||
# Usage: ./scripts/diff-sdk-types.sh # full diff
|
||||
# ./scripts/diff-sdk-types.sh --stat # summary only
|
||||
set -euo pipefail
|
||||
|
||||
DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
SDK="$(cd "$DIR/../sdk/js" && pwd)"
|
||||
|
||||
normalize() {
|
||||
python3 -c "
|
||||
import re, sys
|
||||
content = open(sys.argv[1]).read()
|
||||
blocks = re.split(r'(?=^export (?:type|function|const) )', content, flags=re.MULTILINE)
|
||||
header, body = blocks[0], blocks[1:]
|
||||
body.sort(key=lambda b: m.group(1) if (m := re.match(r'export \w+ (\w+)', b)) else '')
|
||||
sys.stdout.write(header + ''.join(body))
|
||||
" "$1"
|
||||
}
|
||||
|
||||
echo "Generating Hono SDK..." >&2
|
||||
(cd "$SDK" && bun run script/build.ts >/dev/null 2>&1)
|
||||
normalize "$SDK/src/v2/gen/types.gen.ts" > /tmp/sdk-types-hono.ts
|
||||
git -C "$SDK" checkout -- src/ 2>/dev/null
|
||||
|
||||
echo "Generating HttpApi SDK..." >&2
|
||||
(cd "$SDK" && OPENCODE_SDK_OPENAPI=httpapi bun run script/build.ts >/dev/null 2>&1)
|
||||
normalize "$SDK/src/v2/gen/types.gen.ts" > /tmp/sdk-types-httpapi.ts
|
||||
git -C "$SDK" checkout -- src/ 2>/dev/null
|
||||
|
||||
echo "" >&2
|
||||
if [[ "${1:-}" == "--stat" ]]; then
|
||||
diff_output=$(diff /tmp/sdk-types-hono.ts /tmp/sdk-types-httpapi.ts || true)
|
||||
honly=$(printf "%s\n" "$diff_output" | grep -c '^< export type' || true)
|
||||
aonly=$(printf "%s\n" "$diff_output" | grep -c '^> export type' || true)
|
||||
total=$(printf "%s\n" "$diff_output" | wc -l | tr -d ' ')
|
||||
echo "Hono-only: $honly types HttpApi-only: $aonly types Diff lines: $total"
|
||||
echo ""
|
||||
if [[ $honly -gt 0 ]]; then
|
||||
echo "=== Hono-only types ==="
|
||||
printf "%s\n" "$diff_output" | grep '^< export type' | sed 's/< export type //' | sed 's/[ =].*//' | sed 's/^/ /'
|
||||
echo ""
|
||||
fi
|
||||
if [[ $aonly -gt 0 ]]; then
|
||||
echo "=== HttpApi-only types ==="
|
||||
printf "%s\n" "$diff_output" | grep '^> export type' | sed 's/> export type //' | sed 's/[ =].*//' | sed 's/^/ /'
|
||||
fi
|
||||
else
|
||||
diff /tmp/sdk-types-hono.ts /tmp/sdk-types-httpapi.ts || true
|
||||
fi
|
||||
@@ -129,6 +129,14 @@ Required before route deletion:
|
||||
- Compare generated SDK output against `dev` for every route group deletion.
|
||||
- Remove Hono OpenAPI stubs only after Effect OpenAPI is the SDK source for those paths.
|
||||
|
||||
V2 cleanup once SDK compatibility no longer needs the legacy Hono contract:
|
||||
|
||||
- Remove `public.ts` compatibility transforms that hide honest `HttpApi` metadata, including auth `securitySchemes`, per-route `security`, and generated `401` responses.
|
||||
- Stop remapping built-in `HttpApi` error schemas back to legacy Hono `BadRequestError` / `NotFoundError` components if V2 clients can consume the actual Effect error shape.
|
||||
- Prefer the direct `HttpApi` OpenAPI output for request/response bodies and named component schemas instead of rewriting it to match Hono generator quirks.
|
||||
- Keep schema fixes that describe the actual wire format, but delete transforms that only preserve legacy SDK type names or inline-vs-ref shape.
|
||||
- Re-evaluate `auth_token` as an OpenAPI security scheme rather than a hand-injected query parameter once clients can consume the V2 spec.
|
||||
|
||||
### 5. Make HttpApi Default For JSON Routes
|
||||
|
||||
After JSON parity and SDK generation are covered:
|
||||
@@ -170,23 +178,23 @@ Use raw Effect HTTP routes where `HttpApi` does not fit. The goal is deleting Ho
|
||||
|
||||
## Current Route Status
|
||||
|
||||
| Area | Status | Notes |
|
||||
| ------------------------- | ----------------- | -------------------------------------------------------------------------------------------------- |
|
||||
| `question` | `bridged` | `GET /question`, reply, reject |
|
||||
| `permission` | `bridged` | list and reply |
|
||||
| `provider` | `bridged` | list, auth, OAuth authorize/callback |
|
||||
| `config` | `bridged` | read, providers, update |
|
||||
| `project` | `bridged` | list, current, git init, update |
|
||||
| `file` | `bridged` partial | find text/file/symbol, list/content/status |
|
||||
| `mcp` | `bridged` | status, add, OAuth, connect/disconnect |
|
||||
| `workspace` | `bridged` partial | adaptor/list/status; create/remove/session-restore remain |
|
||||
| top-level instance routes | `bridged` | path, vcs, command, agent, skill, lsp, formatter, dispose |
|
||||
| experimental JSON routes | `bridged` partial | console reads, tool ids, worktree list/mutations, resource list; global session list remains later |
|
||||
| `session` | `later/special` | large stateful surface plus streaming |
|
||||
| `sync` | `later` | process/control side effects |
|
||||
| `event` | `special` | SSE |
|
||||
| `pty` | `special` | websocket |
|
||||
| `tui` | `special` | UI bridge |
|
||||
| Area | Status | Notes |
|
||||
| ------------------------- | ----------------- | -------------------------------------------------------------------------- |
|
||||
| `question` | `bridged` | `GET /question`, reply, reject |
|
||||
| `permission` | `bridged` | list and reply |
|
||||
| `provider` | `bridged` | list, auth, OAuth authorize/callback |
|
||||
| `config` | `bridged` | read, providers, update |
|
||||
| `project` | `bridged` | list, current, git init, update |
|
||||
| `file` | `bridged` partial | find text/file/symbol, list/content/status |
|
||||
| `mcp` | `bridged` | status, add, OAuth, connect/disconnect |
|
||||
| `workspace` | `bridged` | adaptor/list/status/create/remove/session-restore |
|
||||
| top-level instance routes | `bridged` | path, vcs, command, agent, skill, lsp, formatter, dispose |
|
||||
| experimental JSON routes | `bridged` | console, tool, worktree list/mutations, global session list, resource list |
|
||||
| `session` | `bridged` | read, lifecycle, prompt, message/part mutations, revert, permission reply |
|
||||
| `sync` | `bridged` | start/replay/history |
|
||||
| `event` | `bridged` | SSE via raw Effect HTTP |
|
||||
| `pty` | `special` | websocket |
|
||||
| `tui` | `special` | UI bridge |
|
||||
|
||||
## Full Route Checklist
|
||||
|
||||
@@ -259,89 +267,89 @@ This checklist tracks bridge parity only. Checked routes are available through t
|
||||
|
||||
- [x] `GET /experimental/console` - active Console provider metadata.
|
||||
- [x] `GET /experimental/console/orgs` - switchable Console orgs.
|
||||
- [ ] `POST /experimental/console/switch` - switch active Console org.
|
||||
- [x] `POST /experimental/console/switch` - switch active Console org.
|
||||
- [x] `GET /experimental/tool/ids` - tool IDs.
|
||||
- [ ] `GET /experimental/tool` - tools for provider/model.
|
||||
- [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/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] `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.
|
||||
- [x] `DELETE /experimental/workspace/:id` - remove workspace.
|
||||
- [x] `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.
|
||||
- [x] `POST /sync/start` - start workspace sync.
|
||||
- [x] `POST /sync/replay` - replay sync events.
|
||||
- [x] `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.
|
||||
- [x] `GET /session` - list sessions.
|
||||
- [x] `GET /session/status` - session status map.
|
||||
- [x] `GET /session/:sessionID` - get session.
|
||||
- [x] `GET /session/:sessionID/children` - get child sessions.
|
||||
- [x] `GET /session/:sessionID/todo` - get session todos.
|
||||
- [x] `POST /session` - create session.
|
||||
- [x] `DELETE /session/:sessionID` - delete session.
|
||||
- [x] `PATCH /session/:sessionID` - update session metadata.
|
||||
- [x] `POST /session/:sessionID/init` - run project init command.
|
||||
- [x] `POST /session/:sessionID/fork` - fork session.
|
||||
- [x] `POST /session/:sessionID/abort` - abort session.
|
||||
- [x] `POST /session/:sessionID/share` - share session.
|
||||
- [x] `GET /session/:sessionID/diff` - session diff.
|
||||
- [x] `DELETE /session/:sessionID/share` - unshare session.
|
||||
- [x] `POST /session/:sessionID/summarize` - summarize session.
|
||||
- [x] `GET /session/:sessionID/message` - list session messages.
|
||||
- [x] `GET /session/:sessionID/message/:messageID` - get message.
|
||||
- [x] `DELETE /session/:sessionID/message/:messageID` - delete message.
|
||||
- [x] `DELETE /session/:sessionID/message/:messageID/part/:partID` - delete part.
|
||||
- [x] `PATCH /session/:sessionID/message/:messageID/part/:partID` - update part.
|
||||
- [x] `POST /session/:sessionID/message` - prompt with streaming response.
|
||||
- [x] `POST /session/:sessionID/prompt_async` - async prompt.
|
||||
- [x] `POST /session/:sessionID/command` - run command.
|
||||
- [x] `POST /session/:sessionID/shell` - run shell command.
|
||||
- [x] `POST /session/:sessionID/revert` - revert message.
|
||||
- [x] `POST /session/:sessionID/unrevert` - restore reverted messages.
|
||||
- [x] `POST /session/:sessionID/permissions/:permissionID` - deprecated permission response route.
|
||||
|
||||
### Event Routes
|
||||
|
||||
- [ ] `GET /event` - SSE event stream; replace with raw Effect HTTP, not `HttpApi`.
|
||||
- [x] `GET /event` - SSE event stream via raw Effect HTTP.
|
||||
|
||||
### 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.
|
||||
- [x] `GET /pty` - list PTY sessions.
|
||||
- [x] `POST /pty` - create PTY session.
|
||||
- [x] `GET /pty/:ptyID` - get PTY session.
|
||||
- [x] `PUT /pty/:ptyID` - update PTY session.
|
||||
- [x] `DELETE /pty/:ptyID` - remove PTY session.
|
||||
- [x] `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.
|
||||
- [x] `POST /tui/append-prompt` - append prompt.
|
||||
- [x] `POST /tui/open-help` - open help.
|
||||
- [x] `POST /tui/open-sessions` - open sessions.
|
||||
- [x] `POST /tui/open-themes` - open themes.
|
||||
- [x] `POST /tui/open-models` - open models.
|
||||
- [x] `POST /tui/submit-prompt` - submit prompt.
|
||||
- [x] `POST /tui/clear-prompt` - clear prompt.
|
||||
- [x] `POST /tui/execute-command` - execute command.
|
||||
- [x] `POST /tui/show-toast` - show toast.
|
||||
- [x] `POST /tui/publish` - publish TUI event.
|
||||
- [x] `POST /tui/select-session` - select session.
|
||||
- [x] `GET /tui/control/next` - get next TUI request.
|
||||
- [x] `POST /tui/control/response` - submit TUI control response.
|
||||
|
||||
## Remaining PR Plan
|
||||
|
||||
@@ -350,16 +358,16 @@ Prefer smaller PRs from here so route behavior and SDK/OpenAPI fallout stays rev
|
||||
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. [ ] 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.
|
||||
4. [x] Bridge experimental console switch and tool list routes.
|
||||
5. [x] Bridge experimental global session list.
|
||||
6. [x] Bridge workspace create/remove/session-restore routes.
|
||||
7. [x] Bridge sync start/replay/history routes.
|
||||
8. [x] Bridge session read routes: list, status, get, children, todo, diff, messages.
|
||||
9. [x] Bridge session lifecycle mutation routes: create, delete, update, fork, abort.
|
||||
10. [x] Bridge remaining session mutation and prompt 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.
|
||||
12. [x] Replace pty websocket/control routes with non-Hono Effect HTTP.
|
||||
13. [x] 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.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { eq } from "drizzle-orm"
|
||||
import { Effect, Layer, Option, Schema, Context } from "effect"
|
||||
|
||||
import { Database } from "@/storage"
|
||||
import { Database } from "@/storage/db"
|
||||
import { AccountStateTable, AccountTable } from "./account.sql"
|
||||
import { AccessToken, AccountID, AccountRepoError, Info, OrgID, RefreshToken } from "./schema"
|
||||
import { normalizeServerUrl } from "./url"
|
||||
|
||||
@@ -31,19 +31,19 @@ import {
|
||||
type Usage,
|
||||
} from "@agentclientprotocol/sdk"
|
||||
|
||||
import { Log } from "../util"
|
||||
import * as Log from "@opencode-ai/core/util/log"
|
||||
import { pathToFileURL } from "url"
|
||||
import { Filesystem } from "../util"
|
||||
import { Filesystem } from "@/util/filesystem"
|
||||
import { Hash } from "@opencode-ai/core/util/hash"
|
||||
import { ACPSessionManager } from "./session"
|
||||
import type { ACPConfig } from "./types"
|
||||
import { Provider } from "../provider"
|
||||
import { Provider } from "@/provider/provider"
|
||||
import { ModelID, ProviderID } from "../provider/schema"
|
||||
import { Agent as AgentModule } from "../agent/agent"
|
||||
import { AppRuntime } from "@/effect/app-runtime"
|
||||
import { Installation } from "@/installation"
|
||||
import { MessageV2 } from "@/session/message-v2"
|
||||
import { Config } from "@/config"
|
||||
import { Config } from "@/config/config"
|
||||
import { ConfigMCP } from "@/config/mcp"
|
||||
import { Todo } from "@/session/todo"
|
||||
import { Result, Schema } from "effect"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { RequestError, type McpServer } from "@agentclientprotocol/sdk"
|
||||
import type { ACPSessionState } from "./types"
|
||||
import { Log } from "@/util"
|
||||
import * as Log from "@opencode-ai/core/util/log"
|
||||
import type { OpencodeClient } from "@opencode-ai/sdk/v2"
|
||||
|
||||
const log = Log.create({ service: "acp-session-manager" })
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { Config } from "../config"
|
||||
import { Config } from "@/config/config"
|
||||
import z from "zod"
|
||||
import { Provider } from "../provider"
|
||||
import { Provider } from "@/provider/provider"
|
||||
import { ModelID, ProviderID } from "../provider/schema"
|
||||
import { generateObject, streamObject, type ModelMessage } from "ai"
|
||||
import { Truncate } from "../tool"
|
||||
import { Truncate } from "@/tool/truncate"
|
||||
import { Auth } from "../auth"
|
||||
import { ProviderTransform } from "../provider"
|
||||
import { ProviderTransform } from "@/provider/transform"
|
||||
|
||||
import PROMPT_GENERATE from "./generate.txt"
|
||||
import PROMPT_COMPACTION from "./prompt/compaction.txt"
|
||||
@@ -19,7 +19,7 @@ import path from "path"
|
||||
import { Plugin } from "@/plugin"
|
||||
import { Skill } from "../skill"
|
||||
import { Effect, Context, Layer, Schema } from "effect"
|
||||
import { InstanceState } from "@/effect"
|
||||
import { InstanceState } from "@/effect/instance-state"
|
||||
import * as Option from "effect/Option"
|
||||
import * as OtelTracer from "@effect/opentelemetry/Tracer"
|
||||
import { zod } from "@/util/effect-zod"
|
||||
@@ -31,8 +31,8 @@ export const Info = Schema.Struct({
|
||||
mode: Schema.Literals(["subagent", "primary", "all"]),
|
||||
native: Schema.optional(Schema.Boolean),
|
||||
hidden: Schema.optional(Schema.Boolean),
|
||||
topP: Schema.optional(Schema.Number),
|
||||
temperature: Schema.optional(Schema.Number),
|
||||
topP: Schema.optional(Schema.Finite),
|
||||
temperature: Schema.optional(Schema.Finite),
|
||||
color: Schema.optional(Schema.String),
|
||||
permission: Permission.Ruleset,
|
||||
model: Schema.optional(
|
||||
@@ -44,7 +44,7 @@ export const Info = Schema.Struct({
|
||||
variant: Schema.optional(Schema.String),
|
||||
prompt: Schema.optional(Schema.String),
|
||||
options: Schema.Record(Schema.String, Schema.Unknown),
|
||||
steps: Schema.optional(Schema.Number),
|
||||
steps: Schema.optional(Schema.Finite),
|
||||
})
|
||||
.annotate({ identifier: "Agent" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import path from "path"
|
||||
import { Effect, Layer, Record, Result, Schema, Context } from "effect"
|
||||
import { zod } from "@/util/effect-zod"
|
||||
import { NonNegativeInt } from "@/util/schema"
|
||||
import { Global } from "@opencode-ai/core/global"
|
||||
import { AppFileSystem } from "@opencode-ai/core/filesystem"
|
||||
|
||||
@@ -14,7 +15,7 @@ export class Oauth extends Schema.Class<Oauth>("OAuth")({
|
||||
type: Schema.Literal("oauth"),
|
||||
refresh: Schema.String,
|
||||
access: Schema.String,
|
||||
expires: Schema.Number,
|
||||
expires: NonNegativeInt,
|
||||
accountId: Schema.optional(Schema.String),
|
||||
enterpriseUrl: Schema.optional(Schema.String),
|
||||
}) {}
|
||||
|
||||
@@ -34,4 +34,16 @@ export function payloads() {
|
||||
.toArray()
|
||||
}
|
||||
|
||||
export function effectPayloads() {
|
||||
return registry
|
||||
.entries()
|
||||
.map(([type, def]) =>
|
||||
Schema.Struct({
|
||||
type: Schema.Literal(type),
|
||||
properties: def.properties,
|
||||
}).annotate({ identifier: `Event.${type}` }),
|
||||
)
|
||||
.toArray()
|
||||
}
|
||||
|
||||
export * as BusEvent from "./bus-event"
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Effect, Exit, Layer, PubSub, Scope, Context, Stream, Schema } from "effect"
|
||||
import { EffectBridge } from "@/effect"
|
||||
import { Log } from "../util"
|
||||
import { EffectBridge } from "@/effect/bridge"
|
||||
import * as Log from "@opencode-ai/core/util/log"
|
||||
import { BusEvent } from "./bus-event"
|
||||
import { GlobalBus } from "./global"
|
||||
import { InstanceState } from "@/effect"
|
||||
import { InstanceState } from "@/effect/instance-state"
|
||||
import { makeRuntime } from "@/effect/run-service"
|
||||
|
||||
const log = Log.create({ service: "bus" })
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Log } from "@/util"
|
||||
import * as Log from "@opencode-ai/core/util/log"
|
||||
import { bootstrap } from "../bootstrap"
|
||||
import { cmd } from "./cmd"
|
||||
import { AgentSideConnection, ndJsonStream } from "@agentclientprotocol/sdk"
|
||||
|
||||
@@ -4,10 +4,10 @@ import { AppRuntime } from "@/effect/app-runtime"
|
||||
import { UI } from "../ui"
|
||||
import { Global } from "@opencode-ai/core/global"
|
||||
import { Agent } from "../../agent/agent"
|
||||
import { Provider } from "../../provider"
|
||||
import { Provider } from "@/provider/provider"
|
||||
import path from "path"
|
||||
import fs from "fs/promises"
|
||||
import { Filesystem } from "../../util"
|
||||
import { Filesystem } from "@/util/filesystem"
|
||||
import matter from "gray-matter"
|
||||
import { Instance } from "../../project/instance"
|
||||
import { EOL } from "os"
|
||||
@@ -15,7 +15,23 @@ import type { Argv } from "yargs"
|
||||
|
||||
type AgentMode = "all" | "primary" | "subagent"
|
||||
|
||||
const AVAILABLE_TOOLS = ["bash", "read", "write", "edit", "glob", "grep", "webfetch", "task", "todowrite"]
|
||||
// Permission keys (not raw tool names). Multiple tools can map to a single
|
||||
// permission — e.g. write/edit/apply_patch all gate on `edit` — so we configure
|
||||
// agents at the permission level to match how the runtime actually enforces it.
|
||||
const AVAILABLE_PERMISSIONS = [
|
||||
"bash",
|
||||
"read",
|
||||
"edit",
|
||||
"glob",
|
||||
"grep",
|
||||
"webfetch",
|
||||
"task",
|
||||
"todowrite",
|
||||
"websearch",
|
||||
"codesearch",
|
||||
"lsp",
|
||||
"skill",
|
||||
]
|
||||
|
||||
const AgentCreateCommand = cmd({
|
||||
command: "create",
|
||||
@@ -35,9 +51,10 @@ const AgentCreateCommand = cmd({
|
||||
describe: "agent mode",
|
||||
choices: ["all", "primary", "subagent"] as const,
|
||||
})
|
||||
.option("tools", {
|
||||
.option("permissions", {
|
||||
type: "string",
|
||||
describe: `comma-separated list of tools to enable (default: all). Available: "${AVAILABLE_TOOLS.join(", ")}"`,
|
||||
alias: ["tools"],
|
||||
describe: `comma-separated list of permissions to allow (default: all). Available: "${AVAILABLE_PERMISSIONS.join(", ")}"`,
|
||||
})
|
||||
.option("model", {
|
||||
type: "string",
|
||||
@@ -51,9 +68,9 @@ const AgentCreateCommand = cmd({
|
||||
const cliPath = args.path
|
||||
const cliDescription = args.description
|
||||
const cliMode = args.mode as AgentMode | undefined
|
||||
const cliTools = args.tools
|
||||
const perms = args.permissions
|
||||
|
||||
const isFullyNonInteractive = cliPath && cliDescription && cliMode && cliTools !== undefined
|
||||
const isFullyNonInteractive = cliPath && cliDescription && cliMode && perms !== undefined
|
||||
|
||||
if (!isFullyNonInteractive) {
|
||||
UI.empty()
|
||||
@@ -120,21 +137,21 @@ const AgentCreateCommand = cmd({
|
||||
})
|
||||
spinner.stop(`Agent ${generated.identifier} generated`)
|
||||
|
||||
// Select tools
|
||||
let selectedTools: string[]
|
||||
if (cliTools !== undefined) {
|
||||
selectedTools = cliTools ? cliTools.split(",").map((t) => t.trim()) : AVAILABLE_TOOLS
|
||||
// Select permissions to allow
|
||||
let selected: string[]
|
||||
if (perms !== undefined) {
|
||||
selected = perms ? perms.split(",").map((t) => t.trim()) : AVAILABLE_PERMISSIONS
|
||||
} else {
|
||||
const result = await prompts.multiselect({
|
||||
message: "Select tools to enable (Space to toggle)",
|
||||
options: AVAILABLE_TOOLS.map((tool) => ({
|
||||
label: tool,
|
||||
value: tool,
|
||||
message: "Select permissions to allow (Space to toggle)",
|
||||
options: AVAILABLE_PERMISSIONS.map((permission) => ({
|
||||
label: permission,
|
||||
value: permission,
|
||||
})),
|
||||
initialValues: AVAILABLE_TOOLS,
|
||||
initialValues: AVAILABLE_PERMISSIONS,
|
||||
})
|
||||
if (prompts.isCancel(result)) throw new UI.CancelledError()
|
||||
selectedTools = result
|
||||
selected = result
|
||||
}
|
||||
|
||||
// Get mode
|
||||
@@ -167,11 +184,11 @@ const AgentCreateCommand = cmd({
|
||||
mode = modeResult
|
||||
}
|
||||
|
||||
// Build tools config
|
||||
const tools: Record<string, boolean> = {}
|
||||
for (const tool of AVAILABLE_TOOLS) {
|
||||
if (!selectedTools.includes(tool)) {
|
||||
tools[tool] = false
|
||||
// Build permissions config — deny anything not explicitly selected.
|
||||
const permissions: Record<string, "deny"> = {}
|
||||
for (const permission of AVAILABLE_PERMISSIONS) {
|
||||
if (!selected.includes(permission)) {
|
||||
permissions[permission] = "deny"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,13 +196,13 @@ const AgentCreateCommand = cmd({
|
||||
const frontmatter: {
|
||||
description: string
|
||||
mode: AgentMode
|
||||
tools?: Record<string, boolean>
|
||||
permission?: Record<string, "deny">
|
||||
} = {
|
||||
description: generated.whenToUse,
|
||||
mode,
|
||||
}
|
||||
if (Object.keys(tools).length > 0) {
|
||||
frontmatter.tools = tools
|
||||
if (Object.keys(permissions).length > 0) {
|
||||
frontmatter.permission = permissions
|
||||
}
|
||||
|
||||
// Write file
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import type { Argv } from "yargs"
|
||||
import { spawn } from "child_process"
|
||||
import { Database } from "../../storage"
|
||||
import { Database } from "@/storage/db"
|
||||
import { drizzle } from "drizzle-orm/bun-sqlite"
|
||||
import { Database as BunDatabase } from "bun:sqlite"
|
||||
import { UI } from "../ui"
|
||||
import { cmd } from "./cmd"
|
||||
import { JsonMigration } from "../../storage"
|
||||
import { JsonMigration } from "@/storage/json-migration"
|
||||
import { EOL } from "os"
|
||||
import { errorMessage } from "../../util/error"
|
||||
|
||||
|
||||
@@ -2,11 +2,11 @@ import { EOL } from "os"
|
||||
import { basename } from "path"
|
||||
import { Effect } from "effect"
|
||||
import { Agent } from "../../../agent/agent"
|
||||
import { Provider } from "../../../provider"
|
||||
import { Session } from "../../../session"
|
||||
import { Provider } from "@/provider/provider"
|
||||
import { Session } from "@/session/session"
|
||||
import type { MessageV2 } from "../../../session/message-v2"
|
||||
import { MessageID, PartID } from "../../../session/schema"
|
||||
import { ToolRegistry } from "../../../tool"
|
||||
import { ToolRegistry } from "@/tool/registry"
|
||||
import { Instance } from "../../../project/instance"
|
||||
import { Permission } from "../../../permission"
|
||||
import { iife } from "../../../util/iife"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { EOL } from "os"
|
||||
import { Config } from "../../../config"
|
||||
import { Config } from "@/config/config"
|
||||
import { AppRuntime } from "@/effect/app-runtime"
|
||||
import { bootstrap } from "../../bootstrap"
|
||||
import { cmd } from "../cmd"
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { LSP } from "../../../lsp"
|
||||
import { LSP } from "@/lsp/lsp"
|
||||
import { AppRuntime } from "../../../effect/app-runtime"
|
||||
import { Effect } from "effect"
|
||||
import { bootstrap } from "../../bootstrap"
|
||||
import { cmd } from "../cmd"
|
||||
import { Log } from "../../../util"
|
||||
import * as Log from "@opencode-ai/core/util/log"
|
||||
import { EOL } from "os"
|
||||
|
||||
export const LSPCommand = cmd({
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { EOL } from "os"
|
||||
import { Project } from "../../../project"
|
||||
import { Log } from "../../../util"
|
||||
import { Project } from "@/project/project"
|
||||
import * as Log from "@opencode-ai/core/util/log"
|
||||
import { cmd } from "../cmd"
|
||||
|
||||
export const ScrapCommand = cmd({
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { Argv } from "yargs"
|
||||
import { Session } from "../../session"
|
||||
import { Session } from "@/session/session"
|
||||
import { MessageV2 } from "../../session/message-v2"
|
||||
import { SessionID } from "../../session/schema"
|
||||
import { cmd } from "./cmd"
|
||||
|
||||
@@ -1,15 +1,26 @@
|
||||
import { Server } from "../../server/server"
|
||||
import { PublicApi } from "../../server/routes/instance/httpapi/public"
|
||||
import type { CommandModule } from "yargs"
|
||||
import { OpenApi } from "effect/unstable/httpapi"
|
||||
|
||||
type Args = {
|
||||
httpapi: boolean
|
||||
}
|
||||
|
||||
export const GenerateCommand = {
|
||||
command: "generate",
|
||||
handler: async () => {
|
||||
const specs = await Server.openapi()
|
||||
builder: (yargs) =>
|
||||
yargs.option("httpapi", {
|
||||
type: "boolean",
|
||||
default: false,
|
||||
description: "Generate OpenAPI from the experimental Effect HttpApi contract",
|
||||
}),
|
||||
handler: async (args) => {
|
||||
const specs = args.httpapi ? OpenApi.fromApi(PublicApi) : await Server.openapi()
|
||||
for (const item of Object.values(specs.paths)) {
|
||||
for (const method of ["get", "post", "put", "delete", "patch"] as const) {
|
||||
const operation = item[method]
|
||||
if (!operation?.operationId) continue
|
||||
// @ts-expect-error
|
||||
operation["x-codeSamples"] = [
|
||||
{
|
||||
lang: "js",
|
||||
@@ -47,4 +58,4 @@ export const GenerateCommand = {
|
||||
})
|
||||
})
|
||||
},
|
||||
} satisfies CommandModule
|
||||
} satisfies CommandModule<object, Args>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import path from "path"
|
||||
import { exec } from "child_process"
|
||||
import { Filesystem } from "../../util"
|
||||
import { Filesystem } from "@/util/filesystem"
|
||||
import * as prompts from "@clack/prompts"
|
||||
import { map, pipe, sortBy, values } from "remeda"
|
||||
import { Octokit } from "@octokit/rest"
|
||||
@@ -18,21 +18,21 @@ import type {
|
||||
} from "@octokit/webhooks-types"
|
||||
import { UI } from "../ui"
|
||||
import { cmd } from "./cmd"
|
||||
import { ModelsDev } from "../../provider"
|
||||
import { ModelsDev } from "@/provider/models"
|
||||
import { Instance } from "@/project/instance"
|
||||
import { bootstrap } from "../bootstrap"
|
||||
import { SessionShare } from "@/share"
|
||||
import { Session } from "../../session"
|
||||
import { SessionShare } from "@/share/session"
|
||||
import { Session } from "@/session/session"
|
||||
import type { SessionID } from "../../session/schema"
|
||||
import { MessageID, PartID } from "../../session/schema"
|
||||
import { Provider } from "../../provider"
|
||||
import { Provider } from "@/provider/provider"
|
||||
import { Bus } from "../../bus"
|
||||
import { MessageV2 } from "../../session/message-v2"
|
||||
import { SessionPrompt } from "@/session/prompt"
|
||||
import { AppRuntime } from "@/effect/app-runtime"
|
||||
import { Git } from "@/git"
|
||||
import { setTimeout as sleep } from "node:timers/promises"
|
||||
import { Process } from "@/util"
|
||||
import { Process } from "@/util/process"
|
||||
import { Effect } from "effect"
|
||||
|
||||
type GitHubAuthor = {
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import type { Argv } from "yargs"
|
||||
import type { Session as SDKSession, Message, Part } from "@opencode-ai/sdk/v2"
|
||||
import { Session } from "../../session"
|
||||
import { Session } from "@/session/session"
|
||||
import { MessageV2 } from "../../session/message-v2"
|
||||
import { cmd } from "./cmd"
|
||||
import { bootstrap } from "../bootstrap"
|
||||
import { Database } from "../../storage"
|
||||
import { Database } from "@/storage/db"
|
||||
import { SessionTable, MessageTable, PartTable } from "../../session/session.sql"
|
||||
import { Instance } from "../../project/instance"
|
||||
import { ShareNext } from "../../share"
|
||||
import { ShareNext } from "@/share/share-next"
|
||||
import { EOL } from "os"
|
||||
import { Filesystem } from "../../util"
|
||||
import { Filesystem } from "@/util/filesystem"
|
||||
import { AppRuntime } from "@/effect/app-runtime"
|
||||
import { Schema } from "effect"
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import { UI } from "../ui"
|
||||
import { MCP } from "../../mcp"
|
||||
import { McpAuth } from "../../mcp/auth"
|
||||
import { McpOAuthProvider } from "../../mcp/oauth-provider"
|
||||
import { Config } from "../../config"
|
||||
import { Config } from "@/config/config"
|
||||
import { ConfigMCP } from "../../config/mcp"
|
||||
import { Instance } from "../../project/instance"
|
||||
import { Installation } from "../../installation"
|
||||
@@ -15,7 +15,7 @@ import { InstallationVersion } from "@opencode-ai/core/installation/version"
|
||||
import path from "path"
|
||||
import { Global } from "@opencode-ai/core/global"
|
||||
import { modify, applyEdits } from "jsonc-parser"
|
||||
import { Filesystem } from "../../util"
|
||||
import { Filesystem } from "@/util/filesystem"
|
||||
import { Bus } from "../../bus"
|
||||
import { AppRuntime } from "../../effect/app-runtime"
|
||||
import { Effect } from "effect"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import type { Argv } from "yargs"
|
||||
import { Instance } from "../../project/instance"
|
||||
import { Provider } from "../../provider"
|
||||
import { Provider } from "@/provider/provider"
|
||||
import { ProviderID } from "../../provider/schema"
|
||||
import { ModelsDev } from "../../provider"
|
||||
import { ModelsDev } from "@/provider/models"
|
||||
import { cmd } from "./cmd"
|
||||
import { UI } from "../ui"
|
||||
import { EOL } from "os"
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { intro, log, outro, spinner } from "@clack/prompts"
|
||||
import type { Argv } from "yargs"
|
||||
|
||||
import { ConfigPaths } from "../../config"
|
||||
import { ConfigPaths } from "@/config/paths"
|
||||
import { Global } from "@opencode-ai/core/global"
|
||||
import { installPlugin, patchPluginConfig, readPluginManifest } from "../../plugin/install"
|
||||
import { resolvePluginTarget } from "../../plugin/shared"
|
||||
import { Instance } from "../../project/instance"
|
||||
import { errorMessage } from "../../util/error"
|
||||
import { Filesystem } from "../../util"
|
||||
import { Process } from "../../util"
|
||||
import { Filesystem } from "@/util/filesystem"
|
||||
import { Process } from "@/util/process"
|
||||
import { UI } from "../ui"
|
||||
import { cmd } from "./cmd"
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import { cmd } from "./cmd"
|
||||
import { AppRuntime } from "@/effect/app-runtime"
|
||||
import { Git } from "@/git"
|
||||
import { Instance } from "@/project/instance"
|
||||
import { Process } from "@/util"
|
||||
import { Process } from "@/util/process"
|
||||
|
||||
export const PrCommand = cmd({
|
||||
command: "pr <number>",
|
||||
|
||||
@@ -3,16 +3,16 @@ import { AppRuntime } from "../../effect/app-runtime"
|
||||
import { cmd } from "./cmd"
|
||||
import * as prompts from "@clack/prompts"
|
||||
import { UI } from "../ui"
|
||||
import { ModelsDev } from "../../provider"
|
||||
import { ModelsDev } from "@/provider/models"
|
||||
import { map, pipe, sortBy, values } from "remeda"
|
||||
import path from "path"
|
||||
import os from "os"
|
||||
import { Config } from "../../config"
|
||||
import { Config } from "@/config/config"
|
||||
import { Global } from "@opencode-ai/core/global"
|
||||
import { Plugin } from "../../plugin"
|
||||
import { Instance } from "../../project/instance"
|
||||
import type { Hooks } from "@opencode-ai/plugin"
|
||||
import { Process } from "../../util"
|
||||
import { Process } from "@/util/process"
|
||||
import { text } from "node:stream/consumers"
|
||||
import { Effect } from "effect"
|
||||
|
||||
|
||||
@@ -6,13 +6,13 @@ import { cmd } from "./cmd"
|
||||
import { Flag } from "@opencode-ai/core/flag/flag"
|
||||
import { bootstrap } from "../bootstrap"
|
||||
import { EOL } from "os"
|
||||
import { Filesystem } from "../../util"
|
||||
import { Filesystem } from "@/util/filesystem"
|
||||
import { createOpencodeClient, type OpencodeClient, type ToolPart } from "@opencode-ai/sdk/v2"
|
||||
import { Server } from "../../server/server"
|
||||
import { Provider } from "../../provider"
|
||||
import { Provider } from "@/provider/provider"
|
||||
import { Agent } from "../../agent/agent"
|
||||
import { Permission } from "../../permission"
|
||||
import { Tool } from "../../tool"
|
||||
import { Tool } from "@/tool/tool"
|
||||
import { GlobTool } from "../../tool/glob"
|
||||
import { GrepTool } from "../../tool/grep"
|
||||
import { ReadTool } from "../../tool/read"
|
||||
@@ -25,7 +25,7 @@ import { TaskTool } from "../../tool/task"
|
||||
import { SkillTool } from "../../tool/skill"
|
||||
import { BashTool } from "../../tool/bash"
|
||||
import { TodoWriteTool } from "../../tool/todo"
|
||||
import { Locale } from "../../util"
|
||||
import { Locale } from "@/util/locale"
|
||||
import { AppRuntime } from "@/effect/app-runtime"
|
||||
|
||||
type ToolProps<T> = {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import type { Argv } from "yargs"
|
||||
import { cmd } from "./cmd"
|
||||
import { Session } from "../../session"
|
||||
import { Session } from "@/session/session"
|
||||
import { SessionID } from "../../session/schema"
|
||||
import { bootstrap } from "../bootstrap"
|
||||
import { UI } from "../ui"
|
||||
import { Locale } from "../../util"
|
||||
import { Locale } from "@/util/locale"
|
||||
import { Flag } from "@opencode-ai/core/flag/flag"
|
||||
import { Filesystem } from "../../util"
|
||||
import { Process } from "../../util"
|
||||
import { Filesystem } from "@/util/filesystem"
|
||||
import { Process } from "@/util/process"
|
||||
import { EOL } from "os"
|
||||
import path from "path"
|
||||
import { which } from "../../util/which"
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import type { Argv } from "yargs"
|
||||
import { cmd } from "./cmd"
|
||||
import { Session } from "../../session"
|
||||
import { Session } from "@/session/session"
|
||||
import { bootstrap } from "../bootstrap"
|
||||
import { Database } from "../../storage"
|
||||
import { Database } from "@/storage/db"
|
||||
import { SessionTable } from "../../session/session.sql"
|
||||
import { Project } from "../../project"
|
||||
import { Project } from "@/project/project"
|
||||
import { Instance } from "../../project/instance"
|
||||
import { AppRuntime } from "@/effect/app-runtime"
|
||||
|
||||
|
||||
@@ -29,7 +29,8 @@ import { SDKProvider, useSDK } from "@tui/context/sdk"
|
||||
import { StartupLoading } from "@tui/component/startup-loading"
|
||||
import { SyncProvider, useSync } from "@tui/context/sync"
|
||||
import { LocalProvider, useLocal } from "@tui/context/local"
|
||||
import { DialogModel, useConnected } from "@tui/component/dialog-model"
|
||||
import { DialogModel } from "@tui/component/dialog-model"
|
||||
import { useConnected } from "@tui/component/use-connected"
|
||||
import { DialogMcp } from "@tui/component/dialog-mcp"
|
||||
import { DialogStatus } from "@tui/component/dialog-status"
|
||||
import { DialogThemeList } from "@tui/component/dialog-theme-list"
|
||||
@@ -49,16 +50,18 @@ import { DialogAlert } from "./ui/dialog-alert"
|
||||
import { DialogConfirm } from "./ui/dialog-confirm"
|
||||
import { ToastProvider, useToast } from "./ui/toast"
|
||||
import { ExitProvider, useExit } from "./context/exit"
|
||||
import { Session as SessionApi } from "@/session"
|
||||
import { Session as SessionApi } from "@/session/session"
|
||||
import { TuiEvent } from "./event"
|
||||
import { KVProvider, useKV } from "./context/kv"
|
||||
import { Provider } from "@/provider"
|
||||
import { Provider } from "@/provider/provider"
|
||||
import { ArgsProvider, useArgs, type Args } from "./context/args"
|
||||
import open from "open"
|
||||
import { PromptRefProvider, usePromptRef } from "./context/prompt"
|
||||
import { TuiConfigProvider, useTuiConfig } from "./context/tui-config"
|
||||
import { TuiConfig } from "@/cli/cmd/tui/config/tui"
|
||||
import { createTuiApi, TuiPluginRuntime, type RouteMap } from "./plugin"
|
||||
import { createTuiApi } from "@/cli/cmd/tui/plugin/api"
|
||||
import { TuiPluginRuntime } from "@/cli/cmd/tui/plugin/runtime"
|
||||
import type { RouteMap } from "@/cli/cmd/tui/plugin/api"
|
||||
import { FormatError, FormatUnknownError } from "@/cli/error"
|
||||
|
||||
import type { EventSource } from "./context/sdk"
|
||||
@@ -724,6 +727,27 @@ function App(props: { onSnapshot?: () => Promise<string[]> }) {
|
||||
dialog.clear()
|
||||
},
|
||||
},
|
||||
{
|
||||
title: kv.get("file_context_enabled", true) ? "Disable file context" : "Enable file context",
|
||||
value: "app.toggle.file_context",
|
||||
category: "System",
|
||||
onSelect: (dialog) => {
|
||||
kv.set("file_context_enabled", !kv.get("file_context_enabled", true))
|
||||
dialog.clear()
|
||||
},
|
||||
},
|
||||
{
|
||||
title: kv.get("session_directory_filter_enabled", true)
|
||||
? "Disable session directory filtering"
|
||||
: "Enable session directory filtering",
|
||||
value: "app.toggle.session_directory_filter",
|
||||
category: "System",
|
||||
onSelect: async (dialog) => {
|
||||
kv.set("session_directory_filter_enabled", !kv.get("session_directory_filter_enabled", true))
|
||||
await sync.session.refresh()
|
||||
dialog.clear()
|
||||
},
|
||||
},
|
||||
{
|
||||
title: kv.get("diff_wrap_mode", "word") === "word" ? "Disable diff wrapping" : "Enable diff wrapping",
|
||||
value: "app.toggle.diffwrap",
|
||||
|
||||
@@ -77,6 +77,8 @@ export function DialogGoUpsell(props: DialogGoUpsellProps) {
|
||||
return
|
||||
}
|
||||
if (evt.name === "return") {
|
||||
evt.preventDefault()
|
||||
evt.stopPropagation()
|
||||
if (selected() === "subscribe") subscribe(props, dialog)
|
||||
else dismiss(props, dialog)
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { useSync } from "@tui/context/sync"
|
||||
import { map, pipe, entries, sortBy } from "remeda"
|
||||
import { DialogSelect, type DialogSelectRef, type DialogSelectOption } from "@tui/ui/dialog-select"
|
||||
import { useTheme } from "../context/theme"
|
||||
import { Keybind } from "@/util"
|
||||
import { Keybind } from "@/util/keybind"
|
||||
import { TextAttributes } from "@opentui/core"
|
||||
import { useSDK } from "@tui/context/sdk"
|
||||
|
||||
|
||||
@@ -8,13 +8,7 @@ import { createDialogProviderOptions, DialogProvider } from "./dialog-provider"
|
||||
import { DialogVariant } from "./dialog-variant"
|
||||
import { useKeybind } from "../context/keybind"
|
||||
import * as fuzzysort from "fuzzysort"
|
||||
|
||||
export function useConnected() {
|
||||
const sync = useSync()
|
||||
return createMemo(() =>
|
||||
sync.data.provider.some((x) => x.id !== "opencode" || Object.values(x.models).some((y) => y.cost?.input !== 0)),
|
||||
)
|
||||
}
|
||||
import { useConnected } from "./use-connected"
|
||||
|
||||
export function DialogModel(props: { providerID?: string }) {
|
||||
const local = useLocal()
|
||||
|
||||
@@ -14,6 +14,7 @@ import { useKeyboard } from "@opentui/solid"
|
||||
import * as Clipboard from "@tui/util/clipboard"
|
||||
import { useToast } from "../ui/toast"
|
||||
import { isConsoleManagedProvider } from "@tui/util/provider-origin"
|
||||
import { useConnected } from "./use-connected"
|
||||
|
||||
const PROVIDER_PRIORITY: Record<string, number> = {
|
||||
opencode: 0,
|
||||
@@ -30,6 +31,7 @@ export function createDialogProviderOptions() {
|
||||
const sdk = useSDK()
|
||||
const toast = useToast()
|
||||
const { theme } = useTheme()
|
||||
const onboarded = useConnected()
|
||||
const options = createMemo(() => {
|
||||
return pipe(
|
||||
sync.data.provider_next.all,
|
||||
@@ -49,7 +51,7 @@ export function createDialogProviderOptions() {
|
||||
}[provider.id],
|
||||
footer: consoleManaged ? sync.data.console_state.activeOrgName : undefined,
|
||||
category: provider.id in PROVIDER_PRIORITY ? "Popular" : "Other",
|
||||
gutter: connected ? <text fg={theme.success}>✓</text> : undefined,
|
||||
gutter: connected && onboarded() ? <text fg={theme.success}>✓</text> : undefined,
|
||||
async onSelect() {
|
||||
if (consoleManaged) return
|
||||
|
||||
|
||||
@@ -42,6 +42,8 @@ export function DialogSessionDeleteFailed(props: {
|
||||
|
||||
useKeyboard((evt) => {
|
||||
if (evt.name === "return") {
|
||||
evt.preventDefault()
|
||||
evt.stopPropagation()
|
||||
void confirm()
|
||||
}
|
||||
if (evt.name === "left" || evt.name === "up") {
|
||||
|
||||
@@ -3,14 +3,14 @@ import { DialogSelect } from "@tui/ui/dialog-select"
|
||||
import { useRoute } from "@tui/context/route"
|
||||
import { useSync } from "@tui/context/sync"
|
||||
import { createMemo, createResource, createSignal, onMount } from "solid-js"
|
||||
import { Locale } from "@/util"
|
||||
import { Locale } from "@/util/locale"
|
||||
import { useProject } from "@tui/context/project"
|
||||
import { useKeybind } from "../context/keybind"
|
||||
import { useTheme } from "../context/theme"
|
||||
import { useSDK } from "../context/sdk"
|
||||
import { Flag } from "@opencode-ai/core/flag/flag"
|
||||
import { DialogSessionRename } from "./dialog-session-rename"
|
||||
import { Keybind } from "@/util"
|
||||
import { Keybind } from "@/util/keybind"
|
||||
import { createDebouncedSignal } from "../util/signal"
|
||||
import { useToast } from "../ui/toast"
|
||||
import { DialogWorkspaceCreate, openWorkspaceSession, restoreWorkspaceSession } from "./dialog-workspace-create"
|
||||
@@ -32,11 +32,14 @@ export function DialogSessionList() {
|
||||
const [toDelete, setToDelete] = createSignal<string>()
|
||||
const [search, setSearch] = createDebouncedSignal("", 150)
|
||||
|
||||
const [searchResults, { refetch }] = createResource(search, async (query) => {
|
||||
if (!query) return undefined
|
||||
const result = await sdk.client.session.list({ search: query, limit: 30 })
|
||||
return result.data ?? []
|
||||
})
|
||||
const [searchResults, { refetch }] = createResource(
|
||||
() => ({ query: search(), filter: sync.session.query() }),
|
||||
async (input) => {
|
||||
if (!input.query) return undefined
|
||||
const result = await sdk.client.session.list({ search: input.query, limit: 30, ...input.filter })
|
||||
return result.data ?? []
|
||||
},
|
||||
)
|
||||
|
||||
const currentSessionID = createMemo(() => (route.data.type === "session" ? route.data.sessionID : undefined))
|
||||
const sessions = createMemo(() => searchResults() ?? sync.data.session)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useDialog } from "@tui/ui/dialog"
|
||||
import { DialogSelect } from "@tui/ui/dialog-select"
|
||||
import { createMemo, createSignal } from "solid-js"
|
||||
import { Locale } from "@/util"
|
||||
import { Locale } from "@/util/locale"
|
||||
import { useTheme } from "../context/theme"
|
||||
import { useKeybind } from "../context/keybind"
|
||||
import { usePromptStash, type StashEntry } from "./prompt/stash"
|
||||
|
||||
@@ -6,8 +6,7 @@ import { useSync } from "@tui/context/sync"
|
||||
import { useProject } from "@tui/context/project"
|
||||
import { createMemo, createSignal, onMount } from "solid-js"
|
||||
import { setTimeout as sleep } from "node:timers/promises"
|
||||
import { errorData, errorMessage } from "@/util/error"
|
||||
import * as Log from "@opencode-ai/core/util/log"
|
||||
import { errorMessage } from "@/util/error"
|
||||
import { useSDK } from "../context/sdk"
|
||||
import { useToast } from "../ui/toast"
|
||||
|
||||
@@ -17,8 +16,6 @@ type Adaptor = {
|
||||
description: string
|
||||
}
|
||||
|
||||
const log = Log.Default.clone().tag("service", "tui-workspace")
|
||||
|
||||
function scoped(sdk: ReturnType<typeof useSDK>, sync: ReturnType<typeof useSync>, workspaceID: string) {
|
||||
return createOpencodeClient({
|
||||
baseUrl: sdk.url,
|
||||
@@ -37,18 +34,9 @@ export async function openWorkspaceSession(input: {
|
||||
workspaceID: string
|
||||
}) {
|
||||
const client = scoped(input.sdk, input.sync, input.workspaceID)
|
||||
log.info("workspace session create requested", {
|
||||
workspaceID: input.workspaceID,
|
||||
})
|
||||
|
||||
while (true) {
|
||||
const result = await client.session.create({ workspace: input.workspaceID }).catch((err) => {
|
||||
log.error("workspace session create request failed", {
|
||||
workspaceID: input.workspaceID,
|
||||
error: errorData(err),
|
||||
})
|
||||
return undefined
|
||||
})
|
||||
const result = await client.session.create({ workspace: input.workspaceID }).catch(() => undefined)
|
||||
if (!result) {
|
||||
input.toast.show({
|
||||
message: "Failed to create workspace session",
|
||||
@@ -56,24 +44,11 @@ export async function openWorkspaceSession(input: {
|
||||
})
|
||||
return
|
||||
}
|
||||
log.info("workspace session create response", {
|
||||
workspaceID: input.workspaceID,
|
||||
status: result.response?.status,
|
||||
sessionID: result.data?.id,
|
||||
})
|
||||
if (result.response?.status && result.response.status >= 500 && result.response.status < 600) {
|
||||
log.warn("workspace session create retrying after server error", {
|
||||
workspaceID: input.workspaceID,
|
||||
status: result.response.status,
|
||||
})
|
||||
await sleep(1000)
|
||||
continue
|
||||
}
|
||||
if (!result.data) {
|
||||
log.error("workspace session create returned no data", {
|
||||
workspaceID: input.workspaceID,
|
||||
status: result.response?.status,
|
||||
})
|
||||
input.toast.show({
|
||||
message: "Failed to create workspace session",
|
||||
variant: "error",
|
||||
@@ -85,10 +60,6 @@ export async function openWorkspaceSession(input: {
|
||||
type: "session",
|
||||
sessionID: result.data.id,
|
||||
})
|
||||
log.info("workspace session create complete", {
|
||||
workspaceID: input.workspaceID,
|
||||
sessionID: result.data.id,
|
||||
})
|
||||
input.dialog.clear()
|
||||
return
|
||||
}
|
||||
@@ -104,27 +75,10 @@ export async function restoreWorkspaceSession(input: {
|
||||
sessionID: string
|
||||
done?: () => void
|
||||
}) {
|
||||
log.info("session restore requested", {
|
||||
workspaceID: input.workspaceID,
|
||||
sessionID: input.sessionID,
|
||||
})
|
||||
const result = await input.sdk.client.experimental.workspace
|
||||
.sessionRestore({ id: input.workspaceID, sessionID: input.sessionID })
|
||||
.catch((err) => {
|
||||
log.error("session restore request failed", {
|
||||
workspaceID: input.workspaceID,
|
||||
sessionID: input.sessionID,
|
||||
error: errorData(err),
|
||||
})
|
||||
return undefined
|
||||
})
|
||||
.catch(() => undefined)
|
||||
if (!result?.data) {
|
||||
log.error("session restore failed", {
|
||||
workspaceID: input.workspaceID,
|
||||
sessionID: input.sessionID,
|
||||
status: result?.response?.status,
|
||||
error: result?.error ? errorData(result.error) : undefined,
|
||||
})
|
||||
input.toast.show({
|
||||
message: `Failed to restore session: ${errorMessage(result?.error ?? "no response")}`,
|
||||
variant: "error",
|
||||
@@ -132,33 +86,11 @@ export async function restoreWorkspaceSession(input: {
|
||||
return
|
||||
}
|
||||
|
||||
log.info("session restore response", {
|
||||
workspaceID: input.workspaceID,
|
||||
sessionID: input.sessionID,
|
||||
status: result.response?.status,
|
||||
total: result.data.total,
|
||||
})
|
||||
|
||||
input.project.workspace.set(input.workspaceID)
|
||||
|
||||
try {
|
||||
await input.sync.bootstrap({ fatal: false })
|
||||
} catch (e) {}
|
||||
await input.sync.bootstrap({ fatal: false }).catch(() => undefined)
|
||||
|
||||
await Promise.all([input.project.workspace.sync(), input.sync.session.sync(input.sessionID)]).catch((err) => {
|
||||
log.error("session restore refresh failed", {
|
||||
workspaceID: input.workspaceID,
|
||||
sessionID: input.sessionID,
|
||||
error: errorData(err),
|
||||
})
|
||||
throw err
|
||||
})
|
||||
|
||||
log.info("session restore complete", {
|
||||
workspaceID: input.workspaceID,
|
||||
sessionID: input.sessionID,
|
||||
total: result.data.total,
|
||||
})
|
||||
await Promise.all([input.project.workspace.sync(), input.sync.session.sync(input.sessionID)])
|
||||
|
||||
input.toast.show({
|
||||
message: "Session restored into the new workspace",
|
||||
@@ -230,47 +162,26 @@ export function DialogWorkspaceCreate(props: { onSelect: (workspaceID: string) =
|
||||
const create = async (type: string) => {
|
||||
if (creating()) return
|
||||
setCreating(type)
|
||||
log.info("workspace create requested", {
|
||||
type,
|
||||
})
|
||||
|
||||
const result = await sdk.client.experimental.workspace.create({ type, branch: null }).catch((err) => {
|
||||
const result = await sdk.client.experimental.workspace.create({ type, branch: null }).catch(() => {
|
||||
toast.show({
|
||||
message: "Creating workspace failed",
|
||||
variant: "error",
|
||||
})
|
||||
log.error("workspace create request failed", {
|
||||
type,
|
||||
error: errorData(err),
|
||||
})
|
||||
return undefined
|
||||
})
|
||||
|
||||
const workspace = result?.data
|
||||
if (!workspace) {
|
||||
setCreating(undefined)
|
||||
log.error("workspace create failed", {
|
||||
type,
|
||||
status: result?.response.status,
|
||||
error: result?.error ? errorData(result.error) : undefined,
|
||||
})
|
||||
toast.show({
|
||||
message: `Failed to create workspace: ${errorMessage(result?.error ?? "no response")}`,
|
||||
variant: "error",
|
||||
})
|
||||
return
|
||||
}
|
||||
log.info("workspace create response", {
|
||||
type,
|
||||
workspaceID: workspace.id,
|
||||
status: result.response?.status,
|
||||
})
|
||||
|
||||
await project.workspace.sync()
|
||||
log.info("workspace create synced", {
|
||||
type,
|
||||
workspaceID: workspace.id,
|
||||
})
|
||||
await props.onSelect(workspace.id)
|
||||
setCreating(undefined)
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import { useTheme, selectedForeground } from "@tui/context/theme"
|
||||
import { SplitBorder } from "@tui/component/border"
|
||||
import { useCommandDialog } from "@tui/component/dialog-command"
|
||||
import { useTerminalDimensions } from "@opentui/solid"
|
||||
import { Locale } from "@/util"
|
||||
import { Locale } from "@/util/locale"
|
||||
import type { PromptInfo } from "./history"
|
||||
import { useFrecency } from "./frecency"
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import path from "path"
|
||||
import { Global } from "@opencode-ai/core/global"
|
||||
import { Filesystem } from "@/util"
|
||||
import { Filesystem } from "@/util/filesystem"
|
||||
import { onMount } from "solid-js"
|
||||
import { createStore } from "solid-js/store"
|
||||
import { createSimpleContext } from "../../context/helper"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import path from "path"
|
||||
import { Global } from "@opencode-ai/core/global"
|
||||
import { Filesystem } from "@/util"
|
||||
import { Filesystem } from "@/util/filesystem"
|
||||
import { onMount } from "solid-js"
|
||||
import { createStore, produce, unwrap } from "solid-js/store"
|
||||
import { createSimpleContext } from "../../context/helper"
|
||||
|
||||
@@ -3,7 +3,7 @@ import { createEffect, createMemo, onMount, createSignal, onCleanup, on, Show, S
|
||||
import "opentui-spinner/solid"
|
||||
import path from "path"
|
||||
import { fileURLToPath } from "url"
|
||||
import { Filesystem } from "@/util"
|
||||
import { Filesystem } from "@/util/filesystem"
|
||||
import { useLocal } from "@tui/context/local"
|
||||
import { tint, useTheme } from "@tui/context/theme"
|
||||
import { EmptyBorder, SplitBorder } from "@tui/component/border"
|
||||
@@ -29,7 +29,7 @@ import * as Clipboard from "../../util/clipboard"
|
||||
import type { AssistantMessage, FilePart, UserMessage } from "@opencode-ai/sdk/v2"
|
||||
import { TuiEvent } from "../../event"
|
||||
import { iife } from "@/util/iife"
|
||||
import { Locale } from "@/util"
|
||||
import { Locale } from "@/util/locale"
|
||||
import { formatDuration } from "@/util/format"
|
||||
import { createColors, createFrames } from "../../ui/spinner.ts"
|
||||
import { useDialog } from "@tui/ui/dialog"
|
||||
@@ -112,9 +112,10 @@ export function Prompt(props: PromptProps) {
|
||||
const animationsEnabled = createMemo(() => kv.get("animations_enabled", true))
|
||||
const list = createMemo(() => props.placeholders?.normal ?? [])
|
||||
const shell = createMemo(() => props.placeholders?.shell ?? [])
|
||||
const editorPath = createMemo(() => editor.selection()?.filePath)
|
||||
const fileContextEnabled = createMemo(() => kv.get("file_context_enabled", true))
|
||||
const editorPath = createMemo(() => (fileContextEnabled() ? editor.selection()?.filePath : undefined))
|
||||
const editorSelectionLabel = createMemo(() => {
|
||||
const selection = editor.selection()?.selection
|
||||
const selection = fileContextEnabled() ? editor.selection()?.selection : undefined
|
||||
if (!selection) return
|
||||
if (selection.start.line === selection.end.line && selection.start.character === selection.end.character) return
|
||||
if (selection.start.line === selection.end.line) return `#${selection.start.line}`
|
||||
@@ -746,7 +747,7 @@ export function Prompt(props: PromptProps) {
|
||||
// Capture mode before it gets reset
|
||||
const currentMode = store.mode
|
||||
const variant = local.model.variant.current()
|
||||
const editorSelection = editor.selection()
|
||||
const editorSelection = fileContextEnabled() ? editor.selection() : undefined
|
||||
const editorParts = editorSelection
|
||||
? [
|
||||
{
|
||||
@@ -755,15 +756,25 @@ export function Prompt(props: PromptProps) {
|
||||
text: (() => {
|
||||
const start = editorSelection.selection.start
|
||||
const end = editorSelection.selection.end
|
||||
|
||||
let text = ""
|
||||
if (start.line === end.line && start.character === end.character) {
|
||||
return `Note: The user opened the file "${editorSelection.filePath}".`
|
||||
text = `Note: The user opened the file "${editorSelection.filePath}".`
|
||||
} else if (start.line === end.line) {
|
||||
text = `Note: The user selected line ${start.line + 1} from "${editorSelection.filePath}". \`\`\`${editorSelection.text}\`\`\`\n\n`
|
||||
} else {
|
||||
text = `Note: The user selected lines ${start.line + 1} to ${end.line + 1} from "${editorSelection.filePath}". \`\`\`${editorSelection.text}\`\`\`\n\n`
|
||||
}
|
||||
if (start.line === end.line) {
|
||||
return `Note: The user selected line ${start.line} from "${editorSelection.filePath}": ${editorSelection.text}`
|
||||
}
|
||||
return `Note: The user selected lines ${start.line} to ${end.line} from "${editorSelection.filePath}": ${editorSelection.text}`
|
||||
|
||||
return `<system-reminder>${text} This may or may not be relevant to the current task.</system-reminder>\n`
|
||||
})(),
|
||||
synthetic: true,
|
||||
metadata: {
|
||||
kind: "editor_context",
|
||||
source: editorSelection.source ?? "editor",
|
||||
filePath: editorSelection.filePath,
|
||||
selection: editorSelection.selection,
|
||||
},
|
||||
},
|
||||
]
|
||||
: []
|
||||
@@ -829,6 +840,7 @@ export function Prompt(props: PromptProps) {
|
||||
],
|
||||
})
|
||||
.catch(() => {})
|
||||
editor.clearSelection()
|
||||
}
|
||||
history.append({
|
||||
...store.prompt,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user