ompchamber 2.0.2 → 3.1.0
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 +31 -11
- package/bunfig.toml +11 -0
- package/dist/client/index.html +16 -5
- package/dist/client/index.js +1393 -0
- package/dist/client/static/js/index-8t70jhyj.js +5149 -0
- package/dist/client/static/js/index-n4wkqj7t.css +1 -0
- package/index.html +54 -0
- package/package.json +9 -10
- package/public/apple-touch-icon.png +0 -0
- package/public/icon-192x192.png +0 -0
- package/public/icon.svg +60 -0
- package/public/manifest.webmanifest +38 -0
- package/src/cli/lib/commands/serve.js +9 -5
- package/src/cli/lib/runtime.js +18 -7
- package/src/client/components/common/code-editor/handler.test.ts +274 -0
- package/src/client/components/common/code-editor/handler.ts +175 -0
- package/src/client/components/common/code-editor/index.tsx +185 -220
- package/src/client/components/common/code-surface/index.tsx +109 -12
- package/src/client/components/common/lazy-panels.tsx +5 -1
- package/src/client/components/common/provider-icon/glyphs.ts +118 -0
- package/src/client/components/common/provider-icon/index.tsx +85 -0
- package/src/client/components/common/viewport.ts +5 -3
- package/src/client/components/layout/RightActivityBar.tsx +2 -1
- package/src/client/components/layout/desktop-layout/TopNavbar.tsx +21 -4
- package/src/client/components/layout/desktop-layout/WorkspacePanels.tsx +4 -0
- package/src/client/components/layout/desktop-layout/index.tsx +26 -4
- package/src/client/components/mobile/LayoutWrapper.tsx +16 -0
- package/src/client/components/mobile/RightSidebar.tsx +11 -4
- package/src/client/components/mobile/SessionSidebar.tsx +10 -0
- package/src/client/components/mobile/mobile-right-sidebar/FullEditor.tsx +0 -1
- package/src/client/components/mobile/mobile-session-sidebar/Item.tsx +16 -1
- package/src/client/components/mobile/mobile-session-sidebar/List.tsx +3 -0
- package/src/client/components/settings/categories/ProviderSettings.tsx +45 -4
- package/src/client/components/settings/categories/UsageSettings.tsx +22 -7
- package/src/client/components/settings/categories/provider-settings/AddModelModal.tsx +322 -0
- package/src/client/components/settings/categories/provider-settings/AddProviderModal.tsx +152 -56
- package/src/client/components/settings/categories/provider-settings/AuthSection.tsx +52 -1
- package/src/client/components/settings/categories/provider-settings/DeleteProviderModal.tsx +133 -0
- package/src/client/components/settings/categories/provider-settings/DialectFields.tsx +136 -0
- package/src/client/components/settings/categories/provider-settings/EffortLadder.tsx +89 -0
- package/src/client/components/settings/categories/provider-settings/Header.tsx +2 -2
- package/src/client/components/settings/categories/provider-settings/LoginModal.tsx +2 -2
- package/src/client/components/settings/categories/provider-settings/ModelsList.tsx +22 -2
- package/src/client/components/settings/categories/provider-settings/PresetPicker.tsx +82 -0
- package/src/client/components/settings/categories/provider-settings/PriceFields.tsx +107 -0
- package/src/client/components/settings/categories/provider-settings/ReconnectModal.tsx +43 -22
- package/src/client/components/settings/categories/provider-settings/SidebarList.tsx +2 -2
- package/src/client/components/settings/categories/usage-settings/LimitsSection.tsx +115 -0
- package/src/client/components/settings/categories/usage-settings/ProviderCard.tsx +19 -26
- package/src/client/components/settings/categories/usage-settings/ProviderDetail.tsx +29 -22
- package/src/client/components/settings/categories/usage-settings/SidebarList.tsx +60 -48
- package/src/client/components/settings/categories/usage-settings/format.ts +36 -0
- package/src/client/components/settings/categories/usage-settings/providers.ts +52 -28
- package/src/client/components/workspace/browser-panel/AddressBar.tsx +1 -10
- package/src/client/components/workspace/browser-panel/Screencast.tsx +4 -5
- package/src/client/components/workspace/browser-panel/index.tsx +6 -6
- package/src/client/components/workspace/browser-toolbar/index.tsx +22 -12
- package/src/client/components/workspace/chat-timeline/AiMessageFooter.tsx +1 -1
- package/src/client/components/workspace/chat-timeline/GeneratingIndicator.tsx +1 -1
- package/src/client/components/workspace/chat-timeline/ToolCallCard.tsx +1 -1
- package/src/client/components/workspace/chat-timeline/tool-renderers/panels/Todo.tsx +1 -1
- package/src/client/components/workspace/diff-panel/Toolbar.tsx +71 -38
- package/src/client/components/workspace/diff-panel/index.tsx +139 -53
- package/src/client/components/workspace/editor/CommandPalette.test.ts +242 -0
- package/src/client/components/workspace/editor/CommandPalette.tsx +138 -0
- package/src/client/components/workspace/editor/FindWidget.test.ts +261 -0
- package/src/client/components/workspace/editor/FindWidget.tsx +219 -0
- package/src/client/components/workspace/editor/Tabs.tsx +2 -2
- package/src/client/components/workspace/editor/Toolbar.tsx +129 -26
- package/src/client/components/workspace/editor/index.tsx +180 -62
- package/src/client/components/workspace/file-explorer/Modals.tsx +79 -2
- package/src/client/components/workspace/file-explorer/TreeItem.tsx +43 -113
- package/src/client/components/workspace/model-dropdown/Item.tsx +13 -23
- package/src/client/components/workspace/model-dropdown/Panel.tsx +1 -1
- package/src/client/components/workspace/model-dropdown/Section.tsx +13 -4
- package/src/client/components/workspace/model-dropdown/index.tsx +7 -3
- package/src/client/components/workspace/todo-panel/PhaseGroup.tsx +76 -0
- package/src/client/components/workspace/todo-panel/Row.tsx +69 -0
- package/src/client/components/workspace/todo-panel/index.tsx +161 -0
- package/src/client/components/workspace/usage-panel/ProviderSelect.tsx +10 -5
- package/src/client/components/workspace/usage-panel/index.tsx +36 -18
- package/src/client/data/samples/dialogue-session.ts +1 -1
- package/src/client/data/samples/sample-tools/other.ts +1 -1
- package/src/client/data/settings/provider.ts +141 -9
- package/src/client/hooks/editor/find-harness.test-util.ts +170 -0
- package/src/client/hooks/editor/scroll-container.test.ts +102 -0
- package/src/client/hooks/editor/scroll-container.ts +26 -0
- package/src/client/hooks/editor/use-code-window.ts +2 -20
- package/src/client/hooks/editor/use-editor-find-write.test.ts +170 -0
- package/src/client/hooks/editor/use-editor-find.test.ts +118 -0
- package/src/client/hooks/editor/use-editor-find.ts +321 -0
- package/src/client/hooks/editor/use-editor-history.test.ts +216 -0
- package/src/client/hooks/editor/use-editor-history.ts +134 -0
- package/src/client/hooks/editor/use-file-editor.ts +24 -27
- package/src/client/hooks/editor/use-occurrences.test.ts +236 -0
- package/src/client/hooks/editor/use-occurrences.ts +98 -0
- package/src/client/hooks/models/use-provider-names.ts +1 -1
- package/src/client/hooks/settings/providers/actions.ts +337 -0
- package/src/client/hooks/settings/providers/api.ts +69 -0
- package/src/client/hooks/settings/providers/index.ts +138 -0
- package/src/client/hooks/settings/providers/messages.ts +77 -0
- package/src/client/hooks/settings/useUsageReport.ts +8 -3
- package/src/client/hooks/ui/theme.ts +3 -3
- package/src/client/hooks/workspace/file-tabs.ts +62 -11
- package/src/client/hooks/workspace/file-tree-actions.test.ts +348 -0
- package/src/client/hooks/workspace/file-tree-actions.ts +250 -0
- package/src/client/hooks/workspace/session-todos.ts +102 -0
- package/src/client/stubs/elkjs.ts +6 -1
- package/src/client/tailwind.css +30 -0
- package/src/server/index.ts +20 -2
- package/src/server/lib/assets/font-css.server.ts +86 -0
- package/src/server/lib/assets/fonts.server.ts +117 -0
- package/src/server/lib/bundler/css.ts +116 -0
- package/src/server/lib/lifecycle/shell-route.ts +17 -0
- package/src/server/lib/models/provider-listing.server.ts +257 -0
- package/src/server/lib/models/provider-registry.server.test.ts +122 -0
- package/src/server/lib/models/provider-registry.server.ts +76 -25
- package/src/server/lib/omp/config/models-config.ts +11 -0
- package/src/server/lib/omp/config/models-validation.test.ts +137 -0
- package/src/server/lib/omp/config/models-validation.ts +111 -2
- package/src/server/lib/omp/config/provider-seeds.test.ts +167 -0
- package/src/server/lib/omp/config/provider-seeds.ts +176 -0
- package/src/server/lib/omp/config/providers.ts +94 -100
- package/src/server/lib/omp/core/auth-credentials.ts +45 -0
- package/src/server/lib/omp/session/todos.ts +100 -0
- package/src/server/lib/omp/session/{usage.ts → usage/aggregate.ts} +1 -118
- package/src/server/lib/omp/session/usage/shaping.ts +130 -0
- package/src/server/lib/usage/deepseek.ts +4 -5
- package/src/server/lib/usage/kenari.ts +7 -6
- package/src/server/lib/usage/omp-usage.server.test.ts +126 -0
- package/src/server/lib/usage/omp-usage.server.ts +194 -0
- package/src/server/lib/usage/provider-key.ts +81 -3
- package/src/server/lib/usage/providers.server.test.ts +47 -0
- package/src/server/lib/usage/providers.server.ts +208 -0
- package/src/server/lib/usage/vendor-balance.server.test.ts +104 -0
- package/src/server/lib/usage/vendor-balance.server.ts +284 -0
- package/src/server/plugins/shell.server.ts +56 -0
- package/src/server/plugins/ssr.ts +24 -36
- package/src/server/plugins/static.test.ts +26 -29
- package/src/server/plugins/static.ts +40 -19
- package/src/server/routes/fs/action-create.test.ts +90 -0
- package/src/server/routes/fs/action.ts +23 -0
- package/src/server/routes/omp/index.ts +2 -0
- package/src/server/routes/omp/session-todos.ts +80 -0
- package/src/server/routes/settings/index.ts +2 -0
- package/src/server/routes/settings/provider-model.ts +107 -0
- package/src/server/routes/settings/provider-models.ts +65 -202
- package/src/server/routes/settings/providers.ts +22 -7
- package/src/server/routes/settings/usage.ts +125 -45
- package/src/server/routes/telemetry/tokens.ts +2 -1
- package/src/shared/lib/chat/{todo-parser.ts → todo/parser.ts} +17 -0
- package/src/shared/lib/chat/todo/progress.ts +97 -0
- package/src/shared/lib/chat/todo/snapshot.test.ts +156 -0
- package/src/shared/lib/chat/todo/snapshot.ts +215 -0
- package/src/shared/lib/code/editor/commands.test.ts +155 -0
- package/src/shared/lib/code/editor/commands.ts +260 -0
- package/src/shared/lib/code/editor/edits.test.ts +100 -0
- package/src/shared/lib/code/editor/edits.ts +122 -0
- package/src/shared/lib/code/editor/find-status.test.ts +50 -0
- package/src/shared/lib/code/editor/find-status.ts +36 -0
- package/src/shared/lib/code/editor/find.test.ts +203 -0
- package/src/shared/lib/code/editor/find.ts +224 -0
- package/src/{client/components/common/code-editor → shared/lib/code/editor}/history.test.ts +1 -1
- package/src/shared/lib/code/editor/keymap.test.ts +109 -0
- package/src/shared/lib/code/editor/keymap.ts +151 -0
- package/src/shared/lib/code/editor/layers.test.ts +77 -0
- package/src/shared/lib/code/editor/layers.ts +67 -0
- package/src/shared/lib/code/editor/line-edits.test.ts +131 -0
- package/src/shared/lib/code/editor/line-edits.ts +159 -0
- package/src/shared/lib/code/editor/lines.test.ts +81 -0
- package/src/shared/lib/code/editor/lines.ts +83 -0
- package/src/shared/lib/code/editor/marks.test.ts +86 -0
- package/src/shared/lib/code/editor/marks.ts +106 -0
- package/src/shared/lib/code/editor/occurrences.test.ts +117 -0
- package/src/shared/lib/code/editor/occurrences.ts +111 -0
- package/src/shared/lib/code/editor/palette.test.ts +91 -0
- package/src/shared/lib/code/editor/palette.ts +92 -0
- package/src/shared/lib/code/editor/reset-css.test.ts +35 -0
- package/src/shared/lib/code/editor/reset-css.ts +32 -0
- package/src/shared/lib/code/editor/text-commands.test.ts +178 -0
- package/src/shared/lib/code/editor/text-commands.ts +154 -0
- package/src/shared/lib/code/syntax-highlight.test.ts +75 -0
- package/src/shared/lib/code/syntax-highlight.ts +29 -17
- package/src/shared/lib/code/windowed-highlight.ts +52 -1
- package/src/shared/lib/fs/diff-parser.test.ts +116 -0
- package/src/shared/lib/fs/diff-parser.ts +86 -33
- package/src/shared/lib/models/{provider-connection.ts → provider/connection.ts} +37 -0
- package/src/shared/lib/models/provider/dialect.ts +179 -0
- package/src/shared/lib/models/provider/glyph.test.ts +116 -0
- package/src/shared/lib/models/provider/glyph.ts +200 -0
- package/src/shared/lib/models/{provider-models.ts → provider/models.ts} +91 -6
- package/src/shared/lib/models/provider/presets.test.ts +172 -0
- package/src/shared/lib/models/provider/presets.ts +83 -0
- package/src/shared/lib/ui/key-binding.test.ts +115 -0
- package/src/shared/lib/ui/key-binding.ts +143 -0
- package/src/shared/lib/util/platform.test.ts +87 -0
- package/src/shared/lib/util/platform.ts +30 -0
- package/src/shared/lib/workspace/file-tab-id.ts +29 -0
- package/src/shared/lib/workspace/keymap.test.ts +82 -0
- package/src/shared/lib/workspace/keymap.ts +30 -0
- package/src/shared/lib/workspace/refresh-cadence.ts +9 -0
- package/src/shared/lib/workspace/right-panels.ts +8 -0
- package/src/shared/lib/workspace/session-state/store.ts +0 -1
- package/src/shared/types/index.ts +1 -0
- package/src/shared/types/settings/provider.ts +81 -0
- package/src/shared/types/settings/usage.ts +88 -14
- package/src/shared/types/todo.ts +108 -0
- package/tsconfig.json +3 -1
- package/dist/client/static/css/index.5f630421b7.css +0 -2
- package/dist/client/static/font/KaTeX_AMS-Regular.a79f1c3119.woff2 +0 -0
- package/dist/client/static/font/KaTeX_Caligraphic-Bold.ec17d13264.woff2 +0 -0
- package/dist/client/static/font/KaTeX_Caligraphic-Regular.55fac25845.woff2 +0 -0
- package/dist/client/static/font/KaTeX_Fraktur-Bold.d42a5579b0.woff2 +0 -0
- package/dist/client/static/font/KaTeX_Fraktur-Regular.d3c882a649.woff2 +0 -0
- package/dist/client/static/font/KaTeX_Main-Bold.c3fb5ac22f.woff2 +0 -0
- package/dist/client/static/font/KaTeX_Main-BoldItalic.6f2bb1dff2.woff2 +0 -0
- package/dist/client/static/font/KaTeX_Main-Italic.8916142bec.woff2 +0 -0
- package/dist/client/static/font/KaTeX_Main-Regular.0462f03bdf.woff2 +0 -0
- package/dist/client/static/font/KaTeX_Math-BoldItalic.572d331f69.woff2 +0 -0
- package/dist/client/static/font/KaTeX_Math-Italic.f28c23acad.woff2 +0 -0
- package/dist/client/static/font/KaTeX_SansSerif-Bold.8c5b5494b6.woff2 +0 -0
- package/dist/client/static/font/KaTeX_SansSerif-Italic.3b1e59b3ba.woff2 +0 -0
- package/dist/client/static/font/KaTeX_SansSerif-Regular.ba21ed5f84.woff2 +0 -0
- package/dist/client/static/font/KaTeX_Script-Regular.03e9641d6f.woff2 +0 -0
- package/dist/client/static/font/KaTeX_Size1-Regular.eae34984b3.woff2 +0 -0
- package/dist/client/static/font/KaTeX_Size2-Regular.5916a24fa3.woff2 +0 -0
- package/dist/client/static/font/KaTeX_Size4-Regular.10d95fd3a2.woff2 +0 -0
- package/dist/client/static/font/KaTeX_Typewriter-Regular.a8709e3622.woff2 +0 -0
- package/dist/client/static/font/fira-code-latin-400-normal.2655b10c55.woff2 +0 -0
- package/dist/client/static/font/fira-code-latin-500-normal.92a991f204.woff2 +0 -0
- package/dist/client/static/font/fira-code-latin-600-normal.43788eb7f1.woff2 +0 -0
- package/dist/client/static/font/fira-code-latin-700-normal.2667215d33.woff2 +0 -0
- package/dist/client/static/js/77.0d81c74cf0.js +0 -139
- package/dist/client/static/js/77.0d81c74cf0.js.LICENSE.txt +0 -8
- package/dist/client/static/js/async/0.8e59f2eb5b.js +0 -1
- package/dist/client/static/js/async/0k.5852e6b4fa.js +0 -1
- package/dist/client/static/js/async/0w.9ed36d5860.js +0 -1
- package/dist/client/static/js/async/1.f387c12b63.js +0 -1
- package/dist/client/static/js/async/12.d091f91c99.js +0 -1
- package/dist/client/static/js/async/13.8f810a8a6c.js +0 -1
- package/dist/client/static/js/async/19.6fe909d55a.js +0 -160
- package/dist/client/static/js/async/1b.23f1141a38.js +0 -1
- package/dist/client/static/js/async/1k.973e8e21fc.js +0 -2
- package/dist/client/static/js/async/1k.973e8e21fc.js.LICENSE.txt +0 -11
- package/dist/client/static/js/async/1p.0d5cddda96.js +0 -1
- package/dist/client/static/js/async/2.b589f1733b.js +0 -1
- package/dist/client/static/js/async/2v.96165101de.js +0 -1
- package/dist/client/static/js/async/3.0cacc08423.js +0 -1
- package/dist/client/static/js/async/37.b28b2f61cd.js +0 -1
- package/dist/client/static/js/async/3d.5085fb913f.js +0 -1
- package/dist/client/static/js/async/3j.357c80ff38.js +0 -2
- package/dist/client/static/js/async/3j.357c80ff38.js.LICENSE.txt +0 -11
- package/dist/client/static/js/async/3p.bcf32a0983.js +0 -1
- package/dist/client/static/js/async/3r.3a69e98ee0.js +0 -64
- package/dist/client/static/js/async/3u.1228460e2a.js +0 -1
- package/dist/client/static/js/async/3y.3530b824ad.js +0 -198
- package/dist/client/static/js/async/3y.3530b824ad.js.LICENSE.txt +0 -5
- package/dist/client/static/js/async/4.9442eeb472.js +0 -1
- package/dist/client/static/js/async/4e.678285ca55.js +0 -1
- package/dist/client/static/js/async/4k.33a0c7eeb4.js +0 -1
- package/dist/client/static/js/async/4m.928a1dde85.js +0 -31
- package/dist/client/static/js/async/4m.928a1dde85.js.LICENSE.txt +0 -11
- package/dist/client/static/js/async/4q.aad20dab25.js +0 -1
- package/dist/client/static/js/async/5.ebaf8b89cc.js +0 -36
- package/dist/client/static/js/async/51.95bcae98af.js +0 -2
- package/dist/client/static/js/async/51.95bcae98af.js.LICENSE.txt +0 -6
- package/dist/client/static/js/async/5b.d88304bc13.js +0 -1
- package/dist/client/static/js/async/5j.d6407c4248.js +0 -287
- package/dist/client/static/js/async/5o.88316d4460.js +0 -62
- package/dist/client/static/js/async/6.f034c9b528.js +0 -1
- package/dist/client/static/js/async/66.5dfa29f957.js +0 -93
- package/dist/client/static/js/async/6o.5b1a06a382.js +0 -1
- package/dist/client/static/js/async/7.e4a9288dd0.js +0 -1
- package/dist/client/static/js/async/73.308dff4da8.js +0 -1
- package/dist/client/static/js/async/7e.a1cc9bfd88.js +0 -1
- package/dist/client/static/js/async/7g.a7814350c3.js +0 -1
- package/dist/client/static/js/async/7l.fadbbc0583.js +0 -1
- package/dist/client/static/js/async/8.5067439d8c.js +0 -1
- package/dist/client/static/js/async/8j.ea110663fb.js +0 -1
- package/dist/client/static/js/async/a.bce4542392.js +0 -1
- package/dist/client/static/js/async/aa.65d3852576.js +0 -1
- package/dist/client/static/js/async/ar.9303e5f2e8.js +0 -2
- package/dist/client/static/js/async/ar.9303e5f2e8.js.LICENSE.txt +0 -11
- package/dist/client/static/js/async/az.d656062b0f.js +0 -1
- package/dist/client/static/js/async/b.b4f6f06515.js +0 -1
- package/dist/client/static/js/async/bi.09688ba75c.js +0 -1
- package/dist/client/static/js/async/bq.586bc738d1.js +0 -1
- package/dist/client/static/js/async/c.797d933882.js +0 -1
- package/dist/client/static/js/async/c0.0af1e640d3.js +0 -24
- package/dist/client/static/js/async/ca.8a52cfd447.js +0 -1
- package/dist/client/static/js/async/cf.d34fff5d67.js +0 -1
- package/dist/client/static/js/async/ct.b74928f7a3.js +0 -1
- package/dist/client/static/js/async/cx.3cb0242a3a.js +0 -226
- package/dist/client/static/js/async/d.a5fc8fe1b3.js +0 -1
- package/dist/client/static/js/async/da.f62c70f6c8.js +0 -1
- package/dist/client/static/js/async/dp.1725d6432c.js +0 -1
- package/dist/client/static/js/async/e.93214d622b.js +0 -79
- package/dist/client/static/js/async/f.ab50467719.js +0 -19
- package/dist/client/static/js/async/f.ab50467719.js.LICENSE.txt +0 -12
- package/dist/client/static/js/async/f7.46971e9d6d.js +0 -2
- package/dist/client/static/js/async/f7.46971e9d6d.js.LICENSE.txt +0 -6
- package/dist/client/static/js/async/f8.bbf0dbae70.js +0 -1
- package/dist/client/static/js/async/g.cb81980498.js +0 -2
- package/dist/client/static/js/async/g.cb81980498.js.LICENSE.txt +0 -11
- package/dist/client/static/js/async/h.4e790471e4.js +0 -27
- package/dist/client/static/js/async/h1.393f066d09.js +0 -1
- package/dist/client/static/js/async/h3.216e9798ab.js +0 -148
- package/dist/client/static/js/async/hd.0da931b622.js +0 -1
- package/dist/client/static/js/async/hk.ba7fb04d41.js +0 -1
- package/dist/client/static/js/async/hn.b645041e00.js +0 -1
- package/dist/client/static/js/async/ho.475a5e1ae4.js +0 -1
- package/dist/client/static/js/async/hp.e9fe2e395a.js +0 -2
- package/dist/client/static/js/async/hp.e9fe2e395a.js.LICENSE.txt +0 -17
- package/dist/client/static/js/async/hs.e7c59d8090.js +0 -41
- package/dist/client/static/js/async/i.7c148e8440.js +0 -1
- package/dist/client/static/js/async/id.573df20f29.js +0 -1
- package/dist/client/static/js/async/j.ab925882d8.js +0 -1
- package/dist/client/static/js/async/jd.63886a1f09.js +0 -1
- package/dist/client/static/js/async/jg.d86ebd4013.js +0 -86
- package/dist/client/static/js/async/jl.874d352278.js +0 -1
- package/dist/client/static/js/async/jll.11313b455a.js +0 -1
- package/dist/client/static/js/async/js.67182759ef.js +0 -1
- package/dist/client/static/js/async/jsc.23b70d6f40.js +0 -1
- package/dist/client/static/js/async/jse.334588ff5d.js +0 -1
- package/dist/client/static/js/async/jz.72eb929106.js +0 -77
- package/dist/client/static/js/async/k.3210286401.js +0 -217
- package/dist/client/static/js/async/ka.c1990ecaa3.js +0 -115
- package/dist/client/static/js/async/katex-vendor.de6a87c308.js +0 -1
- package/dist/client/static/js/async/ku.29c8a59d0c.js +0 -1
- package/dist/client/static/js/async/ky.8dab1dade0.js +0 -1
- package/dist/client/static/js/async/l.12dd34e1be.js +0 -1
- package/dist/client/static/js/async/l9.949710adaf.js +0 -83
- package/dist/client/static/js/async/l9.949710adaf.js.LICENSE.txt +0 -13
- package/dist/client/static/js/async/ls.9d9a01026c.js +0 -104
- package/dist/client/static/js/async/m.eb2e6752e2.js +0 -28
- package/dist/client/static/js/async/m.eb2e6752e2.js.LICENSE.txt +0 -11
- package/dist/client/static/js/async/m3.d2b05f9604.js +0 -2
- package/dist/client/static/js/async/m3.d2b05f9604.js.LICENSE.txt +0 -6
- package/dist/client/static/js/async/ma.2c261b04dd.js +0 -2
- package/dist/client/static/js/async/ma.2c261b04dd.js.LICENSE.txt +0 -6
- package/dist/client/static/js/async/me.8ace414f80.js +0 -23
- package/dist/client/static/js/async/ms.98960af4eb.js +0 -67
- package/dist/client/static/js/async/ms.98960af4eb.js.LICENSE.txt +0 -12
- package/dist/client/static/js/async/mt.0352e976d8.js +0 -1
- package/dist/client/static/js/async/n.a9f1c51701.js +0 -1
- package/dist/client/static/js/async/na.a36cd532d6.js +0 -1
- package/dist/client/static/js/async/nk.fc7e58325e.js +0 -1
- package/dist/client/static/js/async/o.36353dfb88.js +0 -1
- package/dist/client/static/js/async/oc.b73042e8bd.js +0 -8
- package/dist/client/static/js/async/og.8eb577893a.js +0 -193
- package/dist/client/static/js/async/p.48ecfcd14e.js +0 -1
- package/dist/client/static/js/async/px.fc6877924b.js +0 -1
- package/dist/client/static/js/async/q.22588845a9.js +0 -21
- package/dist/client/static/js/async/q.22588845a9.js.LICENSE.txt +0 -6
- package/dist/client/static/js/async/q5.97dc1481b6.js +0 -286
- package/dist/client/static/js/async/qs.2a9ddb3c72.js +0 -1
- package/dist/client/static/js/async/r.51010ad87c.js +0 -1
- package/dist/client/static/js/async/rd.cb6bf495bb.js +0 -2
- package/dist/client/static/js/async/rd.cb6bf495bb.js.LICENSE.txt +0 -4
- package/dist/client/static/js/async/s.0f395cdda5.js +0 -94
- package/dist/client/static/js/async/t.4dca0e2ba8.js +0 -1
- package/dist/client/static/js/async/t9.d44f57d518.js +0 -1
- package/dist/client/static/js/async/ta.973534bbec.js +0 -1
- package/dist/client/static/js/async/tr.e878658140.js +0 -309
- package/dist/client/static/js/async/u.0871ac5b22.js +0 -1
- package/dist/client/static/js/async/ud.3065bfee31.js +0 -2
- package/dist/client/static/js/async/ud.3065bfee31.js.LICENSE.txt +0 -4
- package/dist/client/static/js/async/up.ea990da0ff.js +0 -32
- package/dist/client/static/js/async/uw.8890abbabc.js +0 -1
- package/dist/client/static/js/async/v.7d28d3c241.js +0 -34
- package/dist/client/static/js/async/vp.9b13bf8610.js +0 -1
- package/dist/client/static/js/async/vt.42416b707d.js +0 -1
- package/dist/client/static/js/async/w.08ac210f60.js +0 -1
- package/dist/client/static/js/async/wt.ad92393a90.js +0 -1
- package/dist/client/static/js/async/x.563f72ca6b.js +0 -1
- package/dist/client/static/js/async/x0.475516418f.js +0 -1
- package/dist/client/static/js/async/x1.da8687159b.js +0 -90
- package/dist/client/static/js/async/xe.da8dcc2015.js +0 -2
- package/dist/client/static/js/async/xe.da8dcc2015.js.LICENSE.txt +0 -11
- package/dist/client/static/js/async/xl.a3c562a58c.js +0 -1
- package/dist/client/static/js/async/xn.6510c0abe2.js +0 -2
- package/dist/client/static/js/async/xn.6510c0abe2.js.LICENSE.txt +0 -6
- package/dist/client/static/js/async/xn1.83a7784fe1.js +0 -10
- package/dist/client/static/js/async/xn1.83a7784fe1.js.LICENSE.txt +0 -11
- package/dist/client/static/js/async/xnl.feb0021e50.js +0 -2
- package/dist/client/static/js/async/xnl.feb0021e50.js.LICENSE.txt +0 -12
- package/dist/client/static/js/async/y.1a9ed7a5d8.js +0 -1
- package/dist/client/static/js/async/y6.43c57defe4.js +0 -1
- package/dist/client/static/js/async/yb.8c1342401d.js +0 -1
- package/dist/client/static/js/async/ybq.4491f2f2dc.js +0 -1
- package/dist/client/static/js/async/yg.35bebd6d0c.js +0 -149
- package/dist/client/static/js/async/yq.917ddd7ba2.js +0 -1
- package/dist/client/static/js/async/ys.00687cf82d.js +0 -38
- package/dist/client/static/js/async/yv.d99d829136.js +0 -1
- package/dist/client/static/js/async/z.56f61a4374.js +0 -1
- package/dist/client/static/js/async/zi.5fdb07b86a.js +0 -24
- package/dist/client/static/js/async/zj.654f37e8ff.js +0 -1
- package/dist/client/static/js/async/zn.966d6f1cc6.js +0 -1
- package/dist/client/static/js/async/zo.26213b40c0.js +0 -1
- package/dist/client/static/js/async/zx.e9f4105e00.js +0 -1
- package/dist/client/static/js/index.e6a257402a.js +0 -38
- package/dist/client/static/js/index.e6a257402a.js.LICENSE.txt +0 -4
- package/dist/client/static/js/markdown-vendor.71e43278b3.js +0 -144
- package/dist/client/static/js/shiki-vendor.cb8452ddcd.js +0 -1
- package/src/client/components/settings/categories/provider-settings/Icons.tsx +0 -35
- package/src/client/hooks/settings/providers.ts +0 -326
- package/src/server/plugins/dev-assets.ts +0 -49
- package/src/shared/lib/code/editor-utils.ts +0 -16
- package/src/shared/lib/models/provider-presets.ts +0 -29
- /package/dist/client/{apple-touch-icon.png → static/apple-touch-icon-dskx5sr3.png} +0 -0
- /package/dist/client/{icon-192x192.png → static/icon-192x192-6gn5cr2f.png} +0 -0
- /package/dist/client/{icon.svg → static/icon-d07z9dtz.svg} +0 -0
- /package/dist/client/{manifest.webmanifest → static/manifest-bnyy75kt.webmanifest} +0 -0
- /package/{dist/client → public}/icon-512x512.png +0 -0
- /package/{dist/client → public}/icon-maskable-512x512.png +0 -0
- /package/{dist/client → public}/sw.js +0 -0
- /package/src/{client/components/common/code-editor → shared/lib/code/editor}/history.ts +0 -0
- /package/src/shared/lib/models/{provider-cleanup.ts → provider/cleanup.ts} +0 -0
- /package/src/shared/lib/models/{provider-label.ts → provider/label.ts} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BarChart3, Bot, Files, GitBranch, Globe, Layers, Search, Terminal } from 'lucide-preact';
|
|
1
|
+
import { BarChart3, Bot, Files, GitBranch, Globe, Layers, ListTodo, Search, Terminal } from 'lucide-preact';
|
|
2
2
|
import type { ReactNode } from 'preact/compat';
|
|
3
3
|
import { useGitStatus } from '@/client/hooks/workspace/git-status';
|
|
4
4
|
import { GIT_STATUS_POLL_MS } from '@/shared/lib/workspace/refresh-cadence';
|
|
@@ -27,6 +27,7 @@ const PANEL_META: Record<RightPanelType, { title: string; icon: ReactNode }> = {
|
|
|
27
27
|
'user-browser': { title: 'Browser (Anda)', icon: <Globe size={16} /> },
|
|
28
28
|
browser: { title: 'Browser Agent', icon: <Bot size={16} /> },
|
|
29
29
|
usage: { title: 'Usage', icon: <BarChart3 size={16} /> },
|
|
30
|
+
todo: { title: 'Todos', icon: <ListTodo size={16} /> },
|
|
30
31
|
};
|
|
31
32
|
|
|
32
33
|
export function RightActivityBar({ activePanel, onChangePanel, isPanelOpen, hasActiveContext, activeProjectPath, refreshKey }: RightActivityBarProps) {
|
|
@@ -2,6 +2,19 @@ import { LayoutTemplate, MoreHorizontal, PanelLeft, PanelRight, PanelRightClose,
|
|
|
2
2
|
import { PWAInstallButton } from '@/client/components/common/PWAInstallButton';
|
|
3
3
|
import { StreamStatusDot } from '@/client/components/common/StreamStatusDot';
|
|
4
4
|
import type { AgentStreamStatus } from '@/shared/lib/chat/omp/status';
|
|
5
|
+
import { WORKSPACE_KEY_BINDINGS, type WorkspaceCommand } from '@/shared/lib/workspace/keymap';
|
|
6
|
+
import { describeBinding } from '@/shared/lib/ui/key-binding';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* A tooltip's text with the chord that actually invokes it. Derived from the
|
|
10
|
+
* workspace keymap rather than typed out, because a hand-written "⌘B" beside a
|
|
11
|
+
* binding that listens for something else is exactly the drift the keymap
|
|
12
|
+
* table exists to prevent.
|
|
13
|
+
*/
|
|
14
|
+
function withChord(command: WorkspaceCommand, label: string): string {
|
|
15
|
+
const binding = WORKSPACE_KEY_BINDINGS.find((entry) => entry.command === command);
|
|
16
|
+
return binding ? `${label} (${describeBinding(binding)})` : label;
|
|
17
|
+
}
|
|
5
18
|
|
|
6
19
|
interface TopNavbarProps {
|
|
7
20
|
sessionTitle: string | null;
|
|
@@ -42,8 +55,8 @@ export function TopNavbar({
|
|
|
42
55
|
type="button"
|
|
43
56
|
onClick={onToggleLeftPanel}
|
|
44
57
|
className="p-1.5 rounded hover:bg-ink/10 transition-colors text-ink/60 hover:text-ink cursor-pointer flex-shrink-0 titlebar-no-drag"
|
|
45
|
-
title=
|
|
46
|
-
aria-label=
|
|
58
|
+
title={withChord('toggleSidebar', 'Expand Sidebar')}
|
|
59
|
+
aria-label={withChord('toggleSidebar', 'Expand Sidebar')}
|
|
47
60
|
>
|
|
48
61
|
<PanelLeft size={16} />
|
|
49
62
|
</button>
|
|
@@ -86,7 +99,9 @@ export function TopNavbar({
|
|
|
86
99
|
type="button"
|
|
87
100
|
onClick={onToggleEditor}
|
|
88
101
|
className={`p-1.5 rounded hover:bg-ink/10 transition-colors cursor-pointer ${showEditor ? 'text-ink' : 'text-ink/40'}`}
|
|
89
|
-
title=
|
|
102
|
+
title={withChord('toggleEditorPanel', 'Toggle Editor Layout')}
|
|
103
|
+
aria-label={withChord('toggleEditorPanel', 'Toggle Editor Layout')}
|
|
104
|
+
aria-pressed={showEditor}
|
|
90
105
|
>
|
|
91
106
|
<LayoutTemplate size={16} />
|
|
92
107
|
</button>
|
|
@@ -94,7 +109,9 @@ export function TopNavbar({
|
|
|
94
109
|
type="button"
|
|
95
110
|
onClick={onToggleRightPanel}
|
|
96
111
|
className={`p-1.5 rounded hover:bg-ink/10 transition-colors cursor-pointer ${showRightPanel ? 'text-ink' : 'text-ink/40'}`}
|
|
97
|
-
title=
|
|
112
|
+
title={withChord('toggleRightPanel', 'Toggle Right Panel')}
|
|
113
|
+
aria-label={withChord('toggleRightPanel', 'Toggle Right Panel')}
|
|
114
|
+
aria-pressed={showRightPanel}
|
|
98
115
|
>
|
|
99
116
|
{showRightPanel ? <PanelRightClose size={16} /> : <PanelRight size={16} />}
|
|
100
117
|
</button>
|
|
@@ -56,6 +56,8 @@ interface WorkspacePanelsProps {
|
|
|
56
56
|
refreshKey: number;
|
|
57
57
|
onSetActiveFileId: (id: number | string | null) => void;
|
|
58
58
|
onCloseFile: (id: number | string) => void;
|
|
59
|
+
/** Replace a diff tab with the plain editor tab for the same file. */
|
|
60
|
+
onConvertDiffToEditor: (id: number | string) => void;
|
|
59
61
|
onOpenFile: (file: any) => void;
|
|
60
62
|
onRefreshWorkspace: () => void;
|
|
61
63
|
onChangeRightPanel: (panel: RightPanelType) => void;
|
|
@@ -81,6 +83,7 @@ export function WorkspacePanels(props: WorkspacePanelsProps) {
|
|
|
81
83
|
refreshKey,
|
|
82
84
|
onSetActiveFileId,
|
|
83
85
|
onCloseFile,
|
|
86
|
+
onConvertDiffToEditor,
|
|
84
87
|
onOpenFile,
|
|
85
88
|
onRefreshWorkspace,
|
|
86
89
|
onChangeRightPanel,
|
|
@@ -185,6 +188,7 @@ export function WorkspacePanels(props: WorkspacePanelsProps) {
|
|
|
185
188
|
activeFileId={activeFileId}
|
|
186
189
|
onSelectFile={onSetActiveFileId}
|
|
187
190
|
onCloseFile={onCloseFile}
|
|
191
|
+
onConvertDiffToEditor={onConvertDiffToEditor}
|
|
188
192
|
refreshKey={refreshKey}
|
|
189
193
|
onFileSaved={onRefreshWorkspace}
|
|
190
194
|
/>
|
|
@@ -16,6 +16,8 @@ import { useSidebarData } from '@/client/hooks/chat/omp/session-list';
|
|
|
16
16
|
import { DEFAULT_LEFT_PANEL_WIDTH, MAX_LEFT_PANEL_WIDTH, MIN_LEFT_PANEL_WIDTH, type EditorWidthMode } from '@/shared/lib/workspace/panel-widths';
|
|
17
17
|
import { ResizeHandle } from '@/client/components/layout/desktop-layout/ResizeHandle';
|
|
18
18
|
import { useChamberEvent, useWindowEvent } from '@/client/hooks/ui/window-event';
|
|
19
|
+
import { WORKSPACE_KEY_BINDINGS } from '@/shared/lib/workspace/keymap';
|
|
20
|
+
import { resolveBinding } from '@/shared/lib/ui/key-binding';
|
|
19
21
|
|
|
20
22
|
interface DesktopLayoutProps {
|
|
21
23
|
sessionId: string | null;
|
|
@@ -56,6 +58,7 @@ export function DesktopLayout({ sessionId, onSwitchToMobile, appSettings = {} }:
|
|
|
56
58
|
setActiveFileId,
|
|
57
59
|
handleOpenFile,
|
|
58
60
|
handleCloseFile,
|
|
61
|
+
convertDiffToEditor,
|
|
59
62
|
} = useFileTabs(activeProjectPath, sessionId || '', handleOpenTab);
|
|
60
63
|
|
|
61
64
|
const showEditor = openedFiles.length > 0 && (userToggledEditor ?? true);
|
|
@@ -83,13 +86,31 @@ export function DesktopLayout({ sessionId, onSwitchToMobile, appSettings = {} }:
|
|
|
83
86
|
const [sessionTitle, setSessionTitle] = useState<string | null>(null);
|
|
84
87
|
const streamStatus = useAgentStreamStatus();
|
|
85
88
|
|
|
86
|
-
|
|
89
|
+
/**
|
|
90
|
+
* The workspace's own shortcuts, resolved from the shared keymap so the
|
|
91
|
+
* tooltips on the panel toggles name the chord that is actually bound.
|
|
92
|
+
*
|
|
93
|
+
* `⌘S` is deliberately absent here: the editor panel already owns it (it is
|
|
94
|
+
* the only surface with a buffer to save), and binding it twice would save
|
|
95
|
+
* the file twice.
|
|
96
|
+
*/
|
|
87
97
|
useWindowEvent('keydown', (e) => {
|
|
88
|
-
|
|
89
|
-
|
|
98
|
+
const command = resolveBinding(WORKSPACE_KEY_BINDINGS, e);
|
|
99
|
+
if (!command) return;
|
|
100
|
+
if (command === 'saveFile') return;
|
|
101
|
+
if (command === 'toggleEditorPanel' && !showEditor) {
|
|
102
|
+
// The editor panel is only meaningful with a file open, and `showEditor`
|
|
103
|
+
// already folds in the user's own toggle.
|
|
104
|
+
if (openedFiles.length === 0) return;
|
|
105
|
+
}
|
|
106
|
+
e.preventDefault();
|
|
107
|
+
if (command === 'toggleSidebar') setShowLeftPanel((previous) => !previous);
|
|
108
|
+
else if (command === 'toggleEditorPanel') setUserToggledEditor((previous) => !(previous ?? showEditor));
|
|
109
|
+
else if (command === 'toggleRightPanel') setShowRightPanel((previous) => !previous);
|
|
110
|
+
else if (command === 'openSettings') {
|
|
90
111
|
setSettingsCategory('appearance');
|
|
91
112
|
setAutoOpenAddProvider(false);
|
|
92
|
-
setSettingsOpen(
|
|
113
|
+
setSettingsOpen((previous) => !previous);
|
|
93
114
|
}
|
|
94
115
|
});
|
|
95
116
|
|
|
@@ -183,6 +204,7 @@ export function DesktopLayout({ sessionId, onSwitchToMobile, appSettings = {} }:
|
|
|
183
204
|
refreshKey={refreshKey}
|
|
184
205
|
onSetActiveFileId={setActiveFileId}
|
|
185
206
|
onCloseFile={handleCloseFile}
|
|
207
|
+
onConvertDiffToEditor={convertDiffToEditor}
|
|
186
208
|
onOpenFile={handleOpenFile}
|
|
187
209
|
onRefreshWorkspace={handleRefreshWorkspace}
|
|
188
210
|
onChangeRightPanel={handleChangeRightPanel}
|
|
@@ -118,6 +118,21 @@ export function MobileLayoutWrapper({ onDesktopToggle, appSettings = {} }: Mobil
|
|
|
118
118
|
setCurrentScreen('main');
|
|
119
119
|
};
|
|
120
120
|
|
|
121
|
+
// Desktop parity: the `+` on a workspace header creates the pending session
|
|
122
|
+
// INSIDE that folder, so the prewarmed cwd and the eventual spawn cwd are the
|
|
123
|
+
// folder's — not whatever the active session resolved to.
|
|
124
|
+
const handleNewSessionForFolder = (targetFolderId: number) => {
|
|
125
|
+
const cwd = spawnCwdForNewSession(folders, sessionParam, targetFolderId);
|
|
126
|
+
if (cwd) triggerSessionPrewarm(cwd);
|
|
127
|
+
setSearchParams(prev => {
|
|
128
|
+
const next = new URLSearchParams(prev);
|
|
129
|
+
next.set('sessionId', `new-${Date.now()}`);
|
|
130
|
+
next.set('folderId', targetFolderId.toString());
|
|
131
|
+
return next;
|
|
132
|
+
}, { replace: true });
|
|
133
|
+
setCurrentScreen('main');
|
|
134
|
+
};
|
|
135
|
+
|
|
121
136
|
const handleCreateFolder = async (input: { name: string; path?: string }) => {
|
|
122
137
|
const res = await fetch('/api/folders', {
|
|
123
138
|
method: 'POST',
|
|
@@ -162,6 +177,7 @@ export function MobileLayoutWrapper({ onDesktopToggle, appSettings = {} }: Mobil
|
|
|
162
177
|
activeSessionId={sessionId}
|
|
163
178
|
onSelectSession={handleSelectSession}
|
|
164
179
|
onNewSession={handleNewSession}
|
|
180
|
+
onNewSessionForFolder={handleNewSessionForFolder}
|
|
165
181
|
onCreateFolder={handleCreateFolder}
|
|
166
182
|
onClose={() => setCurrentScreen('main')}
|
|
167
183
|
onDesktopToggle={onDesktopToggle}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { useState } from 'preact/hooks';
|
|
2
2
|
import { Suspense } from 'preact/compat';
|
|
3
3
|
import type { ReactNode } from 'preact/compat';
|
|
4
|
-
import { BarChart3, Bot, Files, GitBranch, Globe, Layers, Search, Terminal, X } from 'lucide-preact';
|
|
5
|
-
import { LazyBrowserPanel, LazyContextPanel, LazyFileExplorer, LazyGitPanel, LazySearchPanel, LazyTerminalPanel, LazyUsagePanel, LazyUserBrowserPanel } from '@/client/components/common/lazy-panels';
|
|
4
|
+
import { BarChart3, Bot, Files, GitBranch, Globe, Layers, ListTodo, Search, Terminal, X } from 'lucide-preact';
|
|
5
|
+
import { LazyBrowserPanel, LazyContextPanel, LazyFileExplorer, LazyGitPanel, LazySearchPanel, LazyTerminalPanel, LazyTodoPanel, LazyUsagePanel, LazyUserBrowserPanel } from '@/client/components/common/lazy-panels';
|
|
6
6
|
import { useGitStatus } from '@/client/hooks/workspace/git-status';
|
|
7
7
|
import { GIT_STATUS_POLL_MS } from '@/shared/lib/workspace/refresh-cadence';
|
|
8
8
|
import { RIGHT_PANEL_TYPES, type RightPanelType } from '@/shared/lib/workspace/right-panels';
|
|
@@ -31,6 +31,7 @@ const PANEL_META: Record<RightPanelType, { title: string; label: string; icon: R
|
|
|
31
31
|
'user-browser': { title: 'Browser (Anda)', label: 'Browser', icon: <Globe size={14} className="flex-shrink-0" /> },
|
|
32
32
|
browser: { title: 'Browser Agent', label: 'Agent', icon: <Bot size={14} className="flex-shrink-0" /> },
|
|
33
33
|
usage: { title: 'Usage', label: 'Usage', icon: <BarChart3 size={14} className="flex-shrink-0" /> },
|
|
34
|
+
todo: { title: 'Todos', label: 'Todos', icon: <ListTodo size={14} className="flex-shrink-0" /> },
|
|
34
35
|
};
|
|
35
36
|
|
|
36
37
|
export function MobileRightSidebar({
|
|
@@ -100,12 +101,17 @@ export function MobileRightSidebar({
|
|
|
100
101
|
</button>
|
|
101
102
|
</div>
|
|
102
103
|
|
|
103
|
-
{/* Main Tab Content — shared components so mobile == desktop features
|
|
104
|
+
{/* Main Tab Content — shared components so mobile == desktop features.
|
|
105
|
+
The workspace gate below applies per TAB, not to the whole drawer: a
|
|
106
|
+
todo list belongs to the session, not to the folder its cwd resolves
|
|
107
|
+
to, so the Todos tab stays reachable for a session running outside
|
|
108
|
+
every registered workspace. Every other view here reads the working
|
|
109
|
+
tree and genuinely needs one. */}
|
|
104
110
|
<div
|
|
105
111
|
className="flex-1 min-h-0 overflow-hidden relative"
|
|
106
112
|
style={{ paddingBottom: 'env(safe-area-inset-bottom, 0px)' }}
|
|
107
113
|
>
|
|
108
|
-
{!enabled ? (
|
|
114
|
+
{!enabled && activeTab !== 'todo' ? (
|
|
109
115
|
<div className="h-full flex items-center justify-center text-ink/40">
|
|
110
116
|
<span className="text-xs font-mono">No session selected</span>
|
|
111
117
|
</div>
|
|
@@ -130,6 +136,7 @@ export function MobileRightSidebar({
|
|
|
130
136
|
{activeTab === 'user-browser' && <LazyUserBrowserPanel className="h-full w-full" />}
|
|
131
137
|
{activeTab === 'browser' && <LazyBrowserPanel className="h-full w-full" active />}
|
|
132
138
|
{activeTab === 'usage' && <LazyUsagePanel className="h-full w-full" />}
|
|
139
|
+
{activeTab === 'todo' && <LazyTodoPanel className="h-full w-full" />}
|
|
133
140
|
</Suspense>
|
|
134
141
|
</>
|
|
135
142
|
)}
|
|
@@ -16,6 +16,7 @@ interface MobileSessionSidebarProps {
|
|
|
16
16
|
activeSessionId: number | string | null;
|
|
17
17
|
onSelectSession: (id: number | string) => void;
|
|
18
18
|
onNewSession: () => void;
|
|
19
|
+
onNewSessionForFolder: (folderId: number) => void;
|
|
19
20
|
onCreateFolder: (input: { name: string; path?: string }) => Promise<void> | void;
|
|
20
21
|
onClose: () => void;
|
|
21
22
|
onDesktopToggle?: () => void;
|
|
@@ -26,6 +27,7 @@ export function MobileSessionSidebar({
|
|
|
26
27
|
activeSessionId,
|
|
27
28
|
onSelectSession,
|
|
28
29
|
onNewSession,
|
|
30
|
+
onNewSessionForFolder,
|
|
29
31
|
onCreateFolder,
|
|
30
32
|
onClose,
|
|
31
33
|
onDesktopToggle,
|
|
@@ -96,6 +98,13 @@ export function MobileSessionSidebar({
|
|
|
96
98
|
onClose();
|
|
97
99
|
};
|
|
98
100
|
|
|
101
|
+
// Same dismissal as the toolbar's New Session: the pending session is opened
|
|
102
|
+
// behind the drawer, so the user must land on the chat, not on the list.
|
|
103
|
+
const handleNewSessionForFolderAndClose = (folderId: number) => {
|
|
104
|
+
onNewSessionForFolder(folderId);
|
|
105
|
+
onClose();
|
|
106
|
+
};
|
|
107
|
+
|
|
99
108
|
const handleToggleArchived = () => {
|
|
100
109
|
setShowArchived(!showArchived);
|
|
101
110
|
setOptionsOpen(false);
|
|
@@ -136,6 +145,7 @@ export function MobileSessionSidebar({
|
|
|
136
145
|
isScrolling={isScrolling}
|
|
137
146
|
onScroll={handleScroll}
|
|
138
147
|
onSelectSession={handleSelectSession}
|
|
148
|
+
onNewSessionForFolder={handleNewSessionForFolderAndClose}
|
|
139
149
|
onToggleFolder={toggleFolder}
|
|
140
150
|
/>
|
|
141
151
|
)}
|
|
@@ -29,7 +29,6 @@ export function MobileFullEditor({ file, onClose, onFileSaved }: MobileFullEdito
|
|
|
29
29
|
const isMd = file.name.endsWith('.md');
|
|
30
30
|
|
|
31
31
|
const editor = useFileEditor(file, {
|
|
32
|
-
reportLoadError: true,
|
|
33
32
|
flushOnUnmount: true,
|
|
34
33
|
reportSaveError: true,
|
|
35
34
|
downloadMimeType: 'text/plain;charset=utf-8',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useRef, useState } from 'preact/hooks';
|
|
2
|
-
import { ChevronDown, ChevronRight, GitBranch, MessageSquare, MoreHorizontal } from 'lucide-preact';
|
|
2
|
+
import { ChevronDown, ChevronRight, GitBranch, MessageSquare, MoreHorizontal, Plus } from 'lucide-preact';
|
|
3
3
|
import { MobileSessionRow } from '@/client/components/mobile/mobile-session-sidebar/SessionRow';
|
|
4
4
|
import { WorkspaceOptionsMenu } from '@/client/components/common/workspace-options-menu';
|
|
5
5
|
import { useShowMore } from '@/client/hooks/ui/show-more';
|
|
@@ -14,6 +14,7 @@ interface MobileSessionCategoryProps {
|
|
|
14
14
|
folder: WorkspaceFolderData;
|
|
15
15
|
activeSessionId: number | string | null;
|
|
16
16
|
onSelectSession: (id: number | string) => void;
|
|
17
|
+
onNewSessionForFolder: (folderId: number) => void;
|
|
17
18
|
isExpanded: boolean;
|
|
18
19
|
onToggleExpand: () => void;
|
|
19
20
|
showArchived?: boolean;
|
|
@@ -24,6 +25,7 @@ export function MobileSessionCategory({
|
|
|
24
25
|
folder,
|
|
25
26
|
activeSessionId,
|
|
26
27
|
onSelectSession,
|
|
28
|
+
onNewSessionForFolder,
|
|
27
29
|
isExpanded,
|
|
28
30
|
onToggleExpand,
|
|
29
31
|
showArchived = false,
|
|
@@ -104,6 +106,19 @@ export function MobileSessionCategory({
|
|
|
104
106
|
<GitBranch size={13} className="text-ink/50 ml-1" />
|
|
105
107
|
)}
|
|
106
108
|
|
|
109
|
+
<button
|
|
110
|
+
type="button"
|
|
111
|
+
onClick={(event) => {
|
|
112
|
+
event.stopPropagation();
|
|
113
|
+
onNewSessionForFolder(folder.id);
|
|
114
|
+
}}
|
|
115
|
+
className="p-1.5 rounded-lg hover:bg-ink/10 active:bg-ink/15 text-ink/60 hover:text-ink"
|
|
116
|
+
title="New Session"
|
|
117
|
+
aria-label={`New session in ${folder.name}`}
|
|
118
|
+
>
|
|
119
|
+
<Plus size={15} />
|
|
120
|
+
</button>
|
|
121
|
+
|
|
107
122
|
<div className="relative flex items-center" ref={menuRef} onClick={(event) => event.stopPropagation()}>
|
|
108
123
|
<button
|
|
109
124
|
type="button"
|
|
@@ -11,6 +11,7 @@ interface MobileSessionListProps {
|
|
|
11
11
|
isScrolling: boolean;
|
|
12
12
|
onScroll: () => void;
|
|
13
13
|
onSelectSession: (id: number | string) => void;
|
|
14
|
+
onNewSessionForFolder: (folderId: number) => void;
|
|
14
15
|
onToggleFolder: (folderId: number) => void;
|
|
15
16
|
}
|
|
16
17
|
|
|
@@ -23,6 +24,7 @@ export function MobileSessionList({
|
|
|
23
24
|
isScrolling,
|
|
24
25
|
onScroll,
|
|
25
26
|
onSelectSession,
|
|
27
|
+
onNewSessionForFolder,
|
|
26
28
|
onToggleFolder,
|
|
27
29
|
}: MobileSessionListProps) {
|
|
28
30
|
return (
|
|
@@ -41,6 +43,7 @@ export function MobileSessionList({
|
|
|
41
43
|
folder={folder}
|
|
42
44
|
activeSessionId={activeSessionId}
|
|
43
45
|
onSelectSession={onSelectSession}
|
|
46
|
+
onNewSessionForFolder={onNewSessionForFolder}
|
|
44
47
|
isExpanded={expandedFolders[folder.id] ?? true}
|
|
45
48
|
onToggleExpand={() => onToggleFolder(folder.id)}
|
|
46
49
|
showArchived={showArchived}
|
|
@@ -9,6 +9,10 @@ import { ReconnectModal } from '@/client/components/settings/categories/provider
|
|
|
9
9
|
import { LoginModal } from '@/client/components/settings/categories/provider-settings/LoginModal';
|
|
10
10
|
import { ModelConfigModal } from '@/client/components/settings/categories/provider-settings/ModelConfigModal';
|
|
11
11
|
import { ModelCapabilitiesModal } from '@/client/components/settings/categories/provider-settings/ModelCapabilitiesModal';
|
|
12
|
+
import { AddModelModal } from '@/client/components/settings/categories/provider-settings/AddModelModal';
|
|
13
|
+
import { DeleteProviderModal } from '@/client/components/settings/categories/provider-settings/DeleteProviderModal';
|
|
14
|
+
import { providerEmptyReason } from '@/shared/lib/models/provider/dialect';
|
|
15
|
+
import { configuredProviderSlugs } from '@/shared/lib/models/provider/presets';
|
|
12
16
|
|
|
13
17
|
interface ProviderSettingsProps {
|
|
14
18
|
autoOpenAdd?: boolean;
|
|
@@ -28,7 +32,15 @@ export function ProviderSettings({
|
|
|
28
32
|
setCurrentProject,
|
|
29
33
|
isFetchingModels,
|
|
30
34
|
toasts,
|
|
35
|
+
pushToast,
|
|
31
36
|
dismissToast,
|
|
37
|
+
isAddModelModalOpen,
|
|
38
|
+
setIsAddModelModalOpen,
|
|
39
|
+
handleModelAdded,
|
|
40
|
+
isDeleteModalOpen,
|
|
41
|
+
setIsDeleteModalOpen,
|
|
42
|
+
isDeletingProvider,
|
|
43
|
+
handleDeleteProvider,
|
|
32
44
|
isAddModalOpen,
|
|
33
45
|
setIsAddModalOpen,
|
|
34
46
|
isReconnectModalOpen,
|
|
@@ -72,19 +84,31 @@ export function ProviderSettings({
|
|
|
72
84
|
<ProviderAuthSection
|
|
73
85
|
provider={selectedProvider}
|
|
74
86
|
onOpenReconnectModal={() => {
|
|
75
|
-
|
|
76
|
-
|
|
87
|
+
// A provider omp signs in through `/login` needs the OAuth
|
|
88
|
+
// dialog; one whose endpoint and key live in models.yml (or the
|
|
89
|
+
// chamber overlay) is edited in place. Testing the provider ID
|
|
90
|
+
// for `omp-auth-` was wrong: a native models.yml entry shares
|
|
91
|
+
// that ID prefix once merged, and a keyless local server has no
|
|
92
|
+
// login flow to complete at all.
|
|
93
|
+
if (selectedProvider.credentialSource === 'omp-auth' && selectedProvider.auth !== 'none') {
|
|
94
|
+
setIsLoginModalOpen(true);
|
|
95
|
+
} else {
|
|
96
|
+
setIsReconnectModalOpen(true);
|
|
97
|
+
}
|
|
77
98
|
}}
|
|
78
99
|
onToggleDisconnect={handleToggleDisconnect}
|
|
79
100
|
onToggleDisabled={handleToggleProviderDisabled}
|
|
101
|
+
onDelete={() => setIsDeleteModalOpen(true)}
|
|
80
102
|
/>
|
|
81
103
|
|
|
82
104
|
<ProviderModelsList
|
|
83
105
|
models={selectedProvider.models}
|
|
106
|
+
emptyReason={providerEmptyReason(selectedProvider)}
|
|
84
107
|
onToggleModelVisibility={handleToggleModelVisibility}
|
|
85
108
|
onHideAll={handleHideAll}
|
|
86
109
|
onShowAll={handleShowAll}
|
|
87
110
|
onFetchModels={handleFetchModelsFromList}
|
|
111
|
+
onAddModel={() => setIsAddModelModalOpen(true)}
|
|
88
112
|
canFetchModels={Boolean(selectedProvider.baseUrl)}
|
|
89
113
|
isFetchingModels={isFetchingModels}
|
|
90
114
|
onOpenModelConfig={(model) => setConfigModel(model)}
|
|
@@ -108,7 +132,7 @@ export function ProviderSettings({
|
|
|
108
132
|
}}
|
|
109
133
|
onAddProvider={handleAddProvider}
|
|
110
134
|
presets={availablePresetProviders}
|
|
111
|
-
existingSlugs={providers
|
|
135
|
+
existingSlugs={configuredProviderSlugs(providers)}
|
|
112
136
|
/>
|
|
113
137
|
|
|
114
138
|
{selectedProvider && (
|
|
@@ -131,13 +155,30 @@ export function ProviderSettings({
|
|
|
131
155
|
/>
|
|
132
156
|
)}
|
|
133
157
|
|
|
158
|
+
{selectedProvider && (
|
|
159
|
+
<AddModelModal
|
|
160
|
+
isOpen={isAddModelModalOpen}
|
|
161
|
+
provider={selectedProvider}
|
|
162
|
+
onClose={() => setIsAddModelModalOpen(false)}
|
|
163
|
+
onAdded={(modelId) => void handleModelAdded(modelId)}
|
|
164
|
+
onError={(message) => pushToast(message, 'error')}
|
|
165
|
+
/>
|
|
166
|
+
)}
|
|
167
|
+
|
|
168
|
+
<DeleteProviderModal
|
|
169
|
+
isOpen={isDeleteModalOpen}
|
|
170
|
+
provider={selectedProvider ?? null}
|
|
171
|
+
isDeleting={isDeletingProvider}
|
|
172
|
+
onClose={() => setIsDeleteModalOpen(false)}
|
|
173
|
+
onConfirm={() => void handleDeleteProvider()}
|
|
174
|
+
/>
|
|
175
|
+
|
|
134
176
|
<ModelConfigModal
|
|
135
177
|
isOpen={!!configModel}
|
|
136
178
|
model={configModel}
|
|
137
179
|
onClose={() => setConfigModel(null)}
|
|
138
180
|
onSaveModelConfig={handleSaveModelConfig}
|
|
139
181
|
/>
|
|
140
|
-
|
|
141
182
|
<ModelCapabilitiesModal
|
|
142
183
|
isOpen={!!capabilitiesModel}
|
|
143
184
|
model={capabilitiesModel}
|
|
@@ -1,15 +1,24 @@
|
|
|
1
|
-
import { useState } from 'preact/hooks';
|
|
1
|
+
import { useEffect, useState } from 'preact/hooks';
|
|
2
2
|
import { AlertCircle, RefreshCw } from 'lucide-preact';
|
|
3
3
|
import { UsageSidebarList } from '@/client/components/settings/categories/usage-settings/SidebarList';
|
|
4
|
-
import type
|
|
4
|
+
import { buildProviders, type UsageProviderId } from '@/client/components/settings/categories/usage-settings/providers';
|
|
5
5
|
import { ProviderDetail } from '@/client/components/settings/categories/usage-settings/ProviderDetail';
|
|
6
6
|
import { formatDateTime } from '@/client/components/settings/categories/usage-settings/format';
|
|
7
7
|
import { useUsageReport } from '@/client/hooks/settings/useUsageReport';
|
|
8
8
|
|
|
9
|
-
/** Settings → Usage: provider
|
|
9
|
+
/** Settings → Usage: provider quota, balances, and locally recorded burn. */
|
|
10
10
|
export function UsageSettings() {
|
|
11
11
|
const { report, isLoading, error, reload } = useUsageReport();
|
|
12
|
-
const [selectedProviderId, setSelectedProviderId] = useState<UsageProviderId>('
|
|
12
|
+
const [selectedProviderId, setSelectedProviderId] = useState<UsageProviderId>('');
|
|
13
|
+
|
|
14
|
+
const providers = report ? buildProviders(report) : [];
|
|
15
|
+
const selected = providers.find((provider) => provider.id === selectedProviderId) ?? providers[0];
|
|
16
|
+
|
|
17
|
+
// The report can arrive with a different provider set (a key was added or
|
|
18
|
+
// removed); keep the selection pointing at something that exists.
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
if (selected && selected.id !== selectedProviderId) setSelectedProviderId(selected.id);
|
|
21
|
+
}, [selected, selectedProviderId]);
|
|
13
22
|
|
|
14
23
|
if (error && !report) {
|
|
15
24
|
return (
|
|
@@ -39,7 +48,7 @@ export function UsageSettings() {
|
|
|
39
48
|
<div className="flex h-full w-full overflow-hidden bg-paper text-xs text-ink">
|
|
40
49
|
<UsageSidebarList
|
|
41
50
|
report={report}
|
|
42
|
-
selectedProviderId={
|
|
51
|
+
selectedProviderId={selected?.id ?? ''}
|
|
43
52
|
onSelectProvider={setSelectedProviderId}
|
|
44
53
|
/>
|
|
45
54
|
|
|
@@ -57,7 +66,7 @@ export function UsageSettings() {
|
|
|
57
66
|
</div>
|
|
58
67
|
<button
|
|
59
68
|
type="button"
|
|
60
|
-
onClick={() => reload()}
|
|
69
|
+
onClick={() => reload({ force: true })}
|
|
61
70
|
disabled={isLoading}
|
|
62
71
|
className="p-1.5 bg-paper border border-ink/15 rounded-md hover:bg-ink/5 text-ink/80 transition-colors disabled:opacity-50 flex-shrink-0"
|
|
63
72
|
title="Refresh usage"
|
|
@@ -69,7 +78,13 @@ export function UsageSettings() {
|
|
|
69
78
|
<div className="flex-1 overflow-y-auto scrollbar-overlay-container scrollbar-overlay-static p-3.5 space-y-4">
|
|
70
79
|
{error && <p className="text-error text-xs">{error}</p>}
|
|
71
80
|
|
|
72
|
-
|
|
81
|
+
{selected ? (
|
|
82
|
+
<ProviderDetail summary={selected.summary} />
|
|
83
|
+
) : (
|
|
84
|
+
<p className="text-[11px] text-ink/50 leading-relaxed">
|
|
85
|
+
No provider credentials detected. Add an API key in Settings → Providers and it will appear here.
|
|
86
|
+
</p>
|
|
87
|
+
)}
|
|
73
88
|
</div>
|
|
74
89
|
</div>
|
|
75
90
|
</div>
|