Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@

calcit.cirru -diff linguist-generated
yarn.lock -diff linguist-generated
Comment on lines 1 to 2

Agents.md -diff linguist-generated
llms/*.md -diff linguist-generated
llms/*.md -diff linguist-generated

history/*.md -diff linguist-generated
4 changes: 1 addition & 3 deletions .github/workflows/upload.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ jobs:
corepack prepare yarn@4.12.0 --activate
yarn --version

- uses: calcit-lang/setup-cr@0.0.8
with:
version: 0.12.14
- uses: calcit-lang/setup-cr@0.0.9

- name: "compiles to js"
run: >
Expand Down
1,314 changes: 847 additions & 467 deletions compact.cirru → calcit.cirru

Large diffs are not rendered by default.

16 changes: 8 additions & 8 deletions deps.cirru
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@

{} (:calcit-version |0.12.35)
{} (:calcit-version |0.12.49)
:dependencies $ {} (|Memkits/genai.calcit |0.0.3)
|Respo/alerts.calcit |0.10.10
|Respo/reel.calcit |main
|Respo/respo-feather.calcit |main
|Respo/respo-markdown.calcit |0.4.13
|Respo/respo-ui.calcit |0.6.4
|Respo/respo.calcit |0.16.45
|calcit-lang/memof |0.0.23
|Respo/alerts.calcit |0.10.13
|Respo/reel.calcit |0.6.4
|Respo/respo-feather.calcit |0.4.1
|Respo/respo-markdown.calcit |0.4.14
|Respo/respo-ui.calcit |0.6.5
|Respo/respo.calcit |0.16.48
|calcit-lang/memof |0.0.24
2 changes: 1 addition & 1 deletion extension/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,5 @@
}
}
},
"permissions": ["sidePanel", "scripting", "activeTab", "tabs", "contextMenus"]
"permissions": ["sidePanel", "scripting", "activeTab", "tabs", "contextMenus", "storage"]
}
86 changes: 86 additions & 0 deletions extension/service-worker.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
let sidepanelOpen = false;
let pendingMessage = null;
let deepseekApiKey = null;

let sendToSidepanel = (message, tabId) => {
console.log("[Worker] Sending message to sidepanel:", message.action);
Expand Down Expand Up @@ -46,10 +47,22 @@ chrome.runtime.onInstalled.addListener(() => {
parentId: "msg-gemini-root",
});
});

// Page-level translation context menu (separate from selection menu)
chrome.contextMenus.create({
id: "msg-gemini-translate-page",
title: "Translate Page (EN→ZH)",
type: "normal",
contexts: ["page"],
});
});

chrome.contextMenus.onClicked.addListener((item, tab) => {
let content = item.selectionText;
if (item.menuItemId === "msg-gemini-translate-page") {
injectTranslateScript(tab);
return;
}
if (item.menuItemId === "msg-gemini-translate") {
sendToSidepanel({ action: "menu-translate", content }, tab.id);
} else if (item.menuItemId === "msg-gemini-custom") {
Expand All @@ -71,8 +84,81 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
}
});
}

// Receive DeepSeek API key from sidepanel
if (message && message.action === "sync-deepseek-key") {
deepseekApiKey = message.key || null;
if (message.key) {
chrome.storage.local.set({ deepseekKey: message.key });
}
console.log("[Worker] DeepSeek API key synced:", deepseekApiKey ? "present" : "cleared");
}
});

// =========================================================================
// Page Translation
// =========================================================================

async function injectTranslateScript(tab) {
// Always read from chrome.storage.local as primary source
try {
const stored = await chrome.storage.local.get("deepseekKey");
if (stored && stored.deepseekKey) {
deepseekApiKey = stored.deepseekKey;
console.log("[Worker] DeepSeek API key loaded from storage");
}
} catch (e) {
console.error("[Worker] Failed to read from storage:", e);
}

// If still no key, prompt once and persist
if (!deepseekApiKey) {
console.log("[Worker] No key found, asking user once...");
try {
const results = await chrome.scripting.executeScript({
target: { tabId: tab.id },
func: () => {
return window.prompt(
"Enter your DeepSeek API key (from platform.deepseek.com):"
);
},
});
if (results && results[0] && results[0].result) {
deepseekApiKey = results[0].result;
await chrome.storage.local.set({ deepseekKey: deepseekApiKey });
console.log("[Worker] DeepSeek API key saved to storage");
}
} catch (e) {
console.error("[Worker] Prompt failed:", e);
}
}

if (!deepseekApiKey) {
console.error("[Worker] No DeepSeek API key, cannot translate");
return;
}

try {
// Inject key and translation script into the page
await chrome.scripting.executeScript({
target: { tabId: tab.id },
func: (key) => {
window.__TRANSLATE_API_KEY__ = key;
},
args: [deepseekApiKey],
});

await chrome.scripting.executeScript({
target: { tabId: tab.id },
files: ["translate-page.js"],
});

console.log("[Worker] Translation script injected successfully");
} catch (err) {
console.error("[Worker] Failed to inject translate script:", err);
}
}

// https://stackoverflow.com/a/77106777/883571
chrome.runtime.onConnect.addListener(function (port) {
if (port.name === "mySidepanel") {
Expand Down
Loading
Loading