mirror of
https://github.com/anomalyco/opencode.git
synced 2026-08-06 17:19:49 -04:00
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1c34d87a16 | |||
| 204f6f3d03 | |||
| 1db70ac06a | |||
| a36db14008 | |||
| 596563f8c1 | |||
| 97b3e39d4c | |||
| 4cfcc422f4 | |||
| 08a4916744 | |||
| 0833265440 | |||
| 512ddf3963 | |||
| 89109da9c2 | |||
| a4509af4ac | |||
| 7a9e1fcb40 | |||
| f148d38b49 | |||
| 0ccae0cea6 | |||
| f890f45df3 | |||
| 2c12ee5a20 | |||
| bcf8c33b11 | |||
| 8aba574555 | |||
| f51a9c4fce | |||
| 2d99b33466 | |||
| 14dc940aac | |||
| cb3337f01e | |||
| b2121c963f |
@@ -33,9 +33,10 @@ permissions:
|
|||||||
jobs:
|
jobs:
|
||||||
version:
|
version:
|
||||||
runs-on: blacksmith-4vcpu-ubuntu-2404
|
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||||
|
timeout-minutes: 30
|
||||||
if: github.repository == 'anomalyco/opencode'
|
if: github.repository == 'anomalyco/opencode'
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
@@ -63,7 +64,7 @@ jobs:
|
|||||||
runs-on: blacksmith-4vcpu-ubuntu-2404
|
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||||
if: github.repository == 'anomalyco/opencode'
|
if: github.repository == 'anomalyco/opencode'
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-tags: true
|
fetch-tags: true
|
||||||
|
|
||||||
@@ -107,7 +108,7 @@ jobs:
|
|||||||
target: aarch64-unknown-linux-gnu
|
target: aarch64-unknown-linux-gnu
|
||||||
runs-on: ${{ matrix.settings.host }}
|
runs-on: ${{ matrix.settings.host }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-tags: true
|
fetch-tags: true
|
||||||
|
|
||||||
@@ -208,8 +209,9 @@ jobs:
|
|||||||
- build-cli
|
- build-cli
|
||||||
- build-tauri
|
- build-tauri
|
||||||
runs-on: blacksmith-4vcpu-ubuntu-2404
|
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||||
|
timeout-minutes: 60
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- uses: ./.github/actions/setup-bun
|
- uses: ./.github/actions/setup-bun
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -1 +1,2 @@
|
|||||||
sst-env.d.ts
|
sst-env.d.ts
|
||||||
|
desktop/src/bindings.ts
|
||||||
|
|||||||
@@ -298,8 +298,8 @@
|
|||||||
"@opencode-ai/sdk": "workspace:*",
|
"@opencode-ai/sdk": "workspace:*",
|
||||||
"@opencode-ai/util": "workspace:*",
|
"@opencode-ai/util": "workspace:*",
|
||||||
"@openrouter/ai-sdk-provider": "1.5.4",
|
"@openrouter/ai-sdk-provider": "1.5.4",
|
||||||
"@opentui/core": "0.1.75",
|
"@opentui/core": "0.1.77",
|
||||||
"@opentui/solid": "0.1.75",
|
"@opentui/solid": "0.1.77",
|
||||||
"@parcel/watcher": "2.5.1",
|
"@parcel/watcher": "2.5.1",
|
||||||
"@pierre/diffs": "catalog:",
|
"@pierre/diffs": "catalog:",
|
||||||
"@solid-primitives/event-bus": "1.1.2",
|
"@solid-primitives/event-bus": "1.1.2",
|
||||||
@@ -1227,21 +1227,21 @@
|
|||||||
|
|
||||||
"@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="],
|
"@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="],
|
||||||
|
|
||||||
"@opentui/core": ["@opentui/core@0.1.75", "", { "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.75", "@opentui/core-darwin-x64": "0.1.75", "@opentui/core-linux-arm64": "0.1.75", "@opentui/core-linux-x64": "0.1.75", "@opentui/core-win32-arm64": "0.1.75", "@opentui/core-win32-x64": "0.1.75", "bun-webgpu": "0.1.4", "planck": "^1.4.2", "three": "0.177.0" }, "peerDependencies": { "web-tree-sitter": "0.25.10" } }, "sha512-8ARRZxSG+BXkJmEVtM2DQ4se7DAF1ZCKD07d+AklgTr2mxCzmdxxPbOwRzboSQ6FM7qGuTVPVbV4O2W9DpUmoA=="],
|
"@opentui/core": ["@opentui/core@0.1.77", "", { "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.77", "@opentui/core-darwin-x64": "0.1.77", "@opentui/core-linux-arm64": "0.1.77", "@opentui/core-linux-x64": "0.1.77", "@opentui/core-win32-arm64": "0.1.77", "@opentui/core-win32-x64": "0.1.77", "bun-webgpu": "0.1.4", "planck": "^1.4.2", "three": "0.177.0" }, "peerDependencies": { "web-tree-sitter": "0.25.10" } }, "sha512-lE3kabm6jdqK3AuBq+O0zZrXdxt6ulmibTc57sf+AsPny6cmwYHnWI4wD6hcreFiYoQVNVvdiJchVgPtowMlEg=="],
|
||||||
|
|
||||||
"@opentui/core-darwin-arm64": ["@opentui/core-darwin-arm64@0.1.75", "", { "os": "darwin", "cpu": "arm64" }, "sha512-gGaGZjkFpqcXJk6321JzhRl66pM2VxBlI470L8W4DQUW4S6iDT1R9L7awSzGB4Cn9toUl7DTV8BemaXZYXV4SA=="],
|
"@opentui/core-darwin-arm64": ["@opentui/core-darwin-arm64@0.1.77", "", { "os": "darwin", "cpu": "arm64" }, "sha512-SNqmygCMEsPCW7xWjzCZ5caBf36xaprwVdAnFijGDOuIzLA4iaDa6um8cj3TJh7awenN3NTRsuRc7OuH42UH+g=="],
|
||||||
|
|
||||||
"@opentui/core-darwin-x64": ["@opentui/core-darwin-x64@0.1.75", "", { "os": "darwin", "cpu": "x64" }, "sha512-tPlvqQI0whZ76amHydpJs5kN+QeWAIcFbI8RAtlAo9baj2EbxTDC+JGwgb9Fnt0/YQx831humbtaNDhV2Jt1bw=="],
|
"@opentui/core-darwin-x64": ["@opentui/core-darwin-x64@0.1.77", "", { "os": "darwin", "cpu": "x64" }, "sha512-/8fsa03swEHTQt/9NrGm98kemlU+VuTURI/OFZiH53vPDRrOYIYoa4Jyga/H7ZMcG+iFhkq97zIe+0Kw95LGmA=="],
|
||||||
|
|
||||||
"@opentui/core-linux-arm64": ["@opentui/core-linux-arm64@0.1.75", "", { "os": "linux", "cpu": "arm64" }, "sha512-nVxIQ4Hqf84uBergDpWiVzU6pzpjy6tqBHRQpySxZ2flkJ/U6/aMEizVrQ1jcgIdxZtvqWDETZhzxhG0yDx+cw=="],
|
"@opentui/core-linux-arm64": ["@opentui/core-linux-arm64@0.1.77", "", { "os": "linux", "cpu": "arm64" }, "sha512-QfUXZJPc69OvqoMu+AlLgjqXrwu4IeqcBuUWYMuH8nPTeLsVUc3CBbXdV2lv9UDxWzxzrxdS4ALPaxvmEv9lsQ=="],
|
||||||
|
|
||||||
"@opentui/core-linux-x64": ["@opentui/core-linux-x64@0.1.75", "", { "os": "linux", "cpu": "x64" }, "sha512-1CnApef4kxA+ORyLfbuCLgZfEjp4wr3HjFnt7FAfOb73kIZH82cb7JYixeqRyy9eOcKfKqxLmBYy3o8IDkc4Rg=="],
|
"@opentui/core-linux-x64": ["@opentui/core-linux-x64@0.1.77", "", { "os": "linux", "cpu": "x64" }, "sha512-Kmfx0yUKnPj67AoXYIgL7qQo0QVsUG5Iw8aRtv6XFzXqa5SzBPhaKkKZ9yHPjOmTalZquUs+9zcCRNKpYYuL7A=="],
|
||||||
|
|
||||||
"@opentui/core-win32-arm64": ["@opentui/core-win32-arm64@0.1.75", "", { "os": "win32", "cpu": "arm64" }, "sha512-j0UB95nmkYGNzmOrs6GqaddO1S90R0YC6IhbKnbKBdjchFPNVLz9JpexAs6MBDXPZwdKAywMxtwG2h3aTJtxng=="],
|
"@opentui/core-win32-arm64": ["@opentui/core-win32-arm64@0.1.77", "", { "os": "win32", "cpu": "arm64" }, "sha512-HGTscPXc7gdd23Nh1DbzUNjog1I+5IZp95XPtLftGTpjrWs60VcetXcyJqK2rQcXNxewJK5yDyaa5QyMjfEhCQ=="],
|
||||||
|
|
||||||
"@opentui/core-win32-x64": ["@opentui/core-win32-x64@0.1.75", "", { "os": "win32", "cpu": "x64" }, "sha512-ESpVZVGewe3JkB2TwrG3VRbkxT909iPdtvgNT7xTCIYH2VB4jqZomJfvERPTE0tvqAZJm19mHECzJFI8asSJgQ=="],
|
"@opentui/core-win32-x64": ["@opentui/core-win32-x64@0.1.77", "", { "os": "win32", "cpu": "x64" }, "sha512-c7GijsbvVgnlzd2murIbwuwrGbcv76KdUw6WlVv7a0vex50z6xJCpv1keGzpe0QfxrZ/6fFEFX7JnwGLno0wjA=="],
|
||||||
|
|
||||||
"@opentui/solid": ["@opentui/solid@0.1.75", "", { "dependencies": { "@babel/core": "7.28.0", "@babel/preset-typescript": "7.27.1", "@opentui/core": "0.1.75", "babel-plugin-module-resolver": "5.0.2", "babel-preset-solid": "1.9.9", "s-js": "^0.4.9" }, "peerDependencies": { "solid-js": "1.9.9" } }, "sha512-WjKsZIfrm29znfRlcD9w3uUn/+uvoy2MmeoDwTvg1YOa0OjCTCmjZ43L9imp0m9S4HmVU8ma6o2bR4COzcyDdg=="],
|
"@opentui/solid": ["@opentui/solid@0.1.77", "", { "dependencies": { "@babel/core": "7.28.0", "@babel/preset-typescript": "7.27.1", "@opentui/core": "0.1.77", "babel-plugin-module-resolver": "5.0.2", "babel-preset-solid": "1.9.9", "s-js": "^0.4.9" }, "peerDependencies": { "solid-js": "1.9.9" } }, "sha512-JY+hUbXVV+XCk6bC8dvcwawWCEmC3Gid6GDs23AJWBgHZ3TU2kRKrgwTdltm45DOq2cZXrYCt690/yE8bP+Gxg=="],
|
||||||
|
|
||||||
"@oslojs/asn1": ["@oslojs/asn1@1.0.0", "", { "dependencies": { "@oslojs/binary": "1.0.0" } }, "sha512-zw/wn0sj0j0QKbIXfIlnEcTviaCzYOY3V5rAyjR6YtOByFtJiT574+8p9Wlach0lZH9fddD4yb9laEAIl4vXQA=="],
|
"@oslojs/asn1": ["@oslojs/asn1@1.0.0", "", { "dependencies": { "@oslojs/binary": "1.0.0" } }, "sha512-zw/wn0sj0j0QKbIXfIlnEcTviaCzYOY3V5rAyjR6YtOByFtJiT574+8p9Wlach0lZH9fddD4yb9laEAIl4vXQA=="],
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"nodeModules": {
|
"nodeModules": {
|
||||||
"x86_64-linux": "sha256-06Otz3loT4vn0578VDxUqVudtzQvV7oM3EIzjZnsejo=",
|
"x86_64-linux": "sha256-4I0lpBnbAi7IZMURTMLysjrqdsNvXJf8802NrJnpdks=",
|
||||||
"aarch64-linux": "sha256-88Qai5RkSenCZkakOg52b6xU2ok+h/Ns4/5L3+55sFY=",
|
"aarch64-linux": "sha256-WOGKsPlcQVSbL8TDr1JYO/2ucPTV2Hy0TXJKWv8EoVw=",
|
||||||
"aarch64-darwin": "sha256-x8dgCF0CJBWi2dZLDHMGdlTqys1X755ok0PM6x0HAGo=",
|
"aarch64-darwin": "sha256-LuvjwGm1QsHoLxuvSSp4VsDIv02Z/rTONsU32arQMuw=",
|
||||||
"x86_64-darwin": "sha256-FkLDqorfIfOw+tB7SW5vgyhOIoI0IV9lqPW1iEmvUiI="
|
"x86_64-darwin": "sha256-AbglfgCWj/r+wHfle+e+D3b/xPcwwg4IK7j5iwn9nzw="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,11 +3,12 @@ import type { JSX } from "solid-js"
|
|||||||
import { createSortable } from "@thisbeyond/solid-dnd"
|
import { createSortable } from "@thisbeyond/solid-dnd"
|
||||||
import { FileIcon } from "@opencode-ai/ui/file-icon"
|
import { FileIcon } from "@opencode-ai/ui/file-icon"
|
||||||
import { IconButton } from "@opencode-ai/ui/icon-button"
|
import { IconButton } from "@opencode-ai/ui/icon-button"
|
||||||
import { Tooltip } from "@opencode-ai/ui/tooltip"
|
import { TooltipKeybind } from "@opencode-ai/ui/tooltip"
|
||||||
import { Tabs } from "@opencode-ai/ui/tabs"
|
import { Tabs } from "@opencode-ai/ui/tabs"
|
||||||
import { getFilename } from "@opencode-ai/util/path"
|
import { getFilename } from "@opencode-ai/util/path"
|
||||||
import { useFile } from "@/context/file"
|
import { useFile } from "@/context/file"
|
||||||
import { useLanguage } from "@/context/language"
|
import { useLanguage } from "@/context/language"
|
||||||
|
import { useCommand } from "@/context/command"
|
||||||
|
|
||||||
export function FileVisual(props: { path: string; active?: boolean }): JSX.Element {
|
export function FileVisual(props: { path: string; active?: boolean }): JSX.Element {
|
||||||
return (
|
return (
|
||||||
@@ -27,6 +28,7 @@ export function FileVisual(props: { path: string; active?: boolean }): JSX.Eleme
|
|||||||
export function SortableTab(props: { tab: string; onTabClose: (tab: string) => void }): JSX.Element {
|
export function SortableTab(props: { tab: string; onTabClose: (tab: string) => void }): JSX.Element {
|
||||||
const file = useFile()
|
const file = useFile()
|
||||||
const language = useLanguage()
|
const language = useLanguage()
|
||||||
|
const command = useCommand()
|
||||||
const sortable = createSortable(props.tab)
|
const sortable = createSortable(props.tab)
|
||||||
const path = createMemo(() => file.pathFromTab(props.tab))
|
const path = createMemo(() => file.pathFromTab(props.tab))
|
||||||
return (
|
return (
|
||||||
@@ -36,7 +38,11 @@ export function SortableTab(props: { tab: string; onTabClose: (tab: string) => v
|
|||||||
<Tabs.Trigger
|
<Tabs.Trigger
|
||||||
value={props.tab}
|
value={props.tab}
|
||||||
closeButton={
|
closeButton={
|
||||||
<Tooltip value={language.t("common.closeTab")} placement="bottom">
|
<TooltipKeybind
|
||||||
|
title={language.t("common.closeTab")}
|
||||||
|
keybind={command.keybind("tab.close")}
|
||||||
|
placement="bottom"
|
||||||
|
>
|
||||||
<IconButton
|
<IconButton
|
||||||
icon="close-small"
|
icon="close-small"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
@@ -44,7 +50,7 @@ export function SortableTab(props: { tab: string; onTabClose: (tab: string) => v
|
|||||||
onClick={() => props.onTabClose(props.tab)}
|
onClick={() => props.onTabClose(props.tab)}
|
||||||
aria-label={language.t("common.closeTab")}
|
aria-label={language.t("common.closeTab")}
|
||||||
/>
|
/>
|
||||||
</Tooltip>
|
</TooltipKeybind>
|
||||||
}
|
}
|
||||||
hideCloseButton
|
hideCloseButton
|
||||||
onMiddleClick={() => props.onTabClose(props.tab)}
|
onMiddleClick={() => props.onTabClose(props.tab)}
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ export function Titlebar() {
|
|||||||
const mac = createMemo(() => platform.platform === "desktop" && platform.os === "macos")
|
const mac = createMemo(() => platform.platform === "desktop" && platform.os === "macos")
|
||||||
const windows = createMemo(() => platform.platform === "desktop" && platform.os === "windows")
|
const windows = createMemo(() => platform.platform === "desktop" && platform.os === "windows")
|
||||||
const web = createMemo(() => platform.platform === "web")
|
const web = createMemo(() => platform.platform === "web")
|
||||||
|
const zoom = () => platform.webviewZoom?.() ?? 1
|
||||||
|
const minHeight = () => (mac() ? `${40 / zoom()}px` : undefined)
|
||||||
|
|
||||||
const [history, setHistory] = createStore({
|
const [history, setHistory] = createStore({
|
||||||
stack: [] as string[],
|
stack: [] as string[],
|
||||||
@@ -134,6 +136,7 @@ export function Titlebar() {
|
|||||||
return (
|
return (
|
||||||
<header
|
<header
|
||||||
class="h-10 shrink-0 bg-background-base relative grid grid-cols-[auto_minmax(0,1fr)_auto] items-center"
|
class="h-10 shrink-0 bg-background-base relative grid grid-cols-[auto_minmax(0,1fr)_auto] items-center"
|
||||||
|
style={{ "min-height": minHeight() }}
|
||||||
data-tauri-drag-region
|
data-tauri-drag-region
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@@ -145,7 +148,7 @@ export function Titlebar() {
|
|||||||
data-tauri-drag-region
|
data-tauri-drag-region
|
||||||
>
|
>
|
||||||
<Show when={mac()}>
|
<Show when={mac()}>
|
||||||
<div class="w-[72px] h-full shrink-0" data-tauri-drag-region />
|
<div class="h-full shrink-0" style={{ width: `${72 / zoom()}px` }} data-tauri-drag-region />
|
||||||
<div class="xl:hidden w-10 shrink-0 flex items-center justify-center">
|
<div class="xl:hidden w-10 shrink-0 flex items-center justify-center">
|
||||||
<IconButton
|
<IconButton
|
||||||
icon="menu"
|
icon="menu"
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { createSimpleContext } from "@opencode-ai/ui/context"
|
import { createSimpleContext } from "@opencode-ai/ui/context"
|
||||||
import { AsyncStorage, SyncStorage } from "@solid-primitives/storage"
|
import { AsyncStorage, SyncStorage } from "@solid-primitives/storage"
|
||||||
|
import type { Accessor } from "solid-js"
|
||||||
|
|
||||||
export type Platform = {
|
export type Platform = {
|
||||||
/** Platform discriminator */
|
/** Platform discriminator */
|
||||||
@@ -55,6 +56,9 @@ export type Platform = {
|
|||||||
|
|
||||||
/** Parse markdown to HTML using native parser (desktop only, returns unprocessed code blocks) */
|
/** Parse markdown to HTML using native parser (desktop only, returns unprocessed code blocks) */
|
||||||
parseMarkdown?(markdown: string): Promise<string>
|
parseMarkdown?(markdown: string): Promise<string>
|
||||||
|
|
||||||
|
/** Webview zoom level (desktop only) */
|
||||||
|
webviewZoom?: Accessor<number>
|
||||||
}
|
}
|
||||||
|
|
||||||
export const { use: usePlatform, provider: PlatformProvider } = createSimpleContext({
|
export const { use: usePlatform, provider: PlatformProvider } = createSimpleContext({
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ export const dict = {
|
|||||||
"command.settings.open": "فتح الإعدادات",
|
"command.settings.open": "فتح الإعدادات",
|
||||||
"command.session.previous": "الجلسة السابقة",
|
"command.session.previous": "الجلسة السابقة",
|
||||||
"command.session.next": "الجلسة التالية",
|
"command.session.next": "الجلسة التالية",
|
||||||
|
"command.session.previous.unseen": "Previous unread session",
|
||||||
|
"command.session.next.unseen": "Next unread session",
|
||||||
"command.session.archive": "أرشفة الجلسة",
|
"command.session.archive": "أرشفة الجلسة",
|
||||||
|
|
||||||
"command.palette": "لوحة الأوامر",
|
"command.palette": "لوحة الأوامر",
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ export const dict = {
|
|||||||
"command.settings.open": "Abrir configurações",
|
"command.settings.open": "Abrir configurações",
|
||||||
"command.session.previous": "Sessão anterior",
|
"command.session.previous": "Sessão anterior",
|
||||||
"command.session.next": "Próxima sessão",
|
"command.session.next": "Próxima sessão",
|
||||||
|
"command.session.previous.unseen": "Previous unread session",
|
||||||
|
"command.session.next.unseen": "Next unread session",
|
||||||
"command.session.archive": "Arquivar sessão",
|
"command.session.archive": "Arquivar sessão",
|
||||||
|
|
||||||
"command.palette": "Paleta de comandos",
|
"command.palette": "Paleta de comandos",
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ export const dict = {
|
|||||||
"command.settings.open": "Åbn indstillinger",
|
"command.settings.open": "Åbn indstillinger",
|
||||||
"command.session.previous": "Forrige session",
|
"command.session.previous": "Forrige session",
|
||||||
"command.session.next": "Næste session",
|
"command.session.next": "Næste session",
|
||||||
|
"command.session.previous.unseen": "Previous unread session",
|
||||||
|
"command.session.next.unseen": "Next unread session",
|
||||||
"command.session.archive": "Arkivér session",
|
"command.session.archive": "Arkivér session",
|
||||||
|
|
||||||
"command.palette": "Kommandopalette",
|
"command.palette": "Kommandopalette",
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ export const dict = {
|
|||||||
"command.settings.open": "Einstellungen öffnen",
|
"command.settings.open": "Einstellungen öffnen",
|
||||||
"command.session.previous": "Vorherige Sitzung",
|
"command.session.previous": "Vorherige Sitzung",
|
||||||
"command.session.next": "Nächste Sitzung",
|
"command.session.next": "Nächste Sitzung",
|
||||||
|
"command.session.previous.unseen": "Previous unread session",
|
||||||
|
"command.session.next.unseen": "Next unread session",
|
||||||
"command.session.archive": "Sitzung archivieren",
|
"command.session.archive": "Sitzung archivieren",
|
||||||
|
|
||||||
"command.palette": "Befehlspalette",
|
"command.palette": "Befehlspalette",
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ export const dict = {
|
|||||||
"command.settings.open": "Open settings",
|
"command.settings.open": "Open settings",
|
||||||
"command.session.previous": "Previous session",
|
"command.session.previous": "Previous session",
|
||||||
"command.session.next": "Next session",
|
"command.session.next": "Next session",
|
||||||
|
"command.session.previous.unseen": "Previous unread session",
|
||||||
|
"command.session.next.unseen": "Next unread session",
|
||||||
"command.session.archive": "Archive session",
|
"command.session.archive": "Archive session",
|
||||||
|
|
||||||
"command.palette": "Command palette",
|
"command.palette": "Command palette",
|
||||||
@@ -43,6 +45,7 @@ export const dict = {
|
|||||||
"command.session.new": "New session",
|
"command.session.new": "New session",
|
||||||
"command.file.open": "Open file",
|
"command.file.open": "Open file",
|
||||||
"command.file.open.description": "Search files and commands",
|
"command.file.open.description": "Search files and commands",
|
||||||
|
"command.tab.close": "Close tab",
|
||||||
"command.context.addSelection": "Add selection to context",
|
"command.context.addSelection": "Add selection to context",
|
||||||
"command.context.addSelection.description": "Add selected lines from the current file",
|
"command.context.addSelection.description": "Add selected lines from the current file",
|
||||||
"command.terminal.toggle": "Toggle terminal",
|
"command.terminal.toggle": "Toggle terminal",
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ export const dict = {
|
|||||||
"command.settings.open": "Abrir ajustes",
|
"command.settings.open": "Abrir ajustes",
|
||||||
"command.session.previous": "Sesión anterior",
|
"command.session.previous": "Sesión anterior",
|
||||||
"command.session.next": "Siguiente sesión",
|
"command.session.next": "Siguiente sesión",
|
||||||
|
"command.session.previous.unseen": "Previous unread session",
|
||||||
|
"command.session.next.unseen": "Next unread session",
|
||||||
"command.session.archive": "Archivar sesión",
|
"command.session.archive": "Archivar sesión",
|
||||||
|
|
||||||
"command.palette": "Paleta de comandos",
|
"command.palette": "Paleta de comandos",
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ export const dict = {
|
|||||||
"command.settings.open": "Ouvrir les paramètres",
|
"command.settings.open": "Ouvrir les paramètres",
|
||||||
"command.session.previous": "Session précédente",
|
"command.session.previous": "Session précédente",
|
||||||
"command.session.next": "Session suivante",
|
"command.session.next": "Session suivante",
|
||||||
|
"command.session.previous.unseen": "Previous unread session",
|
||||||
|
"command.session.next.unseen": "Next unread session",
|
||||||
"command.session.archive": "Archiver la session",
|
"command.session.archive": "Archiver la session",
|
||||||
|
|
||||||
"command.palette": "Palette de commandes",
|
"command.palette": "Palette de commandes",
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ export const dict = {
|
|||||||
"command.settings.open": "設定を開く",
|
"command.settings.open": "設定を開く",
|
||||||
"command.session.previous": "前のセッション",
|
"command.session.previous": "前のセッション",
|
||||||
"command.session.next": "次のセッション",
|
"command.session.next": "次のセッション",
|
||||||
|
"command.session.previous.unseen": "Previous unread session",
|
||||||
|
"command.session.next.unseen": "Next unread session",
|
||||||
"command.session.archive": "セッションをアーカイブ",
|
"command.session.archive": "セッションをアーカイブ",
|
||||||
|
|
||||||
"command.palette": "コマンドパレット",
|
"command.palette": "コマンドパレット",
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ export const dict = {
|
|||||||
"command.settings.open": "설정 열기",
|
"command.settings.open": "설정 열기",
|
||||||
"command.session.previous": "이전 세션",
|
"command.session.previous": "이전 세션",
|
||||||
"command.session.next": "다음 세션",
|
"command.session.next": "다음 세션",
|
||||||
|
"command.session.previous.unseen": "Previous unread session",
|
||||||
|
"command.session.next.unseen": "Next unread session",
|
||||||
"command.session.archive": "세션 보관",
|
"command.session.archive": "세션 보관",
|
||||||
|
|
||||||
"command.palette": "명령 팔레트",
|
"command.palette": "명령 팔레트",
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ export const dict = {
|
|||||||
"command.settings.open": "Åpne innstillinger",
|
"command.settings.open": "Åpne innstillinger",
|
||||||
"command.session.previous": "Forrige sesjon",
|
"command.session.previous": "Forrige sesjon",
|
||||||
"command.session.next": "Neste sesjon",
|
"command.session.next": "Neste sesjon",
|
||||||
|
"command.session.previous.unseen": "Previous unread session",
|
||||||
|
"command.session.next.unseen": "Next unread session",
|
||||||
"command.session.archive": "Arkiver sesjon",
|
"command.session.archive": "Arkiver sesjon",
|
||||||
|
|
||||||
"command.palette": "Kommandopalett",
|
"command.palette": "Kommandopalett",
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ export const dict = {
|
|||||||
"command.settings.open": "Otwórz ustawienia",
|
"command.settings.open": "Otwórz ustawienia",
|
||||||
"command.session.previous": "Poprzednia sesja",
|
"command.session.previous": "Poprzednia sesja",
|
||||||
"command.session.next": "Następna sesja",
|
"command.session.next": "Następna sesja",
|
||||||
|
"command.session.previous.unseen": "Previous unread session",
|
||||||
|
"command.session.next.unseen": "Next unread session",
|
||||||
"command.session.archive": "Zarchiwizuj sesję",
|
"command.session.archive": "Zarchiwizuj sesję",
|
||||||
|
|
||||||
"command.palette": "Paleta poleceń",
|
"command.palette": "Paleta poleceń",
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ export const dict = {
|
|||||||
"command.settings.open": "Открыть настройки",
|
"command.settings.open": "Открыть настройки",
|
||||||
"command.session.previous": "Предыдущая сессия",
|
"command.session.previous": "Предыдущая сессия",
|
||||||
"command.session.next": "Следующая сессия",
|
"command.session.next": "Следующая сессия",
|
||||||
|
"command.session.previous.unseen": "Previous unread session",
|
||||||
|
"command.session.next.unseen": "Next unread session",
|
||||||
"command.session.archive": "Архивировать сессию",
|
"command.session.archive": "Архивировать сессию",
|
||||||
|
|
||||||
"command.palette": "Палитра команд",
|
"command.palette": "Палитра команд",
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ export const dict = {
|
|||||||
"command.settings.open": "เปิดการตั้งค่า",
|
"command.settings.open": "เปิดการตั้งค่า",
|
||||||
"command.session.previous": "เซสชันก่อนหน้า",
|
"command.session.previous": "เซสชันก่อนหน้า",
|
||||||
"command.session.next": "เซสชันถัดไป",
|
"command.session.next": "เซสชันถัดไป",
|
||||||
|
"command.session.previous.unseen": "Previous unread session",
|
||||||
|
"command.session.next.unseen": "Next unread session",
|
||||||
"command.session.archive": "จัดเก็บเซสชัน",
|
"command.session.archive": "จัดเก็บเซสชัน",
|
||||||
|
|
||||||
"command.palette": "คำสั่งค้นหา",
|
"command.palette": "คำสั่งค้นหา",
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ export const dict = {
|
|||||||
"command.settings.open": "打开设置",
|
"command.settings.open": "打开设置",
|
||||||
"command.session.previous": "上一个会话",
|
"command.session.previous": "上一个会话",
|
||||||
"command.session.next": "下一个会话",
|
"command.session.next": "下一个会话",
|
||||||
|
"command.session.previous.unseen": "Previous unread session",
|
||||||
|
"command.session.next.unseen": "Next unread session",
|
||||||
"command.session.archive": "归档会话",
|
"command.session.archive": "归档会话",
|
||||||
|
|
||||||
"command.palette": "命令面板",
|
"command.palette": "命令面板",
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ export const dict = {
|
|||||||
"command.settings.open": "開啟設定",
|
"command.settings.open": "開啟設定",
|
||||||
"command.session.previous": "上一個工作階段",
|
"command.session.previous": "上一個工作階段",
|
||||||
"command.session.next": "下一個工作階段",
|
"command.session.next": "下一個工作階段",
|
||||||
|
"command.session.previous.unseen": "Previous unread session",
|
||||||
|
"command.session.next.unseen": "Next unread session",
|
||||||
"command.session.archive": "封存工作階段",
|
"command.session.archive": "封存工作階段",
|
||||||
|
|
||||||
"command.palette": "命令面板",
|
"command.palette": "命令面板",
|
||||||
|
|||||||
@@ -886,6 +886,52 @@ export default function Layout(props: ParentProps) {
|
|||||||
queueMicrotask(() => scrollToSession(session.id, `${session.directory}:${session.id}`))
|
queueMicrotask(() => scrollToSession(session.id, `${session.directory}:${session.id}`))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function navigateSessionByUnseen(offset: number) {
|
||||||
|
const sessions = currentSessions()
|
||||||
|
if (sessions.length === 0) return
|
||||||
|
|
||||||
|
const hasUnseen = sessions.some((session) => notification.session.unseen(session.id).length > 0)
|
||||||
|
if (!hasUnseen) return
|
||||||
|
|
||||||
|
const activeIndex = params.id ? sessions.findIndex((s) => s.id === params.id) : -1
|
||||||
|
const start = activeIndex === -1 ? (offset > 0 ? -1 : 0) : activeIndex
|
||||||
|
|
||||||
|
for (let i = 1; i <= sessions.length; i++) {
|
||||||
|
const index = offset > 0 ? (start + i) % sessions.length : (start - i + sessions.length) % sessions.length
|
||||||
|
const session = sessions[index]
|
||||||
|
if (!session) continue
|
||||||
|
if (notification.session.unseen(session.id).length === 0) continue
|
||||||
|
|
||||||
|
prefetchSession(session, "high")
|
||||||
|
|
||||||
|
const next = sessions[(index + 1) % sessions.length]
|
||||||
|
const prev = sessions[(index - 1 + sessions.length) % sessions.length]
|
||||||
|
|
||||||
|
if (offset > 0) {
|
||||||
|
if (next) prefetchSession(next, "high")
|
||||||
|
if (prev) prefetchSession(prev)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset < 0) {
|
||||||
|
if (prev) prefetchSession(prev, "high")
|
||||||
|
if (next) prefetchSession(next)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (import.meta.env.DEV) {
|
||||||
|
navStart({
|
||||||
|
dir: base64Encode(session.directory),
|
||||||
|
from: params.id,
|
||||||
|
to: session.id,
|
||||||
|
trigger: offset > 0 ? "shift+alt+arrowdown" : "shift+alt+arrowup",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
navigateToSession(session)
|
||||||
|
queueMicrotask(() => scrollToSession(session.id, `${session.directory}:${session.id}`))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function archiveSession(session: Session) {
|
async function archiveSession(session: Session) {
|
||||||
const [store, setStore] = globalSync.child(session.directory)
|
const [store, setStore] = globalSync.child(session.directory)
|
||||||
const sessions = store.session ?? []
|
const sessions = store.session ?? []
|
||||||
@@ -1024,6 +1070,20 @@ export default function Layout(props: ParentProps) {
|
|||||||
keybind: "alt+arrowdown",
|
keybind: "alt+arrowdown",
|
||||||
onSelect: () => navigateSessionByOffset(1),
|
onSelect: () => navigateSessionByOffset(1),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: "session.previous.unseen",
|
||||||
|
title: language.t("command.session.previous.unseen"),
|
||||||
|
category: language.t("command.category.session"),
|
||||||
|
keybind: "shift+alt+arrowup",
|
||||||
|
onSelect: () => navigateSessionByUnseen(-1),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "session.next.unseen",
|
||||||
|
title: language.t("command.session.next.unseen"),
|
||||||
|
category: language.t("command.category.session"),
|
||||||
|
keybind: "shift+alt+arrowdown",
|
||||||
|
onSelect: () => navigateSessionByUnseen(1),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: "session.archive",
|
id: "session.archive",
|
||||||
title: language.t("command.session.archive"),
|
title: language.t("command.session.archive"),
|
||||||
|
|||||||
@@ -689,6 +689,18 @@ export default function Page() {
|
|||||||
slash: "open",
|
slash: "open",
|
||||||
onSelect: () => dialog.show(() => <DialogSelectFile onOpenFile={() => showAllFiles()} />),
|
onSelect: () => dialog.show(() => <DialogSelectFile onOpenFile={() => showAllFiles()} />),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: "tab.close",
|
||||||
|
title: language.t("command.tab.close"),
|
||||||
|
category: language.t("command.category.file"),
|
||||||
|
keybind: "mod+w",
|
||||||
|
disabled: !tabs().active(),
|
||||||
|
onSelect: () => {
|
||||||
|
const active = tabs().active()
|
||||||
|
if (!active) return
|
||||||
|
tabs().close(active)
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: "context.addSelection",
|
id: "context.addSelection",
|
||||||
title: language.t("command.context.addSelection"),
|
title: language.t("command.context.addSelection"),
|
||||||
@@ -1940,7 +1952,8 @@ export default function Page() {
|
|||||||
"sticky top-0 z-30 bg-background-stronger": true,
|
"sticky top-0 z-30 bg-background-stronger": true,
|
||||||
"w-full": true,
|
"w-full": true,
|
||||||
"px-4 md:px-6": true,
|
"px-4 md:px-6": true,
|
||||||
"md:max-w-200 md:mx-auto": centered(),
|
"md:max-w-200 md:mx-auto 3xl:max-w-[1200px] 3xl:mx-auto 4xl:max-w-[1600px] 4xl:mx-auto 5xl:max-w-[1900px] 5xl:mx-auto":
|
||||||
|
centered(),
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div class="h-10 flex items-center gap-1">
|
<div class="h-10 flex items-center gap-1">
|
||||||
@@ -1968,7 +1981,8 @@ export default function Page() {
|
|||||||
class="flex flex-col gap-32 items-start justify-start pb-[calc(var(--prompt-height,8rem)+64px)] md:pb-[calc(var(--prompt-height,10rem)+64px)] transition-[margin]"
|
class="flex flex-col gap-32 items-start justify-start pb-[calc(var(--prompt-height,8rem)+64px)] md:pb-[calc(var(--prompt-height,10rem)+64px)] transition-[margin]"
|
||||||
classList={{
|
classList={{
|
||||||
"w-full": true,
|
"w-full": true,
|
||||||
"md:max-w-200 md:mx-auto": centered(),
|
"md:max-w-200 md:mx-auto 3xl:max-w-[1200px] 3xl:mx-auto 4xl:max-w-[1600px] 4xl:mx-auto 5xl:max-w-[1900px] 5xl:mx-auto":
|
||||||
|
centered(),
|
||||||
"mt-0.5": centered(),
|
"mt-0.5": centered(),
|
||||||
"mt-0": !centered(),
|
"mt-0": !centered(),
|
||||||
}}
|
}}
|
||||||
@@ -2021,7 +2035,7 @@ export default function Page() {
|
|||||||
data-message-id={message.id}
|
data-message-id={message.id}
|
||||||
classList={{
|
classList={{
|
||||||
"min-w-0 w-full max-w-full": true,
|
"min-w-0 w-full max-w-full": true,
|
||||||
"md:max-w-200": centered(),
|
"md:max-w-200 3xl:max-w-[1200px] 4xl:max-w-[1600px] 5xl:max-w-[1900px]": centered(),
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<SessionTurn
|
<SessionTurn
|
||||||
@@ -2078,7 +2092,7 @@ export default function Page() {
|
|||||||
<div
|
<div
|
||||||
classList={{
|
classList={{
|
||||||
"w-full px-4 pointer-events-auto": true,
|
"w-full px-4 pointer-events-auto": true,
|
||||||
"md:max-w-200 md:mx-auto": centered(),
|
"md:max-w-200 3xl:max-w-[1200px] 4xl:max-w-[1600px] 5xl:max-w-[1900px]": centered(),
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Show when={request()} keyed>
|
<Show when={request()} keyed>
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ export const config = {
|
|||||||
github: {
|
github: {
|
||||||
repoUrl: "https://github.com/anomalyco/opencode",
|
repoUrl: "https://github.com/anomalyco/opencode",
|
||||||
starsFormatted: {
|
starsFormatted: {
|
||||||
compact: "80K",
|
compact: "95K",
|
||||||
full: "80,000",
|
full: "95,000",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -22,8 +22,8 @@ export const config = {
|
|||||||
|
|
||||||
// Static stats (used on landing page)
|
// Static stats (used on landing page)
|
||||||
stats: {
|
stats: {
|
||||||
contributors: "600",
|
contributors: "650",
|
||||||
commits: "7,500",
|
commits: "8,500",
|
||||||
monthlyUsers: "1.5M",
|
monthlyUsers: "2.5M",
|
||||||
},
|
},
|
||||||
} as const
|
} as const
|
||||||
|
|||||||
@@ -2,13 +2,17 @@ import { Database, eq, and, sql, inArray } from "@opencode-ai/console-core/drizz
|
|||||||
import { IpRateLimitTable } from "@opencode-ai/console-core/schema/ip.sql.js"
|
import { IpRateLimitTable } from "@opencode-ai/console-core/schema/ip.sql.js"
|
||||||
import { RateLimitError } from "./error"
|
import { RateLimitError } from "./error"
|
||||||
import { logger } from "./logger"
|
import { logger } from "./logger"
|
||||||
|
import { ZenData } from "@opencode-ai/console-core/model.js"
|
||||||
|
|
||||||
export function createRateLimiter(limit: number | undefined, rawIp: string) {
|
export function createRateLimiter(limit: ZenData.RateLimit | undefined, rawIp: string) {
|
||||||
if (!limit) return
|
if (!limit) return
|
||||||
|
|
||||||
const ip = !rawIp.length ? "unknown" : rawIp
|
const ip = !rawIp.length ? "unknown" : rawIp
|
||||||
const now = Date.now()
|
const now = Date.now()
|
||||||
const intervals = [buildYYYYMMDDHH(now), buildYYYYMMDDHH(now - 3_600_000), buildYYYYMMDDHH(now - 7_200_000)]
|
const intervals =
|
||||||
|
limit.period === "day"
|
||||||
|
? [buildYYYYMMDD(now)]
|
||||||
|
: [buildYYYYMMDDHH(now), buildYYYYMMDDHH(now - 3_600_000), buildYYYYMMDDHH(now - 7_200_000)]
|
||||||
|
|
||||||
return {
|
return {
|
||||||
track: async () => {
|
track: async () => {
|
||||||
@@ -28,11 +32,18 @@ export function createRateLimiter(limit: number | undefined, rawIp: string) {
|
|||||||
)
|
)
|
||||||
const total = rows.reduce((sum, r) => sum + r.count, 0)
|
const total = rows.reduce((sum, r) => sum + r.count, 0)
|
||||||
logger.debug(`rate limit total: ${total}`)
|
logger.debug(`rate limit total: ${total}`)
|
||||||
if (total >= limit) throw new RateLimitError(`Rate limit exceeded. Please try again later.`)
|
if (total >= limit.value) throw new RateLimitError(`Rate limit exceeded. Please try again later.`)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function buildYYYYMMDD(timestamp: number) {
|
||||||
|
return new Date(timestamp)
|
||||||
|
.toISOString()
|
||||||
|
.replace(/[^0-9]/g, "")
|
||||||
|
.substring(0, 8)
|
||||||
|
}
|
||||||
|
|
||||||
function buildYYYYMMDDHH(timestamp: number) {
|
function buildYYYYMMDDHH(timestamp: number) {
|
||||||
return new Date(timestamp)
|
return new Date(timestamp)
|
||||||
.toISOString()
|
.toISOString()
|
||||||
|
|||||||
@@ -18,8 +18,13 @@ export namespace ZenData {
|
|||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
|
const RateLimitSchema = z.object({
|
||||||
|
period: z.enum(["day", "rolling"]),
|
||||||
|
value: z.number().int(),
|
||||||
|
})
|
||||||
export type Format = z.infer<typeof FormatSchema>
|
export type Format = z.infer<typeof FormatSchema>
|
||||||
export type Trial = z.infer<typeof TrialSchema>
|
export type Trial = z.infer<typeof TrialSchema>
|
||||||
|
export type RateLimit = z.infer<typeof RateLimitSchema>
|
||||||
|
|
||||||
const ModelCostSchema = z.object({
|
const ModelCostSchema = z.object({
|
||||||
input: z.number(),
|
input: z.number(),
|
||||||
@@ -37,7 +42,7 @@ export namespace ZenData {
|
|||||||
byokProvider: z.enum(["openai", "anthropic", "google"]).optional(),
|
byokProvider: z.enum(["openai", "anthropic", "google"]).optional(),
|
||||||
stickyProvider: z.enum(["strict", "prefer"]).optional(),
|
stickyProvider: z.enum(["strict", "prefer"]).optional(),
|
||||||
trial: TrialSchema.optional(),
|
trial: TrialSchema.optional(),
|
||||||
rateLimit: z.number().optional(),
|
rateLimit: RateLimitSchema.optional(),
|
||||||
fallbackProvider: z.string().optional(),
|
fallbackProvider: z.string().optional(),
|
||||||
providers: z.array(
|
providers: z.array(
|
||||||
z.object({
|
z.object({
|
||||||
|
|||||||
Generated
+207
-40
@@ -2,6 +2,12 @@
|
|||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 4
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "Inflector"
|
||||||
|
version = "0.11.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "adler2"
|
name = "adler2"
|
||||||
version = "2.0.1"
|
version = "2.0.1"
|
||||||
@@ -1994,9 +2000,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ico"
|
name = "ico"
|
||||||
version = "0.4.0"
|
version = "0.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cc50b891e4acf8fe0e71ef88ec43ad82ee07b3810ad09de10f1d01f072ed4b98"
|
checksum = "3e795dff5605e0f04bff85ca41b51a96b83e80b281e96231bcaaf1ac35103371"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"png 0.17.16",
|
"png 0.17.16",
|
||||||
@@ -3065,12 +3071,14 @@ dependencies = [
|
|||||||
"listeners",
|
"listeners",
|
||||||
"objc2 0.6.3",
|
"objc2 0.6.3",
|
||||||
"objc2-web-kit",
|
"objc2-web-kit",
|
||||||
"reqwest",
|
"reqwest 0.12.24",
|
||||||
"semver",
|
"semver",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"specta",
|
||||||
|
"specta-typescript",
|
||||||
"tauri",
|
"tauri",
|
||||||
"tauri-build",
|
"tauri-build 2.5.2",
|
||||||
"tauri-plugin-clipboard-manager",
|
"tauri-plugin-clipboard-manager",
|
||||||
"tauri-plugin-decorum",
|
"tauri-plugin-decorum",
|
||||||
"tauri-plugin-deep-link",
|
"tauri-plugin-deep-link",
|
||||||
@@ -3085,6 +3093,7 @@ dependencies = [
|
|||||||
"tauri-plugin-store",
|
"tauri-plugin-store",
|
||||||
"tauri-plugin-updater",
|
"tauri-plugin-updater",
|
||||||
"tauri-plugin-window-state",
|
"tauri-plugin-window-state",
|
||||||
|
"tauri-specta",
|
||||||
"tokio",
|
"tokio",
|
||||||
"uuid",
|
"uuid",
|
||||||
"webkit2gtk",
|
"webkit2gtk",
|
||||||
@@ -3221,6 +3230,12 @@ dependencies = [
|
|||||||
"windows-link 0.2.1",
|
"windows-link 0.2.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "paste"
|
||||||
|
version = "1.0.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pathdiff"
|
name = "pathdiff"
|
||||||
version = "0.2.3"
|
version = "0.2.3"
|
||||||
@@ -3947,6 +3962,40 @@ dependencies = [
|
|||||||
"webpki-roots",
|
"webpki-roots",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "reqwest"
|
||||||
|
version = "0.13.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "04e9018c9d814e5f30cc16a0f03271aeab3571e609612d9fe78c1aa8d11c2f62"
|
||||||
|
dependencies = [
|
||||||
|
"base64 0.22.1",
|
||||||
|
"bytes",
|
||||||
|
"futures-core",
|
||||||
|
"futures-util",
|
||||||
|
"http",
|
||||||
|
"http-body",
|
||||||
|
"http-body-util",
|
||||||
|
"hyper",
|
||||||
|
"hyper-util",
|
||||||
|
"js-sys",
|
||||||
|
"log",
|
||||||
|
"percent-encoding",
|
||||||
|
"pin-project-lite",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"sync_wrapper",
|
||||||
|
"tokio",
|
||||||
|
"tokio-util",
|
||||||
|
"tower",
|
||||||
|
"tower-http",
|
||||||
|
"tower-service",
|
||||||
|
"url",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"wasm-bindgen-futures",
|
||||||
|
"wasm-streams",
|
||||||
|
"web-sys",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rfd"
|
name = "rfd"
|
||||||
version = "0.15.4"
|
version = "0.15.4"
|
||||||
@@ -4497,6 +4546,44 @@ dependencies = [
|
|||||||
"system-deps",
|
"system-deps",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "specta"
|
||||||
|
version = "2.0.0-rc.22"
|
||||||
|
source = "git+https://github.com/specta-rs/specta?rev=106425eac4964d8ff34d3a02f1612e33117b08bb#106425eac4964d8ff34d3a02f1612e33117b08bb"
|
||||||
|
dependencies = [
|
||||||
|
"paste",
|
||||||
|
"rustc_version",
|
||||||
|
"specta-macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "specta-macros"
|
||||||
|
version = "2.0.0-rc.18"
|
||||||
|
source = "git+https://github.com/specta-rs/specta?rev=106425eac4964d8ff34d3a02f1612e33117b08bb#106425eac4964d8ff34d3a02f1612e33117b08bb"
|
||||||
|
dependencies = [
|
||||||
|
"Inflector",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.110",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "specta-serde"
|
||||||
|
version = "0.0.9"
|
||||||
|
source = "git+https://github.com/specta-rs/specta?rev=106425eac4964d8ff34d3a02f1612e33117b08bb#106425eac4964d8ff34d3a02f1612e33117b08bb"
|
||||||
|
dependencies = [
|
||||||
|
"specta",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "specta-typescript"
|
||||||
|
version = "0.0.9"
|
||||||
|
source = "git+https://github.com/specta-rs/specta?rev=106425eac4964d8ff34d3a02f1612e33117b08bb#106425eac4964d8ff34d3a02f1612e33117b08bb"
|
||||||
|
dependencies = [
|
||||||
|
"specta",
|
||||||
|
"specta-serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "stable_deref_trait"
|
name = "stable_deref_trait"
|
||||||
version = "1.2.1"
|
version = "1.2.1"
|
||||||
@@ -4712,9 +4799,8 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri"
|
name = "tauri"
|
||||||
version = "2.9.3"
|
version = "2.9.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/tauri-apps/tauri?rev=4d5d78daf636feaac20c5bc48a6071491c4291ee#4d5d78daf636feaac20c5bc48a6071491c4291ee"
|
||||||
checksum = "9e492485dd390b35f7497401f67694f46161a2a00ffd800938d5dd3c898fb9d8"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bytes",
|
"bytes",
|
||||||
@@ -4740,17 +4826,18 @@ dependencies = [
|
|||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"plist",
|
"plist",
|
||||||
"raw-window-handle",
|
"raw-window-handle",
|
||||||
"reqwest",
|
"reqwest 0.13.1",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_repr",
|
"serde_repr",
|
||||||
"serialize-to-javascript",
|
"serialize-to-javascript",
|
||||||
|
"specta",
|
||||||
"swift-rs",
|
"swift-rs",
|
||||||
"tauri-build",
|
"tauri-build 2.5.3",
|
||||||
"tauri-macros",
|
"tauri-macros",
|
||||||
"tauri-runtime",
|
"tauri-runtime",
|
||||||
"tauri-runtime-wry",
|
"tauri-runtime-wry",
|
||||||
"tauri-utils",
|
"tauri-utils 2.8.1",
|
||||||
"thiserror 2.0.17",
|
"thiserror 2.0.17",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tray-icon",
|
"tray-icon",
|
||||||
@@ -4777,7 +4864,28 @@ dependencies = [
|
|||||||
"semver",
|
"semver",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"tauri-utils",
|
"tauri-utils 2.8.0",
|
||||||
|
"tauri-winres",
|
||||||
|
"toml 0.9.8",
|
||||||
|
"walkdir",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tauri-build"
|
||||||
|
version = "2.5.3"
|
||||||
|
source = "git+https://github.com/tauri-apps/tauri?rev=4d5d78daf636feaac20c5bc48a6071491c4291ee#4d5d78daf636feaac20c5bc48a6071491c4291ee"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"cargo_toml",
|
||||||
|
"dirs",
|
||||||
|
"glob",
|
||||||
|
"heck 0.5.0",
|
||||||
|
"json-patch",
|
||||||
|
"schemars 0.8.22",
|
||||||
|
"semver",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"tauri-utils 2.8.1",
|
||||||
"tauri-winres",
|
"tauri-winres",
|
||||||
"toml 0.9.8",
|
"toml 0.9.8",
|
||||||
"walkdir",
|
"walkdir",
|
||||||
@@ -4785,9 +4893,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-codegen"
|
name = "tauri-codegen"
|
||||||
version = "2.5.1"
|
version = "2.5.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/tauri-apps/tauri?rev=4d5d78daf636feaac20c5bc48a6071491c4291ee#4d5d78daf636feaac20c5bc48a6071491c4291ee"
|
||||||
checksum = "b7ef707148f0755110ca54377560ab891d722de4d53297595380a748026f139f"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
"brotli",
|
"brotli",
|
||||||
@@ -4802,7 +4909,7 @@ dependencies = [
|
|||||||
"serde_json",
|
"serde_json",
|
||||||
"sha2",
|
"sha2",
|
||||||
"syn 2.0.110",
|
"syn 2.0.110",
|
||||||
"tauri-utils",
|
"tauri-utils 2.8.1",
|
||||||
"thiserror 2.0.17",
|
"thiserror 2.0.17",
|
||||||
"time",
|
"time",
|
||||||
"url",
|
"url",
|
||||||
@@ -4812,16 +4919,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-macros"
|
name = "tauri-macros"
|
||||||
version = "2.5.1"
|
version = "2.5.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/tauri-apps/tauri?rev=4d5d78daf636feaac20c5bc48a6071491c4291ee#4d5d78daf636feaac20c5bc48a6071491c4291ee"
|
||||||
checksum = "71664fd715ee6e382c05345ad258d6d1d50f90cf1b58c0aa726638b33c2a075d"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck 0.5.0",
|
"heck 0.5.0",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.110",
|
"syn 2.0.110",
|
||||||
"tauri-codegen",
|
"tauri-codegen",
|
||||||
"tauri-utils",
|
"tauri-utils 2.8.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4836,7 +4942,7 @@ dependencies = [
|
|||||||
"schemars 0.8.22",
|
"schemars 0.8.22",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"tauri-utils",
|
"tauri-utils 2.8.0",
|
||||||
"toml 0.9.8",
|
"toml 0.9.8",
|
||||||
"walkdir",
|
"walkdir",
|
||||||
]
|
]
|
||||||
@@ -4886,7 +4992,7 @@ dependencies = [
|
|||||||
"serde_json",
|
"serde_json",
|
||||||
"tauri",
|
"tauri",
|
||||||
"tauri-plugin",
|
"tauri-plugin",
|
||||||
"tauri-utils",
|
"tauri-utils 2.8.0",
|
||||||
"thiserror 2.0.17",
|
"thiserror 2.0.17",
|
||||||
"tracing",
|
"tracing",
|
||||||
"url",
|
"url",
|
||||||
@@ -4928,7 +5034,7 @@ dependencies = [
|
|||||||
"serde_repr",
|
"serde_repr",
|
||||||
"tauri",
|
"tauri",
|
||||||
"tauri-plugin",
|
"tauri-plugin",
|
||||||
"tauri-utils",
|
"tauri-utils 2.8.0",
|
||||||
"thiserror 2.0.17",
|
"thiserror 2.0.17",
|
||||||
"toml 0.9.8",
|
"toml 0.9.8",
|
||||||
"url",
|
"url",
|
||||||
@@ -4945,7 +5051,7 @@ dependencies = [
|
|||||||
"data-url",
|
"data-url",
|
||||||
"http",
|
"http",
|
||||||
"regex",
|
"regex",
|
||||||
"reqwest",
|
"reqwest 0.12.24",
|
||||||
"schemars 0.8.22",
|
"schemars 0.8.22",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
@@ -5096,7 +5202,7 @@ dependencies = [
|
|||||||
"minisign-verify",
|
"minisign-verify",
|
||||||
"osakit",
|
"osakit",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"reqwest",
|
"reqwest 0.12.24",
|
||||||
"semver",
|
"semver",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
@@ -5129,9 +5235,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-runtime"
|
name = "tauri-runtime"
|
||||||
version = "2.9.1"
|
version = "2.9.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/tauri-apps/tauri?rev=4d5d78daf636feaac20c5bc48a6071491c4291ee#4d5d78daf636feaac20c5bc48a6071491c4291ee"
|
||||||
checksum = "9368f09358496f2229313fccb37682ad116b7f46fa76981efe116994a0628926"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cookie",
|
"cookie",
|
||||||
"dpi",
|
"dpi",
|
||||||
@@ -5144,7 +5249,7 @@ dependencies = [
|
|||||||
"raw-window-handle",
|
"raw-window-handle",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"tauri-utils",
|
"tauri-utils 2.8.1",
|
||||||
"thiserror 2.0.17",
|
"thiserror 2.0.17",
|
||||||
"url",
|
"url",
|
||||||
"webkit2gtk",
|
"webkit2gtk",
|
||||||
@@ -5154,9 +5259,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-runtime-wry"
|
name = "tauri-runtime-wry"
|
||||||
version = "2.9.1"
|
version = "2.9.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/tauri-apps/tauri?rev=4d5d78daf636feaac20c5bc48a6071491c4291ee#4d5d78daf636feaac20c5bc48a6071491c4291ee"
|
||||||
checksum = "929f5df216f5c02a9e894554401bcdab6eec3e39ec6a4a7731c7067fc8688a93"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"gtk",
|
"gtk",
|
||||||
"http",
|
"http",
|
||||||
@@ -5171,7 +5275,7 @@ dependencies = [
|
|||||||
"softbuffer",
|
"softbuffer",
|
||||||
"tao",
|
"tao",
|
||||||
"tauri-runtime",
|
"tauri-runtime",
|
||||||
"tauri-utils",
|
"tauri-utils 2.8.1",
|
||||||
"url",
|
"url",
|
||||||
"webkit2gtk",
|
"webkit2gtk",
|
||||||
"webview2-com",
|
"webview2-com",
|
||||||
@@ -5179,11 +5283,74 @@ dependencies = [
|
|||||||
"wry",
|
"wry",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tauri-specta"
|
||||||
|
version = "2.0.0-rc.21"
|
||||||
|
source = "git+https://github.com/specta-rs/tauri-specta?rev=6720b2848eff9a3e40af54c48d65f6d56b640c0b#6720b2848eff9a3e40af54c48d65f6d56b640c0b"
|
||||||
|
dependencies = [
|
||||||
|
"heck 0.5.0",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"specta",
|
||||||
|
"specta-typescript",
|
||||||
|
"tauri",
|
||||||
|
"tauri-specta-macros",
|
||||||
|
"thiserror 2.0.17",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tauri-specta-macros"
|
||||||
|
version = "2.0.0-rc.16"
|
||||||
|
source = "git+https://github.com/specta-rs/tauri-specta?rev=6720b2848eff9a3e40af54c48d65f6d56b640c0b#6720b2848eff9a3e40af54c48d65f6d56b640c0b"
|
||||||
|
dependencies = [
|
||||||
|
"darling",
|
||||||
|
"heck 0.5.0",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.110",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-utils"
|
name = "tauri-utils"
|
||||||
version = "2.8.0"
|
version = "2.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f6b8bbe426abdbf52d050e52ed693130dbd68375b9ad82a3fb17efb4c8d85673"
|
checksum = "f6b8bbe426abdbf52d050e52ed693130dbd68375b9ad82a3fb17efb4c8d85673"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"cargo_metadata",
|
||||||
|
"ctor",
|
||||||
|
"dunce",
|
||||||
|
"glob",
|
||||||
|
"html5ever",
|
||||||
|
"http",
|
||||||
|
"infer",
|
||||||
|
"json-patch",
|
||||||
|
"kuchikiki",
|
||||||
|
"log",
|
||||||
|
"memchr",
|
||||||
|
"phf 0.11.3",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"regex",
|
||||||
|
"schemars 0.8.22",
|
||||||
|
"semver",
|
||||||
|
"serde",
|
||||||
|
"serde-untagged",
|
||||||
|
"serde_json",
|
||||||
|
"serde_with",
|
||||||
|
"swift-rs",
|
||||||
|
"thiserror 2.0.17",
|
||||||
|
"toml 0.9.8",
|
||||||
|
"url",
|
||||||
|
"urlpattern",
|
||||||
|
"uuid",
|
||||||
|
"walkdir",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tauri-utils"
|
||||||
|
version = "2.8.1"
|
||||||
|
source = "git+https://github.com/tauri-apps/tauri?rev=4d5d78daf636feaac20c5bc48a6071491c4291ee#4d5d78daf636feaac20c5bc48a6071491c4291ee"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"brotli",
|
"brotli",
|
||||||
@@ -5547,9 +5714,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tower-http"
|
name = "tower-http"
|
||||||
version = "0.6.6"
|
version = "0.6.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2"
|
checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.10.0",
|
"bitflags 2.10.0",
|
||||||
"bytes",
|
"bytes",
|
||||||
@@ -6034,9 +6201,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webkit2gtk"
|
name = "webkit2gtk"
|
||||||
version = "2.0.1"
|
version = "2.0.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "76b1bc1e54c581da1e9f179d0b38512ba358fb1af2d634a1affe42e37172361a"
|
checksum = "a1027150013530fb2eaf806408df88461ae4815a45c541c8975e61d6f2fc4793"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
"cairo-rs",
|
"cairo-rs",
|
||||||
@@ -6058,9 +6225,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webkit2gtk-sys"
|
name = "webkit2gtk-sys"
|
||||||
version = "2.0.1"
|
version = "2.0.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "62daa38afc514d1f8f12b8693d30d5993ff77ced33ce30cd04deebc267a6d57c"
|
checksum = "916a5f65c2ef0dfe12fff695960a2ec3d4565359fdbb2e9943c974e06c734ea5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
"cairo-sys-rs",
|
"cairo-sys-rs",
|
||||||
@@ -6719,9 +6886,9 @@ checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wry"
|
name = "wry"
|
||||||
version = "0.53.5"
|
version = "0.54.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "728b7d4c8ec8d81cab295e0b5b8a4c263c0d41a785fb8f8c4df284e5411140a2"
|
checksum = "5ed1a195b0375491dd15a7066a10251be217ce743cf4bbbbdcf5391d6473bee0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
"block2 0.6.2",
|
"block2 0.6.2",
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ crate-type = ["staticlib", "cdylib", "rlib"]
|
|||||||
tauri-build = { version = "2", features = [] }
|
tauri-build = { version = "2", features = [] }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tauri = { version = "2", features = ["macos-private-api", "devtools"] }
|
tauri = { version = "2.9.5", features = ["macos-private-api", "devtools"] }
|
||||||
tauri-plugin-opener = "2"
|
tauri-plugin-opener = "2"
|
||||||
tauri-plugin-deep-link = "2.4.6"
|
tauri-plugin-deep-link = "2.4.6"
|
||||||
tauri-plugin-shell = "2"
|
tauri-plugin-shell = "2"
|
||||||
@@ -43,10 +43,13 @@ reqwest = { version = "0.12", default-features = false, features = ["rustls-tls"
|
|||||||
uuid = { version = "1.19.0", features = ["v4"] }
|
uuid = { version = "1.19.0", features = ["v4"] }
|
||||||
tauri-plugin-decorum = "1.1.1"
|
tauri-plugin-decorum = "1.1.1"
|
||||||
comrak = { version = "0.50", default-features = false }
|
comrak = { version = "0.50", default-features = false }
|
||||||
|
specta = "=2.0.0-rc.22"
|
||||||
|
specta-typescript = "0.0.9"
|
||||||
|
tauri-specta = { version = "=2.0.0-rc.21", features = ["derive", "typescript"] }
|
||||||
|
|
||||||
[target.'cfg(target_os = "linux")'.dependencies]
|
[target.'cfg(target_os = "linux")'.dependencies]
|
||||||
gtk = "0.18.2"
|
gtk = "0.18.2"
|
||||||
webkit2gtk = "=2.0.1"
|
webkit2gtk = "=2.0.2"
|
||||||
|
|
||||||
[target.'cfg(target_os = "macos")'.dependencies]
|
[target.'cfg(target_os = "macos")'.dependencies]
|
||||||
objc2 = "0.6"
|
objc2 = "0.6"
|
||||||
@@ -59,3 +62,10 @@ windows = { version = "0.61", features = [
|
|||||||
"Win32_System_Threading",
|
"Win32_System_Threading",
|
||||||
"Win32_Security"
|
"Win32_Security"
|
||||||
] }
|
] }
|
||||||
|
|
||||||
|
[patch.crates-io]
|
||||||
|
specta = { git = "https://github.com/specta-rs/specta", rev = "106425eac4964d8ff34d3a02f1612e33117b08bb" }
|
||||||
|
specta-typescript = { git = "https://github.com/specta-rs/specta", rev = "106425eac4964d8ff34d3a02f1612e33117b08bb" }
|
||||||
|
tauri-specta = { git = "https://github.com/specta-rs/tauri-specta", rev = "6720b2848eff9a3e40af54c48d65f6d56b640c0b" }
|
||||||
|
# TODO: https://github.com/tauri-apps/tauri/pull/14812
|
||||||
|
tauri = { git = "https://github.com/tauri-apps/tauri", rev = "4d5d78daf636feaac20c5bc48a6071491c4291ee" }
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ fn is_cli_installed() -> bool {
|
|||||||
const INSTALL_SCRIPT: &str = include_str!("../../../../install");
|
const INSTALL_SCRIPT: &str = include_str!("../../../../install");
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
|
#[specta::specta]
|
||||||
pub fn install_cli(app: tauri::AppHandle) -> Result<String, String> {
|
pub fn install_cli(app: tauri::AppHandle) -> Result<String, String> {
|
||||||
if cfg!(not(unix)) {
|
if cfg!(not(unix)) {
|
||||||
return Err("CLI installation is only supported on macOS & Linux".to_string());
|
return Err("CLI installation is only supported on macOS & Linux".to_string());
|
||||||
|
|||||||
@@ -16,21 +16,26 @@ use std::{
|
|||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
use tauri::{AppHandle, LogicalSize, Manager, RunEvent, State, WebviewWindowBuilder};
|
use tauri::{AppHandle, LogicalSize, Manager, RunEvent, State, WebviewWindowBuilder};
|
||||||
#[cfg(any(target_os = "linux", all(debug_assertions, windows)))]
|
|
||||||
use tauri_plugin_deep_link::DeepLinkExt;
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
use tauri_plugin_decorum::WebviewWindowExt;
|
use tauri_plugin_decorum::WebviewWindowExt;
|
||||||
|
#[cfg(any(target_os = "linux", all(debug_assertions, windows)))]
|
||||||
|
use tauri_plugin_deep_link::DeepLinkExt;
|
||||||
use tauri_plugin_dialog::{DialogExt, MessageDialogButtons, MessageDialogResult};
|
use tauri_plugin_dialog::{DialogExt, MessageDialogButtons, MessageDialogResult};
|
||||||
use tauri_plugin_shell::process::{CommandChild, CommandEvent};
|
use tauri_plugin_shell::process::{CommandChild, CommandEvent};
|
||||||
use tauri_plugin_store::StoreExt;
|
use tauri_plugin_store::StoreExt;
|
||||||
use tokio::sync::oneshot;
|
use tauri_plugin_window_state::{AppHandleExt, StateFlags};
|
||||||
|
use tokio::sync::{mpsc, oneshot};
|
||||||
|
|
||||||
use crate::window_customizer::PinchZoomDisablePlugin;
|
use crate::window_customizer::PinchZoomDisablePlugin;
|
||||||
|
|
||||||
const SETTINGS_STORE: &str = "opencode.settings.dat";
|
const SETTINGS_STORE: &str = "opencode.settings.dat";
|
||||||
const DEFAULT_SERVER_URL_KEY: &str = "defaultServerUrl";
|
const DEFAULT_SERVER_URL_KEY: &str = "defaultServerUrl";
|
||||||
|
|
||||||
#[derive(Clone, serde::Serialize)]
|
fn window_state_flags() -> StateFlags {
|
||||||
|
StateFlags::all() - StateFlags::DECORATIONS
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, serde::Serialize, specta::Type)]
|
||||||
struct ServerReadyData {
|
struct ServerReadyData {
|
||||||
url: String,
|
url: String,
|
||||||
password: Option<String>,
|
password: Option<String>,
|
||||||
@@ -64,6 +69,7 @@ struct LogState(Arc<Mutex<VecDeque<String>>>);
|
|||||||
const MAX_LOG_ENTRIES: usize = 200;
|
const MAX_LOG_ENTRIES: usize = 200;
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
|
#[specta::specta]
|
||||||
fn kill_sidecar(app: AppHandle) {
|
fn kill_sidecar(app: AppHandle) {
|
||||||
let Some(server_state) = app.try_state::<ServerState>() else {
|
let Some(server_state) = app.try_state::<ServerState>() else {
|
||||||
println!("Server not running");
|
println!("Server not running");
|
||||||
@@ -97,6 +103,7 @@ async fn get_logs(app: AppHandle) -> Result<String, String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
|
#[specta::specta]
|
||||||
async fn ensure_server_ready(state: State<'_, ServerState>) -> Result<ServerReadyData, String> {
|
async fn ensure_server_ready(state: State<'_, ServerState>) -> Result<ServerReadyData, String> {
|
||||||
state
|
state
|
||||||
.status
|
.status
|
||||||
@@ -106,6 +113,7 @@ async fn ensure_server_ready(state: State<'_, ServerState>) -> Result<ServerRead
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
|
#[specta::specta]
|
||||||
fn get_default_server_url(app: AppHandle) -> Result<Option<String>, String> {
|
fn get_default_server_url(app: AppHandle) -> Result<Option<String>, String> {
|
||||||
let store = app
|
let store = app
|
||||||
.store(SETTINGS_STORE)
|
.store(SETTINGS_STORE)
|
||||||
@@ -119,6 +127,7 @@ fn get_default_server_url(app: AppHandle) -> Result<Option<String>, String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
|
#[specta::specta]
|
||||||
async fn set_default_server_url(app: AppHandle, url: Option<String>) -> Result<(), String> {
|
async fn set_default_server_url(app: AppHandle, url: Option<String>) -> Result<(), String> {
|
||||||
let store = app
|
let store = app
|
||||||
.store(SETTINGS_STORE)
|
.store(SETTINGS_STORE)
|
||||||
@@ -252,6 +261,26 @@ async fn check_server_health(url: &str, password: Option<&str>) -> bool {
|
|||||||
pub fn run() {
|
pub fn run() {
|
||||||
let updater_enabled = option_env!("TAURI_SIGNING_PRIVATE_KEY").is_some();
|
let updater_enabled = option_env!("TAURI_SIGNING_PRIVATE_KEY").is_some();
|
||||||
|
|
||||||
|
let builder = tauri_specta::Builder::<tauri::Wry>::new()
|
||||||
|
// Then register them (separated by a comma)
|
||||||
|
.commands(tauri_specta::collect_commands![
|
||||||
|
kill_sidecar,
|
||||||
|
install_cli,
|
||||||
|
ensure_server_ready,
|
||||||
|
get_default_server_url,
|
||||||
|
set_default_server_url,
|
||||||
|
markdown::parse_markdown_command
|
||||||
|
])
|
||||||
|
.error_handling(tauri_specta::ErrorHandlingMode::Throw);
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)] // <- Only export on non-release builds
|
||||||
|
builder
|
||||||
|
.export(
|
||||||
|
specta_typescript::Typescript::default(),
|
||||||
|
"../src/bindings.ts",
|
||||||
|
)
|
||||||
|
.expect("Failed to export typescript bindings");
|
||||||
|
|
||||||
#[cfg(all(target_os = "macos", not(debug_assertions)))]
|
#[cfg(all(target_os = "macos", not(debug_assertions)))]
|
||||||
let _ = std::process::Command::new("killall")
|
let _ = std::process::Command::new("killall")
|
||||||
.arg("opencode-cli")
|
.arg("opencode-cli")
|
||||||
@@ -269,10 +298,7 @@ pub fn run() {
|
|||||||
.plugin(tauri_plugin_os::init())
|
.plugin(tauri_plugin_os::init())
|
||||||
.plugin(
|
.plugin(
|
||||||
tauri_plugin_window_state::Builder::new()
|
tauri_plugin_window_state::Builder::new()
|
||||||
.with_state_flags(
|
.with_state_flags(window_state_flags())
|
||||||
tauri_plugin_window_state::StateFlags::all()
|
|
||||||
- tauri_plugin_window_state::StateFlags::DECORATIONS,
|
|
||||||
)
|
|
||||||
.build(),
|
.build(),
|
||||||
)
|
)
|
||||||
.plugin(tauri_plugin_store::Builder::new().build())
|
.plugin(tauri_plugin_store::Builder::new().build())
|
||||||
@@ -285,15 +311,10 @@ pub fn run() {
|
|||||||
.plugin(tauri_plugin_notification::init())
|
.plugin(tauri_plugin_notification::init())
|
||||||
.plugin(PinchZoomDisablePlugin)
|
.plugin(PinchZoomDisablePlugin)
|
||||||
.plugin(tauri_plugin_decorum::init())
|
.plugin(tauri_plugin_decorum::init())
|
||||||
.invoke_handler(tauri::generate_handler![
|
.invoke_handler(builder.invoke_handler())
|
||||||
kill_sidecar,
|
|
||||||
install_cli,
|
|
||||||
ensure_server_ready,
|
|
||||||
get_default_server_url,
|
|
||||||
set_default_server_url,
|
|
||||||
markdown::parse_markdown_command
|
|
||||||
])
|
|
||||||
.setup(move |app| {
|
.setup(move |app| {
|
||||||
|
builder.mount_events(app);
|
||||||
|
|
||||||
#[cfg(any(target_os = "linux", all(debug_assertions, windows)))]
|
#[cfg(any(target_os = "linux", all(debug_assertions, windows)))]
|
||||||
app.deep_link().register_all().ok();
|
app.deep_link().register_all().ok();
|
||||||
|
|
||||||
@@ -346,6 +367,8 @@ pub fn run() {
|
|||||||
|
|
||||||
let window = window_builder.build().expect("Failed to create window");
|
let window = window_builder.build().expect("Failed to create window");
|
||||||
|
|
||||||
|
setup_window_state_listener(&app, &window);
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
let _ = window.create_overlay_titlebar();
|
let _ = window.create_overlay_titlebar();
|
||||||
|
|
||||||
@@ -526,6 +549,7 @@ async fn spawn_local_server(
|
|||||||
let timestamp = Instant::now();
|
let timestamp = Instant::now();
|
||||||
loop {
|
loop {
|
||||||
if timestamp.elapsed() > Duration::from_secs(30) {
|
if timestamp.elapsed() > Duration::from_secs(30) {
|
||||||
|
let _ = child.kill();
|
||||||
break Err(format!(
|
break Err(format!(
|
||||||
"Failed to spawn OpenCode Server. Logs:\n{}",
|
"Failed to spawn OpenCode Server. Logs:\n{}",
|
||||||
get_logs(app.clone()).await.unwrap()
|
get_logs(app.clone()).await.unwrap()
|
||||||
@@ -540,3 +564,35 @@ async fn spawn_local_server(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn setup_window_state_listener(app: &tauri::AppHandle, window: &tauri::WebviewWindow) {
|
||||||
|
let (tx, mut rx) = mpsc::channel::<()>(1);
|
||||||
|
|
||||||
|
window.on_window_event(move |event| {
|
||||||
|
use tauri::WindowEvent;
|
||||||
|
if !matches!(event, WindowEvent::Moved(_) | WindowEvent::Resized(_)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let _ = tx.try_send(());
|
||||||
|
});
|
||||||
|
|
||||||
|
tauri::async_runtime::spawn({
|
||||||
|
let app = app.clone();
|
||||||
|
|
||||||
|
async move {
|
||||||
|
let save = || {
|
||||||
|
let handle = app.clone();
|
||||||
|
let app = app.clone();
|
||||||
|
let _ = handle.run_on_main_thread(move || {
|
||||||
|
let _ = app.save_window_state(window_state_flags());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
while rx.recv().await.is_some() {
|
||||||
|
tokio::time::sleep(Duration::from_millis(200)).await;
|
||||||
|
|
||||||
|
save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
use comrak::{create_formatter, parse_document, Arena, Options, html::ChildRendering, nodes::NodeValue};
|
use comrak::{
|
||||||
|
Arena, Options, create_formatter, html::ChildRendering, nodes::NodeValue, parse_document,
|
||||||
|
};
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
|
||||||
create_formatter!(ExternalLinkFormatter, {
|
create_formatter!(ExternalLinkFormatter, {
|
||||||
@@ -55,6 +57,7 @@ pub fn parse_markdown(input: &str) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
|
#[specta::specta]
|
||||||
pub async fn parse_markdown_command(markdown: String) -> Result<String, String> {
|
pub async fn parse_markdown_command(markdown: String) -> Result<String, String> {
|
||||||
Ok(parse_markdown(&markdown))
|
Ok(parse_markdown(&markdown))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use tauri::{plugin::Plugin, Manager, Runtime, Window};
|
use tauri::{Manager, Runtime, Window, plugin::Plugin};
|
||||||
|
|
||||||
pub struct PinchZoomDisablePlugin;
|
pub struct PinchZoomDisablePlugin;
|
||||||
|
|
||||||
@@ -21,8 +21,8 @@ impl<R: Runtime> Plugin<R> for PinchZoomDisablePlugin {
|
|||||||
let _ = webview_window.with_webview(|_webview| {
|
let _ = webview_window.with_webview(|_webview| {
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
unsafe {
|
unsafe {
|
||||||
use gtk::glib::ObjectExt;
|
|
||||||
use gtk::GestureZoom;
|
use gtk::GestureZoom;
|
||||||
|
use gtk::glib::ObjectExt;
|
||||||
use webkit2gtk::glib::gobject_ffi;
|
use webkit2gtk::glib::gobject_ffi;
|
||||||
|
|
||||||
if let Some(data) = _webview.inner().data::<GestureZoom>("wk-view-zoom-gesture") {
|
if let Some(data) = _webview.inner().data::<GestureZoom>("wk-view-zoom-gesture") {
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
// This file has been generated by Tauri Specta. Do not edit this file manually.
|
||||||
|
|
||||||
|
import { invoke as __TAURI_INVOKE, Channel } from "@tauri-apps/api/core"
|
||||||
|
|
||||||
|
/** Commands */
|
||||||
|
export const commands = {
|
||||||
|
killSidecar: () => __TAURI_INVOKE<void>("kill_sidecar"),
|
||||||
|
installCli: () => __TAURI_INVOKE<string>("install_cli"),
|
||||||
|
ensureServerReady: () => __TAURI_INVOKE<ServerReadyData>("ensure_server_ready"),
|
||||||
|
getDefaultServerUrl: () => __TAURI_INVOKE<string | null>("get_default_server_url"),
|
||||||
|
setDefaultServerUrl: (url: string | null) => __TAURI_INVOKE<null>("set_default_server_url", { url }),
|
||||||
|
parseMarkdownCommand: (markdown: string) => __TAURI_INVOKE<string>("parse_markdown_command", { markdown }),
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Types */
|
||||||
|
export type ServerReadyData = {
|
||||||
|
url: string
|
||||||
|
password: string | null
|
||||||
|
}
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
import { invoke } from "@tauri-apps/api/core"
|
|
||||||
import { message } from "@tauri-apps/plugin-dialog"
|
import { message } from "@tauri-apps/plugin-dialog"
|
||||||
|
|
||||||
import { initI18n, t } from "./i18n"
|
import { initI18n, t } from "./i18n"
|
||||||
|
import { commands } from "./bindings"
|
||||||
|
|
||||||
export async function installCli(): Promise<void> {
|
export async function installCli(): Promise<void> {
|
||||||
await initI18n()
|
await initI18n()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const path = await invoke<string>("install_cli")
|
const path = await commands.installCli()
|
||||||
await message(t("desktop.cli.installed.message", { path }), { title: t("desktop.cli.installed.title") })
|
await message(t("desktop.cli.installed.message", { path }), { title: t("desktop.cli.installed.title") })
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
await message(t("desktop.cli.failed.message", { error: String(e) }), { title: t("desktop.cli.failed.title") })
|
await message(t("desktop.cli.failed.message", { error: String(e) }), { title: t("desktop.cli.failed.title") })
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// @refresh reload
|
// @refresh reload
|
||||||
import "./webview-zoom"
|
import { webviewZoom } from "./webview-zoom"
|
||||||
import { render } from "solid-js/web"
|
import { render } from "solid-js/web"
|
||||||
import { AppBaseProviders, AppInterface, PlatformProvider, Platform } from "@opencode-ai/app"
|
import { AppBaseProviders, AppInterface, PlatformProvider, Platform } from "@opencode-ai/app"
|
||||||
import { open, save } from "@tauri-apps/plugin-dialog"
|
import { open, save } from "@tauri-apps/plugin-dialog"
|
||||||
@@ -7,7 +7,6 @@ import { getCurrent, onOpenUrl } from "@tauri-apps/plugin-deep-link"
|
|||||||
import { open as shellOpen } from "@tauri-apps/plugin-shell"
|
import { open as shellOpen } from "@tauri-apps/plugin-shell"
|
||||||
import { type as ostype } from "@tauri-apps/plugin-os"
|
import { type as ostype } from "@tauri-apps/plugin-os"
|
||||||
import { check, Update } from "@tauri-apps/plugin-updater"
|
import { check, Update } from "@tauri-apps/plugin-updater"
|
||||||
import { invoke } from "@tauri-apps/api/core"
|
|
||||||
import { getCurrentWindow } from "@tauri-apps/api/window"
|
import { getCurrentWindow } from "@tauri-apps/api/window"
|
||||||
import { isPermissionGranted, requestPermission } from "@tauri-apps/plugin-notification"
|
import { isPermissionGranted, requestPermission } from "@tauri-apps/plugin-notification"
|
||||||
import { relaunch } from "@tauri-apps/plugin-process"
|
import { relaunch } from "@tauri-apps/plugin-process"
|
||||||
@@ -22,6 +21,7 @@ import { createMenu } from "./menu"
|
|||||||
import { initI18n, t } from "./i18n"
|
import { initI18n, t } from "./i18n"
|
||||||
import pkg from "../package.json"
|
import pkg from "../package.json"
|
||||||
import "./styles.css"
|
import "./styles.css"
|
||||||
|
import { commands } from "./bindings"
|
||||||
|
|
||||||
const root = document.getElementById("root")
|
const root = document.getElementById("root")
|
||||||
if (import.meta.env.DEV && !(root instanceof HTMLElement)) {
|
if (import.meta.env.DEV && !(root instanceof HTMLElement)) {
|
||||||
@@ -274,12 +274,12 @@ const createPlatform = (password: Accessor<string | null>): Platform => ({
|
|||||||
|
|
||||||
update: async () => {
|
update: async () => {
|
||||||
if (!UPDATER_ENABLED || !update) return
|
if (!UPDATER_ENABLED || !update) return
|
||||||
if (ostype() === "windows") await invoke("kill_sidecar").catch(() => undefined)
|
if (ostype() === "windows") await commands.killSidecar().catch(() => undefined)
|
||||||
await update.install().catch(() => undefined)
|
await update.install().catch(() => undefined)
|
||||||
},
|
},
|
||||||
|
|
||||||
restart: async () => {
|
restart: async () => {
|
||||||
await invoke("kill_sidecar").catch(() => undefined)
|
await commands.killSidecar().catch(() => undefined)
|
||||||
await relaunch()
|
await relaunch()
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -335,17 +335,17 @@ const createPlatform = (password: Accessor<string | null>): Platform => ({
|
|||||||
},
|
},
|
||||||
|
|
||||||
getDefaultServerUrl: async () => {
|
getDefaultServerUrl: async () => {
|
||||||
const result = await invoke<string | null>("get_default_server_url").catch(() => null)
|
const result = await commands.getDefaultServerUrl().catch(() => null)
|
||||||
return result
|
return result
|
||||||
},
|
},
|
||||||
|
|
||||||
setDefaultServerUrl: async (url: string | null) => {
|
setDefaultServerUrl: async (url: string | null) => {
|
||||||
await invoke("set_default_server_url", { url })
|
await commands.setDefaultServerUrl(url)
|
||||||
},
|
},
|
||||||
|
|
||||||
parseMarkdown: async (markdown: string) => {
|
parseMarkdown: (markdown: string) => commands.parseMarkdownCommand(markdown),
|
||||||
return invoke<string>("parse_markdown_command", { markdown })
|
|
||||||
},
|
webviewZoom,
|
||||||
})
|
})
|
||||||
|
|
||||||
createMenu()
|
createMenu()
|
||||||
@@ -391,11 +391,7 @@ type ServerReadyData = { url: string; password: string | null }
|
|||||||
|
|
||||||
// Gate component that waits for the server to be ready
|
// Gate component that waits for the server to be ready
|
||||||
function ServerGate(props: { children: (data: Accessor<ServerReadyData>) => JSX.Element }) {
|
function ServerGate(props: { children: (data: Accessor<ServerReadyData>) => JSX.Element }) {
|
||||||
const [serverData] = createResource<ServerReadyData>(() =>
|
const [serverData] = createResource(() => commands.ensureServerReady())
|
||||||
invoke("ensure_server_ready").then((v) => {
|
|
||||||
return new Promise((res) => setTimeout(() => res(v as ServerReadyData), 2000))
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
|
|
||||||
const errorMessage = () => {
|
const errorMessage = () => {
|
||||||
const error = serverData.error
|
const error = serverData.error
|
||||||
@@ -406,7 +402,7 @@ function ServerGate(props: { children: (data: Accessor<ServerReadyData>) => JSX.
|
|||||||
}
|
}
|
||||||
|
|
||||||
const restartApp = async () => {
|
const restartApp = async () => {
|
||||||
await invoke("kill_sidecar").catch(() => undefined)
|
await commands.killSidecar().catch(() => undefined)
|
||||||
await relaunch().catch(() => undefined)
|
await relaunch().catch(() => undefined)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { Menu, MenuItem, PredefinedMenuItem, Submenu } from "@tauri-apps/api/menu"
|
import { Menu, MenuItem, PredefinedMenuItem, Submenu } from "@tauri-apps/api/menu"
|
||||||
import { type as ostype } from "@tauri-apps/plugin-os"
|
import { type as ostype } from "@tauri-apps/plugin-os"
|
||||||
import { invoke } from "@tauri-apps/api/core"
|
|
||||||
import { relaunch } from "@tauri-apps/plugin-process"
|
import { relaunch } from "@tauri-apps/plugin-process"
|
||||||
|
|
||||||
import { runUpdater, UPDATER_ENABLED } from "./updater"
|
import { runUpdater, UPDATER_ENABLED } from "./updater"
|
||||||
import { installCli } from "./cli"
|
import { installCli } from "./cli"
|
||||||
import { initI18n, t } from "./i18n"
|
import { initI18n, t } from "./i18n"
|
||||||
|
import { commands } from "./bindings"
|
||||||
|
|
||||||
export async function createMenu() {
|
export async function createMenu() {
|
||||||
if (ostype() !== "macos") return
|
if (ostype() !== "macos") return
|
||||||
@@ -35,7 +35,7 @@ export async function createMenu() {
|
|||||||
}),
|
}),
|
||||||
await MenuItem.new({
|
await MenuItem.new({
|
||||||
action: async () => {
|
action: async () => {
|
||||||
await invoke("kill_sidecar").catch(() => undefined)
|
await commands.killSidecar().catch(() => undefined)
|
||||||
await relaunch().catch(() => undefined)
|
await relaunch().catch(() => undefined)
|
||||||
},
|
},
|
||||||
text: t("desktop.menu.restart"),
|
text: t("desktop.menu.restart"),
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { check } from "@tauri-apps/plugin-updater"
|
import { check } from "@tauri-apps/plugin-updater"
|
||||||
import { relaunch } from "@tauri-apps/plugin-process"
|
import { relaunch } from "@tauri-apps/plugin-process"
|
||||||
import { ask, message } from "@tauri-apps/plugin-dialog"
|
import { ask, message } from "@tauri-apps/plugin-dialog"
|
||||||
import { invoke } from "@tauri-apps/api/core"
|
|
||||||
import { type as ostype } from "@tauri-apps/plugin-os"
|
import { type as ostype } from "@tauri-apps/plugin-os"
|
||||||
|
|
||||||
import { initI18n, t } from "./i18n"
|
import { initI18n, t } from "./i18n"
|
||||||
|
import { commands } from "./bindings"
|
||||||
|
|
||||||
export const UPDATER_ENABLED = window.__OPENCODE__?.updaterEnabled ?? false
|
export const UPDATER_ENABLED = window.__OPENCODE__?.updaterEnabled ?? false
|
||||||
|
|
||||||
@@ -39,13 +39,13 @@ export async function runUpdater({ alertOnFail }: { alertOnFail: boolean }) {
|
|||||||
if (!shouldUpdate) return
|
if (!shouldUpdate) return
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (ostype() === "windows") await invoke("kill_sidecar")
|
if (ostype() === "windows") await commands.killSidecar()
|
||||||
await update.install()
|
await update.install()
|
||||||
} catch {
|
} catch {
|
||||||
await message(t("desktop.updater.installFailed.message"), { title: t("desktop.updater.installFailed.title") })
|
await message(t("desktop.updater.installFailed.message"), { title: t("desktop.updater.installFailed.title") })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
await invoke("kill_sidecar")
|
await commands.killSidecar()
|
||||||
await relaunch()
|
await relaunch()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,28 +4,34 @@
|
|||||||
|
|
||||||
import { invoke } from "@tauri-apps/api/core"
|
import { invoke } from "@tauri-apps/api/core"
|
||||||
import { type as ostype } from "@tauri-apps/plugin-os"
|
import { type as ostype } from "@tauri-apps/plugin-os"
|
||||||
|
import { createSignal } from "solid-js"
|
||||||
|
|
||||||
const OS_NAME = ostype()
|
const OS_NAME = ostype()
|
||||||
|
|
||||||
let zoomLevel = 1
|
const [webviewZoom, setWebviewZoom] = createSignal(1)
|
||||||
|
|
||||||
const MAX_ZOOM_LEVEL = 10
|
const MAX_ZOOM_LEVEL = 10
|
||||||
const MIN_ZOOM_LEVEL = 0.2
|
const MIN_ZOOM_LEVEL = 0.2
|
||||||
|
|
||||||
|
const clamp = (value: number) => Math.min(Math.max(value, MIN_ZOOM_LEVEL), MAX_ZOOM_LEVEL)
|
||||||
|
|
||||||
|
const applyZoom = (next: number) => {
|
||||||
|
setWebviewZoom(next)
|
||||||
|
invoke("plugin:webview|set_webview_zoom", {
|
||||||
|
value: next,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
window.addEventListener("keydown", (event) => {
|
window.addEventListener("keydown", (event) => {
|
||||||
if (OS_NAME === "macos" ? event.metaKey : event.ctrlKey) {
|
if (!(OS_NAME === "macos" ? event.metaKey : event.ctrlKey)) return
|
||||||
if (event.key === "-") {
|
|
||||||
zoomLevel -= 0.2
|
let newZoom = webviewZoom()
|
||||||
} else if (event.key === "=" || event.key === "+") {
|
|
||||||
zoomLevel += 0.2
|
if (event.key === "-") newZoom -= 0.2
|
||||||
} else if (event.key === "0") {
|
if (event.key === "=" || event.key === "+") newZoom += 0.2
|
||||||
zoomLevel = 1
|
if (event.key === "0") newZoom = 1
|
||||||
} else {
|
|
||||||
return
|
applyZoom(clamp(newZoom))
|
||||||
}
|
|
||||||
zoomLevel = Math.min(Math.max(zoomLevel, MIN_ZOOM_LEVEL), MAX_ZOOM_LEVEL)
|
|
||||||
invoke("plugin:webview|set_webview_zoom", {
|
|
||||||
value: zoomLevel,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export { webviewZoom }
|
||||||
|
|||||||
@@ -82,8 +82,8 @@
|
|||||||
"@opencode-ai/sdk": "workspace:*",
|
"@opencode-ai/sdk": "workspace:*",
|
||||||
"@opencode-ai/util": "workspace:*",
|
"@opencode-ai/util": "workspace:*",
|
||||||
"@openrouter/ai-sdk-provider": "1.5.4",
|
"@openrouter/ai-sdk-provider": "1.5.4",
|
||||||
"@opentui/core": "0.1.75",
|
"@opentui/core": "0.1.77",
|
||||||
"@opentui/solid": "0.1.75",
|
"@opentui/solid": "0.1.77",
|
||||||
"@parcel/watcher": "2.5.1",
|
"@parcel/watcher": "2.5.1",
|
||||||
"@pierre/diffs": "catalog:",
|
"@pierre/diffs": "catalog:",
|
||||||
"@solid-primitives/event-bus": "1.1.2",
|
"@solid-primitives/event-bus": "1.1.2",
|
||||||
|
|||||||
@@ -169,6 +169,7 @@ export function tui(input: {
|
|||||||
gatherStats: false,
|
gatherStats: false,
|
||||||
exitOnCtrlC: false,
|
exitOnCtrlC: false,
|
||||||
useKittyKeyboard: {},
|
useKittyKeyboard: {},
|
||||||
|
autoFocus: false,
|
||||||
consoleOptions: {
|
consoleOptions: {
|
||||||
keyBindings: [{ name: "y", ctrl: true, action: "copy-selection" }],
|
keyBindings: [{ name: "y", ctrl: true, action: "copy-selection" }],
|
||||||
onCopySelection: (text) => {
|
onCopySelection: (text) => {
|
||||||
@@ -186,6 +187,7 @@ function App() {
|
|||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const dimensions = useTerminalDimensions()
|
const dimensions = useTerminalDimensions()
|
||||||
const renderer = useRenderer()
|
const renderer = useRenderer()
|
||||||
|
Clipboard.setRenderer(renderer)
|
||||||
renderer.disableStdoutInterception()
|
renderer.disableStdoutInterception()
|
||||||
const dialog = useDialog()
|
const dialog = useDialog()
|
||||||
const local = useLocal()
|
const local = useLocal()
|
||||||
|
|||||||
@@ -1,24 +1,12 @@
|
|||||||
import { $ } from "bun"
|
import { $ } from "bun"
|
||||||
|
import type { CliRenderer } from "@opentui/core"
|
||||||
import { platform, release } from "os"
|
import { platform, release } from "os"
|
||||||
import clipboardy from "clipboardy"
|
import clipboardy from "clipboardy"
|
||||||
import { lazy } from "../../../../util/lazy.js"
|
import { lazy } from "../../../../util/lazy.js"
|
||||||
import { tmpdir } from "os"
|
import { tmpdir } from "os"
|
||||||
import path from "path"
|
import path from "path"
|
||||||
|
|
||||||
/**
|
const rendererRef = { current: undefined as CliRenderer | undefined }
|
||||||
* Writes text to clipboard via OSC 52 escape sequence.
|
|
||||||
* This allows clipboard operations to work over SSH by having
|
|
||||||
* the terminal emulator handle the clipboard locally.
|
|
||||||
*/
|
|
||||||
function writeOsc52(text: string): void {
|
|
||||||
if (!process.stdout.isTTY) return
|
|
||||||
const base64 = Buffer.from(text).toString("base64")
|
|
||||||
const osc52 = `\x1b]52;c;${base64}\x07`
|
|
||||||
// tmux and screen require DCS passthrough wrapping
|
|
||||||
const passthrough = process.env["TMUX"] || process.env["STY"]
|
|
||||||
const sequence = passthrough ? `\x1bPtmux;\x1b${osc52}\x1b\\` : osc52
|
|
||||||
process.stdout.write(sequence)
|
|
||||||
}
|
|
||||||
|
|
||||||
export namespace Clipboard {
|
export namespace Clipboard {
|
||||||
export interface Content {
|
export interface Content {
|
||||||
@@ -26,6 +14,10 @@ export namespace Clipboard {
|
|||||||
mime: string
|
mime: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function setRenderer(renderer: CliRenderer | undefined): void {
|
||||||
|
rendererRef.current = renderer
|
||||||
|
}
|
||||||
|
|
||||||
export async function read(): Promise<Content | undefined> {
|
export async function read(): Promise<Content | undefined> {
|
||||||
const os = platform()
|
const os = platform()
|
||||||
|
|
||||||
@@ -154,7 +146,11 @@ export namespace Clipboard {
|
|||||||
})
|
})
|
||||||
|
|
||||||
export async function copy(text: string): Promise<void> {
|
export async function copy(text: string): Promise<void> {
|
||||||
writeOsc52(text)
|
const renderer = rendererRef.current
|
||||||
|
if (renderer) {
|
||||||
|
const copied = renderer.copyToClipboardOSC52(text)
|
||||||
|
if (copied) return
|
||||||
|
}
|
||||||
await getCopyMethod()(text)
|
await getCopyMethod()(text)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ export namespace Flag {
|
|||||||
export const OPENCODE_EXPERIMENTAL_LSP_TY = truthy("OPENCODE_EXPERIMENTAL_LSP_TY")
|
export const OPENCODE_EXPERIMENTAL_LSP_TY = truthy("OPENCODE_EXPERIMENTAL_LSP_TY")
|
||||||
export const OPENCODE_EXPERIMENTAL_LSP_TOOL = OPENCODE_EXPERIMENTAL || truthy("OPENCODE_EXPERIMENTAL_LSP_TOOL")
|
export const OPENCODE_EXPERIMENTAL_LSP_TOOL = OPENCODE_EXPERIMENTAL || truthy("OPENCODE_EXPERIMENTAL_LSP_TOOL")
|
||||||
export const OPENCODE_DISABLE_FILETIME_CHECK = truthy("OPENCODE_DISABLE_FILETIME_CHECK")
|
export const OPENCODE_DISABLE_FILETIME_CHECK = truthy("OPENCODE_DISABLE_FILETIME_CHECK")
|
||||||
export const OPENCODE_EXPERIMENTAL_PLAN_MODE = OPENCODE_EXPERIMENTAL || truthy("OPENCODE_EXPERIMENTAL_PLAN_MODE")
|
|
||||||
export const OPENCODE_EXPERIMENTAL_MARKDOWN = truthy("OPENCODE_EXPERIMENTAL_MARKDOWN")
|
export const OPENCODE_EXPERIMENTAL_MARKDOWN = truthy("OPENCODE_EXPERIMENTAL_MARKDOWN")
|
||||||
export const OPENCODE_MODELS_URL = process.env["OPENCODE_MODELS_URL"]
|
export const OPENCODE_MODELS_URL = process.env["OPENCODE_MODELS_URL"]
|
||||||
export const OPENCODE_MODELS_PATH = process.env["OPENCODE_MODELS_PATH"]
|
export const OPENCODE_MODELS_PATH = process.env["OPENCODE_MODELS_PATH"]
|
||||||
|
|||||||
@@ -355,3 +355,12 @@ export const pint: Info = {
|
|||||||
return false
|
return false
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const ormolu: Info = {
|
||||||
|
name: "ormolu",
|
||||||
|
command: ["ormolu", "-i", "$FILE"],
|
||||||
|
extensions: [".hs"],
|
||||||
|
async enabled() {
|
||||||
|
return Bun.which("ormolu") !== null
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|||||||
+1
-6
@@ -18,12 +18,7 @@ export function convertToOpenAICompatibleChatMessages(prompt: LanguageModelV2Pro
|
|||||||
case "system": {
|
case "system": {
|
||||||
messages.push({
|
messages.push({
|
||||||
role: "system",
|
role: "system",
|
||||||
content: [
|
content: content,
|
||||||
{
|
|
||||||
type: "text",
|
|
||||||
text: content,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
...metadata,
|
...metadata,
|
||||||
})
|
})
|
||||||
break
|
break
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import { ProviderTransform } from "../provider/transform"
|
|||||||
import { SystemPrompt } from "./system"
|
import { SystemPrompt } from "./system"
|
||||||
import { InstructionPrompt } from "./instruction"
|
import { InstructionPrompt } from "./instruction"
|
||||||
import { Plugin } from "../plugin"
|
import { Plugin } from "../plugin"
|
||||||
import PROMPT_PLAN from "../session/prompt/plan.txt"
|
|
||||||
import BUILD_SWITCH from "../session/prompt/build-switch.txt"
|
import BUILD_SWITCH from "../session/prompt/build-switch.txt"
|
||||||
import MAX_STEPS from "../session/prompt/max-steps.txt"
|
import MAX_STEPS from "../session/prompt/max-steps.txt"
|
||||||
import { defer } from "../util/defer"
|
import { defer } from "../util/defer"
|
||||||
@@ -1232,33 +1231,6 @@ export namespace SessionPrompt {
|
|||||||
const userMessage = input.messages.findLast((msg) => msg.info.role === "user")
|
const userMessage = input.messages.findLast((msg) => msg.info.role === "user")
|
||||||
if (!userMessage) return input.messages
|
if (!userMessage) return input.messages
|
||||||
|
|
||||||
// Original logic when experimental plan mode is disabled
|
|
||||||
if (!Flag.OPENCODE_EXPERIMENTAL_PLAN_MODE) {
|
|
||||||
if (input.agent.name === "plan") {
|
|
||||||
userMessage.parts.push({
|
|
||||||
id: Identifier.ascending("part"),
|
|
||||||
messageID: userMessage.info.id,
|
|
||||||
sessionID: userMessage.info.sessionID,
|
|
||||||
type: "text",
|
|
||||||
text: PROMPT_PLAN,
|
|
||||||
synthetic: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
const wasPlan = input.messages.some((msg) => msg.info.role === "assistant" && msg.info.agent === "plan")
|
|
||||||
if (wasPlan && input.agent.name === "build") {
|
|
||||||
userMessage.parts.push({
|
|
||||||
id: Identifier.ascending("part"),
|
|
||||||
messageID: userMessage.info.id,
|
|
||||||
sessionID: userMessage.info.sessionID,
|
|
||||||
type: "text",
|
|
||||||
text: BUILD_SWITCH,
|
|
||||||
synthetic: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return input.messages
|
|
||||||
}
|
|
||||||
|
|
||||||
// New plan mode logic when flag is enabled
|
|
||||||
const assistantMessage = input.messages.findLast((msg) => msg.info.role === "assistant")
|
const assistantMessage = input.messages.findLast((msg) => msg.info.role === "assistant")
|
||||||
|
|
||||||
// Switching from plan mode to build mode
|
// Switching from plan mode to build mode
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ export namespace ToolRegistry {
|
|||||||
ApplyPatchTool,
|
ApplyPatchTool,
|
||||||
...(Flag.OPENCODE_EXPERIMENTAL_LSP_TOOL ? [LspTool] : []),
|
...(Flag.OPENCODE_EXPERIMENTAL_LSP_TOOL ? [LspTool] : []),
|
||||||
...(config.experimental?.batch_tool === true ? [BatchTool] : []),
|
...(config.experimental?.batch_tool === true ? [BatchTool] : []),
|
||||||
...(Flag.OPENCODE_EXPERIMENTAL_PLAN_MODE && Flag.OPENCODE_CLIENT === "cli" ? [PlanExitTool, PlanEnterTool] : []),
|
...(Flag.OPENCODE_CLIENT === "cli" ? [PlanExitTool, PlanEnterTool] : []),
|
||||||
...custom,
|
...custom,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,24 @@
|
|||||||
import { convertToOpenAICompatibleChatMessages as convertToCopilotMessages } from "@/provider/sdk/copilot/chat/convert-to-openai-compatible-chat-messages"
|
import { convertToOpenAICompatibleChatMessages as convertToCopilotMessages } from "@/provider/sdk/copilot/chat/convert-to-openai-compatible-chat-messages"
|
||||||
import { describe, test, expect } from "bun:test"
|
import { describe, test, expect } from "bun:test"
|
||||||
|
|
||||||
|
describe("system messages", () => {
|
||||||
|
test("should convert system message content to string", () => {
|
||||||
|
const result = convertToCopilotMessages([
|
||||||
|
{
|
||||||
|
role: "system",
|
||||||
|
content: "You are a helpful assistant with AGENTS.md instructions.",
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
expect(result).toEqual([
|
||||||
|
{
|
||||||
|
role: "system",
|
||||||
|
content: "You are a helpful assistant with AGENTS.md instructions.",
|
||||||
|
},
|
||||||
|
])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe("user messages", () => {
|
describe("user messages", () => {
|
||||||
test("should convert messages with only a text part to a string content", () => {
|
test("should convert messages with only a text part to a string content", () => {
|
||||||
const result = convertToCopilotMessages([
|
const result = convertToCopilotMessages([
|
||||||
|
|||||||
@@ -103,7 +103,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
padding: 4px 4px 6px 4px;
|
padding: 4px 4px 6px 4px;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: start;
|
||||||
border-radius: var(--radius-md);
|
border-radius: var(--radius-md);
|
||||||
background: var(--surface-raised-stronger-non-alpha);
|
background: var(--surface-raised-stronger-non-alpha);
|
||||||
max-height: calc(100vh - 6rem);
|
max-height: calc(100vh - 6rem);
|
||||||
|
|||||||
@@ -610,7 +610,7 @@ export function SessionTurn(
|
|||||||
<Match when={working()}>
|
<Match when={working()}>
|
||||||
<Spinner />
|
<Spinner />
|
||||||
</Match>
|
</Match>
|
||||||
<Match when={true}>
|
<Match when={!props.stepsExpanded}>
|
||||||
<svg
|
<svg
|
||||||
width="10"
|
width="10"
|
||||||
height="10"
|
height="10"
|
||||||
@@ -627,6 +627,23 @@ export function SessionTurn(
|
|||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</Match>
|
</Match>
|
||||||
|
<Match when={props.stepsExpanded}>
|
||||||
|
<svg
|
||||||
|
width="10"
|
||||||
|
height="10"
|
||||||
|
viewBox="0 0 10 10"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
class="text-icon-base"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M8.125 8.125H1.875L5 1.875L8.125 8.125Z"
|
||||||
|
fill="currentColor"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</Match>
|
||||||
</Switch>
|
</Switch>
|
||||||
<Switch>
|
<Switch>
|
||||||
<Match when={retry()}>
|
<Match when={retry()}>
|
||||||
|
|||||||
@@ -17,6 +17,9 @@
|
|||||||
--breakpoint-lg: 64rem;
|
--breakpoint-lg: 64rem;
|
||||||
--breakpoint-xl: 80rem;
|
--breakpoint-xl: 80rem;
|
||||||
--breakpoint-2xl: 96rem;
|
--breakpoint-2xl: 96rem;
|
||||||
|
--breakpoint-3xl: 112rem;
|
||||||
|
--breakpoint-4xl: 128rem;
|
||||||
|
--breakpoint-5xl: 144rem;
|
||||||
|
|
||||||
--container-3xs: 16rem;
|
--container-3xs: 16rem;
|
||||||
--container-2xs: 18rem;
|
--container-2xs: 18rem;
|
||||||
|
|||||||
@@ -18,8 +18,7 @@
|
|||||||
"background-base": "#FFF",
|
"background-base": "#FFF",
|
||||||
"background-weak": "#F8F8F8",
|
"background-weak": "#F8F8F8",
|
||||||
"background-strong": "#F0F0F0",
|
"background-strong": "#F0F0F0",
|
||||||
"background-stronger": "#E8E8E8",
|
"background-stronger": "#FBFBFB",
|
||||||
"border-weak-base": "#E8E8E8",
|
|
||||||
"border-weak-hover": "#E0E0E0",
|
"border-weak-hover": "#E0E0E0",
|
||||||
"border-weak-active": "#D8D8D8",
|
"border-weak-active": "#D8D8D8",
|
||||||
"border-weak-selected": "#D0D0D0",
|
"border-weak-selected": "#D0D0D0",
|
||||||
@@ -41,14 +40,15 @@
|
|||||||
"surface-diff-delete-base": "#f5e8e8",
|
"surface-diff-delete-base": "#f5e8e8",
|
||||||
"surface-diff-hidden-base": "#F0F0F0",
|
"surface-diff-hidden-base": "#F0F0F0",
|
||||||
"text-base": "#101010",
|
"text-base": "#101010",
|
||||||
"text-weak": "#A0A0A0",
|
"text-invert-strong": "var(--smoke-dark-alpha-12)",
|
||||||
|
"text-weak": "#606060",
|
||||||
"text-strong": "#000000",
|
"text-strong": "#000000",
|
||||||
"syntax-string": "#99FFE4",
|
"syntax-string": "#0D5C4F",
|
||||||
"syntax-primitive": "#FF8080",
|
"syntax-primitive": "#B30000",
|
||||||
"syntax-property": "#FFC799",
|
"syntax-property": "#C66C00",
|
||||||
"syntax-type": "#FFC799",
|
"syntax-type": "#9C5C12",
|
||||||
"syntax-constant": "#A0A0A0",
|
"syntax-constant": "#404040",
|
||||||
"syntax-info": "#A0A0A0",
|
"syntax-info": "#606060",
|
||||||
"markdown-heading": "#FFC799",
|
"markdown-heading": "#FFC799",
|
||||||
"markdown-text": "#101010",
|
"markdown-text": "#101010",
|
||||||
"markdown-link": "#FFC799",
|
"markdown-link": "#FFC799",
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ OpenCode comes with several built-in formatters for popular languages and framew
|
|||||||
| shfmt | .sh, .bash | `shfmt` command available |
|
| shfmt | .sh, .bash | `shfmt` command available |
|
||||||
| pint | .php | `laravel/pint` dependency in `composer.json` |
|
| pint | .php | `laravel/pint` dependency in `composer.json` |
|
||||||
| oxfmt (Experimental) | .js, .jsx, .ts, .tsx | `oxfmt` dependency in `package.json` and an [experimental env variable flag](/docs/cli/#experimental) |
|
| oxfmt (Experimental) | .js, .jsx, .ts, .tsx | `oxfmt` dependency in `package.json` and an [experimental env variable flag](/docs/cli/#experimental) |
|
||||||
|
| ormolu | .hs | `ormolu` command available |
|
||||||
|
|
||||||
So if your project has `prettier` in your `package.json`, OpenCode will automatically use it.
|
So if your project has `prettier` in your `package.json`, OpenCode will automatically use it.
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ OpenCode comes with several built-in LSP servers for popular languages:
|
|||||||
| fsharp | .fs, .fsi, .fsx, .fsscript | `.NET SDK` installed |
|
| fsharp | .fs, .fsi, .fsx, .fsscript | `.NET SDK` installed |
|
||||||
| gleam | .gleam | `gleam` command available |
|
| gleam | .gleam | `gleam` command available |
|
||||||
| gopls | .go | `go` command available |
|
| gopls | .go | `go` command available |
|
||||||
|
| hls | .hs, .lhs | `haskell-language-server-wrapper` command available |
|
||||||
| jdtls | .java | `Java SDK (version 21+)` installed |
|
| jdtls | .java | `Java SDK (version 21+)` installed |
|
||||||
| kotlin-ls | .kt, .kts | Auto-installs for Kotlin projects |
|
| kotlin-ls | .kt, .kts | Auto-installs for Kotlin projects |
|
||||||
| lua-ls | .lua | Auto-installs for Lua projects |
|
| lua-ls | .lua | Auto-installs for Lua projects |
|
||||||
|
|||||||
Reference in New Issue
Block a user