first commit

This commit is contained in:
yehongyu
2026-07-20 14:40:17 +08:00
commit 50fd043a2d
55 changed files with 7786 additions and 0 deletions
+58
View File
@@ -0,0 +1,58 @@
/**
* Most of this code is from Zotero team's official Make It Red example[1]
* or the Zotero 7 documentation[2].
* [1] https://github.com/zotero/make-it-red
* [2] https://www.zotero.org/support/dev/zotero_7_for_developers
*/
var chromeHandle;
function install(data, reason) {}
async function startup({ id, version, resourceURI, rootURI }, reason) {
var aomStartup = Components.classes[
"@mozilla.org/addons/addon-manager-startup;1"
].getService(Components.interfaces.amIAddonManagerStartup);
var manifestURI = Services.io.newURI(rootURI + "manifest.json");
chromeHandle = aomStartup.registerChrome(manifestURI, [
["content", "__addonRef__", rootURI + "content/"],
]);
/**
* Global variables for plugin code.
* The `_globalThis` is the global root variable of the plugin sandbox environment
* and all child variables assigned to it is globally accessible.
* See `src/index.ts` for details.
*/
const ctx = { rootURI };
ctx._globalThis = ctx;
Services.scriptloader.loadSubScript(
`${rootURI}/content/scripts/__addonRef__.js`,
ctx,
);
await Zotero.__addonInstance__.hooks.onStartup();
}
async function onMainWindowLoad({ window }, reason) {
await Zotero.__addonInstance__?.hooks.onMainWindowLoad(window);
}
async function onMainWindowUnload({ window }, reason) {
await Zotero.__addonInstance__?.hooks.onMainWindowUnload(window);
}
async function shutdown({ id, version, resourceURI, rootURI }, reason) {
if (reason === APP_SHUTDOWN) {
return;
}
await Zotero.__addonInstance__?.hooks.onShutdown();
if (chromeHandle) {
chromeHandle.destruct();
chromeHandle = null;
}
}
async function uninstall(data, reason) {}
+140
View File
@@ -0,0 +1,140 @@
.chatpapers-root {
display: flex;
flex-direction: column;
gap: 8px;
padding: 8px;
min-height: 320px;
box-sizing: border-box;
font-size: 13px;
}
.chatpapers-header {
display: flex;
flex-direction: column;
gap: 2px;
}
.chatpapers-title {
font-weight: 600;
line-height: 1.3;
}
.chatpapers-meta {
opacity: 0.7;
font-size: 12px;
}
.chatpapers-messages {
flex: 1;
min-height: 180px;
max-height: 420px;
overflow: auto;
border: 1px solid color-mix(in srgb, currentColor 18%, transparent);
border-radius: 8px;
padding: 8px;
display: flex;
flex-direction: column;
gap: 8px;
background: color-mix(in srgb, currentColor 4%, transparent);
}
.chatpapers-bubble {
padding: 8px 10px;
border-radius: 8px;
white-space: pre-wrap;
word-break: break-word;
}
.chatpapers-user {
background: color-mix(in srgb, #3b82f6 18%, transparent);
align-self: flex-end;
max-width: 92%;
}
.chatpapers-assistant {
background: color-mix(in srgb, currentColor 8%, transparent);
align-self: flex-start;
max-width: 96%;
}
.chatpapers-role {
font-size: 11px;
opacity: 0.65;
margin-bottom: 4px;
font-weight: 600;
}
.chatpapers-status {
min-height: 1.2em;
font-size: 12px;
opacity: 0.85;
}
.chatpapers-status[data-kind="warn"] {
color: #b45309;
}
.chatpapers-status[data-kind="error"] {
color: #b91c1c;
}
.chatpapers-toolbar,
.chatpapers-actions {
display: flex;
flex-wrap: wrap;
gap: 6px;
}
.chatpapers-btn {
appearance: none;
border: 1px solid color-mix(in srgb, currentColor 22%, transparent);
background: color-mix(in srgb, currentColor 6%, transparent);
border-radius: 6px;
padding: 4px 10px;
cursor: pointer;
font: inherit;
}
.chatpapers-btn:hover:not(:disabled) {
background: color-mix(in srgb, currentColor 12%, transparent);
}
.chatpapers-btn:disabled {
opacity: 0.5;
cursor: default;
}
.chatpapers-primary {
background: #2563eb;
border-color: #2563eb;
color: #fff;
}
.chatpapers-primary:hover:not(:disabled) {
background: #1d4ed8;
}
.chatpapers-input {
width: 100%;
box-sizing: border-box;
resize: vertical;
min-height: 64px;
border-radius: 8px;
border: 1px solid color-mix(in srgb, currentColor 22%, transparent);
padding: 8px;
font: inherit;
background: transparent;
color: inherit;
}
.chatpapers-loading {
padding: 12px;
opacity: 0.7;
}
.chatpapers-pref-hint {
opacity: 0.8;
font-size: 12px;
margin: 4px 0 10px;
max-width: 52em;
}
+6
View File
@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="context-fill" stroke="context-stroke">
<path d="M3.5 4.5h13a1.5 1.5 0 0 1 1.5 1.5v7a1.5 1.5 0 0 1-1.5 1.5H8l-3.2 2.4a.5.5 0 0 1-.8-.4V14.5H3.5A1.5 1.5 0 0 1 2 13V6a1.5 1.5 0 0 1 1.5-1.5z"/>
<circle cx="7" cy="9.5" r="1"/>
<circle cx="10" cy="9.5" r="1"/>
<circle cx="13" cy="9.5" r="1"/>
</svg>

After

Width:  |  Height:  |  Size: 392 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 677 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 836 B

+127
View File
@@ -0,0 +1,127 @@
<linkset>
<html:link rel="localization" href="__addonRef__-preferences.ftl" />
</linkset>
<groupbox
onload="Zotero.__addonInstance__.hooks.onPrefsEvent('load', { window })"
>
<label><html:h2 data-l10n-id="prefs-section-provider"></html:h2></label>
<html:p id="chatpapers-pref-hint" class="chatpapers-pref-hint"></html:p>
<hbox align="center">
<html:label
for="chatpapers-pref-provider"
data-l10n-id="prefs-provider"
></html:label>
<html:select id="chatpapers-pref-provider" preference="provider">
</html:select>
<button id="chatpapers-pref-reset" data-l10n-id="prefs-reset"></button>
</hbox>
<hbox align="center">
<html:label
for="chatpapers-pref-apiBaseUrl"
data-l10n-id="prefs-base-url"
></html:label>
<html:input
type="text"
id="chatpapers-pref-apiBaseUrl"
preference="apiBaseUrl"
></html:input>
</hbox>
<hbox align="center">
<html:label
for="zotero-prefpane-__addonRef__-apiKey"
data-l10n-id="prefs-api-key"
></html:label>
<html:input
type="password"
id="zotero-prefpane-__addonRef__-apiKey"
preference="apiKey"
></html:input>
</hbox>
<hbox align="center">
<html:label
for="chatpapers-pref-model"
data-l10n-id="prefs-model"
></html:label>
<html:input
type="text"
id="chatpapers-pref-model"
preference="model"
></html:input>
<button
id="chatpapers-pref-refresh-models"
data-l10n-id="prefs-refresh-models"
></button>
</hbox>
</groupbox>
<groupbox>
<label><html:h2 data-l10n-id="prefs-section-generation"></html:h2></label>
<hbox align="center">
<html:label data-l10n-id="prefs-temperature"></html:label>
<html:input
type="text"
preference="temperature"
></html:input>
</hbox>
<hbox align="center">
<html:label data-l10n-id="prefs-max-tokens"></html:label>
<html:input
type="number"
preference="maxTokens"
min="256"
max="128000"
></html:input>
</hbox>
<hbox align="center">
<html:label data-l10n-id="prefs-timeout"></html:label>
<html:input
type="number"
preference="timeoutMs"
min="10000"
step="1000"
></html:input>
</hbox>
<hbox align="center">
<html:label data-l10n-id="prefs-max-context"></html:label>
<html:input
type="number"
preference="maxContextChars"
min="5000"
step="1000"
></html:input>
</hbox>
<hbox align="center">
<html:label data-l10n-id="prefs-answer-language"></html:label>
<html:input type="text" preference="answerLanguage"></html:input>
</hbox>
<checkbox preference="sendMetadata" data-l10n-id="prefs-send-metadata" />
</groupbox>
<groupbox>
<label><html:h2 data-l10n-id="prefs-section-openrouter"></html:h2></label>
<hbox align="center">
<html:label data-l10n-id="prefs-openrouter-referer"></html:label>
<html:input
type="text"
preference="openrouterReferer"
></html:input>
</hbox>
<hbox align="center">
<html:label data-l10n-id="prefs-openrouter-title"></html:label>
<html:input type="text" preference="openrouterTitle"></html:input>
</hbox>
</groupbox>
<groupbox>
<label><html:h2 data-l10n-id="prefs-section-prompts"></html:h2></label>
<html:label data-l10n-id="prefs-system-prompt"></html:label>
<html:textarea preference="systemPrompt" rows="4"></html:textarea>
<html:label data-l10n-id="prefs-summary-prompt"></html:label>
<html:textarea preference="summaryPrompt" rows="4"></html:textarea>
</groupbox>
<html:p data-l10n-id="prefs-privacy" class="chatpapers-pref-hint"></html:p>
+3
View File
@@ -0,0 +1,3 @@
.makeItRed {
background-color: red;
}
+24
View File
@@ -0,0 +1,24 @@
startup-begin = ChatPapers is loading
startup-finish = ChatPapers is ready
prefs-title = ChatPapers
item-section-chat-head = ChatPapers
item-section-chat-sidenav = Chat with paper
chat-loading = Loading ChatPapers…
chat-placeholder = Ask a question about this paper…
chat-send = Send
chat-stop = Stop
chat-summarize = Summarize
chat-add-selection = Add selection
chat-clear = Clear
chat-save-note = Save as note
chat-need-config = Configure a provider in Preferences first.
chat-thinking = Thinking…
chat-done = Done
chat-stopped = Stopped
chat-cleared = Chat cleared
chat-no-reply = No AI reply to save yet
chat-note-saved = Saved as note
chat-selection-added = Selection added to next message
chat-selection-empty = No text selected in the reader
+1
View File
@@ -0,0 +1 @@
itemmenu-label = ChatPapers: Summarize
+29
View File
@@ -0,0 +1,29 @@
prefs-title = ChatPapers
prefs-section-provider = AI Provider
prefs-section-generation = Generation
prefs-section-openrouter = OpenRouter (optional)
prefs-section-prompts = Prompts
prefs-provider = Provider
prefs-reset = Reset defaults
prefs-base-url = Base URL
prefs-api-key = API Key
prefs-model = Model
prefs-refresh-models = Refresh models
prefs-temperature = Temperature
prefs-max-tokens = Max tokens
prefs-timeout = Timeout (ms)
prefs-max-context = Max context chars
prefs-answer-language = Answer language
prefs-send-metadata =
.label = Include item metadata in prompts
prefs-openrouter-referer = HTTP-Referer
prefs-openrouter-title = X-Title
prefs-system-prompt = System prompt (leave empty for default)
prefs-summary-prompt = Summary prompt (leave empty for default)
prefs-hint-empty = Choose Ollama, LM Studio, OpenRouter, or another provider.
prefs-hint-local = Local provider: requests stay on this machine. Start the server first.
prefs-hint-openrouter = Cloud aggregator: paper text is sent to OpenRouter / upstream models.
prefs-hint-cloud = Cloud provider: paper text is sent to the selected API endpoint.
prefs-models-empty = No models returned.
prefs-models-pick = Enter a model id from the list (showing up to 30):
prefs-privacy = Privacy: ChatPapers only sends content when you click Send/Summarize, and only to the endpoint you configured. API keys are stored in local Zotero preferences.
+24
View File
@@ -0,0 +1,24 @@
startup-begin = ChatPapers 加载中
startup-finish = ChatPapers 已就绪
prefs-title = ChatPapers
item-section-chat-head = ChatPapers
item-section-chat-sidenav = 论文对话
chat-loading = 正在加载 ChatPapers…
chat-placeholder = 就这篇论文提问…
chat-send = 发送
chat-stop = 停止
chat-summarize = 总结
chat-add-selection = 添加选区
chat-clear = 清空
chat-save-note = 保存为笔记
chat-need-config = 请先在偏好设置中配置 AI Provider
chat-thinking = 思考中…
chat-done = 完成
chat-stopped = 已停止
chat-cleared = 已清空对话
chat-no-reply = 还没有可保存的 AI 回复
chat-note-saved = 已保存为笔记
chat-selection-added = 已将选区加入下一条消息
chat-selection-empty = 阅读器中没有选中文本
+1
View File
@@ -0,0 +1 @@
itemmenu-label = ChatPapers:总结
+29
View File
@@ -0,0 +1,29 @@
prefs-title = ChatPapers
prefs-section-provider = AI 接入
prefs-section-generation = 生成参数
prefs-section-openrouter = OpenRouter(可选)
prefs-section-prompts = 提示词
prefs-provider = Provider
prefs-reset = 重置为预设默认
prefs-base-url = Base URL
prefs-api-key = API Key
prefs-model = 模型
prefs-refresh-models = 刷新模型列表
prefs-temperature = 温度
prefs-max-tokens = 最大 Token
prefs-timeout = 超时(毫秒)
prefs-max-context = 最大上下文字符
prefs-answer-language = 回答语言
prefs-send-metadata =
.label = 在提示词中附带条目元数据
prefs-openrouter-referer = HTTP-Referer
prefs-openrouter-title = X-Title
prefs-system-prompt = 系统提示词(留空使用默认)
prefs-summary-prompt = 总结提示词(留空使用默认)
prefs-hint-empty = 请选择 Ollama、LM Studio、OpenRouter 或其他 Provider。
prefs-hint-local = 本地 Provider:请求发往本机。请先启动对应服务。
prefs-hint-openrouter = 云端聚合:论文内容将发送到 OpenRouter / 上游模型。
prefs-hint-cloud = 云端 Provider:论文内容将发送到所选 API 端点。
prefs-models-empty = 未返回任何模型。
prefs-models-pick = 从列表中输入模型 ID(最多显示 30 个):
prefs-privacy = 隐私说明:仅在你点击发送/总结时,向你配置的端点发送内容。API Key 仅保存在本地 Zotero 偏好设置中。
+20
View File
@@ -0,0 +1,20 @@
{
"manifest_version": 2,
"name": "__addonName__",
"version": "__buildVersion__",
"description": "__description__",
"homepage_url": "__homepage__",
"author": "__author__",
"icons": {
"48": "content/icons/favicon@0.5x.png",
"96": "content/icons/favicon.png"
},
"applications": {
"zotero": {
"id": "__addonID__",
"update_url": "__updateURL__",
"strict_min_version": "9.0",
"strict_max_version": "9.*"
}
}
}
+15
View File
@@ -0,0 +1,15 @@
pref("provider", "");
pref("apiBaseUrl", "");
pref("apiKey", "");
pref("model", "");
pref("openrouterReferer", "https://github.com/chatpapers/chatpapers");
pref("openrouterTitle", "ChatPapers");
pref("temperature", "0.3");
pref("maxTokens", 2048);
pref("timeoutMs", 120000);
pref("maxContextChars", 80000);
pref("answerLanguage", "zh-CN");
pref("systemPrompt", "");
pref("summaryPrompt", "");
pref("sendMetadata", true);
pref("verboseLog", false);