mirror of
https://github.com/aljazceru/opencode.git
synced 2025-12-21 17:54:23 +01:00
Merge branch 'dev' of https://github.com/sst/opencode into dev
This commit is contained in:
1
STATS.md
1
STATS.md
@@ -87,3 +87,4 @@
|
|||||||
| 2025-09-20 | 372,092 (+6,691) | 276,917 (+5,058) | 649,009 (+11,749) |
|
| 2025-09-20 | 372,092 (+6,691) | 276,917 (+5,058) | 649,009 (+11,749) |
|
||||||
| 2025-09-21 | 377,079 (+4,987) | 280,261 (+3,344) | 657,340 (+8,331) |
|
| 2025-09-21 | 377,079 (+4,987) | 280,261 (+3,344) | 657,340 (+8,331) |
|
||||||
| 2025-09-22 | 382,492 (+5,413) | 284,009 (+3,748) | 666,501 (+9,161) |
|
| 2025-09-22 | 382,492 (+5,413) | 284,009 (+3,748) | 666,501 (+9,161) |
|
||||||
|
| 2025-09-23 | 387,008 (+4,516) | 289,129 (+5,120) | 676,137 (+9,636) |
|
||||||
|
|||||||
3
bun.lock
3
bun.lock
@@ -19,6 +19,7 @@
|
|||||||
"@kobalte/core": "0.13.11",
|
"@kobalte/core": "0.13.11",
|
||||||
"@opencode-ai/sdk": "workspace:*",
|
"@opencode-ai/sdk": "workspace:*",
|
||||||
"@shikijs/transformers": "3.9.2",
|
"@shikijs/transformers": "3.9.2",
|
||||||
|
"@solid-primitives/event-bus": "1.1.2",
|
||||||
"@solid-primitives/resize-observer": "2.1.3",
|
"@solid-primitives/resize-observer": "2.1.3",
|
||||||
"@solid-primitives/scroll": "2.1.3",
|
"@solid-primitives/scroll": "2.1.3",
|
||||||
"@solidjs/router": "0.15.3",
|
"@solidjs/router": "0.15.3",
|
||||||
@@ -996,6 +997,8 @@
|
|||||||
|
|
||||||
"@smithy/util-utf8": ["@smithy/util-utf8@4.1.0", "", { "dependencies": { "@smithy/util-buffer-from": "^4.1.0", "tslib": "^2.6.2" } }, "sha512-mEu1/UIXAdNYuBcyEPbjScKi/+MQVXNIuY/7Cm5XLIWe319kDrT5SizBE95jqtmEXoDbGoZxKLCMttdZdqTZKQ=="],
|
"@smithy/util-utf8": ["@smithy/util-utf8@4.1.0", "", { "dependencies": { "@smithy/util-buffer-from": "^4.1.0", "tslib": "^2.6.2" } }, "sha512-mEu1/UIXAdNYuBcyEPbjScKi/+MQVXNIuY/7Cm5XLIWe319kDrT5SizBE95jqtmEXoDbGoZxKLCMttdZdqTZKQ=="],
|
||||||
|
|
||||||
|
"@solid-primitives/event-bus": ["@solid-primitives/event-bus@1.1.2", "", { "dependencies": { "@solid-primitives/utils": "^6.3.2" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-l+n10/51neGcMaP3ypYt21bXfoeWh8IaC8k7fYuY3ww2a8S1Zv2N2a7FF5Qn+waTu86l0V8/nRHjkyqVIZBYwA=="],
|
||||||
|
|
||||||
"@solid-primitives/event-listener": ["@solid-primitives/event-listener@2.4.3", "", { "dependencies": { "@solid-primitives/utils": "^6.3.2" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-h4VqkYFv6Gf+L7SQj+Y6puigL/5DIi7x5q07VZET7AWcS+9/G3WfIE9WheniHWJs51OEkRB43w6lDys5YeFceg=="],
|
"@solid-primitives/event-listener": ["@solid-primitives/event-listener@2.4.3", "", { "dependencies": { "@solid-primitives/utils": "^6.3.2" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-h4VqkYFv6Gf+L7SQj+Y6puigL/5DIi7x5q07VZET7AWcS+9/G3WfIE9WheniHWJs51OEkRB43w6lDys5YeFceg=="],
|
||||||
|
|
||||||
"@solid-primitives/keyed": ["@solid-primitives/keyed@1.5.2", "", { "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-BgoEdqPw48URnI+L5sZIHdF4ua4Las1eWEBBPaoSFs42kkhnHue+rwCBPL2Z9ebOyQ75sUhUfOETdJfmv0D6Kg=="],
|
"@solid-primitives/keyed": ["@solid-primitives/keyed@1.5.2", "", { "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-BgoEdqPw48URnI+L5sZIHdF4ua4Las1eWEBBPaoSFs42kkhnHue+rwCBPL2Z9ebOyQ75sUhUfOETdJfmv0D6Kg=="],
|
||||||
|
|||||||
1
packages/app/.gitignore
vendored
Normal file
1
packages/app/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
src/assets/theme.css
|
||||||
@@ -24,6 +24,7 @@
|
|||||||
"@kobalte/core": "0.13.11",
|
"@kobalte/core": "0.13.11",
|
||||||
"@opencode-ai/sdk": "workspace:*",
|
"@opencode-ai/sdk": "workspace:*",
|
||||||
"@shikijs/transformers": "3.9.2",
|
"@shikijs/transformers": "3.9.2",
|
||||||
|
"@solid-primitives/event-bus": "1.1.2",
|
||||||
"@solid-primitives/resize-observer": "2.1.3",
|
"@solid-primitives/resize-observer": "2.1.3",
|
||||||
"@solid-primitives/scroll": "2.1.3",
|
"@solid-primitives/scroll": "2.1.3",
|
||||||
"@solidjs/router": "0.15.3",
|
"@solidjs/router": "0.15.3",
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ class ColorResolver {
|
|||||||
if (typeof value === "string") {
|
if (typeof value === "string") {
|
||||||
if (value === "none") return { dark: value, light: value }
|
if (value === "none") return { dark: value, light: value }
|
||||||
if (value.startsWith("#")) {
|
if (value.startsWith("#")) {
|
||||||
return { dark: value.toUpperCase(), light: value.toUpperCase() }
|
return { dark: value.toLowerCase(), light: value.toLowerCase() }
|
||||||
}
|
}
|
||||||
const resolved = this.resolveReference(value)
|
const resolved = this.resolveReference(value)
|
||||||
return { dark: resolved, light: resolved }
|
return { dark: resolved, light: resolved }
|
||||||
@@ -57,7 +57,7 @@ class ColorResolver {
|
|||||||
if (typeof value === "string") {
|
if (typeof value === "string") {
|
||||||
if (value === "none") return value
|
if (value === "none") return value
|
||||||
if (value.startsWith("#")) {
|
if (value.startsWith("#")) {
|
||||||
return value.toUpperCase()
|
return value.toLowerCase()
|
||||||
}
|
}
|
||||||
return this.resolveReference(value)
|
return this.resolveReference(value)
|
||||||
}
|
}
|
||||||
@@ -72,7 +72,7 @@ class ColorResolver {
|
|||||||
if (typeof colorValue === "string") {
|
if (typeof colorValue === "string") {
|
||||||
if (colorValue === "none") return colorValue
|
if (colorValue === "none") return colorValue
|
||||||
if (colorValue.startsWith("#")) {
|
if (colorValue.startsWith("#")) {
|
||||||
return colorValue.toUpperCase()
|
return colorValue.toLowerCase()
|
||||||
}
|
}
|
||||||
return this.resolveReference(colorValue)
|
return this.resolveReference(colorValue)
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,584 +1,6 @@
|
|||||||
import { transformerNotationDiff } from "@shikijs/transformers"
|
import { useMarked } from "@/context"
|
||||||
import { marked } from "marked"
|
|
||||||
import markedShiki from "marked-shiki"
|
|
||||||
import { codeToHtml } from "shiki"
|
|
||||||
import { createResource } from "solid-js"
|
import { createResource } from "solid-js"
|
||||||
|
|
||||||
const markedWithShiki = marked.use(
|
|
||||||
markedShiki({
|
|
||||||
highlight(code, lang) {
|
|
||||||
return codeToHtml(code, {
|
|
||||||
// structure: "inline",
|
|
||||||
lang: lang || "text",
|
|
||||||
tabindex: false,
|
|
||||||
theme: {
|
|
||||||
colors: {
|
|
||||||
"actionBar.toggledBackground": "var(--theme-background-element)",
|
|
||||||
"activityBarBadge.background": "var(--theme-accent)",
|
|
||||||
"checkbox.border": "var(--theme-border)",
|
|
||||||
"editor.background": "transparent",
|
|
||||||
"editor.foreground": "var(--theme-text)",
|
|
||||||
"editor.inactiveSelectionBackground": "var(--theme-background-element)",
|
|
||||||
"editor.selectionHighlightBackground": "var(--theme-border-active)",
|
|
||||||
"editorIndentGuide.activeBackground1": "var(--theme-border-subtle)",
|
|
||||||
"editorIndentGuide.background1": "var(--theme-border-subtle)",
|
|
||||||
"input.placeholderForeground": "var(--theme-text-muted)",
|
|
||||||
"list.activeSelectionIconForeground": "var(--theme-text)",
|
|
||||||
"list.dropBackground": "var(--theme-background-element)",
|
|
||||||
"menu.background": "var(--theme-background-panel)",
|
|
||||||
"menu.border": "var(--theme-border)",
|
|
||||||
"menu.foreground": "var(--theme-text)",
|
|
||||||
"menu.selectionBackground": "var(--theme-primary)",
|
|
||||||
"menu.separatorBackground": "var(--theme-border)",
|
|
||||||
"ports.iconRunningProcessForeground": "var(--theme-success)",
|
|
||||||
"sideBarSectionHeader.background": "transparent",
|
|
||||||
"sideBarSectionHeader.border": "var(--theme-border-subtle)",
|
|
||||||
"sideBarTitle.foreground": "var(--theme-text-muted)",
|
|
||||||
"statusBarItem.remoteBackground": "var(--theme-success)",
|
|
||||||
"statusBarItem.remoteForeground": "var(--theme-text)",
|
|
||||||
"tab.lastPinnedBorder": "var(--theme-border-subtle)",
|
|
||||||
"tab.selectedBackground": "var(--theme-background-element)",
|
|
||||||
"tab.selectedForeground": "var(--theme-text-muted)",
|
|
||||||
"terminal.inactiveSelectionBackground": "var(--theme-background-element)",
|
|
||||||
"widget.border": "var(--theme-border)",
|
|
||||||
},
|
|
||||||
displayName: "opencode",
|
|
||||||
name: "opencode",
|
|
||||||
semanticHighlighting: true,
|
|
||||||
semanticTokenColors: {
|
|
||||||
customLiteral: "var(--theme-syntax-function)",
|
|
||||||
newOperator: "var(--theme-syntax-operator)",
|
|
||||||
numberLiteral: "var(--theme-syntax-number)",
|
|
||||||
stringLiteral: "var(--theme-syntax-string)",
|
|
||||||
},
|
|
||||||
tokenColors: [
|
|
||||||
{
|
|
||||||
scope: [
|
|
||||||
"meta.embedded",
|
|
||||||
"source.groovy.embedded",
|
|
||||||
"string meta.image.inline.markdown",
|
|
||||||
"variable.legacy.builtin.python",
|
|
||||||
],
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-text)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: "emphasis",
|
|
||||||
settings: {
|
|
||||||
fontStyle: "italic",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: "strong",
|
|
||||||
settings: {
|
|
||||||
fontStyle: "bold",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: "header",
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-markdown-heading)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: "comment",
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-comment)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: "constant.language",
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-keyword)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: [
|
|
||||||
"constant.numeric",
|
|
||||||
"variable.other.enummember",
|
|
||||||
"keyword.operator.plus.exponent",
|
|
||||||
"keyword.operator.minus.exponent",
|
|
||||||
],
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-number)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: "constant.regexp",
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-operator)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: "entity.name.tag",
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-keyword)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: ["entity.name.tag.css", "entity.name.tag.less"],
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-operator)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: "entity.other.attribute-name",
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-variable)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: [
|
|
||||||
"entity.other.attribute-name.class.css",
|
|
||||||
"source.css entity.other.attribute-name.class",
|
|
||||||
"entity.other.attribute-name.id.css",
|
|
||||||
"entity.other.attribute-name.parent-selector.css",
|
|
||||||
"entity.other.attribute-name.parent.less",
|
|
||||||
"source.css entity.other.attribute-name.pseudo-class",
|
|
||||||
"entity.other.attribute-name.pseudo-element.css",
|
|
||||||
"source.css.less entity.other.attribute-name.id",
|
|
||||||
"entity.other.attribute-name.scss",
|
|
||||||
],
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-operator)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: "invalid",
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-error)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: "markup.underline",
|
|
||||||
settings: {
|
|
||||||
fontStyle: "underline",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: "markup.bold",
|
|
||||||
settings: {
|
|
||||||
fontStyle: "bold",
|
|
||||||
foreground: "var(--theme-markdown-strong)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: "markup.heading",
|
|
||||||
settings: {
|
|
||||||
fontStyle: "bold",
|
|
||||||
foreground: "var(--theme-markdown-heading)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: "markup.italic",
|
|
||||||
settings: {
|
|
||||||
fontStyle: "italic",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: "markup.strikethrough",
|
|
||||||
settings: {
|
|
||||||
fontStyle: "strikethrough",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: "markup.inserted",
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-diff-added)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: "markup.deleted",
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-diff-removed)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: "markup.changed",
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-diff-context)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: "punctuation.definition.quote.begin.markdown",
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-markdown-block-quote)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: "punctuation.definition.list.begin.markdown",
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-markdown-list-enumeration)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: "markup.inline.raw",
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-markdown-code)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: "punctuation.definition.tag",
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-punctuation)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: ["meta.preprocessor", "entity.name.function.preprocessor"],
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-keyword)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: "meta.preprocessor.string",
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-string)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: "meta.preprocessor.numeric",
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-number)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: "meta.structure.dictionary.key.python",
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-variable)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: "meta.diff.header",
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-diff-hunk-header)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: "storage",
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-keyword)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: "storage.type",
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-keyword)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: ["storage.modifier", "keyword.operator.noexcept"],
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-keyword)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: ["string", "meta.embedded.assembly"],
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-string)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: "string.tag",
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-string)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: "string.value",
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-string)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: "string.regexp",
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-operator)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: [
|
|
||||||
"punctuation.definition.template-expression.begin",
|
|
||||||
"punctuation.definition.template-expression.end",
|
|
||||||
"punctuation.section.embedded",
|
|
||||||
],
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-keyword)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: ["meta.template.expression"],
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-text)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: [
|
|
||||||
"support.type.vendored.property-name",
|
|
||||||
"support.type.property-name",
|
|
||||||
"source.css variable",
|
|
||||||
"source.coffee.embedded",
|
|
||||||
],
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-variable)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: "keyword",
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-keyword)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: "keyword.control",
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-keyword)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: "keyword.operator",
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-operator)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: [
|
|
||||||
"keyword.operator.new",
|
|
||||||
"keyword.operator.expression",
|
|
||||||
"keyword.operator.cast",
|
|
||||||
"keyword.operator.sizeof",
|
|
||||||
"keyword.operator.alignof",
|
|
||||||
"keyword.operator.typeid",
|
|
||||||
"keyword.operator.alignas",
|
|
||||||
"keyword.operator.instanceof",
|
|
||||||
"keyword.operator.logical.python",
|
|
||||||
"keyword.operator.wordlike",
|
|
||||||
],
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-keyword)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: "keyword.other.unit",
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-number)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: ["punctuation.section.embedded.begin.php", "punctuation.section.embedded.end.php"],
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-keyword)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: "support.function.git-rebase",
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-variable)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: "constant.sha.git-rebase",
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-number)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: [
|
|
||||||
"storage.modifier.import.java",
|
|
||||||
"variable.language.wildcard.java",
|
|
||||||
"storage.modifier.package.java",
|
|
||||||
],
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-text)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: "variable.language",
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-keyword)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: [
|
|
||||||
"entity.name.function",
|
|
||||||
"support.function",
|
|
||||||
"support.constant.handlebars",
|
|
||||||
"source.powershell variable.other.member",
|
|
||||||
"entity.name.operator.custom-literal",
|
|
||||||
],
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-function)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: [
|
|
||||||
"support.class",
|
|
||||||
"support.type",
|
|
||||||
"entity.name.type",
|
|
||||||
"entity.name.namespace",
|
|
||||||
"entity.other.attribute",
|
|
||||||
"entity.name.scope-resolution",
|
|
||||||
"entity.name.class",
|
|
||||||
"storage.type.numeric.go",
|
|
||||||
"storage.type.byte.go",
|
|
||||||
"storage.type.boolean.go",
|
|
||||||
"storage.type.string.go",
|
|
||||||
"storage.type.uintptr.go",
|
|
||||||
"storage.type.error.go",
|
|
||||||
"storage.type.rune.go",
|
|
||||||
"storage.type.cs",
|
|
||||||
"storage.type.generic.cs",
|
|
||||||
"storage.type.modifier.cs",
|
|
||||||
"storage.type.variable.cs",
|
|
||||||
"storage.type.annotation.java",
|
|
||||||
"storage.type.generic.java",
|
|
||||||
"storage.type.java",
|
|
||||||
"storage.type.object.array.java",
|
|
||||||
"storage.type.primitive.array.java",
|
|
||||||
"storage.type.primitive.java",
|
|
||||||
"storage.type.token.java",
|
|
||||||
"storage.type.groovy",
|
|
||||||
"storage.type.annotation.groovy",
|
|
||||||
"storage.type.parameters.groovy",
|
|
||||||
"storage.type.generic.groovy",
|
|
||||||
"storage.type.object.array.groovy",
|
|
||||||
"storage.type.primitive.array.groovy",
|
|
||||||
"storage.type.primitive.groovy",
|
|
||||||
],
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-type)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: [
|
|
||||||
"meta.type.cast.expr",
|
|
||||||
"meta.type.new.expr",
|
|
||||||
"support.constant.math",
|
|
||||||
"support.constant.dom",
|
|
||||||
"support.constant.json",
|
|
||||||
"entity.other.inherited-class",
|
|
||||||
"punctuation.separator.namespace.ruby",
|
|
||||||
],
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-type)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: [
|
|
||||||
"keyword.control",
|
|
||||||
"source.cpp keyword.operator.new",
|
|
||||||
"keyword.operator.delete",
|
|
||||||
"keyword.other.using",
|
|
||||||
"keyword.other.directive.using",
|
|
||||||
"keyword.other.operator",
|
|
||||||
"entity.name.operator",
|
|
||||||
],
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-operator)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: [
|
|
||||||
"variable",
|
|
||||||
"meta.definition.variable.name",
|
|
||||||
"support.variable",
|
|
||||||
"entity.name.variable",
|
|
||||||
"constant.other.placeholder",
|
|
||||||
],
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-variable)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: ["variable.other.constant", "variable.other.enummember"],
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-variable)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: ["meta.object-literal.key"],
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-variable)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: [
|
|
||||||
"support.constant.property-value",
|
|
||||||
"support.constant.font-name",
|
|
||||||
"support.constant.media-type",
|
|
||||||
"support.constant.media",
|
|
||||||
"constant.other.color.rgb-value",
|
|
||||||
"constant.other.rgb-value",
|
|
||||||
"support.constant.color",
|
|
||||||
],
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-string)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: [
|
|
||||||
"punctuation.definition.group.regexp",
|
|
||||||
"punctuation.definition.group.assertion.regexp",
|
|
||||||
"punctuation.definition.character-class.regexp",
|
|
||||||
"punctuation.character.set.begin.regexp",
|
|
||||||
"punctuation.character.set.end.regexp",
|
|
||||||
"keyword.operator.negation.regexp",
|
|
||||||
"support.other.parenthesis.regexp",
|
|
||||||
],
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-string)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: [
|
|
||||||
"constant.character.character-class.regexp",
|
|
||||||
"constant.other.character-class.set.regexp",
|
|
||||||
"constant.other.character-class.regexp",
|
|
||||||
"constant.character.set.regexp",
|
|
||||||
],
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-operator)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: ["keyword.operator.or.regexp", "keyword.control.anchor.regexp"],
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-operator)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: "keyword.operator.quantifier.regexp",
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-operator)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: ["constant.character", "constant.other.option"],
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-keyword)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: "constant.character.escape",
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-syntax-operator)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scope: "entity.name.label",
|
|
||||||
settings: {
|
|
||||||
foreground: "var(--theme-text-muted)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
type: "dark",
|
|
||||||
},
|
|
||||||
transformers: [transformerNotationDiff()],
|
|
||||||
})
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
|
|
||||||
function strip(text: string): string {
|
function strip(text: string): string {
|
||||||
const wrappedRe = /^\s*<([A-Za-z]\w*)>\s*([\s\S]*?)\s*<\/\1>\s*$/
|
const wrappedRe = /^\s*<([A-Za-z]\w*)>\s*([\s\S]*?)\s*<\/\1>\s*$/
|
||||||
const match = text.match(wrappedRe)
|
const match = text.match(wrappedRe)
|
||||||
@@ -586,10 +8,11 @@ function strip(text: string): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function Markdown(props: { text: string; class?: string }) {
|
export default function Markdown(props: { text: string; class?: string }) {
|
||||||
|
const marked = useMarked()
|
||||||
const [html] = createResource(
|
const [html] = createResource(
|
||||||
() => strip(props.text),
|
() => strip(props.text),
|
||||||
async (markdown) => {
|
async (markdown) => {
|
||||||
return markedWithShiki.parse(markdown)
|
return marked.parse(markdown)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
return (
|
return (
|
||||||
|
|||||||
34
packages/app/src/context/event.tsx
Normal file
34
packages/app/src/context/event.tsx
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import { createContext, useContext, type ParentProps } from "solid-js"
|
||||||
|
import { createEventBus } from "@solid-primitives/event-bus"
|
||||||
|
import type { Event as SDKEvent } from "@opencode-ai/sdk"
|
||||||
|
import { useSDK } from "@/context"
|
||||||
|
|
||||||
|
export type Event = SDKEvent // can extend with custom events later
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
const sdk = useSDK()
|
||||||
|
const bus = createEventBus<Event>()
|
||||||
|
sdk.event.subscribe().then(async (events) => {
|
||||||
|
for await (const event of events.stream) {
|
||||||
|
bus.emit(event)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return bus
|
||||||
|
}
|
||||||
|
|
||||||
|
type EventContext = ReturnType<typeof init>
|
||||||
|
|
||||||
|
const ctx = createContext<EventContext>()
|
||||||
|
|
||||||
|
export function EventProvider(props: ParentProps) {
|
||||||
|
const value = init()
|
||||||
|
return <ctx.Provider value={value}>{props.children}</ctx.Provider>
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useEvent() {
|
||||||
|
const value = useContext(ctx)
|
||||||
|
if (!value) {
|
||||||
|
throw new Error("useEvent must be used within a EventProvider")
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
@@ -1,4 +1,7 @@
|
|||||||
|
export { EventProvider, useEvent } from "./event"
|
||||||
export { LocalProvider, useLocal } from "./local"
|
export { LocalProvider, useLocal } from "./local"
|
||||||
|
export { MarkedProvider, useMarked } from "./marked"
|
||||||
export { SDKProvider, useSDK } from "./sdk"
|
export { SDKProvider, useSDK } from "./sdk"
|
||||||
|
export { ShikiProvider, useShiki } from "./shiki"
|
||||||
export { SyncProvider, useSync } from "./sync"
|
export { SyncProvider, useSync } from "./sync"
|
||||||
export { ThemeProvider, useTheme } from "./theme"
|
export { ThemeProvider, useTheme } from "./theme"
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
import { createStore, produce, reconcile } from "solid-js/store"
|
import { createStore, produce, reconcile } from "solid-js/store"
|
||||||
import { batch, createContext, createEffect, createMemo, useContext, type ParentProps } from "solid-js"
|
import { batch, createContext, createEffect, createMemo, useContext, type ParentProps } from "solid-js"
|
||||||
import { useSync } from "./sync"
|
|
||||||
import { uniqueBy } from "remeda"
|
import { uniqueBy } from "remeda"
|
||||||
import type { FileContent, FileNode } from "@opencode-ai/sdk"
|
import type { FileContent, FileNode } from "@opencode-ai/sdk"
|
||||||
import { useSDK } from "./sdk"
|
import { useSDK, useEvent, useSync } from "@/context"
|
||||||
|
|
||||||
export type LocalFile = FileNode &
|
export type LocalFile = FileNode &
|
||||||
Partial<{
|
Partial<{
|
||||||
@@ -165,17 +164,19 @@ function init() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const load = async (path: string) =>
|
const load = async (path: string) => {
|
||||||
sdk.file.read({ query: { path } }).then((x) => {
|
const relative = path.replace(sync.data.path.directory + "/", "")
|
||||||
|
sdk.file.read({ query: { path: relative } }).then((x) => {
|
||||||
setStore(
|
setStore(
|
||||||
"node",
|
"node",
|
||||||
path,
|
relative,
|
||||||
produce((draft) => {
|
produce((draft) => {
|
||||||
draft.loaded = true
|
draft.loaded = true
|
||||||
draft.content = x.data
|
draft.content = x.data
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const open = async (path: string) => {
|
const open = async (path: string) => {
|
||||||
const relative = path.replace(sync.data.path.directory + "/", "")
|
const relative = path.replace(sync.data.path.directory + "/", "")
|
||||||
@@ -213,27 +214,27 @@ function init() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
sdk.event.subscribe().then(async (events) => {
|
const bus = useEvent()
|
||||||
for await (const event of events.stream) {
|
bus.listen((event) => {
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case "message.part.updated":
|
case "message.part.updated":
|
||||||
const part = event.properties.part
|
const part = event.properties.part
|
||||||
if (part.type === "tool" && part.state.status === "completed") {
|
if (part.type === "tool" && part.state.status === "completed") {
|
||||||
switch (part.tool) {
|
switch (part.tool) {
|
||||||
case "read":
|
case "read":
|
||||||
console.log("read", part.state.input)
|
console.log("read", part.state.input)
|
||||||
break
|
break
|
||||||
case "edit":
|
case "edit":
|
||||||
const absolute = part.state.input["filePath"] as string
|
load(part.state.input["filePath"] as string)
|
||||||
const path = absolute.replace(sync.data.path.directory + "/", "")
|
break
|
||||||
load(path)
|
default:
|
||||||
break
|
break
|
||||||
default:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break
|
}
|
||||||
}
|
break
|
||||||
|
case "file.watcher.updated":
|
||||||
|
load(event.properties.file)
|
||||||
|
break
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
40
packages/app/src/context/marked.tsx
Normal file
40
packages/app/src/context/marked.tsx
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import { createContext, useContext, type ParentProps } from "solid-js"
|
||||||
|
import { useShiki } from "@/context"
|
||||||
|
import { marked } from "marked"
|
||||||
|
import markedShiki from "marked-shiki"
|
||||||
|
import type { BundledLanguage } from "shiki"
|
||||||
|
|
||||||
|
function init(highlighter: ReturnType<typeof useShiki>) {
|
||||||
|
return marked.use(
|
||||||
|
markedShiki({
|
||||||
|
async highlight(code, lang) {
|
||||||
|
if (!highlighter.getLoadedLanguages().includes(lang)) {
|
||||||
|
await highlighter.loadLanguage(lang as BundledLanguage)
|
||||||
|
}
|
||||||
|
return highlighter.codeToHtml(code, {
|
||||||
|
lang: lang || "text",
|
||||||
|
theme: "opencode",
|
||||||
|
tabindex: false,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
type MarkedContext = ReturnType<typeof init>
|
||||||
|
|
||||||
|
const ctx = createContext<MarkedContext>()
|
||||||
|
|
||||||
|
export function MarkedProvider(props: ParentProps) {
|
||||||
|
const highlighter = useShiki()
|
||||||
|
const value = init(highlighter)
|
||||||
|
return <ctx.Provider value={value}>{props.children}</ctx.Provider>
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useMarked() {
|
||||||
|
const value = useContext(ctx)
|
||||||
|
if (!value) {
|
||||||
|
throw new Error("useMarked must be used within a MarkedProvider")
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
582
packages/app/src/context/shiki.tsx
Normal file
582
packages/app/src/context/shiki.tsx
Normal file
@@ -0,0 +1,582 @@
|
|||||||
|
import { createHighlighter, type ThemeInput } from "shiki"
|
||||||
|
import { createContext, useContext, type ParentProps } from "solid-js"
|
||||||
|
|
||||||
|
const theme: ThemeInput = {
|
||||||
|
colors: {
|
||||||
|
"actionBar.toggledBackground": "var(--theme-background-element)",
|
||||||
|
"activityBarBadge.background": "var(--theme-accent)",
|
||||||
|
"checkbox.border": "var(--theme-border)",
|
||||||
|
"editor.background": "transparent",
|
||||||
|
"editor.foreground": "var(--theme-text)",
|
||||||
|
"editor.inactiveSelectionBackground": "var(--theme-background-element)",
|
||||||
|
"editor.selectionHighlightBackground": "var(--theme-border-active)",
|
||||||
|
"editorIndentGuide.activeBackground1": "var(--theme-border-subtle)",
|
||||||
|
"editorIndentGuide.background1": "var(--theme-border-subtle)",
|
||||||
|
"input.placeholderForeground": "var(--theme-text-muted)",
|
||||||
|
"list.activeSelectionIconForeground": "var(--theme-text)",
|
||||||
|
"list.dropBackground": "var(--theme-background-element)",
|
||||||
|
"menu.background": "var(--theme-background-panel)",
|
||||||
|
"menu.border": "var(--theme-border)",
|
||||||
|
"menu.foreground": "var(--theme-text)",
|
||||||
|
"menu.selectionBackground": "var(--theme-primary)",
|
||||||
|
"menu.separatorBackground": "var(--theme-border)",
|
||||||
|
"ports.iconRunningProcessForeground": "var(--theme-success)",
|
||||||
|
"sideBarSectionHeader.background": "transparent",
|
||||||
|
"sideBarSectionHeader.border": "var(--theme-border-subtle)",
|
||||||
|
"sideBarTitle.foreground": "var(--theme-text-muted)",
|
||||||
|
"statusBarItem.remoteBackground": "var(--theme-success)",
|
||||||
|
"statusBarItem.remoteForeground": "var(--theme-text)",
|
||||||
|
"tab.lastPinnedBorder": "var(--theme-border-subtle)",
|
||||||
|
"tab.selectedBackground": "var(--theme-background-element)",
|
||||||
|
"tab.selectedForeground": "var(--theme-text-muted)",
|
||||||
|
"terminal.inactiveSelectionBackground": "var(--theme-background-element)",
|
||||||
|
"widget.border": "var(--theme-border)",
|
||||||
|
},
|
||||||
|
displayName: "opencode",
|
||||||
|
name: "opencode",
|
||||||
|
semanticHighlighting: true,
|
||||||
|
semanticTokenColors: {
|
||||||
|
customLiteral: "var(--theme-syntax-function)",
|
||||||
|
newOperator: "var(--theme-syntax-operator)",
|
||||||
|
numberLiteral: "var(--theme-syntax-number)",
|
||||||
|
stringLiteral: "var(--theme-syntax-string)",
|
||||||
|
},
|
||||||
|
tokenColors: [
|
||||||
|
{
|
||||||
|
scope: [
|
||||||
|
"meta.embedded",
|
||||||
|
"source.groovy.embedded",
|
||||||
|
"string meta.image.inline.markdown",
|
||||||
|
"variable.legacy.builtin.python",
|
||||||
|
],
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-text)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: "emphasis",
|
||||||
|
settings: {
|
||||||
|
fontStyle: "italic",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: "strong",
|
||||||
|
settings: {
|
||||||
|
fontStyle: "bold",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: "header",
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-markdown-heading)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: "comment",
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-comment)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: "constant.language",
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-keyword)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: [
|
||||||
|
"constant.numeric",
|
||||||
|
"variable.other.enummember",
|
||||||
|
"keyword.operator.plus.exponent",
|
||||||
|
"keyword.operator.minus.exponent",
|
||||||
|
],
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-number)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: "constant.regexp",
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-operator)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: "entity.name.tag",
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-keyword)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: ["entity.name.tag.css", "entity.name.tag.less"],
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-operator)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: "entity.other.attribute-name",
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-variable)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: [
|
||||||
|
"entity.other.attribute-name.class.css",
|
||||||
|
"source.css entity.other.attribute-name.class",
|
||||||
|
"entity.other.attribute-name.id.css",
|
||||||
|
"entity.other.attribute-name.parent-selector.css",
|
||||||
|
"entity.other.attribute-name.parent.less",
|
||||||
|
"source.css entity.other.attribute-name.pseudo-class",
|
||||||
|
"entity.other.attribute-name.pseudo-element.css",
|
||||||
|
"source.css.less entity.other.attribute-name.id",
|
||||||
|
"entity.other.attribute-name.scss",
|
||||||
|
],
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-operator)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: "invalid",
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-error)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: "markup.underline",
|
||||||
|
settings: {
|
||||||
|
fontStyle: "underline",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: "markup.bold",
|
||||||
|
settings: {
|
||||||
|
fontStyle: "bold",
|
||||||
|
foreground: "var(--theme-markdown-strong)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: "markup.heading",
|
||||||
|
settings: {
|
||||||
|
fontStyle: "bold",
|
||||||
|
foreground: "var(--theme-markdown-heading)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: "markup.italic",
|
||||||
|
settings: {
|
||||||
|
fontStyle: "italic",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: "markup.strikethrough",
|
||||||
|
settings: {
|
||||||
|
fontStyle: "strikethrough",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: "markup.inserted",
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-diff-added)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: "markup.deleted",
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-diff-removed)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: "markup.changed",
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-diff-context)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: "punctuation.definition.quote.begin.markdown",
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-markdown-block-quote)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: "punctuation.definition.list.begin.markdown",
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-markdown-list-enumeration)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: "markup.inline.raw",
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-markdown-code)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: "punctuation.definition.tag",
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-punctuation)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: ["meta.preprocessor", "entity.name.function.preprocessor"],
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-keyword)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: "meta.preprocessor.string",
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-string)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: "meta.preprocessor.numeric",
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-number)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: "meta.structure.dictionary.key.python",
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-variable)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: "meta.diff.header",
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-diff-hunk-header)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: "storage",
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-keyword)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: "storage.type",
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-keyword)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: ["storage.modifier", "keyword.operator.noexcept"],
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-keyword)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: ["string", "meta.embedded.assembly"],
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-string)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: "string.tag",
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-string)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: "string.value",
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-string)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: "string.regexp",
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-operator)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: [
|
||||||
|
"punctuation.definition.template-expression.begin",
|
||||||
|
"punctuation.definition.template-expression.end",
|
||||||
|
"punctuation.section.embedded",
|
||||||
|
],
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-keyword)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: ["meta.template.expression"],
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-text)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: [
|
||||||
|
"support.type.vendored.property-name",
|
||||||
|
"support.type.property-name",
|
||||||
|
"source.css variable",
|
||||||
|
"source.coffee.embedded",
|
||||||
|
],
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-variable)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: "keyword",
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-keyword)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: "keyword.control",
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-keyword)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: "keyword.operator",
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-operator)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: [
|
||||||
|
"keyword.operator.new",
|
||||||
|
"keyword.operator.expression",
|
||||||
|
"keyword.operator.cast",
|
||||||
|
"keyword.operator.sizeof",
|
||||||
|
"keyword.operator.alignof",
|
||||||
|
"keyword.operator.typeid",
|
||||||
|
"keyword.operator.alignas",
|
||||||
|
"keyword.operator.instanceof",
|
||||||
|
"keyword.operator.logical.python",
|
||||||
|
"keyword.operator.wordlike",
|
||||||
|
],
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-keyword)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: "keyword.other.unit",
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-number)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: ["punctuation.section.embedded.begin.php", "punctuation.section.embedded.end.php"],
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-keyword)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: "support.function.git-rebase",
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-variable)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: "constant.sha.git-rebase",
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-number)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: ["storage.modifier.import.java", "variable.language.wildcard.java", "storage.modifier.package.java"],
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-text)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: "variable.language",
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-keyword)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: [
|
||||||
|
"entity.name.function",
|
||||||
|
"support.function",
|
||||||
|
"support.constant.handlebars",
|
||||||
|
"source.powershell variable.other.member",
|
||||||
|
"entity.name.operator.custom-literal",
|
||||||
|
],
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-function)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: [
|
||||||
|
"support.class",
|
||||||
|
"support.type",
|
||||||
|
"entity.name.type",
|
||||||
|
"entity.name.namespace",
|
||||||
|
"entity.other.attribute",
|
||||||
|
"entity.name.scope-resolution",
|
||||||
|
"entity.name.class",
|
||||||
|
"storage.type.numeric.go",
|
||||||
|
"storage.type.byte.go",
|
||||||
|
"storage.type.boolean.go",
|
||||||
|
"storage.type.string.go",
|
||||||
|
"storage.type.uintptr.go",
|
||||||
|
"storage.type.error.go",
|
||||||
|
"storage.type.rune.go",
|
||||||
|
"storage.type.cs",
|
||||||
|
"storage.type.generic.cs",
|
||||||
|
"storage.type.modifier.cs",
|
||||||
|
"storage.type.variable.cs",
|
||||||
|
"storage.type.annotation.java",
|
||||||
|
"storage.type.generic.java",
|
||||||
|
"storage.type.java",
|
||||||
|
"storage.type.object.array.java",
|
||||||
|
"storage.type.primitive.array.java",
|
||||||
|
"storage.type.primitive.java",
|
||||||
|
"storage.type.token.java",
|
||||||
|
"storage.type.groovy",
|
||||||
|
"storage.type.annotation.groovy",
|
||||||
|
"storage.type.parameters.groovy",
|
||||||
|
"storage.type.generic.groovy",
|
||||||
|
"storage.type.object.array.groovy",
|
||||||
|
"storage.type.primitive.array.groovy",
|
||||||
|
"storage.type.primitive.groovy",
|
||||||
|
],
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-type)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: [
|
||||||
|
"meta.type.cast.expr",
|
||||||
|
"meta.type.new.expr",
|
||||||
|
"support.constant.math",
|
||||||
|
"support.constant.dom",
|
||||||
|
"support.constant.json",
|
||||||
|
"entity.other.inherited-class",
|
||||||
|
"punctuation.separator.namespace.ruby",
|
||||||
|
],
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-type)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: [
|
||||||
|
"keyword.control",
|
||||||
|
"source.cpp keyword.operator.new",
|
||||||
|
"keyword.operator.delete",
|
||||||
|
"keyword.other.using",
|
||||||
|
"keyword.other.directive.using",
|
||||||
|
"keyword.other.operator",
|
||||||
|
"entity.name.operator",
|
||||||
|
],
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-operator)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: [
|
||||||
|
"variable",
|
||||||
|
"meta.definition.variable.name",
|
||||||
|
"support.variable",
|
||||||
|
"entity.name.variable",
|
||||||
|
"constant.other.placeholder",
|
||||||
|
],
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-variable)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: ["variable.other.constant", "variable.other.enummember"],
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-variable)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: ["meta.object-literal.key"],
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-variable)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: [
|
||||||
|
"support.constant.property-value",
|
||||||
|
"support.constant.font-name",
|
||||||
|
"support.constant.media-type",
|
||||||
|
"support.constant.media",
|
||||||
|
"constant.other.color.rgb-value",
|
||||||
|
"constant.other.rgb-value",
|
||||||
|
"support.constant.color",
|
||||||
|
],
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-string)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: [
|
||||||
|
"punctuation.definition.group.regexp",
|
||||||
|
"punctuation.definition.group.assertion.regexp",
|
||||||
|
"punctuation.definition.character-class.regexp",
|
||||||
|
"punctuation.character.set.begin.regexp",
|
||||||
|
"punctuation.character.set.end.regexp",
|
||||||
|
"keyword.operator.negation.regexp",
|
||||||
|
"support.other.parenthesis.regexp",
|
||||||
|
],
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-string)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: [
|
||||||
|
"constant.character.character-class.regexp",
|
||||||
|
"constant.other.character-class.set.regexp",
|
||||||
|
"constant.other.character-class.regexp",
|
||||||
|
"constant.character.set.regexp",
|
||||||
|
],
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-operator)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: ["keyword.operator.or.regexp", "keyword.control.anchor.regexp"],
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-operator)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: "keyword.operator.quantifier.regexp",
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-operator)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: ["constant.character", "constant.other.option"],
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-keyword)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: "constant.character.escape",
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-syntax-operator)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scope: "entity.name.label",
|
||||||
|
settings: {
|
||||||
|
foreground: "var(--theme-text-muted)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
type: "dark",
|
||||||
|
}
|
||||||
|
|
||||||
|
const highlighter = await createHighlighter({
|
||||||
|
themes: [theme],
|
||||||
|
langs: [],
|
||||||
|
})
|
||||||
|
|
||||||
|
type ShikiContext = typeof highlighter
|
||||||
|
|
||||||
|
const ctx = createContext<ShikiContext>()
|
||||||
|
|
||||||
|
export function ShikiProvider(props: ParentProps) {
|
||||||
|
return <ctx.Provider value={highlighter}>{props.children}</ctx.Provider>
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useShiki() {
|
||||||
|
const value = useContext(ctx)
|
||||||
|
if (!value) {
|
||||||
|
throw new Error("useShiki must be used within a ShikiProvider")
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { Message, Agent, Provider, Session, Part, Config, Path, File, FileNode } from "@opencode-ai/sdk"
|
import type { Message, Agent, Provider, Session, Part, Config, Path, File, FileNode } from "@opencode-ai/sdk"
|
||||||
import { createStore, produce, reconcile } from "solid-js/store"
|
import { createStore, produce, reconcile } from "solid-js/store"
|
||||||
import { useSDK } from "./sdk"
|
|
||||||
import { createContext, Show, useContext, type ParentProps } from "solid-js"
|
import { createContext, Show, useContext, type ParentProps } from "solid-js"
|
||||||
|
import { useSDK, useEvent } from "@/context"
|
||||||
import { Binary } from "@/utils/binary"
|
import { Binary } from "@/utils/binary"
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
@@ -33,69 +33,67 @@ function init() {
|
|||||||
changes: [],
|
changes: [],
|
||||||
})
|
})
|
||||||
|
|
||||||
const sdk = useSDK()
|
const bus = useEvent()
|
||||||
|
bus.listen((event) => {
|
||||||
sdk.event.subscribe().then(async (events) => {
|
switch (event.type) {
|
||||||
for await (const event of events.stream) {
|
case "session.updated": {
|
||||||
switch (event.type) {
|
const result = Binary.search(store.session, event.properties.info.id, (s) => s.id)
|
||||||
case "session.updated": {
|
if (result.found) {
|
||||||
const result = Binary.search(store.session, event.properties.info.id, (s) => s.id)
|
setStore("session", result.index, reconcile(event.properties.info))
|
||||||
if (result.found) {
|
|
||||||
setStore("session", result.index, reconcile(event.properties.info))
|
|
||||||
break
|
|
||||||
}
|
|
||||||
setStore(
|
|
||||||
"session",
|
|
||||||
produce((draft) => {
|
|
||||||
draft.splice(result.index, 0, event.properties.info)
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case "message.updated": {
|
setStore(
|
||||||
const messages = store.message[event.properties.info.sessionID]
|
"session",
|
||||||
if (!messages) {
|
produce((draft) => {
|
||||||
setStore("message", event.properties.info.sessionID, [event.properties.info])
|
draft.splice(result.index, 0, event.properties.info)
|
||||||
break
|
}),
|
||||||
}
|
)
|
||||||
const result = Binary.search(messages, event.properties.info.id, (m) => m.id)
|
break
|
||||||
if (result.found) {
|
}
|
||||||
setStore("message", event.properties.info.sessionID, result.index, reconcile(event.properties.info))
|
case "message.updated": {
|
||||||
break
|
const messages = store.message[event.properties.info.sessionID]
|
||||||
}
|
if (!messages) {
|
||||||
setStore(
|
setStore("message", event.properties.info.sessionID, [event.properties.info])
|
||||||
"message",
|
|
||||||
event.properties.info.sessionID,
|
|
||||||
produce((draft) => {
|
|
||||||
draft.splice(result.index, 0, event.properties.info)
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case "message.part.updated": {
|
const result = Binary.search(messages, event.properties.info.id, (m) => m.id)
|
||||||
const parts = store.part[event.properties.part.messageID]
|
if (result.found) {
|
||||||
if (!parts) {
|
setStore("message", event.properties.info.sessionID, result.index, reconcile(event.properties.info))
|
||||||
setStore("part", event.properties.part.messageID, [event.properties.part])
|
|
||||||
break
|
|
||||||
}
|
|
||||||
const result = Binary.search(parts, event.properties.part.id, (p) => p.id)
|
|
||||||
if (result.found) {
|
|
||||||
setStore("part", event.properties.part.messageID, result.index, reconcile(event.properties.part))
|
|
||||||
break
|
|
||||||
}
|
|
||||||
setStore(
|
|
||||||
"part",
|
|
||||||
event.properties.part.messageID,
|
|
||||||
produce((draft) => {
|
|
||||||
draft.splice(result.index, 0, event.properties.part)
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
setStore(
|
||||||
|
"message",
|
||||||
|
event.properties.info.sessionID,
|
||||||
|
produce((draft) => {
|
||||||
|
draft.splice(result.index, 0, event.properties.info)
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case "message.part.updated": {
|
||||||
|
const parts = store.part[event.properties.part.messageID]
|
||||||
|
if (!parts) {
|
||||||
|
setStore("part", event.properties.part.messageID, [event.properties.part])
|
||||||
|
break
|
||||||
|
}
|
||||||
|
const result = Binary.search(parts, event.properties.part.id, (p) => p.id)
|
||||||
|
if (result.found) {
|
||||||
|
setStore("part", event.properties.part.messageID, result.index, reconcile(event.properties.part))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
setStore(
|
||||||
|
"part",
|
||||||
|
event.properties.part.messageID,
|
||||||
|
produce((draft) => {
|
||||||
|
draft.splice(result.index, 0, event.properties.part)
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const sdk = useSDK()
|
||||||
Promise.all([
|
Promise.all([
|
||||||
sdk.config.providers().then((x) => setStore("provider", x.data!.providers)),
|
sdk.config.providers().then((x) => setStore("provider", x.data!.providers)),
|
||||||
sdk.path.get().then((x) => setStore("path", x.data!)),
|
sdk.path.get().then((x) => setStore("path", x.data!)),
|
||||||
|
|||||||
@@ -4,7 +4,15 @@ import { Router, Route } from "@solidjs/router"
|
|||||||
import "@/index.css"
|
import "@/index.css"
|
||||||
import Layout from "@/pages/layout"
|
import Layout from "@/pages/layout"
|
||||||
import Home from "@/pages"
|
import Home from "@/pages"
|
||||||
import { SDKProvider, SyncProvider, LocalProvider, ThemeProvider } from "@/context"
|
import {
|
||||||
|
EventProvider,
|
||||||
|
SDKProvider,
|
||||||
|
SyncProvider,
|
||||||
|
LocalProvider,
|
||||||
|
ThemeProvider,
|
||||||
|
ShikiProvider,
|
||||||
|
MarkedProvider,
|
||||||
|
} from "@/context"
|
||||||
|
|
||||||
const root = document.getElementById("root")
|
const root = document.getElementById("root")
|
||||||
|
|
||||||
@@ -18,15 +26,21 @@ render(
|
|||||||
() => (
|
() => (
|
||||||
<div class="h-full bg-background text-text-muted">
|
<div class="h-full bg-background text-text-muted">
|
||||||
<ThemeProvider defaultTheme="opencode" defaultDarkMode={true}>
|
<ThemeProvider defaultTheme="opencode" defaultDarkMode={true}>
|
||||||
<SDKProvider>
|
<ShikiProvider>
|
||||||
<SyncProvider>
|
<MarkedProvider>
|
||||||
<LocalProvider>
|
<SDKProvider>
|
||||||
<Router root={Layout}>
|
<EventProvider>
|
||||||
<Route path="/" component={Home} />
|
<SyncProvider>
|
||||||
</Router>
|
<LocalProvider>
|
||||||
</LocalProvider>
|
<Router root={Layout}>
|
||||||
</SyncProvider>
|
<Route path="/" component={Home} />
|
||||||
</SDKProvider>
|
</Router>
|
||||||
|
</LocalProvider>
|
||||||
|
</SyncProvider>
|
||||||
|
</EventProvider>
|
||||||
|
</SDKProvider>
|
||||||
|
</MarkedProvider>
|
||||||
|
</ShikiProvider>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { LSP } from "../../../lsp"
|
|||||||
import { bootstrap } from "../../bootstrap"
|
import { bootstrap } from "../../bootstrap"
|
||||||
import { cmd } from "../cmd"
|
import { cmd } from "../cmd"
|
||||||
import { Log } from "../../../util/log"
|
import { Log } from "../../../util/log"
|
||||||
|
import { UI } from "../../ui"
|
||||||
|
|
||||||
export const LSPCommand = cmd({
|
export const LSPCommand = cmd({
|
||||||
command: "lsp",
|
command: "lsp",
|
||||||
@@ -15,6 +16,10 @@ const DiagnosticsCommand = cmd({
|
|||||||
builder: (yargs) => yargs.positional("file", { type: "string", demandOption: true }),
|
builder: (yargs) => yargs.positional("file", { type: "string", demandOption: true }),
|
||||||
async handler(args) {
|
async handler(args) {
|
||||||
await bootstrap(process.cwd(), async () => {
|
await bootstrap(process.cwd(), async () => {
|
||||||
|
if (!(await Bun.file(args.file).exists())) {
|
||||||
|
UI.error(`File ${args.file} does not exist`)
|
||||||
|
return
|
||||||
|
}
|
||||||
await LSP.touchFile(args.file, true)
|
await LSP.touchFile(args.file, true)
|
||||||
console.log(JSON.stringify(await LSP.diagnostics(), null, 2))
|
console.log(JSON.stringify(await LSP.diagnostics(), null, 2))
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ export namespace FileWatcher {
|
|||||||
const ignore = (cfg.watcher?.ignore ?? []).map((v) => new Bun.Glob(v))
|
const ignore = (cfg.watcher?.ignore ?? []).map((v) => new Bun.Glob(v))
|
||||||
const watcher = chokidar.watch(Instance.directory, {
|
const watcher = chokidar.watch(Instance.directory, {
|
||||||
ignoreInitial: true,
|
ignoreInitial: true,
|
||||||
awaitWriteFinish: true,
|
|
||||||
ignored: (filepath) => {
|
ignored: (filepath) => {
|
||||||
return FileIgnore.match(filepath, {
|
return FileIgnore.match(filepath, {
|
||||||
extra: ignore,
|
extra: ignore,
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ export namespace LSP {
|
|||||||
...existing,
|
...existing,
|
||||||
id: name,
|
id: name,
|
||||||
root: existing?.root ?? (async () => Instance.directory),
|
root: existing?.root ?? (async () => Instance.directory),
|
||||||
extensions: item.extensions ?? existing.extensions,
|
extensions: item.extensions ?? existing?.extensions ?? [],
|
||||||
spawn: async (root) => {
|
spawn: async (root) => {
|
||||||
return {
|
return {
|
||||||
process: spawn(item.command[0], item.command.slice(1), {
|
process: spawn(item.command[0], item.command.slice(1), {
|
||||||
|
|||||||
@@ -495,9 +495,7 @@ For quick reference, here are common setups.
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
See the full permissions guide for more patterns.
|
See the full [permissions guide](/docs/permissions) for more patterns.
|
||||||
|
|
||||||
- /docs/permissions
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ title: LSP Servers
|
|||||||
description: opencode integrates with your LSP servers.
|
description: opencode integrates with your LSP servers.
|
||||||
---
|
---
|
||||||
|
|
||||||
opencode integrates with your Language Server Protocol (LSP) to help the LLM interacts with your codebase. It uses diagnostics to provide feedback to the LLM.
|
opencode integrates with your Language Server Protocol (LSP) to help the LLM interact with your codebase. It uses diagnostics to provide feedback to the LLM.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -356,6 +356,8 @@ To use your GitHub Copilot subscription with opencode:
|
|||||||
:::note
|
:::note
|
||||||
Some models might need a [Pro+
|
Some models might need a [Pro+
|
||||||
subscription](https://github.com/features/copilot/plans) to use.
|
subscription](https://github.com/features/copilot/plans) to use.
|
||||||
|
|
||||||
|
Some models need to be manually enabled in your [GitHub Copilot settings](https://docs.github.com/en/copilot/how-tos/use-ai-models/configure-access-to-ai-models#setup-for-individual-use).
|
||||||
:::
|
:::
|
||||||
|
|
||||||
1. Run `opencode auth login` and select GitHub Copilot.
|
1. Run `opencode auth login` and select GitHub Copilot.
|
||||||
|
|||||||
Reference in New Issue
Block a user