wip: desktop work

This commit is contained in:
Adam
2025-09-19 06:05:05 -05:00
parent 20cb5a7c56
commit b1e6b9c7c9
8 changed files with 605 additions and 383 deletions

View File

@@ -24,7 +24,8 @@
"@solidjs/router": "0.15.3",
"@thisbeyond/solid-dnd": "0.7.5",
"diff": "8.0.2",
"luxon": "3.7.1",
"fuzzysort": "catalog:",
"luxon": "catalog:",
"marked": "16.2.0",
"marked-shiki": "1.2.1",
"remeda": "catalog:",
@@ -218,11 +219,11 @@
"diff": "8.0.2",
"js-base64": "3.7.7",
"lang-map": "0.4.0",
"luxon": "3.6.1",
"luxon": "catalog:",
"marked": "15.0.12",
"marked-shiki": "1.2.1",
"rehype-autolink-headings": "7.1.0",
"remeda": "2.26.0",
"remeda": "catalog:",
"sharp": "0.32.5",
"shiki": "3.4.2",
"solid-js": "catalog:",
@@ -249,7 +250,9 @@
"@types/bun": "1.2.21",
"@types/node": "22.13.9",
"ai": "5.0.8",
"fuzzysort": "3.1.0",
"hono": "4.7.10",
"luxon": "3.6.1",
"remeda": "2.26.0",
"solid-js": "1.9.9",
"typescript": "5.8.2",
@@ -1660,6 +1663,8 @@
"function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
"fuzzysort": ["fuzzysort@3.1.0", "", {}, "sha512-sR9BNCjBg6LNgwvxlBd0sBABvQitkLzoVY9MYYROQVX/FvfJ4Mai9LsGhDgd8qYdds0bY77VzYd5iuB+v5rwQQ=="],
"gel": ["gel@2.1.1", "", { "dependencies": { "@petamoriken/float16": "^3.8.7", "debug": "^4.3.4", "env-paths": "^3.0.0", "semver": "^7.6.2", "shell-quote": "^1.8.1", "which": "^4.0.0" }, "bin": { "gel": "dist/cli.mjs" } }, "sha512-Newg9X7mRYskoBjSw70l1YnJ/ZGbq64VPyR821H5WVkTGpHG2O0mQILxCeUhxdYERLFY9B4tUyKLyf3uMTjtKw=="],
"generate-function": ["generate-function@2.3.1", "", { "dependencies": { "is-property": "^1.0.2" } }, "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ=="],
@@ -1988,7 +1993,7 @@
"lru.min": ["lru.min@1.1.2", "", {}, "sha512-Nv9KddBcQSlQopmBHXSsZVY5xsdlZkdH/Iey0BlcBYggMd4two7cZnKOK9vmy3nY0O5RGH99z1PCeTpPqszUYg=="],
"luxon": ["luxon@3.7.1", "", {}, "sha512-RkRWjA926cTvz5rAb1BqyWkKbbjzCGchDUIKMCUvNi17j6f6j8uHGDV82Aqcqtzd+icoYpELmG3ksgGiFNNcNg=="],
"luxon": ["luxon@3.6.1", "", {}, "sha512-tJLxrKJhO2ukZ5z0gyjY1zPh3Rh88Ej9P7jNrZiHMUXHae1yvI2imgOZtL1TO8TW6biMMKfTtAOoEJANgtWBMQ=="],
"magic-string": ["magic-string@0.30.19", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw=="],
@@ -3034,8 +3039,6 @@
"@opencode/web/@types/luxon": ["@types/luxon@3.6.2", "", {}, "sha512-R/BdP7OxEMc44l2Ex5lSXHoIXTB2JLNa3y2QISIbr58U/YcsffyQrYW//hZSdrfxrjRZj3GcUoxMPGdO8gSYuw=="],
"@opencode/web/luxon": ["luxon@3.6.1", "", {}, "sha512-tJLxrKJhO2ukZ5z0gyjY1zPh3Rh88Ej9P7jNrZiHMUXHae1yvI2imgOZtL1TO8TW6biMMKfTtAOoEJANgtWBMQ=="],
"@opencode/web/marked": ["marked@15.0.12", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA=="],
"@opencode/web/shiki": ["shiki@3.4.2", "", { "dependencies": { "@shikijs/core": "3.4.2", "@shikijs/engine-javascript": "3.4.2", "@shikijs/engine-oniguruma": "3.4.2", "@shikijs/langs": "3.4.2", "@shikijs/themes": "3.4.2", "@shikijs/types": "3.4.2", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-wuxzZzQG8kvZndD7nustrNFIKYJ1jJoWIPaBpVe2+KHSvtzMi4SBjOxrigs8qeqce/l3U0cwiC+VAkLKSunHQQ=="],

View File

@@ -23,6 +23,8 @@
"@tsconfig/node22": "22.0.2",
"ai": "5.0.8",
"hono": "4.7.10",
"fuzzysort": "3.1.0",
"luxon": "3.6.1",
"typescript": "5.8.2",
"zod": "4.1.8",
"remeda": "2.26.0",

View File

@@ -29,7 +29,8 @@
"@solidjs/router": "0.15.3",
"@thisbeyond/solid-dnd": "0.7.5",
"diff": "8.0.2",
"luxon": "3.7.1",
"fuzzysort": "catalog:",
"luxon": "catalog:",
"marked": "16.2.0",
"marked-shiki": "1.2.1",
"remeda": "catalog:",

View File

@@ -159,109 +159,109 @@
}
[data-theme="ayu"][data-dark="false"] {
--theme-primary: #59c2ff;
--theme-secondary: #d2a6ff;
--theme-accent: #e6b450;
--theme-error: #d95757;
--theme-warning: #e6b673;
--theme-success: #7fd962;
--theme-info: #39bae6;
--theme-text: #bfbdb6;
--theme-text-muted: #565b66;
--theme-background: #0b0e14;
--theme-background-panel: #0f131a;
--theme-background-element: #0d1017;
--theme-border: #6c7380;
--theme-border-active: #6c7380;
--theme-border-subtle: #11151c;
--theme-diff-added: #7fd962;
--theme-diff-removed: #f26d78;
--theme-diff-context: #acb6bf;
--theme-diff-hunk-header: #acb6bf;
--theme-diff-highlight-added: #aad94c;
--theme-diff-highlight-removed: #f07178;
--theme-primary: #59C2FF;
--theme-secondary: #D2A6FF;
--theme-accent: #E6B450;
--theme-error: #D95757;
--theme-warning: #E6B673;
--theme-success: #7FD962;
--theme-info: #39BAE6;
--theme-text: #BFBDB6;
--theme-text-muted: #565B66;
--theme-background: #0B0E14;
--theme-background-panel: #0F131A;
--theme-background-element: #0D1017;
--theme-border: #6C7380;
--theme-border-active: #6C7380;
--theme-border-subtle: #11151C;
--theme-diff-added: #7FD962;
--theme-diff-removed: #F26D78;
--theme-diff-context: #ACB6BF;
--theme-diff-hunk-header: #ACB6BF;
--theme-diff-highlight-added: #AAD94C;
--theme-diff-highlight-removed: #F07178;
--theme-diff-added-bg: #20303b;
--theme-diff-removed-bg: #37222c;
--theme-diff-context-bg: #0f131a;
--theme-diff-line-number: #6c7380;
--theme-diff-context-bg: #0F131A;
--theme-diff-line-number: #6C7380;
--theme-diff-added-line-number-bg: #1b2b34;
--theme-diff-removed-line-number-bg: #2d1f26;
--theme-markdown-text: #bfbdb6;
--theme-markdown-heading: #d2a6ff;
--theme-markdown-link: #59c2ff;
--theme-markdown-link-text: #39bae6;
--theme-markdown-code: #aad94c;
--theme-markdown-block-quote: #e6b673;
--theme-markdown-emph: #e6b673;
--theme-markdown-strong: #ffb454;
--theme-markdown-horizontal-rule: #565b66;
--theme-markdown-list-item: #59c2ff;
--theme-markdown-list-enumeration: #39bae6;
--theme-markdown-image: #59c2ff;
--theme-markdown-image-text: #39bae6;
--theme-markdown-code-block: #bfbdb6;
--theme-syntax-comment: #acb6bf;
--theme-syntax-keyword: #ff8f40;
--theme-syntax-function: #ffb454;
--theme-syntax-variable: #59c2ff;
--theme-syntax-string: #aad94c;
--theme-syntax-number: #d2a6ff;
--theme-syntax-type: #e6b673;
--theme-syntax-operator: #f29668;
--theme-syntax-punctuation: #bfbdb6;
--theme-markdown-text: #BFBDB6;
--theme-markdown-heading: #D2A6FF;
--theme-markdown-link: #59C2FF;
--theme-markdown-link-text: #39BAE6;
--theme-markdown-code: #AAD94C;
--theme-markdown-block-quote: #E6B673;
--theme-markdown-emph: #E6B673;
--theme-markdown-strong: #FFB454;
--theme-markdown-horizontal-rule: #565B66;
--theme-markdown-list-item: #59C2FF;
--theme-markdown-list-enumeration: #39BAE6;
--theme-markdown-image: #59C2FF;
--theme-markdown-image-text: #39BAE6;
--theme-markdown-code-block: #BFBDB6;
--theme-syntax-comment: #ACB6BF;
--theme-syntax-keyword: #FF8F40;
--theme-syntax-function: #FFB454;
--theme-syntax-variable: #59C2FF;
--theme-syntax-string: #AAD94C;
--theme-syntax-number: #D2A6FF;
--theme-syntax-type: #E6B673;
--theme-syntax-operator: #F29668;
--theme-syntax-punctuation: #BFBDB6;
}
[data-theme="ayu"][data-dark="true"] {
--theme-primary: #59c2ff;
--theme-secondary: #d2a6ff;
--theme-accent: #e6b450;
--theme-error: #d95757;
--theme-warning: #e6b673;
--theme-success: #7fd962;
--theme-info: #39bae6;
--theme-text: #bfbdb6;
--theme-text-muted: #565b66;
--theme-background: #0b0e14;
--theme-background-panel: #0f131a;
--theme-background-element: #0d1017;
--theme-border: #6c7380;
--theme-border-active: #6c7380;
--theme-border-subtle: #11151c;
--theme-diff-added: #7fd962;
--theme-diff-removed: #f26d78;
--theme-diff-context: #acb6bf;
--theme-diff-hunk-header: #acb6bf;
--theme-diff-highlight-added: #aad94c;
--theme-diff-highlight-removed: #f07178;
--theme-primary: #59C2FF;
--theme-secondary: #D2A6FF;
--theme-accent: #E6B450;
--theme-error: #D95757;
--theme-warning: #E6B673;
--theme-success: #7FD962;
--theme-info: #39BAE6;
--theme-text: #BFBDB6;
--theme-text-muted: #565B66;
--theme-background: #0B0E14;
--theme-background-panel: #0F131A;
--theme-background-element: #0D1017;
--theme-border: #6C7380;
--theme-border-active: #6C7380;
--theme-border-subtle: #11151C;
--theme-diff-added: #7FD962;
--theme-diff-removed: #F26D78;
--theme-diff-context: #ACB6BF;
--theme-diff-hunk-header: #ACB6BF;
--theme-diff-highlight-added: #AAD94C;
--theme-diff-highlight-removed: #F07178;
--theme-diff-added-bg: #20303b;
--theme-diff-removed-bg: #37222c;
--theme-diff-context-bg: #0f131a;
--theme-diff-line-number: #6c7380;
--theme-diff-context-bg: #0F131A;
--theme-diff-line-number: #6C7380;
--theme-diff-added-line-number-bg: #1b2b34;
--theme-diff-removed-line-number-bg: #2d1f26;
--theme-markdown-text: #bfbdb6;
--theme-markdown-heading: #d2a6ff;
--theme-markdown-link: #59c2ff;
--theme-markdown-link-text: #39bae6;
--theme-markdown-code: #aad94c;
--theme-markdown-block-quote: #e6b673;
--theme-markdown-emph: #e6b673;
--theme-markdown-strong: #ffb454;
--theme-markdown-horizontal-rule: #565b66;
--theme-markdown-list-item: #59c2ff;
--theme-markdown-list-enumeration: #39bae6;
--theme-markdown-image: #59c2ff;
--theme-markdown-image-text: #39bae6;
--theme-markdown-code-block: #bfbdb6;
--theme-syntax-comment: #acb6bf;
--theme-syntax-keyword: #ff8f40;
--theme-syntax-function: #ffb454;
--theme-syntax-variable: #59c2ff;
--theme-syntax-string: #aad94c;
--theme-syntax-number: #d2a6ff;
--theme-syntax-type: #e6b673;
--theme-syntax-operator: #f29668;
--theme-syntax-punctuation: #bfbdb6;
--theme-markdown-text: #BFBDB6;
--theme-markdown-heading: #D2A6FF;
--theme-markdown-link: #59C2FF;
--theme-markdown-link-text: #39BAE6;
--theme-markdown-code: #AAD94C;
--theme-markdown-block-quote: #E6B673;
--theme-markdown-emph: #E6B673;
--theme-markdown-strong: #FFB454;
--theme-markdown-horizontal-rule: #565B66;
--theme-markdown-list-item: #59C2FF;
--theme-markdown-list-enumeration: #39BAE6;
--theme-markdown-image: #59C2FF;
--theme-markdown-image-text: #39BAE6;
--theme-markdown-code-block: #BFBDB6;
--theme-syntax-comment: #ACB6BF;
--theme-syntax-keyword: #FF8F40;
--theme-syntax-function: #FFB454;
--theme-syntax-variable: #59C2FF;
--theme-syntax-string: #AAD94C;
--theme-syntax-number: #D2A6FF;
--theme-syntax-type: #E6B673;
--theme-syntax-operator: #F29668;
--theme-syntax-punctuation: #BFBDB6;
}
[data-theme="catppuccin"][data-dark="false"] {
@@ -901,109 +901,109 @@
}
[data-theme="kanagawa"][data-dark="false"] {
--theme-primary: #2d4f67;
--theme-secondary: #957fb8;
--theme-accent: #d27e99;
--theme-error: #e82424;
--theme-warning: #d7a657;
--theme-success: #98bb6c;
--theme-info: #76946a;
--theme-text: #54433a;
--theme-text-muted: #9e9389;
--theme-background: #f2e9de;
--theme-background-panel: #eae4d7;
--theme-background-element: #e3dcd2;
--theme-border: #d4cbbf;
--theme-border-active: #c38d9d;
--theme-border-subtle: #dcd4c9;
--theme-diff-added: #98bb6c;
--theme-diff-removed: #e82424;
--theme-diff-context: #9e9389;
--theme-diff-hunk-header: #2d4f67;
--theme-diff-highlight-added: #89af5b;
--theme-diff-highlight-removed: #d61f1f;
--theme-diff-added-bg: #eaf3e4;
--theme-diff-removed-bg: #fbe6e6;
--theme-diff-context-bg: #eae4d7;
--theme-diff-line-number: #c7beb4;
--theme-diff-added-line-number-bg: #dde8d6;
--theme-diff-removed-line-number-bg: #f2dada;
--theme-markdown-text: #54433a;
--theme-markdown-heading: #957fb8;
--theme-markdown-link: #2d4f67;
--theme-markdown-link-text: #76946a;
--theme-markdown-code: #98bb6c;
--theme-markdown-block-quote: #9e9389;
--theme-markdown-emph: #c38d9d;
--theme-markdown-strong: #d7a657;
--theme-markdown-horizontal-rule: #9e9389;
--theme-markdown-list-item: #2d4f67;
--theme-markdown-list-enumeration: #76946a;
--theme-markdown-image: #2d4f67;
--theme-markdown-image-text: #76946a;
--theme-markdown-code-block: #54433a;
--theme-syntax-comment: #9e9389;
--theme-syntax-keyword: #957fb8;
--theme-syntax-function: #2d4f67;
--theme-syntax-variable: #54433a;
--theme-syntax-string: #98bb6c;
--theme-syntax-number: #d7a657;
--theme-syntax-type: #c38d9d;
--theme-syntax-operator: #d27e99;
--theme-syntax-punctuation: #54433a;
--theme-primary: #2D4F67;
--theme-secondary: #957FB8;
--theme-accent: #D27E99;
--theme-error: #E82424;
--theme-warning: #D7A657;
--theme-success: #98BB6C;
--theme-info: #76946A;
--theme-text: #54433A;
--theme-text-muted: #9E9389;
--theme-background: #F2E9DE;
--theme-background-panel: #EAE4D7;
--theme-background-element: #E3DCD2;
--theme-border: #D4CBBF;
--theme-border-active: #C38D9D;
--theme-border-subtle: #DCD4C9;
--theme-diff-added: #98BB6C;
--theme-diff-removed: #E82424;
--theme-diff-context: #9E9389;
--theme-diff-hunk-header: #2D4F67;
--theme-diff-highlight-added: #89AF5B;
--theme-diff-highlight-removed: #D61F1F;
--theme-diff-added-bg: #EAF3E4;
--theme-diff-removed-bg: #FBE6E6;
--theme-diff-context-bg: #EAE4D7;
--theme-diff-line-number: #C7BEB4;
--theme-diff-added-line-number-bg: #DDE8D6;
--theme-diff-removed-line-number-bg: #F2DADA;
--theme-markdown-text: #54433A;
--theme-markdown-heading: #957FB8;
--theme-markdown-link: #2D4F67;
--theme-markdown-link-text: #76946A;
--theme-markdown-code: #98BB6C;
--theme-markdown-block-quote: #9E9389;
--theme-markdown-emph: #C38D9D;
--theme-markdown-strong: #D7A657;
--theme-markdown-horizontal-rule: #9E9389;
--theme-markdown-list-item: #2D4F67;
--theme-markdown-list-enumeration: #76946A;
--theme-markdown-image: #2D4F67;
--theme-markdown-image-text: #76946A;
--theme-markdown-code-block: #54433A;
--theme-syntax-comment: #9E9389;
--theme-syntax-keyword: #957FB8;
--theme-syntax-function: #2D4F67;
--theme-syntax-variable: #54433A;
--theme-syntax-string: #98BB6C;
--theme-syntax-number: #D7A657;
--theme-syntax-type: #C38D9D;
--theme-syntax-operator: #D27E99;
--theme-syntax-punctuation: #54433A;
}
[data-theme="kanagawa"][data-dark="true"] {
--theme-primary: #7e9cd8;
--theme-secondary: #957fb8;
--theme-accent: #d27e99;
--theme-error: #e82424;
--theme-warning: #d7a657;
--theme-success: #98bb6c;
--theme-info: #76946a;
--theme-text: #dcd7ba;
--theme-primary: #7E9CD8;
--theme-secondary: #957FB8;
--theme-accent: #D27E99;
--theme-error: #E82424;
--theme-warning: #D7A657;
--theme-success: #98BB6C;
--theme-info: #76946A;
--theme-text: #DCD7BA;
--theme-text-muted: #727169;
--theme-background: #1f1f28;
--theme-background-panel: #2a2a37;
--theme-background: #1F1F28;
--theme-background-panel: #2A2A37;
--theme-background-element: #363646;
--theme-border: #54546d;
--theme-border-active: #c38d9d;
--theme-border: #54546D;
--theme-border-active: #C38D9D;
--theme-border-subtle: #363646;
--theme-diff-added: #98bb6c;
--theme-diff-removed: #e82424;
--theme-diff-added: #98BB6C;
--theme-diff-removed: #E82424;
--theme-diff-context: #727169;
--theme-diff-hunk-header: #2d4f67;
--theme-diff-highlight-added: #a9d977;
--theme-diff-highlight-removed: #f24a4a;
--theme-diff-added-bg: #252e25;
--theme-diff-hunk-header: #2D4F67;
--theme-diff-highlight-added: #A9D977;
--theme-diff-highlight-removed: #F24A4A;
--theme-diff-added-bg: #252E25;
--theme-diff-removed-bg: #362020;
--theme-diff-context-bg: #2a2a37;
--theme-diff-line-number: #54546d;
--theme-diff-context-bg: #2A2A37;
--theme-diff-line-number: #54546D;
--theme-diff-added-line-number-bg: #202820;
--theme-diff-removed-line-number-bg: #2d1c1c;
--theme-markdown-text: #dcd7ba;
--theme-markdown-heading: #957fb8;
--theme-markdown-link: #7e9cd8;
--theme-markdown-link-text: #76946a;
--theme-markdown-code: #98bb6c;
--theme-diff-removed-line-number-bg: #2D1C1C;
--theme-markdown-text: #DCD7BA;
--theme-markdown-heading: #957FB8;
--theme-markdown-link: #7E9CD8;
--theme-markdown-link-text: #76946A;
--theme-markdown-code: #98BB6C;
--theme-markdown-block-quote: #727169;
--theme-markdown-emph: #c38d9d;
--theme-markdown-strong: #d7a657;
--theme-markdown-emph: #C38D9D;
--theme-markdown-strong: #D7A657;
--theme-markdown-horizontal-rule: #727169;
--theme-markdown-list-item: #7e9cd8;
--theme-markdown-list-enumeration: #76946a;
--theme-markdown-image: #7e9cd8;
--theme-markdown-image-text: #76946a;
--theme-markdown-code-block: #dcd7ba;
--theme-markdown-list-item: #7E9CD8;
--theme-markdown-list-enumeration: #76946A;
--theme-markdown-image: #7E9CD8;
--theme-markdown-image-text: #76946A;
--theme-markdown-code-block: #DCD7BA;
--theme-syntax-comment: #727169;
--theme-syntax-keyword: #957fb8;
--theme-syntax-function: #7e9cd8;
--theme-syntax-variable: #dcd7ba;
--theme-syntax-string: #98bb6c;
--theme-syntax-number: #d7a657;
--theme-syntax-type: #c38d9d;
--theme-syntax-operator: #d27e99;
--theme-syntax-punctuation: #dcd7ba;
--theme-syntax-keyword: #957FB8;
--theme-syntax-function: #7E9CD8;
--theme-syntax-variable: #DCD7BA;
--theme-syntax-string: #98BB6C;
--theme-syntax-number: #D7A657;
--theme-syntax-type: #C38D9D;
--theme-syntax-operator: #D27E99;
--theme-syntax-punctuation: #DCD7BA;
}
[data-theme="material"][data-dark="false"] {
@@ -1325,109 +1325,109 @@
}
[data-theme="nord"][data-dark="false"] {
--theme-primary: #5e81ac;
--theme-secondary: #81a1c1;
--theme-accent: #8fbcbb;
--theme-error: #bf616a;
--theme-warning: #d08770;
--theme-success: #a3be8c;
--theme-info: #5e81ac;
--theme-text: #2e3440;
--theme-text-muted: #3b4252;
--theme-background: #eceff4;
--theme-background-panel: #e5e9f0;
--theme-background-element: #d8dee9;
--theme-border: #4c566a;
--theme-border-active: #434c5e;
--theme-border-subtle: #4c566a;
--theme-diff-added: #a3be8c;
--theme-diff-removed: #bf616a;
--theme-diff-context: #4c566a;
--theme-diff-hunk-header: #4c566a;
--theme-diff-highlight-added: #a3be8c;
--theme-diff-highlight-removed: #bf616a;
--theme-diff-added-bg: #e5e9f0;
--theme-diff-removed-bg: #e5e9f0;
--theme-diff-context-bg: #e5e9f0;
--theme-diff-line-number: #d8dee9;
--theme-diff-added-line-number-bg: #e5e9f0;
--theme-diff-removed-line-number-bg: #e5e9f0;
--theme-markdown-text: #2e3440;
--theme-markdown-heading: #5e81ac;
--theme-markdown-link: #81a1c1;
--theme-markdown-link-text: #8fbcbb;
--theme-markdown-code: #a3be8c;
--theme-markdown-block-quote: #4c566a;
--theme-markdown-emph: #d08770;
--theme-markdown-strong: #ebcb8b;
--theme-markdown-horizontal-rule: #4c566a;
--theme-markdown-list-item: #5e81ac;
--theme-markdown-list-enumeration: #8fbcbb;
--theme-markdown-image: #81a1c1;
--theme-markdown-image-text: #8fbcbb;
--theme-markdown-code-block: #2e3440;
--theme-syntax-comment: #4c566a;
--theme-syntax-keyword: #81a1c1;
--theme-syntax-function: #88c0d0;
--theme-syntax-variable: #8fbcbb;
--theme-syntax-string: #a3be8c;
--theme-syntax-number: #b48ead;
--theme-syntax-type: #8fbcbb;
--theme-syntax-operator: #81a1c1;
--theme-syntax-punctuation: #2e3440;
--theme-primary: #5E81AC;
--theme-secondary: #81A1C1;
--theme-accent: #8FBCBB;
--theme-error: #BF616A;
--theme-warning: #D08770;
--theme-success: #A3BE8C;
--theme-info: #5E81AC;
--theme-text: #2E3440;
--theme-text-muted: #3B4252;
--theme-background: #ECEFF4;
--theme-background-panel: #E5E9F0;
--theme-background-element: #D8DEE9;
--theme-border: #4C566A;
--theme-border-active: #434C5E;
--theme-border-subtle: #4C566A;
--theme-diff-added: #A3BE8C;
--theme-diff-removed: #BF616A;
--theme-diff-context: #4C566A;
--theme-diff-hunk-header: #4C566A;
--theme-diff-highlight-added: #A3BE8C;
--theme-diff-highlight-removed: #BF616A;
--theme-diff-added-bg: #E5E9F0;
--theme-diff-removed-bg: #E5E9F0;
--theme-diff-context-bg: #E5E9F0;
--theme-diff-line-number: #D8DEE9;
--theme-diff-added-line-number-bg: #E5E9F0;
--theme-diff-removed-line-number-bg: #E5E9F0;
--theme-markdown-text: #2E3440;
--theme-markdown-heading: #5E81AC;
--theme-markdown-link: #81A1C1;
--theme-markdown-link-text: #8FBCBB;
--theme-markdown-code: #A3BE8C;
--theme-markdown-block-quote: #4C566A;
--theme-markdown-emph: #D08770;
--theme-markdown-strong: #EBCB8B;
--theme-markdown-horizontal-rule: #4C566A;
--theme-markdown-list-item: #5E81AC;
--theme-markdown-list-enumeration: #8FBCBB;
--theme-markdown-image: #81A1C1;
--theme-markdown-image-text: #8FBCBB;
--theme-markdown-code-block: #2E3440;
--theme-syntax-comment: #4C566A;
--theme-syntax-keyword: #81A1C1;
--theme-syntax-function: #88C0D0;
--theme-syntax-variable: #8FBCBB;
--theme-syntax-string: #A3BE8C;
--theme-syntax-number: #B48EAD;
--theme-syntax-type: #8FBCBB;
--theme-syntax-operator: #81A1C1;
--theme-syntax-punctuation: #2E3440;
}
[data-theme="nord"][data-dark="true"] {
--theme-primary: #88c0d0;
--theme-secondary: #81a1c1;
--theme-accent: #8fbcbb;
--theme-error: #bf616a;
--theme-warning: #d08770;
--theme-success: #a3be8c;
--theme-info: #88c0d0;
--theme-text: #eceff4;
--theme-text-muted: #8b95a7;
--theme-background: #2e3440;
--theme-background-panel: #3b4252;
--theme-background-element: #434c5e;
--theme-border: #434c5e;
--theme-border-active: #4c566a;
--theme-border-subtle: #434c5e;
--theme-diff-added: #a3be8c;
--theme-diff-removed: #bf616a;
--theme-diff-context: #8b95a7;
--theme-diff-hunk-header: #8b95a7;
--theme-diff-highlight-added: #a3be8c;
--theme-diff-highlight-removed: #bf616a;
--theme-diff-added-bg: #3b4252;
--theme-diff-removed-bg: #3b4252;
--theme-diff-context-bg: #3b4252;
--theme-diff-line-number: #434c5e;
--theme-diff-added-line-number-bg: #3b4252;
--theme-diff-removed-line-number-bg: #3b4252;
--theme-markdown-text: #d8dee9;
--theme-markdown-heading: #88c0d0;
--theme-markdown-link: #81a1c1;
--theme-markdown-link-text: #8fbcbb;
--theme-markdown-code: #a3be8c;
--theme-markdown-block-quote: #8b95a7;
--theme-markdown-emph: #d08770;
--theme-markdown-strong: #ebcb8b;
--theme-markdown-horizontal-rule: #8b95a7;
--theme-markdown-list-item: #88c0d0;
--theme-markdown-list-enumeration: #8fbcbb;
--theme-markdown-image: #81a1c1;
--theme-markdown-image-text: #8fbcbb;
--theme-markdown-code-block: #d8dee9;
--theme-syntax-comment: #8b95a7;
--theme-syntax-keyword: #81a1c1;
--theme-syntax-function: #88c0d0;
--theme-syntax-variable: #8fbcbb;
--theme-syntax-string: #a3be8c;
--theme-syntax-number: #b48ead;
--theme-syntax-type: #8fbcbb;
--theme-syntax-operator: #81a1c1;
--theme-syntax-punctuation: #d8dee9;
--theme-primary: #88C0D0;
--theme-secondary: #81A1C1;
--theme-accent: #8FBCBB;
--theme-error: #BF616A;
--theme-warning: #D08770;
--theme-success: #A3BE8C;
--theme-info: #88C0D0;
--theme-text: #ECEFF4;
--theme-text-muted: #8B95A7;
--theme-background: #2E3440;
--theme-background-panel: #3B4252;
--theme-background-element: #434C5E;
--theme-border: #434C5E;
--theme-border-active: #4C566A;
--theme-border-subtle: #434C5E;
--theme-diff-added: #A3BE8C;
--theme-diff-removed: #BF616A;
--theme-diff-context: #8B95A7;
--theme-diff-hunk-header: #8B95A7;
--theme-diff-highlight-added: #A3BE8C;
--theme-diff-highlight-removed: #BF616A;
--theme-diff-added-bg: #3B4252;
--theme-diff-removed-bg: #3B4252;
--theme-diff-context-bg: #3B4252;
--theme-diff-line-number: #434C5E;
--theme-diff-added-line-number-bg: #3B4252;
--theme-diff-removed-line-number-bg: #3B4252;
--theme-markdown-text: #D8DEE9;
--theme-markdown-heading: #88C0D0;
--theme-markdown-link: #81A1C1;
--theme-markdown-link-text: #8FBCBB;
--theme-markdown-code: #A3BE8C;
--theme-markdown-block-quote: #8B95A7;
--theme-markdown-emph: #D08770;
--theme-markdown-strong: #EBCB8B;
--theme-markdown-horizontal-rule: #8B95A7;
--theme-markdown-list-item: #88C0D0;
--theme-markdown-list-enumeration: #8FBCBB;
--theme-markdown-image: #81A1C1;
--theme-markdown-image-text: #8FBCBB;
--theme-markdown-code-block: #D8DEE9;
--theme-syntax-comment: #8B95A7;
--theme-syntax-keyword: #81A1C1;
--theme-syntax-function: #88C0D0;
--theme-syntax-variable: #8FBCBB;
--theme-syntax-string: #A3BE8C;
--theme-syntax-number: #B48EAD;
--theme-syntax-type: #8FBCBB;
--theme-syntax-operator: #81A1C1;
--theme-syntax-punctuation: #D8DEE9;
}
[data-theme="one-dark"][data-dark="false"] {
@@ -2173,109 +2173,109 @@
}
[data-theme="vesper"][data-dark="false"] {
--theme-primary: #ffc799;
--theme-secondary: #99ffe4;
--theme-accent: #ffc799;
--theme-error: #ff8080;
--theme-warning: #ffc799;
--theme-success: #99ffe4;
--theme-info: #ffc799;
--theme-primary: #FFC799;
--theme-secondary: #99FFE4;
--theme-accent: #FFC799;
--theme-error: #FF8080;
--theme-warning: #FFC799;
--theme-success: #99FFE4;
--theme-info: #FFC799;
--theme-text: #101010;
--theme-text-muted: #a0a0a0;
--theme-background: #fff;
--theme-background-panel: #f0f0f0;
--theme-background-element: #e0e0e0;
--theme-border: #d0d0d0;
--theme-border-active: #ffc799;
--theme-border-subtle: #e8e8e8;
--theme-diff-added: #99ffe4;
--theme-diff-removed: #ff8080;
--theme-diff-context: #a0a0a0;
--theme-diff-hunk-header: #a0a0a0;
--theme-diff-highlight-added: #99ffe4;
--theme-diff-highlight-removed: #ff8080;
--theme-text-muted: #A0A0A0;
--theme-background: #FFF;
--theme-background-panel: #F0F0F0;
--theme-background-element: #E0E0E0;
--theme-border: #D0D0D0;
--theme-border-active: #FFC799;
--theme-border-subtle: #E8E8E8;
--theme-diff-added: #99FFE4;
--theme-diff-removed: #FF8080;
--theme-diff-context: #A0A0A0;
--theme-diff-hunk-header: #A0A0A0;
--theme-diff-highlight-added: #99FFE4;
--theme-diff-highlight-removed: #FF8080;
--theme-diff-added-bg: #e8f5e8;
--theme-diff-removed-bg: #f5e8e8;
--theme-diff-context-bg: #f8f8f8;
--theme-diff-context-bg: #F8F8F8;
--theme-diff-line-number: #808080;
--theme-diff-added-line-number-bg: #e8f5e8;
--theme-diff-removed-line-number-bg: #f5e8e8;
--theme-markdown-text: #101010;
--theme-markdown-heading: #ffc799;
--theme-markdown-link: #ffc799;
--theme-markdown-link-text: #a0a0a0;
--theme-markdown-code: #a0a0a0;
--theme-markdown-heading: #FFC799;
--theme-markdown-link: #FFC799;
--theme-markdown-link-text: #A0A0A0;
--theme-markdown-code: #A0A0A0;
--theme-markdown-block-quote: #101010;
--theme-markdown-emph: #101010;
--theme-markdown-strong: #101010;
--theme-markdown-horizontal-rule: #65737e;
--theme-markdown-horizontal-rule: #65737E;
--theme-markdown-list-item: #101010;
--theme-markdown-list-enumeration: #101010;
--theme-markdown-image: #ffc799;
--theme-markdown-image-text: #a0a0a0;
--theme-markdown-image: #FFC799;
--theme-markdown-image-text: #A0A0A0;
--theme-markdown-code-block: #101010;
--theme-syntax-comment: #8b8b8b94;
--theme-syntax-keyword: #a0a0a0;
--theme-syntax-function: #ffc799;
--theme-syntax-keyword: #A0A0A0;
--theme-syntax-function: #FFC799;
--theme-syntax-variable: #101010;
--theme-syntax-string: #99ffe4;
--theme-syntax-number: #ffc799;
--theme-syntax-type: #ffc799;
--theme-syntax-operator: #a0a0a0;
--theme-syntax-string: #99FFE4;
--theme-syntax-number: #FFC799;
--theme-syntax-type: #FFC799;
--theme-syntax-operator: #A0A0A0;
--theme-syntax-punctuation: #101010;
}
[data-theme="vesper"][data-dark="true"] {
--theme-primary: #ffc799;
--theme-secondary: #99ffe4;
--theme-accent: #ffc799;
--theme-error: #ff8080;
--theme-warning: #ffc799;
--theme-success: #99ffe4;
--theme-info: #ffc799;
--theme-text: #fff;
--theme-text-muted: #a0a0a0;
--theme-primary: #FFC799;
--theme-secondary: #99FFE4;
--theme-accent: #FFC799;
--theme-error: #FF8080;
--theme-warning: #FFC799;
--theme-success: #99FFE4;
--theme-info: #FFC799;
--theme-text: #FFF;
--theme-text-muted: #A0A0A0;
--theme-background: #101010;
--theme-background-panel: #101010;
--theme-background-element: #101010;
--theme-border: #282828;
--theme-border-active: #ffc799;
--theme-border-subtle: #1c1c1c;
--theme-diff-added: #99ffe4;
--theme-diff-removed: #ff8080;
--theme-diff-context: #a0a0a0;
--theme-diff-hunk-header: #a0a0a0;
--theme-diff-highlight-added: #99ffe4;
--theme-diff-highlight-removed: #ff8080;
--theme-border-active: #FFC799;
--theme-border-subtle: #1C1C1C;
--theme-diff-added: #99FFE4;
--theme-diff-removed: #FF8080;
--theme-diff-context: #A0A0A0;
--theme-diff-hunk-header: #A0A0A0;
--theme-diff-highlight-added: #99FFE4;
--theme-diff-highlight-removed: #FF8080;
--theme-diff-added-bg: #0d2818;
--theme-diff-removed-bg: #281a1a;
--theme-diff-context-bg: #101010;
--theme-diff-line-number: #505050;
--theme-diff-added-line-number-bg: #0d2818;
--theme-diff-removed-line-number-bg: #281a1a;
--theme-markdown-text: #fff;
--theme-markdown-heading: #ffc799;
--theme-markdown-link: #ffc799;
--theme-markdown-link-text: #a0a0a0;
--theme-markdown-code: #a0a0a0;
--theme-markdown-block-quote: #fff;
--theme-markdown-emph: #fff;
--theme-markdown-strong: #fff;
--theme-markdown-horizontal-rule: #65737e;
--theme-markdown-list-item: #fff;
--theme-markdown-list-enumeration: #fff;
--theme-markdown-image: #ffc799;
--theme-markdown-image-text: #a0a0a0;
--theme-markdown-code-block: #fff;
--theme-markdown-text: #FFF;
--theme-markdown-heading: #FFC799;
--theme-markdown-link: #FFC799;
--theme-markdown-link-text: #A0A0A0;
--theme-markdown-code: #A0A0A0;
--theme-markdown-block-quote: #FFF;
--theme-markdown-emph: #FFF;
--theme-markdown-strong: #FFF;
--theme-markdown-horizontal-rule: #65737E;
--theme-markdown-list-item: #FFF;
--theme-markdown-list-enumeration: #FFF;
--theme-markdown-image: #FFC799;
--theme-markdown-image-text: #A0A0A0;
--theme-markdown-code-block: #FFF;
--theme-syntax-comment: #8b8b8b94;
--theme-syntax-keyword: #a0a0a0;
--theme-syntax-function: #ffc799;
--theme-syntax-variable: #fff;
--theme-syntax-string: #99ffe4;
--theme-syntax-number: #ffc799;
--theme-syntax-type: #ffc799;
--theme-syntax-operator: #a0a0a0;
--theme-syntax-punctuation: #fff;
--theme-syntax-keyword: #A0A0A0;
--theme-syntax-function: #FFC799;
--theme-syntax-variable: #FFF;
--theme-syntax-string: #99FFE4;
--theme-syntax-number: #FFC799;
--theme-syntax-type: #FFC799;
--theme-syntax-operator: #A0A0A0;
--theme-syntax-punctuation: #FFF;
}
[data-theme="zenburn"][data-dark="false"] {
@@ -2383,3 +2383,4 @@
--theme-syntax-operator: #f0dfaf;
--theme-syntax-punctuation: #dcdccc;
}

View File

@@ -0,0 +1,184 @@
import { Select as KobalteSelect } from "@kobalte/core/select"
import { createEffect, createMemo } from "solid-js"
import type { ComponentProps } from "solid-js"
import { Icon } from "@/ui/icon"
import fuzzysort from "fuzzysort"
import { pipe, groupBy, entries, map } from "remeda"
import { createStore } from "solid-js/store"
export interface SelectProps<T> {
variant?: "default" | "outline"
size?: "sm" | "md" | "lg"
placeholder?: string
options: T[]
current?: T
value?: (x: T) => string
label?: (x: T) => string
groupBy?: (x: T) => string
filterKeys: string[]
onFilter?: (query: string) => void
onSelect?: (value: T | undefined) => void
class?: ComponentProps<"div">["class"]
classList?: ComponentProps<"div">["classList"]
}
export function Select<T>(props: SelectProps<T>) {
let inputRef: HTMLInputElement | undefined = undefined
let listboxRef: HTMLUListElement | undefined = undefined
let contentRef: HTMLDivElement | undefined = undefined
const [store, setStore] = createStore({
filter: "",
})
const grouped = createMemo(() => {
const needle = store.filter.toLowerCase()
const result = pipe(
props.options,
(x) => (!needle ? x : fuzzysort.go(needle, x, { keys: props.filterKeys }).map((x) => x.obj)),
groupBy((x) => (props.groupBy ? props.groupBy(x) : "")),
// mapValues((x) => x.sort((a, b) => a.title.localeCompare(b.title))),
entries(),
map(([k, v]) => ({ category: k, options: v })),
)
return result
})
// const flat = createMemo(() => {
// return pipe(
// grouped(),
// flatMap(({ options }) => options),
// )
// })
createEffect(() => {
store.filter
listboxRef?.scrollTo(0, 0)
// setStore("selected", 0)
// scroll.scrollTo(0)
})
return (
<KobalteSelect<T, { category: string; options: T[] }>
allowDuplicateSelectionEvents={false}
disallowEmptySelection={true}
closeOnSelection={false}
value={props.current}
options={grouped()}
optionValue={(x) => (props.value ? props.value(x) : (x as string))}
optionTextValue={(x) => (props.label ? props.label(x) : (x as string))}
optionGroupChildren="options"
placeholder={props.placeholder}
sectionComponent={(props) => (
<KobalteSelect.Section class="text-xs uppercase text-text-muted/60 font-light mt-3 first:mt-0 ml-2">
{props.section.rawValue.category}
</KobalteSelect.Section>
)}
itemComponent={(itemProps) => (
<KobalteSelect.Item
classList={{
"relative flex cursor-pointer select-none items-center": true,
"rounded-sm px-2 py-0.5 text-xs outline-none text-text": true,
"transition-colors data-[disabled]:pointer-events-none": true,
"data-[highlighted]:bg-background-element data-[disabled]:opacity-50": true,
[props.class ?? ""]: !!props.class,
}}
{...itemProps}
>
<KobalteSelect.ItemLabel>
{props.label ? props.label(itemProps.item.rawValue) : (itemProps.item.rawValue as string)}
</KobalteSelect.ItemLabel>
<KobalteSelect.ItemIndicator
classList={{
"ml-auto": true,
}}
>
<Icon name="checkmark" size={16} />
</KobalteSelect.ItemIndicator>
</KobalteSelect.Item>
)}
onChange={(v) => {
if (props.onSelect) props.onSelect(v ?? undefined)
if (v !== null) {
// close the select
}
}}
onOpenChange={(v) => v || setStore("filter", "")}
>
<KobalteSelect.Trigger
classList={{
...(props.classList ?? {}),
"flex w-full items-center justify-between rounded-md transition-colors": true,
"focus-visible:outline-none focus-visible:ring focus-visible:ring-border-active/30": true,
"disabled:cursor-not-allowed disabled:opacity-50": true,
"data-[placeholder-shown]:text-text-muted cursor-pointer": true,
"hover:bg-background-element focus-visible:ring-border-active": true,
"bg-background-element text-text": props.variant === "default" || !props.variant,
"border-2 border-border bg-transparent text-text": props.variant === "outline",
"h-6 pl-2 text-xs": props.size === "sm",
"h-8 pl-3 text-sm": props.size === "md" || !props.size,
"h-10 pl-4 text-base": props.size === "lg",
[props.class ?? ""]: !!props.class,
}}
>
<KobalteSelect.Value<T>>
{(state) => {
const selected = state.selectedOption() ?? props.current
if (!selected) return props.placeholder || ""
if (props.label) return props.label(selected)
return selected as string
}}
</KobalteSelect.Value>
<KobalteSelect.Icon
classList={{
"size-fit shrink-0 text-text-muted transition-transform duration-100 data-[expanded]:rotate-180": true,
}}
>
<Icon name="chevron-down" size={24} />
</KobalteSelect.Icon>
</KobalteSelect.Trigger>
<KobalteSelect.Portal>
<KobalteSelect.Content
ref={(el) => (contentRef = el)}
onKeyDown={(e) => {
if (e.key === "ArrowUp" || e.key === "ArrowDown" || e.key === "Escape") {
return
}
inputRef?.focus()
}}
classList={{
"min-w-32 overflow-hidden rounded-md border border-border-subtle/40": true,
"bg-background-panel p-1 shadow-md z-50": true,
"data-[closed]:animate-out data-[closed]:fade-out-0 data-[closed]:zoom-out-95": true,
"data-[expanded]:animate-in data-[expanded]:fade-in-0 data-[expanded]:zoom-in-95": true,
}}
>
<form>
<input
ref={(el) => (inputRef = el)}
id="select-filter"
type="text"
placeholder="Filter models"
value={store.filter}
onInput={(e) => setStore("filter", e.currentTarget.value)}
onKeyDown={(e) => {
if (e.key === "ArrowUp" || e.key === "ArrowDown" || e.key === "Escape") {
e.preventDefault()
e.stopPropagation()
listboxRef?.focus()
}
}}
classList={{
"w-full": true,
"px-2 pb-2 text-text font-light placeholder-text-muted/70 text-xs focus:outline-none": true,
}}
/>
</form>
<KobalteSelect.Listbox
ref={(el) => (listboxRef = el)}
classList={{
"overflow-y-auto max-h-48 no-scrollbar": true,
}}
/>
</KobalteSelect.Content>
</KobalteSelect.Portal>
</KobalteSelect>
)
}

View File

@@ -24,22 +24,26 @@ function init() {
const sdk = useSDK()
const sync = useSync()
const agents = createMemo(() => sync.data.agent.filter((x) => x.mode !== "subagent"))
const list = createMemo(() => sync.data.agent.filter((x) => x.mode !== "subagent"))
const agent = (() => {
const [store, setStore] = createStore<{
current: string
}>({
current: agents()[0].name,
current: list()[0].name,
})
return {
list,
current() {
return agents().find((x) => x.name === store.current)!
return list().find((x) => x.name === store.current)!
},
set(name: string | undefined) {
setStore("current", name ?? list()[0].name)
},
move(direction: 1 | -1) {
let next = agents().findIndex((x) => x.name === store.current) + direction
if (next < 0) next = agents().length - 1
if (next >= agents().length) next = 0
const value = agents()[next]
let next = list().findIndex((x) => x.name === store.current) + direction
if (next < 0) next = list().length - 1
if (next >= list().length) next = 0
const value = list()[next]
setStore("current", value.name)
if (value.model)
model.set({
@@ -89,7 +93,12 @@ function init() {
return store.model[agent.current().name] ?? (a.model ? a.model : fallback())
})
const list = createMemo(() =>
sync.data.provider.flatMap((x) => Object.values(x.models).map((m) => ({ providerID: x.id, modelID: m.id }))),
)
return {
list,
current,
recent() {
return store.recent
@@ -103,10 +112,10 @@ function init() {
model: model.name ?? value.modelID,
}
}),
set(model: { providerID: string; modelID: string }, options?: { recent?: boolean }) {
set(model: { providerID: string; modelID: string } | undefined, options?: { recent?: boolean }) {
batch(() => {
setStore("model", agent.current().name, model)
if (options?.recent) {
setStore("model", agent.current().name, model ?? fallback())
if (options?.recent && model) {
const uniq = uniqueBy([model, ...store.recent], (x) => x.providerID + x.modelID)
if (uniq.length > 5) uniq.pop()
setStore("recent", uniq)

View File

@@ -1,5 +1,6 @@
import { FileIcon, Icon, IconButton, Logo, Tooltip } from "@/ui"
import { Tabs } from "@/ui/tabs"
import { Select } from "@/components/select"
import FileTree from "@/components/file-tree"
import { createSignal, For, Match, onCleanup, onMount, Show, Switch } from "solid-js"
import { useLocal, useSDK } from "@/context"
@@ -51,6 +52,10 @@ export default function Page() {
return
}
if (document.activeElement?.id === "select-filter") {
return
}
if (local.file.active()) {
if (e.getModifierState(MOD)) {
if (e.key.toLowerCase() === "a") {
@@ -228,10 +233,10 @@ export default function Page() {
<Tabs class="relative flex flex-col h-full" defaultValue="files">
<div class="sticky top-0 shrink-0 flex">
<Tabs.List class="grow w-full after:hidden">
<Tabs.Trigger value="files" class="flex-1 justify-center">
<Tabs.Trigger value="files" class="flex-1 justify-center text-xs">
Files
</Tabs.Trigger>
<Tabs.Trigger value="changes" class="flex-1 justify-center">
<Tabs.Trigger value="changes" class="flex-1 justify-center text-xs">
Changes
</Tabs.Trigger>
</Tabs.List>
@@ -256,7 +261,7 @@ export default function Page() {
/>
</Tabs.Content>
<Tabs.Content value="changes" class="grow min-h-0 py-2 bg-background">
<div class="px-2 text-sm text-text-muted">No changes yet</div>
<div class="px-2 text-xs text-text-muted">No changes yet</div>
</Tabs.Content>
</Tabs>
</div>
@@ -493,11 +498,28 @@ export default function Page() {
placeholder="It all starts with a prompt..."
class="w-full p-1 pb-4 text-text font-light placeholder-text-muted/70 text-sm focus:outline-none"
/>
<div class="px-1 flex justify-between items-center text-xs text-text-muted">
<span>
<span class="text-primary uppercase">{local.agent.current()?.name ?? "unknown"}</span> /{" "}
{local.model.parsed().provider} / {local.model.parsed().model}
</span>
<div class="flex justify-between items-center text-xs text-text-muted">
<div class="flex gap-2 items-center">
<Select
options={local.agent.list().map((a) => a.name)}
current={local.agent.current().name}
onSelect={local.agent.set}
size="sm"
class="uppercase"
/>
<Select
options={local.model.list()}
current={local.model.current()}
onSelect={local.model.set}
label={(x) => x.modelID}
value={(x) => `${x.providerID}.${x.modelID}`}
filterKeys={["providerID", "modelID"]}
groupBy={(x) => x.providerID}
size="sm"
class="uppercase"
/>
<span class="text-text-muted/70">{local.model.parsed().provider}</span>
</div>
<div class="flex gap-1 items-center">
<IconButton class="text-text-muted" size="xs" variant="ghost">
<Icon name="photo" size={16} />

View File

@@ -23,11 +23,11 @@
"diff": "8.0.2",
"js-base64": "3.7.7",
"lang-map": "0.4.0",
"luxon": "3.6.1",
"luxon": "catalog:",
"marked": "15.0.12",
"marked-shiki": "1.2.1",
"rehype-autolink-headings": "7.1.0",
"remeda": "2.26.0",
"remeda": "catalog:",
"sharp": "0.32.5",
"shiki": "3.4.2",
"solid-js": "catalog:",