mirror of
https://github.com/anomalyco/opencode.git
synced 2026-08-03 08:46:15 -04:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ae4d089c06 | |||
| 5110fbdaf9 | |||
| e6ddb474fc | |||
| 0dc71774ce | |||
| b470466e30 | |||
| d1f9311931 | |||
| 1c58023df9 | |||
| 4e0aa58b7e | |||
| 23ee34b35f |
@@ -45,6 +45,7 @@
|
||||
"zod-openapi": "4.2.4",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ai-sdk/anthropic": "1.2.12",
|
||||
"@tsconfig/bun": "1.0.7",
|
||||
"@types/bun": "latest",
|
||||
"@types/turndown": "5.0.5",
|
||||
@@ -74,7 +75,7 @@
|
||||
"sharp": "0.32.5",
|
||||
"shiki": "3.4.2",
|
||||
"solid-js": "1.9.7",
|
||||
"toolbeam-docs-theme": "0.2.4",
|
||||
"toolbeam-docs-theme": "0.3.0",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "catalog:",
|
||||
@@ -99,6 +100,8 @@
|
||||
"zod": "3.24.2",
|
||||
},
|
||||
"packages": {
|
||||
"@ai-sdk/anthropic": ["@ai-sdk/anthropic@1.2.12", "", { "dependencies": { "@ai-sdk/provider": "1.1.3", "@ai-sdk/provider-utils": "2.2.8" }, "peerDependencies": { "zod": "^3.0.0" } }, "sha512-YSzjlko7JvuiyQFmI9RN1tNZdEiZxc+6xld/0tq/VkJaHpEzGAb1yiNxxvmYVcjvfu/PcvCxAAYXmTYQQ63IHQ=="],
|
||||
|
||||
"@ai-sdk/provider": ["@ai-sdk/provider@1.1.3", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-qZMxYJ0qqX/RfnuIaab+zp8UAeJn/ygXXAffR5I4N0n1IrvA6qBsjc8hXLmBiMV2zoXlifkacF7sEFnYnjBcqg=="],
|
||||
|
||||
"@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@2.2.8", "", { "dependencies": { "@ai-sdk/provider": "1.1.3", "nanoid": "^3.3.8", "secure-json-parse": "^2.7.0" }, "peerDependencies": { "zod": "^3.23.8" } }, "sha512-fqhG+4sCVv8x7nFzYnFo19ryhAa3w096Kmc3hWxMQfW/TubPOmt3A6tYZhl4mUfQWWQMsuSkLrtjlWuXBVSGQA=="],
|
||||
@@ -1491,7 +1494,7 @@
|
||||
|
||||
"token-types": ["token-types@6.0.0", "", { "dependencies": { "@tokenizer/token": "^0.3.0", "ieee754": "^1.2.1" } }, "sha512-lbDrTLVsHhOMljPscd0yitpozq7Ga2M5Cvez5AjGg8GASBjtt6iERCAJ93yommPmz62fb45oFIXHEZ3u9bfJEA=="],
|
||||
|
||||
"toolbeam-docs-theme": ["toolbeam-docs-theme@0.2.4", "", { "peerDependencies": { "@astrojs/starlight": "^0.34.3", "astro": "^5.7.13" } }, "sha512-W5mdbcgRpTBDFyEdcU81USs3MFZoXMInpSznc/AFZCwqz8atk4iBNDIlhvihpGHY54Nf5crKmZwJjxVojkHFvA=="],
|
||||
"toolbeam-docs-theme": ["toolbeam-docs-theme@0.3.0", "", { "peerDependencies": { "@astrojs/starlight": "^0.34.3", "astro": "^5.7.13" } }, "sha512-qlBkKRp8HVYV7p7jaG9lT2lvQY7c8b9czZ0tnsJUrN2TBTtEyFJymCdkhhpZNC9U4oGZ7lLk0glRJHrndWvVsg=="],
|
||||
|
||||
"tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="],
|
||||
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
"@types/turndown": "5.0.5",
|
||||
"@types/yargs": "17.0.33",
|
||||
"typescript": "catalog:",
|
||||
"zod-to-json-schema": "3.24.5"
|
||||
"zod-to-json-schema": "3.24.5",
|
||||
"@ai-sdk/anthropic": "1.2.12"
|
||||
},
|
||||
"dependencies": {
|
||||
"@clack/prompts": "0.11.0",
|
||||
|
||||
@@ -18,6 +18,7 @@ export namespace App {
|
||||
data: z.string(),
|
||||
root: z.string(),
|
||||
cwd: z.string(),
|
||||
state: z.string(),
|
||||
}),
|
||||
time: z.object({
|
||||
initialized: z.number().optional(),
|
||||
@@ -68,6 +69,7 @@ export namespace App {
|
||||
git: git !== undefined,
|
||||
path: {
|
||||
config: Global.Path.config,
|
||||
state: Global.Path.state,
|
||||
data,
|
||||
root: git ?? input.cwd,
|
||||
cwd: input.cwd,
|
||||
|
||||
@@ -48,6 +48,7 @@ export namespace AuthAnthropic {
|
||||
await Auth.set("anthropic", {
|
||||
type: "oauth",
|
||||
refresh: json.refresh_token as string,
|
||||
access: json.access_token as string,
|
||||
expires: Date.now() + json.expires_in * 1000,
|
||||
})
|
||||
}
|
||||
@@ -55,6 +56,7 @@ export namespace AuthAnthropic {
|
||||
export async function access() {
|
||||
const info = await Auth.get("anthropic")
|
||||
if (!info || info.type !== "oauth") return
|
||||
if (info.access && info.expires > Date.now()) return info.access
|
||||
const response = await fetch(
|
||||
"https://console.anthropic.com/v1/oauth/token",
|
||||
{
|
||||
@@ -74,6 +76,7 @@ export namespace AuthAnthropic {
|
||||
await Auth.set("anthropic", {
|
||||
type: "oauth",
|
||||
refresh: json.refresh_token as string,
|
||||
access: json.access_token as string,
|
||||
expires: Date.now() + json.expires_in * 1000,
|
||||
})
|
||||
return json.access_token as string
|
||||
|
||||
@@ -7,6 +7,7 @@ export namespace Auth {
|
||||
export const Oauth = z.object({
|
||||
type: z.literal("oauth"),
|
||||
refresh: z.string(),
|
||||
access: z.string(),
|
||||
expires: z.number(),
|
||||
})
|
||||
|
||||
|
||||
@@ -5,10 +5,10 @@ import path from "path"
|
||||
|
||||
export namespace GlobalConfig {
|
||||
export const Info = z.object({
|
||||
autoupdate: z.boolean().optional(),
|
||||
autoshare: z.boolean().optional(),
|
||||
provider: z.string().optional(),
|
||||
model: z.string().optional(),
|
||||
autoupdate: z.boolean().optional(),
|
||||
autoshare: z.boolean().optional(),
|
||||
disabled_providers: z.array(z.string()).optional(),
|
||||
})
|
||||
export type Info = z.infer<typeof Info>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import fs from "fs/promises"
|
||||
import { xdgData, xdgCache, xdgConfig } from "xdg-basedir"
|
||||
import { xdgData, xdgCache, xdgConfig, xdgState } from "xdg-basedir"
|
||||
import path from "path"
|
||||
|
||||
const app = "opencode"
|
||||
@@ -7,6 +7,7 @@ const app = "opencode"
|
||||
const data = path.join(xdgData!, app)
|
||||
const cache = path.join(xdgCache!, app)
|
||||
const config = path.join(xdgConfig!, app)
|
||||
const state = path.join(xdgState!, app)
|
||||
|
||||
export namespace Global {
|
||||
export const Path = {
|
||||
@@ -15,12 +16,14 @@ export namespace Global {
|
||||
providers: path.join(config, "providers"),
|
||||
cache,
|
||||
config,
|
||||
state,
|
||||
} as const
|
||||
}
|
||||
|
||||
await Promise.all([
|
||||
fs.mkdir(data, { recursive: true }),
|
||||
fs.mkdir(config, { recursive: true }),
|
||||
fs.mkdir(cache, { recursive: true }),
|
||||
fs.mkdir(Global.Path.data, { recursive: true }),
|
||||
fs.mkdir(Global.Path.config, { recursive: true }),
|
||||
fs.mkdir(Global.Path.cache, { recursive: true }),
|
||||
fs.mkdir(Global.Path.providers, { recursive: true }),
|
||||
fs.mkdir(Global.Path.state, { recursive: true }),
|
||||
])
|
||||
|
||||
@@ -127,14 +127,13 @@ const cli = yargs(hideBin(process.argv))
|
||||
) {
|
||||
cli.showHelp("log")
|
||||
}
|
||||
Log.Default.error(msg, {
|
||||
err,
|
||||
})
|
||||
})
|
||||
.strict()
|
||||
|
||||
try {
|
||||
await cli.parse()
|
||||
} catch (e) {
|
||||
Log.Default.error(e)
|
||||
Log.Default.error(e, {
|
||||
stack: e instanceof Error ? e.stack : undefined,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@ export namespace ModelsDev {
|
||||
cost: z.object({
|
||||
input: z.number(),
|
||||
output: z.number(),
|
||||
inputCached: z.number(),
|
||||
outputCached: z.number(),
|
||||
cache_read: z.number().optional(),
|
||||
cache_write: z.number().optional(),
|
||||
}),
|
||||
limit: z.object({
|
||||
context: z.number(),
|
||||
@@ -64,30 +64,4 @@ export namespace ModelsDev {
|
||||
throw new Error(`Failed to fetch models.dev: ${result.statusText}`)
|
||||
await Bun.write(file, result)
|
||||
}
|
||||
|
||||
const aisdk = lazy(async () => {
|
||||
log.info("fetching ai-sdk")
|
||||
const response = await fetch(
|
||||
"https://registry.npmjs.org/-/v1/search?text=scope:@ai-sdk",
|
||||
)
|
||||
if (!response.ok)
|
||||
throw new Error(
|
||||
`Failed to fetch ai-sdk information: ${response.statusText}`,
|
||||
)
|
||||
const result = await response.json()
|
||||
log.info("found ai-sdk", result.objects.length)
|
||||
return result.objects
|
||||
.filter((obj: any) => obj.package.name.startsWith("@ai-sdk/"))
|
||||
.reduce((acc: any, obj: any) => {
|
||||
acc[obj.package.name] = obj
|
||||
return acc
|
||||
}, {})
|
||||
})
|
||||
|
||||
export async function pkg(providerID: string): Promise<[string, string]> {
|
||||
const packages = await aisdk()
|
||||
const match = packages[`@ai-sdk/${providerID}`]
|
||||
if (match) return [match.package.name, "latest"]
|
||||
return [providerID, "latest"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,16 +43,23 @@ export namespace Provider {
|
||||
for (const model of Object.values(provider.models)) {
|
||||
model.cost = {
|
||||
input: 0,
|
||||
inputCached: 0,
|
||||
output: 0,
|
||||
outputCached: 0,
|
||||
}
|
||||
}
|
||||
return {
|
||||
apiKey: "",
|
||||
headers: {
|
||||
authorization: `Bearer ${access}`,
|
||||
"anthropic-beta": "oauth-2025-04-20",
|
||||
async fetch(input: any, init: any) {
|
||||
const access = await AuthAnthropic.access()
|
||||
const headers = {
|
||||
...init.headers,
|
||||
authorization: `Bearer ${access}`,
|
||||
"anthropic-beta": "oauth-2025-04-20",
|
||||
}
|
||||
delete headers["x-api-key"]
|
||||
return fetch(input, {
|
||||
...init,
|
||||
headers,
|
||||
})
|
||||
},
|
||||
}
|
||||
},
|
||||
@@ -225,7 +232,7 @@ export namespace Provider {
|
||||
const s = await state()
|
||||
const existing = s.sdk.get(provider.id)
|
||||
if (existing) return existing
|
||||
const [pkg, version] = await ModelsDev.pkg(provider.npm ?? provider.id)
|
||||
const [pkg, version] = provider.npm ?? provider.id
|
||||
const mod = await import(await BunProc.install(pkg, version))
|
||||
const fn = mod[Object.keys(mod).find((key) => key.startsWith("create"))!]
|
||||
const loaded = fn(s.providers[provider.id]?.options)
|
||||
|
||||
@@ -759,6 +759,16 @@ export namespace Session {
|
||||
cost: new Decimal(0)
|
||||
.add(new Decimal(tokens.input).mul(model.cost.input).div(1_000_000))
|
||||
.add(new Decimal(tokens.output).mul(model.cost.output).div(1_000_000))
|
||||
.add(
|
||||
new Decimal(tokens.cache.read)
|
||||
.mul(model.cost.cache_read ?? 0)
|
||||
.div(1_000_000),
|
||||
)
|
||||
.add(
|
||||
new Decimal(tokens.cache.write)
|
||||
.mul(model.cost.cache_write ?? 0)
|
||||
.div(1_000_000),
|
||||
)
|
||||
.toNumber(),
|
||||
tokens,
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
you will generate a short title based on the first message a user begins a conversation with
|
||||
You will generate a short title based on the first message a user begins a conversation with
|
||||
- ensure it is not more than 50 characters long
|
||||
- the title should be a summary of the user's message
|
||||
- it should be one line long
|
||||
|
||||
@@ -0,0 +1,298 @@
|
||||
package theme
|
||||
|
||||
import (
|
||||
"github.com/charmbracelet/lipgloss/v2"
|
||||
"github.com/charmbracelet/lipgloss/v2/compat"
|
||||
)
|
||||
|
||||
// EverforestTheme implements the Theme interface with Everforest colors.
|
||||
// It provides both dark and light variants with Medium (default) contrast.
|
||||
type EverforestTheme struct {
|
||||
BaseTheme
|
||||
}
|
||||
|
||||
// NewEverforestTheme creates a new instance of the Everforest Medium theme.
|
||||
func NewEverforestTheme() *EverforestTheme {
|
||||
// Everforest color palette - Medium variant
|
||||
// Official colors from https://github.com/sainnhe/everforest/wiki
|
||||
// Dark mode colors - using Everforest:Dark Medium contrast palette
|
||||
darkStep1 := "#2d353b" // App background
|
||||
darkStep2 := "#333c43" // Subtle background
|
||||
darkStep3 := "#343f44" // UI element background
|
||||
darkStep4 := "#3d484d" // Hovered UI element background
|
||||
darkStep5 := "#475258" // Active/Selected UI element background
|
||||
darkStep6 := "#7a8478" // Subtle borders and separators
|
||||
darkStep7 := "#859289" // UI element border and focus rings
|
||||
darkStep8 := "#9da9a0" // Hovered UI element border
|
||||
darkStep9 := "#a7c080" // Solid backgrounds
|
||||
darkStep10 := "#83c092" // Hovered solid backgrounds
|
||||
darkStep11 := "#7a8478" // Low-contrast text
|
||||
darkStep12 := "#d3c6aa" // High-contrast text
|
||||
|
||||
// Dark mode accent colors
|
||||
darkPrimary := darkStep9 // Primary uses step 9 (green)
|
||||
darkSecondary := "#7fbbb3" // Secondary (blue)
|
||||
darkAccent := "#d699b6" // Accent (purple)
|
||||
darkRed := "#e67e80" // Error (red)
|
||||
darkOrange := "#e69875" // Warning (orange)
|
||||
darkGreen := "#a7c080" // Success (green)
|
||||
darkCyan := "#83c092" // Info (aqua)
|
||||
darkYellow := "#dbbc7f" // Emphasized text
|
||||
|
||||
// Light mode colors for the Everforest:Light Medium contrast palette
|
||||
lightStep1 := "#fdf6e3" // App background
|
||||
lightStep2 := "#efebd4" // Subtle background
|
||||
lightStep3 := "#f4f0d9" // UI element background
|
||||
lightStep4 := "#efebd4" // Hovered UI element background
|
||||
lightStep5 := "#e6e2cc" // Active/Selected UI element background
|
||||
lightStep6 := "#a6b0a0" // Subtle borders and separators
|
||||
lightStep7 := "#939f91" // UI element border and focus rings
|
||||
lightStep8 := "#829181" // Hovered UI element border
|
||||
lightStep9 := "#8da101" // Solid backgrounds
|
||||
lightStep10 := "#35a77c" // Hovered solid backgrounds
|
||||
lightStep11 := "#a6b0a0" // Low-contrast text
|
||||
lightStep12 := "#5c6a72" // High-contrast text
|
||||
|
||||
// Light mode accent colors
|
||||
lightPrimary := lightStep9 // Primary uses step 9 (green)
|
||||
lightSecondary := "#3a94c5" // Secondary blue
|
||||
lightAccent := "#df69ba" // Accent purple
|
||||
lightRed := "#f85552" // Error red
|
||||
lightOrange := "#f57d26" // Warning orange
|
||||
lightGreen := "#8da101" // Success green
|
||||
lightCyan := "#35a77c" // Info aqua
|
||||
lightYellow := "#dfa000" // Emphasized text
|
||||
|
||||
// Unused variables. These could be used for hover states
|
||||
_ = darkStep4
|
||||
_ = darkStep5
|
||||
_ = darkStep10
|
||||
_ = lightStep4
|
||||
_ = lightStep5
|
||||
_ = lightStep10
|
||||
|
||||
theme := &EverforestTheme{}
|
||||
|
||||
// Base colors
|
||||
theme.PrimaryColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkPrimary),
|
||||
Light: lipgloss.Color(lightPrimary),
|
||||
}
|
||||
theme.SecondaryColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkSecondary),
|
||||
Light: lipgloss.Color(lightSecondary),
|
||||
}
|
||||
theme.AccentColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkAccent),
|
||||
Light: lipgloss.Color(lightAccent),
|
||||
}
|
||||
|
||||
// Status colors
|
||||
theme.ErrorColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkRed),
|
||||
Light: lipgloss.Color(lightRed),
|
||||
}
|
||||
theme.WarningColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkOrange),
|
||||
Light: lipgloss.Color(lightOrange),
|
||||
}
|
||||
theme.SuccessColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkGreen),
|
||||
Light: lipgloss.Color(lightGreen),
|
||||
}
|
||||
theme.InfoColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkCyan),
|
||||
Light: lipgloss.Color(lightCyan),
|
||||
}
|
||||
|
||||
// Text colors
|
||||
theme.TextColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkStep12),
|
||||
Light: lipgloss.Color(lightStep12),
|
||||
}
|
||||
theme.TextMutedColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkStep11),
|
||||
Light: lipgloss.Color(lightStep11),
|
||||
}
|
||||
|
||||
// Background colors
|
||||
theme.BackgroundColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkStep1),
|
||||
Light: lipgloss.Color(lightStep1),
|
||||
}
|
||||
theme.BackgroundSubtleColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkStep2),
|
||||
Light: lipgloss.Color(lightStep2),
|
||||
}
|
||||
theme.BackgroundElementColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkStep3),
|
||||
Light: lipgloss.Color(lightStep3),
|
||||
}
|
||||
|
||||
// Border colors
|
||||
theme.BorderColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkStep7),
|
||||
Light: lipgloss.Color(lightStep7),
|
||||
}
|
||||
theme.BorderActiveColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkStep8),
|
||||
Light: lipgloss.Color(lightStep8),
|
||||
}
|
||||
theme.BorderSubtleColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkStep6),
|
||||
Light: lipgloss.Color(lightStep6),
|
||||
}
|
||||
|
||||
// Diff view colors
|
||||
theme.DiffAddedColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color("#A7C080"),
|
||||
Light: lipgloss.Color("#8DA101"),
|
||||
}
|
||||
theme.DiffRemovedColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color("#E67E80"),
|
||||
Light: lipgloss.Color("#F85552"),
|
||||
}
|
||||
theme.DiffContextColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color("#7A8478"),
|
||||
Light: lipgloss.Color("#A6B0A0"),
|
||||
}
|
||||
theme.DiffHunkHeaderColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color("#859289"),
|
||||
Light: lipgloss.Color("#939F91"),
|
||||
}
|
||||
theme.DiffHighlightAddedColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color("#A7C080"),
|
||||
Light: lipgloss.Color("#8DA101"),
|
||||
}
|
||||
theme.DiffHighlightRemovedColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color("#E67E80"),
|
||||
Light: lipgloss.Color("#F85552"),
|
||||
}
|
||||
theme.DiffAddedBgColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color("#425047"),
|
||||
Light: lipgloss.Color("#F0F1D2"),
|
||||
}
|
||||
theme.DiffRemovedBgColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color("#543A48"),
|
||||
Light: lipgloss.Color("#FBE3DA"),
|
||||
}
|
||||
theme.DiffContextBgColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkStep2),
|
||||
Light: lipgloss.Color(lightStep2),
|
||||
}
|
||||
theme.DiffLineNumberColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkStep3),
|
||||
Light: lipgloss.Color(lightStep3),
|
||||
}
|
||||
theme.DiffAddedLineNumberBgColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color("#3A4A3F"),
|
||||
Light: lipgloss.Color("#E8F2D1"),
|
||||
}
|
||||
theme.DiffRemovedLineNumberBgColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color("#4A3A40"),
|
||||
Light: lipgloss.Color("#FBDAD2"),
|
||||
}
|
||||
|
||||
// Markdown colors
|
||||
theme.MarkdownTextColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkStep12),
|
||||
Light: lipgloss.Color(lightStep12),
|
||||
}
|
||||
theme.MarkdownHeadingColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkSecondary),
|
||||
Light: lipgloss.Color(lightSecondary),
|
||||
}
|
||||
theme.MarkdownLinkColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkPrimary),
|
||||
Light: lipgloss.Color(lightPrimary),
|
||||
}
|
||||
theme.MarkdownLinkTextColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkCyan),
|
||||
Light: lipgloss.Color(lightCyan),
|
||||
}
|
||||
theme.MarkdownCodeColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkGreen),
|
||||
Light: lipgloss.Color(lightGreen),
|
||||
}
|
||||
theme.MarkdownBlockQuoteColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkYellow),
|
||||
Light: lipgloss.Color(lightYellow),
|
||||
}
|
||||
theme.MarkdownEmphColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkYellow),
|
||||
Light: lipgloss.Color(lightYellow),
|
||||
}
|
||||
theme.MarkdownStrongColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkAccent),
|
||||
Light: lipgloss.Color(lightAccent),
|
||||
}
|
||||
theme.MarkdownHorizontalRuleColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkStep11),
|
||||
Light: lipgloss.Color(lightStep11),
|
||||
}
|
||||
theme.MarkdownListItemColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkPrimary),
|
||||
Light: lipgloss.Color(lightPrimary),
|
||||
}
|
||||
theme.MarkdownListEnumerationColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkCyan),
|
||||
Light: lipgloss.Color(lightCyan),
|
||||
}
|
||||
theme.MarkdownImageColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkPrimary),
|
||||
Light: lipgloss.Color(lightPrimary),
|
||||
}
|
||||
theme.MarkdownImageTextColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkCyan),
|
||||
Light: lipgloss.Color(lightCyan),
|
||||
}
|
||||
theme.MarkdownCodeBlockColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkStep12),
|
||||
Light: lipgloss.Color(lightStep12),
|
||||
}
|
||||
|
||||
// Syntax highlighting colors
|
||||
theme.SyntaxCommentColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkStep11),
|
||||
Light: lipgloss.Color(lightStep11),
|
||||
}
|
||||
theme.SyntaxKeywordColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkPrimary),
|
||||
Light: lipgloss.Color(lightPrimary),
|
||||
}
|
||||
theme.SyntaxFunctionColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkSecondary),
|
||||
Light: lipgloss.Color(lightSecondary),
|
||||
}
|
||||
theme.SyntaxVariableColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkRed),
|
||||
Light: lipgloss.Color(lightRed),
|
||||
}
|
||||
theme.SyntaxStringColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkGreen),
|
||||
Light: lipgloss.Color(lightGreen),
|
||||
}
|
||||
theme.SyntaxNumberColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkAccent),
|
||||
Light: lipgloss.Color(lightAccent),
|
||||
}
|
||||
theme.SyntaxTypeColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkYellow),
|
||||
Light: lipgloss.Color(lightYellow),
|
||||
}
|
||||
theme.SyntaxOperatorColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkCyan),
|
||||
Light: lipgloss.Color(lightCyan),
|
||||
}
|
||||
theme.SyntaxPunctuationColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkStep12),
|
||||
Light: lipgloss.Color(lightStep12),
|
||||
}
|
||||
|
||||
return theme
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Register the Everforest theme with the theme manager
|
||||
RegisterTheme("everforest", NewEverforestTheme())
|
||||
}
|
||||
@@ -27,7 +27,7 @@
|
||||
"sharp": "0.32.5",
|
||||
"shiki": "3.4.2",
|
||||
"solid-js": "1.9.7",
|
||||
"toolbeam-docs-theme": "0.2.4"
|
||||
"toolbeam-docs-theme": "0.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "catalog:",
|
||||
|
||||
@@ -18,9 +18,9 @@ function CodeBlock(props: CodeBlockProps) {
|
||||
const [local, rest] = splitProps(props, ["code", "lang", "onRendered"])
|
||||
let containerRef!: HTMLDivElement
|
||||
|
||||
const [html] = createResource(async () => {
|
||||
return (await codeToHtml(local.code, {
|
||||
lang: local.lang || "text",
|
||||
const [html] = createResource(() => [local.code, local.lang], async ([code, lang]) => {
|
||||
return (await codeToHtml(code || "", {
|
||||
lang: lang || "text",
|
||||
themes: {
|
||||
light: "github-light",
|
||||
dark: "github-dark",
|
||||
|
||||
@@ -54,9 +54,3 @@ const links = config.social || [];
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style is:global>
|
||||
body > div.page > header {
|
||||
border-color: var(--sl-color-divider);
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
.codeblock {
|
||||
pre {
|
||||
--shiki-dark-bg: var(--sl-color-bg) !important;
|
||||
background-color: var(--sl-color-bg) !important;
|
||||
--shiki-dark-bg: var(--sl-color-bg-surface) !important;
|
||||
background-color: var(--sl-color-bg-surface) !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,10 @@
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
strong {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
ol {
|
||||
list-style-position: inside;
|
||||
padding-left: 0.75rem;
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
gap: 2.5rem;
|
||||
line-height: 1;
|
||||
|
||||
--sm-tool-width: 28rem;
|
||||
--md-tool-width: 40rem;
|
||||
--lg-tool-width: 56rem;
|
||||
|
||||
--term-icon: url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2060%2016'%20preserveAspectRatio%3D'xMidYMid%20meet'%3E%3Ccircle%20cx%3D'8'%20cy%3D'8'%20r%3D'8'%2F%3E%3Ccircle%20cx%3D'30'%20cy%3D'8'%20r%3D'8'%2F%3E%3Ccircle%20cx%3D'52'%20cy%3D'8'%20r%3D'8'%2F%3E%3C%2Fsvg%3E");
|
||||
}
|
||||
|
||||
@@ -37,7 +41,7 @@
|
||||
|
||||
[data-element-label] {
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
letter-spacing: -0.5px;
|
||||
color: var(--sl-color-text-dimmed);
|
||||
}
|
||||
|
||||
@@ -164,30 +168,6 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
[data-section="system-prompt"] {
|
||||
display: flex;
|
||||
gap: 0.3125rem;
|
||||
|
||||
[data-section="icon"] {
|
||||
flex: 0 0 auto;
|
||||
color: var(--sl-color-text-dimmed);
|
||||
opacity: 0.85;
|
||||
svg {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
[data-section="content"] {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
button {
|
||||
line-height: 1rem;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.parts {
|
||||
@@ -227,6 +207,7 @@
|
||||
}
|
||||
|
||||
& > [data-section="content"] {
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
padding: 0 0 0.375rem;
|
||||
display: flex;
|
||||
@@ -236,20 +217,28 @@
|
||||
[data-part-tool-body] {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 0.375rem;
|
||||
}
|
||||
|
||||
span[data-part-title] {
|
||||
[data-part-title] {
|
||||
line-height: 18px;
|
||||
font-size: 0.75rem;
|
||||
font-size: 0.875rem;
|
||||
color: var(--sl-color-text-secondary);
|
||||
max-wdith: var(--sm-tool-width);
|
||||
|
||||
b {
|
||||
word-break: break-all;
|
||||
font-weight: 500;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 0.375rem;
|
||||
|
||||
span[data-element-label] {
|
||||
color: var(--sl-color-text-secondary);
|
||||
}
|
||||
|
||||
&[data-size="md"] {
|
||||
font-size: 0.875rem;
|
||||
b {
|
||||
color: var(--sl-color-text);
|
||||
word-break: break-all;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,7 +256,7 @@
|
||||
display: inline-grid;
|
||||
align-items: center;
|
||||
grid-template-columns: max-content max-content minmax(0, 1fr);
|
||||
max-width: 100%;
|
||||
max-width: var(--md-tool-width);
|
||||
gap: 0.25rem 0.375rem;
|
||||
|
||||
& > div:nth-child(3n + 1) {
|
||||
@@ -279,16 +268,14 @@
|
||||
|
||||
& > div:nth-child(3n + 2),
|
||||
& > div:nth-child(3n + 3) {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font-size: 0.75rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
& > div:nth-child(3n + 3) {
|
||||
padding-left: 0.125rem;
|
||||
color: var(--sl-color-text-dimmed);
|
||||
word-break: break-word;
|
||||
color: var(--sl-color-text-secondary);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -302,6 +289,11 @@
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
[data-part-tool-edit] {
|
||||
width: 100%;
|
||||
max-width: var(--lg-tool-width);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -325,16 +317,6 @@
|
||||
& > [data-section="content"] > [data-part-tool-body] {
|
||||
gap: 0.5rem;
|
||||
}
|
||||
[data-part-title] {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 0.5rem;
|
||||
|
||||
b {
|
||||
color: var(--sl-color-text);
|
||||
word-break: break-all;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[data-part-type="tool-grep"] {
|
||||
@@ -342,16 +324,6 @@
|
||||
> [data-section="content"] > [data-part-tool-body] {
|
||||
gap: 0.5rem;
|
||||
}
|
||||
[data-part-title] {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 0.5rem;
|
||||
|
||||
b {
|
||||
color: var(--sl-color-text);
|
||||
word-break: break-all;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[data-part-type="tool-write"],
|
||||
@@ -359,7 +331,9 @@
|
||||
[data-part-type="tool-fetch"] {
|
||||
[data-part-tool-result] {
|
||||
[data-part-tool-code] {
|
||||
width: var(--md-tool-width);
|
||||
border: 1px solid var(--sl-color-divider);
|
||||
background-color: var(--sl-color-bg-surface);
|
||||
border-radius: 0.25rem;
|
||||
padding: 0.5rem calc(0.5rem + 3px);
|
||||
|
||||
@@ -372,8 +346,6 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
[data-part-type="tool-edit"] {
|
||||
}
|
||||
}
|
||||
|
||||
.message-text {
|
||||
@@ -384,6 +356,8 @@
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 1rem;
|
||||
align-self: flex-start;
|
||||
max-width: var(--md-tool-width);
|
||||
|
||||
&[data-size="sm"] {
|
||||
pre {
|
||||
@@ -411,7 +385,7 @@
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
&[data-highlight="true"] {
|
||||
&[data-invert="true"] {
|
||||
background-color: var(--sl-color-blue-high);
|
||||
|
||||
pre {
|
||||
@@ -428,6 +402,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
&[data-highlight="true"] {
|
||||
background-color: var(--sl-color-blue-low);
|
||||
}
|
||||
|
||||
&[data-expanded="true"] {
|
||||
pre {
|
||||
display: block;
|
||||
@@ -450,6 +428,7 @@
|
||||
gap: 0.5rem;
|
||||
|
||||
& > [data-section="body"] {
|
||||
width: var(--sm-tool-width);
|
||||
border: 1px solid var(--sl-color-divider);
|
||||
border-radius: 0.25rem;
|
||||
max-width: 100%;
|
||||
@@ -460,7 +439,7 @@
|
||||
width: 100%;
|
||||
height: 1.625rem;
|
||||
text-align: center;
|
||||
padding: 0 0.75rem 0 3.25rem;
|
||||
padding: 0 3.25rem;
|
||||
|
||||
& > span {
|
||||
max-width: min(100%, 140ch);
|
||||
@@ -491,12 +470,10 @@
|
||||
|
||||
[data-section="content"] {
|
||||
padding: 0.5rem calc(0.5rem + 3px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 1rem;
|
||||
|
||||
pre {
|
||||
--shiki-dark-bg: var(--sl-color-bg) !important;
|
||||
background-color: var(--sl-color-bg) !important;
|
||||
line-height: 1.6;
|
||||
font-size: 0.75rem;
|
||||
white-space: pre-wrap;
|
||||
@@ -533,6 +510,8 @@
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 1rem;
|
||||
align-self: flex-start;
|
||||
max-width: var(--md-tool-width);
|
||||
|
||||
button {
|
||||
flex: 0 0 auto;
|
||||
@@ -540,6 +519,10 @@
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
&[data-highlight="true"] {
|
||||
background-color: var(--sl-color-blue-low);
|
||||
}
|
||||
|
||||
&[data-expanded="true"] {
|
||||
[data-elment-markdown] {
|
||||
display: block;
|
||||
@@ -566,6 +549,7 @@
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
width: var(--sm-tool-width);
|
||||
border: 1px solid var(--sl-color-divider);
|
||||
border-radius: 0.25rem;
|
||||
|
||||
@@ -577,6 +561,7 @@
|
||||
padding: 0.375rem 0.625rem 0.375rem 1.75rem;
|
||||
border-bottom: 1px solid var(--sl-color-divider);
|
||||
line-height: 1.5;
|
||||
word-break: break-word;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
@@ -614,9 +599,9 @@
|
||||
}
|
||||
}
|
||||
&[data-status="completed"] {
|
||||
color: var(--sl-color-text-dimmed);
|
||||
color: var(--sl-color-text-secondary);
|
||||
|
||||
& > span { border-color: var(--sl-color-hairline); }
|
||||
& > span { border-color: var(--sl-color-green-low); }
|
||||
& > span::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
@@ -624,7 +609,7 @@
|
||||
left: 2px;
|
||||
width: calc(0.75rem - 2px - 4px);
|
||||
height: calc(0.75rem - 2px - 4px);
|
||||
box-shadow: inset 1rem 1rem var(--sl-color-divider);
|
||||
box-shadow: inset 1rem 1rem var(--sl-color-green);
|
||||
|
||||
transform-origin: bottom left;
|
||||
clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%);
|
||||
|
||||
Reference in New Issue
Block a user