free-coding-models 0.5.10 → 0.5.12
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/README.md +40 -0
- package/bin/free-coding-models.js +6 -1
- package/changelog/v0.5.11.md +56 -0
- package/changelog/v0.5.12.md +152 -0
- package/package.json +1 -1
- package/src/core/config.js +59 -1
- package/src/core/playground.js +502 -0
- package/src/core/router-daemon.js +861 -29
- package/src/core/utils.js +7 -0
- package/src/tui/app.js +9 -1
- package/src/tui/cli-help.js +2 -0
- package/src/tui/command-palette.js +1 -0
- package/src/tui/key-handler.js +22 -0
- package/src/tui/overlays.js +11 -0
- package/src/tui/render-helpers.js +35 -0
- package/src/tui/render-table.js +22 -7
- package/src/tui/theme.js +3 -0
- package/web/dist/assets/index-Ce_pr2YF.js +39 -0
- package/web/dist/assets/index-H9JWDRIh.css +1 -0
- package/web/dist/index.html +2 -2
- package/web/server.js +203 -1
- package/web/src/App.jsx +15 -1
- package/web/src/components/dashboard/ModelTable.jsx +9 -0
- package/web/src/components/dashboard/ModelTable.module.css +13 -0
- package/web/src/components/layout/Header.jsx +2 -1
- package/web/src/components/palette/CommandPalette.jsx +1 -0
- package/web/src/components/playground/PlaygroundView.jsx +528 -0
- package/web/src/components/playground/PlaygroundView.module.css +413 -0
- package/web/src/components/router/RouterView.jsx +519 -35
- package/web/src/components/router/RouterView.module.css +355 -0
- package/web/dist/assets/index-BrJgRhTA.css +0 -1
- package/web/dist/assets/index-BwLMt0bw.js +0 -39
package/src/core/utils.js
CHANGED
|
@@ -417,6 +417,7 @@ export function findBestModel(results) {
|
|
|
417
417
|
// --xcode, --gemini, --jcode, --copilot, --forgecode,
|
|
418
418
|
// --daemon, --daemon-bg, --daemon-stop,
|
|
419
419
|
// --daemon-status, --no-telemetry, --json, --help/-h (case-insensitive)
|
|
420
|
+
// --playground / playground subcommand (open the in-TUI chat playground)
|
|
420
421
|
// - Value flag: --tier <letter> (the next non-flag arg is the tier value)
|
|
421
422
|
//
|
|
422
423
|
// Returns:
|
|
@@ -519,6 +520,11 @@ export function parseArgs(argv) {
|
|
|
519
520
|
// 📖 --web / --gui / web subcommand — launch the web dashboard instead of the TUI
|
|
520
521
|
const webMode = flags.includes('--web') || flags.includes('--gui') || args[0] === 'web'
|
|
521
522
|
|
|
523
|
+
// 📖 --playground / playground subcommand — boot the TUI directly into the
|
|
524
|
+
// 📖 Playground chat overlay (assumes the router daemon is running or can
|
|
525
|
+
// 📖 be started with `free-coding-models --daemon-bg` first).
|
|
526
|
+
const playgroundMode = flags.includes('--playground') || args[0] === 'playground'
|
|
527
|
+
|
|
522
528
|
// New boolean flags
|
|
523
529
|
const sortDesc = flags.includes('--desc')
|
|
524
530
|
const sortAscFlag = flags.includes('--asc')
|
|
@@ -574,6 +580,7 @@ export function parseArgs(argv) {
|
|
|
574
580
|
showUnconfigured,
|
|
575
581
|
premiumMode,
|
|
576
582
|
webMode,
|
|
583
|
+
playgroundMode,
|
|
577
584
|
daemonMode,
|
|
578
585
|
daemonBackgroundMode,
|
|
579
586
|
daemonStopMode,
|
package/src/tui/app.js
CHANGED
|
@@ -343,6 +343,12 @@ export async function runApp(cliArgs, config, startupOptions = {}) {
|
|
|
343
343
|
updateInstallFailures: startupUpdate.failures || 0,
|
|
344
344
|
})
|
|
345
345
|
|
|
346
|
+
// 📖 `--playground` / `playground` subcommand: open the in-TUI chat
|
|
347
|
+
// 📖 overlay on first render so the user lands directly in the chat.
|
|
348
|
+
if (startupOptions.wantPlayground === true) {
|
|
349
|
+
state.playgroundOpen = true
|
|
350
|
+
}
|
|
351
|
+
|
|
346
352
|
// 📖 Apply the pre-fetched last release date now that state is initialized
|
|
347
353
|
state.lastReleaseDate = lastReleaseDate
|
|
348
354
|
|
|
@@ -759,7 +765,7 @@ export async function runApp(cliArgs, config, startupOptions = {}) {
|
|
|
759
765
|
// 📖 usable right now: models enter/leave as soon as ping status changes.
|
|
760
766
|
applyTierFilter()
|
|
761
767
|
// 📖 Cache visible+sorted models each frame so Enter handler always matches the display
|
|
762
|
-
if (!state.settingsOpen && !state.installEndpointsOpen && !state.toolInstallPromptOpen && !state.incompatibleFallbackOpen && !state.recommendOpen && !state.changelogOpen && !state.installedModelsOpen && !state.routerDashboardOpen && !state.commandPaletteOpen) {
|
|
768
|
+
if (!state.settingsOpen && !state.installEndpointsOpen && !state.toolInstallPromptOpen && !state.incompatibleFallbackOpen && !state.recommendOpen && !state.changelogOpen && !state.installedModelsOpen && !state.routerDashboardOpen && !state.playgroundOpen && !state.commandPaletteOpen) {
|
|
763
769
|
const visible = state.results.filter(r => !r.hidden)
|
|
764
770
|
state.visibleSorted = sortResultsWithPinnedFavorites(visible, state.sortColumn, state.sortDirection, {
|
|
765
771
|
pinFavorites: state.favoritesPinnedAndSticky,
|
|
@@ -834,6 +840,8 @@ export async function runApp(cliArgs, config, startupOptions = {}) {
|
|
|
834
840
|
? overlays.renderInstalledModels()
|
|
835
841
|
: state.routerDashboardOpen
|
|
836
842
|
? overlays.renderRouterDashboard()
|
|
843
|
+
: state.playgroundOpen
|
|
844
|
+
? overlays.renderPlayground()
|
|
837
845
|
: state.tokenUsageOpen
|
|
838
846
|
? overlays.renderTokenUsage()
|
|
839
847
|
: state.routerOnboardingOpen
|
package/src/tui/cli-help.js
CHANGED
|
@@ -37,6 +37,7 @@ const ANALYSIS_FLAGS = [
|
|
|
37
37
|
|
|
38
38
|
const CONFIG_FLAGS = [
|
|
39
39
|
{ flag: 'web | --web | --gui', description: 'Start the full-catalog realtime Web Dashboard' },
|
|
40
|
+
{ flag: 'playground | --playground', description: 'Open the in-TUI Playground chat overlay (auto-starts the router if needed)' },
|
|
40
41
|
{ flag: '--daemon', description: 'Start the FCM Router daemon + web dashboard (same port)' },
|
|
41
42
|
{ flag: '--daemon-bg', description: 'Start the FCM Router daemon in the background' },
|
|
42
43
|
{ flag: '--daemon-status', description: 'Print FCM Router daemon status JSON' },
|
|
@@ -54,6 +55,7 @@ const EXAMPLES = [
|
|
|
54
55
|
'free-coding-models --daemon-status',
|
|
55
56
|
'free-coding-models --sync-set',
|
|
56
57
|
'free-coding-models --sync-set my-coding-set',
|
|
58
|
+
'free-coding-models --playground',
|
|
57
59
|
'free-coding-models --openclaw --tier S',
|
|
58
60
|
"free-coding-models --json | jq '.[0]'",
|
|
59
61
|
]
|
|
@@ -211,6 +211,7 @@ const BASE_COMMAND_TREE = [
|
|
|
211
211
|
{ id: 'open-changelog', label: 'Changelog', icon: '📋', type: 'page', description: 'Version history', keywords: ['changelog', 'release'] },
|
|
212
212
|
|
|
213
213
|
{ id: 'open-recommend', label: 'Smart recommend', shortcut: 'Q', icon: '🎯', type: 'page', description: 'Find best model for task', keywords: ['recommend', 'best model'] },
|
|
214
|
+
{ id: 'open-playground', label: 'Playground', shortcut: ';', icon: '💬', type: 'page', description: 'Chat with the FCM router', keywords: ['playground', 'chat', 'try', 'prompt', 'router'] },
|
|
214
215
|
{ id: 'open-install-endpoints', label: 'Install endpoints', icon: '🔌', type: 'page', description: 'Install provider catalogs', keywords: ['install', 'endpoints', 'providers'] },
|
|
215
216
|
{ id: 'open-installed-models', label: 'Installed models', icon: '🗂️', type: 'page', description: 'View models configured in tools', keywords: ['installed', 'models', 'configured', 'tools', 'manager', 'goose', 'crush', 'aider'] },
|
|
216
217
|
]
|
package/src/tui/key-handler.js
CHANGED
|
@@ -55,6 +55,11 @@ import {
|
|
|
55
55
|
restartRouterDashboardDaemon,
|
|
56
56
|
toggleRouterDashboardProbePause,
|
|
57
57
|
} from '../core/router-dashboard.js'
|
|
58
|
+
import {
|
|
59
|
+
closePlaygroundOverlay,
|
|
60
|
+
openPlaygroundOverlay,
|
|
61
|
+
handlePlaygroundKeypress,
|
|
62
|
+
} from '../core/playground.js'
|
|
58
63
|
import { benchmarkModel } from '../core/benchmark.js'
|
|
59
64
|
|
|
60
65
|
// 📖 Some providers need an explicit probe model because the first catalog entry
|
|
@@ -1283,6 +1288,7 @@ export function createKeyHandler(ctx) {
|
|
|
1283
1288
|
|| state.toolInstallPromptOpen
|
|
1284
1289
|
|| state.installedModelsOpen
|
|
1285
1290
|
|| state.routerDashboardOpen
|
|
1291
|
+
|| state.playgroundOpen
|
|
1286
1292
|
|| state.recommendOpen
|
|
1287
1293
|
|
|
1288
1294
|
|| state.helpVisible
|
|
@@ -1475,6 +1481,7 @@ export function createKeyHandler(ctx) {
|
|
|
1475
1481
|
|
|
1476
1482
|
case 'open-recommend': return openRecommendOverlay()
|
|
1477
1483
|
case 'open-router-dashboard': return openRouterDashboardOverlay(state)
|
|
1484
|
+
case 'open-playground': return openPlaygroundOverlay(state)
|
|
1478
1485
|
case 'open-token-usage': return openTokenUsageOverlay()
|
|
1479
1486
|
case 'open-install-endpoints': return openInstallEndpointsOverlay()
|
|
1480
1487
|
case 'open-installed-models': return openInstalledModelsOverlay()
|
|
@@ -1745,6 +1752,14 @@ export function createKeyHandler(ctx) {
|
|
|
1745
1752
|
return
|
|
1746
1753
|
}
|
|
1747
1754
|
|
|
1755
|
+
// 📖 Playground overlay: handles Enter, Esc, Backspace, Ctrl+S, Ctrl+L,
|
|
1756
|
+
// 📖 PageUp/PageDown, and printable input itself. The dedicated handler
|
|
1757
|
+
// 📖 in core/playground.js owns the draft and submission state.
|
|
1758
|
+
if (state.playgroundOpen) {
|
|
1759
|
+
if (handlePlaygroundKeypress(key.string != null ? key.string : key.name, { fetchFn: globalThis.fetch })) return
|
|
1760
|
+
return
|
|
1761
|
+
}
|
|
1762
|
+
|
|
1748
1763
|
// 📖 Install Endpoints overlay: provider → tool → connection → scope → optional model subset.
|
|
1749
1764
|
if (state.installEndpointsOpen) {
|
|
1750
1765
|
if (key.ctrl && key.name === 'c') { exit(0); return }
|
|
@@ -2838,6 +2853,13 @@ export function createKeyHandler(ctx) {
|
|
|
2838
2853
|
return
|
|
2839
2854
|
}
|
|
2840
2855
|
|
|
2856
|
+
// 📖 ; (semicolon) key: open the Playground chat overlay. Avoids clashes
|
|
2857
|
+
// 📖 with P (settings), K (help), Z (tool), N (changelog), etc.
|
|
2858
|
+
if (key.name === ';' || (key.shift && key.name === ':')) {
|
|
2859
|
+
void openPlaygroundOverlay(state)
|
|
2860
|
+
return
|
|
2861
|
+
}
|
|
2862
|
+
|
|
2841
2863
|
// 📖 Y key toggles favorites display mode (pinned+sticky vs normal rows).
|
|
2842
2864
|
if (key.name === 'y' && !key.ctrl && !key.meta) {
|
|
2843
2865
|
toggleFavoritesDisplayMode()
|
package/src/tui/overlays.js
CHANGED
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
import { loadChangelog } from '../core/changelog-loader.js'
|
|
23
23
|
import { buildCliHelpLines } from './cli-help.js'
|
|
24
24
|
import { renderRouterDashboard as renderRouterDashboardOverlay } from '../core/router-dashboard.js'
|
|
25
|
+
import { renderPlayground as renderPlaygroundOverlay } from '../core/playground.js'
|
|
25
26
|
import { themeColors, getThemeStatusLabel, getProviderRgb } from './theme.js'
|
|
26
27
|
|
|
27
28
|
export function createOverlayRenderers(state, deps) {
|
|
@@ -1334,6 +1335,15 @@ export function createOverlayRenderers(state, deps) {
|
|
|
1334
1335
|
return renderRouterDashboardOverlay(state, { LOCAL_VERSION })
|
|
1335
1336
|
}
|
|
1336
1337
|
|
|
1338
|
+
// ─── Playground overlay ───────────────────────────────────────────────────────
|
|
1339
|
+
// 📖 Renders the in-TUI chat playground when the user presses `;` or opens
|
|
1340
|
+
// 📖 it from the command palette. All chat traffic flows to the local
|
|
1341
|
+
// 📖 daemon over HTTP, so the TUI process never has to import the
|
|
1342
|
+
// 📖 provider catalog.
|
|
1343
|
+
function renderPlayground() {
|
|
1344
|
+
return renderPlaygroundOverlay(state, state.terminalRows, state.terminalCols)
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1337
1347
|
// ─── Incompatible fallback overlay ─────────────────────────────────────────
|
|
1338
1348
|
// 📖 renderIncompatibleFallback shows when user presses Enter on a model that
|
|
1339
1349
|
// 📖 is NOT compatible with the active tool. Two sections:
|
|
@@ -1615,6 +1625,7 @@ export function createOverlayRenderers(state, deps) {
|
|
|
1615
1625
|
renderChangelog,
|
|
1616
1626
|
renderInstalledModels,
|
|
1617
1627
|
renderRouterDashboard,
|
|
1628
|
+
renderPlayground,
|
|
1618
1629
|
renderIncompatibleFallback,
|
|
1619
1630
|
renderTokenUsage,
|
|
1620
1631
|
renderRouterOnboarding,
|
|
@@ -31,6 +31,8 @@
|
|
|
31
31
|
* - `calculateViewport`: Compute visible slice of model rows
|
|
32
32
|
* - `sortResultsWithPinnedFavorites`: Sort with pinned items at top
|
|
33
33
|
* - `adjustScrollOffset`: Clamp scrollOffset so cursor stays visible
|
|
34
|
+
* - `fadedRow`: Multiply every 24-bit RGB channel by a factor to fade an
|
|
35
|
+
* entire ANSI-colored line uniformly — used for "unusable" rows.
|
|
34
36
|
*
|
|
35
37
|
* 📦 Dependencies:
|
|
36
38
|
* - chalk: Terminal colors and formatting
|
|
@@ -56,6 +58,39 @@ export function stripAnsi(input) {
|
|
|
56
58
|
return String(input).replace(/\x1b\[[0-9;]*m/g, '').replace(/\x1b\][^\x1b]*\x1b\\/g, '')
|
|
57
59
|
}
|
|
58
60
|
|
|
61
|
+
// 📖 fadedRow: Multiply every 24-bit RGB channel inside an ANSI-colored string by `factor`
|
|
62
|
+
// 📖 (default 0.8 = 80% opacity, i.e. 20% less opaque) so the whole line reads as
|
|
63
|
+
// 📖 uniformly faded. Only foreground/background 24-bit SGR codes (38;2;R;G;B and
|
|
64
|
+
// 📖 48;2;R;G;B) are touched — bold, dim, reset codes, hyperlinks, and cursor SGRs
|
|
65
|
+
// 📖 pass through unchanged so the structural styling stays intact.
|
|
66
|
+
// 📖 Used to make "unusable" rows (NO KEY / AUTH FAIL) visually de-emphasized at
|
|
67
|
+
// 📖 the row level rather than dimming a single cell, which is easier to miss at
|
|
68
|
+
// 📖 a glance when scanning the table.
|
|
69
|
+
// 📖 Channels are clamped to 0–255 and rounded to integers so terminal parsers
|
|
70
|
+
// 📖 never receive an out-of-range byte. When `factor >= 1` the input is returned
|
|
71
|
+
// 📖 untouched (identity fast path) so callers can wire this in without paying
|
|
72
|
+
// 📖 the cost on every row.
|
|
73
|
+
export function fadedRow(input, factor = 0.8) {
|
|
74
|
+
const text = String(input)
|
|
75
|
+
if (factor >= 1) return text
|
|
76
|
+
// 📖 Pre-clamp factor to [0, 1] to avoid negative channel values that would
|
|
77
|
+
// 📖 confuse downstream regex replacements; we still respect very small values
|
|
78
|
+
// 📖 so a caller can pass e.g. 0.1 to almost black-out a row.
|
|
79
|
+
const safeFactor = Math.max(0, Math.min(1, factor))
|
|
80
|
+
return text.replace(
|
|
81
|
+
/\x1b\[(38|48);2;(\d+);(\d+);(\d+)m/g,
|
|
82
|
+
(_match, kind, rStr, gStr, bStr) => {
|
|
83
|
+
const r = parseInt(rStr, 10)
|
|
84
|
+
const g = parseInt(gStr, 10)
|
|
85
|
+
const b = parseInt(bStr, 10)
|
|
86
|
+
const nr = Math.max(0, Math.min(255, Math.round(r * safeFactor)))
|
|
87
|
+
const ng = Math.max(0, Math.min(255, Math.round(g * safeFactor)))
|
|
88
|
+
const nb = Math.max(0, Math.min(255, Math.round(b * safeFactor)))
|
|
89
|
+
return `\x1b[${kind};2;${nr};${ng};${nb}m`
|
|
90
|
+
}
|
|
91
|
+
)
|
|
92
|
+
}
|
|
93
|
+
|
|
59
94
|
// 📖 maskApiKey: Mask all but first 4 and last 3 characters of an API key.
|
|
60
95
|
// 📖 Prevents accidental disclosure of secrets in TUI display.
|
|
61
96
|
export function maskApiKey(key) {
|
package/src/tui/render-table.js
CHANGED
|
@@ -17,6 +17,8 @@
|
|
|
17
17
|
* - High-visibility active text-filter banner with one-key clear action (`X`)
|
|
18
18
|
* - Full-width red outdated-version banner when a newer npm release is known
|
|
19
19
|
* - Distinct auth-failure vs missing-key health labels so configured providers stay honest
|
|
20
|
+
* - 80%-opacity row fade for "unusable" models (NO KEY / AUTH FAIL) so the user can spot at a glance
|
|
21
|
+
* which rows are not actually reachable, even when the cursor is parked elsewhere
|
|
20
22
|
*
|
|
21
23
|
* → Functions:
|
|
22
24
|
* - `renderTable` — Render the full TUI table as a string (no side effects)
|
|
@@ -27,7 +29,7 @@
|
|
|
27
29
|
* - ../src/tier-colors.js: TIER_COLOR
|
|
28
30
|
* - ../src/utils.js: getAvg, getVerdict, getUptime, getStabilityScore
|
|
29
31
|
* - ../src/ping.js: usagePlaceholderForProvider
|
|
30
|
-
* - ../src/render-helpers.js: calculateViewport, sortResultsWithPinnedFavorites, padEndDisplay
|
|
32
|
+
* - ../src/render-helpers.js: calculateViewport, sortResultsWithPinnedFavorites, padEndDisplay, fadedRow
|
|
31
33
|
*
|
|
32
34
|
* @see bin/free-coding-models.js — main entry point that calls renderTable
|
|
33
35
|
*/
|
|
@@ -50,7 +52,7 @@ import { TIER_COLOR } from './tier-colors.js'
|
|
|
50
52
|
import { getAvg, getVerdict, getUptime, getStabilityScore, getVersionStatusInfo } from '../core/utils.js'
|
|
51
53
|
import { usagePlaceholderForProvider } from '../core/ping.js'
|
|
52
54
|
import { formatBenchmarkLatency, formatBenchmarkTps } from '../core/benchmark.js'
|
|
53
|
-
import { calculateViewport, sortResultsWithPinnedFavorites, padEndDisplay, displayWidth, stripAnsi } from './render-helpers.js'
|
|
55
|
+
import { calculateViewport, sortResultsWithPinnedFavorites, padEndDisplay, displayWidth, stripAnsi, fadedRow } from './render-helpers.js'
|
|
54
56
|
import { getToolMeta, TOOL_METADATA, TOOL_MODE_ORDER, isModelCompatibleWithTool } from '../core/tool-metadata.js'
|
|
55
57
|
import { getColumnSpacing } from './ui-config.js'
|
|
56
58
|
import { detectPackageManager, getManualInstallCmd } from '../core/updater.js'
|
|
@@ -946,20 +948,33 @@ export function renderTable({
|
|
|
946
948
|
if (showBenchmarkColumns) rowParts.push(latencyCell, tpsCell)
|
|
947
949
|
const row = ' ' + rowParts.join(COL_SEP)
|
|
948
950
|
|
|
951
|
+
// 📖 "Unusable" models (no key / bad key) are visually de-emphasized at the
|
|
952
|
+
// 📖 row level. The user cannot actually send a request to these models, so
|
|
953
|
+
// 📖 we drop the whole line to 80% opacity (20% less opaque) so it stands
|
|
954
|
+
// 📖 out from working rows at a glance, even if the cursor is parked on a
|
|
955
|
+
// 📖 different model. The cursor always wins so the user never loses track
|
|
956
|
+
// 📖 of their active selection. fadedRow multiplies every 24-bit RGB
|
|
957
|
+
// 📖 channel by 0.8 so the result works on every terminal that supports
|
|
958
|
+
// 📖 truecolor (no reliance on the SGR 2 "faint" code, which is ignored by
|
|
959
|
+
// 📖 some terminals).
|
|
960
|
+
const isUnusable = r.status === 'noauth' || r.status === 'auth_error'
|
|
961
|
+
|
|
962
|
+
let renderedRow
|
|
949
963
|
if (isCursor) {
|
|
950
|
-
|
|
964
|
+
renderedRow = themeColors.bgModelCursor(row)
|
|
951
965
|
} else if (isIncompatible) {
|
|
952
966
|
// 📖 Dark red background for models incompatible with the active tool mode.
|
|
953
967
|
// 📖 This visually warns the user that selecting this model won't work with their current tool.
|
|
954
|
-
|
|
968
|
+
renderedRow = chalk.bgRgb(60, 15, 15).rgb(180, 130, 130)(row)
|
|
955
969
|
} else if (r.isRecommended) {
|
|
956
970
|
// 📖 Medium green background for recommended models (distinguishable from favorites)
|
|
957
|
-
|
|
971
|
+
renderedRow = themeColors.bgModelRecommended(row)
|
|
958
972
|
} else if (r.isFavorite) {
|
|
959
|
-
|
|
973
|
+
renderedRow = themeColors.bgModelFavorite(row)
|
|
960
974
|
} else {
|
|
961
|
-
|
|
975
|
+
renderedRow = row
|
|
962
976
|
}
|
|
977
|
+
lines.push(isUnusable ? fadedRow(renderedRow, 0.8) : renderedRow)
|
|
963
978
|
}
|
|
964
979
|
|
|
965
980
|
// 📖 Mouse support: record the 1-based terminal row range of model data rows.
|
package/src/tui/theme.js
CHANGED
|
@@ -53,6 +53,7 @@ const PALETTES = {
|
|
|
53
53
|
feedback: [31, 13, 20],
|
|
54
54
|
changelog: [12, 24, 44],
|
|
55
55
|
commandPalette: [14, 20, 36],
|
|
56
|
+
playground: [10, 22, 18],
|
|
56
57
|
},
|
|
57
58
|
cursor: {
|
|
58
59
|
defaultBg: [39, 55, 90],
|
|
@@ -99,6 +100,7 @@ const PALETTES = {
|
|
|
99
100
|
feedback: [255, 247, 248],
|
|
100
101
|
changelog: [244, 248, 255],
|
|
101
102
|
commandPalette: [242, 247, 255],
|
|
103
|
+
playground: [244, 252, 246],
|
|
102
104
|
},
|
|
103
105
|
cursor: {
|
|
104
106
|
defaultBg: [217, 231, 255],
|
|
@@ -326,5 +328,6 @@ export const themeColors = {
|
|
|
326
328
|
overlayBgRecommend: (text) => paintBg(currentPalette().overlayBg.recommend, text, currentPalette().overlayFg),
|
|
327
329
|
overlayBgFeedback: (text) => paintBg(currentPalette().overlayBg.feedback, text, currentPalette().overlayFg),
|
|
328
330
|
overlayBgChangelog: (text) => paintBg(currentPalette().overlayBg.changelog, text, currentPalette().overlayFg),
|
|
331
|
+
overlayBgPlayground: (text) => paintBg(currentPalette().overlayBg.playground, text, currentPalette().overlayFg),
|
|
329
332
|
overlayBgCommandPalette: (text) => paintBg(currentPalette().overlayBg.commandPalette, text, currentPalette().overlayFg),
|
|
330
333
|
}
|