소스 검색

wip: desktop work

Adam 5 달 전
부모
커밋
a8bf1ad40f

+ 4 - 1
packages/desktop/src/context/sync.tsx

@@ -124,7 +124,7 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
     const absolute = (path: string) => (store.path.directory + "/" + path).replace("//", "/")
     const sanitizePart = (part: Part) => {
       if (part.type === "tool") {
-        if (part.state.status === "completed") {
+        if (part.state.status === "completed" || part.state.status === "error") {
           for (const key in part.state.metadata) {
             if (typeof part.state.metadata[key] === "string") {
               part.state.metadata[key] = sanitize(part.state.metadata[key] as string)
@@ -135,6 +135,9 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
               part.state.input[key] = sanitize(part.state.input[key] as string)
             }
           }
+          if ("error" in part.state) {
+            part.state.error = sanitize(part.state.error as string)
+          }
         }
       }
       return part

+ 30 - 28
packages/desktop/src/pages/index.tsx

@@ -53,10 +53,11 @@ export default function Page() {
   const [activeItem, setActiveItem] = createSignal<string | undefined>(undefined)
 
   createEffect(() => {
-    if (!local.session.activeMessage()) return
-    if (!messageScrollElement) return
-    const element = messageScrollElement.querySelector(`[data-message="${local.session.activeMessage()?.id}"]`)
-    element?.scrollIntoView({ block: "start", behavior: "instant" })
+    // Set first message as active if none selected
+    const userMessages = local.session.userMessages()
+    if (userMessages.length > 0 && !local.session.activeMessage()) {
+      local.session.setActiveMessage(userMessages[0].id)
+    }
   })
 
   const MOD = typeof navigator === "object" && /(Mac|iPod|iPhone|iPad)/.test(navigator.platform) ? "Meta" : "Control"
@@ -567,28 +568,29 @@ export default function Page() {
                             </ul>
                           </Show>
                           <div ref={messageScrollElement} class="grow min-w-0 h-full overflow-y-auto no-scrollbar">
-                            <div class="flex flex-col items-start gap-50 pb-50">
-                              <For each={local.session.userMessages()}>
-                                {(message) => {
-                                  const [initialized, setInitialized] = createSignal(!!message.summary?.title)
-                                  const [expanded, setExpanded] = createSignal(false)
-                                  const parts = createMemo(() => sync.data.part[message.id])
-                                  const title = createMemo(() => message.summary?.title)
-                                  const summary = createMemo(() => message.summary?.body)
-                                  const assistantMessages = createMemo(() => {
-                                    return sync.data.message[activeSession().id]?.filter(
-                                      (m) => m.role === "assistant" && m.parentID == message.id,
-                                    ) as AssistantMessageType[]
-                                  })
-                                  const working = createMemo(() => !summary())
-                                  createEffect(() => {
-                                    setTimeout(() => setInitialized(!!title()), 10_000)
-                                  })
-
-                                  return (
+                            <For each={local.session.userMessages()}>
+                              {(message) => {
+                                const isActive = createMemo(() => local.session.activeMessage()?.id === message.id)
+                                const [initialized, setInitialized] = createSignal(!!message.summary?.title)
+                                const [expanded, setExpanded] = createSignal(false)
+                                const parts = createMemo(() => sync.data.part[message.id])
+                                const title = createMemo(() => message.summary?.title)
+                                const summary = createMemo(() => message.summary?.body)
+                                const assistantMessages = createMemo(() => {
+                                  return sync.data.message[activeSession().id]?.filter(
+                                    (m) => m.role === "assistant" && m.parentID == message.id,
+                                  ) as AssistantMessageType[]
+                                })
+                                const working = createMemo(() => !summary())
+                                createEffect(() => {
+                                  setTimeout(() => setInitialized(!!title()), 10_000)
+                                })
+
+                                return (
+                                  <Show when={isActive()}>
                                     <div
                                       data-message={message.id}
-                                      class="flex flex-col items-start self-stretch gap-8 min-h-screen"
+                                      class="flex flex-col items-start self-stretch gap-8 pb-50"
                                     >
                                       {/* Title */}
                                       <div class="py-2 flex flex-col items-start gap-2 self-stretch sticky top-0 bg-background-stronger z-10">
@@ -774,10 +776,10 @@ export default function Page() {
                                         </Switch>
                                       </div>
                                     </div>
-                                  )
-                                }}
-                              </For>
-                            </div>
+                                  </Show>
+                                )
+                              }}
+                            </For>
                           </div>
                         </div>
                       </div>

+ 22 - 17
packages/ui/script/colors.txt

@@ -2,8 +2,8 @@
 --background-weak: var(--smoke-light-3);
 --background-strong: var(--smoke-light-1);
 --background-stronger: #FCFCFC;
---base: var(--smoke-light-alpha-2);
 --surface-base: var(--smoke-light-alpha-2);
+--base: var(--smoke-light-alpha-2);
 --surface-base-hover: #0500000F;
 --surface-base-active: var(--smoke-light-alpha-3);
 --surface-base-interactive-active: var(--cobalt-light-alpha-3);
@@ -17,6 +17,7 @@
 --surface-float-base: var(--smoke-dark-1);
 --surface-float-base-hover: var(--smoke-dark-2);
 --surface-raised-base-hover: var(--smoke-light-alpha-2);
+--surface-raised-base-active: var(--smoke-light-alpha-3);
 --surface-raised-strong: var(--smoke-light-1);
 --surface-raised-strong-hover: var(--white);
 --surface-raised-stronger: var(--white);
@@ -43,8 +44,8 @@
 --surface-info-base: var(--lilac-light-3);
 --surface-info-weak: var(--lilac-light-2);
 --surface-info-strong: var(--lilac-light-9);
---surface-diff-hidden-base: var(--blue-light-3);
 --surface-diff-skip-base: var(--smoke-light-2);
+--surface-diff-hidden-base: var(--blue-light-3);
 --surface-diff-unchanged-base: #FFFFFF00;
 --surface-diff-hidden-weak: var(--blue-light-2);
 --surface-diff-hidden-weaker: var(--blue-light-1);
@@ -74,19 +75,22 @@
 --text-on-brand-base: var(--smoke-light-alpha-11);
 --text-on-interactive-base: var(--smoke-light-1);
 --text-on-interactive-weak: var(--smoke-dark-alpha-11);
---text-on-success-base: var(--smoke-dark-alpha-11);
+--text-on-success-base: var(--apple-light-10);
+--text-on-critical-base: var(--ember-light-10);
+--text-on-critical-weak: var(--ember-light-8);
+--text-on-critical-strong: var(--ember-light-12);
 --text-on-warning-base: var(--smoke-dark-alpha-11);
 --text-on-info-base: var(--smoke-dark-alpha-11);
 --text-diff-add-base: var(--mint-light-11);
---text-diff-delete-base: var(--ember-light-11);
+--text-diff-delete-base: var(--ember-light-10);
 --text-diff-delete-strong: var(--ember-light-12);
 --text-diff-add-strong: var(--mint-light-12);
 --text-on-info-weak: var(--smoke-dark-alpha-9);
 --text-on-info-strong: var(--smoke-dark-alpha-12);
 --text-on-warning-weak: var(--smoke-dark-alpha-9);
 --text-on-warning-strong: var(--smoke-dark-alpha-12);
---text-on-success-weak: var(--smoke-dark-alpha-9);
---text-on-success-strong: var(--smoke-dark-alpha-12);
+--text-on-success-weak: var(--apple-light-6);
+--text-on-success-strong: var(--apple-light-12);
 --text-on-brand-weak: var(--smoke-light-alpha-9);
 --text-on-brand-weaker: var(--smoke-light-alpha-8);
 --text-on-brand-strong: var(--smoke-light-alpha-12);
@@ -134,19 +138,19 @@
 --icon-selected: var(--smoke-light-12);
 --icon-disabled: var(--smoke-light-8);
 --icon-focus: var(--smoke-light-12);
---icon-weak-base: var(--smoke-light-7);
 --icon-invert-base: #FFFFFF;
+--icon-weak-base: var(--smoke-light-7);
 --icon-weak-hover: var(--smoke-light-8);
 --icon-weak-active: var(--smoke-light-9);
 --icon-weak-selected: var(--smoke-light-10);
 --icon-weak-disabled: var(--smoke-light-6);
 --icon-weak-focus: var(--smoke-light-9);
 --icon-strong-base: var(--smoke-light-12);
---icon-strong-hover: var(--smoke-light-12);
---icon-strong-active: var(--smoke-light-12);
---icon-strong-selected: var(--smoke-light-12);
+--icon-strong-hover: #151313;
+--icon-strong-active: #020202;
+--icon-strong-selected: #020202;
 --icon-strong-disabled: var(--smoke-light-8);
---icon-strong-focus: var(--smoke-light-12);
+--icon-strong-focus: #020202;
 --icon-brand-base: var(--smoke-light-12);
 --icon-interactive-base: var(--cobalt-light-9);
 --icon-success-base: var(--apple-light-7);
@@ -155,9 +159,9 @@
 --icon-warning-base: var(--amber-light-7);
 --icon-warning-hover: var(--amber-light-8);
 --icon-warning-active: var(--amber-light-11);
---icon-critical-base: var(--ember-light-7);
---icon-critical-hover: var(--ember-light-8);
---icon-critical-active: var(--ember-light-11);
+--icon-critical-base: var(--ember-light-10);
+--icon-critical-hover: var(--ember-light-11);
+--icon-critical-active: var(--ember-light-12);
 --icon-info-base: var(--lilac-light-7);
 --icon-info-hover: var(--lilac-light-8);
 --icon-info-active: var(--lilac-light-11);
@@ -184,9 +188,8 @@
 --icon-diff-add-base: var(--mint-light-11);
 --icon-diff-add-hover: var(--mint-light-12);
 --icon-diff-add-active: var(--mint-light-12);
---icon-diff-delete-base: var(--ember-light-9);
---icon-diff-delete-hover: var(--ember-light-10);
---icon-diff-delete-active: var(--ember-light-11);
+--icon-diff-delete-base: var(--ember-light-10);
+--icon-diff-delete-hover: var(--ember-light-11);
 --syntax-comment: #8A8A8A;
 --syntax-string: #D68C27;
 --syntax-keyword: #3B7DD8;
@@ -222,3 +225,5 @@
 --border-weaker-selected: var(--cobalt-light-alpha-4);
 --border-weaker-disabled: var(--smoke-light-alpha-2);
 --border-weaker-focus: var(--smoke-light-alpha-6);
+--button-ghost-hover: var(--smoke-light-alpha-2);
+--button-ghost-hover2: var(--smoke-light-alpha-3);

+ 5 - 5
packages/ui/src/components/message-part.css

@@ -33,7 +33,7 @@
   gap: 8px;
 
   [data-slot="tool-error-icon"] {
-    color: var(--icon-critical-active);
+    color: var(--icon-critical-base);
     margin-top: 4px;
   }
 
@@ -50,13 +50,13 @@
     font-weight: var(--font-weight-medium);
     line-height: var(--line-height-large);
     letter-spacing: var(--letter-spacing-normal);
-    color: var(--ember-light-11);
-    text-transform: capitalize;
+    color: var(--text-on-critical-base);
     white-space: nowrap;
   }
 
-  /* [data-slot="tool-error-message"] { */
-  /* } */
+  [data-slot="tool-error-message"] {
+    color: var(--text-on-critical-weak);
+  }
 }
 
 [data-component="tool-output"] {

+ 1 - 1
packages/ui/src/components/message-part.tsx

@@ -153,7 +153,7 @@ PART_MAPPING["tool"] = function ToolPartDisplay(props) {
                 <div data-component="tool-error">
                   <Icon name="circle-ban-sign" size="small" data-slot="tool-error-icon" />
                   <Switch>
-                    <Match when={title}>
+                    <Match when={title && title.length < 30}>
                       <div data-slot="tool-error-content">
                         <div data-slot="tool-error-title">{title}</div>
                         <span data-slot="tool-error-message">{rest.join(": ")}</span>

+ 9 - 4
packages/ui/src/styles/tailwind/colors.css

@@ -7,8 +7,8 @@
   --color-background-weak: var(--background-weak);
   --color-background-strong: var(--background-strong);
   --color-background-stronger: var(--background-stronger);
-  --color-base: var(--base);
   --color-surface-base: var(--surface-base);
+  --color-base: var(--base);
   --color-surface-base-hover: var(--surface-base-hover);
   --color-surface-base-active: var(--surface-base-active);
   --color-surface-base-interactive-active: var(--surface-base-interactive-active);
@@ -22,6 +22,7 @@
   --color-surface-float-base: var(--surface-float-base);
   --color-surface-float-base-hover: var(--surface-float-base-hover);
   --color-surface-raised-base-hover: var(--surface-raised-base-hover);
+  --color-surface-raised-base-active: var(--surface-raised-base-active);
   --color-surface-raised-strong: var(--surface-raised-strong);
   --color-surface-raised-strong-hover: var(--surface-raised-strong-hover);
   --color-surface-raised-stronger: var(--surface-raised-stronger);
@@ -48,8 +49,8 @@
   --color-surface-info-base: var(--surface-info-base);
   --color-surface-info-weak: var(--surface-info-weak);
   --color-surface-info-strong: var(--surface-info-strong);
-  --color-surface-diff-hidden-base: var(--surface-diff-hidden-base);
   --color-surface-diff-skip-base: var(--surface-diff-skip-base);
+  --color-surface-diff-hidden-base: var(--surface-diff-hidden-base);
   --color-surface-diff-unchanged-base: var(--surface-diff-unchanged-base);
   --color-surface-diff-hidden-weak: var(--surface-diff-hidden-weak);
   --color-surface-diff-hidden-weaker: var(--surface-diff-hidden-weaker);
@@ -80,6 +81,9 @@
   --color-text-on-interactive-base: var(--text-on-interactive-base);
   --color-text-on-interactive-weak: var(--text-on-interactive-weak);
   --color-text-on-success-base: var(--text-on-success-base);
+  --color-text-on-critical-base: var(--text-on-critical-base);
+  --color-text-on-critical-weak: var(--text-on-critical-weak);
+  --color-text-on-critical-strong: var(--text-on-critical-strong);
   --color-text-on-warning-base: var(--text-on-warning-base);
   --color-text-on-info-base: var(--text-on-info-base);
   --color-text-diff-add-base: var(--text-diff-add-base);
@@ -139,8 +143,8 @@
   --color-icon-selected: var(--icon-selected);
   --color-icon-disabled: var(--icon-disabled);
   --color-icon-focus: var(--icon-focus);
-  --color-icon-weak-base: var(--icon-weak-base);
   --color-icon-invert-base: var(--icon-invert-base);
+  --color-icon-weak-base: var(--icon-weak-base);
   --color-icon-weak-hover: var(--icon-weak-hover);
   --color-icon-weak-active: var(--icon-weak-active);
   --color-icon-weak-selected: var(--icon-weak-selected);
@@ -191,7 +195,6 @@
   --color-icon-diff-add-active: var(--icon-diff-add-active);
   --color-icon-diff-delete-base: var(--icon-diff-delete-base);
   --color-icon-diff-delete-hover: var(--icon-diff-delete-hover);
-  --color-icon-diff-delete-active: var(--icon-diff-delete-active);
   --color-syntax-comment: var(--syntax-comment);
   --color-syntax-string: var(--syntax-string);
   --color-syntax-keyword: var(--syntax-keyword);
@@ -227,4 +230,6 @@
   --color-border-weaker-selected: var(--border-weaker-selected);
   --color-border-weaker-disabled: var(--border-weaker-disabled);
   --color-border-weaker-focus: var(--border-weaker-focus);
+  --color-button-ghost-hover: var(--button-ghost-hover);
+  --color-button-ghost-hover2: var(--button-ghost-hover2);
 }

+ 20 - 14
packages/ui/src/styles/theme.css

@@ -114,9 +114,9 @@
   --surface-info-base: var(--lilac-light-3);
   --surface-info-weak: var(--lilac-light-2);
   --surface-info-strong: var(--lilac-light-9);
-  --surface-diff-unchanged-base: #ffffff00;
   --surface-diff-skip-base: var(--smoke-light-2);
   --surface-diff-hidden-base: var(--blue-light-3);
+  --surface-diff-unchanged-base: #ffffff00;
   --surface-diff-hidden-weak: var(--blue-light-2);
   --surface-diff-hidden-weaker: var(--blue-light-1);
   --surface-diff-hidden-strong: var(--blue-light-5);
@@ -145,7 +145,10 @@
   --text-on-brand-base: var(--smoke-light-alpha-11);
   --text-on-interactive-base: var(--smoke-light-1);
   --text-on-interactive-weak: var(--smoke-dark-alpha-11);
-  --text-on-success-base: var(--smoke-dark-alpha-11);
+  --text-on-success-base: var(--apple-light-10);
+  --text-on-critical-base: var(--ember-light-10);
+  --text-on-critical-weak: var(--ember-light-8);
+  --text-on-critical-strong: var(--ember-light-12);
   --text-on-warning-base: var(--smoke-dark-alpha-11);
   --text-on-info-base: var(--smoke-dark-alpha-11);
   --text-diff-add-base: var(--mint-light-11);
@@ -156,8 +159,8 @@
   --text-on-info-strong: var(--smoke-dark-alpha-12);
   --text-on-warning-weak: var(--smoke-dark-alpha-9);
   --text-on-warning-strong: var(--smoke-dark-alpha-12);
-  --text-on-success-weak: var(--smoke-dark-alpha-9);
-  --text-on-success-strong: var(--smoke-dark-alpha-12);
+  --text-on-success-weak: var(--apple-light-6);
+  --text-on-success-strong: var(--apple-light-12);
   --text-on-brand-weak: var(--smoke-light-alpha-9);
   --text-on-brand-weaker: var(--smoke-light-alpha-8);
   --text-on-brand-strong: var(--smoke-light-alpha-12);
@@ -226,9 +229,9 @@
   --icon-warning-base: var(--amber-light-7);
   --icon-warning-hover: var(--amber-light-8);
   --icon-warning-active: var(--amber-light-11);
-  --icon-critical-base: var(--ember-light-7);
-  --icon-critical-hover: var(--ember-light-8);
-  --icon-critical-active: var(--ember-light-11);
+  --icon-critical-base: var(--ember-light-10);
+  --icon-critical-hover: var(--ember-light-11);
+  --icon-critical-active: var(--ember-light-12);
   --icon-info-base: var(--lilac-light-7);
   --icon-info-hover: var(--lilac-light-8);
   --icon-info-active: var(--lilac-light-11);
@@ -346,9 +349,9 @@
     --surface-info-base: var(--lilac-light-3);
     --surface-info-weak: var(--lilac-light-2);
     --surface-info-strong: var(--lilac-light-9);
-    --surface-diff-unchanged-base: var(--smoke-dark-1);
     --surface-diff-skip-base: var(--smoke-dark-alpha-1);
     --surface-diff-hidden-base: var(--blue-dark-2);
+    --surface-diff-unchanged-base: var(--smoke-dark-1);
     --surface-diff-hidden-weak: var(--blue-dark-1);
     --surface-diff-hidden-weaker: var(--blue-dark-3);
     --surface-diff-hidden-strong: var(--blue-dark-5);
@@ -377,7 +380,10 @@
     --text-on-brand-base: var(--smoke-dark-alpha-11);
     --text-on-interactive-base: var(--smoke-dark-12);
     --text-on-interactive-weak: var(--smoke-dark-alpha-11);
-    --text-on-success-base: var(--smoke-dark-alpha-11);
+    --text-on-success-base: var(--apple-dark-9);
+    --text-on-critical-base: var(--ember-dark-9);
+    --text-on-critical-weak: var(--ember-dark-8);
+    --text-on-critical-strong: var(--ember-dark-12);
     --text-on-warning-base: var(--smoke-dark-alpha-11);
     --text-on-info-base: var(--smoke-dark-alpha-11);
     --text-diff-add-base: var(--mint-dark-11);
@@ -388,8 +394,8 @@
     --text-on-info-strong: var(--smoke-dark-alpha-12);
     --text-on-warning-weak: var(--smoke-dark-alpha-9);
     --text-on-warning-strong: var(--smoke-dark-alpha-12);
-    --text-on-success-weak: var(--smoke-dark-alpha-9);
-    --text-on-success-strong: var(--smoke-dark-alpha-12);
+    --text-on-success-weak: var(--apple-dark-8);
+    --text-on-success-strong: var(--apple-dark-12);
     --text-on-brand-weak: var(--smoke-dark-alpha-9);
     --text-on-brand-weaker: var(--smoke-dark-alpha-8);
     --text-on-brand-strong: var(--smoke-dark-alpha-12);
@@ -458,9 +464,9 @@
     --icon-warning-base: var(--amber-dark-7);
     --icon-warning-hover: var(--amber-dark-8);
     --icon-warning-active: var(--amber-dark-11);
-    --icon-critical-base: var(--ember-dark-7);
-    --icon-critical-hover: var(--ember-dark-8);
-    --icon-critical-active: var(--ember-dark-11);
+    --icon-critical-base: var(--ember-dark-9);
+    --icon-critical-hover: var(--ember-dark-11);
+    --icon-critical-active: var(--ember-dark-12);
     --icon-info-base: var(--lilac-dark-7);
     --icon-info-hover: var(--lilac-dark-8);
     --icon-info-active: var(--lilac-dark-11);