瀏覽代碼

release: v0.0.8
- 添加页面智能总结功能
- 集成 Readability.js 提取正文
- 优化总结提示词模板
- 改进页面分析能力

alibct 7 月之前
父節點
當前提交
93a93d4144
共有 8 個文件被更改,包括 200 次插入20 次删除
  1. 17 0
      CHANGELOG.md
  2. 9 7
      css/chat.css
  3. 27 0
      js/ai-service.js
  4. 29 8
      js/chat-ui.js
  5. 23 0
      js/content.js
  6. 18 0
      js/libs/Readability.js
  7. 72 1
      js/page-analyzer.js
  8. 5 4
      manifest.json

+ 17 - 0
CHANGELOG.md

@@ -1,5 +1,22 @@
 # 更新日志
 
+## [0.0.8] - 2024-03-xx
+
+### 新增
+
+- 添加页面智能总结功能
+  - 集成 Readability.js 提取正文
+  - 优化总结提示词模板
+  - 添加后备提取方案
+  - 完善错误处理机制
+
+### 优化
+
+- 改进页面分析能力
+  - 优化正文提取算法
+  - 添加内容过滤规则
+  - 提升提取准确度
+
 ## [0.0.6] - 2024-03-xx
 
 ### 优化

+ 9 - 7
css/chat.css

@@ -69,13 +69,13 @@
   border-radius: 8px !important;
   padding: 8px 12px !important;
   transition: all 0.3s ease-out !important;
-  will-change: min-height, max-height !important;
-  min-height: 40px !important; /* 设置最小高度 */
-  max-height: 120px !important; /* 设置最大高度 */
+  min-height: 40px !important; /* 设置固定的最小高度 */
+  max-height: 120px !important;
 }
 
 .input-wrapper:focus-within {
   box-shadow: 0 0 0 1px #1a73e8;
+  background: #f0f4f8 !important; /* 保持背景色一致 */
 }
 
 #chat-input {
@@ -86,11 +86,12 @@
   padding: 8px !important;
   font-size: 14px !important;
   line-height: 1.5 !important;
-  min-height: 24px !important; /* 设置最小高度 */
-  max-height: 100px !important; /* 设置最大高度 */
+  min-height: 24px !important; /* 确保最小高度一致 */
+  max-height: 100px !important;
   outline: none !important;
   color: #333 !important;
-  overflow-y: auto !important; /* 允许内容超出时滚动 */
+  overflow-y: auto !important;
+  box-sizing: border-box !important; /* 添加盒模型设置 */
 }
 
 /* 确保输入框placeholder样式一致 */
@@ -760,7 +761,7 @@
 /* 输入框过渡动画 */
 .input-transition {
   transition: height 0.3s ease-out !important;
-  will-change: height !important; /* 优化动画性能 */
+  will-change: height !important;
 }
 
 #chat-input {
@@ -776,4 +777,5 @@
   outline: none !important;
   color: #333 !important;
   overflow-y: auto !important;
+  box-sizing: border-box !important; /* 添加盒模型设置 */
 }

+ 27 - 0
js/ai-service.js

@@ -144,6 +144,33 @@ class AIService {
       this.controller = null;
     }
   }
+
+  /**
+   * 获取页面总结提示词
+   * @param {Object} pageInfo 页面信息
+   * @returns {string} 提示词
+   */
+  getSummaryPrompt(pageInfo) {
+    return `请帮我总结以下网页内容的要点:
+
+页面标题:${pageInfo.title}
+网站:${pageInfo.siteName}
+URL:${pageInfo.url}
+
+主要内容:
+${pageInfo.mainContent}
+
+要求:
+1. 提取3-5个核心要点
+2. 使用简洁清晰的语言
+3. 保持客观中立的语气
+4. 按重要性排序
+5. 如果内容是新闻,需要包含时间、地点、人物等关键信息
+6. 如果内容是教程,需要突出操作步骤和关键提示
+7. 如果内容是产品介绍,需要包含主要特点和优势
+
+请以"以下是对该页面内容的总结:"开头,然后用要点的形式列出主要内容。`;
+  }
 }
 
 // 确保在DOM加载完成后再创建实例

+ 29 - 8
js/chat-ui.js

@@ -21,6 +21,9 @@ class ChatUI {
     // 设置初始高度
     this.input.style.height = "40px";
 
+    // 获取总结按钮
+    this.summarizeButton = document.querySelector(".summarize-button");
+
     // 初始化其他组件
     this.setupEventListeners();
     this.init();
@@ -123,6 +126,13 @@ class ChatUI {
         this.promptPanel.classList.remove("show");
       }
     });
