From 9f91eba2e00c8671165082da89b7eca2cdccf70c Mon Sep 17 00:00:00 2001 From: tiye Date: Wed, 9 Sep 2026 17:07:34 +0800 Subject: [PATCH 1/3] perf: reduce extension startup work --- .github/workflows/upload.yaml | 5 +- extension/content.js | 61 ---------------- extension/get-selected.mjs | 73 ++++++------------- extension/manifest.json | 9 +-- extension/service-worker.js | 51 +++++++++++-- ...202609091100-optimize-extension-startup.md | 11 +++ index.html | 7 +- vite.config.mjs | 2 +- 8 files changed, 82 insertions(+), 137 deletions(-) delete mode 100644 extension/content.js create mode 100644 history/202609091100-optimize-extension-startup.md diff --git a/.github/workflows/upload.yaml b/.github/workflows/upload.yaml index 393a276..6cfca87 100644 --- a/.github/workflows/upload.yaml +++ b/.github/workflows/upload.yaml @@ -74,10 +74,11 @@ jobs: run: | test -f extension/dist/index.html find extension/dist/assets -maxdepth 1 -name '*.css' -print -quit | grep -q . - node --check extension/content.js + find extension/dist/assets -maxdepth 1 -name 'gemini-icon-*.png' -print -quit | grep -q . node --check extension/service-worker.js node --check extension/get-selected.mjs - node -e 'const manifest = require("./extension/manifest.json"); if (manifest.manifest_version !== 3 || manifest.side_panel?.default_path !== "dist/index.html") process.exit(1)' + node -e 'const manifest = require("./extension/manifest.json"); if (manifest.manifest_version !== 3 || manifest.side_panel?.default_path !== "dist/index.html" || manifest.content_scripts || manifest.permissions.includes("tabs")) process.exit(1)' + test -z "$(grep -E 'https?://' extension/dist/index.html)" - name: Select deployment path if: github.event_name == 'push' && github.ref == 'refs/heads/main' diff --git a/extension/content.js b/extension/content.js deleted file mode 100644 index 8d4c506..0000000 --- a/extension/content.js +++ /dev/null @@ -1,61 +0,0 @@ -// Listen for messages -chrome.runtime.onMessage.addListener(function (msg, sender, sendResponse) { - // If the received message has the expected format... - console.log("[Side Message] msg", msg); - if (msg.get === "selected") { - // Call the specified callback, passing - // the web-page's DOM content as argument - sendResponse(getSelectedText()); - return; - } - if (msg.action === "fill-text") { - insertTextAtCursor(String(msg.text || "")); - } -}); - -let getSelectedText = () => { - if (window.getSelection) { - // 标准浏览器 - return window.getSelection().toString(); - } else if (document.selection) { - // IE 浏览器 - return document.selection.createRange().text; - } else { - return "<未获取到内容>"; - } -}; - -console.log("[Side Message] prepared content script"); - -function insertTextAtCursor(text) { - try { - const active = document.activeElement; - if (!active) return; - - if (active.tagName === "INPUT" || active.tagName === "TEXTAREA") { - const input = active; - if (input.readOnly || input.disabled) return; - const start = input.selectionStart ?? input.value.length; - const end = input.selectionEnd ?? input.value.length; - input.setRangeText(text, start, end, "end"); - input.dispatchEvent(new Event("input", { bubbles: true })); - return; - } - - if (active.isContentEditable) { - const sel = window.getSelection(); - if (!sel || sel.rangeCount === 0) return; - const range = sel.getRangeAt(0); - if (!active.contains(range.commonAncestorContainer)) return; - range.deleteContents(); - const textNode = document.createTextNode(text); - range.insertNode(textNode); - range.setStartAfter(textNode); - range.setEndAfter(textNode); - sel.removeAllRanges(); - sel.addRange(range); - } - } catch (err) { - console.error("[Side Message] failed to insert text", err); - } -} diff --git a/extension/get-selected.mjs b/extension/get-selected.mjs index d454c9f..28501a3 100644 --- a/extension/get-selected.mjs +++ b/extension/get-selected.mjs @@ -1,53 +1,24 @@ -export let get_selected = () => { - return new Promise((resolve, reject) => { - if (window.chrome?.runtime?.id == null) { - resolve(null); - return; - } - console.log("calling content script..."); - window.chrome.tabs - .query({ active: true, currentWindow: true }) - .then((x) => { - let activeTab = x[0]; - if (activeTab) { - let id = activeTab.id; - window.chrome.tabs.sendMessage(id, { get: "selected" }, function (response) { - // 接收来自 content.js 的返回数据 - // console.info('Content script returned: ' + response); - resolve(response); - }); - } else { - reject("found not active tab"); - } - }) - .catch((error) => { - console.error("Error", error); - }); - }); -}; - -// setTimeout(()=>{ -// chrome.tabs.query({active: true, currentWindow: true}).then(x => { -// let activeTab = x[0] -// if (activeTab) { -// let id = activeTab.id -// chrome.tabs.sendMessage(id, {get: 'selected'}, function(response) { -// // 接收来自 content.js 的返回数据 -// console.info('Content script returned: ' + response); -// }); +export let get_selected = async () => { + if (window.chrome?.runtime?.id == null) { + return null; + } -// } else { -// throw Error("no active tab found") -// } -// }) -// }, 2000) - -// chrome.scripting.executeScript({ -// target: { tabId: 1201634844 }, -// function: () => { console.log(document.body.innerText) } -// }); + try { + let [activeTab] = await window.chrome.tabs.query({ + active: true, + currentWindow: true, + }); + if (activeTab?.id == null) { + return null; + } -// chrome.tabs.sendMessage(1201634844, {get: 'selected'}, function(response) { -// // 接收来自 content.js 的返回数据 -// console.info('Content script returned: ' + response.message); -// }); + let results = await window.chrome.scripting.executeScript({ + target: { tabId: activeTab.id }, + func: () => window.getSelection?.().toString() ?? "", + }); + return results[0]?.result ?? ""; + } catch (error) { + console.warn("Unable to read selection from the active tab", error); + return null; + } +}; diff --git a/extension/manifest.json b/extension/manifest.json index 609389a..5eec083 100644 --- a/extension/manifest.json +++ b/extension/manifest.json @@ -12,13 +12,6 @@ "icons": { "128": "gemini-icon.png" }, - "content_scripts": [ - { - "matches": [""], - "match_origin_as_fallback": true, - "js": ["content.js"] - } - ], "side_panel": { "default_path": "dist/index.html" }, @@ -29,5 +22,5 @@ } } }, - "permissions": ["sidePanel", "scripting", "activeTab", "tabs", "contextMenus", "storage"] + "permissions": ["sidePanel", "scripting", "activeTab", "contextMenus", "storage"] } diff --git a/extension/service-worker.js b/extension/service-worker.js index 3f1c2a4..bdd0f43 100644 --- a/extension/service-worker.js +++ b/extension/service-worker.js @@ -74,14 +74,8 @@ chrome.contextMenus.onClicked.addListener((item, tab) => { chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { if (message && message.action === "fill-text") { - chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => { - const tab = tabs && tabs[0]; - if (tab && tab.id != null) { - chrome.tabs.sendMessage(tab.id, { - action: "fill-text", - text: message.text || "", - }); - } + fillTextInActiveTab(message.text || "").catch((error) => { + console.warn("[Worker] Unable to fill text in the active tab:", error); }); } @@ -95,6 +89,47 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { } }); +async function fillTextInActiveTab(text) { + const [tab] = await chrome.tabs.query({ active: true, currentWindow: true }); + if (tab?.id == null) { + return; + } + + await chrome.scripting.executeScript({ + target: { tabId: tab.id }, + func: insertTextAtCursor, + args: [String(text)], + }); +} + +function insertTextAtCursor(text) { + const active = document.activeElement; + if (!active) return; + + if (active.tagName === "INPUT" || active.tagName === "TEXTAREA") { + if (active.readOnly || active.disabled) return; + const start = active.selectionStart ?? active.value.length; + const end = active.selectionEnd ?? active.value.length; + active.setRangeText(text, start, end, "end"); + active.dispatchEvent(new Event("input", { bubbles: true })); + return; + } + + if (active.isContentEditable) { + const selection = window.getSelection(); + if (!selection || selection.rangeCount === 0) return; + const range = selection.getRangeAt(0); + if (!active.contains(range.commonAncestorContainer)) return; + range.deleteContents(); + const textNode = document.createTextNode(text); + range.insertNode(textNode); + range.setStartAfter(textNode); + range.setEndAfter(textNode); + selection.removeAllRanges(); + selection.addRange(range); + } +} + // ========================================================================= // Page Translation // ========================================================================= diff --git a/history/202609091100-optimize-extension-startup.md b/history/202609091100-optimize-extension-startup.md new file mode 100644 index 0000000..92c0dc5 --- /dev/null +++ b/history/202609091100-optimize-extension-startup.md @@ -0,0 +1,11 @@ +# Optimize extension startup / 优化扩展启动 + +- Minify production bundles with Vite's Oxc minifier to reduce side-panel parsing work. +- Replace the remote favicon and unused web-app manifest request with the packaged extension icon. +- Replace the `` startup content script with on-demand `chrome.scripting.executeScript` calls authorized by the existing `activeTab` permission. +- Resolve selection failures to `null` so restricted pages cannot leave side-panel initialization waiting on an unsettled Promise. + +- 使用 Vite 的 Oxc 压缩生产构建,减少侧边栏启动时的解析工作。 +- 使用扩展包内图标替代远程 favicon,并移除未使用的 Web App Manifest 请求。 +- 移除在 `` 页面启动时注入的 content script,改由现有 `activeTab` 权限授权,在读取选区及填写文本时按需执行 `chrome.scripting.executeScript`。 +- 受限页面无法读取选区时返回 `null`,避免未结束的 Promise 让侧边栏初始化持续等待。 diff --git a/index.html b/index.html index 063b0d6..83dd5d4 100644 --- a/index.html +++ b/index.html @@ -2,12 +2,7 @@ Gemini Msg - - + Date: Wed, 9 Sep 2026 17:28:49 +0800 Subject: [PATCH 2/3] fix: build with Calcit 0.14.4 --- .github/workflows/upload.yaml | 8 ++++---- calcit.cirru | 11 +++++++++-- deps.cirru | 2 +- history/202609091100-optimize-extension-startup.md | 2 ++ package.json | 4 ++-- yarn.lock | 10 +++++----- 6 files changed, 23 insertions(+), 14 deletions(-) diff --git a/.github/workflows/upload.yaml b/.github/workflows/upload.yaml index 6cfca87..d975467 100644 --- a/.github/workflows/upload.yaml +++ b/.github/workflows/upload.yaml @@ -50,22 +50,22 @@ jobs: git diff --exit-code -- calcit.cirru - name: Check Calcit types - run: calcit calcit.cirru --check-only + run: calcit calcit.cirru --compat-types --check-only - name: Check application dynamic methods - run: calcit calcit.cirru analyze dynamic-methods --max 0 --format json + run: calcit calcit.cirru --compat-types analyze dynamic-methods --max 0 --format json - name: Check deprecated Calcit APIs run: calcit calcit.cirru analyze deprecated --summary-only - name: Audit provider dynamic methods - run: calcit calcit.cirru analyze dynamic-methods --deps --format json + run: calcit calcit.cirru --compat-types analyze dynamic-methods --deps --format json - name: Check Calcit quality baseline run: calcit calcit.cirru analyze quality --baseline config/calcit-quality.cirru - name: Run Calcit regression tests - run: calcit calcit.cirru test --summary-only --format json + run: calcit calcit.cirru --compat-types test --summary-only --format json - name: Build extension package run: yarn build diff --git a/calcit.cirru b/calcit.cirru index acb6a15..71e0052 100644 --- a/calcit.cirru +++ b/calcit.cirru @@ -83,6 +83,7 @@ :code $ quote defn call-anthropic-msg! (cursor state prompt-text model thinking? d!) hint-fn $ {} (:async true) + :args $ [] 'List 'app.schema/ChatState 'String 'String 'Bool 'Dynamic let abort $ deref *abort-control when (js-present-dynamic? abort) @@ -275,6 +276,7 @@ :code $ quote defn call-genai-msg! (variant cursor state prompt-text search? think? d! *text *thinking-text) hint-fn $ {} (:async true) + :args $ [] 'Tag 'List 'app.schema/ChatState 'String 'Bool 'Bool 'Dynamic 'Ref 'Ref if (= false @*gen-ai-new) let mod $ js-await (js/import |@google/genai) @@ -434,6 +436,7 @@ :code $ quote defn call-openrouter! (cursor state prompt-text variant thinking? d! *text) hint-fn $ {} (:async true) + :args $ [] 'List 'app.schema/ChatState 'String 'String 'Bool 'Dynamic 'Ref if (= false @*openai) let mod $ js-await (js/import |openai) @@ -933,7 +936,7 @@ if dev? $ comp-inspect |Store app-store nil :examples $ [] :schema $ :: 'Fn - {} (:return 'Dynamic) + {} (:return 'respo.schema/Component) :args $ [] (:: 'Map 'Tag 'Dynamic) :features $ #{} :js-ffi 'comp-fill $ %{} 'CodeEntry (:doc |) @@ -1921,6 +1924,7 @@ :code $ quote defn submit-message! (cursor state prompt-text search? think? model d!) hint-fn $ {} (:async true) + :args $ [] 'List 'app.schema/ChatState 'String 'Bool 'Bool 'Tag 'Dynamic let state1 $ unsafe-coerce assoc state :messages $ append-user-message (:messages state) prompt-text @@ -2276,7 +2280,10 @@ , t_start , |ms :examples $ [] - :schema $ :: 'Dynamic + :schema $ :: 'Fn + {} (:return 'Unit) + :args $ [] + :features $ #{} :js-ffi 'sync-gemini-key! $ %{} 'CodeEntry (:doc |) :code $ quote defn sync-gemini-key! () $ when config/chrome-extension? diff --git a/deps.cirru b/deps.cirru index ad776cb..fa10554 100644 --- a/deps.cirru +++ b/deps.cirru @@ -1,5 +1,5 @@ -{} (:calcit-version |0.13.77) +{} (:calcit-version |0.14.4) :version |0.0.6 :dependencies $ {} (|Respo/alerts.calcit |0.10.30) |Respo/reel.calcit |0.6.19 diff --git a/history/202609091100-optimize-extension-startup.md b/history/202609091100-optimize-extension-startup.md index 92c0dc5..39f9dfc 100644 --- a/history/202609091100-optimize-extension-startup.md +++ b/history/202609091100-optimize-extension-startup.md @@ -4,8 +4,10 @@ - Replace the remote favicon and unused web-app manifest request with the packaged extension icon. - Replace the `` startup content script with on-demand `chrome.scripting.executeScript` calls authorized by the existing `activeTab` permission. - Resolve selection failures to `null` so restricted pages cannot leave side-panel initialization waiting on an unsettled Promise. +- Upgrade the project toolchain to Calcit and `@calcit/procs` 0.14.4, add explicit async-boundary type hints, and use the compiler's compatibility mode for the remaining Respo `Dynamic` boundaries so `yarn build` works without a local downgrade. - 使用 Vite 的 Oxc 压缩生产构建,减少侧边栏启动时的解析工作。 - 使用扩展包内图标替代远程 favicon,并移除未使用的 Web App Manifest 请求。 - 移除在 `` 页面启动时注入的 content script,改由现有 `activeTab` 权限授权,在读取选区及填写文本时按需执行 `chrome.scripting.executeScript`。 - 受限页面无法读取选区时返回 `null`,避免未结束的 Promise 让侧边栏初始化持续等待。 +- 将项目工具链升级到 Calcit 与 `@calcit/procs` 0.14.4,为异步边界补充显式类型提示,并对仍由 Respo 使用的 `Dynamic` 边界启用编译器兼容模式,使 `yarn build` 无需本地降级即可通过。 diff --git a/package.json b/package.json index 0bf387b..d892a19 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "dependencies": { - "@calcit/procs": "0.13.77", + "@calcit/procs": "0.14.4", "@google/genai": "^2.20.0", "@tiye/main-fonts": "0.0.1", "axios": "^1.15.0", @@ -15,7 +15,7 @@ "vite": "8.2.2" }, "scripts": { - "build": "rm -rfv dist && calcit calcit.cirru js && yarn vite build --base ./ && rm -rfv extension/dist && cp -vr dist extension/" + "build": "rm -rfv dist && calcit calcit.cirru --compat-types js && yarn vite build --base ./ && rm -rfv extension/dist && cp -vr dist extension/" }, "version": "0.0.6", "packageManager": "yarn@4.12.0" diff --git a/yarn.lock b/yarn.lock index 103b5d4..cf05f20 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5,14 +5,14 @@ __metadata: version: 8 cacheKey: 10c0 -"@calcit/procs@npm:0.13.77": - version: 0.13.77 - resolution: "@calcit/procs@npm:0.13.77" +"@calcit/procs@npm:0.14.4": + version: 0.14.4 + resolution: "@calcit/procs@npm:0.14.4" dependencies: "@calcit/ternary-tree": "npm:0.0.26" "@cirru/parser.ts": "npm:^0.0.9" "@cirru/writer.ts": "npm:^0.1.9" - checksum: 10c0/7f0d79ad9e7963728518c3754174136d7c2e906c7177785d633f622300be11b84a8f9ae659c5b93c9fb8f7d47e4fffba773bbe90a30a0f53fc3d1258ab850851 + checksum: 10c0/50b8e0cb0f65eab75dffdbf2624ed5b02610a75546f04d53d2ee7adaa81dceb1676b268a76112a715972a0fe52faacf2ffd953042fb86c673e749f214b73e8f2 languageName: node linkType: hard @@ -1527,7 +1527,7 @@ __metadata: version: 0.0.0-use.local resolution: "root-workspace-0b6124@workspace:." dependencies: - "@calcit/procs": "npm:0.13.77" + "@calcit/procs": "npm:0.14.4" "@google/genai": "npm:^2.20.0" "@tiye/main-fonts": "npm:0.0.1" axios: "npm:^1.15.0" From 0033f8ca6e04bf4b694865715ceac46adaa86fe0 Mon Sep 17 00:00:00 2001 From: tiye Date: Wed, 9 Sep 2026 17:50:46 +0800 Subject: [PATCH 3/3] perf: defer provider and icon code --- .github/workflows/upload.yaml | 3 +++ calcit.cirru | 26 ++++++++++++++----- deps.cirru | 1 - ...202609091100-optimize-extension-startup.md | 2 ++ package.json | 1 - yarn.lock | 25 ------------------ 6 files changed, 25 insertions(+), 33 deletions(-) diff --git a/.github/workflows/upload.yaml b/.github/workflows/upload.yaml index d975467..5da8a6b 100644 --- a/.github/workflows/upload.yaml +++ b/.github/workflows/upload.yaml @@ -75,10 +75,13 @@ jobs: test -f extension/dist/index.html find extension/dist/assets -maxdepth 1 -name '*.css' -print -quit | grep -q . find extension/dist/assets -maxdepth 1 -name 'gemini-icon-*.png' -print -quit | grep -q . + find extension/dist/assets -maxdepth 1 -name 'axios-*.js' -print -quit | grep -q . node --check extension/service-worker.js node --check extension/get-selected.mjs node -e 'const manifest = require("./extension/manifest.json"); if (manifest.manifest_version !== 3 || manifest.side_panel?.default_path !== "dist/index.html" || manifest.content_scripts || manifest.permissions.includes("tabs")) process.exit(1)' test -z "$(grep -E 'https?://' extension/dist/index.html)" + test -z "$(grep -E 'axios-' extension/dist/index.html)" + test -z "$(grep -R 'feathericons.com' extension/dist/assets || true)" - name: Select deployment path if: github.event_name == 'push' && github.ref == 'refs/heads/main' diff --git a/calcit.cirru b/calcit.cirru index 71e0052..42deb26 100644 --- a/calcit.cirru +++ b/calcit.cirru @@ -3,7 +3,7 @@ :entries $ {} :default $ {} (:description |) (:init-fn 'app.main/main!) (:mode :js) (:reload-fn 'app.main/reload!) :feature-policy $ {} - :modules $ [] |respo.calcit/ |respo-ui.calcit/ |reel.calcit/ |respo-markdown.calcit/ |alerts.calcit/ |respo-feather.calcit/ + :modules $ [] |respo.calcit/ |respo-ui.calcit/ |reel.calcit/ |respo-markdown.calcit/ |alerts.calcit/ :type-slots $ {} :files $ {} 'app.comp.container $ %{} 'FileEntry @@ -92,9 +92,12 @@ do (js/console.warn |Aborting-prev) (.!abort abort-controller) d! $ :: :change-model let + axios $ unsafe-coerce + .-default $ js-await (js/import |axios) + , 'Dynamic selected $ let selected0 $ js-await (get-selected) - if (js-present? selected0) (unsafe-coerce selected0 'String) "|<未找到内容>" + if (js-present? selected0) (stream-text selected0) "|<未找到内容>" content $ .replace prompt-text |{{selected}} selected messages0 $ append-user-message (:messages state) content messages1 $ upsert-assistant-message messages0 | | @@ -804,7 +807,7 @@ :on-click $ fn (e d!) (.show sessions-plugin d!) &unit div {} $ :class-name style-history-button - comp-i |clock + comp-local-icon :clock 14 =< 4 nil if > (count sessions) 0 @@ -948,9 +951,22 @@ when chrome-extension? $ js/chrome.runtime.sendMessage js-object (:action |fill-text) (:text text) , &unit - comp-i :send 12 :currentColor + comp-local-icon :send 12 :examples $ [] :schema $ :: 'Dynamic + 'comp-local-icon $ %{} 'CodeEntry (:doc |) + :code $ quote + defcomp comp-local-icon (icon size) + span $ {} (:aria-hidden |true) + :style $ {} (:display :inline-flex) (:align-items :center) (:justify-content :center) + :width $ str size |px + :height $ str size |px + :line-height |0 + :innerHTML $ case-default icon | (:clock "|") (:send "|") + :examples $ [] + :schema $ :: 'Fn + {} (:return 'respo.schema/Component) + :args $ [] 'Tag 'Number 'comp-message-box $ %{} 'CodeEntry (:doc |) :code $ quote defcomp comp-message-box (states picker-el on-submit model) @@ -2037,13 +2053,11 @@ respo.comp.inspect :refer $ comp-inspect reel.comp.reel :refer $ comp-reel app.config :refer $ dev? chrome-extension? site - |axios :default axios respo-md.comp.md :refer $ comp-md-block style-code-block respo-ui.comp :refer $ comp-copy style-close |../extension/get-selected :refer $ get-selected |../lib/db :refer $ db-get db-set |../lib/image :refer $ base64ToBlob - feather.core :refer $ comp-i respo-alerts.core :refer $ [] use-modal-menu use-prompt use-drawer use-alert respo-ui.util :refer $ tab-echo! app.schema :refer $ Store ChatState ChatSession ChatMessage MessageBoxState store diff --git a/deps.cirru b/deps.cirru index fa10554..a17fb35 100644 --- a/deps.cirru +++ b/deps.cirru @@ -3,7 +3,6 @@ :version |0.0.6 :dependencies $ {} (|Respo/alerts.calcit |0.10.30) |Respo/reel.calcit |0.6.19 - |Respo/respo-feather.calcit |0.4.11 |Respo/respo-markdown.calcit |0.4.33 |Respo/respo-ui.calcit |0.7.19 |Respo/respo.calcit |0.16.95 diff --git a/history/202609091100-optimize-extension-startup.md b/history/202609091100-optimize-extension-startup.md index 39f9dfc..cfa3df3 100644 --- a/history/202609091100-optimize-extension-startup.md +++ b/history/202609091100-optimize-extension-startup.md @@ -5,9 +5,11 @@ - Replace the `` startup content script with on-demand `chrome.scripting.executeScript` calls authorized by the existing `activeTab` permission. - Resolve selection failures to `null` so restricted pages cannot leave side-panel initialization waiting on an unsettled Promise. - Upgrade the project toolchain to Calcit and `@calcit/procs` 0.14.4, add explicit async-boundary type hints, and use the compiler's compatibility mode for the remaining Respo `Dynamic` boundaries so `yarn build` works without a local downgrade. +- Replace the full Feather icon dependency with two local inline SVGs, and dynamically import Axios only when the Anthropic provider is used. - 使用 Vite 的 Oxc 压缩生产构建,减少侧边栏启动时的解析工作。 - 使用扩展包内图标替代远程 favicon,并移除未使用的 Web App Manifest 请求。 - 移除在 `` 页面启动时注入的 content script,改由现有 `activeTab` 权限授权,在读取选区及填写文本时按需执行 `chrome.scripting.executeScript`。 - 受限页面无法读取选区时返回 `null`,避免未结束的 Promise 让侧边栏初始化持续等待。 - 将项目工具链升级到 Calcit 与 `@calcit/procs` 0.14.4,为异步边界补充显式类型提示,并对仍由 Respo 使用的 `Dynamic` 边界启用编译器兼容模式,使 `yarn build` 无需本地降级即可通过。 +- 使用两个本地内联 SVG 替代完整 Feather 图标依赖,并仅在调用 Anthropic 服务时动态加载 Axios。 diff --git a/package.json b/package.json index d892a19..a17e03b 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,6 @@ "cirru-color": "^0.2.4", "copy-text-to-clipboard": "^3.2.2", "dayjs": "^1.11.18", - "feather-icons": "^4.29.2", "openai": "^6.34.0" }, "devDependencies": { diff --git a/yarn.lock b/yarn.lock index cf05f20..bd7edbf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -435,13 +435,6 @@ __metadata: languageName: node linkType: hard -"classnames@npm:^2.2.5": - version: 2.5.1 - resolution: "classnames@npm:2.5.1" - checksum: 10c0/afff4f77e62cea2d79c39962980bf316bacb0d7c49e13a21adaadb9221e1c6b9d3cdb829d8bb1b23c406f4e740507f37e1dcf506f7e3b7113d17c5bab787aa69 - languageName: node - linkType: hard - "combined-stream@npm:^1.0.8": version: 1.0.8 resolution: "combined-stream@npm:1.0.8" @@ -458,13 +451,6 @@ __metadata: languageName: node linkType: hard -"core-js@npm:^3.1.3": - version: 3.47.0 - resolution: "core-js@npm:3.47.0" - checksum: 10c0/9b1a7088b7c660c7b8f1d4c90bb1816a8d5352ebdcb7bc742e3a0e4eb803316b5aa17bacb8769522342196351a5430178f46914644f2bfdb94ce0ced3c7fd523 - languageName: node - linkType: hard - "data-uri-to-buffer@npm:^4.0.0": version: 4.0.1 resolution: "data-uri-to-buffer@npm:4.0.1" @@ -636,16 +622,6 @@ __metadata: languageName: node linkType: hard -"feather-icons@npm:^4.29.2": - version: 4.29.2 - resolution: "feather-icons@npm:4.29.2" - dependencies: - classnames: "npm:^2.2.5" - core-js: "npm:^3.1.3" - checksum: 10c0/a23f8fbb6e96c901290308bb96267660ddd32c367074411e6a641c030448eff8041072c46e82cbf3bb3c4b2440df107e8defed09ff068e55117db6b867ca7b32 - languageName: node - linkType: hard - "fetch-blob@npm:^3.1.2, fetch-blob@npm:^3.1.4": version: 3.2.0 resolution: "fetch-blob@npm:3.2.0" @@ -1535,7 +1511,6 @@ __metadata: cirru-color: "npm:^0.2.4" copy-text-to-clipboard: "npm:^3.2.2" dayjs: "npm:^1.11.18" - feather-icons: "npm:^4.29.2" openai: "npm:^6.34.0" vite: "npm:8.2.2" languageName: unknown