Jay V 8 месяцев назад
Родитель
Сommit
160428d2d4
2 измененных файлов с 113 добавлено и 1 удалено
  1. 96 1
      packages/web/src/components/Share.tsx
  2. 17 0
      packages/web/src/components/share.module.css

+ 96 - 1
packages/web/src/components/Share.tsx

@@ -25,6 +25,7 @@ import {
   IconMagnifyingGlass,
   IconMagnifyingGlass,
   IconWrenchScrewdriver,
   IconWrenchScrewdriver,
   IconDocumentArrowDown,
   IconDocumentArrowDown,
+  IconDocumentMagnifyingGlass,
 } from "./icons"
 } from "./icons"
 import DiffView from "./DiffView"
 import DiffView from "./DiffView"
 import CodeBlock from "./CodeBlock"
 import CodeBlock from "./CodeBlock"
@@ -735,6 +736,100 @@ export default function Share(props: { api: string }) {
                             </div>
                             </div>
                           )}
                           )}
                         </Match>
                         </Match>
+                        {/* Grep tool */}
+                        <Match
+                          when={
+                            msg.role === "assistant" &&
+                            part.type === "tool-invocation" &&
+                            part.toolInvocation.toolName === "opencode_grep" &&
+                            part
+                          }
+                        >
+                          {(part) => {
+                            const metadata = createMemo(() =>
+                              msg.metadata?.tool[part().toolInvocation.toolCallId]
+                            )
+                            const args = part().toolInvocation.args
+                            const result = part().toolInvocation.state === "result" && part().toolInvocation.result
+                            const matches = metadata()?.matches
+
+                            const { pattern, ...rest } = args
+
+                            const duration = createMemo(() =>
+                              DateTime.fromMillis(metadata()?.time.end || 0).diff(
+                                DateTime.fromMillis(metadata()?.time.start || 0),
+                              ).toMillis(),
+                            )
+
+                            return (
+                              <div data-section="part" data-part-type="tool-grep">
+                                <div data-section="decoration">
+                                  <div title="Grep files">
+                                    <IconDocumentMagnifyingGlass
+                                      width={18} height={18}
+                                    />
+                                  </div>
+                                  <div></div>
+                                </div>
+                                <div data-section="content">
+                                  <div data-part-tool-body>
+                                    <span data-part-title data-size="md">
+                                      <span data-element-label>Grep</span>
+                                      <b>&ldquo;{pattern}&rdquo;</b>
+                                    </span>
+                                    <Show when={Object.keys(rest).length > 0}>
+                                      <div data-part-tool-args>
+                                        <For each={flattenToolArgs(rest)}>
+                                          {([name, value]) => (
+                                            <>
+                                              <div></div>
+                                              <div>{name}</div>
+                                              <div>{value}</div>
+                                            </>
+                                          )}
+                                        </For>
+                                      </div>
+                                    </Show>
+                                    <Switch>
+                                      <Match when={matches > 0}>
+                                        <div data-part-tool-result>
+                                          <ResultsButton
+                                            showCopy={matches === 1
+                                              ? "1 match"
+                                              : `${matches} matches`
+                                            }
+                                            hideCopy="Hide matches"
+                                            results={results()}
+                                            onClick={() => showResults((e) => !e)}
+                                          />
+                                          <Show when={results()}>
+                                            <TextPart
+                                              expand
+                                              text={result}
+                                              data-size="sm"
+                                              data-color="dimmed"
+                                            />
+                                          </Show>
+                                        </div>
+                                      </Match>
+                                      <Match when={result}>
+                                        <div data-part-tool-result>
+                                          <TextPart
+                                            expand
+                                            text={result}
+                                            data-size="sm"
+                                            data-color="dimmed"
+                                          />
+                                        </div>
+                                      </Match>
+                                    </Switch>
+                                  </div>
+                                  <ToolFooter time={duration()} />
+                                </div>
+                              </div>
+                            )
+                          }}
+                        </Match>
                         {/* Glob tool */}
                         {/* Glob tool */}
                         <Match
                         <Match
                           when={
                           when={
@@ -762,7 +857,7 @@ export default function Share(props: { api: string }) {
                             return (
                             return (
                               <div data-section="part" data-part-type="tool-glob">
                               <div data-section="part" data-part-type="tool-glob">
                                 <div data-section="decoration">
                                 <div data-section="decoration">
-                                  <div title="List files">
+                                  <div title="Glob files">
                                     <IconMagnifyingGlass width={18} height={18} />
                                     <IconMagnifyingGlass width={18} height={18} />
                                   </div>
                                   </div>
                                   <div></div>
                                   <div></div>

+ 17 - 0
packages/web/src/components/share.module.css

@@ -332,6 +332,23 @@
     }
     }
   }
   }
 
 
+  [data-part-type="tool-grep"] {
+    &:not(:has([data-part-tool-args]))
+      > [data-section="content"] > [data-part-tool-body] {
+      gap: 0.5rem;
+    }
+    [data-part-title] {
+      display: flex;
+      align-items: flex-start;
+      gap: 0.5rem;
+
+      b {
+        color: var(--sl-color-text);
+        word-break: break-all;
+      }
+    }
+  }
+
   [data-part-type="tool-read"] {
   [data-part-type="tool-read"] {
     [data-part-tool-result] {
     [data-part-tool-result] {
       [data-part-tool-code] {
       [data-part-tool-code] {