+
+    // 添加总结按钮点击事件
+    if (this.summarizeButton) {
+      this.summarizeButton.addEventListener("click", () => {
+        this.handleSummarize();
+      });
+    }
   }
 
   async handleSend() {
@@ -594,14 +604,25 @@ class ChatUI {
       this.setInputState(true);
       this.loadingDiv = this.createLoadingMessage();
 
-      // 获取页面分析结果
-      const pageContext = window.pageAnalyzer.analyzePage();
+      // 通过postMessage请求页面分析结果
+      const pageInfo = await new Promise((resolve) => {
+        // 创建一次性消息监听器
+        const messageHandler = (event) => {
+          if (event.data.type === "PAGE_ANALYSIS_RESULT") {
+            window.removeEventListener("message", messageHandler);
+            resolve(event.data.pageInfo);
+          }
+        };
+
+        // 添加消息监听
+        window.addEventListener("message", messageHandler);
+
+        // 发送分析请求到父页面
+        window.parent.postMessage({ type: "ANALYZE_PAGE" }, "*");
+      });
 
       // 构建提示词
-      const prompt = `请总结当前页面的主要内容:
-标题:${pageContext.title}
-URL:${pageContext.url}
-主要内容:${pageContext.mainContent}`;
+      const prompt = this.aiService.getSummaryPrompt(pageInfo);
 
       // 发送分析请求
       const response = await this.aiService.sendMessage(prompt);
@@ -613,7 +634,7 @@ URL:${pageContext.url}
       }
 
       await this.addMessage(response, "assistant", true);
-      this.setInputState(false); // 总结完成后自动聚焦输入框
+      this.setInputState(false);
     } catch (error) {
       console.error("Failed to summarize page:", error);
       this.addMessage(
@@ -621,7 +642,7 @@ URL:${pageContext.url}
         "assistant",
         false
       );
-      this.setInputState(false); // 错误后也自动聚焦输入框
+      this.setInputState(false);
     }
   }
 }

+ 23 - 0
js/content.js

@@ -93,6 +93,29 @@ class SidebarManager {
         }
       }
     });
+
+    // 监听来自iframe的消息
+    window.addEventListener("message", (event) => {
+      // 确保消息来自我们的iframe
+      if (
+        event.source ===
+        document.getElementById("paiwise-sidebar")?.contentWindow
+      ) {
+        if (event.data.type === "ANALYZE_PAGE") {
+          // 分析页面并返回结果
+          const pageInfo = window.pageAnalyzer.analyzePage();
+
+          // 发送分析结果回iframe
+          event.source.postMessage(
+            {
+              type: "PAGE_ANALYSIS_RESULT",
+              pageInfo: pageInfo,
+            },
+            "*"
+          );
+        }
+      }
+    });
   }
 
   /**

+ 18 - 0
js/libs/Readability.js

@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2010 Arc90 Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// 从这里复制完整的Readability.js代码
+// https://raw.githubusercontent.com/mozilla/readability/master/Readability.js

+ 72 - 1
js/page-analyzer.js

@@ -1 +1,72 @@
- 
+// 确保类定义在全局作用域
+window.PageAnalyzer = class PageAnalyzer {
+  constructor() {
+    this.readability = null;
+  }
+
+  /**
+   * 分析页面内容
+   * @returns {Object} 页面分析结果
+   */
+  analyzePage() {
+    try {
+      // 检查Readability是否可用
+      if (typeof Readability === "undefined") {
+        console.warn(
+          "Readability not loaded, falling back to basic extraction"
+        );
+        return this.fallbackAnalysis();
+      }
+
+      // 创建文档副本以避免修改原始DOM
+      const documentClone = document.cloneNode(true);
+
+      // 初始化 Readability
+      this.readability = new Readability(documentClone, {
+        debug: false,
+        charThreshold: 20,
+      });
+
+      // 解析页面
+      const article = this.readability.parse();
+
+      return {
+        title: article.title || document.title,
+        url: window.location.href,
+        mainContent: article.textContent || article.excerpt || "",
+        excerpt: article.excerpt || "",
+        siteName: article.siteName || new URL(window.location.href).hostname,
+        wordCount: article.length || 0,
+      };
+    } catch (error) {
+      console.warn("Readability failed, using fallback:", error);
+      return this.fallbackAnalysis();
+    }
+  }
+
+  // 基础提取方法作为后备
+  fallbackAnalysis() {
+    return {
+      title: document.title,
+      url: window.location.href,
+      mainContent: this.extractMainContent(),
+      excerpt: "",
+      siteName: new URL(window.location.href).hostname,
+      wordCount: 0,
+    };
+  }
+
+  // 基础的内容提取方法
+  extractMainContent() {
+    // 移除脚本、样式等
+    const content = document.body.cloneNode(true);
+    content
+      .querySelectorAll("script, style, iframe, nav, header, footer")
+      .forEach((el) => el.remove());
+
+    return content.textContent.trim().replace(/\s+/g, " ");
+  }
+};
+
+// 创建全局实例
+window.pageAnalyzer = new window.PageAnalyzer();

+ 5 - 4
manifest.json

@@ -1,7 +1,7 @@
 {
   "manifest_version": 3,
   "name": "派维斯智能体助手",
-  "version": "0.0.6",
+  "version": "0.0.8",
   "description": "一个辅助用户处理业务流程的智能体助手",
   "author": "Paiwise Team",
   "permissions": [
@@ -37,10 +37,11 @@
       "js": [
         "js/config.js",
         "js/utils.js",
-        "js/page-analyzer.js",
         "js/ai-service.js",
-        "js/chat-ui.js",
-        "js/content.js"
+        "js/libs/Readability.js",
+        "js/page-analyzer.js",
+        "js/content.js",
+        "js/chat-ui.js"
       ]
     }
   ],