pluidr 0.7.1 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/cli/commands/doctor.js +14 -2
- package/src/cli/commands/init.js +6 -2
- package/src/cli/commands/launch.js +1 -1
- package/src/cli/commands/uninstall.js +27 -0
- package/src/core/backup.js +11 -5
- package/src/core/paths.js +2 -0
- package/src/core/paths.test.js +9 -1
- package/src/core/squeezeInstaller.js +2 -5
- package/src/core/squeezeInstaller.test.js +4 -0
- package/src/core/themeWriter.js +12 -0
- package/src/core/themeWriter.test.js +29 -0
- package/src/core/tuiConfigWriter.js +22 -0
- package/src/core/tuiConfigWriter.test.js +38 -0
- package/src/templates/agent-prompts/composer.txt +1 -2
- package/src/templates/agent-prompts/debugger.txt +1 -0
- package/src/templates/agent-prompts/prober.txt +4 -0
- package/src/templates/opencode.config.json +1 -0
- package/src/templates/themes/pluidr-contrast.json +177 -0
package/package.json
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import { existsSync, readFileSync, readdirSync } from "node:fs"
|
|
2
2
|
import { join } from "node:path"
|
|
3
|
-
import { getConfigDir, getConfigPath, getPromptsDir } from "../../core/paths.js"
|
|
3
|
+
import { getConfigDir, getConfigPath, getPromptsDir, getThemesDir } from "../../core/paths.js"
|
|
4
4
|
import { findSqueezePath } from "../../core/squeezeInstaller.js"
|
|
5
5
|
|
|
6
6
|
const EXPECTED_PROMPT_COUNT = 18
|
|
7
7
|
const PLUGIN_FILES = ["pluidr-flow.js", "pluidr-squeeze.js"]
|
|
8
8
|
|
|
9
|
+
export function cleanJsonc(content) {
|
|
10
|
+
return content.replace(
|
|
11
|
+
/\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)|(,\s*(?=[\]}]))/g,
|
|
12
|
+
(m, g1, g2) => g1 ? "" : g2 ? "" : m
|
|
13
|
+
)
|
|
14
|
+
}
|
|
15
|
+
|
|
9
16
|
export function collectChecks() {
|
|
10
17
|
const configDir = getConfigDir()
|
|
11
18
|
const configPath = getConfigPath()
|
|
@@ -13,6 +20,7 @@ export function collectChecks() {
|
|
|
13
20
|
const pluginsDir = join(configDir, "plugins")
|
|
14
21
|
const packageJsonPath = join(configDir, "package.json")
|
|
15
22
|
const binDir = join(configDir, "bin")
|
|
23
|
+
const themesDir = getThemesDir()
|
|
16
24
|
|
|
17
25
|
const checks = []
|
|
18
26
|
|
|
@@ -39,6 +47,10 @@ export function collectChecks() {
|
|
|
39
47
|
}
|
|
40
48
|
checks.push({ component: "plugin files", pass: pluginsFound === PLUGIN_FILES.length, detail: `${pluginsFound}/${PLUGIN_FILES.length}` })
|
|
41
49
|
|
|
50
|
+
// 3b. Custom theme exists
|
|
51
|
+
const themeExists = existsSync(join(themesDir, "pluidr-contrast.json"))
|
|
52
|
+
checks.push({ component: "pluidr-contrast theme file", pass: themeExists })
|
|
53
|
+
|
|
42
54
|
// 4. package.json with @opencode-ai/plugin dependency
|
|
43
55
|
let pkgValid = false
|
|
44
56
|
if (existsSync(packageJsonPath)) {
|
|
@@ -67,7 +79,7 @@ export function collectChecks() {
|
|
|
67
79
|
if (configExists) {
|
|
68
80
|
try {
|
|
69
81
|
const content = readFileSync(configPath, "utf-8")
|
|
70
|
-
const cleaned = content
|
|
82
|
+
const cleaned = cleanJsonc(content)
|
|
71
83
|
JSON.parse(cleaned)
|
|
72
84
|
configValid = true
|
|
73
85
|
} catch {
|
package/src/cli/commands/init.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readFileSync } from "node:fs"
|
|
1
|
+
import { readFileSync, writeFileSync } from "node:fs"
|
|
2
2
|
import { resolve, dirname } from "node:path"
|
|
3
3
|
import { fileURLToPath } from "node:url"
|
|
4
4
|
import { confirm, isCancel } from "@clack/prompts"
|
|
@@ -8,8 +8,10 @@ import { buildConfig } from "../../core/configBuilder.js"
|
|
|
8
8
|
import { writeConfig } from "../../core/configWriter.js"
|
|
9
9
|
import { writeAgentPrompts } from "../../core/agentPromptWriter.js"
|
|
10
10
|
import { writePluginBundle, writePluginPackageJson } from "../../core/pluginWriter.js"
|
|
11
|
+
import { writeThemes } from "../../core/themeWriter.js"
|
|
12
|
+
import { writeTuiConfig } from "../../core/tuiConfigWriter.js"
|
|
11
13
|
import { installSqueeze } from "../../core/squeezeInstaller.js"
|
|
12
|
-
import { getConfigPath } from "../../core/paths.js"
|
|
14
|
+
import { getConfigPath, getConfigDir } from "../../core/paths.js"
|
|
13
15
|
|
|
14
16
|
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
15
17
|
const TEMPLATES_DIR = resolve(__dirname, "../../templates")
|
|
@@ -32,6 +34,8 @@ export async function runInit() {
|
|
|
32
34
|
const configObject = buildConfig(tierChoices, TEMPLATES_DIR)
|
|
33
35
|
writeConfig(configObject)
|
|
34
36
|
writeAgentPrompts(TEMPLATES_DIR)
|
|
37
|
+
writeThemes(TEMPLATES_DIR)
|
|
38
|
+
writeTuiConfig("pluidr-contrast")
|
|
35
39
|
writePluginBundle()
|
|
36
40
|
writePluginPackageJson()
|
|
37
41
|
if (installSqueezePlugin) {
|
|
@@ -31,7 +31,7 @@ export async function runLaunch() {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
// 3. Launch opencode
|
|
34
|
-
console.log("Launching
|
|
34
|
+
console.log("Launching pluidr...")
|
|
35
35
|
const child = process.platform === "win32"
|
|
36
36
|
? spawn("opencode", { stdio: "inherit", shell: true })
|
|
37
37
|
: spawn("opencode", [], { stdio: "inherit" })
|
|
@@ -16,6 +16,20 @@ function findLatestBackup() {
|
|
|
16
16
|
return backups.length > 0 ? join(dir, backups[0]) : null
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
function findLatestTuiBackup() {
|
|
20
|
+
const dir = getConfigDir()
|
|
21
|
+
let backups = []
|
|
22
|
+
try {
|
|
23
|
+
backups = readdirSync(dir)
|
|
24
|
+
.filter((f) => f.startsWith("tui.json.bak."))
|
|
25
|
+
.sort()
|
|
26
|
+
.reverse()
|
|
27
|
+
} catch {
|
|
28
|
+
return null
|
|
29
|
+
}
|
|
30
|
+
return backups.length > 0 ? join(dir, backups[0]) : null
|
|
31
|
+
}
|
|
32
|
+
|
|
19
33
|
export async function runUninstall() {
|
|
20
34
|
const configDir = getConfigDir()
|
|
21
35
|
const configPath = getConfigPath()
|
|
@@ -32,6 +46,14 @@ export async function runUninstall() {
|
|
|
32
46
|
summary.restored = latestBackup
|
|
33
47
|
}
|
|
34
48
|
|
|
49
|
+
const latestTuiBackup = findLatestTuiBackup()
|
|
50
|
+
const tuiConfigPath = join(configDir, "tui.json")
|
|
51
|
+
if (latestTuiBackup) {
|
|
52
|
+
copyFileSync(latestTuiBackup, tuiConfigPath)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const themesDir = join(configDir, "themes")
|
|
56
|
+
|
|
35
57
|
// Remove Pluidr-installed artifacts
|
|
36
58
|
if (existsSync(promptsDir)) {
|
|
37
59
|
rmSync(promptsDir, { recursive: true, force: true })
|
|
@@ -45,6 +67,11 @@ export async function runUninstall() {
|
|
|
45
67
|
rmSync(binDir, { recursive: true, force: true })
|
|
46
68
|
summary.removed.push("bin/")
|
|
47
69
|
}
|
|
70
|
+
const customThemePath = join(themesDir, "pluidr-contrast.json")
|
|
71
|
+
if (existsSync(customThemePath)) {
|
|
72
|
+
rmSync(customThemePath, { force: true })
|
|
73
|
+
summary.removed.push("themes/pluidr-contrast.json")
|
|
74
|
+
}
|
|
48
75
|
|
|
49
76
|
// Print summary
|
|
50
77
|
console.log("Uninstall complete:")
|
package/src/core/backup.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync, copyFileSync, readdirSync, unlinkSync } from "node:fs"
|
|
2
2
|
import { join, dirname } from "node:path"
|
|
3
|
-
import { getConfigPath } from "./paths.js"
|
|
3
|
+
import { getConfigPath, getTuiConfigPath } from "./paths.js"
|
|
4
4
|
|
|
5
5
|
const MAX_BACKUPS = 5
|
|
6
6
|
|
|
@@ -32,9 +32,15 @@ function rotateBackups(configPath) {
|
|
|
32
32
|
|
|
33
33
|
export function backupExistingConfig(configPath) {
|
|
34
34
|
const resolvedPath = configPath || getConfigPath()
|
|
35
|
-
if (
|
|
35
|
+
if (existsSync(resolvedPath)) {
|
|
36
|
+
rotateBackups(resolvedPath)
|
|
37
|
+
const backupPath = `${resolvedPath}.bak.${timestamp()}`
|
|
38
|
+
copyFileSync(resolvedPath, backupPath)
|
|
39
|
+
}
|
|
36
40
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
41
|
+
const tuiPath = getTuiConfigPath()
|
|
42
|
+
if (existsSync(tuiPath)) {
|
|
43
|
+
const backupTuiPath = `${tuiPath}.bak.${timestamp()}`
|
|
44
|
+
copyFileSync(tuiPath, backupTuiPath)
|
|
45
|
+
}
|
|
40
46
|
}
|
package/src/core/paths.js
CHANGED
|
@@ -5,5 +5,7 @@ const BASE = join(homedir(), ".config", "opencode")
|
|
|
5
5
|
|
|
6
6
|
export const getConfigDir = () => BASE
|
|
7
7
|
export const getConfigPath = () => join(BASE, "opencode.jsonc")
|
|
8
|
+
export const getTuiConfigPath = () => join(BASE, "tui.json")
|
|
8
9
|
export const getPromptsDir = () => join(BASE, "prompts")
|
|
10
|
+
export const getThemesDir = () => join(BASE, "themes")
|
|
9
11
|
// ponytail: getBackupPath removed (YAGNI)
|
package/src/core/paths.test.js
CHANGED
|
@@ -2,7 +2,7 @@ import { describe, it } from "node:test"
|
|
|
2
2
|
import assert from "node:assert"
|
|
3
3
|
import { homedir } from "node:os"
|
|
4
4
|
import { join } from "node:path"
|
|
5
|
-
import { getConfigDir, getConfigPath, getPromptsDir } from "./paths.js"
|
|
5
|
+
import { getConfigDir, getConfigPath, getTuiConfigPath, getPromptsDir, getThemesDir } from "./paths.js"
|
|
6
6
|
|
|
7
7
|
const BASE = join(homedir(), ".config", "opencode")
|
|
8
8
|
|
|
@@ -15,7 +15,15 @@ describe("paths", () => {
|
|
|
15
15
|
assert.strictEqual(getConfigPath(), join(BASE, "opencode.jsonc"))
|
|
16
16
|
})
|
|
17
17
|
|
|
18
|
+
it("getTuiConfigPath returns tui.json path", () => {
|
|
19
|
+
assert.strictEqual(getTuiConfigPath(), join(BASE, "tui.json"))
|
|
20
|
+
})
|
|
21
|
+
|
|
18
22
|
it("getPromptsDir returns prompts path", () => {
|
|
19
23
|
assert.strictEqual(getPromptsDir(), join(BASE, "prompts"))
|
|
20
24
|
})
|
|
25
|
+
|
|
26
|
+
it("getThemesDir returns themes path", () => {
|
|
27
|
+
assert.strictEqual(getThemesDir(), join(BASE, "themes"))
|
|
28
|
+
})
|
|
21
29
|
})
|
|
@@ -26,7 +26,7 @@ export function platformAsset() {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
export function validatePath(path) {
|
|
29
|
-
if (!/^[a-zA-Z0-9_\-\.\:\/\\]+$/.test(path)) {
|
|
29
|
+
if (!/^[a-zA-Z0-9_\-\.\:\/\\ ]+$/.test(path)) {
|
|
30
30
|
throw new Error(`Invalid path: "${path}" contains unsafe characters`)
|
|
31
31
|
}
|
|
32
32
|
}
|
|
@@ -53,10 +53,7 @@ function extract(archivePath, destDir) {
|
|
|
53
53
|
execFileSync("powershell", [
|
|
54
54
|
"-NoProfile",
|
|
55
55
|
"-Command",
|
|
56
|
-
|
|
57
|
-
"-LiteralPath", archivePath,
|
|
58
|
-
"-DestinationPath", destDir,
|
|
59
|
-
"-Force"
|
|
56
|
+
`Expand-Archive -LiteralPath '${archivePath}' -DestinationPath '${destDir}' -Force`
|
|
60
57
|
], { stdio: "ignore" })
|
|
61
58
|
} else {
|
|
62
59
|
execFileSync("tar", ["-xzf", archivePath, "-C", destDir], { stdio: "ignore" })
|
|
@@ -41,6 +41,10 @@ describe("validatePath", () => {
|
|
|
41
41
|
assert.doesNotThrow(() => validatePath("C:\\Users\\test"))
|
|
42
42
|
})
|
|
43
43
|
|
|
44
|
+
it("accepts paths with spaces", () => {
|
|
45
|
+
assert.doesNotThrow(() => validatePath("C:\\Users\\John Doe\\.config"))
|
|
46
|
+
})
|
|
47
|
+
|
|
44
48
|
it("accepts paths with dots and dashes", () => {
|
|
45
49
|
assert.doesNotThrow(() => validatePath("./dir/file-name.ext"))
|
|
46
50
|
})
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { mkdirSync, copyFileSync } from "node:fs"
|
|
2
|
+
import { resolve } from "node:path"
|
|
3
|
+
import { getThemesDir } from "./paths.js"
|
|
4
|
+
|
|
5
|
+
export function writeThemes(templatesDir, destDir) {
|
|
6
|
+
const sourcePath = resolve(templatesDir, "themes", "pluidr-contrast.json")
|
|
7
|
+
const targetDir = destDir || getThemesDir()
|
|
8
|
+
const destPath = resolve(targetDir, "pluidr-contrast.json")
|
|
9
|
+
|
|
10
|
+
mkdirSync(targetDir, { recursive: true })
|
|
11
|
+
copyFileSync(sourcePath, destPath)
|
|
12
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { describe, it, after } from "node:test"
|
|
2
|
+
import assert from "node:assert"
|
|
3
|
+
import { existsSync, mkdtempSync, readFileSync, rmSync, mkdirSync, writeFileSync } from "node:fs"
|
|
4
|
+
import { join } from "node:path"
|
|
5
|
+
import { tmpdir } from "node:os"
|
|
6
|
+
import { writeThemes } from "./themeWriter.js"
|
|
7
|
+
|
|
8
|
+
describe("themeWriter", () => {
|
|
9
|
+
const destDir = mkdtempSync(join(tmpdir(), "pluidr-theme-dest-"))
|
|
10
|
+
|
|
11
|
+
after(() => {
|
|
12
|
+
if (existsSync(destDir)) rmSync(destDir, { recursive: true })
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
it("copies theme file to destination directory", () => {
|
|
16
|
+
const tmpSrcDir = mkdtempSync(join(tmpdir(), "pluidr-theme-src-"))
|
|
17
|
+
const srcThemesDir = join(tmpSrcDir, "themes")
|
|
18
|
+
mkdirSync(srcThemesDir, { recursive: true })
|
|
19
|
+
writeFileSync(join(srcThemesDir, "pluidr-contrast.json"), "mock-theme-content", "utf-8")
|
|
20
|
+
|
|
21
|
+
writeThemes(tmpSrcDir, destDir)
|
|
22
|
+
|
|
23
|
+
const destPath = join(destDir, "pluidr-contrast.json")
|
|
24
|
+
assert.ok(existsSync(destPath), "theme file should be copied")
|
|
25
|
+
assert.strictEqual(readFileSync(destPath, "utf-8"), "mock-theme-content")
|
|
26
|
+
|
|
27
|
+
rmSync(tmpSrcDir, { recursive: true })
|
|
28
|
+
})
|
|
29
|
+
})
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, existsSync } from "node:fs"
|
|
2
|
+
import { getTuiConfigPath } from "./paths.js"
|
|
3
|
+
|
|
4
|
+
export function writeTuiConfig(themeName, customPath) {
|
|
5
|
+
const path = customPath || getTuiConfigPath()
|
|
6
|
+
let config = {
|
|
7
|
+
"$schema": "https://opencode.ai/tui.json"
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
if (existsSync(path)) {
|
|
11
|
+
try {
|
|
12
|
+
const content = readFileSync(path, "utf-8")
|
|
13
|
+
config = JSON.parse(content)
|
|
14
|
+
} catch {
|
|
15
|
+
// If parsing fails, fall back to default structure
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
config.theme = themeName
|
|
20
|
+
|
|
21
|
+
writeFileSync(path, JSON.stringify(config, null, 2), "utf-8")
|
|
22
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { describe, it, after } from "node:test"
|
|
2
|
+
import assert from "node:assert"
|
|
3
|
+
import { existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs"
|
|
4
|
+
import { join } from "node:path"
|
|
5
|
+
import { tmpdir } from "node:os"
|
|
6
|
+
import { writeTuiConfig } from "./tuiConfigWriter.js"
|
|
7
|
+
|
|
8
|
+
describe("tuiConfigWriter", () => {
|
|
9
|
+
const destDir = mkdtempSync(join(tmpdir(), "pluidr-tui-dest-"))
|
|
10
|
+
const tuiPath = join(destDir, "tui.json")
|
|
11
|
+
|
|
12
|
+
after(() => {
|
|
13
|
+
if (existsSync(destDir)) rmSync(destDir, { recursive: true })
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
it("writes new tui.json with theme name if it does not exist", () => {
|
|
17
|
+
writeTuiConfig("pluidr-contrast", tuiPath)
|
|
18
|
+
|
|
19
|
+
assert.ok(existsSync(tuiPath))
|
|
20
|
+
const parsed = JSON.parse(readFileSync(tuiPath, "utf-8"))
|
|
21
|
+
assert.strictEqual(parsed.theme, "pluidr-contrast")
|
|
22
|
+
assert.strictEqual(parsed["$schema"], "https://opencode.ai/tui.json")
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
it("updates existing tui.json theme name while preserving other fields", () => {
|
|
26
|
+
writeFileSync(tuiPath, JSON.stringify({
|
|
27
|
+
"$schema": "https://opencode.ai/tui.json",
|
|
28
|
+
"theme": "ayu-dark",
|
|
29
|
+
"font": "monolisa"
|
|
30
|
+
}, null, 2), "utf-8")
|
|
31
|
+
|
|
32
|
+
writeTuiConfig("pluidr-contrast", tuiPath)
|
|
33
|
+
|
|
34
|
+
const parsed = JSON.parse(readFileSync(tuiPath, "utf-8"))
|
|
35
|
+
assert.strictEqual(parsed.theme, "pluidr-contrast")
|
|
36
|
+
assert.strictEqual(parsed.font, "monolisa")
|
|
37
|
+
})
|
|
38
|
+
})
|
|
@@ -394,8 +394,7 @@ elsewhere. Do not accept a report that is not in `docs/reports/`.
|
|
|
394
394
|
- **Regression Awareness** — When re-triggering coder after a FAIL, pass the
|
|
395
395
|
gap list in full so coder doesn't fix one thing and break something
|
|
396
396
|
already confirmed as PASS.
|
|
397
|
-
- **Clarification** — If anything is ambiguous at any phase,
|
|
398
|
-
using multiple-choice options (2-4 short choices per question).
|
|
397
|
+
- **Clarification** — If anything is ambiguous at any phase, avoid excessive questioning. For minor details, make a reasonable, safe engineering assumption based on existing codebase conventions and document it. Only prompt the user using multiple-choice options (2-3 short choices per question, and list your recommended option first prefixed with '(Recommended)') if there is a critical blocking issue that directly impacts the design direction or has high regression risk.
|
|
399
398
|
- **Front-End / UI Mockups** — If the user asks for a design, mockup, or anything related to the Front-End (FE), you must provide a detailed ASCII mockup of the UI structure in your output.
|
|
400
399
|
|
|
401
400
|
---
|
|
@@ -132,6 +132,7 @@ just a technical restriction.
|
|
|
132
132
|
- **Separation of Investigation/Fix/Report** — Do not mix investigation,
|
|
133
133
|
implementation, and reporting in the same delegate call. Each subagent
|
|
134
134
|
has one job; the Debugger orchestrates the sequence.
|
|
135
|
+
- **Avoid Excessive Questioning** — Avoid excessive querying of the user for minor ambiguities. For small implementation details, make a reasonable, safe engineering assumption based on existing codebase conventions and proceed. Only prompt the user using multiple-choice options (2-3 short choices per question, and list your recommended option first prefixed with '(Recommended)') when a critical blocking issue directly prevents a safe diagnosis or fix.
|
|
135
136
|
|
|
136
137
|
## What you do NOT do
|
|
137
138
|
|
|
@@ -85,6 +85,10 @@ Do NOT remain in a completed state without offering next steps.
|
|
|
85
85
|
- You do not patch without a GUARDRAIL GATE user confirmation after TRACE.
|
|
86
86
|
- You do not loop more than 5 times on AUDIT before surfacing to the user.
|
|
87
87
|
|
|
88
|
+
## Principles you apply
|
|
89
|
+
|
|
90
|
+
- **Avoid Excessive Questioning** — Avoid excessive querying of the user for minor ambiguities. For small implementation details, make a reasonable, safe engineering assumption based on existing codebase conventions and proceed. Only prompt the user using the `question` tool with multiple-choice options (2-3 short choices per question, and list your recommended option first prefixed with '(Recommended)') for critical blocking decisions (such as the Guardrail Gate or a complete audit block).
|
|
91
|
+
|
|
88
92
|
## Conflict Resolution
|
|
89
93
|
Refer to `hierarchy.txt` (loaded globally) — you do not resolve principle
|
|
90
94
|
conflicts by your own judgment outside that hierarchy.
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://opencode.ai/theme.json",
|
|
3
|
+
"theme": {
|
|
4
|
+
"primary": {
|
|
5
|
+
"dark": "#ff7039",
|
|
6
|
+
"light": "#ff7039"
|
|
7
|
+
},
|
|
8
|
+
"secondary": {
|
|
9
|
+
"dark": "#99f3ff",
|
|
10
|
+
"light": "#99f3ff"
|
|
11
|
+
},
|
|
12
|
+
"accent": {
|
|
13
|
+
"dark": "#ff7039",
|
|
14
|
+
"light": "#ff7039"
|
|
15
|
+
},
|
|
16
|
+
"error": {
|
|
17
|
+
"dark": "#fc5d7c",
|
|
18
|
+
"light": "#fc5d7c"
|
|
19
|
+
},
|
|
20
|
+
"warning": {
|
|
21
|
+
"dark": "#ff669c",
|
|
22
|
+
"light": "#ff669c"
|
|
23
|
+
},
|
|
24
|
+
"success": {
|
|
25
|
+
"dark": "#00cc76",
|
|
26
|
+
"light": "#00cc76"
|
|
27
|
+
},
|
|
28
|
+
"info": {
|
|
29
|
+
"dark": "#00b4cc",
|
|
30
|
+
"light": "#00b4cc"
|
|
31
|
+
},
|
|
32
|
+
"text": {
|
|
33
|
+
"dark": "#ffffff",
|
|
34
|
+
"light": "#ffffff"
|
|
35
|
+
},
|
|
36
|
+
"textMuted": {
|
|
37
|
+
"dark": "#888888",
|
|
38
|
+
"light": "#888888"
|
|
39
|
+
},
|
|
40
|
+
"background": {
|
|
41
|
+
"dark": "#000000",
|
|
42
|
+
"light": "#000000"
|
|
43
|
+
},
|
|
44
|
+
"backgroundPanel": {
|
|
45
|
+
"dark": "#000000",
|
|
46
|
+
"light": "#000000"
|
|
47
|
+
},
|
|
48
|
+
"backgroundElement": {
|
|
49
|
+
"dark": "#000000",
|
|
50
|
+
"light": "#000000"
|
|
51
|
+
},
|
|
52
|
+
"border": {
|
|
53
|
+
"dark": "#101520",
|
|
54
|
+
"light": "#101520"
|
|
55
|
+
},
|
|
56
|
+
"borderActive": {
|
|
57
|
+
"dark": "#ff7039",
|
|
58
|
+
"light": "#ff7039"
|
|
59
|
+
},
|
|
60
|
+
"borderSubtle": {
|
|
61
|
+
"dark": "#101520",
|
|
62
|
+
"light": "#101520"
|
|
63
|
+
},
|
|
64
|
+
"diffAdded": {
|
|
65
|
+
"dark": "#00cc76",
|
|
66
|
+
"light": "#00cc76"
|
|
67
|
+
},
|
|
68
|
+
"diffRemoved": {
|
|
69
|
+
"dark": "#fc5d7c",
|
|
70
|
+
"light": "#fc5d7c"
|
|
71
|
+
},
|
|
72
|
+
"diffContext": {
|
|
73
|
+
"dark": "#888888",
|
|
74
|
+
"light": "#888888"
|
|
75
|
+
},
|
|
76
|
+
"diffAddedBg": {
|
|
77
|
+
"dark": "#1a2618",
|
|
78
|
+
"light": "#1a2618"
|
|
79
|
+
},
|
|
80
|
+
"diffRemovedBg": {
|
|
81
|
+
"dark": "#2a1a1a",
|
|
82
|
+
"light": "#2a1a1a"
|
|
83
|
+
},
|
|
84
|
+
"diffContextBg": {
|
|
85
|
+
"dark": "#000000",
|
|
86
|
+
"light": "#000000"
|
|
87
|
+
},
|
|
88
|
+
"markdownText": {
|
|
89
|
+
"dark": "#ffffff",
|
|
90
|
+
"light": "#ffffff"
|
|
91
|
+
},
|
|
92
|
+
"markdownHeading": {
|
|
93
|
+
"dark": "#ff669c",
|
|
94
|
+
"light": "#ff669c"
|
|
95
|
+
},
|
|
96
|
+
"markdownLink": {
|
|
97
|
+
"dark": "#99f3ff",
|
|
98
|
+
"light": "#99f3ff"
|
|
99
|
+
},
|
|
100
|
+
"markdownLinkText": {
|
|
101
|
+
"dark": "#ff7039",
|
|
102
|
+
"light": "#ff7039"
|
|
103
|
+
},
|
|
104
|
+
"markdownCode": {
|
|
105
|
+
"dark": "#66ffbf",
|
|
106
|
+
"light": "#66ffbf"
|
|
107
|
+
},
|
|
108
|
+
"markdownBlockQuote": {
|
|
109
|
+
"dark": "#888888",
|
|
110
|
+
"light": "#888888"
|
|
111
|
+
},
|
|
112
|
+
"markdownStrong": {
|
|
113
|
+
"dark": "#ff7039",
|
|
114
|
+
"light": "#ff7039"
|
|
115
|
+
},
|
|
116
|
+
"syntaxComment": {
|
|
117
|
+
"dark": "#888888",
|
|
118
|
+
"light": "#888888"
|
|
119
|
+
},
|
|
120
|
+
"syntaxKeyword": {
|
|
121
|
+
"dark": "#ff669c",
|
|
122
|
+
"light": "#ff669c"
|
|
123
|
+
},
|
|
124
|
+
"syntaxFunction": {
|
|
125
|
+
"dark": "#00b4cc",
|
|
126
|
+
"light": "#00b4cc"
|
|
127
|
+
},
|
|
128
|
+
"syntaxVariable": {
|
|
129
|
+
"dark": "#ffb966",
|
|
130
|
+
"light": "#ffb966"
|
|
131
|
+
},
|
|
132
|
+
"syntaxString": {
|
|
133
|
+
"dark": "#66ffbf",
|
|
134
|
+
"light": "#66ffbf"
|
|
135
|
+
},
|
|
136
|
+
"syntaxNumber": {
|
|
137
|
+
"dark": "#a000ff",
|
|
138
|
+
"light": "#a000ff"
|
|
139
|
+
},
|
|
140
|
+
"syntaxType": {
|
|
141
|
+
"dark": "#99f3ff",
|
|
142
|
+
"light": "#99f3ff"
|
|
143
|
+
},
|
|
144
|
+
"syntaxOperator": {
|
|
145
|
+
"dark": "#ff669c",
|
|
146
|
+
"light": "#ff669c"
|
|
147
|
+
},
|
|
148
|
+
"syntaxPunctuation": {
|
|
149
|
+
"dark": "#ffffff",
|
|
150
|
+
"light": "#ffffff"
|
|
151
|
+
},
|
|
152
|
+
"inputBackground": {
|
|
153
|
+
"dark": "#000000",
|
|
154
|
+
"light": "#000000"
|
|
155
|
+
},
|
|
156
|
+
"InputBorder": {
|
|
157
|
+
"dark": "#101520",
|
|
158
|
+
"light": "#101520"
|
|
159
|
+
},
|
|
160
|
+
"InputBorderActive": {
|
|
161
|
+
"dark": "#ff7039",
|
|
162
|
+
"light": "#ff7039"
|
|
163
|
+
},
|
|
164
|
+
"inputPrompt": {
|
|
165
|
+
"dark": "#ff7039",
|
|
166
|
+
"light": "#ff7039"
|
|
167
|
+
},
|
|
168
|
+
"inputCursor": {
|
|
169
|
+
"dark": "#ff7039",
|
|
170
|
+
"light": "#ff7039"
|
|
171
|
+
},
|
|
172
|
+
"inputText": {
|
|
173
|
+
"dark": "#ffffff",
|
|
174
|
+
"light": "#ffffff"
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|